0001: package org.bouncycastle.jce.provider;
0002:
0003: import org.bouncycastle.asn1.ASN1EncodableVector;
0004: import org.bouncycastle.asn1.ASN1InputStream;
0005: import org.bouncycastle.asn1.ASN1OctetString;
0006: import org.bouncycastle.asn1.ASN1OutputStream;
0007: import org.bouncycastle.asn1.ASN1Sequence;
0008: import org.bouncycastle.asn1.DEREncodable;
0009: import org.bouncycastle.asn1.DEREnumerated;
0010: import org.bouncycastle.asn1.DERGeneralizedTime;
0011: import org.bouncycastle.asn1.DERIA5String;
0012: import org.bouncycastle.asn1.DERObject;
0013: import org.bouncycastle.asn1.DERObjectIdentifier;
0014: import org.bouncycastle.asn1.DERSequence;
0015: import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
0016: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
0017: import org.bouncycastle.asn1.x509.CRLDistPoint;
0018: import org.bouncycastle.asn1.x509.CRLNumber;
0019: import org.bouncycastle.asn1.x509.CRLReason;
0020: import org.bouncycastle.asn1.x509.DistributionPoint;
0021: import org.bouncycastle.asn1.x509.DistributionPointName;
0022: import org.bouncycastle.asn1.x509.GeneralName;
0023: import org.bouncycastle.asn1.x509.GeneralNames;
0024: import org.bouncycastle.asn1.x509.PolicyInformation;
0025: import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
0026: import org.bouncycastle.asn1.x509.X509Extensions;
0027: import org.bouncycastle.jce.X509LDAPCertStoreParameters;
0028: import org.bouncycastle.util.Selector;
0029: import org.bouncycastle.util.StoreException;
0030: import org.bouncycastle.x509.ExtendedPKIXParameters;
0031: import org.bouncycastle.x509.X509AttributeCertificate;
0032: import org.bouncycastle.x509.X509CRLStoreSelector;
0033: import org.bouncycastle.x509.X509Store;
0034:
0035: import javax.security.auth.x500.X500Principal;
0036: import java.io.ByteArrayOutputStream;
0037: import java.io.IOException;
0038: import java.math.BigInteger;
0039: import java.security.KeyFactory;
0040: import java.security.PublicKey;
0041: import java.security.cert.CRL;
0042: import java.security.cert.CertPath;
0043: import java.security.cert.CertPathValidatorException;
0044: import java.security.cert.CertSelector;
0045: import java.security.cert.CertStore;
0046: import java.security.cert.CertStoreException;
0047: import java.security.cert.PKIXParameters;
0048: import java.security.cert.PolicyQualifierInfo;
0049: import java.security.cert.TrustAnchor;
0050: import java.security.cert.X509CRL;
0051: import java.security.cert.X509CRLEntry;
0052: import java.security.cert.X509CRLSelector;
0053: import java.security.cert.X509CertSelector;
0054: import java.security.cert.X509Certificate;
0055: import java.security.interfaces.DSAParams;
0056: import java.security.interfaces.DSAPublicKey;
0057: import java.security.spec.DSAPublicKeySpec;
0058: import java.text.ParseException;
0059: import java.util.ArrayList;
0060: import java.util.Collection;
0061: import java.util.Date;
0062: import java.util.Enumeration;
0063: import java.util.HashSet;
0064: import java.util.Iterator;
0065: import java.util.List;
0066: import java.util.Map;
0067: import java.util.Set;
0068:
0069: public class CertPathValidatorUtilities {
0070: protected static final String CERTIFICATE_POLICIES = X509Extensions.CertificatePolicies
0071: .getId();
0072: protected static final String BASIC_CONSTRAINTS = X509Extensions.BasicConstraints
0073: .getId();
0074: protected static final String POLICY_MAPPINGS = X509Extensions.PolicyMappings
0075: .getId();
0076: protected static final String SUBJECT_ALTERNATIVE_NAME = X509Extensions.SubjectAlternativeName
0077: .getId();
0078: protected static final String NAME_CONSTRAINTS = X509Extensions.NameConstraints
0079: .getId();
0080: protected static final String KEY_USAGE = X509Extensions.KeyUsage
0081: .getId();
0082: protected static final String INHIBIT_ANY_POLICY = X509Extensions.InhibitAnyPolicy
0083: .getId();
0084: protected static final String ISSUING_DISTRIBUTION_POINT = X509Extensions.IssuingDistributionPoint
0085: .getId();
0086: protected static final String DELTA_CRL_INDICATOR = X509Extensions.DeltaCRLIndicator
0087: .getId();
0088: protected static final String POLICY_CONSTRAINTS = X509Extensions.PolicyConstraints
0089: .getId();
0090: protected static final String FRESHEST_CRL = X509Extensions.FreshestCRL
0091: .getId();
0092: protected static final String CRL_DISTRIBUTION_POINTS = X509Extensions.CRLDistributionPoints
0093: .getId();
0094: protected static final String AUTHORITY_KEY_IDENTIFIER = X509Extensions.AuthorityKeyIdentifier
0095: .getId();
0096:
0097: protected static final String ANY_POLICY = "2.5.29.32.0";
0098:
0099: protected static final String CRL_NUMBER = X509Extensions.CRLNumber
0100: .getId();
0101:
0102: /*
0103: * key usage bits
0104: */
0105: protected static final int KEY_CERT_SIGN = 5;
0106: protected static final int CRL_SIGN = 6;
0107:
0108: protected static final String[] crlReasons = new String[] {
0109: "unspecified", "keyCompromise", "cACompromise",
0110: "affiliationChanged", "superseded", "cessationOfOperation",
0111: "certificateHold", "unknown", "removeFromCRL",
0112: "privilegeWithdrawn", "aACompromise" };
0113:
0114: /**
0115: * Search the given Set of TrustAnchor's for one that is the
0116: * issuer of the given X509 certificate.
0117: *
0118: * @param cert the X509 certificate
0119: * @param trustAnchors a Set of TrustAnchor's
0120: *
0121: * @return the <code>TrustAnchor</code> object if found or
0122: * <code>null</code> if not.
0123: *
0124: * @exception CertPathValidatorException if a TrustAnchor was
0125: * found but the signature verification on the given certificate
0126: * has thrown an exception. This Exception can be obtainted with
0127: * <code>getCause()</code> method.
0128: **/
0129: protected static final TrustAnchor findTrustAnchor(
0130: X509Certificate cert, CertPath certPath, int index,
0131: Set trustAnchors) throws CertPathValidatorException {
0132: Iterator iter = trustAnchors.iterator();
0133: TrustAnchor trust = null;
0134: PublicKey trustPublicKey = null;
0135: Exception invalidKeyEx = null;
0136:
0137: X509CertSelector certSelectX509 = new X509CertSelector();
0138:
0139: try {
0140: certSelectX509.setSubject(getEncodedIssuerPrincipal(cert)
0141: .getEncoded());
0142: } catch (IOException ex) {
0143: throw new CertPathValidatorException(ex);
0144: }
0145:
0146: while (iter.hasNext() && trust == null) {
0147: trust = (TrustAnchor) iter.next();
0148: if (trust.getTrustedCert() != null) {
0149: if (certSelectX509.match(trust.getTrustedCert())) {
0150: trustPublicKey = trust.getTrustedCert()
0151: .getPublicKey();
0152: } else {
0153: trust = null;
0154: }
0155: } else if (trust.getCAName() != null
0156: && trust.getCAPublicKey() != null) {
0157: try {
0158: X500Principal certIssuer = getEncodedIssuerPrincipal(cert);
0159: X500Principal caName = new X500Principal(trust
0160: .getCAName());
0161: if (certIssuer.equals(caName)) {
0162: trustPublicKey = trust.getCAPublicKey();
0163: } else {
0164: trust = null;
0165: }
0166: } catch (IllegalArgumentException ex) {
0167: trust = null;
0168: }
0169: } else {
0170: trust = null;
0171: }
0172:
0173: if (trustPublicKey != null) {
0174: try {
0175: cert.verify(trustPublicKey);
0176: } catch (Exception ex) {
0177: invalidKeyEx = ex;
0178: trust = null;
0179: }
0180: }
0181: }
0182:
0183: if (trust == null && invalidKeyEx != null) {
0184: throw new CertPathValidatorException(
0185: "TrustAnchor found but certificate validation failed.",
0186: invalidKeyEx, certPath, index);
0187: }
0188:
0189: return trust;
0190: }
0191:
0192: /**
0193: * Returns the issuer of an attribute certificate or certificate.
0194: * @param cert The attribute certificate or certificate.
0195: * @return The issuer as <code>X500Principal</code>.
0196: */
0197: protected static X500Principal getEncodedIssuerPrincipal(Object cert) {
0198: if (cert instanceof X509Certificate) {
0199: return ((X509Certificate) cert).getIssuerX500Principal();
0200: } else {
0201: return (X500Principal) ((X509AttributeCertificate) cert)
0202: .getIssuer().getPrincipals()[0];
0203: }
0204: }
0205:
0206: protected static Date getValidDate(PKIXParameters paramsPKIX) {
0207: Date validDate = paramsPKIX.getDate();
0208:
0209: if (validDate == null) {
0210: validDate = new Date();
0211: }
0212:
0213: return validDate;
0214: }
0215:
0216: protected static X500Principal getSubjectPrincipal(
0217: X509Certificate cert) {
0218: return cert.getSubjectX500Principal();
0219: }
0220:
0221: protected static boolean isSelfIssued(X509Certificate cert) {
0222: return cert.getSubjectDN().equals(cert.getIssuerDN());
0223: }
0224:
0225: /**
0226: * extract the value of the given extension, if it exists.
0227: */
0228: protected static DERObject getExtensionValue(
0229: java.security.cert.X509Extension ext, String oid)
0230: throws AnnotatedException {
0231: byte[] bytes = ext.getExtensionValue(oid);
0232: if (bytes == null) {
0233: return null;
0234: }
0235:
0236: return getObject(oid, bytes);
0237: }
0238:
0239: private static DERObject getObject(String oid, byte[] ext)
0240: throws AnnotatedException {
0241: try {
0242: ASN1InputStream aIn = new ASN1InputStream(ext);
0243: ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
0244:
0245: aIn = new ASN1InputStream(octs.getOctets());
0246: return aIn.readObject();
0247: } catch (IOException e) {
0248: throw new AnnotatedException(
0249: "exception processing extension " + oid, e);
0250: }
0251: }
0252:
0253: protected static X500Principal getIssuerPrincipal(X509CRL crl) {
0254: return crl.getIssuerX500Principal();
0255: }
0256:
0257: protected static AlgorithmIdentifier getAlgorithmIdentifier(
0258: PublicKey key) throws CertPathValidatorException {
0259: try {
0260: ASN1InputStream aIn = new ASN1InputStream(key.getEncoded());
0261:
0262: SubjectPublicKeyInfo info = SubjectPublicKeyInfo
0263: .getInstance(aIn.readObject());
0264:
0265: return info.getAlgorithmId();
0266: } catch (IOException e) {
0267: throw new CertPathValidatorException(
0268: "exception processing public key");
0269: }
0270: }
0271:
0272: // crl checking
0273:
0274: /**
0275: * Return a Collection of all CRLs found in the
0276: * CertStore's that are matching the crlSelect criteriums.
0277: *
0278: * @param crlSelect a {@link CertSelector CertSelector}
0279: * object that will be used to select the CRLs
0280: * @param crlStores a List containing only {@link CertStore
0281: * CertStore} objects. These are used to search for
0282: * CRLs
0283: *
0284: * @return a Collection of all found {@link CRL CRL}
0285: * objects. May be empty but never <code>null</code>.
0286: */
0287: protected static final Collection findCRLs(
0288: X509CRLSelector crlSelect, List crlStores)
0289: throws AnnotatedException {
0290: Set crls = new HashSet();
0291: Iterator iter = crlStores.iterator();
0292:
0293: while (iter.hasNext()) {
0294: CertStore certStore = (CertStore) iter.next();
0295:
0296: try {
0297: crls.addAll(certStore.getCRLs(crlSelect));
0298: } catch (CertStoreException e) {
0299: throw new AnnotatedException(
0300: "cannot extract crl: " + e, e);
0301: }
0302: }
0303:
0304: return crls;
0305: }
0306:
0307: /**
0308: * Return a Collection of all CRLs found in the X509Store's that are
0309: * matching the crlSelect criteriums.
0310: *
0311: * @param crlSelect a {@link X509CRLStoreSelector} object that will be used
0312: * to select the CRLs
0313: * @param crlStores a List containing only
0314: * {@link org.bouncycastle.x509.X509Store X509Store} objects.
0315: * These are used to search for CRLs
0316: *
0317: * @return a Collection of all found {@link X509CRL X509CRL} objects. May be
0318: * empty but never <code>null</code>.
0319: */
0320: protected static final Collection findCRLs(
0321: X509CRLStoreSelector crlSelect, List crlStores)
0322: throws AnnotatedException {
0323: Set crls = new HashSet();
0324: Iterator iter = crlStores.iterator();
0325:
0326: AnnotatedException lastException = null;
0327: boolean foundValidStore = false;
0328:
0329: while (iter.hasNext()) {
0330: X509Store store = (X509Store) iter.next();
0331:
0332: try {
0333: crls.addAll(store.getMatches(crlSelect));
0334: foundValidStore = true;
0335: } catch (StoreException e) {
0336: lastException = new AnnotatedException(
0337: "Exception searching in X.509 CRL store.", e);
0338: }
0339: }
0340: if (!foundValidStore && lastException != null) {
0341: throw lastException;
0342: }
0343: return crls;
0344: }
0345:
0346: //
0347: // policy checking
0348: //
0349:
0350: protected static final Set getQualifierSet(ASN1Sequence qualifiers)
0351: throws CertPathValidatorException {
0352: Set pq = new HashSet();
0353:
0354: if (qualifiers == null) {
0355: return pq;
0356: }
0357:
0358: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
0359: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
0360:
0361: Enumeration e = qualifiers.getObjects();
0362:
0363: while (e.hasMoreElements()) {
0364: try {
0365: aOut.writeObject(e.nextElement());
0366:
0367: pq.add(new PolicyQualifierInfo(bOut.toByteArray()));
0368: } catch (IOException ex) {
0369: throw new CertPathValidatorException(
0370: "exception building qualifier set: " + ex);
0371: }
0372:
0373: bOut.reset();
0374: }
0375:
0376: return pq;
0377: }
0378:
0379: protected static PKIXPolicyNode removePolicyNode(
0380: PKIXPolicyNode validPolicyTree, List[] policyNodes,
0381: PKIXPolicyNode _node) {
0382: PKIXPolicyNode _parent = (PKIXPolicyNode) _node.getParent();
0383:
0384: if (validPolicyTree == null) {
0385: return null;
0386: }
0387:
0388: if (_parent == null) {
0389: for (int j = 0; j < policyNodes.length; j++) {
0390: policyNodes[j] = new ArrayList();
0391: }
0392:
0393: return null;
0394: } else {
0395: _parent.removeChild(_node);
0396: removePolicyNodeRecurse(policyNodes, _node);
0397:
0398: return validPolicyTree;
0399: }
0400: }
0401:
0402: private static void removePolicyNodeRecurse(List[] policyNodes,
0403: PKIXPolicyNode _node) {
0404: policyNodes[_node.getDepth()].remove(_node);
0405:
0406: if (_node.hasChildren()) {
0407: Iterator _iter = _node.getChildren();
0408: while (_iter.hasNext()) {
0409: PKIXPolicyNode _child = (PKIXPolicyNode) _iter.next();
0410: removePolicyNodeRecurse(policyNodes, _child);
0411: }
0412: }
0413: }
0414:
0415: protected static boolean processCertD1i(int index,
0416: List[] policyNodes, DERObjectIdentifier pOid, Set pq) {
0417: List policyNodeVec = policyNodes[index - 1];
0418:
0419: for (int j = 0; j < policyNodeVec.size(); j++) {
0420: PKIXPolicyNode node = (PKIXPolicyNode) policyNodeVec.get(j);
0421: Set expectedPolicies = node.getExpectedPolicies();
0422:
0423: if (expectedPolicies.contains(pOid.getId())) {
0424: Set childExpectedPolicies = new HashSet();
0425: childExpectedPolicies.add(pOid.getId());
0426:
0427: PKIXPolicyNode child = new PKIXPolicyNode(
0428: new ArrayList(), index, childExpectedPolicies,
0429: node, pq, pOid.getId(), false);
0430: node.addChild(child);
0431: policyNodes[index].add(child);
0432:
0433: return true;
0434: }
0435: }
0436:
0437: return false;
0438: }
0439:
0440: protected static void processCertD1ii(int index,
0441: List[] policyNodes, DERObjectIdentifier _poid, Set _pq) {
0442: List policyNodeVec = policyNodes[index - 1];
0443:
0444: for (int j = 0; j < policyNodeVec.size(); j++) {
0445: PKIXPolicyNode _node = (PKIXPolicyNode) policyNodeVec
0446: .get(j);
0447: Set _expectedPolicies = _node.getExpectedPolicies();
0448:
0449: if (ANY_POLICY.equals(_node.getValidPolicy())) {
0450: Set _childExpectedPolicies = new HashSet();
0451: _childExpectedPolicies.add(_poid.getId());
0452:
0453: PKIXPolicyNode _child = new PKIXPolicyNode(
0454: new ArrayList(), index, _childExpectedPolicies,
0455: _node, _pq, _poid.getId(), false);
0456: _node.addChild(_child);
0457: policyNodes[index].add(_child);
0458: return;
0459: }
0460: }
0461: }
0462:
0463: protected static void prepareNextCertB1(int i, List[] policyNodes,
0464: String id_p, Map m_idp, X509Certificate cert)
0465: throws AnnotatedException, CertPathValidatorException {
0466: boolean idp_found = false;
0467: Iterator nodes_i = policyNodes[i].iterator();
0468: while (nodes_i.hasNext()) {
0469: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i.next();
0470: if (node.getValidPolicy().equals(id_p)) {
0471: idp_found = true;
0472: node.expectedPolicies = (Set) m_idp.get(id_p);
0473: break;
0474: }
0475: }
0476:
0477: if (!idp_found) {
0478: nodes_i = policyNodes[i].iterator();
0479: while (nodes_i.hasNext()) {
0480: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i.next();
0481: if (ANY_POLICY.equals(node.getValidPolicy())) {
0482: Set pq = null;
0483: ASN1Sequence policies = (ASN1Sequence) getExtensionValue(
0484: cert, CERTIFICATE_POLICIES);
0485: Enumeration e = policies.getObjects();
0486: while (e.hasMoreElements()) {
0487: PolicyInformation pinfo = PolicyInformation
0488: .getInstance(e.nextElement());
0489: if (ANY_POLICY.equals(pinfo
0490: .getPolicyIdentifier().getId())) {
0491: pq = getQualifierSet(pinfo
0492: .getPolicyQualifiers());
0493: break;
0494: }
0495: }
0496: boolean ci = false;
0497: if (cert.getCriticalExtensionOIDs() != null) {
0498: ci = cert.getCriticalExtensionOIDs().contains(
0499: CERTIFICATE_POLICIES);
0500: }
0501:
0502: PKIXPolicyNode p_node = (PKIXPolicyNode) node
0503: .getParent();
0504: if (ANY_POLICY.equals(p_node.getValidPolicy())) {
0505: PKIXPolicyNode c_node = new PKIXPolicyNode(
0506: new ArrayList(), i, (Set) m_idp
0507: .get(id_p), p_node, pq, id_p,
0508: ci);
0509: p_node.addChild(c_node);
0510: policyNodes[i].add(c_node);
0511: }
0512: break;
0513: }
0514: }
0515: }
0516: }
0517:
0518: protected static PKIXPolicyNode prepareNextCertB2(int i,
0519: List[] policyNodes, String id_p,
0520: PKIXPolicyNode validPolicyTree) {
0521: Iterator nodes_i = policyNodes[i].iterator();
0522: while (nodes_i.hasNext()) {
0523: PKIXPolicyNode node = (PKIXPolicyNode) nodes_i.next();
0524: if (node.getValidPolicy().equals(id_p)) {
0525: PKIXPolicyNode p_node = (PKIXPolicyNode) node
0526: .getParent();
0527: p_node.removeChild(node);
0528: nodes_i.remove();
0529: for (int k = (i - 1); k >= 0; k--) {
0530: List nodes = policyNodes[k];
0531: for (int l = 0; l < nodes.size(); l++) {
0532: PKIXPolicyNode node2 = (PKIXPolicyNode) nodes
0533: .get(l);
0534: if (!node2.hasChildren()) {
0535: validPolicyTree = removePolicyNode(
0536: validPolicyTree, policyNodes, node2);
0537: if (validPolicyTree == null) {
0538: break;
0539: }
0540: }
0541: }
0542: }
0543: }
0544: }
0545: return validPolicyTree;
0546: }
0547:
0548: protected static boolean isAnyPolicy(Set policySet) {
0549: return policySet == null || policySet.contains(ANY_POLICY)
0550: || policySet.isEmpty();
0551: }
0552:
0553: protected static void addAdditionalStoreFromLocation(
0554: String location, ExtendedPKIXParameters pkixParams) {
0555: if (pkixParams.isAdditionalLocationsEnabled()) {
0556: try {
0557: if (location.startsWith("ldap://")) {
0558: // ldap://directory.d-trust.net/CN=D-TRUST
0559: // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
0560: // skip "ldap://"
0561: location = location.substring(7);
0562: // after first / baseDN starts
0563: String base = null;
0564: String url = null;
0565: if (location.indexOf("/") != -1) {
0566: base = location
0567: .substring(location.indexOf("/"));
0568: // URL
0569: url = "ldap://"
0570: + location.substring(0, location
0571: .indexOf("/"));
0572: } else {
0573: url = "ldap://" + location;
0574: }
0575: // use all purpose parameters
0576: X509LDAPCertStoreParameters params = new X509LDAPCertStoreParameters.Builder(
0577: url, base).build();
0578: pkixParams.addAddionalStore(X509Store.getInstance(
0579: "CERTIFICATE/LDAP", params, "BC"));
0580: pkixParams.addAddionalStore(X509Store.getInstance(
0581: "CRL/LDAP", params, "BC"));
0582: pkixParams.addAddionalStore(X509Store.getInstance(
0583: "ATTRIBUTECERTIFICATE/LDAP", params, "BC"));
0584: pkixParams.addAddionalStore(X509Store.getInstance(
0585: "CERTIFICATEPAIR/LDAP", params, "BC"));
0586: }
0587: } catch (Exception e) {
0588: // cannot happen
0589: throw new RuntimeException(
0590: "Exception adding X.509 stores.");
0591: }
0592: }
0593: }
0594:
0595: /**
0596: * Return a Collection of all certificates found in the CertStore's that are
0597: * matching the certSelect criteriums.
0598: *
0599: * @param certSelect a {@link CertSelector CertSelector} object that will
0600: * be used to select the certificates
0601: * @param certStores a List containing only {@link CertStore CertStore}
0602: * objects. These are used to search for certificates
0603: *
0604: * @return a Collection of all found {@link java.security.cert.Certificate Certificate}
0605: * objects. May be empty but never <code>null</code>.
0606: */
0607: protected static Collection findCertificates(
0608: CertSelector certSelect, List certStores)
0609: throws AnnotatedException {
0610: Set certs = new HashSet();
0611: Iterator iter = certStores.iterator();
0612:
0613: while (iter.hasNext()) {
0614: CertStore certStore = (CertStore) iter.next();
0615:
0616: try {
0617: certs.addAll(certStore.getCertificates(certSelect));
0618: } catch (CertStoreException e) {
0619: throw
0620:
0621: new AnnotatedException(
0622: "Problem while picking certificates from certificate store.",
0623: e);
0624: }
0625: }
0626:
0627: return certs;
0628: }
0629:
0630: /**
0631: * Return a Collection of all certificates or attribute certificates found
0632: * in the X509Store's that are matching the certSelect criteriums.
0633: *
0634: * @param certSelect a {@link Selector} object that will be used to select
0635: * the certificates
0636: * @param certStores a List containing only {@link X509Store} objects. These
0637: * are used to search for certificates.
0638: *
0639: * @return a Collection of all found {@link X509Certificate} or
0640: * {@link org.bouncycastle.x509.X509AttributeCertificate} objects.
0641: * May be empty but never <code>null</code>.
0642: */
0643: protected static Collection findCertificates(Selector certSelect,
0644: List certStores) throws AnnotatedException {
0645: Set certs = new HashSet();
0646: Iterator iter = certStores.iterator();
0647:
0648: while (iter.hasNext()) {
0649: X509Store certStore = (X509Store) iter.next();
0650: try {
0651: certs.addAll(certStore.getMatches(certSelect));
0652: } catch (StoreException e) {
0653: throw
0654:
0655: new AnnotatedException(
0656: "Problem while picking certificates from X.509 store.",
0657: e);
0658: }
0659: }
0660: return certs;
0661: }
0662:
0663: protected static void addAdditionalStoresFromCRLDistributionPoint(
0664: CRLDistPoint crldp, ExtendedPKIXParameters pkixParams)
0665: throws AnnotatedException {
0666: if (crldp != null) {
0667: DistributionPoint dps[] = null;
0668: try {
0669: dps = crldp.getDistributionPoints();
0670: } catch (Exception e) {
0671: throw new AnnotatedException(
0672: "Distribution points could not be read.", e);
0673: }
0674: for (int i = 0; i < dps.length; i++) {
0675: DistributionPointName dpn = dps[i]
0676: .getDistributionPoint();
0677: // look for URIs in fullName
0678: if (dpn.getType() == DistributionPointName.FULL_NAME) {
0679: GeneralName[] genNames = GeneralNames.getInstance(
0680: dpn.getName()).getNames();
0681: // look for an URI
0682: for (int j = 0; j < genNames.length; j++) {
0683: if (genNames[j].getTagNo() == GeneralName.uniformResourceIdentifier) {
0684: String location = DERIA5String.getInstance(
0685: genNames[j].getName()).getString();
0686: CertPathValidatorUtilities
0687: .addAdditionalStoreFromLocation(
0688: location, pkixParams);
0689: }
0690: }
0691: }
0692: }
0693: }
0694: }
0695:
0696: /**
0697: * Add the CRL issuers from the cRLIssuer field of the distribution point or
0698: * from the certificate if not given to the issuer criterion of the
0699: * <code>selector</code>.
0700: * <p>
0701: * The <code>issuerPrincipals</code> are a collection with a single
0702: * <code>X500Principal</code> for <code>X509Certificate</code>s. For
0703: * {@link X509AttributeCertificate}s the issuer may contain more than one
0704: * <code>X500Principal</code>.
0705: *
0706: * @param dp The distribution point.
0707: * @param issuerPrincipals The issuers of the certificate or atribute
0708: * certificate which contains the distribution point.
0709: * @param selector The CRL selector.
0710: * @param pkixParams The PKIX parameters containing the cert stores.
0711: * @throws AnnotatedException if an exception occurs while processing.
0712: * @throws ClassCastException if <code>issuerPrincipals</code> does not
0713: * contain only <code>X500Principal</code>s.
0714: */
0715: protected static void getCRLIssuersFromDistributionPoint(
0716: DistributionPoint dp, Collection issuerPrincipals,
0717: X509CRLStoreSelector selector,
0718: ExtendedPKIXParameters pkixParams)
0719: throws AnnotatedException {
0720: List issuers = new ArrayList();
0721: // indirect CRL
0722: if (dp.getCRLIssuer() != null) {
0723: GeneralName genNames[] = dp.getCRLIssuer().getNames();
0724: // look for a DN
0725: for (int j = 0; j < genNames.length; j++) {
0726: if (genNames[j].getTagNo() == GeneralName.directoryName) {
0727: try {
0728: issuers
0729: .add(new X500Principal(genNames[j]
0730: .getName().getDERObject()
0731: .getEncoded()));
0732: } catch (IOException e) {
0733: throw new AnnotatedException(
0734: "CRL issuer information from distribution point cannot be decoded.",
0735: e);
0736: }
0737: }
0738: }
0739: } else {
0740: /*
0741: * certificate issuer is CRL issuer, distributionPoint field MUST be
0742: * present.
0743: */
0744: if (dp.getDistributionPoint() == null) {
0745: throw new AnnotatedException(
0746: "CRL issuer is omitted from distribution point but no distributionPoint field present.");
0747: }
0748: // add and check issuer principals
0749: for (Iterator it = issuerPrincipals.iterator(); it
0750: .hasNext();) {
0751: issuers.add((X500Principal) it.next());
0752: }
0753: }
0754: // distributionPoint
0755: if (dp.getDistributionPoint() != null) {
0756: // look for nameRelativeToCRLIssuer
0757: if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER) {
0758: // append fragment to issuer, only one
0759: // issuer can be there, if this is given
0760: if (issuers.size() != 1) {
0761: throw new AnnotatedException(
0762: "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
0763: }
0764: DEREncodable relName = dp.getDistributionPoint()
0765: .getName();
0766: Iterator it = issuers.iterator();
0767: List issuersTemp = new ArrayList(issuers.size());
0768: while (it.hasNext()) {
0769: Enumeration e = null;
0770: try {
0771: e = ASN1Sequence.getInstance(
0772: new ASN1InputStream(((X500Principal) it
0773: .next()).getEncoded())
0774: .readObject()).getObjects();
0775: } catch (IOException ex) {
0776: throw new AnnotatedException(
0777: "Cannot decode CRL issuer information.",
0778: ex);
0779: }
0780: ASN1EncodableVector v = new ASN1EncodableVector();
0781: while (e.hasMoreElements()) {
0782: v.add((DEREncodable) e.nextElement());
0783: }
0784: v.add(relName);
0785: issuersTemp.add(new X500Principal(
0786: new DERSequence(v).getDEREncoded()));
0787: }
0788: issuers.clear();
0789: issuers.addAll(issuersTemp);
0790: }
0791: }
0792: Iterator it = issuers.iterator();
0793: while (it.hasNext()) {
0794: try {
0795: selector.addIssuerName(((X500Principal) it.next())
0796: .getEncoded());
0797: } catch (IOException ex) {
0798: throw new AnnotatedException(
0799: "Cannot decode CRL issuer information.", ex);
0800: }
0801: }
0802: }
0803:
0804: protected static void getCertStatus(Date validDate, X509CRL crl,
0805: BigInteger serialNumber, CertStatus certStatus)
0806: throws AnnotatedException {
0807: // (i) or (j)
0808: // TODO: If two certificates from different issuers in indirect CRLs have
0809: // the same serial number ...
0810: X509CRLEntry crl_entry = crl
0811: .getRevokedCertificate(serialNumber);
0812: if (crl_entry != null) {
0813: DEREnumerated reasonCode = null;
0814: if (crl_entry.hasExtensions()) {
0815: try {
0816: reasonCode = DEREnumerated
0817: .getInstance(CertPathValidatorUtilities
0818: .getExtensionValue(crl_entry,
0819: X509Extensions.ReasonCode
0820: .getId()));
0821: } catch (Exception e) {
0822: new AnnotatedException(
0823: "Reason code CRL entry extension could not be decoded.",
0824: e);
0825: }
0826: }
0827:
0828: // for reason keyCompromise, caCompromise, aACompromise or
0829: // unspecified
0830: if (!(validDate.getTime() < crl_entry.getRevocationDate()
0831: .getTime())
0832: || reasonCode == null
0833: || reasonCode.getValue().intValue() == 0
0834: || reasonCode.getValue().intValue() == 1
0835: || reasonCode.getValue().intValue() == 2
0836: || reasonCode.getValue().intValue() == 8) {
0837:
0838: // (i) or (j) (1)
0839: if (reasonCode != null) {
0840: certStatus.setCertStatus(reasonCode.getValue()
0841: .intValue());
0842: }
0843: // (i) or (j) (2)
0844: else {
0845: certStatus.setCertStatus(CRLReason.unspecified);
0846: }
0847: certStatus.setRevocationDate(crl_entry
0848: .getRevocationDate());
0849: }
0850: }
0851: }
0852:
0853: /**
0854: * Fetches delta CRLs according to RFC 3280 section 5.2.4.
0855: *
0856: * @param currentDate The date for which the delta CRLs must be valid.
0857: * @param paramsPKIX The extended PKIX parameters.
0858: * @param completeCRL The complete CRL the delta CRL is for.
0859: * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
0860: * @throws AnnotatedException if an exception occurs while picking the delta
0861: * CRLs or no delta CRLs are found.
0862: */
0863: protected static Set getDeltaCRLs(Date currentDate,
0864: ExtendedPKIXParameters paramsPKIX, X509CRL completeCRL)
0865: throws AnnotatedException {
0866:
0867: Set set = new HashSet();
0868:
0869: X509CRLStoreSelector deltaSelect = new X509CRLStoreSelector();
0870: deltaSelect.setDateAndTime(currentDate);
0871:
0872: // 5.2.4 (a)
0873: try {
0874: deltaSelect.addIssuerName(CertPathValidatorUtilities
0875: .getIssuerPrincipal(completeCRL).getEncoded());
0876: } catch (IOException e) {
0877: new AnnotatedException("Cannot extract issuer from CRL.", e);
0878: }
0879:
0880: BigInteger completeCRLNumber;
0881: try {
0882: completeCRLNumber = CRLNumber.getInstance(
0883: CertPathValidatorUtilities.getExtensionValue(
0884: completeCRL, CRL_NUMBER))
0885: .getPositiveValue();
0886: } catch (Exception e) {
0887: throw new AnnotatedException(
0888: "CRL number extension could not be extracted from CRL.",
0889: e);
0890: }
0891:
0892: // 5.2.4 (b)
0893: byte[] idp = null;
0894: try {
0895: idp = completeCRL
0896: .getExtensionValue(ISSUING_DISTRIBUTION_POINT);
0897: } catch (Exception e) {
0898: throw new AnnotatedException(
0899: "Issuing distribution point extension value could not be read.",
0900: e);
0901: }
0902: deltaSelect.setIssuingDistributionPoint(idp);
0903: deltaSelect.setIssuingDistributionPointEnabled(true);
0904:
0905: // 5.2.4 (c)
0906: deltaSelect.setMaxBaseCRLNumber(completeCRLNumber);
0907:
0908: // 5.2.4 (d)
0909:
0910: deltaSelect.setMinCRLNumber(completeCRLNumber.add(BigInteger
0911: .valueOf(1)));
0912:
0913: Set temp = new HashSet();
0914: // find delta CRLs
0915: try {
0916: temp.addAll(CertPathValidatorUtilities.findCRLs(
0917: deltaSelect, paramsPKIX.getAddionalStores()));
0918: temp.addAll(CertPathValidatorUtilities.findCRLs(
0919: deltaSelect, paramsPKIX.getStores()));
0920: } catch (AnnotatedException e) {
0921: throw new AnnotatedException(
0922: "Could not search for delta CRLs.", e);
0923: }
0924: if (set.isEmpty()) {
0925: throw new AnnotatedException("No delta CRLs found.");
0926: }
0927: return set;
0928: }
0929:
0930: /**
0931: * Fetches complete CRLs according to RFC 3280.
0932: *
0933: * @param dp The distribution point for which the complete CRL
0934: * @param cert The <code>X509Certificate</code> or
0935: * {@link org.bouncycastle.x509.X509AttributeCertificate} for
0936: * which the CRL should be searched.
0937: * @param currentDate The date for which the delta CRLs must be valid.
0938: * @param paramsPKIX The extended PKIX parameters.
0939: * @return A <code>Set</code> of <code>X509CRL</code>s with complete
0940: * CRLs.
0941: * @throws AnnotatedException if an exception occurs while picking the CRLs
0942: * or no CRLs are found.
0943: */
0944: protected static Set getCompleteCRLs(DistributionPoint dp,
0945: Object cert, Date currentDate,
0946: ExtendedPKIXParameters paramsPKIX)
0947: throws AnnotatedException {
0948: X509CRLStoreSelector crlselect = new X509CRLStoreSelector();
0949: try {
0950: Set issuers = new HashSet();
0951: if (cert instanceof X509AttributeCertificate) {
0952: issuers.add(((X509AttributeCertificate) cert)
0953: .getIssuer().getPrincipals()[0]);
0954: } else {
0955: issuers.add(((X509Certificate) cert)
0956: .getSubjectX500Principal());
0957: }
0958: CertPathValidatorUtilities
0959: .getCRLIssuersFromDistributionPoint(dp, issuers,
0960: crlselect, paramsPKIX);
0961: } catch (AnnotatedException e) {
0962: new AnnotatedException(
0963: "Could not get issuer information from distribution point.",
0964: e);
0965: }
0966: if (cert instanceof X509Certificate) {
0967: crlselect.setCertificateChecking((X509Certificate) cert);
0968: } else {
0969: crlselect
0970: .setAttrCertificateChecking((X509AttributeCertificate) cert);
0971: }
0972: crlselect.setDateAndTime(currentDate);
0973: crlselect.setCompleteCRLEnabled(true);
0974:
0975: Set crls = new HashSet();
0976: try {
0977: crls.addAll(CertPathValidatorUtilities.findCRLs(crlselect,
0978: paramsPKIX.getStores()));
0979: crls.addAll(CertPathValidatorUtilities.findCRLs(crlselect,
0980: paramsPKIX.getAddionalStores()));
0981: } catch (AnnotatedException e) {
0982: throw new AnnotatedException("Could not search for CRLs.",
0983: e);
0984: }
0985: if (crls.isEmpty()) {
0986: throw new AnnotatedException("No CRLs found.");
0987: }
0988: return crls;
0989: }
0990:
0991: protected static Date getValidCertDateFromValidityModel(
0992: ExtendedPKIXParameters paramsPKIX, CertPath certPath,
0993: int index) throws AnnotatedException {
0994: if (paramsPKIX.getValidityModel() == ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL) {
0995: // if end cert use given signing/encryption/... time
0996: if (index <= 0) {
0997: return CertPathValidatorUtilities
0998: .getValidDate(paramsPKIX);
0999: // else use time when previous cert was created
1000: } else {
1001: if (index - 1 == 0) {
1002: DERGeneralizedTime dateOfCertgen = null;
1003: try {
1004: dateOfCertgen = DERGeneralizedTime
1005: .getInstance(((X509Certificate) certPath
1006: .getCertificates().get(
1007: index - 1))
1008: .getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen
1009: .getId()));
1010: } catch (IllegalArgumentException e) {
1011: throw new AnnotatedException(
1012: "Date of cert gen extension could not be read.");
1013: }
1014: if (dateOfCertgen != null) {
1015: try {
1016: return dateOfCertgen.getDate();
1017: } catch (ParseException e) {
1018: throw new AnnotatedException(
1019: "Date from dat of cert gen extension could not be parsed.",
1020: e);
1021: }
1022: }
1023: return ((X509Certificate) certPath
1024: .getCertificates().get(index - 1))
1025: .getNotBefore();
1026: } else {
1027: return ((X509Certificate) certPath
1028: .getCertificates().get(index - 1))
1029: .getNotBefore();
1030: }
1031: }
1032: } else {
1033: return getValidDate(paramsPKIX);
1034: }
1035: }
1036:
1037: /**
1038: * Return the next working key inheriting DSA parameters if necessary.
1039: * <p>
1040: * This methods inherits DSA parameters from the indexed certificate or
1041: * previous certificates in the certificate chain to the returned
1042: * <code>PublicKey</code>. The list is searched upwards, meaning the end
1043: * certificate is at position 0 and previous certificates are following.
1044: * </p>
1045: * <p>
1046: * If the indexed certificate does not contain a DSA key this method simply
1047: * returns the public key. If the DSA key already contains DSA parameters
1048: * the key is also only returned.
1049: * </p>
1050: *
1051: * @param certs The certification path.
1052: * @param index The index of the certificate which contains the public key
1053: * which should be extended with DSA parameters.
1054: * @return The public key of the certificate in list position
1055: * <code>index</code> extended with DSA parameters if applicable.
1056: * @throws AnnotatedException if DSA parameters cannot be inherited.
1057: */
1058: protected static PublicKey getNextWorkingKey(X509Certificate cert,
1059: List certs, int index) throws CertPathValidatorException {
1060: PublicKey pubKey = cert.getPublicKey();
1061: if (!(pubKey instanceof DSAPublicKey)) {
1062: return pubKey;
1063: }
1064: DSAPublicKey dsaPubKey = (DSAPublicKey) pubKey;
1065: if (dsaPubKey.getParams() != null) {
1066: return dsaPubKey;
1067: }
1068: for (int i = index + 1; i < certs.size(); i++) {
1069: X509Certificate parentCert = (X509Certificate) certs.get(i);
1070: pubKey = parentCert.getPublicKey();
1071: if (!(pubKey instanceof DSAPublicKey)) {
1072: throw new CertPathValidatorException(
1073: "DSA parameters cannot be inherited from previous certificate.");
1074: }
1075: DSAPublicKey prevDSAPubKey = (DSAPublicKey) pubKey;
1076: if (prevDSAPubKey.getParams() == null) {
1077: continue;
1078: }
1079: DSAParams dsaParams = prevDSAPubKey.getParams();
1080: DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(
1081: dsaPubKey.getY(), dsaParams.getP(), dsaParams
1082: .getQ(), dsaParams.getG());
1083: try {
1084: KeyFactory keyFactory = KeyFactory.getInstance("DSA",
1085: "BC");
1086: return keyFactory.generatePublic(dsaPubKeySpec);
1087: } catch (Exception exception) {
1088: throw new CertPathValidatorException(exception);
1089: }
1090: }
1091: throw new CertPathValidatorException(
1092: "DSA parameters cannot be inherited from previous certificate.");
1093: }
1094: }
|