Home | History | Annotate | Download | only in utils
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 /**
     19 * @author Vladimir N. Molotkov
     20 * @version $Revision$
     21 */
     22 
     23 package org.apache.harmony.security.utils;
     24 
     25 import java.security.Provider;
     26 import java.security.Security;
     27 import java.util.HashMap;
     28 import java.util.Map;
     29 import java.util.Map.Entry;
     30 import java.util.Set;
     31 import org.apache.harmony.security.Util;
     32 import org.apache.harmony.security.asn1.ObjectIdentifier;
     33 
     34 /**
     35  * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
     36  * mappings are hardcoded. Tries to obtain additional mappings from installed
     37  * providers during initialization.
     38  */
     39 public class AlgNameMapper {
     40 
     41     // Will search OID mappings for these services
     42     private static final String[] serviceName = {
     43             "Cipher",
     44             "AlgorithmParameters",
     45             "Signature"
     46     };
     47 
     48     // These mappings CAN NOT be overridden
     49     // by the ones from available providers
     50     // during maps initialization
     51     // (source: http://asn1.elibel.tm.fr):
     52     private static final String[][] knownAlgMappings = {
     53         {"1.2.840.10040.4.1",       "DSA"},
     54         {"1.2.840.10040.4.3",       "SHA1withDSA"},
     55         {"1.2.840.113549.1.1.1",    "RSA"},
     56         // BEGIN android-removed
     57         // Dropping MD2
     58         // {"1.2.840.113549.1.1.2",    "MD2withRSA"},
     59         // END android-removed
     60         {"1.2.840.113549.1.1.4",    "MD5withRSA"},
     61         {"1.2.840.113549.1.1.5",    "SHA1withRSA"},
     62         {"1.2.840.113549.1.3.1",    "DiffieHellman"},
     63         {"1.2.840.113549.1.5.3",    "pbeWithMD5AndDES-CBC"},
     64         {"1.2.840.113549.1.12.1.3", "pbeWithSHAAnd3-KeyTripleDES-CBC"},
     65         {"1.2.840.113549.1.12.1.6", "pbeWithSHAAnd40BitRC2-CBC"},
     66         {"1.2.840.113549.3.2",      "RC2-CBC"},
     67         {"1.2.840.113549.3.3",      "RC2-EBC"},
     68         {"1.2.840.113549.3.4",      "RC4"},
     69         {"1.2.840.113549.3.5",      "RC4WithMAC"},
     70         {"1.2.840.113549.3.6",      "DESx-CBC"},
     71         {"1.2.840.113549.3.7",      "TripleDES-CBC"},
     72         {"1.2.840.113549.3.8",      "rc5CBC"},
     73         {"1.2.840.113549.3.9",      "RC5-CBC"},
     74         {"1.2.840.113549.3.10",     "DESCDMF"},
     75         {"2.23.42.9.11.4.1",        "ECDSA"},
     76     };
     77     // Maps alg name to OID
     78     private static final Map<String, String> alg2OidMap = new HashMap<String, String>();
     79     // Maps OID to alg name
     80     private static final Map<String, String> oid2AlgMap = new HashMap<String, String>();
     81     // Maps aliases to alg names
     82     private static final Map<String, String> algAliasesMap = new HashMap<String, String>();
     83 
     84     static {
     85         for (String[] element : knownAlgMappings) {
     86             String algUC = Util.toUpperCase(element[1]);
     87             alg2OidMap.put(algUC, element[0]);
     88             oid2AlgMap.put(element[0], algUC);
     89             // map upper case alg name to its original name
     90             algAliasesMap.put(algUC, element[1]);
     91         }
     92         //
     93         // Now search providers for mappings like
     94         // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
     95         //  or
     96         // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
     97         //
     98         Provider[] pl = Security.getProviders();
     99         for (Provider element : pl) {
    100             selectEntries(element);
    101         }
    102     }
    103 
    104     // No instances
    105     private AlgNameMapper() {
    106     }
    107 
    108     /**
    109      * Returns OID for algName
    110      *
    111      * @param algName algorithm name to be mapped
    112      * @return OID as String
    113      */
    114     public static String map2OID(String algName) {
    115         // alg2OidMap map contains upper case keys
    116         return alg2OidMap.get(Util.toUpperCase(algName));
    117     }
    118 
    119     /**
    120      * Returns algName for OID
    121      *
    122      * @param oid OID to be mapped
    123      * @return algorithm name
    124      */
    125     public static String map2AlgName(String oid) {
    126         // oid2AlgMap map contains upper case values
    127         String algUC = oid2AlgMap.get(oid);
    128         // if not null there is always map UC->Orig
    129         return algUC == null ? null : algAliasesMap.get(algUC);
    130     }
    131 
    132     /**
    133      * Returns Algorithm name for given algorithm alias
    134      *
    135      * @param algName - alias
    136      * @return algorithm name
    137      */
    138     public static String getStandardName(String algName) {
    139         return algAliasesMap.get(Util.toUpperCase(algName));
    140     }
    141 
    142     // Searches given provider for mappings like
    143     // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
    144     //  or
    145     // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
    146     // Puts mappings found into appropriate internal maps
    147     private static void selectEntries(Provider p) {
    148         Set<Map.Entry<Object, Object>> entrySet = p.entrySet();
    149         for (String service : serviceName) {
    150             String keyPrfix2find = "Alg.Alias." + service + ".";
    151             for (Entry<Object, Object> me : entrySet) {
    152                 String key = (String)me.getKey();
    153                 if (key.startsWith(keyPrfix2find)) {
    154                     String alias = key.substring(keyPrfix2find.length());
    155                     String alg = (String)me.getValue();
    156                     String algUC = Util.toUpperCase(alg);
    157                     if (isOID(alias)) {
    158                         if (alias.startsWith("OID.")) {
    159                             alias = alias.substring(4);
    160                         }
    161                         // Do not overwrite already known mappings
    162                         boolean oid2AlgContains = oid2AlgMap.containsKey(alias);
    163                         boolean alg2OidContains = alg2OidMap.containsKey(algUC);
    164                         if (!oid2AlgContains || !alg2OidContains) {
    165                             if (!oid2AlgContains) {
    166                                 oid2AlgMap.put(alias, algUC);
    167                             }
    168                             if (!alg2OidContains) {
    169                                 alg2OidMap.put(algUC, alias);
    170                             }
    171                             // map upper case alg name to its original name
    172                             algAliasesMap.put(algUC, alg);
    173                         }
    174                            // Do not override known standard names
    175                     } else if (!algAliasesMap.containsKey(Util.toUpperCase(alias))) {
    176                         algAliasesMap.put(Util.toUpperCase(alias), alg);
    177                     }
    178                 }
    179             }
    180         }
    181     }
    182 
    183     /**
    184      * Checks if parameter represents OID
    185      *
    186      * @param alias alias to be checked
    187      * @return 'true' if parameter represents OID
    188      */
    189     public static boolean isOID(String alias) {
    190         // BEGIN android-changed
    191         return ObjectIdentifier.isOID(normalize(alias));
    192         // END android-changed
    193     }
    194 
    195     /**
    196      * Removes leading "OID." from oid String passed
    197      *
    198      * @param oid string that may contain leading "OID."
    199      * @return string passed without leading "OID."
    200      */
    201     public static String normalize(String oid) {
    202         return oid.startsWith("OID.")
    203             ? oid.substring(4)
    204             : oid;
    205     }
    206 
    207     /**
    208      * Present all internal maps as formatted string
    209      * @return Internal maps String representation
    210      */
    211     public static String dump() {
    212         StringBuilder sb = new StringBuilder("alg2OidMap: ");
    213         sb.append(alg2OidMap);
    214         sb.append("\noid2AlgMap: ");
    215         sb.append(oid2AlgMap);
    216         sb.append("\nalgAliasesMap: ");
    217         sb.append(algAliasesMap);
    218         return sb.toString();
    219     }
    220 }
    221