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