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