0001: package org.bouncycastle.jce.provider;
0002:
0003: import org.bouncycastle.asn1.ASN1InputStream;
0004: import org.bouncycastle.asn1.ASN1Sequence;
0005: import org.bouncycastle.asn1.ASN1TaggedObject;
0006: import org.bouncycastle.asn1.DEREncodable;
0007: import org.bouncycastle.asn1.DEREnumerated;
0008: import org.bouncycastle.asn1.DERInteger;
0009: import org.bouncycastle.asn1.DERObject;
0010: import org.bouncycastle.asn1.DERObjectIdentifier;
0011: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
0012: import org.bouncycastle.asn1.x509.BasicConstraints;
0013: import org.bouncycastle.asn1.x509.GeneralName;
0014: import org.bouncycastle.asn1.x509.GeneralSubtree;
0015: import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
0016: import org.bouncycastle.asn1.x509.NameConstraints;
0017: import org.bouncycastle.asn1.x509.PolicyInformation;
0018: import org.bouncycastle.asn1.x509.X509Extensions;
0019:
0020: import javax.security.auth.x500.X500Principal;
0021: import java.io.IOException;
0022: import java.math.BigInteger;
0023: import java.security.GeneralSecurityException;
0024: import java.security.InvalidAlgorithmParameterException;
0025: import java.security.PublicKey;
0026: import java.security.cert.CertPath;
0027: import java.security.cert.CertPathParameters;
0028: import java.security.cert.CertPathValidatorException;
0029: import java.security.cert.CertPathValidatorResult;
0030: import java.security.cert.CertPathValidatorSpi;
0031: import java.security.cert.CertificateExpiredException;
0032: import java.security.cert.CertificateNotYetValidException;
0033: import java.security.cert.PKIXCertPathChecker;
0034: import java.security.cert.PKIXCertPathValidatorResult;
0035: import java.security.cert.PKIXParameters;
0036: import java.security.cert.TrustAnchor;
0037: import java.security.cert.X509CRL;
0038: import java.security.cert.X509CRLEntry;
0039: import java.security.cert.X509CRLSelector;
0040: import java.security.cert.X509Certificate;
0041: import java.util.ArrayList;
0042: import java.util.Date;
0043: import java.util.Enumeration;
0044: import java.util.HashMap;
0045: import java.util.HashSet;
0046: import java.util.Iterator;
0047: import java.util.List;
0048: import java.util.Map;
0049: import java.util.Set;
0050:
0051: /**
0052: * CertPathValidatorSpi implemenation for X.509 Certificate validation ala rfc 3280<br />
0053: **/
0054: public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi {
0055: private static final String CERTIFICATE_POLICIES = X509Extensions.CertificatePolicies
0056: .getId();
0057: private static final String POLICY_MAPPINGS = X509Extensions.PolicyMappings
0058: .getId();
0059: private static final String INHIBIT_ANY_POLICY = X509Extensions.InhibitAnyPolicy
0060: .getId();
0061: private static final String ISSUING_DISTRIBUTION_POINT = X509Extensions.IssuingDistributionPoint
0062: .getId();
0063: private static final String DELTA_CRL_INDICATOR = X509Extensions.DeltaCRLIndicator
0064: .getId();
0065: private static final String POLICY_CONSTRAINTS = X509Extensions.PolicyConstraints
0066: .getId();
0067: private static final String BASIC_CONSTRAINTS = X509Extensions.BasicConstraints
0068: .getId();
0069: private static final String SUBJECT_ALTERNATIVE_NAME = X509Extensions.SubjectAlternativeName
0070: .getId();
0071: private static final String NAME_CONSTRAINTS = X509Extensions.NameConstraints
0072: .getId();
0073: private static final String KEY_USAGE = X509Extensions.KeyUsage
0074: .getId();
0075:
0076: private static final String CRL_NUMBER = X509Extensions.CRLNumber
0077: .getId();
0078:
0079: private static final String ANY_POLICY = "2.5.29.32.0";
0080:
0081: /*
0082: * key usage bits
0083: */
0084: private static final int KEY_CERT_SIGN = 5;
0085: private static final int CRL_SIGN = 6;
0086:
0087: private static final String[] crlReasons = new String[] {
0088: "unspecified", "keyCompromise", "cACompromise",
0089: "affiliationChanged", "superseded", "cessationOfOperation",
0090: "certificateHold", "unknown", "removeFromCRL",
0091: "privilegeWithdrawn", "aACompromise" };
0092:
0093: public CertPathValidatorResult engineValidate(CertPath certPath,
0094: CertPathParameters params)
0095: throws CertPathValidatorException,
0096: InvalidAlgorithmParameterException {
0097: if (!(params instanceof PKIXParameters)) {
0098: throw new InvalidAlgorithmParameterException(
0099: "params must be a PKIXParameters instance");
0100: }
0101:
0102: PKIXParameters paramsPKIX = (PKIXParameters) params;
0103: if (paramsPKIX.getTrustAnchors() == null) {
0104: throw new InvalidAlgorithmParameterException(
0105: "trustAnchors is null, this is not allowed for path validation");
0106: }
0107:
0108: //
0109: // 6.1.1 - inputs
0110: //
0111:
0112: //
0113: // (a)
0114: //
0115: List certs = certPath.getCertificates();
0116: int n = certs.size();
0117:
0118: if (certs.isEmpty()) {
0119: throw new CertPathValidatorException("CertPath is empty",
0120: null, certPath, 0);
0121: }
0122:
0123: //
0124: // (b)
0125: //
0126: Date validDate = CertPathValidatorUtilities
0127: .getValidDate(paramsPKIX);
0128:
0129: //
0130: // (c)
0131: //
0132: Set userInitialPolicySet = paramsPKIX.getInitialPolicies();
0133:
0134: //
0135: // (d)
0136: //
0137: TrustAnchor trust = CertPathValidatorUtilities.findTrustAnchor(
0138: (X509Certificate) certs.get(certs.size() - 1),
0139: certPath, certs.size() - 1, paramsPKIX
0140: .getTrustAnchors());
0141:
0142: if (trust == null) {
0143: throw new CertPathValidatorException(
0144: "TrustAnchor for CertPath not found.", null,
0145: certPath, -1);
0146: }
0147:
0148: //
0149: // (e), (f), (g) are part of the paramsPKIX object.
0150: //
0151:
0152: Iterator certIter;
0153: int index = 0;
0154: int i;
0155:
0156: //
0157: // 6.1.2 - setup
0158: //
0159:
0160: //
0161: // (a)
0162: //
0163: List[] policyNodes = new ArrayList[n + 1];
0164: for (int j = 0; j < policyNodes.length; j++) {
0165: policyNodes[j] = new ArrayList();
0166: }
0167:
0168: Set policySet = new HashSet();
0169:
0170: policySet.add(ANY_POLICY);
0171:
0172: PKIXPolicyNode validPolicyTree = new PKIXPolicyNode(
0173: new ArrayList(), 0, policySet, null, new HashSet(),
0174: ANY_POLICY, false);
0175:
0176: policyNodes[0].add(validPolicyTree);
0177:
0178: //
0179: // (b) and (c)
0180: //
0181: PKIXNameConstraints nameConstraints = new PKIXNameConstraints();
0182:
0183: //
0184: // (d)
0185: //
0186: int explicitPolicy;
0187: Set acceptablePolicies = null;
0188:
0189: if (paramsPKIX.isExplicitPolicyRequired()) {
0190: explicitPolicy = 0;
0191: } else {
0192: explicitPolicy = n + 1;
0193: }
0194:
0195: //
0196: // (e)
0197: //
0198: int inhibitAnyPolicy;
0199:
0200: if (paramsPKIX.isAnyPolicyInhibited()) {
0201: inhibitAnyPolicy = 0;
0202: } else {
0203: inhibitAnyPolicy = n + 1;
0204: }
0205:
0206: //
0207: // (f)
0208: //
0209: int policyMapping;
0210:
0211: if (paramsPKIX.isPolicyMappingInhibited()) {
0212: policyMapping = 0;
0213: } else {
0214: policyMapping = n + 1;
0215: }
0216:
0217: //
0218: // (g), (h), (i), (j)
0219: //
0220: PublicKey workingPublicKey;
0221: X500Principal workingIssuerName;
0222:
0223: X509Certificate sign = trust.getTrustedCert();
0224: try {
0225: if (sign != null) {
0226: workingIssuerName = CertPathValidatorUtilities
0227: .getSubjectPrincipal(sign);
0228: workingPublicKey = sign.getPublicKey();
0229: } else {
0230: workingIssuerName = new X500Principal(trust.getCAName());
0231: workingPublicKey = trust.getCAPublicKey();
0232: }
0233: } catch (IllegalArgumentException ex) {
0234: throw new CertPathValidatorException(
0235: "TrustAnchor subjectDN: " + ex.toString());
0236: }
0237:
0238: AlgorithmIdentifier workingAlgId = CertPathValidatorUtilities
0239: .getAlgorithmIdentifier(workingPublicKey);
0240: DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId
0241: .getObjectId();
0242: DEREncodable workingPublicKeyParameters = workingAlgId
0243: .getParameters();
0244:
0245: //
0246: // (k)
0247: //
0248: int maxPathLength = n;
0249:
0250: //
0251: // 6.1.3
0252: //
0253: Iterator tmpIter;
0254: int tmpInt;
0255:
0256: if (paramsPKIX.getTargetCertConstraints() != null
0257: && !paramsPKIX.getTargetCertConstraints().match(
0258: (X509Certificate) certs.get(0))) {
0259: throw new CertPathValidatorException(
0260: "target certificate in certpath does not match targetcertconstraints",
0261: null, certPath, 0);
0262: }
0263:
0264: //
0265: // initialise CertPathChecker's
0266: //
0267: List pathCheckers = paramsPKIX.getCertPathCheckers();
0268: certIter = pathCheckers.iterator();
0269: while (certIter.hasNext()) {
0270: ((PKIXCertPathChecker) certIter.next()).init(false);
0271: }
0272:
0273: X509Certificate cert = null;
0274:
0275: for (index = certs.size() - 1; index >= 0; index--) {
0276: try {
0277: //
0278: // i as defined in the algorithm description
0279: //
0280: i = n - index;
0281:
0282: //
0283: // set certificate to be checked in this round
0284: // sign and workingPublicKey and workingIssuerName are set
0285: // at the end of the for loop and initialied the
0286: // first time from the TrustAnchor
0287: //
0288: cert = (X509Certificate) certs.get(index);
0289:
0290: //
0291: // 6.1.3
0292: //
0293:
0294: //
0295: // (a) verify
0296: //
0297: try {
0298:
0299: // (a) (1)
0300: //
0301: cert.verify(workingPublicKey, "BC");
0302: } catch (GeneralSecurityException e) {
0303: throw new CertPathValidatorException(
0304: "Could not validate certificate signature.",
0305: e, certPath, index);
0306: }
0307:
0308: try {
0309: // (a) (2)
0310: //
0311: cert.checkValidity(validDate);
0312: } catch (CertificateExpiredException e) {
0313: throw new CertPathValidatorException(
0314: "Could not validate certificate: "
0315: + e.getMessage(), e, certPath,
0316: index);
0317: } catch (CertificateNotYetValidException e) {
0318: throw new CertPathValidatorException(
0319: "Could not validate certificate: "
0320: + e.getMessage(), e, certPath,
0321: index);
0322: }
0323:
0324: //
0325: // (a) (3)
0326: //
0327: if (paramsPKIX.isRevocationEnabled()) {
0328: checkCRLs(paramsPKIX, cert, validDate, sign,
0329: workingPublicKey);
0330: }
0331:
0332: //
0333: // (a) (4) name chaining
0334: //
0335: if (!CertPathValidatorUtilities
0336: .getEncodedIssuerPrincipal(cert).equals(
0337: workingIssuerName)) {
0338: throw new CertPathValidatorException("IssuerName("
0339: + CertPathValidatorUtilities
0340: .getEncodedIssuerPrincipal(cert)
0341: + ") does not match SubjectName("
0342: + workingIssuerName
0343: + ") of signing certificate", null,
0344: certPath, index);
0345: }
0346:
0347: //
0348: // (b), (c) permitted and excluded subtree checking.
0349: //
0350: if (!(CertPathValidatorUtilities.isSelfIssued(cert) && (i < n))) {
0351: X500Principal principal = CertPathValidatorUtilities
0352: .getSubjectPrincipal(cert);
0353: ASN1InputStream aIn = new ASN1InputStream(principal
0354: .getEncoded());
0355: ASN1Sequence dns;
0356:
0357: try {
0358: dns = (ASN1Sequence) aIn.readObject();
0359: } catch (IOException e) {
0360: throw new CertPathValidatorException(
0361: "exception extracting subject name when checking subtrees");
0362: }
0363:
0364: nameConstraints.checkPermittedDN(dns);
0365: nameConstraints.checkExcludedDN(dns);
0366:
0367: ASN1Sequence altName = (ASN1Sequence) CertPathValidatorUtilities
0368: .getExtensionValue(cert,
0369: SUBJECT_ALTERNATIVE_NAME);
0370: if (altName != null) {
0371: for (int j = 0; j < altName.size(); j++) {
0372: GeneralName name = GeneralName
0373: .getInstance(altName.getObjectAt(j));
0374:
0375: nameConstraints.checkPermitted(name);
0376: nameConstraints.checkExcluded(name);
0377: }
0378: }
0379: }
0380:
0381: //
0382: // (d) policy Information checking against initial policy and
0383: // policy mapping
0384: //
0385: ASN1Sequence certPolicies = (ASN1Sequence) CertPathValidatorUtilities
0386: .getExtensionValue(cert, CERTIFICATE_POLICIES);
0387: if (certPolicies != null && validPolicyTree != null) {
0388: //
0389: // (d) (1)
0390: //
0391: Enumeration e = certPolicies.getObjects();
0392: Set pols = new HashSet();
0393:
0394: while (e.hasMoreElements()) {
0395: PolicyInformation pInfo = PolicyInformation
0396: .getInstance(e.nextElement());
0397: DERObjectIdentifier pOid = pInfo
0398: .getPolicyIdentifier();
0399:
0400: pols.add(pOid.getId());
0401:
0402: if (!ANY_POLICY.equals(pOid.getId())) {
0403: Set pq = CertPathValidatorUtilities
0404: .getQualifierSet(pInfo
0405: .getPolicyQualifiers());
0406:
0407: boolean match = CertPathValidatorUtilities
0408: .processCertD1i(i, policyNodes,
0409: pOid, pq);
0410:
0411: if (!match) {
0412: CertPathValidatorUtilities
0413: .processCertD1ii(i,
0414: policyNodes, pOid, pq);
0415: }
0416: }
0417: }
0418:
0419: if (acceptablePolicies == null
0420: || acceptablePolicies.contains(ANY_POLICY)) {
0421: acceptablePolicies = pols;
0422: } else {
0423: Iterator it = acceptablePolicies.iterator();
0424: Set t1 = new HashSet();
0425:
0426: while (it.hasNext()) {
0427: Object o = it.next();
0428:
0429: if (pols.contains(o)) {
0430: t1.add(o);
0431: }
0432: }
0433:
0434: acceptablePolicies = t1;
0435: }
0436:
0437: //
0438: // (d) (2)
0439: //
0440: if ((inhibitAnyPolicy > 0)
0441: || ((i < n) && CertPathValidatorUtilities
0442: .isSelfIssued(cert))) {
0443: e = certPolicies.getObjects();
0444:
0445: while (e.hasMoreElements()) {
0446: PolicyInformation pInfo = PolicyInformation
0447: .getInstance(e.nextElement());
0448:
0449: if (ANY_POLICY.equals(pInfo
0450: .getPolicyIdentifier().getId())) {
0451: Set _apq = CertPathValidatorUtilities
0452: .getQualifierSet(pInfo
0453: .getPolicyQualifiers());
0454: List _nodes = policyNodes[i - 1];
0455:
0456: for (int k = 0; k < _nodes.size(); k++) {
0457: PKIXPolicyNode _node = (PKIXPolicyNode) _nodes
0458: .get(k);
0459:
0460: Iterator _policySetIter = _node
0461: .getExpectedPolicies()
0462: .iterator();
0463: while (_policySetIter.hasNext()) {
0464: Object _tmp = _policySetIter
0465: .next();
0466:
0467: String _policy;
0468: if (_tmp instanceof String) {
0469: _policy = (String) _tmp;
0470: } else if (_tmp instanceof DERObjectIdentifier) {
0471: _policy = ((DERObjectIdentifier) _tmp)
0472: .getId();
0473: } else {
0474: continue;
0475: }
0476:
0477: boolean _found = false;
0478: Iterator _childrenIter = _node
0479: .getChildren();
0480:
0481: while (_childrenIter.hasNext()) {
0482: PKIXPolicyNode _child = (PKIXPolicyNode) _childrenIter
0483: .next();
0484:
0485: if (_policy.equals(_child
0486: .getValidPolicy())) {
0487: _found = true;
0488: }
0489: }
0490:
0491: if (!_found) {
0492: Set _newChildExpectedPolicies = new HashSet();
0493: _newChildExpectedPolicies
0494: .add(_policy);
0495:
0496: PKIXPolicyNode _newChild = new PKIXPolicyNode(
0497: new ArrayList(),
0498: i,
0499: _newChildExpectedPolicies,
0500: _node, _apq,
0501: _policy, false);
0502: _node.addChild(_newChild);
0503: policyNodes[i]
0504: .add(_newChild);
0505: }
0506: }
0507: }
0508: break;
0509: }
0510: }
0511: }
0512:
0513: //
0514: // (d) (3)
0515: //
0516: for (int j = (i - 1); j >= 0; j--) {
0517: List nodes = policyNodes[j];
0518:
0519: for (int k = 0; k < nodes.size(); k++) {
0520: PKIXPolicyNode node = (PKIXPolicyNode) nodes
0521: .get(k);
0522: if (!node.hasChildren()) {
0523: validPolicyTree = CertPathValidatorUtilities
0524: .removePolicyNode(
0525: validPolicyTree,
0526: policyNodes, node);
0527: if (validPolicyTree == null) {
0528: break;
0529: }
0530: }
0531: }
0532: }
0533:
0534: //
0535: // d (4)
0536: //
0537: Set criticalExtensionOids = cert
0538: .getCriticalExtensionOIDs();
0539:
0540: if (criticalExtensionOids != null) {
0541: boolean critical = criticalExtensionOids
0542: .contains(CERTIFICATE_POLICIES);
0543:
0544: List nodes = policyNodes[i];
0545: for (int j = 0; j < nodes.size(); j++) {
0546: PKIXPolicyNode node = (PKIXPolicyNode) nodes
0547: .get(j);
0548: node.setCritical(critical);
0549: }
0550: }
0551: }
0552:
0553: //
0554: // (e)
0555: //
0556: if (certPolicies == null) {
0557: validPolicyTree = null;
0558: }
0559:
0560: //
0561: // (f)
0562: //
0563: if (explicitPolicy <= 0 && validPolicyTree == null) {
0564: throw new CertPathValidatorException(
0565: "No valid policy tree found when one expected.");
0566: }
0567:
0568: //
0569: // 6.1.4
0570: //
0571:
0572: if (i != n) {
0573: if (cert != null && cert.getVersion() == 1) {
0574: throw new CertPathValidatorException(
0575: "Version 1 certs can't be used as CA ones");
0576: }
0577:
0578: //
0579: //
0580: // (a) check the policy mappings
0581: //
0582: DERObject pm = CertPathValidatorUtilities
0583: .getExtensionValue(cert, POLICY_MAPPINGS);
0584: if (pm != null) {
0585: ASN1Sequence mappings = (ASN1Sequence) pm;
0586:
0587: for (int j = 0; j < mappings.size(); j++) {
0588: ASN1Sequence mapping = (ASN1Sequence) mappings
0589: .getObjectAt(j);
0590:
0591: DERObjectIdentifier issuerDomainPolicy = (DERObjectIdentifier) mapping
0592: .getObjectAt(0);
0593: DERObjectIdentifier subjectDomainPolicy = (DERObjectIdentifier) mapping
0594: .getObjectAt(1);
0595:
0596: if (ANY_POLICY.equals(issuerDomainPolicy
0597: .getId())) {
0598:
0599: throw new CertPathValidatorException(
0600: "IssuerDomainPolicy is anyPolicy");
0601: }
0602:
0603: if (ANY_POLICY.equals(subjectDomainPolicy
0604: .getId())) {
0605:
0606: throw new CertPathValidatorException(
0607: "SubjectDomainPolicy is anyPolicy");
0608: }
0609: }
0610: }
0611:
0612: // (b)
0613: //
0614: if (pm != null) {
0615: ASN1Sequence mappings = (ASN1Sequence) pm;
0616: Map m_idp = new HashMap();
0617: Set s_idp = new HashSet();
0618:
0619: for (int j = 0; j < mappings.size(); j++) {
0620: ASN1Sequence mapping = (ASN1Sequence) mappings
0621: .getObjectAt(j);
0622: String id_p = ((DERObjectIdentifier) mapping
0623: .getObjectAt(0)).getId();
0624: String sd_p = ((DERObjectIdentifier) mapping
0625: .getObjectAt(1)).getId();
0626: Set tmp;
0627:
0628: if (!m_idp.containsKey(id_p)) {
0629: tmp = new HashSet();
0630: tmp.add(sd_p);
0631: m_idp.put(id_p, tmp);
0632: s_idp.add(id_p);
0633: } else {
0634: tmp = (Set) m_idp.get(id_p);
0635: tmp.add(sd_p);
0636: }
0637: }
0638:
0639: Iterator it_idp = s_idp.iterator();
0640: while (it_idp.hasNext()) {
0641: String id_p = (String) it_idp.next();
0642:
0643: //
0644: // (1)
0645: //
0646: if (policyMapping > 0) {
0647: boolean idp_found = false;
0648: Iterator nodes_i = policyNodes[i]
0649: .iterator();
0650: while (nodes_i.hasNext()) {
0651: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i
0652: .next();
0653: if (node.getValidPolicy().equals(
0654: id_p)) {
0655: idp_found = true;
0656: node.expectedPolicies = (Set) m_idp
0657: .get(id_p);
0658: break;
0659: }
0660: }
0661:
0662: if (!idp_found) {
0663: nodes_i = policyNodes[i].iterator();
0664: while (nodes_i.hasNext()) {
0665: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i
0666: .next();
0667: if (ANY_POLICY.equals(node
0668: .getValidPolicy())) {
0669: Set pq = null;
0670: ASN1Sequence policies = (ASN1Sequence) CertPathValidatorUtilities
0671: .getExtensionValue(
0672: cert,
0673: CERTIFICATE_POLICIES);
0674: Enumeration e = policies
0675: .getObjects();
0676: while (e.hasMoreElements()) {
0677: PolicyInformation pinfo = PolicyInformation
0678: .getInstance(e
0679: .nextElement());
0680: if (ANY_POLICY
0681: .equals(pinfo
0682: .getPolicyIdentifier()
0683: .getId())) {
0684: pq = CertPathValidatorUtilities
0685: .getQualifierSet(pinfo
0686: .getPolicyQualifiers());
0687: break;
0688: }
0689: }
0690: boolean ci = false;
0691: if (cert
0692: .getCriticalExtensionOIDs() != null) {
0693: ci = cert
0694: .getCriticalExtensionOIDs()
0695: .contains(
0696: CERTIFICATE_POLICIES);
0697: }
0698:
0699: PKIXPolicyNode p_node = (PKIXPolicyNode) node
0700: .getParent();
0701: if (ANY_POLICY
0702: .equals(p_node
0703: .getValidPolicy())) {
0704: PKIXPolicyNode c_node = new PKIXPolicyNode(
0705: new ArrayList(),
0706: i,
0707: (Set) m_idp
0708: .get(id_p),
0709: p_node, pq,
0710: id_p, ci);
0711: p_node.addChild(c_node);
0712: policyNodes[i]
0713: .add(c_node);
0714: }
0715: break;
0716: }
0717: }
0718: }
0719:
0720: //
0721: // (2)
0722: //
0723: } else if (policyMapping <= 0) {
0724: Iterator nodes_i = policyNodes[i]
0725: .iterator();
0726: while (nodes_i.hasNext()) {
0727: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i
0728: .next();
0729: if (node.getValidPolicy().equals(
0730: id_p)) {
0731: PKIXPolicyNode p_node = (PKIXPolicyNode) node
0732: .getParent();
0733: p_node.removeChild(node);
0734: nodes_i.remove();
0735: for (int k = (i - 1); k >= 0; k--) {
0736: List nodes = policyNodes[k];
0737: for (int l = 0; l < nodes
0738: .size(); l++) {
0739: PKIXPolicyNode node2 = (PKIXPolicyNode) nodes
0740: .get(l);
0741: if (!node2
0742: .hasChildren()) {
0743: validPolicyTree = CertPathValidatorUtilities
0744: .removePolicyNode(
0745: validPolicyTree,
0746: policyNodes,
0747: node2);
0748: if (validPolicyTree == null) {
0749: break;
0750: }
0751: }
0752: }
0753: }
0754: }
0755: }
0756: }
0757: }
0758: }
0759:
0760: //
0761: // (g) handle the name constraints extension
0762: //
0763: ASN1Sequence ncSeq = (ASN1Sequence) CertPathValidatorUtilities
0764: .getExtensionValue(cert, NAME_CONSTRAINTS);
0765: if (ncSeq != null) {
0766: NameConstraints nc = new NameConstraints(ncSeq);
0767:
0768: //
0769: // (g) (1) permitted subtrees
0770: //
0771: ASN1Sequence permitted = nc
0772: .getPermittedSubtrees();
0773: if (permitted != null) {
0774: Enumeration e = permitted.getObjects();
0775: while (e.hasMoreElements()) {
0776: GeneralSubtree subtree = GeneralSubtree
0777: .getInstance(e.nextElement());
0778:
0779: nameConstraints
0780: .intersectPermittedSubtree(subtree);
0781: }
0782: }
0783:
0784: //
0785: // (g) (2) excluded subtrees
0786: //
0787: ASN1Sequence excluded = nc
0788: .getExcludedSubtrees();
0789: if (excluded != null) {
0790: Enumeration e = excluded.getObjects();
0791: while (e.hasMoreElements()) {
0792: GeneralSubtree subtree = GeneralSubtree
0793: .getInstance(e.nextElement());
0794: nameConstraints
0795: .addExcludedSubtree(subtree);
0796: }
0797: }
0798: }
0799:
0800: //
0801: // (h)
0802: //
0803: if (!CertPathValidatorUtilities.isSelfIssued(cert)) {
0804: //
0805: // (1)
0806: //
0807: if (explicitPolicy != 0) {
0808: explicitPolicy--;
0809: }
0810:
0811: //
0812: // (2)
0813: //
0814: if (policyMapping != 0) {
0815: policyMapping--;
0816: }
0817:
0818: //
0819: // (3)
0820: //
0821: if (inhibitAnyPolicy != 0) {
0822: inhibitAnyPolicy--;
0823: }
0824: }
0825:
0826: //
0827: // (i)
0828: //
0829: ASN1Sequence pc = (ASN1Sequence) CertPathValidatorUtilities
0830: .getExtensionValue(cert, POLICY_CONSTRAINTS);
0831:
0832: if (pc != null) {
0833: Enumeration policyConstraints = pc.getObjects();
0834:
0835: while (policyConstraints.hasMoreElements()) {
0836: ASN1TaggedObject constraint = (ASN1TaggedObject) policyConstraints
0837: .nextElement();
0838: switch (constraint.getTagNo()) {
0839: case 0:
0840: tmpInt = DERInteger.getInstance(
0841: constraint).getValue()
0842: .intValue();
0843: if (tmpInt < explicitPolicy) {
0844: explicitPolicy = tmpInt;
0845: }
0846: break;
0847: case 1:
0848: tmpInt = DERInteger.getInstance(
0849: constraint).getValue()
0850: .intValue();
0851: if (tmpInt < policyMapping) {
0852: policyMapping = tmpInt;
0853: }
0854: break;
0855: }
0856: }
0857: }
0858:
0859: //
0860: // (j)
0861: //
0862: DERInteger iap = (DERInteger) CertPathValidatorUtilities
0863: .getExtensionValue(cert, INHIBIT_ANY_POLICY);
0864:
0865: if (iap != null) {
0866: int _inhibitAnyPolicy = iap.getValue()
0867: .intValue();
0868:
0869: if (_inhibitAnyPolicy < inhibitAnyPolicy) {
0870: inhibitAnyPolicy = _inhibitAnyPolicy;
0871: }
0872: }
0873:
0874: //
0875: // (k)
0876: //
0877: BasicConstraints bc = BasicConstraints
0878: .getInstance(CertPathValidatorUtilities
0879: .getExtensionValue(cert,
0880: BASIC_CONSTRAINTS));
0881: if (bc != null) {
0882: if (!(bc.isCA())) {
0883: throw new CertPathValidatorException(
0884: "Not a CA certificate");
0885: }
0886: } else {
0887: throw new CertPathValidatorException(
0888: "Intermediate certificate lacks BasicConstraints");
0889: }
0890:
0891: //
0892: // (l)
0893: //
0894: if (!CertPathValidatorUtilities.isSelfIssued(cert)) {
0895: if (maxPathLength <= 0) {
0896: throw new CertPathValidatorException(
0897: "Max path length not greater than zero");
0898: }
0899:
0900: maxPathLength--;
0901: }
0902:
0903: //
0904: // (m)
0905: //
0906: if (bc != null) {
0907: BigInteger _pathLengthConstraint = bc
0908: .getPathLenConstraint();
0909:
0910: if (_pathLengthConstraint != null) {
0911: int _plc = _pathLengthConstraint.intValue();
0912:
0913: if (_plc < maxPathLength) {
0914: maxPathLength = _plc;
0915: }
0916: }
0917: }
0918:
0919: //
0920: // (n)
0921: //
0922: boolean[] _usage = cert.getKeyUsage();
0923:
0924: if ((_usage != null) && !_usage[5]) {
0925: throw new CertPathValidatorException(
0926: "Issuer certificate keyusage extension is critical an does not permit key signing.\n",
0927: null, certPath, index);
0928: }
0929:
0930: //
0931: // (o)
0932: //
0933: Set criticalExtensions = new HashSet(cert
0934: .getCriticalExtensionOIDs());
0935: // these extensions are handle by the algorithem
0936: criticalExtensions.remove(KEY_USAGE);
0937: criticalExtensions.remove(CERTIFICATE_POLICIES);
0938: criticalExtensions.remove(POLICY_MAPPINGS);
0939: criticalExtensions.remove(INHIBIT_ANY_POLICY);
0940: criticalExtensions
0941: .remove(ISSUING_DISTRIBUTION_POINT);
0942: criticalExtensions.remove(DELTA_CRL_INDICATOR);
0943: criticalExtensions.remove(POLICY_CONSTRAINTS);
0944: criticalExtensions.remove(BASIC_CONSTRAINTS);
0945: criticalExtensions.remove(SUBJECT_ALTERNATIVE_NAME);
0946: criticalExtensions.remove(NAME_CONSTRAINTS);
0947:
0948: tmpIter = pathCheckers.iterator();
0949: while (tmpIter.hasNext()) {
0950: try {
0951: ((PKIXCertPathChecker) tmpIter.next())
0952: .check(cert, criticalExtensions);
0953: } catch (CertPathValidatorException e) {
0954: throw new CertPathValidatorException(e
0955: .getMessage(), e.getCause(),
0956: certPath, index);
0957: }
0958: }
0959: if (!criticalExtensions.isEmpty()) {
0960: throw new CertPathValidatorException(
0961: "Certificate has unsupported critical extension",
0962: null, certPath, index);
0963: }
0964: }
0965:
0966: // set signing certificate for next round
0967: sign = cert;
0968: workingPublicKey = CertPathValidatorUtilities
0969: .getNextWorkingKey(sign, certs, index);
0970: try {
0971: workingIssuerName = CertPathValidatorUtilities
0972: .getSubjectPrincipal(sign);
0973: } catch (IllegalArgumentException ex) {
0974: throw new CertPathValidatorException(sign
0975: .getSubjectDN().getName()
0976: + " :" + ex.toString());
0977: }
0978: workingAlgId = CertPathValidatorUtilities
0979: .getAlgorithmIdentifier(workingPublicKey);
0980: workingPublicKeyAlgorithm = workingAlgId.getObjectId();
0981: workingPublicKeyParameters = workingAlgId
0982: .getParameters();
0983: } catch (AnnotatedException e) {
0984: throw new CertPathValidatorException(e.getMessage(), e
0985: .getUnderlyingException(), certPath, index);
0986: }
0987: }
0988:
0989: //
0990: // 6.1.5 Wrap-up procedure
0991: //
0992:
0993: //
0994: // (a)
0995: //
0996: if (!CertPathValidatorUtilities.isSelfIssued(cert)
0997: && (explicitPolicy != 0)) {
0998: explicitPolicy--;
0999: }
1000:
1001: //
1002: // (b)
1003: //
1004: try {
1005: ASN1Sequence pc = (ASN1Sequence) CertPathValidatorUtilities
1006: .getExtensionValue(cert, POLICY_CONSTRAINTS);
1007: if (pc != null) {
1008: Enumeration policyConstraints = pc.getObjects();
1009:
1010: while (policyConstraints.hasMoreElements()) {
1011: ASN1TaggedObject constraint = (ASN1TaggedObject) policyConstraints
1012: .nextElement();
1013: switch (constraint.getTagNo()) {
1014: case 0:
1015: tmpInt = DERInteger.getInstance(constraint)
1016: .getValue().intValue();
1017: if (tmpInt == 0) {
1018: explicitPolicy = 0;
1019: }
1020: break;
1021: }
1022: }
1023: }
1024: } catch (AnnotatedException e) {
1025: throw new CertPathValidatorException(e.getMessage(), e
1026: .getUnderlyingException(), certPath, index);
1027: }
1028:
1029: //
1030: // (c) (d) and (e) are already done
1031: //
1032:
1033: //
1034: // (f)
1035: //
1036: Set criticalExtensions = cert.getCriticalExtensionOIDs();
1037:
1038: if (criticalExtensions != null) {
1039: criticalExtensions = new HashSet(criticalExtensions);
1040: // these extensions are handle by the algorithm
1041: criticalExtensions.remove(KEY_USAGE);
1042: criticalExtensions.remove(CERTIFICATE_POLICIES);
1043: criticalExtensions.remove(POLICY_MAPPINGS);
1044: criticalExtensions.remove(INHIBIT_ANY_POLICY);
1045: criticalExtensions.remove(ISSUING_DISTRIBUTION_POINT);
1046: criticalExtensions.remove(DELTA_CRL_INDICATOR);
1047: criticalExtensions.remove(POLICY_CONSTRAINTS);
1048: criticalExtensions.remove(BASIC_CONSTRAINTS);
1049: criticalExtensions.remove(SUBJECT_ALTERNATIVE_NAME);
1050: criticalExtensions.remove(NAME_CONSTRAINTS);
1051: } else {
1052: criticalExtensions = new HashSet();
1053: }
1054:
1055: tmpIter = pathCheckers.iterator();
1056: while (tmpIter.hasNext()) {
1057: try {
1058: ((PKIXCertPathChecker) tmpIter.next()).check(cert,
1059: criticalExtensions);
1060: } catch (CertPathValidatorException e) {
1061: throw new CertPathValidatorException(e.getMessage(), e
1062: .getCause(), certPath, index);
1063: }
1064: }
1065:
1066: if (!criticalExtensions.isEmpty()) {
1067: throw new CertPathValidatorException(
1068: "Certificate has unsupported critical extension",
1069: null, certPath, index);
1070: }
1071:
1072: //
1073: // (g)
1074: //
1075: PKIXPolicyNode intersection;
1076:
1077: //
1078: // (g) (i)
1079: //
1080: if (validPolicyTree == null) {
1081: if (paramsPKIX.isExplicitPolicyRequired()) {
1082: throw new CertPathValidatorException(
1083: "Explicit policy requested but none available.");
1084: }
1085: intersection = null;
1086: } else if (CertPathValidatorUtilities
1087: .isAnyPolicy(userInitialPolicySet)) // (g) (ii)
1088: {
1089: if (paramsPKIX.isExplicitPolicyRequired()) {
1090: if (acceptablePolicies.isEmpty()) {
1091: throw new CertPathValidatorException(
1092: "Explicit policy requested but none available.");
1093: } else {
1094: Set _validPolicyNodeSet = new HashSet();
1095:
1096: for (int j = 0; j < policyNodes.length; j++) {
1097: List _nodeDepth = policyNodes[j];
1098:
1099: for (int k = 0; k < _nodeDepth.size(); k++) {
1100: PKIXPolicyNode _node = (PKIXPolicyNode) _nodeDepth
1101: .get(k);
1102:
1103: if (ANY_POLICY.equals(_node
1104: .getValidPolicy())) {
1105: Iterator _iter = _node.getChildren();
1106: while (_iter.hasNext()) {
1107: _validPolicyNodeSet.add(_iter
1108: .next());
1109: }
1110: }
1111: }
1112: }
1113:
1114: Iterator _vpnsIter = _validPolicyNodeSet.iterator();
1115: while (_vpnsIter.hasNext()) {
1116: PKIXPolicyNode _node = (PKIXPolicyNode) _vpnsIter
1117: .next();
1118: String _validPolicy = _node.getValidPolicy();
1119:
1120: if (!acceptablePolicies.contains(_validPolicy)) {
1121: //validPolicyTree = removePolicyNode(validPolicyTree, policyNodes, _node);
1122: }
1123: }
1124: if (validPolicyTree != null) {
1125: for (int j = (n - 1); j >= 0; j--) {
1126: List nodes = policyNodes[j];
1127:
1128: for (int k = 0; k < nodes.size(); k++) {
1129: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1130: .get(k);
1131: if (!node.hasChildren()) {
1132: validPolicyTree = CertPathValidatorUtilities
1133: .removePolicyNode(
1134: validPolicyTree,
1135: policyNodes, node);
1136: }
1137: }
1138: }
1139: }
1140: }
1141: }
1142:
1143: intersection = validPolicyTree;
1144: } else {
1145: //
1146: // (g) (iii)
1147: //
1148: // This implementation is not exactly same as the one described in RFC3280.
1149: // However, as far as the validation result is concerned, both produce
1150: // adequate result. The only difference is whether AnyPolicy is remain
1151: // in the policy tree or not.
1152: //
1153: // (g) (iii) 1
1154: //
1155: Set _validPolicyNodeSet = new HashSet();
1156:
1157: for (int j = 0; j < policyNodes.length; j++) {
1158: List _nodeDepth = policyNodes[j];
1159:
1160: for (int k = 0; k < _nodeDepth.size(); k++) {
1161: PKIXPolicyNode _node = (PKIXPolicyNode) _nodeDepth
1162: .get(k);
1163:
1164: if (ANY_POLICY.equals(_node.getValidPolicy())) {
1165: Iterator _iter = _node.getChildren();
1166: while (_iter.hasNext()) {
1167: PKIXPolicyNode _c_node = (PKIXPolicyNode) _iter
1168: .next();
1169: if (!ANY_POLICY.equals(_c_node
1170: .getValidPolicy())) {
1171: _validPolicyNodeSet.add(_c_node);
1172: }
1173: }
1174: }
1175: }
1176: }
1177:
1178: //
1179: // (g) (iii) 2
1180: //
1181: Iterator _vpnsIter = _validPolicyNodeSet.iterator();
1182: while (_vpnsIter.hasNext()) {
1183: PKIXPolicyNode _node = (PKIXPolicyNode) _vpnsIter
1184: .next();
1185: String _validPolicy = _node.getValidPolicy();
1186:
1187: if (!userInitialPolicySet.contains(_validPolicy)) {
1188: validPolicyTree = CertPathValidatorUtilities
1189: .removePolicyNode(validPolicyTree,
1190: policyNodes, _node);
1191: }
1192: }
1193:
1194: //
1195: // (g) (iii) 4
1196: //
1197: if (validPolicyTree != null) {
1198: for (int j = (n - 1); j >= 0; j--) {
1199: List nodes = policyNodes[j];
1200:
1201: for (int k = 0; k < nodes.size(); k++) {
1202: PKIXPolicyNode node = (PKIXPolicyNode) nodes
1203: .get(k);
1204: if (!node.hasChildren()) {
1205: validPolicyTree = CertPathValidatorUtilities
1206: .removePolicyNode(validPolicyTree,
1207: policyNodes, node);
1208: }
1209: }
1210: }
1211: }
1212:
1213: intersection = validPolicyTree;
1214: }
1215:
1216: if ((explicitPolicy > 0) || (intersection != null)) {
1217: return new PKIXCertPathValidatorResult(trust, intersection,
1218: workingPublicKey);
1219: }
1220:
1221: throw new CertPathValidatorException(
1222: "Path processing failed on policy.", null, certPath,
1223: index);
1224: }
1225:
1226: private void checkCRLs(PKIXParameters paramsPKIX,
1227: X509Certificate cert, Date validDate, X509Certificate sign,
1228: PublicKey workingPublicKey) throws AnnotatedException {
1229: X509CRLSelector crlselect;
1230: crlselect = new X509CRLSelector();
1231:
1232: try {
1233: crlselect.addIssuerName(CertPathValidatorUtilities
1234: .getEncodedIssuerPrincipal(cert).getEncoded());
1235: } catch (IOException e) {
1236: throw new AnnotatedException(
1237: "Cannot extract issuer from certificate: " + e, e);
1238: }
1239:
1240: crlselect.setCertificateChecking(cert);
1241:
1242: Iterator crl_iter = CertPathValidatorUtilities.findCRLs(
1243: crlselect, paramsPKIX.getCertStores()).iterator();
1244: boolean validCrlFound = false;
1245: X509CRLEntry crl_entry;
1246: while (crl_iter.hasNext()) {
1247: X509CRL crl = (X509CRL) crl_iter.next();
1248:
1249: if (cert.getNotAfter().after(crl.getThisUpdate())) {
1250: if (crl.getNextUpdate() == null
1251: || validDate.before(crl.getNextUpdate())) {
1252: validCrlFound = true;
1253: }
1254:
1255: if (sign != null) {
1256: boolean[] keyusage = sign.getKeyUsage();
1257:
1258: if (keyusage != null
1259: && (keyusage.length < 7 || !keyusage[CRL_SIGN])) {
1260: throw new AnnotatedException(
1261: "Issuer certificate keyusage extension does not permit crl signing.\n"
1262: + sign);
1263: }
1264: }
1265:
1266: try {
1267: crl.verify(workingPublicKey, "BC");
1268: } catch (Exception e) {
1269: throw new AnnotatedException("can't verify CRL: "
1270: + e, e);
1271: }
1272:
1273: crl_entry = crl.getRevokedCertificate(cert
1274: .getSerialNumber());
1275: if (crl_entry != null
1276: && !validDate.before(crl_entry
1277: .getRevocationDate())) {
1278: String reason = null;
1279:
1280: if (crl_entry.hasExtensions()) {
1281: DEREnumerated reasonCode = DEREnumerated
1282: .getInstance(CertPathValidatorUtilities
1283: .getExtensionValue(
1284: crl_entry,
1285: X509Extensions.ReasonCode
1286: .getId()));
1287: if (reasonCode != null) {
1288: reason = crlReasons[reasonCode.getValue()
1289: .intValue()];
1290: }
1291: }
1292:
1293: String message = "Certificate revocation after "
1294: + crl_entry.getRevocationDate();
1295:
1296: if (reason != null) {
1297: message += ", reason: " + reason;
1298: }
1299:
1300: throw new AnnotatedException(message);
1301: }
1302:
1303: //
1304: // check the DeltaCRL indicator, base point and the issuing distribution point
1305: //
1306: DERObject idp = CertPathValidatorUtilities
1307: .getExtensionValue(crl,
1308: ISSUING_DISTRIBUTION_POINT);
1309: DERObject dci = CertPathValidatorUtilities
1310: .getExtensionValue(crl, DELTA_CRL_INDICATOR);
1311:
1312: if (dci != null) {
1313: X509CRLSelector baseSelect = new X509CRLSelector();
1314:
1315: try {
1316: baseSelect
1317: .addIssuerName(CertPathValidatorUtilities
1318: .getIssuerPrincipal(crl)
1319: .getEncoded());
1320: } catch (IOException e) {
1321: throw new AnnotatedException(
1322: "can't extract issuer from certificate: "
1323: + e, e);
1324: }
1325:
1326: baseSelect.setMinCRLNumber(((DERInteger) dci)
1327: .getPositiveValue());
1328: baseSelect
1329: .setMaxCRLNumber(((DERInteger) CertPathValidatorUtilities
1330: .getExtensionValue(crl, CRL_NUMBER))
1331: .getPositiveValue().subtract(
1332: BigInteger.valueOf(1)));
1333:
1334: boolean foundBase = false;
1335: Iterator it = CertPathValidatorUtilities.findCRLs(
1336: baseSelect, paramsPKIX.getCertStores())
1337: .iterator();
1338: while (it.hasNext()) {
1339: X509CRL base = (X509CRL) it.next();
1340:
1341: DERObject baseIdp = CertPathValidatorUtilities
1342: .getExtensionValue(base,
1343: ISSUING_DISTRIBUTION_POINT);
1344:
1345: if (idp == null) {
1346: if (baseIdp == null) {
1347: foundBase = true;
1348: break;
1349: }
1350: } else {
1351: if (idp.equals(baseIdp)) {
1352: foundBase = true;
1353: break;
1354: }
1355: }
1356: }
1357:
1358: if (!foundBase) {
1359: throw new AnnotatedException(
1360: "No base CRL for delta CRL");
1361: }
1362: }
1363:
1364: if (idp != null) {
1365: IssuingDistributionPoint p = IssuingDistributionPoint
1366: .getInstance(idp);
1367: BasicConstraints bc = BasicConstraints
1368: .getInstance(CertPathValidatorUtilities
1369: .getExtensionValue(cert,
1370: BASIC_CONSTRAINTS));
1371:
1372: if (p.onlyContainsUserCerts()
1373: && (bc != null && bc.isCA())) {
1374: throw new AnnotatedException(
1375: "CA Cert CRL only contains user certificates");
1376: }
1377:
1378: if (p.onlyContainsCACerts()
1379: && (bc == null || !bc.isCA())) {
1380: throw new AnnotatedException(
1381: "End CRL only contains CA certificates");
1382: }
1383:
1384: if (p.onlyContainsAttributeCerts()) {
1385: throw new AnnotatedException(
1386: "onlyContainsAttributeCerts boolean is asserted");
1387: }
1388: }
1389: }
1390: }
1391:
1392: if (!validCrlFound) {
1393: throw new AnnotatedException("no valid CRL found");
1394: }
1395: }
1396: }
|