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