• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Locale;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Set;
32 import org.apache.harmony.security.asn1.ObjectIdentifier;
33 import org.apache.harmony.security.fortress.Services;
34 
35 /**
36  * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
37  * mappings are hardcoded. Tries to obtain additional mappings from installed
38  * providers during initialization.
39  */
40 public class AlgNameMapper {
41     private static AlgNameMapperSource source = null;
42 
43     private static volatile int cacheVersion = -1;
44 
45     // Will search OID mappings for these services
46     private static final String[] serviceName = {
47             "Cipher",
48             "AlgorithmParameters",
49             "Signature"
50     };
51 
52     // These mappings CAN NOT be overridden
53     // by the ones from available providers
54     // during maps initialization
55     // (source: http://asn1.elibel.tm.fr):
56     private static final String[][] knownAlgMappings = {
57         {"1.2.840.10040.4.1",       "DSA"},
58         {"1.2.840.10040.4.3",       "SHA1withDSA"},
59         {"1.2.840.113549.1.1.1",    "RSA"},
60         // BEGIN android-removed
61         // Dropping MD2
62         // {"1.2.840.113549.1.1.2",    "MD2withRSA"},
63         // END android-removed
64         {"1.2.840.113549.1.1.4",    "MD5withRSA"},
65         {"1.2.840.113549.1.1.5",    "SHA1withRSA"},
66         {"1.2.840.113549.1.3.1",    "DiffieHellman"},
67         {"1.2.840.113549.1.5.3",    "pbeWithMD5AndDES-CBC"},
68         {"1.2.840.113549.1.12.1.3", "pbeWithSHAAnd3-KeyTripleDES-CBC"},
69         {"1.2.840.113549.1.12.1.6", "pbeWithSHAAnd40BitRC2-CBC"},
70         {"1.2.840.113549.3.2",      "RC2-CBC"},
71         {"1.2.840.113549.3.3",      "RC2-EBC"},
72         {"1.2.840.113549.3.4",      "RC4"},
73         {"1.2.840.113549.3.5",      "RC4WithMAC"},
74         {"1.2.840.113549.3.6",      "DESx-CBC"},
75         {"1.2.840.113549.3.7",      "TripleDES-CBC"},
76         {"1.2.840.113549.3.8",      "rc5CBC"},
77         {"1.2.840.113549.3.9",      "RC5-CBC"},
78         {"1.2.840.113549.3.10",     "DESCDMF"},
79         {"2.23.42.9.11.4.1",        "ECDSA"},
80     };
81     // Maps alg name to OID
82     private static final Map<String, String> alg2OidMap = new HashMap<String, String>();
83     // Maps OID to alg name
84     private static final Map<String, String> oid2AlgMap = new HashMap<String, String>();
85     // Maps aliases to alg names
86     private static final Map<String, String> algAliasesMap = new HashMap<String, String>();
87 
88     static {
89         for (String[] element : knownAlgMappings) {
90             String algUC = element[1].toUpperCase(Locale.US);
alg2OidMap.put(algUC, element[0])91             alg2OidMap.put(algUC, element[0]);
oid2AlgMap.put(element[0], algUC)92             oid2AlgMap.put(element[0], algUC);
93             // map upper case alg name to its original name
algAliasesMap.put(algUC, element[1])94             algAliasesMap.put(algUC, element[1]);
95         }
96     }
97 
98     // No instances
AlgNameMapper()99     private AlgNameMapper() {
100     }
101 
checkCacheVersion()102     private static synchronized void checkCacheVersion() {
103         int newCacheVersion = Services.getCacheVersion();
104         if (newCacheVersion != cacheVersion) {
105             //
106             // Now search providers for mappings like
107             // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
108             //  or
109             // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
110             //
111             Provider[] pl = Security.getProviders();
112             for (Provider element : pl) {
113                 selectEntries(element);
114             }
115             cacheVersion = newCacheVersion;
116         }
117     }
118 
119     /**
120      * Returns OID for algName
121      *
122      * @param algName algorithm name to be mapped
123      * @return OID as String
124      */
map2OID(String algName)125     public static String map2OID(String algName) {
126         checkCacheVersion();
127 
128         // alg2OidMap map contains upper case keys
129         String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
130         if (result != null) {
131             return result;
132         }
133 
134         // Check our external source.
135         AlgNameMapperSource s = source;
136         if (s != null) {
137             return s.mapNameToOid(algName);
138         }
139 
140         return null;
141     }
142 
143     /**
144      * Returns algName for OID
145      *
146      * @param oid OID to be mapped
147      * @return algorithm name
148      */
map2AlgName(String oid)149     public static String map2AlgName(String oid) {
150         checkCacheVersion();
151 
152         // oid2AlgMap map contains upper case values
153         String algUC = oid2AlgMap.get(oid);
154         // if not null there is always map UC->Orig
155         if (algUC != null) {
156             return algAliasesMap.get(algUC);
157         }
158 
159         // Check our external source.
160         AlgNameMapperSource s = source;
161         if (s != null) {
162             return s.mapOidToName(oid);
163         }
164 
165         return null;
166     }
167 
168     /**
169      * Returns Algorithm name for given algorithm alias
170      *
171      * @param algName - alias
172      * @return algorithm name
173      */
getStandardName(String algName)174     public static String getStandardName(String algName) {
175         return algAliasesMap.get(algName.toUpperCase(Locale.US));
176     }
177 
178     // Searches given provider for mappings like
179     // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
180     //  or
181     // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
182     // Puts mappings found into appropriate internal maps
selectEntries(Provider p)183     private static void selectEntries(Provider p) {
184         Set<Map.Entry<Object, Object>> entrySet = p.entrySet();
185         for (String service : serviceName) {
186             String keyPrfix2find = "Alg.Alias." + service + ".";
187             for (Entry<Object, Object> me : entrySet) {
188                 String key = (String)me.getKey();
189                 if (key.startsWith(keyPrfix2find)) {
190                     String alias = key.substring(keyPrfix2find.length());
191                     String alg = (String)me.getValue();
192                     String algUC = alg.toUpperCase(Locale.US);
193                     if (isOID(alias)) {
194                         if (alias.startsWith("OID.")) {
195                             alias = alias.substring(4);
196                         }
197                         // Do not overwrite already known mappings
198                         boolean oid2AlgContains = oid2AlgMap.containsKey(alias);
199                         boolean alg2OidContains = alg2OidMap.containsKey(algUC);
200                         if (!oid2AlgContains || !alg2OidContains) {
201                             if (!oid2AlgContains) {
202                                 oid2AlgMap.put(alias, algUC);
203                             }
204                             if (!alg2OidContains) {
205                                 alg2OidMap.put(algUC, alias);
206                             }
207                             // map upper case alg name to its original name
208                             algAliasesMap.put(algUC, alg);
209                         }
210                            // Do not override known standard names
211                     } else if (!algAliasesMap.containsKey(alias.toUpperCase(Locale.US))) {
212                         algAliasesMap.put(alias.toUpperCase(Locale.US), alg);
213                     }
214                 }
215             }
216         }
217     }
218 
219     /**
220      * Checks if parameter represents OID
221      *
222      * @param alias alias to be checked
223      * @return 'true' if parameter represents OID
224      */
isOID(String alias)225     public static boolean isOID(String alias) {
226         return ObjectIdentifier.isOID(normalize(alias));
227     }
228 
229     /**
230      * Removes leading "OID." from oid String passed
231      *
232      * @param oid string that may contain leading "OID."
233      * @return string passed without leading "OID."
234      */
normalize(String oid)235     public static String normalize(String oid) {
236         return oid.startsWith("OID.")
237             ? oid.substring(4)
238             : oid;
239     }
240 
setSource(AlgNameMapperSource source)241     public static void setSource(AlgNameMapperSource source) {
242         AlgNameMapper.source = source;
243     }
244 }
245