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