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