1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 package com.android.org.bouncycastle.jcajce.provider.keystore.pkcs12; 3 4 import java.io.BufferedInputStream; 5 import java.io.ByteArrayInputStream; 6 import java.io.ByteArrayOutputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.OutputStream; 10 import java.math.BigInteger; 11 import java.security.InvalidAlgorithmParameterException; 12 import java.security.InvalidKeyException; 13 import java.security.Key; 14 import java.security.KeyStore; 15 import java.security.KeyStore.LoadStoreParameter; 16 import java.security.KeyStore.ProtectionParameter; 17 import java.security.KeyStoreException; 18 import java.security.KeyStoreSpi; 19 import java.security.NoSuchAlgorithmException; 20 import java.security.NoSuchProviderException; 21 import java.security.Principal; 22 import java.security.PrivateKey; 23 import java.security.PublicKey; 24 import java.security.SecureRandom; 25 import java.security.UnrecoverableKeyException; 26 import java.security.cert.Certificate; 27 import java.security.cert.CertificateEncodingException; 28 import java.security.cert.CertificateException; 29 import java.security.cert.CertificateFactory; 30 import java.security.cert.X509Certificate; 31 import java.security.spec.InvalidKeySpecException; 32 import java.util.Collections; 33 import java.util.Date; 34 import java.util.Enumeration; 35 import java.util.HashMap; 36 import java.util.HashSet; 37 import java.util.Hashtable; 38 import java.util.Map; 39 import java.util.Set; 40 import java.util.Vector; 41 42 import javax.crypto.Cipher; 43 import javax.crypto.Mac; 44 import javax.crypto.NoSuchPaddingException; 45 import javax.crypto.SecretKey; 46 import javax.crypto.SecretKeyFactory; 47 import javax.crypto.spec.IvParameterSpec; 48 import javax.crypto.spec.PBEKeySpec; 49 import javax.crypto.spec.PBEParameterSpec; 50 51 import com.android.org.bouncycastle.asn1.ASN1Encodable; 52 import com.android.org.bouncycastle.asn1.ASN1EncodableVector; 53 import com.android.org.bouncycastle.asn1.ASN1Encoding; 54 import com.android.org.bouncycastle.asn1.ASN1InputStream; 55 import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier; 56 import com.android.org.bouncycastle.asn1.ASN1OctetString; 57 import com.android.org.bouncycastle.asn1.ASN1Primitive; 58 import com.android.org.bouncycastle.asn1.ASN1Sequence; 59 import com.android.org.bouncycastle.asn1.ASN1Set; 60 import com.android.org.bouncycastle.asn1.BEROctetString; 61 import com.android.org.bouncycastle.asn1.BEROutputStream; 62 import com.android.org.bouncycastle.asn1.DERBMPString; 63 import com.android.org.bouncycastle.asn1.DERNull; 64 import com.android.org.bouncycastle.asn1.DEROctetString; 65 import com.android.org.bouncycastle.asn1.DEROutputStream; 66 import com.android.org.bouncycastle.asn1.DERSequence; 67 import com.android.org.bouncycastle.asn1.DERSet; 68 // Android-removed: Unsupported algorithms 69 // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; 70 // import org.bouncycastle.asn1.cryptopro.GOST28147Parameters; 71 import com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers; 72 // import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; 73 import com.android.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 74 import com.android.org.bouncycastle.asn1.pkcs.AuthenticatedSafe; 75 import com.android.org.bouncycastle.asn1.pkcs.CertBag; 76 import com.android.org.bouncycastle.asn1.pkcs.ContentInfo; 77 import com.android.org.bouncycastle.asn1.pkcs.EncryptedData; 78 import com.android.org.bouncycastle.asn1.pkcs.MacData; 79 import com.android.org.bouncycastle.asn1.pkcs.PBES2Parameters; 80 import com.android.org.bouncycastle.asn1.pkcs.PBKDF2Params; 81 import com.android.org.bouncycastle.asn1.pkcs.PKCS12PBEParams; 82 import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 83 import com.android.org.bouncycastle.asn1.pkcs.Pfx; 84 import com.android.org.bouncycastle.asn1.pkcs.SafeBag; 85 import com.android.org.bouncycastle.asn1.util.ASN1Dump; 86 import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 87 import com.android.org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; 88 import com.android.org.bouncycastle.asn1.x509.DigestInfo; 89 import com.android.org.bouncycastle.asn1.x509.Extension; 90 import com.android.org.bouncycastle.asn1.x509.SubjectKeyIdentifier; 91 import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 92 import com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 93 import com.android.org.bouncycastle.crypto.CryptoServicesRegistrar; 94 import com.android.org.bouncycastle.crypto.Digest; 95 // Android-changed: Use Android digests 96 // import org.bouncycastle.crypto.util.DigestFactory; 97 import com.android.org.bouncycastle.crypto.digests.AndroidDigestFactory; 98 import com.android.org.bouncycastle.jcajce.PKCS12Key; 99 import com.android.org.bouncycastle.jcajce.PKCS12StoreParameter; 100 // Android-removed: Unsupported algorithms 101 // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; 102 import com.android.org.bouncycastle.jcajce.spec.PBKDF2KeySpec; 103 import com.android.org.bouncycastle.jcajce.util.BCJcaJceHelper; 104 import com.android.org.bouncycastle.jcajce.util.DefaultJcaJceHelper; 105 import com.android.org.bouncycastle.jcajce.util.JcaJceHelper; 106 import com.android.org.bouncycastle.jce.interfaces.BCKeyStore; 107 import com.android.org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; 108 import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider; 109 import com.android.org.bouncycastle.jce.provider.JDKPKCS12StoreParameter; 110 import com.android.org.bouncycastle.util.Arrays; 111 import com.android.org.bouncycastle.util.Integers; 112 import com.android.org.bouncycastle.util.Properties; 113 import com.android.org.bouncycastle.util.Strings; 114 import com.android.org.bouncycastle.util.encoders.Hex; 115 116 /** 117 * @hide This class is not part of the Android public SDK API 118 */ 119 public class PKCS12KeyStoreSpi 120 extends KeyStoreSpi 121 implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore 122 { 123 static final String PKCS12_MAX_IT_COUNT_PROPERTY = "com.android.org.bouncycastle.pkcs12.max_it_count"; 124 125 // Android-changed: Use default provider for JCA algorithms instead of BC 126 // Was: private final JcaJceHelper helper = new BCJcaJceHelper(); 127 private final JcaJceHelper helper = new DefaultJcaJceHelper(); 128 129 private static final int SALT_SIZE = 20; 130 private static final int MIN_ITERATIONS = 50 * 1024; 131 132 private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider(); 133 134 private IgnoresCaseHashtable keys = new IgnoresCaseHashtable(); 135 private Hashtable localIds = new Hashtable(); 136 private IgnoresCaseHashtable certs = new IgnoresCaseHashtable(); 137 private Hashtable chainCerts = new Hashtable(); 138 private Hashtable keyCerts = new Hashtable(); 139 140 // 141 // generic object types 142 // 143 static final int NULL = 0; 144 static final int CERTIFICATE = 1; 145 static final int KEY = 2; 146 static final int SECRET = 3; 147 static final int SEALED = 4; 148 149 // 150 // key types 151 // 152 static final int KEY_PRIVATE = 0; 153 static final int KEY_PUBLIC = 1; 154 static final int KEY_SECRET = 2; 155 156 protected SecureRandom random = CryptoServicesRegistrar.getSecureRandom(); 157 158 // use of final causes problems with JDK 1.2 compiler 159 private CertificateFactory certFact; 160 private ASN1ObjectIdentifier keyAlgorithm; 161 private ASN1ObjectIdentifier certAlgorithm; 162 163 private AlgorithmIdentifier macAlgorithm = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE); 164 private int itCount = 2 * MIN_ITERATIONS; 165 private int saltLength = 20; 166 167 private class CertId 168 { 169 byte[] id; 170 171 CertId( 172 PublicKey key) 173 { 174 this.id = createSubjectKeyId(key).getKeyIdentifier(); 175 } 176 177 CertId( 178 byte[] id) 179 { 180 this.id = id; 181 } 182 183 public int hashCode() 184 { 185 return Arrays.hashCode(id); 186 } 187 188 public boolean equals( 189 Object o) 190 { 191 if (o == this) 192 { 193 return true; 194 } 195 196 if (!(o instanceof CertId)) 197 { 198 return false; 199 } 200 201 CertId cId = (CertId)o; 202 203 return Arrays.areEqual(id, cId.id); 204 } 205 } 206 207 public PKCS12KeyStoreSpi( 208 JcaJceHelper helper, 209 ASN1ObjectIdentifier keyAlgorithm, 210 ASN1ObjectIdentifier certAlgorithm) 211 { 212 this.keyAlgorithm = keyAlgorithm; 213 this.certAlgorithm = certAlgorithm; 214 215 try 216 { 217 certFact = helper.createCertificateFactory("X.509"); 218 } 219 catch (Exception e) 220 { 221 throw new IllegalArgumentException("can't create cert factory - " + e.toString()); 222 } 223 } 224 225 private SubjectKeyIdentifier createSubjectKeyId( 226 PublicKey pubKey) 227 { 228 try 229 { 230 SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); 231 232 return new SubjectKeyIdentifier(getDigest(info)); 233 } 234 catch (Exception e) 235 { 236 throw new RuntimeException("error creating key"); 237 } 238 } 239 240 private static byte[] getDigest(SubjectPublicKeyInfo spki) 241 { 242 // Android-changed: Use Android digests 243 // Digest digest = DigestFactory.createSHA1(); 244 Digest digest = AndroidDigestFactory.getSHA1(); 245 byte[] resBuf = new byte[digest.getDigestSize()]; 246 247 byte[] bytes = spki.getPublicKeyData().getBytes(); 248 digest.update(bytes, 0, bytes.length); 249 digest.doFinal(resBuf, 0); 250 return resBuf; 251 } 252 253 public void setRandom( 254 SecureRandom rand) 255 { 256 this.random = rand; 257 } 258 259 public Enumeration engineAliases() 260 { 261 Hashtable tab = new Hashtable(); 262 263 Enumeration e = certs.keys(); 264 while (e.hasMoreElements()) 265 { 266 tab.put(e.nextElement(), "cert"); 267 } 268 269 e = keys.keys(); 270 while (e.hasMoreElements()) 271 { 272 String a = (String)e.nextElement(); 273 if (tab.get(a) == null) 274 { 275 tab.put(a, "key"); 276 } 277 } 278 279 return tab.keys(); 280 } 281 282 public boolean engineContainsAlias( 283 String alias) 284 { 285 return (certs.get(alias) != null || keys.get(alias) != null); 286 } 287 288 /** 289 * this is not quite complete - we should follow up on the chain, a bit 290 * tricky if a certificate appears in more than one chain... the store method 291 * now prunes out unused certificates from the chain map if they are present. 292 */ 293 public void engineDeleteEntry( 294 String alias) 295 throws KeyStoreException 296 { 297 Key k = (Key)keys.remove(alias); 298 299 Certificate c = (Certificate)certs.remove(alias); 300 301 if (c != null) 302 { 303 chainCerts.remove(new CertId(c.getPublicKey())); 304 } 305 306 if (k != null) 307 { 308 String id = (String)localIds.remove(alias); 309 if (id != null) 310 { 311 c = (Certificate)keyCerts.remove(id); 312 } 313 if (c != null) 314 { 315 chainCerts.remove(new CertId(c.getPublicKey())); 316 } 317 } 318 } 319 320 /** 321 * simply return the cert for the private key 322 */ 323 public Certificate engineGetCertificate( 324 String alias) 325 { 326 if (alias == null) 327 { 328 throw new IllegalArgumentException("null alias passed to getCertificate."); 329 } 330 331 Certificate c = (Certificate)certs.get(alias); 332 333 // 334 // look up the key table - and try the local key id 335 // 336 if (c == null) 337 { 338 String id = (String)localIds.get(alias); 339 if (id != null) 340 { 341 c = (Certificate)keyCerts.get(id); 342 } 343 else 344 { 345 c = (Certificate)keyCerts.get(alias); 346 } 347 } 348 349 return c; 350 } 351 352 public String engineGetCertificateAlias( 353 Certificate cert) 354 { 355 Enumeration c = certs.elements(); 356 Enumeration k = certs.keys(); 357 358 while (c.hasMoreElements()) 359 { 360 Certificate tc = (Certificate)c.nextElement(); 361 String ta = (String)k.nextElement(); 362 363 if (tc.equals(cert)) 364 { 365 return ta; 366 } 367 } 368 369 c = keyCerts.elements(); 370 k = keyCerts.keys(); 371 372 while (c.hasMoreElements()) 373 { 374 Certificate tc = (Certificate)c.nextElement(); 375 String ta = (String)k.nextElement(); 376 377 if (tc.equals(cert)) 378 { 379 return ta; 380 } 381 } 382 383 return null; 384 } 385 386 public Certificate[] engineGetCertificateChain( 387 String alias) 388 { 389 if (alias == null) 390 { 391 throw new IllegalArgumentException("null alias passed to getCertificateChain."); 392 } 393 394 if (!engineIsKeyEntry(alias)) 395 { 396 return null; 397 } 398 399 Certificate c = engineGetCertificate(alias); 400 401 if (c != null) 402 { 403 Vector cs = new Vector(); 404 405 while (c != null) 406 { 407 X509Certificate x509c = (X509Certificate)c; 408 Certificate nextC = null; 409 410 byte[] bytes = x509c.getExtensionValue(Extension.authorityKeyIdentifier.getId()); 411 if (bytes != null) 412 { 413 try 414 { 415 ASN1InputStream aIn = new ASN1InputStream(bytes); 416 417 byte[] authBytes = ((ASN1OctetString)aIn.readObject()).getOctets(); 418 aIn = new ASN1InputStream(authBytes); 419 420 AuthorityKeyIdentifier id = AuthorityKeyIdentifier.getInstance(aIn.readObject()); 421 if (id.getKeyIdentifier() != null) 422 { 423 nextC = (Certificate)chainCerts.get(new CertId(id.getKeyIdentifier())); 424 } 425 426 } 427 catch (IOException e) 428 { 429 throw new RuntimeException(e.toString()); 430 } 431 } 432 433 if (nextC == null) 434 { 435 // 436 // no authority key id, try the Issuer DN 437 // 438 Principal i = x509c.getIssuerDN(); 439 Principal s = x509c.getSubjectDN(); 440 441 if (!i.equals(s)) 442 { 443 Enumeration e = chainCerts.keys(); 444 445 while (e.hasMoreElements()) 446 { 447 X509Certificate crt = (X509Certificate)chainCerts.get(e.nextElement()); 448 Principal sub = crt.getSubjectDN(); 449 if (sub.equals(i)) 450 { 451 try 452 { 453 x509c.verify(crt.getPublicKey()); 454 nextC = crt; 455 break; 456 } 457 catch (Exception ex) 458 { 459 // continue 460 } 461 } 462 } 463 } 464 } 465 466 if (cs.contains(c)) 467 { 468 c = null; // we've got a certificate chain loop time to stop 469 } 470 else 471 { 472 cs.addElement(c); 473 if (nextC != c) // self signed - end of the chain 474 { 475 c = nextC; 476 } 477 else 478 { 479 c = null; 480 } 481 } 482 } 483 484 Certificate[] certChain = new Certificate[cs.size()]; 485 486 for (int i = 0; i != certChain.length; i++) 487 { 488 certChain[i] = (Certificate)cs.elementAt(i); 489 } 490 491 return certChain; 492 } 493 494 return null; 495 } 496 497 public Date engineGetCreationDate(String alias) 498 { 499 if (alias == null) 500 { 501 throw new NullPointerException("alias == null"); 502 } 503 if (keys.get(alias) == null && certs.get(alias) == null) 504 { 505 return null; 506 } 507 return new Date(); 508 } 509 510 public Key engineGetKey( 511 String alias, 512 char[] password) 513 throws NoSuchAlgorithmException, UnrecoverableKeyException 514 { 515 if (alias == null) 516 { 517 throw new IllegalArgumentException("null alias passed to getKey."); 518 } 519 520 return (Key)keys.get(alias); 521 } 522 523 public boolean engineIsCertificateEntry( 524 String alias) 525 { 526 return (certs.get(alias) != null && keys.get(alias) == null); 527 } 528 529 public boolean engineIsKeyEntry( 530 String alias) 531 { 532 return (keys.get(alias) != null); 533 } 534 535 public void engineSetCertificateEntry( 536 String alias, 537 Certificate cert) 538 throws KeyStoreException 539 { 540 if (keys.get(alias) != null) 541 { 542 throw new KeyStoreException("There is a key entry with the name " + alias + "."); 543 } 544 545 certs.put(alias, cert); 546 chainCerts.put(new CertId(cert.getPublicKey()), cert); 547 } 548 549 public void engineSetKeyEntry( 550 String alias, 551 byte[] key, 552 Certificate[] chain) 553 throws KeyStoreException 554 { 555 throw new RuntimeException("operation not supported"); 556 } 557 558 public void engineSetKeyEntry( 559 String alias, 560 Key key, 561 char[] password, 562 Certificate[] chain) 563 throws KeyStoreException 564 { 565 if (!(key instanceof PrivateKey)) 566 { 567 throw new KeyStoreException("PKCS12 does not support non-PrivateKeys"); 568 } 569 570 if ((key instanceof PrivateKey) && (chain == null)) 571 { 572 throw new KeyStoreException("no certificate chain for private key"); 573 } 574 575 if (keys.get(alias) != null) 576 { 577 engineDeleteEntry(alias); 578 } 579 580 keys.put(alias, key); 581 if (chain != null) 582 { 583 certs.put(alias, chain[0]); 584 585 for (int i = 0; i != chain.length; i++) 586 { 587 chainCerts.put(new CertId(chain[i].getPublicKey()), chain[i]); 588 } 589 } 590 } 591 592 public int engineSize() 593 { 594 Hashtable tab = new Hashtable(); 595 596 Enumeration e = certs.keys(); 597 while (e.hasMoreElements()) 598 { 599 tab.put(e.nextElement(), "cert"); 600 } 601 602 e = keys.keys(); 603 while (e.hasMoreElements()) 604 { 605 String a = (String)e.nextElement(); 606 if (tab.get(a) == null) 607 { 608 tab.put(a, "key"); 609 } 610 } 611 612 return tab.size(); 613 } 614 615 protected PrivateKey unwrapKey( 616 AlgorithmIdentifier algId, 617 byte[] data, 618 char[] password, 619 boolean wrongPKCS12Zero) 620 throws IOException 621 { 622 ASN1ObjectIdentifier algorithm = algId.getAlgorithm(); 623 try 624 { 625 if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds)) 626 { 627 PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); 628 PBEParameterSpec defParams = new PBEParameterSpec( 629 pbeParams.getIV(), 630 validateIterationCount(pbeParams.getIterations())); 631 632 Cipher cipher = helper.createCipher(algorithm.getId()); 633 634 PKCS12Key key = new PKCS12Key(password, wrongPKCS12Zero); 635 636 cipher.init(Cipher.UNWRAP_MODE, key, defParams); 637 638 // we pass "" as the key algorithm type as it is unknown at this point 639 return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY); 640 } 641 else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2)) 642 { 643 644 Cipher cipher = createCipher(Cipher.UNWRAP_MODE, password, algId); 645 646 // we pass "" as the key algorithm type as it is unknown at this point 647 return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY); 648 } 649 } 650 catch (Exception e) 651 { 652 throw new IOException("exception unwrapping private key - " + e.toString()); 653 } 654 655 throw new IOException("exception unwrapping private key - cannot recognise: " + algorithm); 656 } 657 658 protected byte[] wrapKey( 659 String algorithm, 660 Key key, 661 PKCS12PBEParams pbeParams, 662 char[] password) 663 throws IOException 664 { 665 PBEKeySpec pbeSpec = new PBEKeySpec(password); 666 byte[] out; 667 668 try 669 { 670 SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm); 671 PBEParameterSpec defParams = new PBEParameterSpec( 672 pbeParams.getIV(), 673 pbeParams.getIterations().intValue()); 674 675 Cipher cipher = helper.createCipher(algorithm); 676 677 cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams); 678 679 out = cipher.wrap(key); 680 } 681 catch (Exception e) 682 { 683 throw new IOException("exception encrypting data - " + e.toString()); 684 } 685 686 return out; 687 } 688 689 protected byte[] cryptData( 690 boolean forEncryption, 691 AlgorithmIdentifier algId, 692 char[] password, 693 boolean wrongPKCS12Zero, 694 byte[] data) 695 throws IOException 696 { 697 ASN1ObjectIdentifier algorithm = algId.getAlgorithm(); 698 int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; 699 700 if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds)) 701 { 702 PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); 703 try 704 { 705 PBEParameterSpec defParams = new PBEParameterSpec( 706 pbeParams.getIV(), 707 pbeParams.getIterations().intValue()); 708 PKCS12Key key = new PKCS12Key(password, wrongPKCS12Zero); 709 710 Cipher cipher = helper.createCipher(algorithm.getId()); 711 712 cipher.init(mode, key, defParams); 713 return cipher.doFinal(data); 714 } 715 catch (Exception e) 716 { 717 throw new IOException("exception decrypting data - " + e.toString()); 718 } 719 } 720 else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2)) 721 { 722 try 723 { 724 Cipher cipher = createCipher(mode, password, algId); 725 726 return cipher.doFinal(data); 727 } 728 catch (Exception e) 729 { 730 throw new IOException("exception decrypting data - " + e.toString()); 731 } 732 } 733 else 734 { 735 throw new IOException("unknown PBE algorithm: " + algorithm); 736 } 737 } 738 739 private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId) 740 throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchProviderException 741 { 742 PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters()); 743 PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters()); 744 AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme()); 745 746 SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId()); 747 SecretKey key; 748 749 if (func.isDefaultPrf()) 750 { 751 key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), validateIterationCount(func.getIterationCount()), keySizeProvider.getKeySize(encScheme))); 752 } 753 else 754 { 755 key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), validateIterationCount(func.getIterationCount()), keySizeProvider.getKeySize(encScheme), func.getPrf())); 756 } 757 758 Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId()); 759 760 ASN1Encodable encParams = alg.getEncryptionScheme().getParameters(); 761 if (encParams instanceof ASN1OctetString) 762 { 763 cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets())); 764 } 765 // BEGIN Android-removed: Unsupported algorithms 766 /* 767 else 768 { 769 // TODO: at the moment it's just GOST, but... 770 GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams); 771 772 cipher.init(mode, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV())); 773 } 774 */ 775 // END Android-removed: Unsupported algorithms 776 return cipher; 777 } 778 779 public void engineLoad( 780 InputStream stream, 781 char[] password) 782 throws IOException 783 { 784 if (stream == null) // just initialising 785 { 786 return; 787 } 788 789 if (password == null) 790 { 791 throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); 792 } 793 794 BufferedInputStream bufIn = new BufferedInputStream(stream); 795 796 bufIn.mark(10); 797 798 int head = bufIn.read(); 799 800 if (head != 0x30) 801 { 802 throw new IOException("stream does not represent a PKCS12 key store"); 803 } 804 805 bufIn.reset(); 806 807 ASN1InputStream bIn = new ASN1InputStream(bufIn); 808 809 Pfx bag; 810 try 811 { 812 bag = Pfx.getInstance(bIn.readObject()); 813 } 814 catch (Exception e) 815 { 816 throw new IOException(e.getMessage()); 817 } 818 819 ContentInfo info = bag.getAuthSafe(); 820 Vector chain = new Vector(); 821 boolean unmarkedKey = false; 822 boolean wrongPKCS12Zero = false; 823 824 if (bag.getMacData() != null) // check the mac code 825 { 826 MacData mData = bag.getMacData(); 827 DigestInfo dInfo = mData.getMac(); 828 macAlgorithm = dInfo.getAlgorithmId(); 829 byte[] salt = mData.getSalt(); 830 itCount = validateIterationCount(mData.getIterationCount()); 831 saltLength = salt.length; 832 833 byte[] data = ((ASN1OctetString)info.getContent()).getOctets(); 834 835 try 836 { 837 byte[] res = calculatePbeMac(macAlgorithm.getAlgorithm(), salt, itCount, password, false, data); 838 byte[] dig = dInfo.getDigest(); 839 840 if (!Arrays.constantTimeAreEqual(res, dig)) 841 { 842 if (password.length > 0) 843 { 844 throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); 845 } 846 847 // Try with incorrect zero length password 848 res = calculatePbeMac(macAlgorithm.getAlgorithm(), salt, itCount, password, true, data); 849 850 if (!Arrays.constantTimeAreEqual(res, dig)) 851 { 852 throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); 853 } 854 855 wrongPKCS12Zero = true; 856 } 857 } 858 catch (IOException e) 859 { 860 throw e; 861 } 862 catch (Exception e) 863 { 864 throw new IOException("error constructing MAC: " + e.toString()); 865 } 866 } 867 868 keys = new IgnoresCaseHashtable(); 869 localIds = new Hashtable(); 870 871 if (info.getContentType().equals(data)) 872 { 873 bIn = new ASN1InputStream(((ASN1OctetString)info.getContent()).getOctets()); 874 875 AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(bIn.readObject()); 876 ContentInfo[] c = authSafe.getContentInfo(); 877 878 for (int i = 0; i != c.length; i++) 879 { 880 if (c[i].getContentType().equals(data)) 881 { 882 ASN1InputStream dIn = new ASN1InputStream(((ASN1OctetString)c[i].getContent()).getOctets()); 883 ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); 884 885 for (int j = 0; j != seq.size(); j++) 886 { 887 SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); 888 if (b.getBagId().equals(pkcs8ShroudedKeyBag)) 889 { 890 com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); 891 PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); 892 893 // 894 // set the attributes on the key 895 // 896 String alias = null; 897 ASN1OctetString localId = null; 898 899 if (b.getBagAttributes() != null) 900 { 901 Enumeration e = b.getBagAttributes().getObjects(); 902 while (e.hasMoreElements()) 903 { 904 ASN1Sequence sq = (ASN1Sequence)e.nextElement(); 905 ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); 906 ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); 907 ASN1Primitive attr = null; 908 909 if (attrSet.size() > 0) 910 { 911 attr = (ASN1Primitive)attrSet.getObjectAt(0); 912 913 if (privKey instanceof PKCS12BagAttributeCarrier) 914 { 915 PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; 916 ASN1Encodable existing = bagAttr.getBagAttribute(aOid); 917 if (existing != null) 918 { 919 // OK, but the value has to be the same 920 if (!existing.toASN1Primitive().equals(attr)) 921 { 922 throw new IOException( 923 "attempt to add existing attribute with different value"); 924 } 925 } 926 else 927 { 928 bagAttr.setBagAttribute(aOid, attr); 929 } 930 } 931 } 932 933 if (aOid.equals(pkcs_9_at_friendlyName)) 934 { 935 alias = ((DERBMPString)attr).getString(); 936 keys.put(alias, privKey); 937 } 938 else if (aOid.equals(pkcs_9_at_localKeyId)) 939 { 940 localId = (ASN1OctetString)attr; 941 } 942 } 943 } 944 945 if (localId != null) 946 { 947 String name = new String(Hex.encode(localId.getOctets())); 948 949 if (alias == null) 950 { 951 keys.put(name, privKey); 952 } 953 else 954 { 955 localIds.put(alias, name); 956 } 957 } 958 else 959 { 960 unmarkedKey = true; 961 keys.put("unmarked", privKey); 962 } 963 } 964 else if (b.getBagId().equals(certBag)) 965 { 966 chain.addElement(b); 967 } 968 else 969 { 970 System.out.println("extra in data " + b.getBagId()); 971 System.out.println(ASN1Dump.dumpAsString(b)); 972 } 973 } 974 } 975 else if (c[i].getContentType().equals(encryptedData)) 976 { 977 EncryptedData d = EncryptedData.getInstance(c[i].getContent()); 978 byte[] octets = cryptData(false, d.getEncryptionAlgorithm(), 979 password, wrongPKCS12Zero, d.getContent().getOctets()); 980 ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(octets); 981 982 for (int j = 0; j != seq.size(); j++) 983 { 984 SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); 985 986 if (b.getBagId().equals(certBag)) 987 { 988 chain.addElement(b); 989 } 990 else if (b.getBagId().equals(pkcs8ShroudedKeyBag)) 991 { 992 com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); 993 PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); 994 995 // 996 // set the attributes on the key 997 // 998 PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; 999 String alias = null; 1000 ASN1OctetString localId = null; 1001 1002 Enumeration e = b.getBagAttributes().getObjects(); 1003 while (e.hasMoreElements()) 1004 { 1005 ASN1Sequence sq = (ASN1Sequence)e.nextElement(); 1006 ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); 1007 ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); 1008 ASN1Primitive attr = null; 1009 1010 if (attrSet.size() > 0) 1011 { 1012 attr = (ASN1Primitive)attrSet.getObjectAt(0); 1013 1014 ASN1Encodable existing = bagAttr.getBagAttribute(aOid); 1015 if (existing != null) 1016 { 1017 // OK, but the value has to be the same 1018 if (!existing.toASN1Primitive().equals(attr)) 1019 { 1020 throw new IOException( 1021 "attempt to add existing attribute with different value"); 1022 } 1023 } 1024 else 1025 { 1026 bagAttr.setBagAttribute(aOid, attr); 1027 } 1028 } 1029 1030 if (aOid.equals(pkcs_9_at_friendlyName)) 1031 { 1032 alias = ((DERBMPString)attr).getString(); 1033 keys.put(alias, privKey); 1034 } 1035 else if (aOid.equals(pkcs_9_at_localKeyId)) 1036 { 1037 localId = (ASN1OctetString)attr; 1038 } 1039 } 1040 1041 String name = new String(Hex.encode(localId.getOctets())); 1042 1043 if (alias == null) 1044 { 1045 keys.put(name, privKey); 1046 } 1047 else 1048 { 1049 localIds.put(alias, name); 1050 } 1051 } 1052 else if (b.getBagId().equals(keyBag)) 1053 { 1054 com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo kInfo = com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(b.getBagValue()); 1055 PrivateKey privKey = BouncyCastleProvider.getPrivateKey(kInfo); 1056 1057 // 1058 // set the attributes on the key 1059 // 1060 PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; 1061 String alias = null; 1062 ASN1OctetString localId = null; 1063 1064 Enumeration e = b.getBagAttributes().getObjects(); 1065 while (e.hasMoreElements()) 1066 { 1067 ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement()); 1068 ASN1ObjectIdentifier aOid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0)); 1069 ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1)); 1070 ASN1Primitive attr = null; 1071 1072 if (attrSet.size() > 0) 1073 { 1074 attr = (ASN1Primitive)attrSet.getObjectAt(0); 1075 1076 ASN1Encodable existing = bagAttr.getBagAttribute(aOid); 1077 if (existing != null) 1078 { 1079 // OK, but the value has to be the same 1080 if (!existing.toASN1Primitive().equals(attr)) 1081 { 1082 throw new IOException( 1083 "attempt to add existing attribute with different value"); 1084 } 1085 } 1086 else 1087 { 1088 bagAttr.setBagAttribute(aOid, attr); 1089 } 1090 1091 if (aOid.equals(pkcs_9_at_friendlyName)) 1092 { 1093 alias = ((DERBMPString)attr).getString(); 1094 keys.put(alias, privKey); 1095 } 1096 else if (aOid.equals(pkcs_9_at_localKeyId)) 1097 { 1098 localId = (ASN1OctetString)attr; 1099 } 1100 } 1101 } 1102 1103 String name = new String(Hex.encode(localId.getOctets())); 1104 1105 if (alias == null) 1106 { 1107 keys.put(name, privKey); 1108 } 1109 else 1110 { 1111 localIds.put(alias, name); 1112 } 1113 } 1114 else 1115 { 1116 System.out.println("extra in encryptedData " + b.getBagId()); 1117 System.out.println(ASN1Dump.dumpAsString(b)); 1118 } 1119 } 1120 } 1121 else 1122 { 1123 System.out.println("extra " + c[i].getContentType().getId()); 1124 System.out.println("extra " + ASN1Dump.dumpAsString(c[i].getContent())); 1125 } 1126 } 1127 } 1128 1129 certs = new IgnoresCaseHashtable(); 1130 chainCerts = new Hashtable(); 1131 keyCerts = new Hashtable(); 1132 1133 for (int i = 0; i != chain.size(); i++) 1134 { 1135 SafeBag b = (SafeBag)chain.elementAt(i); 1136 CertBag cb = CertBag.getInstance(b.getBagValue()); 1137 1138 if (!cb.getCertId().equals(x509Certificate)) 1139 { 1140 throw new RuntimeException("Unsupported certificate type: " + cb.getCertId()); 1141 } 1142 1143 Certificate cert; 1144 1145 try 1146 { 1147 ByteArrayInputStream cIn = new ByteArrayInputStream( 1148 ((ASN1OctetString)cb.getCertValue()).getOctets()); 1149 cert = certFact.generateCertificate(cIn); 1150 } 1151 catch (Exception e) 1152 { 1153 throw new RuntimeException(e.toString()); 1154 } 1155 1156 // 1157 // set the attributes 1158 // 1159 ASN1OctetString localId = null; 1160 String alias = null; 1161 1162 if (b.getBagAttributes() != null) 1163 { 1164 Enumeration e = b.getBagAttributes().getObjects(); 1165 while (e.hasMoreElements()) 1166 { 1167 ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement()); 1168 ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0)); 1169 ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1)); 1170 1171 if (attrSet.size() > 0) // sometimes this is empty! 1172 { 1173 ASN1Primitive attr = (ASN1Primitive)attrSet.getObjectAt(0); 1174 PKCS12BagAttributeCarrier bagAttr = null; 1175 1176 if (cert instanceof PKCS12BagAttributeCarrier) 1177 { 1178 bagAttr = (PKCS12BagAttributeCarrier)cert; 1179 1180 ASN1Encodable existing = bagAttr.getBagAttribute(oid); 1181 if (existing != null) 1182 { 1183 // OK, but the value has to be the same 1184 if (!existing.toASN1Primitive().equals(attr)) 1185 { 1186 throw new IOException( 1187 "attempt to add existing attribute with different value"); 1188 } 1189 } 1190 else 1191 { 1192 bagAttr.setBagAttribute(oid, attr); 1193 } 1194 } 1195 1196 if (oid.equals(pkcs_9_at_friendlyName)) 1197 { 1198 alias = ((DERBMPString)attr).getString(); 1199 } 1200 else if (oid.equals(pkcs_9_at_localKeyId)) 1201 { 1202 localId = (ASN1OctetString)attr; 1203 } 1204 } 1205 } 1206 } 1207 1208 chainCerts.put(new CertId(cert.getPublicKey()), cert); 1209 1210 if (unmarkedKey) 1211 { 1212 if (keyCerts.isEmpty()) 1213 { 1214 String name = new String(Hex.encode(createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier())); 1215 1216 keyCerts.put(name, cert); 1217 keys.put(name, keys.remove("unmarked")); 1218 } 1219 } 1220 else 1221 { 1222 // 1223 // the local key id needs to override the friendly name 1224 // 1225 if (localId != null) 1226 { 1227 String name = new String(Hex.encode(localId.getOctets())); 1228 1229 keyCerts.put(name, cert); 1230 } 1231 if (alias != null) 1232 { 1233 certs.put(alias, cert); 1234 } 1235 } 1236 } 1237 } 1238 1239 private int validateIterationCount(BigInteger i) 1240 { 1241 int count = i.intValue(); 1242 1243 if (count < 0) 1244 { 1245 throw new IllegalStateException("negative iteration count found"); 1246 } 1247 1248 BigInteger maxValue = Properties.asBigInteger(PKCS12_MAX_IT_COUNT_PROPERTY); 1249 if (maxValue != null) 1250 { 1251 if (maxValue.intValue() < count) 1252 { 1253 throw new IllegalStateException("iteration count " + count + " greater than " + maxValue.intValue()); 1254 } 1255 } 1256 1257 return count; 1258 } 1259 1260 public void engineStore(LoadStoreParameter param) 1261 throws IOException, 1262 NoSuchAlgorithmException, CertificateException 1263 { 1264 if (param == null) 1265 { 1266 throw new IllegalArgumentException("'param' arg cannot be null"); 1267 } 1268 1269 if (!(param instanceof PKCS12StoreParameter || param instanceof JDKPKCS12StoreParameter)) 1270 { 1271 throw new IllegalArgumentException( 1272 "No support for 'param' of type " + param.getClass().getName()); 1273 } 1274 1275 PKCS12StoreParameter bcParam; 1276 1277 if (param instanceof PKCS12StoreParameter) 1278 { 1279 bcParam = (PKCS12StoreParameter)param; 1280 } 1281 else 1282 { 1283 bcParam = new PKCS12StoreParameter(((JDKPKCS12StoreParameter)param).getOutputStream(), 1284 param.getProtectionParameter(), ((JDKPKCS12StoreParameter)param).isUseDEREncoding()); 1285 } 1286 1287 char[] password; 1288 ProtectionParameter protParam = param.getProtectionParameter(); 1289 if (protParam == null) 1290 { 1291 password = null; 1292 } 1293 else if (protParam instanceof KeyStore.PasswordProtection) 1294 { 1295 password = ((KeyStore.PasswordProtection)protParam).getPassword(); 1296 } 1297 else 1298 { 1299 throw new IllegalArgumentException( 1300 "No support for protection parameter of type " + protParam.getClass().getName()); 1301 } 1302 1303 doStore(bcParam.getOutputStream(), password, bcParam.isForDEREncoding()); 1304 } 1305 1306 public void engineStore(OutputStream stream, char[] password) 1307 throws IOException 1308 { 1309 doStore(stream, password, false); 1310 } 1311 1312 private void doStore(OutputStream stream, char[] password, boolean useDEREncoding) 1313 throws IOException 1314 { 1315 if (password == null) 1316 { 1317 throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); 1318 } 1319 1320 // 1321 // handle the key 1322 // 1323 ASN1EncodableVector keyS = new ASN1EncodableVector(); 1324 1325 Enumeration ks = keys.keys(); 1326 1327 while (ks.hasMoreElements()) 1328 { 1329 byte[] kSalt = new byte[SALT_SIZE]; 1330 1331 random.nextBytes(kSalt); 1332 1333 String name = (String)ks.nextElement(); 1334 PrivateKey privKey = (PrivateKey)keys.get(name); 1335 PKCS12PBEParams kParams = new PKCS12PBEParams(kSalt, MIN_ITERATIONS); 1336 byte[] kBytes = wrapKey(keyAlgorithm.getId(), privKey, kParams, password); 1337 AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(keyAlgorithm, kParams.toASN1Primitive()); 1338 com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo kInfo = new com.android.org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, kBytes); 1339 boolean attrSet = false; 1340 ASN1EncodableVector kName = new ASN1EncodableVector(); 1341 1342 if (privKey instanceof PKCS12BagAttributeCarrier) 1343 { 1344 PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)privKey; 1345 // 1346 // make sure we are using the local alias on store 1347 // 1348 DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); 1349 if (nm == null || !nm.getString().equals(name)) 1350 { 1351 bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); 1352 } 1353 1354 // 1355 // make sure we have a local key-id 1356 // 1357 if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) 1358 { 1359 Certificate ct = engineGetCertificate(name); 1360 1361 bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(ct.getPublicKey())); 1362 } 1363 1364 Enumeration e = bagAttrs.getBagAttributeKeys(); 1365 1366 while (e.hasMoreElements()) 1367 { 1368 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 1369 ASN1EncodableVector kSeq = new ASN1EncodableVector(); 1370 1371 kSeq.add(oid); 1372 kSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); 1373 1374 attrSet = true; 1375 1376 kName.add(new DERSequence(kSeq)); 1377 } 1378 } 1379 1380 if (!attrSet) 1381 { 1382 // 1383 // set a default friendly name (from the key id) and local id 1384 // 1385 ASN1EncodableVector kSeq = new ASN1EncodableVector(); 1386 Certificate ct = engineGetCertificate(name); 1387 1388 kSeq.add(pkcs_9_at_localKeyId); 1389 kSeq.add(new DERSet(createSubjectKeyId(ct.getPublicKey()))); 1390 1391 kName.add(new DERSequence(kSeq)); 1392 1393 kSeq = new ASN1EncodableVector(); 1394 1395 kSeq.add(pkcs_9_at_friendlyName); 1396 kSeq.add(new DERSet(new DERBMPString(name))); 1397 1398 kName.add(new DERSequence(kSeq)); 1399 } 1400 1401 SafeBag kBag = new SafeBag(pkcs8ShroudedKeyBag, kInfo.toASN1Primitive(), new DERSet(kName)); 1402 keyS.add(kBag); 1403 } 1404 1405 byte[] keySEncoded = new DERSequence(keyS).getEncoded(ASN1Encoding.DER); 1406 BEROctetString keyString = new BEROctetString(keySEncoded); 1407 1408 // 1409 // certificate processing 1410 // 1411 byte[] cSalt = new byte[SALT_SIZE]; 1412 1413 random.nextBytes(cSalt); 1414 1415 ASN1EncodableVector certSeq = new ASN1EncodableVector(); 1416 PKCS12PBEParams cParams = new PKCS12PBEParams(cSalt, MIN_ITERATIONS); 1417 AlgorithmIdentifier cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Primitive()); 1418 Hashtable doneCerts = new Hashtable(); 1419 1420 Enumeration cs = keys.keys(); 1421 while (cs.hasMoreElements()) 1422 { 1423 try 1424 { 1425 String name = (String)cs.nextElement(); 1426 Certificate cert = engineGetCertificate(name); 1427 boolean cAttrSet = false; 1428 CertBag cBag = new CertBag( 1429 x509Certificate, 1430 new DEROctetString(cert.getEncoded())); 1431 ASN1EncodableVector fName = new ASN1EncodableVector(); 1432 1433 if (cert instanceof PKCS12BagAttributeCarrier) 1434 { 1435 PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; 1436 // 1437 // make sure we are using the local alias on store 1438 // 1439 DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); 1440 if (nm == null || !nm.getString().equals(name)) 1441 { 1442 bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); 1443 } 1444 1445 // 1446 // make sure we have a local key-id 1447 // 1448 if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) 1449 { 1450 bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(cert.getPublicKey())); 1451 } 1452 1453 Enumeration e = bagAttrs.getBagAttributeKeys(); 1454 1455 while (e.hasMoreElements()) 1456 { 1457 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 1458 ASN1EncodableVector fSeq = new ASN1EncodableVector(); 1459 1460 fSeq.add(oid); 1461 fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); 1462 fName.add(new DERSequence(fSeq)); 1463 1464 cAttrSet = true; 1465 } 1466 } 1467 1468 if (!cAttrSet) 1469 { 1470 ASN1EncodableVector fSeq = new ASN1EncodableVector(); 1471 1472 fSeq.add(pkcs_9_at_localKeyId); 1473 fSeq.add(new DERSet(createSubjectKeyId(cert.getPublicKey()))); 1474 fName.add(new DERSequence(fSeq)); 1475 1476 fSeq = new ASN1EncodableVector(); 1477 1478 fSeq.add(pkcs_9_at_friendlyName); 1479 fSeq.add(new DERSet(new DERBMPString(name))); 1480 1481 fName.add(new DERSequence(fSeq)); 1482 } 1483 1484 SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); 1485 1486 certSeq.add(sBag); 1487 1488 doneCerts.put(cert, cert); 1489 } 1490 catch (CertificateEncodingException e) 1491 { 1492 throw new IOException("Error encoding certificate: " + e.toString()); 1493 } 1494 } 1495 1496 cs = certs.keys(); 1497 while (cs.hasMoreElements()) 1498 { 1499 try 1500 { 1501 String certId = (String)cs.nextElement(); 1502 Certificate cert = (Certificate)certs.get(certId); 1503 boolean cAttrSet = false; 1504 1505 if (keys.get(certId) != null) 1506 { 1507 continue; 1508 } 1509 1510 CertBag cBag = new CertBag( 1511 x509Certificate, 1512 new DEROctetString(cert.getEncoded())); 1513 ASN1EncodableVector fName = new ASN1EncodableVector(); 1514 1515 if (cert instanceof PKCS12BagAttributeCarrier) 1516 { 1517 PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; 1518 // 1519 // make sure we are using the local alias on store 1520 // 1521 DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); 1522 if (nm == null || !nm.getString().equals(certId)) 1523 { 1524 bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(certId)); 1525 } 1526 1527 Enumeration e = bagAttrs.getBagAttributeKeys(); 1528 1529 while (e.hasMoreElements()) 1530 { 1531 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 1532 1533 // a certificate not immediately linked to a key doesn't require 1534 // a localKeyID and will confuse some PKCS12 implementations. 1535 // 1536 // If we find one, we'll prune it out. 1537 if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) 1538 { 1539 continue; 1540 } 1541 1542 ASN1EncodableVector fSeq = new ASN1EncodableVector(); 1543 1544 fSeq.add(oid); 1545 fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); 1546 fName.add(new DERSequence(fSeq)); 1547 1548 cAttrSet = true; 1549 } 1550 } 1551 1552 if (!cAttrSet) 1553 { 1554 ASN1EncodableVector fSeq = new ASN1EncodableVector(); 1555 1556 fSeq.add(pkcs_9_at_friendlyName); 1557 fSeq.add(new DERSet(new DERBMPString(certId))); 1558 1559 fName.add(new DERSequence(fSeq)); 1560 } 1561 1562 SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); 1563 1564 certSeq.add(sBag); 1565 1566 doneCerts.put(cert, cert); 1567 } 1568 catch (CertificateEncodingException e) 1569 { 1570 throw new IOException("Error encoding certificate: " + e.toString()); 1571 } 1572 } 1573 1574 Set usedSet = getUsedCertificateSet(); 1575 1576 cs = chainCerts.keys(); 1577 while (cs.hasMoreElements()) 1578 { 1579 try 1580 { 1581 CertId certId = (CertId)cs.nextElement(); 1582 Certificate cert = (Certificate)chainCerts.get(certId); 1583 1584 if (!usedSet.contains(cert)) 1585 { 1586 continue; 1587 } 1588 1589 if (doneCerts.get(cert) != null) 1590 { 1591 continue; 1592 } 1593 1594 CertBag cBag = new CertBag( 1595 x509Certificate, 1596 new DEROctetString(cert.getEncoded())); 1597 ASN1EncodableVector fName = new ASN1EncodableVector(); 1598 1599 if (cert instanceof PKCS12BagAttributeCarrier) 1600 { 1601 PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; 1602 Enumeration e = bagAttrs.getBagAttributeKeys(); 1603 1604 while (e.hasMoreElements()) 1605 { 1606 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 1607 1608 // a certificate not immediately linked to a key doesn't require 1609 // a localKeyID and will confuse some PKCS12 implementations. 1610 // 1611 // If we find one, we'll prune it out. 1612 if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) 1613 { 1614 continue; 1615 } 1616 1617 ASN1EncodableVector fSeq = new ASN1EncodableVector(); 1618 1619 fSeq.add(oid); 1620 fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); 1621 fName.add(new DERSequence(fSeq)); 1622 } 1623 } 1624 1625 SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); 1626 1627 certSeq.add(sBag); 1628 } 1629 catch (CertificateEncodingException e) 1630 { 1631 throw new IOException("Error encoding certificate: " + e.toString()); 1632 } 1633 } 1634 1635 byte[] certSeqEncoded = new DERSequence(certSeq).getEncoded(ASN1Encoding.DER); 1636 byte[] certBytes = cryptData(true, cAlgId, password, false, certSeqEncoded); 1637 EncryptedData cInfo = new EncryptedData(data, cAlgId, new BEROctetString(certBytes)); 1638 1639 ContentInfo[] info = new ContentInfo[] 1640 { 1641 new ContentInfo(data, keyString), 1642 new ContentInfo(encryptedData, cInfo.toASN1Primitive()) 1643 }; 1644 1645 AuthenticatedSafe auth = new AuthenticatedSafe(info); 1646 1647 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 1648 DEROutputStream asn1Out; 1649 if (useDEREncoding) 1650 { 1651 asn1Out = new DEROutputStream(bOut); 1652 } 1653 else 1654 { 1655 asn1Out = new BEROutputStream(bOut); 1656 } 1657 1658 asn1Out.writeObject(auth); 1659 1660 byte[] pkg = bOut.toByteArray(); 1661 1662 ContentInfo mainInfo = new ContentInfo(data, new BEROctetString(pkg)); 1663 1664 // 1665 // create the mac 1666 // 1667 byte[] mSalt = new byte[saltLength]; 1668 1669 random.nextBytes(mSalt); 1670 1671 byte[] data = ((ASN1OctetString)mainInfo.getContent()).getOctets(); 1672 1673 MacData mData; 1674 1675 try 1676 { 1677 byte[] res = calculatePbeMac(macAlgorithm.getAlgorithm(), mSalt, itCount, password, false, data); 1678 1679 DigestInfo dInfo = new DigestInfo(macAlgorithm, res); 1680 1681 mData = new MacData(dInfo, mSalt, itCount); 1682 } 1683 catch (Exception e) 1684 { 1685 throw new IOException("error constructing MAC: " + e.toString()); 1686 } 1687 1688 // 1689 // output the Pfx 1690 // 1691 Pfx pfx = new Pfx(mainInfo, mData); 1692 1693 if (useDEREncoding) 1694 { 1695 asn1Out = new DEROutputStream(stream); 1696 } 1697 else 1698 { 1699 asn1Out = new BEROutputStream(stream); 1700 } 1701 1702 asn1Out.writeObject(pfx); 1703 } 1704 1705 private Set getUsedCertificateSet() 1706 { 1707 Set usedSet = new HashSet(); 1708 1709 for (Enumeration en = keys.keys(); en.hasMoreElements();) 1710 { 1711 String alias = (String)en.nextElement(); 1712 1713 Certificate[] certs = engineGetCertificateChain(alias); 1714 1715 for (int i = 0; i != certs.length; i++) 1716 { 1717 usedSet.add(certs[i]); 1718 } 1719 } 1720 1721 for (Enumeration en = certs.keys(); en.hasMoreElements();) 1722 { 1723 String alias = (String)en.nextElement(); 1724 1725 Certificate cert = engineGetCertificate(alias); 1726 1727 usedSet.add(cert); 1728 } 1729 1730 return usedSet; 1731 } 1732 1733 private byte[] calculatePbeMac( 1734 ASN1ObjectIdentifier oid, 1735 byte[] salt, 1736 int itCount, 1737 char[] password, 1738 boolean wrongPkcs12Zero, 1739 byte[] data) 1740 throws Exception 1741 { 1742 PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount); 1743 1744 Mac mac = helper.createMac(oid.getId()); 1745 mac.init(new PKCS12Key(password, wrongPkcs12Zero), defParams); 1746 mac.update(data); 1747 1748 return mac.doFinal(); 1749 } 1750 1751 /** 1752 * @hide This class is not part of the Android public SDK API 1753 */ 1754 public static class BCPKCS12KeyStore 1755 extends PKCS12KeyStoreSpi 1756 { 1757 public BCPKCS12KeyStore() 1758 { 1759 // Android-changed: Use default provider for JCA algorithms instead of BC 1760 // Was: super(new BCJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); 1761 super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); 1762 } 1763 } 1764 1765 // BEGIN Android-removed: Unsupported algorithms 1766 /* 1767 public static class BCPKCS12KeyStore3DES 1768 extends PKCS12KeyStoreSpi 1769 { 1770 public BCPKCS12KeyStore3DES() 1771 { 1772 super(new BCJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); 1773 } 1774 } 1775 1776 public static class DefPKCS12KeyStore 1777 extends PKCS12KeyStoreSpi 1778 { 1779 public DefPKCS12KeyStore() 1780 { 1781 super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); 1782 } 1783 } 1784 1785 public static class DefPKCS12KeyStore3DES 1786 extends PKCS12KeyStoreSpi 1787 { 1788 public DefPKCS12KeyStore3DES() 1789 { 1790 super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); 1791 } 1792 } 1793 */ 1794 // END android-removed 1795 1796 private static class IgnoresCaseHashtable 1797 { 1798 private Hashtable orig = new Hashtable(); 1799 private Hashtable keys = new Hashtable(); 1800 1801 public void put(String key, Object value) 1802 { 1803 String lower = (key == null) ? null : Strings.toLowerCase(key); 1804 String k = (String)keys.get(lower); 1805 if (k != null) 1806 { 1807 orig.remove(k); 1808 } 1809 1810 keys.put(lower, key); 1811 orig.put(key, value); 1812 } 1813 1814 public Enumeration keys() 1815 { 1816 return orig.keys(); 1817 } 1818 1819 public Object remove(String alias) 1820 { 1821 String k = (String)keys.remove(alias == null ? null : Strings.toLowerCase(alias)); 1822 if (k == null) 1823 { 1824 return null; 1825 } 1826 1827 return orig.remove(k); 1828 } 1829 1830 public Object get(String alias) 1831 { 1832 String k = (String)keys.get(alias == null ? null : Strings.toLowerCase(alias)); 1833 if (k == null) 1834 { 1835 return null; 1836 } 1837 1838 return orig.get(k); 1839 } 1840 1841 public Enumeration elements() 1842 { 1843 return orig.elements(); 1844 } 1845 } 1846 1847 private static class DefaultSecretKeyProvider 1848 { 1849 private final Map KEY_SIZES; 1850 1851 DefaultSecretKeyProvider() 1852 { 1853 Map keySizes = new HashMap(); 1854 1855 keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128)); 1856 1857 keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); 1858 1859 keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128)); 1860 keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192)); 1861 keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256)); 1862 1863 // BEGIN Android-removed: Unsupported algorithms 1864 /* 1865 keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128)); 1866 keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192)); 1867 keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256)); 1868 1869 keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256)); 1870 */ 1871 // END Android-removed: Unsupported algorithms 1872 1873 KEY_SIZES = Collections.unmodifiableMap(keySizes); 1874 } 1875 1876 public int getKeySize(AlgorithmIdentifier algorithmIdentifier) 1877 { 1878 // TODO: not all ciphers/oid relationships are this simple. 1879 Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm()); 1880 1881 if (keySize != null) 1882 { 1883 return keySize.intValue(); 1884 } 1885 1886 return -1; 1887 } 1888 } 1889 } 1890