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