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