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