0001: package org.bouncycastle.jce.provider;
0002:
0003: import org.bouncycastle.asn1.ASN1InputStream;
0004: import org.bouncycastle.asn1.DERObject;
0005: import org.bouncycastle.asn1.x509.BasicConstraints;
0006: import org.bouncycastle.asn1.x509.CRLDistPoint;
0007: import org.bouncycastle.asn1.x509.CRLReason;
0008: import org.bouncycastle.asn1.x509.DistributionPoint;
0009: import org.bouncycastle.asn1.x509.DistributionPointName;
0010: import org.bouncycastle.asn1.x509.GeneralName;
0011: import org.bouncycastle.asn1.x509.GeneralNames;
0012: import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
0013: import org.bouncycastle.asn1.x509.TargetInformation;
0014: import org.bouncycastle.asn1.x509.X509Extensions;
0015: import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
0016: import org.bouncycastle.util.Selector;
0017: import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
0018: import org.bouncycastle.x509.ExtendedPKIXParameters;
0019: import org.bouncycastle.x509.PKIXAttrCertChecker;
0020: import org.bouncycastle.x509.X509AttributeCertificate;
0021: import org.bouncycastle.x509.X509CRLStoreSelector;
0022: import org.bouncycastle.x509.X509CertStoreSelector;
0023:
0024: import javax.security.auth.x500.X500Principal;
0025: import java.io.IOException;
0026: import java.math.BigInteger;
0027: import java.security.InvalidAlgorithmParameterException;
0028: import java.security.NoSuchAlgorithmException;
0029: import java.security.NoSuchProviderException;
0030: import java.security.Principal;
0031: import java.security.PublicKey;
0032: import java.security.cert.CertPath;
0033: import java.security.cert.CertPathBuilder;
0034: import java.security.cert.CertPathBuilderException;
0035: import java.security.cert.CertPathBuilderResult;
0036: import java.security.cert.CertPathValidator;
0037: import java.security.cert.CertPathValidatorException;
0038: import java.security.cert.CertPathValidatorResult;
0039: import java.security.cert.CertificateExpiredException;
0040: import java.security.cert.CertificateNotYetValidException;
0041: import java.security.cert.TrustAnchor;
0042: import java.security.cert.X509CRL;
0043: import java.security.cert.X509Certificate;
0044: import java.util.ArrayList;
0045: import java.util.Collection;
0046: import java.util.Date;
0047: import java.util.HashSet;
0048: import java.util.Iterator;
0049: import java.util.List;
0050: import java.util.Set;
0051:
0052: class RFC3281CertPathUtilities extends CertPathValidatorUtilities {
0053: private static final String TARGET_INFORMATION = X509Extensions.TargetInformation
0054: .getId();
0055:
0056: private static final String NO_REV_AVAIL = X509Extensions.NoRevAvail
0057: .getId();
0058:
0059: private static final String AUTHORITY_INFO_ACCESS = X509Extensions.AuthorityInfoAccess
0060: .getId();
0061:
0062: protected static void processAttrCert7(
0063: X509AttributeCertificate attrCert, CertPath certPath,
0064: CertPath holderCertPath, ExtendedPKIXParameters pkixParams)
0065: throws CertPathValidatorException {
0066: // TODO:
0067: // AA Controls
0068: // Attribute encryption
0069: // Proxy
0070: Set set = attrCert.getCriticalExtensionOIDs();
0071: // 7.1
0072: // process extensions
0073:
0074: // target information checked in step 6 / X509AttributeCertStoreSelector
0075: if (set.contains(TARGET_INFORMATION)) {
0076: try {
0077: TargetInformation
0078: .getInstance(CertPathValidatorUtilities
0079: .getExtensionValue(attrCert,
0080: TARGET_INFORMATION));
0081: } catch (AnnotatedException e) {
0082: throw new ExtCertPathValidatorException(
0083: "Target information extension could not be read.",
0084: e);
0085: } catch (IllegalArgumentException e) {
0086: throw new ExtCertPathValidatorException(
0087: "Target information extension could not be read.",
0088: e);
0089: }
0090: }
0091: set.remove(TARGET_INFORMATION);
0092: for (Iterator it = pkixParams.getAttrCertCheckers().iterator(); it
0093: .hasNext();) {
0094: ((PKIXAttrCertChecker) it.next()).check(attrCert, certPath,
0095: holderCertPath, set);
0096: }
0097: if (!set.isEmpty()) {
0098: throw new CertPathValidatorException(
0099: "Attribute certificate contains unsupported critical extensions: "
0100: + set);
0101: }
0102: }
0103:
0104: /**
0105: * Checks if an attribute certificate is revoked.
0106: *
0107: * @param attrCert Attribute certificate to check if it is revoked.
0108: * @param paramsPKIX PKIX parameters.
0109: * @param issuerCert The issuer certificate of the attribute certificate
0110: * <code>attrCert</code>.
0111: * @param validDate The date when the certificate revocation status should
0112: * be checked.
0113: *
0114: * @throws CertPathValidatorException if the certificate is revoked or the
0115: * status cannot be checked or some error occurs.
0116: */
0117: protected static void checkCRLs(X509AttributeCertificate attrCert,
0118: ExtendedPKIXParameters paramsPKIX,
0119: X509Certificate issuerCert, Date validDate)
0120: throws CertPathValidatorException {
0121: if (paramsPKIX.isRevocationEnabled()) {
0122: // check if revocation is available
0123: if (attrCert.getExtensionValue(NO_REV_AVAIL) == null) {
0124: CRLDistPoint crldp = null;
0125: try {
0126: crldp = CRLDistPoint
0127: .getInstance(CertPathValidatorUtilities
0128: .getExtensionValue(attrCert,
0129: CRL_DISTRIBUTION_POINTS));
0130: } catch (AnnotatedException e) {
0131: throw new CertPathValidatorException(
0132: "CRL distribution point extension could not be read.",
0133: e);
0134: }
0135: try {
0136: CertPathValidatorUtilities
0137: .addAdditionalStoresFromCRLDistributionPoint(
0138: crldp, paramsPKIX);
0139: } catch (AnnotatedException e) {
0140: throw new CertPathValidatorException(
0141: "No additional CRL locations could be decoded from CRL distribution point extension.",
0142: e);
0143: }
0144: CertStatus certStatus = new CertStatus();
0145: ReasonsMask reasonsMask = new ReasonsMask();
0146:
0147: AnnotatedException lastException = null;
0148: boolean validCrlFound = false;
0149: // for each distribution point
0150: if (crldp != null) {
0151: DistributionPoint dps[] = null;
0152: try {
0153: dps = crldp.getDistributionPoints();
0154: } catch (Exception e) {
0155: throw new ExtCertPathValidatorException(
0156: "Distribution points could not be read.",
0157: e);
0158: }
0159: try {
0160: for (int i = 0; i < dps.length
0161: && certStatus.getCertStatus() == CertStatus.UNREVOKED
0162: && !reasonsMask.isAllReasons(); i++) {
0163: ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX
0164: .clone();
0165: checkCRL(dps[i], attrCert, paramsPKIXClone,
0166: validDate, issuerCert, certStatus,
0167: reasonsMask);
0168: validCrlFound = true;
0169: }
0170: } catch (AnnotatedException e) {
0171: lastException = new AnnotatedException(
0172: "No valid CRL for distribution point found.",
0173: e);
0174: }
0175: }
0176:
0177: /*
0178: * If the revocation status has not been determined, repeat the
0179: * process above with any available CRLs not specified in a
0180: * distribution point but issued by the certificate issuer.
0181: */
0182:
0183: if (certStatus.getCertStatus() == CertStatus.UNREVOKED
0184: && !reasonsMask.isAllReasons()) {
0185: try {
0186: /*
0187: * assume a DP with both the reasons and the cRLIssuer
0188: * fields omitted and a distribution point name of the
0189: * certificate issuer.
0190: */
0191: DERObject issuer = null;
0192: try {
0193:
0194: issuer = new ASN1InputStream(
0195: ((X500Principal) attrCert
0196: .getIssuer()
0197: .getPrincipals()[0])
0198: .getEncoded()).readObject();
0199: } catch (Exception e) {
0200: throw new AnnotatedException(
0201: "Issuer from certificate for CRL could not be reencoded.",
0202: e);
0203: }
0204: DistributionPoint dp = new DistributionPoint(
0205: new DistributionPointName(
0206: 0,
0207: new GeneralNames(
0208: new GeneralName(
0209: GeneralName.directoryName,
0210: issuer))),
0211: null, null);
0212: ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX
0213: .clone();
0214: checkCRL(dp, attrCert, paramsPKIXClone,
0215: validDate, issuerCert, certStatus,
0216: reasonsMask);
0217: validCrlFound = true;
0218: } catch (AnnotatedException e) {
0219: lastException = new AnnotatedException(
0220: "No valid CRL for distribution point found.",
0221: e);
0222: }
0223: }
0224:
0225: if (!validCrlFound) {
0226: throw new ExtCertPathValidatorException(
0227: "No valid CRL found.", lastException);
0228: }
0229: if (certStatus.getCertStatus() != CertStatus.UNREVOKED) {
0230: String message = "Attribute certificate revocation after "
0231: + certStatus.getRevocationDate();
0232: message += ", reason: "
0233: + crlReasons[certStatus.getCertStatus()];
0234: throw new CertPathValidatorException(message);
0235: }
0236: if (!reasonsMask.isAllReasons()
0237: && certStatus.getCertStatus() == CertStatus.UNREVOKED) {
0238: certStatus.setCertStatus(CertStatus.UNDETERMINED);
0239: }
0240: if (certStatus.getCertStatus() == CertStatus.UNDETERMINED) {
0241: throw new CertPathValidatorException(
0242: "Attribute certificate status could not be determined.");
0243: }
0244:
0245: } else {
0246: if (attrCert.getExtensionValue(CRL_DISTRIBUTION_POINTS) != null
0247: || attrCert
0248: .getExtensionValue(AUTHORITY_INFO_ACCESS) != null) {
0249: throw new CertPathValidatorException(
0250: "No rev avail extension is set, but also an AC revocation pointer.");
0251: }
0252: }
0253: }
0254: }
0255:
0256: protected static void additionalChecks(
0257: X509AttributeCertificate attrCert,
0258: ExtendedPKIXParameters pkixParams)
0259: throws CertPathValidatorException {
0260: // 1
0261: for (Iterator it = pkixParams.getProhibitedACAttributes()
0262: .iterator(); it.hasNext();) {
0263: String oid = (String) it.next();
0264: if (attrCert.getAttributes(oid) != null) {
0265: throw new CertPathValidatorException(
0266: "Attribute certificate contains prohibited attribute: "
0267: + oid + ".");
0268: }
0269: }
0270: for (Iterator it = pkixParams.getNecessaryACAttributes()
0271: .iterator(); it.hasNext();) {
0272: String oid = (String) it.next();
0273: if (attrCert.getAttributes(oid) == null) {
0274: throw new CertPathValidatorException(
0275: "Attribute certificate does not contain necessary attribute: "
0276: + oid + ".");
0277: }
0278: }
0279: }
0280:
0281: protected static void processAttrCert5(
0282: X509AttributeCertificate attrCert,
0283: ExtendedPKIXParameters pkixParams)
0284: throws CertPathValidatorException {
0285: try {
0286: attrCert.checkValidity(CertPathValidatorUtilities
0287: .getValidDate(pkixParams));
0288: } catch (CertificateExpiredException e) {
0289: throw new ExtCertPathValidatorException(
0290: "Attribute certificate is not valid.", e);
0291: } catch (CertificateNotYetValidException e) {
0292: throw new ExtCertPathValidatorException(
0293: "Attribute certificate is not valid.", e);
0294: }
0295: }
0296:
0297: protected static void processAttrCert4(
0298: X509Certificate acIssuerCert,
0299: ExtendedPKIXParameters pkixParams)
0300: throws CertPathValidatorException {
0301: Set set = pkixParams.getTrustedACIssuers();
0302: boolean trusted = false;
0303: for (Iterator it = set.iterator(); it.hasNext();) {
0304: TrustAnchor anchor = (TrustAnchor) it.next();
0305: if (acIssuerCert.getSubjectX500Principal().getName(
0306: "RFC2253").equals(anchor.getCAName())
0307: || acIssuerCert.equals(anchor.getTrustedCert())) {
0308: trusted = true;
0309: }
0310: }
0311: if (!trusted) {
0312: throw new CertPathValidatorException(
0313: "Attribute certificate issuer is not directly trusted.");
0314: }
0315: }
0316:
0317: protected static void processAttrCert3(
0318: X509Certificate acIssuerCert,
0319: ExtendedPKIXParameters pkixParams)
0320: throws CertPathValidatorException {
0321: if (acIssuerCert.getKeyUsage() != null
0322: && (!acIssuerCert.getKeyUsage()[0] && !acIssuerCert
0323: .getKeyUsage()[1])) {
0324: throw new CertPathValidatorException(
0325: "Attribute certificate issuer public key cannot be used to validate digital signatures.");
0326: }
0327: if (acIssuerCert.getBasicConstraints() != -1) {
0328: throw new CertPathValidatorException(
0329: "Attribute certificate issuer is also a public key certificate issuer.");
0330: }
0331: }
0332:
0333: protected static CertPathValidatorResult processAttrCert2(
0334: CertPath certPath, ExtendedPKIXParameters pkixParams)
0335: throws CertPathValidatorException {
0336: CertPathValidator validator = null;
0337: try {
0338: validator = CertPathValidator.getInstance("PKIX", "BC");
0339: } catch (NoSuchProviderException e) {
0340: throw new ExtCertPathValidatorException(
0341: "Support class could not be created.", e);
0342: } catch (NoSuchAlgorithmException e) {
0343: throw new ExtCertPathValidatorException(
0344: "Support class could not be created.", e);
0345: }
0346: try {
0347: return validator.validate(certPath, pkixParams);
0348: } catch (CertPathValidatorException e) {
0349: throw new ExtCertPathValidatorException(
0350: "Certification path for issuer certificate of attribute certificate could not be validated.",
0351: e);
0352: } catch (InvalidAlgorithmParameterException e) {
0353: // must be a programming error
0354: throw new RuntimeException(e.getMessage());
0355: }
0356: }
0357:
0358: /**
0359: * Searches for a holder public key certificate and verifies its
0360: * certification path.
0361: *
0362: * @param attrCert the attribute certificate.
0363: * @param pkixParams The PKIX parameters.
0364: * @return The certificate path of the holder certificate.
0365: * @throws AnnotatedException if
0366: * <ul>
0367: * <li>no public key certificate can be found although holder
0368: * information is given by an entity name or a base certificate
0369: * ID
0370: * <li>support classes cannot be created
0371: * <li>no certification path for the public key certificate can
0372: * be built
0373: * </ul>
0374: */
0375: protected static CertPath processAttrCert1(
0376: X509AttributeCertificate attrCert,
0377: ExtendedPKIXParameters pkixParams)
0378: throws CertPathValidatorException {
0379: CertPathBuilderResult result = null;
0380: // find holder PKCs
0381: Set holderPKCs = new HashSet();
0382: if (attrCert.getHolder().getIssuer() != null) {
0383: X509CertStoreSelector selector = new X509CertStoreSelector();
0384: selector.setSerialNumber(attrCert.getHolder()
0385: .getSerialNumber());
0386: Principal[] principals = attrCert.getHolder().getIssuer();
0387: for (int i = 0; i < principals.length; i++) {
0388: try {
0389: if (principals[i] instanceof X500Principal) {
0390: selector
0391: .setIssuer(((X500Principal) principals[i])
0392: .getEncoded());
0393: }
0394: holderPKCs.addAll(CertPathValidatorUtilities
0395: .findCertificates((Selector) selector,
0396: pkixParams.getStores()));
0397: } catch (AnnotatedException e) {
0398: throw new ExtCertPathValidatorException(
0399: "Public key certificate for attribute certificate cannot be searched.",
0400: e);
0401: } catch (IOException e) {
0402: throw new ExtCertPathValidatorException(
0403: "Unable to encode X500 principal.", e);
0404: }
0405: }
0406: if (holderPKCs.isEmpty()) {
0407: throw new CertPathValidatorException(
0408: "Public key certificate specified in base certificate ID for attribute certificate cannot be found.");
0409: }
0410: }
0411: if (attrCert.getHolder().getEntityNames() != null) {
0412: X509CertStoreSelector selector = new X509CertStoreSelector();
0413: Principal[] principals = attrCert.getHolder()
0414: .getEntityNames();
0415: for (int i = 0; i < principals.length; i++) {
0416: try {
0417: if (principals[i] instanceof X500Principal) {
0418: selector
0419: .setIssuer(((X500Principal) principals[i])
0420: .getEncoded());
0421: }
0422: holderPKCs.addAll(CertPathValidatorUtilities
0423: .findCertificates((Selector) selector,
0424: pkixParams.getStores()));
0425: } catch (AnnotatedException e) {
0426: throw new ExtCertPathValidatorException(
0427: "Public key certificate for attribute certificate cannot be searched.",
0428: e);
0429: } catch (IOException e) {
0430: throw new ExtCertPathValidatorException(
0431: "Unable to encode X500 principal.", e);
0432: }
0433: }
0434: if (holderPKCs.isEmpty()) {
0435: throw new CertPathValidatorException(
0436: "Public key certificate specified in entity name for attribute certificate cannot be found.");
0437: }
0438: }
0439: // verify cert paths for PKCs
0440: ExtendedPKIXBuilderParameters params = (ExtendedPKIXBuilderParameters) ExtendedPKIXBuilderParameters
0441: .getInstance(pkixParams);
0442: CertPathValidatorException lastException = null;
0443: for (Iterator it = holderPKCs.iterator(); it.hasNext();) {
0444: X509CertStoreSelector selector = new X509CertStoreSelector();
0445: selector.setCertificate((X509Certificate) it.next());
0446: params.setTargetConstraints(selector);
0447: CertPathBuilder builder = null;
0448: try {
0449: builder = CertPathBuilder.getInstance("PKIX", "BC");
0450: } catch (NoSuchProviderException e) {
0451: throw new ExtCertPathValidatorException(
0452: "Support class could not be created.", e);
0453: } catch (NoSuchAlgorithmException e) {
0454: throw new ExtCertPathValidatorException(
0455: "Support class could not be created.", e);
0456: }
0457: try {
0458: result = builder.build(ExtendedPKIXBuilderParameters
0459: .getInstance(params));
0460: } catch (CertPathBuilderException e) {
0461: lastException = new ExtCertPathValidatorException(
0462: "Certification path for public key certificate of attribute certificate could not be build.",
0463: e);
0464: } catch (InvalidAlgorithmParameterException e) {
0465: // must be a programming error
0466: throw new RuntimeException(e.getMessage());
0467: }
0468: }
0469: if (lastException != null) {
0470: throw lastException;
0471: }
0472: return result.getCertPath();
0473: }
0474:
0475: /**
0476: *
0477: * Checks a distribution point for revocation information for the
0478: * certificate <code>cert</code>.
0479: *
0480: * @param dp The distribution point to consider.
0481: * @param attrCert The attribute certificate which should be checked.
0482: * @param paramsPKIX PKIX parameters.
0483: * @param validDate The date when the certificate revocation status should
0484: * be checked.
0485: * @param issuerCert Certificate to check if it is revoked.
0486: * @param reasonMask The reasons mask which is already checked.
0487: * @throws AnnotatedException if the certificate is revoked or the status
0488: * cannot be checked or some error occurs.
0489: */
0490: private static void checkCRL(DistributionPoint dp,
0491: X509AttributeCertificate attrCert,
0492: ExtendedPKIXParameters paramsPKIX, Date validDate,
0493: X509Certificate issuerCert, CertStatus certStatus,
0494: ReasonsMask reasonMask) throws AnnotatedException {
0495:
0496: /*
0497: * 4.3.6 No Revocation Available
0498: *
0499: * The noRevAvail extension, defined in [X.509-2000], allows an AC
0500: * issuer to indicate that no revocation information will be made
0501: * available for this AC.
0502: */
0503: if (attrCert.getExtensionValue(X509Extensions.NoRevAvail
0504: .getId()) != null) {
0505: return;
0506: }
0507: Date currentDate = new Date(System.currentTimeMillis());
0508: if (validDate.getTime() > currentDate.getTime()) {
0509: throw new AnnotatedException(
0510: "Validation time is in future.");
0511: }
0512:
0513: // (a)
0514: /*
0515: * We always get timely valid CRLs, so there is no step (a) (1).
0516: * "locally cached" CRLs are assumed to be in getStore(), additional
0517: * CRLs must be enabled in the ExtendedPKIXParameters and are in
0518: * getAdditionalStore()
0519: */
0520:
0521: Set crls = CertPathValidatorUtilities.getCompleteCRLs(dp,
0522: attrCert, currentDate, paramsPKIX);
0523: boolean validCrlFound = false;
0524: AnnotatedException lastException = null;
0525: Iterator crl_iter = crls.iterator();
0526:
0527: while (crl_iter.hasNext()
0528: && certStatus.getCertStatus() == CertStatus.UNREVOKED
0529: && !reasonMask.isAllReasons()) {
0530: try {
0531: X509CRL crl = (X509CRL) crl_iter.next();
0532:
0533: // (d)
0534: ReasonsMask interimReasonsMask = processCRLD(crl, dp);
0535:
0536: // (e)
0537: /*
0538: * The reasons mask is updated at the end, so only valid CRLs
0539: * can update it. If this CRL does not contain new reasons it
0540: * must be ignored.
0541: */
0542: if (!interimReasonsMask.hasNewReasons(reasonMask)) {
0543: continue;
0544: }
0545:
0546: // (f)
0547: Set keys = processCRLF(crl, attrCert, null, null,
0548: paramsPKIX);
0549: // (g)
0550: PublicKey key = processCRLG(crl, keys);
0551:
0552: X509CRL deltaCRL = null;
0553:
0554: if (paramsPKIX.isUseDeltasEnabled()) {
0555: // get delta CRLs
0556: Set deltaCRLs = CertPathValidatorUtilities
0557: .getDeltaCRLs(currentDate, paramsPKIX, crl);
0558: // we only want one valid delta CRL
0559: // (h)
0560: deltaCRL = processCRLH(deltaCRLs, key);
0561: }
0562:
0563: /*
0564: * CRL must be be valid at the current time, not the validation
0565: * time. If a certificate is revoked with reason keyCompromise,
0566: * cACompromise, it can be used for forgery, also for the past.
0567: * This reason may not be contained in older CRLs.
0568: */
0569:
0570: /*
0571: * in the chain model signatures stay valid also after the
0572: * certificate has been expired, so they do not have to be in
0573: * the CRL vality time
0574: */
0575:
0576: if (paramsPKIX.getValidityModel() != ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL) {
0577: /*
0578: * if a certificate has expired, but was revoked, it is not
0579: * more in the CRL, so it would be regarded as valid if the
0580: * first check is not done
0581: */
0582: if (attrCert.getNotAfter().getTime() < crl
0583: .getThisUpdate().getTime()) {
0584: throw new AnnotatedException(
0585: "No valid CRL for current time found.");
0586: }
0587: }
0588:
0589: processCRLB1(dp, attrCert, crl);
0590:
0591: // (b) (2)
0592: processCRLB2(dp, attrCert, crl);
0593:
0594: // (c)
0595: processCRLC(deltaCRL, crl, paramsPKIX);
0596:
0597: // (i)
0598: processCRLI(validDate, deltaCRL, attrCert
0599: .getSerialNumber(), certStatus, paramsPKIX);
0600:
0601: // (j)
0602: processCRLJ(validDate, crl, attrCert.getSerialNumber(),
0603: certStatus);
0604:
0605: // (k)
0606: if (certStatus.getCertStatus() == CRLReason.removeFromCRL) {
0607: certStatus.setCertStatus(CertStatus.UNREVOKED);
0608: }
0609:
0610: // update reasons mask
0611: reasonMask.addReasons(interimReasonsMask);
0612: validCrlFound = true;
0613: } catch (AnnotatedException e) {
0614: lastException = e;
0615: }
0616: }
0617: if (!validCrlFound) {
0618: throw lastException;
0619: }
0620: }
0621:
0622: protected static void processCRLB2(DistributionPoint dp,
0623: Object cert, X509CRL crl) throws AnnotatedException {
0624: IssuingDistributionPoint idp = null;
0625: try {
0626: idp = IssuingDistributionPoint
0627: .getInstance(CertPathValidatorUtilities
0628: .getExtensionValue(crl,
0629: ISSUING_DISTRIBUTION_POINT));
0630: } catch (Exception e) {
0631: throw new AnnotatedException(
0632: "Issuing distribution point extension could not be decoded.",
0633: e);
0634: }
0635: // distribution point name is present
0636: if (idp != null && idp.getDistributionPoint() != null) {
0637: // make list of names
0638: DistributionPointName dpName = IssuingDistributionPoint
0639: .getInstance(idp).getDistributionPoint();
0640: List names = new ArrayList();
0641: if (dpName.getType() == DistributionPointName.FULL_NAME) {
0642: GeneralName[] genNames = GeneralNames.getInstance(
0643: dpName.getName()).getNames();
0644: for (int j = 0; j < genNames.length; j++) {
0645: names.add(genNames[j].getDEREncoded());
0646: }
0647: }
0648: boolean matches = false;
0649: // verify that one of the names in the IDP matches one
0650: // of the names in the DP.
0651: if (dp.getDistributionPoint() != null) {
0652: dpName = dp.getDistributionPoint();
0653: if (dpName.getType() == DistributionPointName.FULL_NAME) {
0654: GeneralName[] genNames = GeneralNames.getInstance(
0655: dpName.getName()).getNames();
0656: for (int j = 0; j < genNames.length; j++) {
0657: if (names.contains(genNames[j])) {
0658: matches = true;
0659: break;
0660: }
0661: }
0662: }
0663: if (!matches) {
0664: throw new AnnotatedException(
0665: "None of the names in the CRL issuing distribution point matches one "
0666: + "of the names in a distributionPoint field of the certificate CRL distribution point.");
0667: }
0668: }
0669: // verify that one of the names in
0670: // the IDP matches one of the names in the cRLIssuer field of
0671: // the DP
0672: else {
0673: if (dp.getCRLIssuer() == null) {
0674: throw new AnnotatedException(
0675: "Either the cRLIssuer or the distributionPoint field must "
0676: + "be contained in DistributionPoint.");
0677: }
0678: GeneralName[] genNames = dp.getCRLIssuer().getNames();
0679: for (int j = 0; j < genNames.length; j++) {
0680: if (names.contains(genNames[j])) {
0681: matches = true;
0682: break;
0683: }
0684: }
0685: if (!matches) {
0686: throw new AnnotatedException(
0687: "None of the names in the CRL issuing distribution point matches one "
0688: + "of the names in a cRLIssuer field of the certificate CRL distribution point.");
0689: }
0690: }
0691: BasicConstraints bc = null;
0692: try {
0693: bc = BasicConstraints
0694: .getInstance(CertPathValidatorUtilities
0695: .getExtensionValue(
0696: (java.security.cert.X509Extension) cert,
0697: BASIC_CONSTRAINTS));
0698: } catch (Exception e) {
0699: throw new AnnotatedException(
0700: "Basic constraints extension could not be decoded.",
0701: e);
0702: }
0703:
0704: if (cert instanceof X509Certificate) {
0705: // (b) (ii)
0706: if (idp.onlyContainsUserCerts()
0707: && (bc != null && bc.isCA())) {
0708: throw new AnnotatedException(
0709: "CA Cert CRL only contains user certificates.");
0710: }
0711:
0712: // (b) (iii)
0713: if (idp.onlyContainsCACerts()
0714: && (bc == null || !bc.isCA())) {
0715: throw new AnnotatedException(
0716: "End CRL only contains CA certificates.");
0717: }
0718: }
0719:
0720: // (b) (iv)
0721: if (idp.onlyContainsAttributeCerts()) {
0722: throw new AnnotatedException(
0723: "onlyContainsAttributeCerts boolean is asserted.");
0724: }
0725: }
0726: }
0727:
0728: protected static void processCRLB1(DistributionPoint dp,
0729: Object cert, X509CRL crl) throws AnnotatedException {
0730: DERObject idp = CertPathValidatorUtilities.getExtensionValue(
0731: crl, ISSUING_DISTRIBUTION_POINT);
0732: boolean isIndirect = false;
0733: if (idp != null) {
0734: if (IssuingDistributionPoint.getInstance(idp)
0735: .isIndirectCRL()) {
0736: isIndirect = true;
0737: }
0738: }
0739: byte[] issuerBytes = CertPathValidatorUtilities
0740: .getIssuerPrincipal(crl).getEncoded();
0741:
0742: boolean matchIssuer = false;
0743: if (dp.getCRLIssuer() != null) {
0744: GeneralName genNames[] = dp.getCRLIssuer().getNames();
0745: for (int j = 0; j < genNames.length; j++) {
0746: if (genNames[j].getTagNo() == GeneralName.directoryName) {
0747: try {
0748: if (genNames[j].getName().getDERObject()
0749: .getEncoded().equals(issuerBytes)) {
0750: matchIssuer = true;
0751: }
0752: } catch (IOException e) {
0753: throw new AnnotatedException(
0754: "CRL issuer information from distribution point cannot be decoded.",
0755: e);
0756: }
0757: }
0758: }
0759: if (matchIssuer && !isIndirect) {
0760: throw new AnnotatedException(
0761: "Distribution point contains cRLIssuer field but CRL is not indirect.");
0762: }
0763: if (!matchIssuer) {
0764: throw new AnnotatedException(
0765: "CRL issuer of CRL does not match CRL issuer of distribution point.");
0766: }
0767: } else {
0768: if (CertPathValidatorUtilities.getIssuerPrincipal(crl)
0769: .equals(
0770: CertPathValidatorUtilities
0771: .getEncodedIssuerPrincipal(cert))) {
0772: matchIssuer = true;
0773: }
0774: }
0775: if (!matchIssuer) {
0776: throw new AnnotatedException(
0777: "Cannot find matching CRL issuer for certificate.");
0778: }
0779: }
0780:
0781: protected static ReasonsMask processCRLD(X509CRL crl,
0782: DistributionPoint dp) throws AnnotatedException {
0783: IssuingDistributionPoint idp = null;
0784: try {
0785: idp = IssuingDistributionPoint
0786: .getInstance(CertPathValidatorUtilities
0787: .getExtensionValue(crl,
0788: ISSUING_DISTRIBUTION_POINT));
0789: } catch (Exception e) {
0790: throw new AnnotatedException(
0791: "Issuing distribution point extension could not be decoded.",
0792: e);
0793: }
0794: // (d) (1)
0795: if (idp != null && idp.getOnlySomeReasons() != null
0796: && dp.getReasons() != null) {
0797: return new ReasonsMask(dp.getReasons().intValue())
0798: .intersect(new ReasonsMask(idp.getOnlySomeReasons()
0799: .intValue()));
0800: }
0801: // (d) (4)
0802: if ((idp == null || idp.getOnlySomeReasons() == null)
0803: && dp.getReasons() == null) {
0804: return ReasonsMask.allReasons;
0805: }
0806: // (d) (2) and (d)(3)
0807: return (dp.getReasons() == null ? ReasonsMask.allReasons
0808: : new ReasonsMask(dp.getReasons().intValue()))
0809: .intersect(idp == null ? ReasonsMask.allReasons
0810: : new ReasonsMask(idp.getOnlySomeReasons()
0811: .intValue()));
0812:
0813: }
0814:
0815: /**
0816: * Obtain and validate the certification path for the complete CRL issuer.
0817: * If a key usage extension is present in the CRL issuer's certificate,
0818: * verify that the cRLSign bit is set.
0819: *
0820: * @param crl CRL which contains revocation information for the certificate
0821: * <code>cert</code>.
0822: * @param cert The attribute certificate or certificate to check if it is
0823: * revoked.
0824: * @param defaultCRLSignCert The issuer certificate of the certificate
0825: * <code>cert</code>. May be <code>null</code>.
0826: * @param defaultCRLSignKey The public key of the issuer certificate
0827: * <code>defaultCRLSignCert</code>. May be <code>null</code>.
0828: * @param paramsPKIX paramsPKIX PKIX parameters.
0829: * @return A <code>Set</code> with all keys of possible CRL issuer
0830: * certificates.
0831: * @throws AnnotatedException if the CRL is no valid or the status cannot be
0832: * checked or some error occurs.
0833: */
0834: protected static Set processCRLF(X509CRL crl, Object cert,
0835: X509Certificate defaultCRLSignCert,
0836: PublicKey defaultCRLSignKey,
0837: ExtendedPKIXParameters paramsPKIX)
0838: throws AnnotatedException {
0839: // (f)
0840:
0841: // get issuer from CRL
0842: X509CertStoreSelector selector = new X509CertStoreSelector();
0843: try {
0844: selector.setSubject(CertPathValidatorUtilities
0845: .getIssuerPrincipal(crl).getEncoded());
0846: } catch (IOException e) {
0847: throw new AnnotatedException(
0848: "Subject criteria for certificate selector to find issuer certificate for CRL could not be set.",
0849: e);
0850: }
0851:
0852: // get CRL signing certs
0853: Collection coll = null;
0854: try {
0855: coll = CertPathValidatorUtilities.findCertificates(
0856: (Selector) selector, paramsPKIX.getStores());
0857: coll = CertPathValidatorUtilities
0858: .findCertificates((Selector) selector, paramsPKIX
0859: .getAddionalStores());
0860: } catch (AnnotatedException e) {
0861: throw new AnnotatedException(
0862: "Issuer certificate for CRL cannot be searched.", e);
0863: }
0864:
0865: if (defaultCRLSignCert != null) {
0866: coll.add(defaultCRLSignCert);
0867: }
0868: Iterator cert_it = coll.iterator();
0869:
0870: Set validCerts = new HashSet();
0871:
0872: while (cert_it.hasNext()) {
0873: X509Certificate signingCert = (X509Certificate) cert_it
0874: .next();
0875:
0876: /*
0877: * CA of certificate, for which this CRL is checked, also signed
0878: * CRL, so skip path validation, because is already checked in way
0879: * from trusted CA to end certificate.
0880: */
0881: // double check with key, because name could be thereotical the same
0882: if (CertPathValidatorUtilities.getEncodedIssuerPrincipal(
0883: cert).equals(signingCert.getSubjectX500Principal())
0884: && signingCert.getPublicKey().equals(
0885: defaultCRLSignKey)) {
0886: validCerts.add(signingCert);
0887: continue;
0888: }
0889: try {
0890: CertPathBuilder builder = CertPathBuilder.getInstance(
0891: "PKIX", "BC");
0892: selector = new X509CertStoreSelector();
0893: selector.setCertificate(signingCert);
0894: ExtendedPKIXBuilderParameters params = (ExtendedPKIXBuilderParameters) ExtendedPKIXBuilderParameters
0895: .getInstance(paramsPKIX);
0896: params.setTargetConstraints(selector);
0897: /*
0898: * CRL for CA cannot be signed from CA lower in PKI path
0899: * (compromised key of upper CA could be used to forge this CA.)
0900: * (and we run in an endless loop aside from this.)
0901: */
0902: // cert is not allowed to appear in PKI path
0903: Set excluded = new HashSet();
0904: excluded.add(cert);
0905: params.setExcludedCerts(excluded);
0906: builder.build(params);
0907: validCerts.add(signingCert);
0908: } catch (Exception e) {
0909: }
0910: }
0911:
0912: Set checkKeys = new HashSet();
0913:
0914: // trivially included if cert cannot be checked for key usage extension
0915: if (defaultCRLSignCert == null && defaultCRLSignKey != null) {
0916: checkKeys.add(defaultCRLSignKey);
0917: }
0918:
0919: AnnotatedException lastException = null;
0920: for (Iterator it = validCerts.iterator(); it.hasNext();) {
0921: X509Certificate signCert = (X509Certificate) it.next();
0922: boolean[] keyusage = signCert.getKeyUsage();
0923:
0924: if (keyusage != null
0925: && (keyusage.length < 7 || !keyusage[CRL_SIGN])) {
0926: lastException = new AnnotatedException(
0927: "Issuer certificate key usage extension does not permit CRL signing.");
0928: } else {
0929: checkKeys.add(signCert.getPublicKey());
0930: }
0931: }
0932:
0933: if (checkKeys.isEmpty() && lastException == null) {
0934: throw new AnnotatedException(
0935: "Cannot find a valid issuer certificate.");
0936: }
0937: if (checkKeys.isEmpty() && lastException != null) {
0938: throw lastException;
0939: }
0940:
0941: return checkKeys;
0942: }
0943:
0944: protected static PublicKey processCRLG(X509CRL crl, Set keys)
0945: throws AnnotatedException {
0946: Exception lastException = null;
0947: try {
0948: for (Iterator it = keys.iterator(); it.hasNext();) {
0949: PublicKey key = (PublicKey) it.next();
0950: crl.verify(key);
0951: return key;
0952: }
0953: } catch (Exception e) {
0954: lastException = e;
0955: }
0956: throw new AnnotatedException("Cannot verify CRL.",
0957: lastException);
0958: }
0959:
0960: protected static X509CRL processCRLH(Set deltacrls, PublicKey key)
0961: throws AnnotatedException {
0962: Exception lastException = null;
0963: try {
0964: for (Iterator it = deltacrls.iterator(); it.hasNext();) {
0965: X509CRL crl = (X509CRL) it.next();
0966: crl.verify(key);
0967: return crl;
0968: }
0969: } catch (Exception e) {
0970: lastException = e;
0971: }
0972: throw new AnnotatedException("Cannot verify delta CRL.",
0973: lastException);
0974: }
0975:
0976: protected static Set processCRLA1i(Date currentDate,
0977: ExtendedPKIXParameters paramsPKIX, X509Certificate cert,
0978: X509CRL crl) throws AnnotatedException {
0979: Set set = new HashSet();
0980: if (paramsPKIX.isUseDeltasEnabled()) {
0981: CRLDistPoint freshestCRL = null;
0982: try {
0983: freshestCRL = CRLDistPoint
0984: .getInstance(CertPathValidatorUtilities
0985: .getExtensionValue(cert, FRESHEST_CRL));
0986: } catch (AnnotatedException e) {
0987: throw new AnnotatedException(
0988: "Freshest CRL extension could not be decoded from certificate.",
0989: e);
0990: }
0991: if (freshestCRL == null) {
0992: try {
0993: freshestCRL = CRLDistPoint
0994: .getInstance(CertPathValidatorUtilities
0995: .getExtensionValue(crl,
0996: FRESHEST_CRL));
0997: } catch (AnnotatedException e) {
0998: throw new AnnotatedException(
0999: "Freshest CRL extension could not be decoded from CRL.",
1000: e);
1001: }
1002: }
1003: if (freshestCRL != null) {
1004: try {
1005: CertPathValidatorUtilities
1006: .addAdditionalStoresFromCRLDistributionPoint(
1007: freshestCRL, paramsPKIX);
1008: } catch (AnnotatedException e) {
1009: throw new AnnotatedException(
1010: "No new delta CRL locations could be added from Freshest CRL extension.",
1011: e);
1012: }
1013: // get delta CRL(s)
1014: try {
1015: set.addAll(CertPathValidatorUtilities.getDeltaCRLs(
1016: currentDate, paramsPKIX, crl));
1017: } catch (AnnotatedException e) {
1018: throw new AnnotatedException(
1019: "Exception obtaining delta CRLs.", e);
1020: }
1021: }
1022: }
1023: return set;
1024: }
1025:
1026: protected static Set[] processCRLA1ii(Date currentDate,
1027: ExtendedPKIXParameters paramsPKIX, X509Certificate cert,
1028: X509CRL crl) throws AnnotatedException {
1029: Set completeSet = new HashSet();
1030: Set deltaSet = new HashSet();
1031: X509CRLStoreSelector crlselect = new X509CRLStoreSelector();
1032: crlselect.setCertificateChecking(cert);
1033: crlselect.setCompleteCRLEnabled(true);
1034: crlselect.setDateAndTime(currentDate);
1035: try {
1036: crlselect.addIssuerName(crl.getIssuerX500Principal()
1037: .getEncoded());
1038: } catch (IOException e) {
1039: throw new AnnotatedException(
1040: "Cannot extract issuer from CRL." + e, e);
1041: }
1042: // get complete CRL(s)
1043: try {
1044: completeSet.addAll(CertPathValidatorUtilities.findCRLs(
1045: crlselect, paramsPKIX.getAddionalStores()));
1046: completeSet.addAll(CertPathValidatorUtilities.findCRLs(
1047: crlselect, paramsPKIX.getStores()));
1048: } catch (AnnotatedException e) {
1049: throw new AnnotatedException(
1050: "Exception obtaining complete CRLs.", e);
1051: }
1052: if (paramsPKIX.isUseDeltasEnabled()) {
1053: // get delta CRL(s)
1054: try {
1055: deltaSet.addAll(CertPathValidatorUtilities
1056: .getDeltaCRLs(currentDate, paramsPKIX, crl));
1057: } catch (AnnotatedException e) {
1058: throw new AnnotatedException(
1059: "Exception obtaining delta CRLs.", e);
1060: }
1061: }
1062: return new Set[] { completeSet, deltaSet };
1063: }
1064:
1065: /**
1066: * If use-deltas is set, verify the issuer and scope of the delta CRL.
1067: *
1068: * @param deltaCRL The delta CRL.
1069: * @param completeCRL The complete CRL.
1070: * @param pkixParams The PKIX paramaters.
1071: * @throws AnnotatedException if an exception occurs.
1072: */
1073: protected static void processCRLC(X509CRL deltaCRL,
1074: X509CRL completeCRL, ExtendedPKIXParameters pkixParams)
1075: throws AnnotatedException {
1076: IssuingDistributionPoint completeidp = null;
1077: try {
1078: completeidp = IssuingDistributionPoint
1079: .getInstance(CertPathValidatorUtilities
1080: .getExtensionValue(completeCRL,
1081: ISSUING_DISTRIBUTION_POINT));
1082: } catch (Exception e) {
1083: throw new AnnotatedException(
1084: "Issuing distribution point extension could not be decoded.",
1085: e);
1086: }
1087:
1088: if (pkixParams.isUseDeltasEnabled()) {
1089:
1090: // (c) (1)
1091: if (!deltaCRL.getIssuerX500Principal().equals(
1092: completeCRL.getIssuerX500Principal())) {
1093: throw new AnnotatedException(
1094: "Complete CRL issuer does not match delta CRL issuer.");
1095: }
1096:
1097: // (c) (2)
1098: if (completeidp != null) {
1099:
1100: IssuingDistributionPoint deltaidp = null;
1101: try {
1102: deltaidp = IssuingDistributionPoint
1103: .getInstance(CertPathValidatorUtilities
1104: .getExtensionValue(deltaCRL,
1105: ISSUING_DISTRIBUTION_POINT));
1106: } catch (Exception e) {
1107: throw new AnnotatedException(
1108: "Issuing distribution point extension from delta CRL could not be decoded.",
1109: e);
1110: }
1111: boolean match = false;
1112: if (completeidp == null) {
1113: if (deltaidp == null) {
1114: match = true;
1115: }
1116: } else {
1117: if (completeidp.equals(deltaidp)) {
1118: match = true;
1119: }
1120: }
1121: if (!match) {
1122: throw new AnnotatedException(
1123: "Issuing distribution point extension from delta CRL and complete CRL does not match.");
1124: }
1125: }
1126:
1127: // (c) (3)
1128: DERObject completeKeyIdentifier = null;
1129: try {
1130: completeKeyIdentifier = CertPathValidatorUtilities
1131: .getExtensionValue(deltaCRL,
1132: AUTHORITY_KEY_IDENTIFIER);
1133: } catch (AnnotatedException e) {
1134: throw new AnnotatedException(
1135: "Authority key identifier extension could not be extracted from complete CRL.",
1136: e);
1137: }
1138: DERObject deltaKeyIdentifier = null;
1139: try {
1140: deltaKeyIdentifier = CertPathValidatorUtilities
1141: .getExtensionValue(deltaCRL,
1142: AUTHORITY_KEY_IDENTIFIER);
1143: } catch (AnnotatedException e) {
1144: throw new AnnotatedException(
1145: "Authority key identifier extension could not be extracted from delta CRL.",
1146: e);
1147: }
1148: if (!completeKeyIdentifier.equals(deltaKeyIdentifier)) {
1149: throw new AnnotatedException(
1150: "Delta CRL authority key identifier does not match complete CRL authority key identifier.");
1151: }
1152: }
1153: }
1154:
1155: protected static void processCRLI(Date validDate, X509CRL deltacrl,
1156: BigInteger serialNumber, CertStatus certStatus,
1157: ExtendedPKIXParameters pkixParams)
1158: throws AnnotatedException {
1159: if (pkixParams.isUseDeltasEnabled()) {
1160: CertPathValidatorUtilities.getCertStatus(validDate,
1161: deltacrl, serialNumber, certStatus);
1162: }
1163: }
1164:
1165: protected static void processCRLJ(Date validDate,
1166: X509CRL completecrl, BigInteger serialNumber,
1167: CertStatus certStatus) throws AnnotatedException {
1168: CertPathValidatorUtilities.getCertStatus(validDate,
1169: completecrl, serialNumber, certStatus);
1170: }
1171:
1172: /**
1173: *
1174: * Checks a distribution point for revocation information for the
1175: * certificate <code>cert</code>.
1176: *
1177: * @param dp The distribution point to consider.
1178: * @param paramsPKIX PKIX parameters.
1179: * @param cert Certificate to check if it is revoked.
1180: * @param validDate The date when the certificate revocation status should
1181: * be checked.
1182: * @param defaultCRLSignCert The issuer certificate of the certificate
1183: * <code>cert</code>.
1184: * @param defaultCRLSignKey The public key of the issuer certificate
1185: * <code>defaultCRLSignCert</code>.
1186: * @param certStatus The current certificate revocation status.
1187: * @param reasonMask The reasons mask which is already checked.
1188: * @param certPathCerts The certificates of the certification path.
1189: * @throws AnnotatedException if the certificate is revoked or the status
1190: * cannot be checked or some error occurs.
1191: */
1192: private static void checkCRL(DistributionPoint dp,
1193: ExtendedPKIXParameters paramsPKIX, X509Certificate cert,
1194: Date validDate, X509Certificate defaultCRLSignCert,
1195: PublicKey defaultCRLSignKey, CertStatus certStatus,
1196: ReasonsMask reasonMask, List certPathCerts)
1197: throws AnnotatedException {
1198: Date currentDate = new Date(System.currentTimeMillis());
1199: if (validDate.getTime() > currentDate.getTime()) {
1200: throw new AnnotatedException(
1201: "Validation time is in future.");
1202: }
1203:
1204: // (a)
1205: /*
1206: * We always get timely valid CRLs, so there is no step (a) (1).
1207: * "locally cached" CRLs are assumed to be in getStore(), additional
1208: * CRLs must be enabled in the ExtendedPKIXParameters and are in
1209: * getAdditionalStore()
1210: */
1211:
1212: Set crls = CertPathValidatorUtilities.getCompleteCRLs(dp, cert,
1213: currentDate, paramsPKIX);
1214: boolean validCrlFound = false;
1215: AnnotatedException lastException = null;
1216: Iterator crl_iter = crls.iterator();
1217:
1218: while (crl_iter.hasNext()
1219: && certStatus.getCertStatus() == CertStatus.UNREVOKED
1220: && !reasonMask.isAllReasons()) {
1221: try {
1222: X509CRL crl = (X509CRL) crl_iter.next();
1223:
1224: // (d)
1225: ReasonsMask interimReasonsMask = processCRLD(crl, dp);
1226:
1227: // (e)
1228: /*
1229: * The reasons mask is updated at the end, so only valid CRLs
1230: * can update it. If this CRL does not contain new reasons it
1231: * must be ignored.
1232: */
1233: if (!interimReasonsMask.hasNewReasons(reasonMask)) {
1234: continue;
1235: }
1236:
1237: // (f)
1238: Set keys = processCRLF(crl, cert, defaultCRLSignCert,
1239: defaultCRLSignKey, paramsPKIX);
1240: // (g)
1241: PublicKey key = processCRLG(crl, keys);
1242:
1243: X509CRL deltaCRL = null;
1244:
1245: if (paramsPKIX.isUseDeltasEnabled()) {
1246: // get delta CRLs
1247: Set deltaCRLs = CertPathValidatorUtilities
1248: .getDeltaCRLs(currentDate, paramsPKIX, crl);
1249: // we only want one valid delta CRL
1250: // (h)
1251: deltaCRL = processCRLH(deltaCRLs, key);
1252: }
1253:
1254: /*
1255: * CRL must be be valid at the current time, not the validation
1256: * time. If a certificate is revoked with reason keyCompromise,
1257: * cACompromise, it can be used for forgery, also for the past.
1258: * This reason may not be contained in older CRLs.
1259: */
1260:
1261: /*
1262: * in the chain model signatures stay valid also after the
1263: * certificate has been expired, so they do not have to be in
1264: * the CRL vality time
1265: */
1266:
1267: if (paramsPKIX.getValidityModel() != ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL) {
1268: /*
1269: * if a certificate has expired, but was revoked, it is not
1270: * more in the CRL, so it would be regarded as valid if the
1271: * first check is not done
1272: */
1273: if (cert.getNotAfter().getTime() < crl
1274: .getThisUpdate().getTime()) {
1275: throw new AnnotatedException(
1276: "No valid CRL for current time found.");
1277: }
1278: }
1279:
1280: processCRLB1(dp, cert, crl);
1281:
1282: // (b) (2)
1283: processCRLB2(dp, cert, crl);
1284:
1285: // (c)
1286: processCRLC(deltaCRL, crl, paramsPKIX);
1287:
1288: // (i)
1289: processCRLI(validDate, deltaCRL,
1290: cert.getSerialNumber(), certStatus, paramsPKIX);
1291:
1292: // (j)
1293: processCRLJ(validDate, crl, cert.getSerialNumber(),
1294: certStatus);
1295:
1296: // (k)
1297: if (certStatus.getCertStatus() == CRLReason.removeFromCRL) {
1298: certStatus.setCertStatus(CertStatus.UNREVOKED);
1299: }
1300:
1301: // update reasons mask
1302: reasonMask.addReasons(interimReasonsMask);
1303: validCrlFound = true;
1304: } catch (AnnotatedException e) {
1305: lastException = e;
1306: }
1307: }
1308: if (!validCrlFound) {
1309: throw lastException;
1310: }
1311: }
1312:
1313: /**
1314: * Checks a certificate if it is revoked.
1315: *
1316: * @param paramsPKIX PKIX parameters.
1317: * @param cert Certificate to check if it is revoked.
1318: * @param validDate The date when the certificate revocation status should
1319: * be checked.
1320: *
1321: * @param sign The issuer certificate of the certificate <code>cert</code>.
1322: * @param workingPublicKey The public key of the issuer certificate
1323: * <code>sign</code>.
1324: * @param certPathCerts The certificates of the certification path.
1325: * @throws AnnotatedException if the certificate is revoked or the status
1326: * cannot be checked or some error occurs.
1327: */
1328: private static void checkCRLs(ExtendedPKIXParameters paramsPKIX,
1329: X509Certificate cert, Date validDate, X509Certificate sign,
1330: PublicKey workingPublicKey, List certPathCerts)
1331: throws AnnotatedException {
1332: AnnotatedException lastException = null;
1333: CRLDistPoint crldp = null;
1334: try {
1335: crldp = CRLDistPoint.getInstance(CertPathValidatorUtilities
1336: .getExtensionValue(cert, CRL_DISTRIBUTION_POINTS));
1337: } catch (Exception e) {
1338: throw new AnnotatedException(
1339: "CRL distribution point extension could not be read.",
1340: e);
1341: }
1342: try {
1343: CertPathValidatorUtilities
1344: .addAdditionalStoresFromCRLDistributionPoint(crldp,
1345: paramsPKIX);
1346: } catch (AnnotatedException e) {
1347: throw new AnnotatedException(
1348: "No additional CRL locations could be decoded from CRL distribution point extension.",
1349: e);
1350: }
1351: CertStatus certStatus = new CertStatus();
1352: ReasonsMask reasonsMask = new ReasonsMask();
1353:
1354: boolean validCrlFound = false;
1355: // for each distribution point
1356: if (crldp != null) {
1357: DistributionPoint dps[] = null;
1358: try {
1359: dps = crldp.getDistributionPoints();
1360: } catch (Exception e) {
1361: throw new AnnotatedException(
1362: "Distribution points could not be read.", e);
1363: }
1364: try {
1365: for (int i = 0; i < dps.length
1366: && certStatus.getCertStatus() == CertStatus.UNREVOKED
1367: && !reasonsMask.isAllReasons(); i++) {
1368: ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX
1369: .clone();
1370: checkCRL(dps[i], paramsPKIXClone, cert, validDate,
1371: sign, workingPublicKey, certStatus,
1372: reasonsMask, certPathCerts);
1373: validCrlFound = true;
1374: }
1375: } catch (AnnotatedException e) {
1376: lastException = new AnnotatedException(
1377: "No valid CRL for distribution point found.", e);
1378: }
1379: }
1380:
1381: /*
1382: * If the revocation status has not been determined, repeat the process
1383: * above with any available CRLs not specified in a distribution point
1384: * but issued by the certificate issuer.
1385: */
1386:
1387: if (certStatus.getCertStatus() == CertStatus.UNREVOKED
1388: && !reasonsMask.isAllReasons()) {
1389: try {
1390: /*
1391: * assume a DP with both the reasons and the cRLIssuer fields
1392: * omitted and a distribution point name of the certificate
1393: * issuer.
1394: */
1395: DERObject issuer = null;
1396: try {
1397: issuer = new ASN1InputStream(
1398: CertPathValidatorUtilities
1399: .getEncodedIssuerPrincipal(cert)
1400: .getEncoded()).readObject();
1401: } catch (Exception e) {
1402: throw new AnnotatedException(
1403: "Issuer from certificate for CRL could not be reencoded.",
1404: e);
1405: }
1406: DistributionPoint dp = new DistributionPoint(
1407: new DistributionPointName(0, new GeneralNames(
1408: new GeneralName(
1409: GeneralName.directoryName,
1410: issuer))), null, null);
1411: ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX
1412: .clone();
1413: checkCRL(dp, paramsPKIXClone, cert, validDate, sign,
1414: workingPublicKey, certStatus, reasonsMask,
1415: certPathCerts);
1416: validCrlFound = true;
1417: } catch (AnnotatedException e) {
1418: lastException = new AnnotatedException(
1419: "No valid CRL for distribution point found.", e);
1420: }
1421: }
1422:
1423: if (!validCrlFound) {
1424: throw new AnnotatedException("No valid CRL found.",
1425: lastException);
1426: }
1427: if (certStatus.getCertStatus() != CertStatus.UNREVOKED) {
1428: String message = "Certificate revocation after "
1429: + certStatus.getRevocationDate();
1430: message += ", reason: "
1431: + crlReasons[certStatus.getCertStatus()];
1432: throw new AnnotatedException(message);
1433: }
1434: if (!reasonsMask.isAllReasons()
1435: && certStatus.getCertStatus() == CertStatus.UNREVOKED) {
1436: certStatus.setCertStatus(CertStatus.UNDETERMINED);
1437: }
1438: if (certStatus.getCertStatus() == CertStatus.UNDETERMINED) {
1439: throw new AnnotatedException(
1440: "Certificate status could not be determined.");
1441: }
1442: }
1443: }
|