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 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 = element[1].toUpperCase(Locale.US); 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(algName.toUpperCase(Locale.US)); 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(algName.toUpperCase(Locale.US)); 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 = alg.toUpperCase(Locale.US); 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(alias.toUpperCase(Locale.US))) { 176 algAliasesMap.put(alias.toUpperCase(Locale.US), 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 return ObjectIdentifier.isOID(normalize(alias)); 191 } 192 193 /** 194 * Removes leading "OID." from oid String passed 195 * 196 * @param oid string that may contain leading "OID." 197 * @return string passed without leading "OID." 198 */ 199 public static String normalize(String oid) { 200 return oid.startsWith("OID.") 201 ? oid.substring(4) 202 : oid; 203 } 204 } 205