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