1package org.bouncycastle.jce.provider; 2 3import java.io.ByteArrayOutputStream; 4import java.io.IOException; 5import java.math.BigInteger; 6import java.security.GeneralSecurityException; 7import java.security.KeyFactory; 8import java.security.PublicKey; 9import java.security.cert.CRLException; 10import java.security.cert.CertPath; 11import java.security.cert.CertPathValidatorException; 12import java.security.cert.CertStore; 13import java.security.cert.CertStoreException; 14import java.security.cert.Certificate; 15import java.security.cert.CertificateParsingException; 16import java.security.cert.PKIXParameters; 17import java.security.cert.PolicyQualifierInfo; 18import java.security.cert.TrustAnchor; 19import java.security.cert.X509CRL; 20import java.security.cert.X509CRLEntry; 21import java.security.cert.X509CRLSelector; 22import java.security.cert.X509CertSelector; 23import java.security.cert.X509Certificate; 24import java.security.interfaces.DSAParams; 25import java.security.interfaces.DSAPublicKey; 26import java.security.spec.DSAPublicKeySpec; 27import java.text.ParseException; 28import java.util.ArrayList; 29import java.util.Collection; 30import java.util.Date; 31import java.util.Enumeration; 32import java.util.HashSet; 33import java.util.Iterator; 34import java.util.List; 35import java.util.Map; 36import java.util.Set; 37 38import javax.security.auth.x500.X500Principal; 39 40import org.bouncycastle.asn1.ASN1Encodable; 41import org.bouncycastle.asn1.ASN1InputStream; 42import org.bouncycastle.asn1.ASN1Integer; 43import org.bouncycastle.asn1.ASN1OctetString; 44import org.bouncycastle.asn1.ASN1OutputStream; 45import org.bouncycastle.asn1.ASN1Primitive; 46import org.bouncycastle.asn1.ASN1Sequence; 47import org.bouncycastle.asn1.DEREnumerated; 48import org.bouncycastle.asn1.DERGeneralizedTime; 49import org.bouncycastle.asn1.DERIA5String; 50import org.bouncycastle.asn1.DERObjectIdentifier; 51import org.bouncycastle.asn1.DERSequence; 52import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers; 53import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 54import org.bouncycastle.asn1.x509.CRLDistPoint; 55import org.bouncycastle.asn1.x509.CRLReason; 56import org.bouncycastle.asn1.x509.DistributionPoint; 57import org.bouncycastle.asn1.x509.DistributionPointName; 58import org.bouncycastle.asn1.x509.GeneralName; 59import org.bouncycastle.asn1.x509.GeneralNames; 60import org.bouncycastle.asn1.x509.PolicyInformation; 61import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 62import org.bouncycastle.asn1.x509.X509Extension; 63import org.bouncycastle.asn1.x509.X509Extensions; 64// BEGIN android-removed 65// import org.bouncycastle.jce.X509LDAPCertStoreParameters; 66// END android-removed 67import org.bouncycastle.jce.exception.ExtCertPathValidatorException; 68import org.bouncycastle.util.Selector; 69import org.bouncycastle.util.StoreException; 70import org.bouncycastle.x509.ExtendedPKIXBuilderParameters; 71import org.bouncycastle.x509.ExtendedPKIXParameters; 72// BEGIN android-removed 73// import org.bouncycastle.x509.X509AttributeCertStoreSelector; 74// END android-removed 75import org.bouncycastle.x509.X509AttributeCertificate; 76import org.bouncycastle.x509.X509CRLStoreSelector; 77import org.bouncycastle.x509.X509CertStoreSelector; 78import org.bouncycastle.x509.X509Store; 79 80public class CertPathValidatorUtilities 81{ 82 protected static final PKIXCRLUtil CRL_UTIL = new PKIXCRLUtil(); 83 84 protected static final String CERTIFICATE_POLICIES = X509Extensions.CertificatePolicies.getId(); 85 protected static final String BASIC_CONSTRAINTS = X509Extensions.BasicConstraints.getId(); 86 protected static final String POLICY_MAPPINGS = X509Extensions.PolicyMappings.getId(); 87 protected static final String SUBJECT_ALTERNATIVE_NAME = X509Extensions.SubjectAlternativeName.getId(); 88 protected static final String NAME_CONSTRAINTS = X509Extensions.NameConstraints.getId(); 89 protected static final String KEY_USAGE = X509Extensions.KeyUsage.getId(); 90 protected static final String INHIBIT_ANY_POLICY = X509Extensions.InhibitAnyPolicy.getId(); 91 protected static final String ISSUING_DISTRIBUTION_POINT = X509Extensions.IssuingDistributionPoint.getId(); 92 protected static final String DELTA_CRL_INDICATOR = X509Extensions.DeltaCRLIndicator.getId(); 93 protected static final String POLICY_CONSTRAINTS = X509Extensions.PolicyConstraints.getId(); 94 protected static final String FRESHEST_CRL = X509Extensions.FreshestCRL.getId(); 95 protected static final String CRL_DISTRIBUTION_POINTS = X509Extensions.CRLDistributionPoints.getId(); 96 protected static final String AUTHORITY_KEY_IDENTIFIER = X509Extensions.AuthorityKeyIdentifier.getId(); 97 98 protected static final String ANY_POLICY = "2.5.29.32.0"; 99 100 protected static final String CRL_NUMBER = X509Extensions.CRLNumber.getId(); 101 102 /* 103 * key usage bits 104 */ 105 protected static final int KEY_CERT_SIGN = 5; 106 protected static final int CRL_SIGN = 6; 107 108 protected static final String[] crlReasons = new String[]{ 109 "unspecified", 110 "keyCompromise", 111 "cACompromise", 112 "affiliationChanged", 113 "superseded", 114 "cessationOfOperation", 115 "certificateHold", 116 "unknown", 117 "removeFromCRL", 118 "privilegeWithdrawn", 119 "aACompromise"}; 120 121 /** 122 * Search the given Set of TrustAnchor's for one that is the 123 * issuer of the given X509 certificate. Uses the default provider 124 * for signature verification. 125 * 126 * @param cert the X509 certificate 127 * @param trustAnchors a Set of TrustAnchor's 128 * @return the <code>TrustAnchor</code> object if found or 129 * <code>null</code> if not. 130 * @throws AnnotatedException if a TrustAnchor was found but the signature verification 131 * on the given certificate has thrown an exception. 132 */ 133 protected static TrustAnchor findTrustAnchor( 134 X509Certificate cert, 135 Set trustAnchors) 136 throws AnnotatedException 137 { 138 return findTrustAnchor(cert, trustAnchors, null); 139 } 140 141 /** 142 * Search the given Set of TrustAnchor's for one that is the 143 * issuer of the given X509 certificate. Uses the specified 144 * provider for signature verification, or the default provider 145 * if null. 146 * 147 * @param cert the X509 certificate 148 * @param trustAnchors a Set of TrustAnchor's 149 * @param sigProvider the provider to use for signature verification 150 * @return the <code>TrustAnchor</code> object if found or 151 * <code>null</code> if not. 152 * @throws AnnotatedException if a TrustAnchor was found but the signature verification 153 * on the given certificate has thrown an exception. 154 */ 155 protected static TrustAnchor findTrustAnchor( 156 X509Certificate cert, 157 Set trustAnchors, 158 String sigProvider) 159 throws AnnotatedException 160 { 161 TrustAnchor trust = null; 162 PublicKey trustPublicKey = null; 163 Exception invalidKeyEx = null; 164 165 X509CertSelector certSelectX509 = new X509CertSelector(); 166 X500Principal certIssuer = getEncodedIssuerPrincipal(cert); 167 168 try 169 { 170 certSelectX509.setSubject(certIssuer.getEncoded()); 171 } 172 catch (IOException ex) 173 { 174 throw new AnnotatedException("Cannot set subject search criteria for trust anchor.", ex); 175 } 176 177 Iterator iter = trustAnchors.iterator(); 178 while (iter.hasNext() && trust == null) 179 { 180 trust = (TrustAnchor)iter.next(); 181 if (trust.getTrustedCert() != null) 182 { 183 if (certSelectX509.match(trust.getTrustedCert())) 184 { 185 trustPublicKey = trust.getTrustedCert().getPublicKey(); 186 } 187 else 188 { 189 trust = null; 190 } 191 } 192 else if (trust.getCAName() != null 193 && trust.getCAPublicKey() != null) 194 { 195 try 196 { 197 X500Principal caName = new X500Principal(trust.getCAName()); 198 if (certIssuer.equals(caName)) 199 { 200 trustPublicKey = trust.getCAPublicKey(); 201 } 202 else 203 { 204 trust = null; 205 } 206 } 207 catch (IllegalArgumentException ex) 208 { 209 trust = null; 210 } 211 } 212 else 213 { 214 trust = null; 215 } 216 217 if (trustPublicKey != null) 218 { 219 try 220 { 221 verifyX509Certificate(cert, trustPublicKey, sigProvider); 222 } 223 catch (Exception ex) 224 { 225 invalidKeyEx = ex; 226 trust = null; 227 trustPublicKey = null; 228 } 229 } 230 } 231 232 if (trust == null && invalidKeyEx != null) 233 { 234 throw new AnnotatedException("TrustAnchor found but certificate validation failed.", invalidKeyEx); 235 } 236 237 return trust; 238 } 239 240 protected static void addAdditionalStoresFromAltNames( 241 X509Certificate cert, 242 ExtendedPKIXParameters pkixParams) 243 throws CertificateParsingException 244 { 245 // if in the IssuerAltName extension an URI 246 // is given, add an additinal X.509 store 247 if (cert.getIssuerAlternativeNames() != null) 248 { 249 Iterator it = cert.getIssuerAlternativeNames().iterator(); 250 while (it.hasNext()) 251 { 252 // look for URI 253 List list = (List)it.next(); 254 // BEGIN android-changed 255 if (list.get(0).equals(Integer.valueOf(GeneralName.uniformResourceIdentifier))) 256 // END android-changed 257 { 258 // found 259 String temp = (String)list.get(1); 260 CertPathValidatorUtilities.addAdditionalStoreFromLocation(temp, pkixParams); 261 } 262 } 263 } 264 } 265 266 /** 267 * Returns the issuer of an attribute certificate or certificate. 268 * 269 * @param cert The attribute certificate or certificate. 270 * @return The issuer as <code>X500Principal</code>. 271 */ 272 protected static X500Principal getEncodedIssuerPrincipal( 273 Object cert) 274 { 275 if (cert instanceof X509Certificate) 276 { 277 return ((X509Certificate)cert).getIssuerX500Principal(); 278 } 279 else 280 { 281 return (X500Principal)((X509AttributeCertificate)cert).getIssuer().getPrincipals()[0]; 282 } 283 } 284 285 protected static Date getValidDate(PKIXParameters paramsPKIX) 286 { 287 Date validDate = paramsPKIX.getDate(); 288 289 if (validDate == null) 290 { 291 validDate = new Date(); 292 } 293 294 return validDate; 295 } 296 297 protected static X500Principal getSubjectPrincipal(X509Certificate cert) 298 { 299 return cert.getSubjectX500Principal(); 300 } 301 302 protected static boolean isSelfIssued(X509Certificate cert) 303 { 304 return cert.getSubjectDN().equals(cert.getIssuerDN()); 305 } 306 307 308 /** 309 * Extract the value of the given extension, if it exists. 310 * 311 * @param ext The extension object. 312 * @param oid The object identifier to obtain. 313 * @throws AnnotatedException if the extension cannot be read. 314 */ 315 protected static ASN1Primitive getExtensionValue( 316 java.security.cert.X509Extension ext, 317 String oid) 318 throws AnnotatedException 319 { 320 byte[] bytes = ext.getExtensionValue(oid); 321 if (bytes == null) 322 { 323 return null; 324 } 325 326 return getObject(oid, bytes); 327 } 328 329 private static ASN1Primitive getObject( 330 String oid, 331 byte[] ext) 332 throws AnnotatedException 333 { 334 try 335 { 336 ASN1InputStream aIn = new ASN1InputStream(ext); 337 ASN1OctetString octs = (ASN1OctetString)aIn.readObject(); 338 339 aIn = new ASN1InputStream(octs.getOctets()); 340 return aIn.readObject(); 341 } 342 catch (Exception e) 343 { 344 throw new AnnotatedException("exception processing extension " + oid, e); 345 } 346 } 347 348 protected static X500Principal getIssuerPrincipal(X509CRL crl) 349 { 350 return crl.getIssuerX500Principal(); 351 } 352 353 protected static AlgorithmIdentifier getAlgorithmIdentifier( 354 PublicKey key) 355 throws CertPathValidatorException 356 { 357 try 358 { 359 ASN1InputStream aIn = new ASN1InputStream(key.getEncoded()); 360 361 SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject()); 362 363 return info.getAlgorithmId(); 364 } 365 catch (Exception e) 366 { 367 throw new ExtCertPathValidatorException("Subject public key cannot be decoded.", e); 368 } 369 } 370 371 // crl checking 372 373 374 // 375 // policy checking 376 // 377 378 protected static final Set getQualifierSet(ASN1Sequence qualifiers) 379 throws CertPathValidatorException 380 { 381 Set pq = new HashSet(); 382 383 if (qualifiers == null) 384 { 385 return pq; 386 } 387 388 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 389 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 390 391 Enumeration e = qualifiers.getObjects(); 392 393 while (e.hasMoreElements()) 394 { 395 try 396 { 397 aOut.writeObject((ASN1Encodable)e.nextElement()); 398 399 pq.add(new PolicyQualifierInfo(bOut.toByteArray())); 400 } 401 catch (IOException ex) 402 { 403 throw new ExtCertPathValidatorException("Policy qualifier info cannot be decoded.", ex); 404 } 405 406 bOut.reset(); 407 } 408 409 return pq; 410 } 411 412 protected static PKIXPolicyNode removePolicyNode( 413 PKIXPolicyNode validPolicyTree, 414 List[] policyNodes, 415 PKIXPolicyNode _node) 416 { 417 PKIXPolicyNode _parent = (PKIXPolicyNode)_node.getParent(); 418 419 if (validPolicyTree == null) 420 { 421 return null; 422 } 423 424 if (_parent == null) 425 { 426 for (int j = 0; j < policyNodes.length; j++) 427 { 428 policyNodes[j] = new ArrayList(); 429 } 430 431 return null; 432 } 433 else 434 { 435 _parent.removeChild(_node); 436 removePolicyNodeRecurse(policyNodes, _node); 437 438 return validPolicyTree; 439 } 440 } 441 442 private static void removePolicyNodeRecurse( 443 List[] policyNodes, 444 PKIXPolicyNode _node) 445 { 446 policyNodes[_node.getDepth()].remove(_node); 447 448 if (_node.hasChildren()) 449 { 450 Iterator _iter = _node.getChildren(); 451 while (_iter.hasNext()) 452 { 453 PKIXPolicyNode _child = (PKIXPolicyNode)_iter.next(); 454 removePolicyNodeRecurse(policyNodes, _child); 455 } 456 } 457 } 458 459 460 protected static boolean processCertD1i( 461 int index, 462 List[] policyNodes, 463 DERObjectIdentifier pOid, 464 Set pq) 465 { 466 List policyNodeVec = policyNodes[index - 1]; 467 468 for (int j = 0; j < policyNodeVec.size(); j++) 469 { 470 PKIXPolicyNode node = (PKIXPolicyNode)policyNodeVec.get(j); 471 Set expectedPolicies = node.getExpectedPolicies(); 472 473 if (expectedPolicies.contains(pOid.getId())) 474 { 475 Set childExpectedPolicies = new HashSet(); 476 childExpectedPolicies.add(pOid.getId()); 477 478 PKIXPolicyNode child = new PKIXPolicyNode(new ArrayList(), 479 index, 480 childExpectedPolicies, 481 node, 482 pq, 483 pOid.getId(), 484 false); 485 node.addChild(child); 486 policyNodes[index].add(child); 487 488 return true; 489 } 490 } 491 492 return false; 493 } 494 495 protected static void processCertD1ii( 496 int index, 497 List[] policyNodes, 498 DERObjectIdentifier _poid, 499 Set _pq) 500 { 501 List policyNodeVec = policyNodes[index - 1]; 502 503 for (int j = 0; j < policyNodeVec.size(); j++) 504 { 505 PKIXPolicyNode _node = (PKIXPolicyNode)policyNodeVec.get(j); 506 507 if (ANY_POLICY.equals(_node.getValidPolicy())) 508 { 509 Set _childExpectedPolicies = new HashSet(); 510 _childExpectedPolicies.add(_poid.getId()); 511 512 PKIXPolicyNode _child = new PKIXPolicyNode(new ArrayList(), 513 index, 514 _childExpectedPolicies, 515 _node, 516 _pq, 517 _poid.getId(), 518 false); 519 _node.addChild(_child); 520 policyNodes[index].add(_child); 521 return; 522 } 523 } 524 } 525 526 protected static void prepareNextCertB1( 527 int i, 528 List[] policyNodes, 529 String id_p, 530 Map m_idp, 531 X509Certificate cert 532 ) 533 throws AnnotatedException, CertPathValidatorException 534 { 535 boolean idp_found = false; 536 Iterator nodes_i = policyNodes[i].iterator(); 537 while (nodes_i.hasNext()) 538 { 539 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 540 if (node.getValidPolicy().equals(id_p)) 541 { 542 idp_found = true; 543 node.expectedPolicies = (Set)m_idp.get(id_p); 544 break; 545 } 546 } 547 548 if (!idp_found) 549 { 550 nodes_i = policyNodes[i].iterator(); 551 while (nodes_i.hasNext()) 552 { 553 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 554 if (ANY_POLICY.equals(node.getValidPolicy())) 555 { 556 Set pq = null; 557 ASN1Sequence policies = null; 558 try 559 { 560 policies = DERSequence.getInstance(getExtensionValue(cert, CERTIFICATE_POLICIES)); 561 } 562 catch (Exception e) 563 { 564 throw new AnnotatedException("Certificate policies cannot be decoded.", e); 565 } 566 Enumeration e = policies.getObjects(); 567 while (e.hasMoreElements()) 568 { 569 PolicyInformation pinfo = null; 570 571 try 572 { 573 pinfo = PolicyInformation.getInstance(e.nextElement()); 574 } 575 catch (Exception ex) 576 { 577 throw new AnnotatedException("Policy information cannot be decoded.", ex); 578 } 579 if (ANY_POLICY.equals(pinfo.getPolicyIdentifier().getId())) 580 { 581 try 582 { 583 pq = getQualifierSet(pinfo.getPolicyQualifiers()); 584 } 585 catch (CertPathValidatorException ex) 586 { 587 throw new ExtCertPathValidatorException( 588 "Policy qualifier info set could not be built.", ex); 589 } 590 break; 591 } 592 } 593 boolean ci = false; 594 if (cert.getCriticalExtensionOIDs() != null) 595 { 596 ci = cert.getCriticalExtensionOIDs().contains(CERTIFICATE_POLICIES); 597 } 598 599 PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent(); 600 if (ANY_POLICY.equals(p_node.getValidPolicy())) 601 { 602 PKIXPolicyNode c_node = new PKIXPolicyNode( 603 new ArrayList(), i, 604 (Set)m_idp.get(id_p), 605 p_node, pq, id_p, ci); 606 p_node.addChild(c_node); 607 policyNodes[i].add(c_node); 608 } 609 break; 610 } 611 } 612 } 613 } 614 615 protected static PKIXPolicyNode prepareNextCertB2( 616 int i, 617 List[] policyNodes, 618 String id_p, 619 PKIXPolicyNode validPolicyTree) 620 { 621 Iterator nodes_i = policyNodes[i].iterator(); 622 while (nodes_i.hasNext()) 623 { 624 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 625 if (node.getValidPolicy().equals(id_p)) 626 { 627 PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent(); 628 p_node.removeChild(node); 629 nodes_i.remove(); 630 for (int k = (i - 1); k >= 0; k--) 631 { 632 List nodes = policyNodes[k]; 633 for (int l = 0; l < nodes.size(); l++) 634 { 635 PKIXPolicyNode node2 = (PKIXPolicyNode)nodes.get(l); 636 if (!node2.hasChildren()) 637 { 638 validPolicyTree = removePolicyNode(validPolicyTree, policyNodes, node2); 639 if (validPolicyTree == null) 640 { 641 break; 642 } 643 } 644 } 645 } 646 } 647 } 648 return validPolicyTree; 649 } 650 651 protected static boolean isAnyPolicy( 652 Set policySet) 653 { 654 return policySet == null || policySet.contains(ANY_POLICY) || policySet.isEmpty(); 655 } 656 657 protected static void addAdditionalStoreFromLocation(String location, 658 ExtendedPKIXParameters pkixParams) 659 { 660 if (pkixParams.isAdditionalLocationsEnabled()) 661 { 662 try 663 { 664 // BEGIN android-removed 665 // if (location.startsWith("ldap://")) 666 // { 667 // // ldap://directory.d-trust.net/CN=D-TRUST 668 // // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE 669 // // skip "ldap://" 670 // location = location.substring(7); 671 // // after first / baseDN starts 672 // String base = null; 673 // String url = null; 674 // if (location.indexOf("/") != -1) 675 // { 676 // base = location.substring(location.indexOf("/")); 677 // // URL 678 // url = "ldap://" 679 // + location.substring(0, location.indexOf("/")); 680 // } 681 // else 682 // { 683 // url = "ldap://" + location; 684 // } 685 // // use all purpose parameters 686 // X509LDAPCertStoreParameters params = new X509LDAPCertStoreParameters.Builder( 687 // url, base).build(); 688 // pkixParams.addAdditionalStore(X509Store.getInstance( 689 // "CERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME)); 690 // pkixParams.addAdditionalStore(X509Store.getInstance( 691 // "CRL/LDAP", params, BouncyCastleProvider.PROVIDER_NAME)); 692 // pkixParams.addAdditionalStore(X509Store.getInstance( 693 // "ATTRIBUTECERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME)); 694 // pkixParams.addAdditionalStore(X509Store.getInstance( 695 // "CERTIFICATEPAIR/LDAP", params, BouncyCastleProvider.PROVIDER_NAME)); 696 // } 697 // END android-removed 698 } 699 catch (Exception e) 700 { 701 // cannot happen 702 throw new RuntimeException("Exception adding X.509 stores."); 703 } 704 } 705 } 706 707 /** 708 * Return a Collection of all certificates or attribute certificates found 709 * in the X509Store's that are matching the certSelect criteriums. 710 * 711 * @param certSelect a {@link Selector} object that will be used to select 712 * the certificates 713 * @param certStores a List containing only {@link X509Store} objects. These 714 * are used to search for certificates. 715 * @return a Collection of all found {@link X509Certificate} or 716 * {@link org.bouncycastle.x509.X509AttributeCertificate} objects. 717 * May be empty but never <code>null</code>. 718 */ 719 protected static Collection findCertificates(X509CertStoreSelector certSelect, 720 List certStores) 721 throws AnnotatedException 722 { 723 Set certs = new HashSet(); 724 Iterator iter = certStores.iterator(); 725 726 while (iter.hasNext()) 727 { 728 Object obj = iter.next(); 729 730 if (obj instanceof X509Store) 731 { 732 X509Store certStore = (X509Store)obj; 733 try 734 { 735 certs.addAll(certStore.getMatches(certSelect)); 736 } 737 catch (StoreException e) 738 { 739 throw new AnnotatedException( 740 "Problem while picking certificates from X.509 store.", e); 741 } 742 } 743 else 744 { 745 CertStore certStore = (CertStore)obj; 746 747 try 748 { 749 certs.addAll(certStore.getCertificates(certSelect)); 750 } 751 catch (CertStoreException e) 752 { 753 throw new AnnotatedException( 754 "Problem while picking certificates from certificate store.", 755 e); 756 } 757 } 758 } 759 return certs; 760 } 761 762 // BEGIN android-removed 763 // protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect, 764 // List certStores) 765 // throws AnnotatedException 766 // { 767 // Set certs = new HashSet(); 768 // Iterator iter = certStores.iterator(); 769 // 770 // while (iter.hasNext()) 771 // { 772 // Object obj = iter.next(); 773 // 774 // if (obj instanceof X509Store) 775 // { 776 // X509Store certStore = (X509Store)obj; 777 // try 778 // { 779 // certs.addAll(certStore.getMatches(certSelect)); 780 // } 781 // catch (StoreException e) 782 // { 783 // throw new AnnotatedException( 784 // "Problem while picking certificates from X.509 store.", e); 785 // } 786 // } 787 // } 788 // return certs; 789 // } 790 // END android-removed 791 792 protected static void addAdditionalStoresFromCRLDistributionPoint( 793 CRLDistPoint crldp, ExtendedPKIXParameters pkixParams) 794 throws AnnotatedException 795 { 796 if (crldp != null) 797 { 798 DistributionPoint dps[] = null; 799 try 800 { 801 dps = crldp.getDistributionPoints(); 802 } 803 catch (Exception e) 804 { 805 throw new AnnotatedException( 806 "Distribution points could not be read.", e); 807 } 808 for (int i = 0; i < dps.length; i++) 809 { 810 DistributionPointName dpn = dps[i].getDistributionPoint(); 811 // look for URIs in fullName 812 if (dpn != null) 813 { 814 if (dpn.getType() == DistributionPointName.FULL_NAME) 815 { 816 GeneralName[] genNames = GeneralNames.getInstance( 817 dpn.getName()).getNames(); 818 // look for an URI 819 for (int j = 0; j < genNames.length; j++) 820 { 821 if (genNames[j].getTagNo() == GeneralName.uniformResourceIdentifier) 822 { 823 String location = DERIA5String.getInstance( 824 genNames[j].getName()).getString(); 825 CertPathValidatorUtilities 826 .addAdditionalStoreFromLocation(location, 827 pkixParams); 828 } 829 } 830 } 831 } 832 } 833 } 834 } 835 836 /** 837 * Add the CRL issuers from the cRLIssuer field of the distribution point or 838 * from the certificate if not given to the issuer criterion of the 839 * <code>selector</code>. 840 * <p/> 841 * The <code>issuerPrincipals</code> are a collection with a single 842 * <code>X500Principal</code> for <code>X509Certificate</code>s. For 843 * {@link X509AttributeCertificate}s the issuer may contain more than one 844 * <code>X500Principal</code>. 845 * 846 * @param dp The distribution point. 847 * @param issuerPrincipals The issuers of the certificate or attribute 848 * certificate which contains the distribution point. 849 * @param selector The CRL selector. 850 * @param pkixParams The PKIX parameters containing the cert stores. 851 * @throws AnnotatedException if an exception occurs while processing. 852 * @throws ClassCastException if <code>issuerPrincipals</code> does not 853 * contain only <code>X500Principal</code>s. 854 */ 855 protected static void getCRLIssuersFromDistributionPoint( 856 DistributionPoint dp, 857 Collection issuerPrincipals, 858 X509CRLSelector selector, 859 ExtendedPKIXParameters pkixParams) 860 throws AnnotatedException 861 { 862 List issuers = new ArrayList(); 863 // indirect CRL 864 if (dp.getCRLIssuer() != null) 865 { 866 GeneralName genNames[] = dp.getCRLIssuer().getNames(); 867 // look for a DN 868 for (int j = 0; j < genNames.length; j++) 869 { 870 if (genNames[j].getTagNo() == GeneralName.directoryName) 871 { 872 try 873 { 874 issuers.add(new X500Principal(genNames[j].getName() 875 .toASN1Primitive().getEncoded())); 876 } 877 catch (IOException e) 878 { 879 throw new AnnotatedException( 880 "CRL issuer information from distribution point cannot be decoded.", 881 e); 882 } 883 } 884 } 885 } 886 else 887 { 888 /* 889 * certificate issuer is CRL issuer, distributionPoint field MUST be 890 * present. 891 */ 892 if (dp.getDistributionPoint() == null) 893 { 894 throw new AnnotatedException( 895 "CRL issuer is omitted from distribution point but no distributionPoint field present."); 896 } 897 // add and check issuer principals 898 for (Iterator it = issuerPrincipals.iterator(); it.hasNext(); ) 899 { 900 issuers.add((X500Principal)it.next()); 901 } 902 } 903 // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid 904 // distributionPoint 905// if (dp.getDistributionPoint() != null) 906// { 907// // look for nameRelativeToCRLIssuer 908// if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER) 909// { 910// // append fragment to issuer, only one 911// // issuer can be there, if this is given 912// if (issuers.size() != 1) 913// { 914// throw new AnnotatedException( 915// "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given."); 916// } 917// ASN1Encodable relName = dp.getDistributionPoint().getName(); 918// Iterator it = issuers.iterator(); 919// List issuersTemp = new ArrayList(issuers.size()); 920// while (it.hasNext()) 921// { 922// Enumeration e = null; 923// try 924// { 925// e = ASN1Sequence.getInstance( 926// new ASN1InputStream(((X500Principal) it.next()) 927// .getEncoded()).readObject()).getObjects(); 928// } 929// catch (IOException ex) 930// { 931// throw new AnnotatedException( 932// "Cannot decode CRL issuer information.", ex); 933// } 934// ASN1EncodableVector v = new ASN1EncodableVector(); 935// while (e.hasMoreElements()) 936// { 937// v.add((ASN1Encodable) e.nextElement()); 938// } 939// v.add(relName); 940// issuersTemp.add(new X500Principal(new DERSequence(v) 941// .getDEREncoded())); 942// } 943// issuers.clear(); 944// issuers.addAll(issuersTemp); 945// } 946// } 947 Iterator it = issuers.iterator(); 948 while (it.hasNext()) 949 { 950 try 951 { 952 selector.addIssuerName(((X500Principal)it.next()).getEncoded()); 953 } 954 catch (IOException ex) 955 { 956 throw new AnnotatedException( 957 "Cannot decode CRL issuer information.", ex); 958 } 959 } 960 } 961 962 private static BigInteger getSerialNumber( 963 Object cert) 964 { 965 if (cert instanceof X509Certificate) 966 { 967 return ((X509Certificate)cert).getSerialNumber(); 968 } 969 else 970 { 971 return ((X509AttributeCertificate)cert).getSerialNumber(); 972 } 973 } 974 975 protected static void getCertStatus( 976 Date validDate, 977 X509CRL crl, 978 Object cert, 979 CertStatus certStatus) 980 throws AnnotatedException 981 { 982 X509CRLEntry crl_entry = null; 983 984 boolean isIndirect; 985 try 986 { 987 isIndirect = X509CRLObject.isIndirectCRL(crl); 988 } 989 catch (CRLException exception) 990 { 991 throw new AnnotatedException("Failed check for indirect CRL.", exception); 992 } 993 994 if (isIndirect) 995 { 996 crl_entry = crl.getRevokedCertificate(getSerialNumber(cert)); 997 998 if (crl_entry == null) 999 { 1000 return; 1001 } 1002 1003 X500Principal certIssuer = crl_entry.getCertificateIssuer(); 1004 1005 if (certIssuer == null) 1006 { 1007 certIssuer = getIssuerPrincipal(crl); 1008 } 1009 1010 if (!getEncodedIssuerPrincipal(cert).equals(certIssuer)) 1011 { 1012 return; 1013 } 1014 } 1015 else if (!getEncodedIssuerPrincipal(cert).equals(getIssuerPrincipal(crl))) 1016 { 1017 return; // not for our issuer, ignore 1018 } 1019 else 1020 { 1021 crl_entry = crl.getRevokedCertificate(getSerialNumber(cert)); 1022 1023 if (crl_entry == null) 1024 { 1025 return; 1026 } 1027 } 1028 1029 DEREnumerated reasonCode = null; 1030 if (crl_entry.hasExtensions()) 1031 { 1032 try 1033 { 1034 reasonCode = DEREnumerated 1035 .getInstance(CertPathValidatorUtilities 1036 .getExtensionValue(crl_entry, 1037 X509Extension.reasonCode.getId())); 1038 } 1039 catch (Exception e) 1040 { 1041 throw new AnnotatedException( 1042 "Reason code CRL entry extension could not be decoded.", 1043 e); 1044 } 1045 } 1046 1047 // for reason keyCompromise, caCompromise, aACompromise or 1048 // unspecified 1049 if (!(validDate.getTime() < crl_entry.getRevocationDate().getTime()) 1050 || reasonCode == null 1051 || reasonCode.getValue().intValue() == 0 1052 || reasonCode.getValue().intValue() == 1 1053 || reasonCode.getValue().intValue() == 2 1054 || reasonCode.getValue().intValue() == 8) 1055 { 1056 1057 // (i) or (j) (1) 1058 if (reasonCode != null) 1059 { 1060 certStatus.setCertStatus(reasonCode.getValue().intValue()); 1061 } 1062 // (i) or (j) (2) 1063 else 1064 { 1065 certStatus.setCertStatus(CRLReason.unspecified); 1066 } 1067 certStatus.setRevocationDate(crl_entry.getRevocationDate()); 1068 } 1069 } 1070 1071 /** 1072 * Fetches delta CRLs according to RFC 3280 section 5.2.4. 1073 * 1074 * @param currentDate The date for which the delta CRLs must be valid. 1075 * @param paramsPKIX The extended PKIX parameters. 1076 * @param completeCRL The complete CRL the delta CRL is for. 1077 * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs. 1078 * @throws AnnotatedException if an exception occurs while picking the delta 1079 * CRLs. 1080 */ 1081 protected static Set getDeltaCRLs(Date currentDate, 1082 ExtendedPKIXParameters paramsPKIX, X509CRL completeCRL) 1083 throws AnnotatedException 1084 { 1085 1086 X509CRLStoreSelector deltaSelect = new X509CRLStoreSelector(); 1087 1088 // 5.2.4 (a) 1089 try 1090 { 1091 deltaSelect.addIssuerName(CertPathValidatorUtilities 1092 .getIssuerPrincipal(completeCRL).getEncoded()); 1093 } 1094 catch (IOException e) 1095 { 1096 throw new AnnotatedException("Cannot extract issuer from CRL.", e); 1097 } 1098 1099 BigInteger completeCRLNumber = null; 1100 try 1101 { 1102 ASN1Primitive derObject = CertPathValidatorUtilities.getExtensionValue(completeCRL, 1103 CRL_NUMBER); 1104 if (derObject != null) 1105 { 1106 completeCRLNumber = ASN1Integer.getInstance(derObject).getPositiveValue(); 1107 } 1108 } 1109 catch (Exception e) 1110 { 1111 throw new AnnotatedException( 1112 "CRL number extension could not be extracted from CRL.", e); 1113 } 1114 1115 // 5.2.4 (b) 1116 byte[] idp = null; 1117 try 1118 { 1119 idp = completeCRL.getExtensionValue(ISSUING_DISTRIBUTION_POINT); 1120 } 1121 catch (Exception e) 1122 { 1123 throw new AnnotatedException( 1124 "Issuing distribution point extension value could not be read.", 1125 e); 1126 } 1127 1128 // 5.2.4 (d) 1129 1130 deltaSelect.setMinCRLNumber(completeCRLNumber == null ? null : completeCRLNumber 1131 .add(BigInteger.valueOf(1))); 1132 1133 deltaSelect.setIssuingDistributionPoint(idp); 1134 deltaSelect.setIssuingDistributionPointEnabled(true); 1135 1136 // 5.2.4 (c) 1137 deltaSelect.setMaxBaseCRLNumber(completeCRLNumber); 1138 1139 // find delta CRLs 1140 Set temp = CRL_UTIL.findCRLs(deltaSelect, paramsPKIX, currentDate); 1141 1142 Set result = new HashSet(); 1143 1144 for (Iterator it = temp.iterator(); it.hasNext(); ) 1145 { 1146 X509CRL crl = (X509CRL)it.next(); 1147 1148 if (isDeltaCRL(crl)) 1149 { 1150 result.add(crl); 1151 } 1152 } 1153 1154 return result; 1155 } 1156 1157 private static boolean isDeltaCRL(X509CRL crl) 1158 { 1159 Set critical = crl.getCriticalExtensionOIDs(); 1160 1161 if (critical == null) 1162 { 1163 return false; 1164 } 1165 1166 return critical.contains(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR); 1167 } 1168 1169 /** 1170 * Fetches complete CRLs according to RFC 3280. 1171 * 1172 * @param dp The distribution point for which the complete CRL 1173 * @param cert The <code>X509Certificate</code> or 1174 * {@link org.bouncycastle.x509.X509AttributeCertificate} for 1175 * which the CRL should be searched. 1176 * @param currentDate The date for which the delta CRLs must be valid. 1177 * @param paramsPKIX The extended PKIX parameters. 1178 * @return A <code>Set</code> of <code>X509CRL</code>s with complete 1179 * CRLs. 1180 * @throws AnnotatedException if an exception occurs while picking the CRLs 1181 * or no CRLs are found. 1182 */ 1183 protected static Set getCompleteCRLs(DistributionPoint dp, Object cert, 1184 Date currentDate, ExtendedPKIXParameters paramsPKIX) 1185 throws AnnotatedException 1186 { 1187 X509CRLStoreSelector crlselect = new X509CRLStoreSelector(); 1188 try 1189 { 1190 Set issuers = new HashSet(); 1191 if (cert instanceof X509AttributeCertificate) 1192 { 1193 issuers.add(((X509AttributeCertificate)cert) 1194 .getIssuer().getPrincipals()[0]); 1195 } 1196 else 1197 { 1198 issuers.add(getEncodedIssuerPrincipal(cert)); 1199 } 1200 CertPathValidatorUtilities.getCRLIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX); 1201 } 1202 catch (AnnotatedException e) 1203 { 1204 throw new AnnotatedException( 1205 "Could not get issuer information from distribution point.", e); 1206 } 1207 if (cert instanceof X509Certificate) 1208 { 1209 crlselect.setCertificateChecking((X509Certificate)cert); 1210 } 1211 else if (cert instanceof X509AttributeCertificate) 1212 { 1213 crlselect.setAttrCertificateChecking((X509AttributeCertificate)cert); 1214 } 1215 1216 1217 crlselect.setCompleteCRLEnabled(true); 1218 1219 Set crls = CRL_UTIL.findCRLs(crlselect, paramsPKIX, currentDate); 1220 1221 if (crls.isEmpty()) 1222 { 1223 if (cert instanceof X509AttributeCertificate) 1224 { 1225 X509AttributeCertificate aCert = (X509AttributeCertificate)cert; 1226 1227 throw new AnnotatedException("No CRLs found for issuer \"" + aCert.getIssuer().getPrincipals()[0] + "\""); 1228 } 1229 else 1230 { 1231 X509Certificate xCert = (X509Certificate)cert; 1232 1233 throw new AnnotatedException("No CRLs found for issuer \"" + xCert.getIssuerX500Principal() + "\""); 1234 } 1235 } 1236 return crls; 1237 } 1238 1239 protected static Date getValidCertDateFromValidityModel( 1240 ExtendedPKIXParameters paramsPKIX, CertPath certPath, int index) 1241 throws AnnotatedException 1242 { 1243 if (paramsPKIX.getValidityModel() == ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL) 1244 { 1245 // if end cert use given signing/encryption/... time 1246 if (index <= 0) 1247 { 1248 return CertPathValidatorUtilities.getValidDate(paramsPKIX); 1249 // else use time when previous cert was created 1250 } 1251 else 1252 { 1253 if (index - 1 == 0) 1254 { 1255 DERGeneralizedTime dateOfCertgen = null; 1256 try 1257 { 1258 byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId()); 1259 if (extBytes != null) 1260 { 1261 dateOfCertgen = DERGeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); 1262 } 1263 } 1264 catch (IOException e) 1265 { 1266 throw new AnnotatedException( 1267 "Date of cert gen extension could not be read."); 1268 } 1269 catch (IllegalArgumentException e) 1270 { 1271 throw new AnnotatedException( 1272 "Date of cert gen extension could not be read."); 1273 } 1274 if (dateOfCertgen != null) 1275 { 1276 try 1277 { 1278 return dateOfCertgen.getDate(); 1279 } 1280 catch (ParseException e) 1281 { 1282 throw new AnnotatedException( 1283 "Date from date of cert gen extension could not be parsed.", 1284 e); 1285 } 1286 } 1287 return ((X509Certificate)certPath.getCertificates().get( 1288 index - 1)).getNotBefore(); 1289 } 1290 else 1291 { 1292 return ((X509Certificate)certPath.getCertificates().get( 1293 index - 1)).getNotBefore(); 1294 } 1295 } 1296 } 1297 else 1298 { 1299 return getValidDate(paramsPKIX); 1300 } 1301 } 1302 1303 /** 1304 * Return the next working key inheriting DSA parameters if necessary. 1305 * <p> 1306 * This methods inherits DSA parameters from the indexed certificate or 1307 * previous certificates in the certificate chain to the returned 1308 * <code>PublicKey</code>. The list is searched upwards, meaning the end 1309 * certificate is at position 0 and previous certificates are following. 1310 * </p> 1311 * <p> 1312 * If the indexed certificate does not contain a DSA key this method simply 1313 * returns the public key. If the DSA key already contains DSA parameters 1314 * the key is also only returned. 1315 * </p> 1316 * 1317 * @param certs The certification path. 1318 * @param index The index of the certificate which contains the public key 1319 * which should be extended with DSA parameters. 1320 * @return The public key of the certificate in list position 1321 * <code>index</code> extended with DSA parameters if applicable. 1322 * @throws AnnotatedException if DSA parameters cannot be inherited. 1323 */ 1324 protected static PublicKey getNextWorkingKey(List certs, int index) 1325 throws CertPathValidatorException 1326 { 1327 Certificate cert = (Certificate)certs.get(index); 1328 PublicKey pubKey = cert.getPublicKey(); 1329 if (!(pubKey instanceof DSAPublicKey)) 1330 { 1331 return pubKey; 1332 } 1333 DSAPublicKey dsaPubKey = (DSAPublicKey)pubKey; 1334 if (dsaPubKey.getParams() != null) 1335 { 1336 return dsaPubKey; 1337 } 1338 for (int i = index + 1; i < certs.size(); i++) 1339 { 1340 X509Certificate parentCert = (X509Certificate)certs.get(i); 1341 pubKey = parentCert.getPublicKey(); 1342 if (!(pubKey instanceof DSAPublicKey)) 1343 { 1344 throw new CertPathValidatorException( 1345 "DSA parameters cannot be inherited from previous certificate."); 1346 } 1347 DSAPublicKey prevDSAPubKey = (DSAPublicKey)pubKey; 1348 if (prevDSAPubKey.getParams() == null) 1349 { 1350 continue; 1351 } 1352 DSAParams dsaParams = prevDSAPubKey.getParams(); 1353 DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec( 1354 dsaPubKey.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()); 1355 try 1356 { 1357 KeyFactory keyFactory = KeyFactory.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME); 1358 return keyFactory.generatePublic(dsaPubKeySpec); 1359 } 1360 catch (Exception exception) 1361 { 1362 throw new RuntimeException(exception.getMessage()); 1363 } 1364 } 1365 throw new CertPathValidatorException("DSA parameters cannot be inherited from previous certificate."); 1366 } 1367 1368 /** 1369 * Find the issuer certificates of a given certificate. 1370 * 1371 * @param cert The certificate for which an issuer should be found. 1372 * @param pkixParams 1373 * @return A <code>Collection</code> object containing the issuer 1374 * <code>X509Certificate</code>s. Never <code>null</code>. 1375 * @throws AnnotatedException if an error occurs. 1376 */ 1377 protected static Collection findIssuerCerts( 1378 X509Certificate cert, 1379 ExtendedPKIXBuilderParameters pkixParams) 1380 throws AnnotatedException 1381 { 1382 X509CertStoreSelector certSelect = new X509CertStoreSelector(); 1383 Set certs = new HashSet(); 1384 try 1385 { 1386 certSelect.setSubject(cert.getIssuerX500Principal().getEncoded()); 1387 } 1388 catch (IOException ex) 1389 { 1390 throw new AnnotatedException( 1391 "Subject criteria for certificate selector to find issuer certificate could not be set.", ex); 1392 } 1393 1394 Iterator iter; 1395 1396 try 1397 { 1398 List matches = new ArrayList(); 1399 1400 matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getCertStores())); 1401 matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getStores())); 1402 matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getAdditionalStores())); 1403 1404 iter = matches.iterator(); 1405 } 1406 catch (AnnotatedException e) 1407 { 1408 throw new AnnotatedException("Issuer certificate cannot be searched.", e); 1409 } 1410 1411 X509Certificate issuer = null; 1412 while (iter.hasNext()) 1413 { 1414 issuer = (X509Certificate)iter.next(); 1415 // issuer cannot be verified because possible DSA inheritance 1416 // parameters are missing 1417 certs.add(issuer); 1418 } 1419 return certs; 1420 } 1421 1422 protected static void verifyX509Certificate(X509Certificate cert, PublicKey publicKey, 1423 String sigProvider) 1424 throws GeneralSecurityException 1425 { 1426 if (sigProvider == null) 1427 { 1428 cert.verify(publicKey); 1429 } 1430 else 1431 { 1432 cert.verify(publicKey, sigProvider); 1433 } 1434 } 1435} 1436