1package org.bouncycastle.x509; 2 3import org.bouncycastle.asn1.ASN1Encodable; 4import org.bouncycastle.asn1.DEREncodable; 5import org.bouncycastle.asn1.DERInteger; 6import org.bouncycastle.asn1.DERNull; 7import org.bouncycastle.asn1.DERObjectIdentifier; 8import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; 9import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; 10import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 11import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 12import org.bouncycastle.asn1.pkcs.RSASSAPSSparams; 13import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; 14import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 15import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 16import org.bouncycastle.jce.X509Principal; 17import org.bouncycastle.util.Strings; 18 19import javax.security.auth.x500.X500Principal; 20import java.io.IOException; 21import java.security.InvalidKeyException; 22import java.security.NoSuchAlgorithmException; 23import java.security.NoSuchProviderException; 24import java.security.PrivateKey; 25import java.security.Provider; 26import java.security.SecureRandom; 27import java.security.Security; 28import java.security.Signature; 29import java.security.SignatureException; 30import java.util.ArrayList; 31import java.util.Enumeration; 32import java.util.HashSet; 33import java.util.Hashtable; 34import java.util.Iterator; 35import java.util.List; 36import java.util.Set; 37 38class X509Util 39{ 40 private static Hashtable algorithms = new Hashtable(); 41 private static Hashtable params = new Hashtable(); 42 private static Set noParams = new HashSet(); 43 44 static 45 { 46 // BEGIN android-removed 47 // algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); 48 // algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); 49 // END android-removed 50 algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); 51 algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); 52 algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); 53 algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); 54 algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); 55 algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); 56 algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); 57 algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); 58 algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); 59 algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); 60 algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); 61 algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); 62 algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); 63 algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); 64 algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); 65 algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); 66 algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); 67 algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); 68 algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); 69 algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); 70 algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); 71 algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); 72 algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); 73 algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); 74 algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); 75 algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); 76 algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); 77 algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); 78 algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); 79 algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); 80 algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); 81 algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); 82 algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); 83 algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); 84 algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); 85 algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); 86 algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); 87 algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); 88 89 // 90 // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. 91 // The parameters field SHALL be NULL for RSA based signature algorithms. 92 // 93 noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); 94 noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); 95 noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); 96 noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); 97 noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); 98 noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); 99 noParams.add(NISTObjectIdentifiers.dsa_with_sha224); 100 noParams.add(NISTObjectIdentifiers.dsa_with_sha256); 101 102 // 103 // RFC 4491 104 // 105 noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); 106 noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); 107 108 // 109 // explicit params 110 // 111 // BEGIN android-changed 112 AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE); 113 // END android-changed 114 params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20)); 115 116 // BEGIN android-changed 117 AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, DERNull.INSTANCE); 118 // END android-changed 119 params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28)); 120 121 // BEGIN android-changed 122 AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE); 123 // END android-changed 124 params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32)); 125 126 // BEGIN android-changed 127 AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, DERNull.INSTANCE); 128 // END android-changed 129 params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48)); 130 131 // BEGIN android-changed 132 AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, DERNull.INSTANCE); 133 // END android-changed 134 params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64)); 135 } 136 137 private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize) 138 { 139 return new RSASSAPSSparams( 140 hashAlgId, 141 new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId), 142 new DERInteger(saltSize), 143 new DERInteger(1)); 144 } 145 146 static DERObjectIdentifier getAlgorithmOID( 147 String algorithmName) 148 { 149 algorithmName = Strings.toUpperCase(algorithmName); 150 151 if (algorithms.containsKey(algorithmName)) 152 { 153 return (DERObjectIdentifier)algorithms.get(algorithmName); 154 } 155 156 return new DERObjectIdentifier(algorithmName); 157 } 158 159 static AlgorithmIdentifier getSigAlgID( 160 DERObjectIdentifier sigOid, 161 String algorithmName) 162 { 163 if (noParams.contains(sigOid)) 164 { 165 return new AlgorithmIdentifier(sigOid); 166 } 167 168 algorithmName = Strings.toUpperCase(algorithmName); 169 170 if (params.containsKey(algorithmName)) 171 { 172 return new AlgorithmIdentifier(sigOid, (DEREncodable)params.get(algorithmName)); 173 } 174 else 175 { 176 // BEGIN android-changed 177 return new AlgorithmIdentifier(sigOid, DERNull.INSTANCE); 178 // END android-changed 179 } 180 } 181 182 static Iterator getAlgNames() 183 { 184 Enumeration e = algorithms.keys(); 185 List l = new ArrayList(); 186 187 while (e.hasMoreElements()) 188 { 189 l.add(e.nextElement()); 190 } 191 192 return l.iterator(); 193 } 194 195 static Signature getSignatureInstance( 196 String algorithm) 197 throws NoSuchAlgorithmException 198 { 199 return Signature.getInstance(algorithm); 200 } 201 202 static Signature getSignatureInstance( 203 String algorithm, 204 String provider) 205 throws NoSuchProviderException, NoSuchAlgorithmException 206 { 207 if (provider != null) 208 { 209 return Signature.getInstance(algorithm, provider); 210 } 211 else 212 { 213 return Signature.getInstance(algorithm); 214 } 215 } 216 217 static byte[] calculateSignature( 218 DERObjectIdentifier sigOid, 219 String sigName, 220 PrivateKey key, 221 SecureRandom random, 222 ASN1Encodable object) 223 throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException 224 { 225 Signature sig; 226 227 if (sigOid == null) 228 { 229 throw new IllegalStateException("no signature algorithm specified"); 230 } 231 232 sig = X509Util.getSignatureInstance(sigName); 233 234 if (random != null) 235 { 236 sig.initSign(key, random); 237 } 238 else 239 { 240 sig.initSign(key); 241 } 242 243 sig.update(object.getEncoded(ASN1Encodable.DER)); 244 245 return sig.sign(); 246 } 247 248 static byte[] calculateSignature( 249 DERObjectIdentifier sigOid, 250 String sigName, 251 String provider, 252 PrivateKey key, 253 SecureRandom random, 254 ASN1Encodable object) 255 throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException 256 { 257 Signature sig; 258 259 if (sigOid == null) 260 { 261 throw new IllegalStateException("no signature algorithm specified"); 262 } 263 264 sig = X509Util.getSignatureInstance(sigName, provider); 265 266 if (random != null) 267 { 268 sig.initSign(key, random); 269 } 270 else 271 { 272 sig.initSign(key); 273 } 274 275 sig.update(object.getEncoded(ASN1Encodable.DER)); 276 277 return sig.sign(); 278 } 279 280 static X509Principal convertPrincipal( 281 X500Principal principal) 282 { 283 try 284 { 285 return new X509Principal(principal.getEncoded()); 286 } 287 catch (IOException e) 288 { 289 throw new IllegalArgumentException("cannot convert principal"); 290 } 291 } 292 293 static class Implementation 294 { 295 Object engine; 296 Provider provider; 297 298 Implementation( 299 Object engine, 300 Provider provider) 301 { 302 this.engine = engine; 303 this.provider = provider; 304 } 305 306 Object getEngine() 307 { 308 return engine; 309 } 310 311 Provider getProvider() 312 { 313 return provider; 314 } 315 } 316 317 /** 318 * see if we can find an algorithm (or its alias and what it represents) in 319 * the property table for the given provider. 320 */ 321 static Implementation getImplementation( 322 String baseName, 323 String algorithm, 324 Provider prov) 325 throws NoSuchAlgorithmException 326 { 327 algorithm = Strings.toUpperCase(algorithm); 328 329 String alias; 330 331 while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) 332 { 333 algorithm = alias; 334 } 335 336 String className = prov.getProperty(baseName + "." + algorithm); 337 338 if (className != null) 339 { 340 try 341 { 342 Class cls; 343 ClassLoader clsLoader = prov.getClass().getClassLoader(); 344 345 if (clsLoader != null) 346 { 347 cls = clsLoader.loadClass(className); 348 } 349 else 350 { 351 cls = Class.forName(className); 352 } 353 354 return new Implementation(cls.newInstance(), prov); 355 } 356 catch (ClassNotFoundException e) 357 { 358 throw new IllegalStateException( 359 "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!"); 360 } 361 catch (Exception e) 362 { 363 throw new IllegalStateException( 364 "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!"); 365 } 366 } 367 368 throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName()); 369 } 370 371 /** 372 * return an implementation for a given algorithm/provider. 373 * If the provider is null, we grab the first avalaible who has the required algorithm. 374 */ 375 static Implementation getImplementation( 376 String baseName, 377 String algorithm) 378 throws NoSuchAlgorithmException 379 { 380 Provider[] prov = Security.getProviders(); 381 382 // 383 // search every provider looking for the algorithm we want. 384 // 385 for (int i = 0; i != prov.length; i++) 386 { 387 // 388 // try case insensitive 389 // 390 Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]); 391 if (imp != null) 392 { 393 return imp; 394 } 395 396 try 397 { 398 imp = getImplementation(baseName, algorithm, prov[i]); 399 } 400 catch (NoSuchAlgorithmException e) 401 { 402 // continue 403 } 404 } 405 406 throw new NoSuchAlgorithmException("cannot find implementation " + algorithm); 407 } 408 409 static Provider getProvider(String provider) 410 throws NoSuchProviderException 411 { 412 Provider prov = Security.getProvider(provider); 413 414 if (prov == null) 415 { 416 throw new NoSuchProviderException("Provider " + provider + " not found"); 417 } 418 419 return prov; 420 } 421} 422