1 package org.bouncycastle.pkix.jcajce; 2 3 import java.io.IOException; 4 import java.security.PublicKey; 5 import java.security.cert.CertPathBuilder; 6 import java.security.cert.CertPathBuilderException; 7 import java.security.cert.CertPathValidatorException; 8 import java.security.cert.X509CRL; 9 import java.security.cert.X509CRLSelector; 10 import java.security.cert.X509CertSelector; 11 import java.security.cert.X509Certificate; 12 import java.security.cert.X509Extension; 13 import java.util.ArrayList; 14 import java.util.Date; 15 import java.util.Enumeration; 16 import java.util.HashSet; 17 import java.util.Iterator; 18 import java.util.LinkedHashSet; 19 import java.util.List; 20 import java.util.Set; 21 22 import org.bouncycastle.asn1.ASN1Encodable; 23 import org.bouncycastle.asn1.ASN1EncodableVector; 24 import org.bouncycastle.asn1.ASN1Primitive; 25 import org.bouncycastle.asn1.ASN1Sequence; 26 import org.bouncycastle.asn1.DERSequence; 27 import org.bouncycastle.asn1.x500.X500Name; 28 import org.bouncycastle.asn1.x509.BasicConstraints; 29 import org.bouncycastle.asn1.x509.CRLDistPoint; 30 import org.bouncycastle.asn1.x509.CRLReason; 31 import org.bouncycastle.asn1.x509.DistributionPoint; 32 import org.bouncycastle.asn1.x509.DistributionPointName; 33 import org.bouncycastle.asn1.x509.Extension; 34 import org.bouncycastle.asn1.x509.GeneralName; 35 import org.bouncycastle.asn1.x509.GeneralNames; 36 import org.bouncycastle.asn1.x509.IssuingDistributionPoint; 37 import org.bouncycastle.jcajce.PKIXCRLStoreSelector; 38 import org.bouncycastle.jcajce.PKIXCertStoreSelector; 39 import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters; 40 import org.bouncycastle.jcajce.PKIXExtendedParameters; 41 import org.bouncycastle.jcajce.util.JcaJceHelper; 42 import org.bouncycastle.util.Arrays; 43 44 class RFC3280CertPathUtilities 45 { 46 /** 47 * If the complete CRL includes an issuing distribution point (IDP) CRL 48 * extension check the following: 49 * <p> 50 * (i) If the distribution point name is present in the IDP CRL extension 51 * and the distribution field is present in the DP, then verify that one of 52 * the names in the IDP matches one of the names in the DP. If the 53 * distribution point name is present in the IDP CRL extension and the 54 * distribution field is omitted from the DP, then verify that one of the 55 * names in the IDP matches one of the names in the cRLIssuer field of the 56 * DP. 57 * </p> 58 * <p> 59 * (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL 60 * extension, verify that the certificate does not include the basic 61 * constraints extension with the cA boolean asserted. 62 * </p> 63 * <p> 64 * (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL 65 * extension, verify that the certificate includes the basic constraints 66 * extension with the cA boolean asserted. 67 * </p> 68 * <p> 69 * (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted. 70 * </p> 71 * 72 * @param dp The distribution point. 73 * @param cert The certificate. 74 * @param crl The CRL. 75 * @throws AnnotatedException if one of the conditions is not met or an error occurs. 76 */ processCRLB2( DistributionPoint dp, Object cert, X509CRL crl)77 protected static void processCRLB2( 78 DistributionPoint dp, 79 Object cert, 80 X509CRL crl) 81 throws AnnotatedException 82 { 83 IssuingDistributionPoint idp = null; 84 try 85 { 86 idp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(crl, 87 Extension.issuingDistributionPoint)); 88 } 89 catch (Exception e) 90 { 91 throw new AnnotatedException("Issuing distribution point extension could not be decoded.", e); 92 } 93 // (b) (2) (i) 94 // distribution point name is present 95 if (idp != null) 96 { 97 if (idp.getDistributionPoint() != null) 98 { 99 // make list of names 100 DistributionPointName dpName = IssuingDistributionPoint.getInstance(idp).getDistributionPoint(); 101 List names = new ArrayList(); 102 103 if (dpName.getType() == DistributionPointName.FULL_NAME) 104 { 105 GeneralName[] genNames = GeneralNames.getInstance(dpName.getName()).getNames(); 106 for (int j = 0; j < genNames.length; j++) 107 { 108 names.add(genNames[j]); 109 } 110 } 111 if (dpName.getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER) 112 { 113 ASN1EncodableVector vec = new ASN1EncodableVector(); 114 try 115 { 116 Enumeration e = ASN1Sequence.getInstance(crl.getIssuerX500Principal().getEncoded()).getObjects(); 117 while (e.hasMoreElements()) 118 { 119 vec.add((ASN1Encodable)e.nextElement()); 120 } 121 } 122 catch (Exception e) 123 { 124 throw new AnnotatedException("Could not read CRL issuer.", e); 125 } 126 vec.add(dpName.getName()); 127 names.add(new GeneralName(X500Name.getInstance(new DERSequence(vec)))); 128 } 129 boolean matches = false; 130 // verify that one of the names in the IDP matches one 131 // of the names in the DP. 132 if (dp.getDistributionPoint() != null) 133 { 134 dpName = dp.getDistributionPoint(); 135 GeneralName[] genNames = null; 136 if (dpName.getType() == DistributionPointName.FULL_NAME) 137 { 138 genNames = GeneralNames.getInstance(dpName.getName()).getNames(); 139 } 140 if (dpName.getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER) 141 { 142 if (dp.getCRLIssuer() != null) 143 { 144 genNames = dp.getCRLIssuer().getNames(); 145 } 146 else 147 { 148 genNames = new GeneralName[1]; 149 try 150 { 151 genNames[0] = new GeneralName(X500Name.getInstance(((X509Certificate)cert).getIssuerX500Principal().getEncoded())); 152 } 153 catch (Exception e) 154 { 155 throw new AnnotatedException("Could not read certificate issuer.", e); 156 } 157 } 158 for (int j = 0; j < genNames.length; j++) 159 { 160 Enumeration e = ASN1Sequence.getInstance(genNames[j].getName().toASN1Primitive()).getObjects(); 161 ASN1EncodableVector vec = new ASN1EncodableVector(); 162 while (e.hasMoreElements()) 163 { 164 vec.add((ASN1Encodable)e.nextElement()); 165 } 166 vec.add(dpName.getName()); 167 genNames[j] = new GeneralName(X500Name.getInstance(new DERSequence(vec))); 168 } 169 } 170 if (genNames != null) 171 { 172 for (int j = 0; j < genNames.length; j++) 173 { 174 if (names.contains(genNames[j])) 175 { 176 matches = true; 177 break; 178 } 179 } 180 } 181 if (!matches) 182 { 183 throw new AnnotatedException( 184 "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); 185 } 186 } 187 // verify that one of the names in 188 // the IDP matches one of the names in the cRLIssuer field of 189 // the DP 190 else 191 { 192 if (dp.getCRLIssuer() == null) 193 { 194 throw new AnnotatedException("Either the cRLIssuer or the distributionPoint field must " 195 + "be contained in DistributionPoint."); 196 } 197 GeneralName[] genNames = dp.getCRLIssuer().getNames(); 198 for (int j = 0; j < genNames.length; j++) 199 { 200 if (names.contains(genNames[j])) 201 { 202 matches = true; 203 break; 204 } 205 } 206 if (!matches) 207 { 208 throw new AnnotatedException( 209 "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point."); 210 } 211 } 212 } 213 BasicConstraints bc = null; 214 try 215 { 216 bc = BasicConstraints.getInstance(RevocationUtilities.getExtensionValue((X509Extension)cert, 217 Extension.basicConstraints)); 218 } 219 catch (Exception e) 220 { 221 throw new AnnotatedException("Basic constraints extension could not be decoded.", e); 222 } 223 224 if (cert instanceof X509Certificate) 225 { 226 // (b) (2) (ii) 227 if (idp.onlyContainsUserCerts() && (bc != null && bc.isCA())) 228 { 229 throw new AnnotatedException("CA Cert CRL only contains user certificates."); 230 } 231 232 // (b) (2) (iii) 233 if (idp.onlyContainsCACerts() && (bc == null || !bc.isCA())) 234 { 235 throw new AnnotatedException("End CRL only contains CA certificates."); 236 } 237 } 238 239 // (b) (2) (iv) 240 if (idp.onlyContainsAttributeCerts()) 241 { 242 throw new AnnotatedException("onlyContainsAttributeCerts boolean is asserted."); 243 } 244 } 245 } 246 247 /** 248 * If the DP includes cRLIssuer, then verify that the issuer field in the 249 * complete CRL matches cRLIssuer in the DP and that the complete CRL 250 * contains an issuing distribution point extension with the indirectCRL 251 * boolean asserted. Otherwise, verify that the CRL issuer matches the 252 * certificate issuer. 253 * 254 * @param dp The distribution point. 255 * @param cert The certificate ot attribute certificate. 256 * @param crl The CRL for <code>cert</code>. 257 * @throws AnnotatedException if one of the above conditions does not apply or an error 258 * occurs. 259 */ processCRLB1( DistributionPoint dp, Object cert, X509CRL crl)260 protected static void processCRLB1( 261 DistributionPoint dp, 262 Object cert, 263 X509CRL crl) 264 throws AnnotatedException 265 { 266 ASN1Primitive idp = RevocationUtilities.getExtensionValue(crl, Extension.issuingDistributionPoint); 267 boolean isIndirect = false; 268 if (idp != null) 269 { 270 if (IssuingDistributionPoint.getInstance(idp).isIndirectCRL()) 271 { 272 isIndirect = true; 273 } 274 } 275 byte[] issuerBytes; 276 277 issuerBytes = crl.getIssuerX500Principal().getEncoded(); 278 279 280 boolean matchIssuer = false; 281 if (dp.getCRLIssuer() != null) 282 { 283 GeneralName genNames[] = dp.getCRLIssuer().getNames(); 284 for (int j = 0; j < genNames.length; j++) 285 { 286 if (genNames[j].getTagNo() == GeneralName.directoryName) 287 { 288 try 289 { 290 if (Arrays.areEqual(genNames[j].getName().toASN1Primitive().getEncoded(), issuerBytes)) 291 { 292 matchIssuer = true; 293 } 294 } 295 catch (IOException e) 296 { 297 throw new AnnotatedException( 298 "CRL issuer information from distribution point cannot be decoded.", e); 299 } 300 } 301 } 302 if (matchIssuer && !isIndirect) 303 { 304 throw new AnnotatedException("Distribution point contains cRLIssuer field but CRL is not indirect."); 305 } 306 if (!matchIssuer) 307 { 308 throw new AnnotatedException("CRL issuer of CRL does not match CRL issuer of distribution point."); 309 } 310 } 311 else 312 { 313 if (crl.getIssuerX500Principal().equals(((X509Certificate)cert).getIssuerX500Principal())) 314 { 315 matchIssuer = true; 316 } 317 } 318 if (!matchIssuer) 319 { 320 throw new AnnotatedException("Cannot find matching CRL issuer for certificate."); 321 } 322 } 323 processCRLD( X509CRL crl, DistributionPoint dp)324 protected static ReasonsMask processCRLD( 325 X509CRL crl, 326 DistributionPoint dp) 327 throws AnnotatedException 328 { 329 IssuingDistributionPoint idp = null; 330 try 331 { 332 idp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(crl, 333 Extension.issuingDistributionPoint)); 334 } 335 catch (Exception e) 336 { 337 throw new AnnotatedException("Issuing distribution point extension could not be decoded.", e); 338 } 339 // (d) (1) 340 if (idp != null && idp.getOnlySomeReasons() != null && dp.getReasons() != null) 341 { 342 return new ReasonsMask(dp.getReasons()).intersect(new ReasonsMask(idp.getOnlySomeReasons())); 343 } 344 // (d) (4) 345 if ((idp == null || idp.getOnlySomeReasons() == null) && dp.getReasons() == null) 346 { 347 return ReasonsMask.allReasons; 348 } 349 // (d) (2) and (d)(3) 350 return (dp.getReasons() == null 351 ? ReasonsMask.allReasons 352 : new ReasonsMask(dp.getReasons())).intersect(idp == null 353 ? ReasonsMask.allReasons 354 : new ReasonsMask(idp.getOnlySomeReasons())); 355 356 } 357 358 359 public static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId(); 360 361 public static final String FRESHEST_CRL = Extension.freshestCRL.getId(); 362 363 public static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId(); 364 365 public static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId(); 366 367 public static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId(); 368 369 /* 370 * key usage bits 371 */ 372 protected static final int KEY_CERT_SIGN = 5; 373 374 protected static final int CRL_SIGN = 6; 375 376 /** 377 * Obtain and validate the certification path for the complete CRL issuer. 378 * If a key usage extension is present in the CRL issuer's certificate, 379 * verify that the cRLSign bit is set. 380 * 381 * @param crl CRL which contains revocation information for the certificate 382 * <code>cert</code>. 383 * @param cert The attribute certificate or certificate to check if it is 384 * revoked. 385 * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>. 386 * @param defaultCRLSignKey The public key of the issuer certificate 387 * <code>defaultCRLSignCert</code>. 388 * @param paramsPKIX PKIX parameters. 389 * @param certPathCerts The certificates on the certification path. 390 * @return A <code>Set</code> with all keys of possible CRL issuer 391 * certificates. 392 * @throws AnnotatedException if the CRL is not valid or the status cannot be checked or 393 * some error occurs. 394 */ processCRLF( X509CRL crl, Object cert, X509Certificate defaultCRLSignCert, PublicKey defaultCRLSignKey, PKIXExtendedParameters paramsPKIX, List certPathCerts, JcaJceHelper helper)395 protected static Set processCRLF( 396 X509CRL crl, 397 Object cert, 398 X509Certificate defaultCRLSignCert, 399 PublicKey defaultCRLSignKey, 400 PKIXExtendedParameters paramsPKIX, 401 List certPathCerts, 402 JcaJceHelper helper) 403 throws AnnotatedException 404 { 405 // (f) 406 407 // get issuer from CRL 408 X509CertSelector certSelector = new X509CertSelector(); 409 try 410 { 411 byte[] issuerPrincipal = crl.getIssuerX500Principal().getEncoded(); 412 certSelector.setSubject(issuerPrincipal); 413 } 414 catch (IOException e) 415 { 416 throw new AnnotatedException( 417 "subject criteria for certificate selector to find issuer certificate for CRL could not be set", e); 418 } 419 420 PKIXCertStoreSelector selector = new PKIXCertStoreSelector.Builder(certSelector).build(); 421 422 // get CRL signing certs 423 LinkedHashSet coll = new LinkedHashSet(); 424 try 425 { 426 RevocationUtilities.findCertificates(coll, selector, paramsPKIX.getCertificateStores()); 427 RevocationUtilities.findCertificates(coll, selector, paramsPKIX.getCertStores()); 428 } 429 catch (AnnotatedException e) 430 { 431 throw new AnnotatedException("Issuer certificate for CRL cannot be searched.", e); 432 } 433 434 coll.add(defaultCRLSignCert); 435 436 List validCerts = new ArrayList(); 437 List validKeys = new ArrayList(); 438 439 Iterator cert_it = coll.iterator(); 440 while (cert_it.hasNext()) 441 { 442 X509Certificate signingCert = (X509Certificate)cert_it.next(); 443 444 /* 445 * CA of the certificate, for which this CRL is checked, has also 446 * signed CRL, so skip the path validation, because is already done 447 */ 448 if (signingCert.equals(defaultCRLSignCert)) 449 { 450 validCerts.add(signingCert); 451 validKeys.add(defaultCRLSignKey); 452 continue; 453 } 454 try 455 { 456 CertPathBuilder builder = helper.createCertPathBuilder("PKIX"); 457 X509CertSelector tmpCertSelector = new X509CertSelector(); 458 tmpCertSelector.setCertificate(signingCert); 459 460 PKIXExtendedParameters.Builder paramsBuilder = new PKIXExtendedParameters.Builder(paramsPKIX) 461 .setTargetConstraints(new PKIXCertStoreSelector.Builder(tmpCertSelector).build()); 462 463 /* 464 * if signingCert is placed not higher on the cert path a 465 * dependency loop results. CRL for cert is checked, but 466 * signingCert is needed for checking the CRL which is dependent 467 * on checking cert because it is higher in the cert path and so 468 * signing signingCert transitively. so, revocation is disabled, 469 * forgery attacks of the CRL are detected in this outer loop 470 * for all other it must be enabled to prevent forgery attacks 471 */ 472 if (certPathCerts.contains(signingCert)) 473 { 474 paramsBuilder.setRevocationEnabled(false); 475 } 476 else 477 { 478 paramsBuilder.setRevocationEnabled(true); 479 } 480 481 PKIXExtendedBuilderParameters extParams = new PKIXExtendedBuilderParameters.Builder(paramsBuilder.build()).build(); 482 483 List certs = builder.build(extParams).getCertPath().getCertificates(); 484 validCerts.add(signingCert); 485 validKeys.add(RevocationUtilities.getNextWorkingKey(certs, 0, helper)); 486 } 487 catch (CertPathBuilderException e) 488 { 489 throw new AnnotatedException("CertPath for CRL signer failed to validate.", e); 490 } 491 catch (CertPathValidatorException e) 492 { 493 throw new AnnotatedException("Public key of issuer certificate of CRL could not be retrieved.", e); 494 } 495 catch (Exception e) 496 { 497 throw new AnnotatedException(e.getMessage()); 498 } 499 } 500 501 Set checkKeys = new HashSet(); 502 503 AnnotatedException lastException = null; 504 for (int i = 0; i < validCerts.size(); i++) 505 { 506 X509Certificate signCert = (X509Certificate)validCerts.get(i); 507 boolean[] keyUsage = signCert.getKeyUsage(); 508 509 if (keyUsage != null && (keyUsage.length <= CRL_SIGN || !keyUsage[CRL_SIGN])) 510 { 511 lastException = new AnnotatedException( 512 "Issuer certificate key usage extension does not permit CRL signing."); 513 } 514 else 515 { 516 checkKeys.add(validKeys.get(i)); 517 } 518 } 519 520 if (checkKeys.isEmpty() && lastException == null) 521 { 522 throw new AnnotatedException("Cannot find a valid issuer certificate."); 523 } 524 if (checkKeys.isEmpty() && lastException != null) 525 { 526 throw lastException; 527 } 528 529 return checkKeys; 530 } 531 processCRLG( X509CRL crl, Set keys)532 protected static PublicKey processCRLG( 533 X509CRL crl, 534 Set keys) 535 throws AnnotatedException 536 { 537 Exception lastException = null; 538 for (Iterator it = keys.iterator(); it.hasNext();) 539 { 540 PublicKey key = (PublicKey)it.next(); 541 try 542 { 543 crl.verify(key); 544 return key; 545 } 546 catch (Exception e) 547 { 548 lastException = e; 549 } 550 } 551 throw new AnnotatedException("Cannot verify CRL.", lastException); 552 } 553 processCRLH( Set deltacrls, PublicKey key)554 protected static X509CRL processCRLH( 555 Set deltacrls, 556 PublicKey key) 557 throws AnnotatedException 558 { 559 Exception lastException = null; 560 561 for (Iterator it = deltacrls.iterator(); it.hasNext();) 562 { 563 X509CRL crl = (X509CRL)it.next(); 564 try 565 { 566 crl.verify(key); 567 return crl; 568 } 569 catch (Exception e) 570 { 571 lastException = e; 572 } 573 } 574 575 if (lastException != null) 576 { 577 throw new AnnotatedException("Cannot verify delta CRL.", lastException); 578 } 579 return null; 580 } 581 processCRLA1i( PKIXExtendedParameters paramsPKIX, Date currentDate, X509Certificate cert, X509CRL crl)582 protected static Set processCRLA1i( 583 PKIXExtendedParameters paramsPKIX, 584 Date currentDate, 585 X509Certificate cert, 586 X509CRL crl) 587 throws AnnotatedException 588 { 589 Set set = new HashSet(); 590 if (paramsPKIX.isUseDeltasEnabled()) 591 { 592 CRLDistPoint freshestCRL = null; 593 try 594 { 595 freshestCRL = CRLDistPoint 596 .getInstance(RevocationUtilities.getExtensionValue(cert, Extension.freshestCRL)); 597 } 598 catch (AnnotatedException e) 599 { 600 throw new AnnotatedException("Freshest CRL extension could not be decoded from certificate.", e); 601 } 602 if (freshestCRL == null) 603 { 604 try 605 { 606 freshestCRL = CRLDistPoint.getInstance(RevocationUtilities.getExtensionValue(crl, 607 Extension.freshestCRL)); 608 } 609 catch (AnnotatedException e) 610 { 611 throw new AnnotatedException("Freshest CRL extension could not be decoded from CRL.", e); 612 } 613 } 614 if (freshestCRL != null) 615 { 616 List crlStores = new ArrayList(); 617 618 crlStores.addAll(paramsPKIX.getCRLStores()); 619 620 try 621 { 622 crlStores.addAll(RevocationUtilities.getAdditionalStoresFromCRLDistributionPoint(freshestCRL, paramsPKIX.getNamedCRLStoreMap())); 623 } 624 catch (AnnotatedException e) 625 { 626 throw new AnnotatedException( 627 "No new delta CRL locations could be added from Freshest CRL extension.", e); 628 } 629 630 // get delta CRL(s) 631 try 632 { 633 set.addAll(RevocationUtilities.getDeltaCRLs(currentDate, crl, paramsPKIX.getCertStores(), crlStores)); 634 } 635 catch (AnnotatedException e) 636 { 637 throw new AnnotatedException("Exception obtaining delta CRLs.", e); 638 } 639 } 640 } 641 return set; 642 } 643 processCRLA1ii( PKIXExtendedParameters paramsPKIX, Date currentDate, Date validityDate, X509Certificate cert, X509CRL crl)644 protected static Set[] processCRLA1ii( 645 PKIXExtendedParameters paramsPKIX, 646 Date currentDate, 647 Date validityDate, 648 X509Certificate cert, 649 X509CRL crl) 650 throws AnnotatedException 651 { 652 X509CRLSelector crlselect = new X509CRLSelector(); 653 crlselect.setCertificateChecking(cert); 654 655 try 656 { 657 crlselect.addIssuerName(crl.getIssuerX500Principal().getEncoded()); 658 } 659 catch (IOException e) 660 { 661 throw new AnnotatedException("Cannot extract issuer from CRL." + e, e); 662 } 663 664 PKIXCRLStoreSelector extSelect = new PKIXCRLStoreSelector.Builder(crlselect).setCompleteCRLEnabled(true).build(); 665 666 Set completeSet = PKIXCRLUtil.findCRLs(extSelect, validityDate, paramsPKIX.getCertStores(), 667 paramsPKIX.getCRLStores()); 668 Set deltaSet = new HashSet(); 669 670 if (paramsPKIX.isUseDeltasEnabled()) 671 { 672 // get delta CRL(s) 673 try 674 { 675 deltaSet.addAll(RevocationUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores())); 676 } 677 catch (AnnotatedException e) 678 { 679 throw new AnnotatedException("Exception obtaining delta CRLs.", e); 680 } 681 } 682 return new Set[]{ completeSet, deltaSet }; 683 } 684 685 /** 686 * If use-deltas is set, verify the issuer and scope of the delta CRL. 687 * 688 * @param deltaCRL The delta CRL. 689 * @param completeCRL The complete CRL. 690 * @param pkixParams The PKIX paramaters. 691 * @throws AnnotatedException if an exception occurs. 692 */ processCRLC( X509CRL deltaCRL, X509CRL completeCRL, PKIXExtendedParameters pkixParams)693 protected static void processCRLC( 694 X509CRL deltaCRL, 695 X509CRL completeCRL, 696 PKIXExtendedParameters pkixParams) 697 throws AnnotatedException 698 { 699 if (deltaCRL == null) 700 { 701 return; 702 } 703 IssuingDistributionPoint completeidp = null; 704 try 705 { 706 completeidp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue( 707 completeCRL, Extension.issuingDistributionPoint)); 708 } 709 catch (Exception e) 710 { 711 throw new AnnotatedException("issuing distribution point extension could not be decoded.", e); 712 } 713 714 if (pkixParams.isUseDeltasEnabled()) 715 { 716 // (c) (1) 717 if (!deltaCRL.getIssuerX500Principal().equals(completeCRL.getIssuerX500Principal())) 718 { 719 throw new AnnotatedException("complete CRL issuer does not match delta CRL issuer"); 720 } 721 722 // (c) (2) 723 IssuingDistributionPoint deltaidp = null; 724 try 725 { 726 deltaidp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue( 727 deltaCRL, Extension.issuingDistributionPoint)); 728 } 729 catch (Exception e) 730 { 731 throw new AnnotatedException( 732 "Issuing distribution point extension from delta CRL could not be decoded.", e); 733 } 734 735 boolean match = false; 736 if (completeidp == null) 737 { 738 if (deltaidp == null) 739 { 740 match = true; 741 } 742 } 743 else 744 { 745 if (completeidp.equals(deltaidp)) 746 { 747 match = true; 748 } 749 } 750 if (!match) 751 { 752 throw new AnnotatedException( 753 "Issuing distribution point extension from delta CRL and complete CRL does not match."); 754 } 755 756 // (c) (3) 757 ASN1Primitive completeKeyIdentifier = null; 758 try 759 { 760 completeKeyIdentifier = RevocationUtilities.getExtensionValue( 761 completeCRL, Extension.authorityKeyIdentifier); 762 } 763 catch (AnnotatedException e) 764 { 765 throw new AnnotatedException( 766 "Authority key identifier extension could not be extracted from complete CRL.", e); 767 } 768 769 ASN1Primitive deltaKeyIdentifier = null; 770 try 771 { 772 deltaKeyIdentifier = RevocationUtilities.getExtensionValue( 773 deltaCRL, Extension.authorityKeyIdentifier); 774 } 775 catch (AnnotatedException e) 776 { 777 throw new AnnotatedException( 778 "Authority key identifier extension could not be extracted from delta CRL.", e); 779 } 780 781 if (completeKeyIdentifier == null) 782 { 783 throw new AnnotatedException("CRL authority key identifier is null."); 784 } 785 786 if (deltaKeyIdentifier == null) 787 { 788 throw new AnnotatedException("Delta CRL authority key identifier is null."); 789 } 790 791 if (!completeKeyIdentifier.equals(deltaKeyIdentifier)) 792 { 793 throw new AnnotatedException( 794 "Delta CRL authority key identifier does not match complete CRL authority key identifier."); 795 } 796 } 797 } 798 processCRLI( Date validDate, X509CRL deltacrl, Object cert, CertStatus certStatus, PKIXExtendedParameters pkixParams)799 protected static void processCRLI( 800 Date validDate, 801 X509CRL deltacrl, 802 Object cert, 803 CertStatus certStatus, 804 PKIXExtendedParameters pkixParams) 805 throws AnnotatedException 806 { 807 if (pkixParams.isUseDeltasEnabled() && deltacrl != null) 808 { 809 RevocationUtilities.getCertStatus(validDate, deltacrl, cert, certStatus); 810 } 811 } 812 processCRLJ( Date validDate, X509CRL completecrl, Object cert, CertStatus certStatus)813 protected static void processCRLJ( 814 Date validDate, 815 X509CRL completecrl, 816 Object cert, 817 CertStatus certStatus) 818 throws AnnotatedException 819 { 820 if (certStatus.getCertStatus() == CertStatus.UNREVOKED) 821 { 822 RevocationUtilities.getCertStatus(validDate, completecrl, cert, certStatus); 823 } 824 } 825 826 /** 827 * Checks a distribution point for revocation information for the 828 * certificate <code>cert</code>. 829 * 830 * @param dp The distribution point to consider. 831 * @param paramsPKIX PKIX parameters. 832 * @param cert Certificate to check if it is revoked. 833 * @param validDate The date when the certificate revocation status should be 834 * checked. 835 * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>. 836 * @param defaultCRLSignKey The public key of the issuer certificate 837 * <code>defaultCRLSignCert</code>. 838 * @param certStatus The current certificate revocation status. 839 * @param reasonMask The reasons mask which is already checked. 840 * @param certPathCerts The certificates of the certification path. 841 * @throws AnnotatedException if the certificate is revoked or the status cannot be checked 842 * or some error occurs. 843 */ checkCRL( DistributionPoint dp, PKIXExtendedParameters paramsPKIX, Date currentDate, Date validityDate, X509Certificate cert, X509Certificate defaultCRLSignCert, PublicKey defaultCRLSignKey, CertStatus certStatus, ReasonsMask reasonMask, List certPathCerts, JcaJceHelper helper)844 static void checkCRL( 845 DistributionPoint dp, 846 PKIXExtendedParameters paramsPKIX, 847 Date currentDate, 848 Date validityDate, 849 X509Certificate cert, 850 X509Certificate defaultCRLSignCert, 851 PublicKey defaultCRLSignKey, 852 CertStatus certStatus, 853 ReasonsMask reasonMask, 854 List certPathCerts, 855 JcaJceHelper helper) 856 throws AnnotatedException, CRLNotFoundException 857 { 858 if (validityDate.getTime() > currentDate.getTime()) 859 { 860 throw new AnnotatedException("Validation time is in future."); 861 } 862 863 // (a) 864 /* 865 * We always get timely valid CRLs, so there is no step (a) (1). 866 * "locally cached" CRLs are assumed to be in getStore(), additional 867 * CRLs must be enabled in the ExtendedPKIXParameters and are in 868 * getAdditionalStore() 869 */ 870 871 Set crls = RevocationUtilities.getCompleteCRLs(dp, cert, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores()); 872 boolean validCrlFound = false; 873 AnnotatedException lastException = null; 874 Iterator crl_iter = crls.iterator(); 875 876 while (crl_iter.hasNext() && certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonMask.isAllReasons()) 877 { 878 try 879 { 880 X509CRL crl = (X509CRL)crl_iter.next(); 881 882 // (d) 883 ReasonsMask interimReasonsMask = RFC3280CertPathUtilities.processCRLD(crl, dp); 884 885 // (e) 886 /* 887 * The reasons mask is updated at the end, so only valid CRLs 888 * can update it. If this CRL does not contain new reasons it 889 * must be ignored. 890 */ 891 if (!interimReasonsMask.hasNewReasons(reasonMask)) 892 { 893 continue; 894 } 895 896 // (f) 897 Set keys = RFC3280CertPathUtilities.processCRLF(crl, cert, defaultCRLSignCert, defaultCRLSignKey, 898 paramsPKIX, certPathCerts, helper); 899 // (g) 900 PublicKey key = RFC3280CertPathUtilities.processCRLG(crl, keys); 901 902 X509CRL deltaCRL = null; 903 904 if (paramsPKIX.isUseDeltasEnabled()) 905 { 906 // get delta CRLs 907 Set deltaCRLs = RevocationUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores()); 908 // we only want one valid delta CRL 909 // (h) 910 deltaCRL = RFC3280CertPathUtilities.processCRLH(deltaCRLs, key); 911 } 912 913 /* 914 * CRL must be be valid at the current time, not the validation 915 * time. If a certificate is revoked with reason keyCompromise, 916 * cACompromise, it can be used for forgery, also for the past. 917 * This reason may not be contained in older CRLs. 918 */ 919 920 /* 921 * in the chain model signatures stay valid also after the 922 * certificate has been expired, so they do not have to be in 923 * the CRL validity time 924 */ 925 926 if (paramsPKIX.getValidityModel() != PKIXExtendedParameters.CHAIN_VALIDITY_MODEL) 927 { 928 /* 929 * if a certificate has expired, but was revoked, it is not 930 * more in the CRL, so it would be regarded as valid if the 931 * first check is not done 932 */ 933 if (cert.getNotAfter().getTime() < crl.getThisUpdate().getTime()) 934 { 935 throw new AnnotatedException("No valid CRL for current time found."); 936 } 937 } 938 939 RFC3280CertPathUtilities.processCRLB1(dp, cert, crl); 940 941 // (b) (2) 942 RFC3280CertPathUtilities.processCRLB2(dp, cert, crl); 943 944 // (c) 945 RFC3280CertPathUtilities.processCRLC(deltaCRL, crl, paramsPKIX); 946 947 // (i) 948 RFC3280CertPathUtilities.processCRLI(validityDate, deltaCRL, cert, certStatus, paramsPKIX); 949 950 // (j) 951 RFC3280CertPathUtilities.processCRLJ(validityDate, crl, cert, certStatus); 952 953 // (k) 954 if (certStatus.getCertStatus() == CRLReason.removeFromCRL) 955 { 956 certStatus.setCertStatus(CertStatus.UNREVOKED); 957 } 958 959 // update reasons mask 960 reasonMask.addReasons(interimReasonsMask); 961 962 Set criticalExtensions = crl.getCriticalExtensionOIDs(); 963 if (criticalExtensions != null) 964 { 965 criticalExtensions = new HashSet(criticalExtensions); 966 criticalExtensions.remove(Extension.issuingDistributionPoint.getId()); 967 criticalExtensions.remove(Extension.deltaCRLIndicator.getId()); 968 969 if (!criticalExtensions.isEmpty()) 970 { 971 throw new AnnotatedException("CRL contains unsupported critical extensions."); 972 } 973 } 974 975 if (deltaCRL != null) 976 { 977 criticalExtensions = deltaCRL.getCriticalExtensionOIDs(); 978 if (criticalExtensions != null) 979 { 980 criticalExtensions = new HashSet(criticalExtensions); 981 criticalExtensions.remove(Extension.issuingDistributionPoint.getId()); 982 criticalExtensions.remove(Extension.deltaCRLIndicator.getId()); 983 if (!criticalExtensions.isEmpty()) 984 { 985 throw new AnnotatedException("Delta CRL contains unsupported critical extension."); 986 } 987 } 988 } 989 990 validCrlFound = true; 991 } 992 catch (AnnotatedException e) 993 { 994 lastException = e; 995 } 996 } 997 if (!validCrlFound) 998 { 999 throw lastException; 1000 } 1001 } 1002 } 1003