/android/upstream/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
Java | 521 lines | 321 code | 79 blank | 121 comment | 40 complexity | 5a9fb72bd67793358351ea3ccac7a820 MD5 | raw file
- package org.bouncycastle.jce.provider;
- // BEGIN android-added
- import java.math.BigInteger;
- // END android-added
- import java.security.InvalidAlgorithmParameterException;
- import java.security.PublicKey;
- import java.security.cert.CertPath;
- import java.security.cert.CertPathParameters;
- import java.security.cert.CertPathValidatorException;
- import java.security.cert.CertPathValidatorResult;
- import java.security.cert.CertPathValidatorSpi;
- import java.security.cert.PKIXCertPathChecker;
- import java.security.cert.PKIXCertPathValidatorResult;
- import java.security.cert.PKIXParameters;
- import java.security.cert.TrustAnchor;
- import java.security.cert.X509Certificate;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Set;
- import javax.security.auth.x500.X500Principal;
- import org.bouncycastle.asn1.DEREncodable;
- import org.bouncycastle.asn1.DERObjectIdentifier;
- import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
- // BEGIN android-added
- import org.bouncycastle.crypto.Digest;
- import org.bouncycastle.crypto.digests.OpenSSLDigest;
- // END android-added
- import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
- import org.bouncycastle.x509.ExtendedPKIXParameters;
- /**
- * CertPathValidatorSpi implementation for X.509 Certificate validation � la RFC
- * 3280.
- */
- public class PKIXCertPathValidatorSpi
- extends CertPathValidatorSpi
- {
- // BEGIN android-added
- // From http://src.chromium.org/viewvc/chrome/trunk/src/net/base/x509_certificate.cc?revision=78748&view=markup
- private static final Set<BigInteger> SERIAL_BLACKLIST = new HashSet<BigInteger>(Arrays.asList(
- // Not a real certificate. For testing only.
- new BigInteger(1, new byte[] {(byte)0x07,(byte)0x7a,(byte)0x59,(byte)0xbc,(byte)0xd5,(byte)0x34,(byte)0x59,(byte)0x60,(byte)0x1c,(byte)0xa6,(byte)0x90,(byte)0x72,(byte)0x67,(byte)0xa6,(byte)0xdd,(byte)0x1c}),
- new BigInteger(1, new byte[] {(byte)0x04,(byte)0x7e,(byte)0xcb,(byte)0xe9,(byte)0xfc,(byte)0xa5,(byte)0x5f,(byte)0x7b,(byte)0xd0,(byte)0x9e,(byte)0xae,(byte)0x36,(byte)0xe1,(byte)0x0c,(byte)0xae,(byte)0x1e}),
- new BigInteger(1, new byte[] {(byte)0xd8,(byte)0xf3,(byte)0x5f,(byte)0x4e,(byte)0xb7,(byte)0x87,(byte)0x2b,(byte)0x2d,(byte)0xab,(byte)0x06,(byte)0x92,(byte)0xe3,(byte)0x15,(byte)0x38,(byte)0x2f,(byte)0xb0}),
- new BigInteger(1, new byte[] {(byte)0xb0,(byte)0xb7,(byte)0x13,(byte)0x3e,(byte)0xd0,(byte)0x96,(byte)0xf9,(byte)0xb5,(byte)0x6f,(byte)0xae,(byte)0x91,(byte)0xc8,(byte)0x74,(byte)0xbd,(byte)0x3a,(byte)0xc0}),
- new BigInteger(1, new byte[] {(byte)0x92,(byte)0x39,(byte)0xd5,(byte)0x34,(byte)0x8f,(byte)0x40,(byte)0xd1,(byte)0x69,(byte)0x5a,(byte)0x74,(byte)0x54,(byte)0x70,(byte)0xe1,(byte)0xf2,(byte)0x3f,(byte)0x43}),
- new BigInteger(1, new byte[] {(byte)0xe9,(byte)0x02,(byte)0x8b,(byte)0x95,(byte)0x78,(byte)0xe4,(byte)0x15,(byte)0xdc,(byte)0x1a,(byte)0x71,(byte)0x0a,(byte)0x2b,(byte)0x88,(byte)0x15,(byte)0x44,(byte)0x47}),
- new BigInteger(1, new byte[] {(byte)0xd7,(byte)0x55,(byte)0x8f,(byte)0xda,(byte)0xf5,(byte)0xf1,(byte)0x10,(byte)0x5b,(byte)0xb2,(byte)0x13,(byte)0x28,(byte)0x2b,(byte)0x70,(byte)0x77,(byte)0x29,(byte)0xa3}),
- new BigInteger(1, new byte[] {(byte)0xf5,(byte)0xc8,(byte)0x6a,(byte)0xf3,(byte)0x61,(byte)0x62,(byte)0xf1,(byte)0x3a,(byte)0x64,(byte)0xf5,(byte)0x4f,(byte)0x6d,(byte)0xc9,(byte)0x58,(byte)0x7c,(byte)0x06}),
- new BigInteger(1, new byte[] {(byte)0x39,(byte)0x2a,(byte)0x43,(byte)0x4f,(byte)0x0e,(byte)0x07,(byte)0xdf,(byte)0x1f,(byte)0x8a,(byte)0xa3,(byte)0x05,(byte)0xde,(byte)0x34,(byte)0xe0,(byte)0xc2,(byte)0x29}),
- new BigInteger(1, new byte[] {(byte)0x3e,(byte)0x75,(byte)0xce,(byte)0xd4,(byte)0x6b,(byte)0x69,(byte)0x30,(byte)0x21,(byte)0x21,(byte)0x88,(byte)0x30,(byte)0xae,(byte)0x86,(byte)0xa8,(byte)0x2a,(byte)0x71})
- ));
- // From http://src.chromium.org/viewvc/chrome/branches/782/src/net/base/x509_certificate.cc?r1=98750&r2=98749&pathrev=98750
- private static final byte[][] PUBLIC_KEY_SHA1_BLACKLIST = {
- // C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl
- {(byte)0x41, (byte)0x0f, (byte)0x36, (byte)0x36, (byte)0x32, (byte)0x58, (byte)0xf3, (byte)0x0b, (byte)0x34, (byte)0x7d,
- (byte)0x12, (byte)0xce, (byte)0x48, (byte)0x63, (byte)0xe4, (byte)0x33, (byte)0x43, (byte)0x78, (byte)0x06, (byte)0xa8},
- // Subject: CN=DigiNotar Cyber CA
- // Issuer: CN=GTE CyberTrust Global Root
- {(byte)0xba, (byte)0x3e, (byte)0x7b, (byte)0xd3, (byte)0x8c, (byte)0xd7, (byte)0xe1, (byte)0xe6, (byte)0xb9, (byte)0xcd,
- (byte)0x4c, (byte)0x21, (byte)0x99, (byte)0x62, (byte)0xe5, (byte)0x9d, (byte)0x7a, (byte)0x2f, (byte)0x4e, (byte)0x37},
- // Subject: CN=DigiNotar Services 1024 CA
- // Issuer: CN=Entrust.net
- {(byte)0xe2, (byte)0x3b, (byte)0x8d, (byte)0x10, (byte)0x5f, (byte)0x87, (byte)0x71, (byte)0x0a, (byte)0x68, (byte)0xd9,
- (byte)0x24, (byte)0x80, (byte)0x50, (byte)0xeb, (byte)0xef, (byte)0xc6, (byte)0x27, (byte)0xbe, (byte)0x4c, (byte)0xa6},
- // Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2
- // Issuer: CN=Staat der Nederlanden Organisatie CA - G2
- {(byte)0x7b, (byte)0x2e, (byte)0x16, (byte)0xbc, (byte)0x39, (byte)0xbc, (byte)0xd7, (byte)0x2b, (byte)0x45, (byte)0x6e,
- (byte)0x9f, (byte)0x05, (byte)0x5d, (byte)0x1d, (byte)0xe6, (byte)0x15, (byte)0xb7, (byte)0x49, (byte)0x45, (byte)0xdb},
- // Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven
- // Issuer: CN=Staat der Nederlanden Overheid CA
- {(byte)0xe8, (byte)0xf9, (byte)0x12, (byte)0x00, (byte)0xc6, (byte)0x5c, (byte)0xee, (byte)0x16, (byte)0xe0, (byte)0x39,
- (byte)0xb9, (byte)0xf8, (byte)0x83, (byte)0x84, (byte)0x16, (byte)0x61, (byte)0x63, (byte)0x5f, (byte)0x81, (byte)0xc5},
- };
- private static boolean isPublicKeyBlackListed(PublicKey publicKey) {
- byte[] encoded = publicKey.getEncoded();
- Digest digest = new OpenSSLDigest.SHA1();
- digest.update(encoded, 0, encoded.length);
- byte[] out = new byte[digest.getDigestSize()];
- digest.doFinal(out, 0);
- for (byte[] sha1 : PUBLIC_KEY_SHA1_BLACKLIST) {
- if (Arrays.equals(out, sha1)) {
- return true;
- }
- }
- return false;
- }
- // END android-added
- public CertPathValidatorResult engineValidate(
- CertPath certPath,
- CertPathParameters params)
- throws CertPathValidatorException,
- InvalidAlgorithmParameterException
- {
- if (!(params instanceof PKIXParameters))
- {
- throw new InvalidAlgorithmParameterException("Parameters must be a " + PKIXParameters.class.getName()
- + " instance.");
- }
- ExtendedPKIXParameters paramsPKIX;
- if (params instanceof ExtendedPKIXParameters)
- {
- paramsPKIX = (ExtendedPKIXParameters)params;
- }
- else
- {
- paramsPKIX = ExtendedPKIXParameters.getInstance((PKIXParameters)params);
- }
- if (paramsPKIX.getTrustAnchors() == null)
- {
- throw new InvalidAlgorithmParameterException(
- "trustAnchors is null, this is not allowed for certification path validation.");
- }
- //
- // 6.1.1 - inputs
- //
- //
- // (a)
- //
- List certs = certPath.getCertificates();
- int n = certs.size();
- if (certs.isEmpty())
- {
- throw new CertPathValidatorException("Certification path is empty.", null, certPath, 0);
- }
- // BEGIN android-added
- {
- X509Certificate cert = (X509Certificate) certs.get(0);
- if (cert != null) {
- BigInteger serial = cert.getSerialNumber();
- if (serial != null && SERIAL_BLACKLIST.contains(serial)) {
- // emulate CRL exception message in RFC3280CertPathUtilities.checkCRLs
- String message = "Certificate revocation of serial 0x" + serial.toString(16);
- System.out.println(message);
- AnnotatedException e = new AnnotatedException(message);
- throw new CertPathValidatorException(e.getMessage(), e, certPath, 0);
- }
- }
- }
- // END android-added
- //
- // (b)
- //
- // Date validDate = CertPathValidatorUtilities.getValidDate(paramsPKIX);
- //
- // (c)
- //
- Set userInitialPolicySet = paramsPKIX.getInitialPolicies();
- //
- // (d)
- //
- TrustAnchor trust;
- try
- {
- trust = CertPathValidatorUtilities.findTrustAnchor((X509Certificate) certs.get(certs.size() - 1),
- paramsPKIX.getTrustAnchors(), paramsPKIX.getSigProvider());
- }
- catch (AnnotatedException e)
- {
- throw new CertPathValidatorException(e.getMessage(), e, certPath, certs.size() - 1);
- }
- if (trust == null)
- {
- throw new CertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
- }
- //
- // (e), (f), (g) are part of the paramsPKIX object.
- //
- Iterator certIter;
- int index = 0;
- int i;
- // Certificate for each interation of the validation loop
- // Signature information for each iteration of the validation loop
- //
- // 6.1.2 - setup
- //
- //
- // (a)
- //
- List[] policyNodes = new ArrayList[n + 1];
- for (int j = 0; j < policyNodes.length; j++)
- {
- policyNodes[j] = new ArrayList();
- }
- Set policySet = new HashSet();
- policySet.add(RFC3280CertPathUtilities.ANY_POLICY);
- PKIXPolicyNode validPolicyTree = new PKIXPolicyNode(new ArrayList(), 0, policySet, null, new HashSet(),
- RFC3280CertPathUtilities.ANY_POLICY, false);
- policyNodes[0].add(validPolicyTree);
- //
- // (b) and (c)
- //
- PKIXNameConstraintValidator nameConstraintValidator = new PKIXNameConstraintValidator();
- // (d)
- //
- int explicitPolicy;
- Set acceptablePolicies = new HashSet();
- if (paramsPKIX.isExplicitPolicyRequired())
- {
- explicitPolicy = 0;
- }
- else
- {
- explicitPolicy = n + 1;
- }
- //
- // (e)
- //
- int inhibitAnyPolicy;
- if (paramsPKIX.isAnyPolicyInhibited())
- {
- inhibitAnyPolicy = 0;
- }
- else
- {
- inhibitAnyPolicy = n + 1;
- }
- //
- // (f)
- //
- int policyMapping;
- if (paramsPKIX.isPolicyMappingInhibited())
- {
- policyMapping = 0;
- }
- else
- {
- policyMapping = n + 1;
- }
- //
- // (g), (h), (i), (j)
- //
- PublicKey workingPublicKey;
- X500Principal workingIssuerName;
- X509Certificate sign = trust.getTrustedCert();
- try
- {
- if (sign != null)
- {
- workingIssuerName = CertPathValidatorUtilities.getSubjectPrincipal(sign);
- workingPublicKey = sign.getPublicKey();
- }
- else
- {
- workingIssuerName = new X500Principal(trust.getCAName());
- workingPublicKey = trust.getCAPublicKey();
- }
- }
- catch (IllegalArgumentException ex)
- {
- throw new ExtCertPathValidatorException("Subject of trust anchor could not be (re)encoded.", ex, certPath,
- -1);
- }
- AlgorithmIdentifier workingAlgId = null;
- try
- {
- workingAlgId = CertPathValidatorUtilities.getAlgorithmIdentifier(workingPublicKey);
- }
- catch (CertPathValidatorException e)
- {
- throw new ExtCertPathValidatorException(
- "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
- }
- DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId();
- DEREncodable workingPublicKeyParameters = workingAlgId.getParameters();
- //
- // (k)
- //
- int maxPathLength = n;
- //
- // 6.1.3
- //
- if (paramsPKIX.getTargetConstraints() != null
- && !paramsPKIX.getTargetConstraints().match((X509Certificate) certs.get(0)))
- {
- throw new ExtCertPathValidatorException(
- "Target certificate in certification path does not match targetConstraints.", null, certPath, 0);
- }
- //
- // initialize CertPathChecker's
- //
- List pathCheckers = paramsPKIX.getCertPathCheckers();
- certIter = pathCheckers.iterator();
- while (certIter.hasNext())
- {
- ((PKIXCertPathChecker) certIter.next()).init(false);
- }
- X509Certificate cert = null;
- for (index = certs.size() - 1; index >= 0; index--)
- {
- // BEGIN android-added
- if (isPublicKeyBlackListed(workingPublicKey)) {
- // emulate CRL exception message in RFC3280CertPathUtilities.checkCRLs
- String message = "Certificate revocation of public key " + workingPublicKey;
- System.out.println(message);
- AnnotatedException e = new AnnotatedException(message);
- throw new CertPathValidatorException(e.getMessage(), e, certPath, index);
- }
- // END android-added
- // try
- // {
- //
- // i as defined in the algorithm description
- //
- i = n - index;
- //
- // set certificate to be checked in this round
- // sign and workingPublicKey and workingIssuerName are set
- // at the end of the for loop and initialized the
- // first time from the TrustAnchor
- //
- cert = (X509Certificate) certs.get(index);
- boolean verificationAlreadyPerformed = (index == certs.size() - 1);
- //
- // 6.1.3
- //
- RFC3280CertPathUtilities.processCertA(certPath, paramsPKIX, index, workingPublicKey,
- verificationAlreadyPerformed, workingIssuerName, sign);
- RFC3280CertPathUtilities.processCertBC(certPath, index, nameConstraintValidator);
- validPolicyTree = RFC3280CertPathUtilities.processCertD(certPath, index, acceptablePolicies,
- validPolicyTree, policyNodes, inhibitAnyPolicy);
- validPolicyTree = RFC3280CertPathUtilities.processCertE(certPath, index, validPolicyTree);
- RFC3280CertPathUtilities.processCertF(certPath, index, validPolicyTree, explicitPolicy);
- //
- // 6.1.4
- //
- if (i != n)
- {
- if (cert != null && cert.getVersion() == 1)
- {
- throw new CertPathValidatorException("Version 1 certificates can't be used as CA ones.", null,
- certPath, index);
- }
- RFC3280CertPathUtilities.prepareNextCertA(certPath, index);
- validPolicyTree = RFC3280CertPathUtilities.prepareCertB(certPath, index, policyNodes, validPolicyTree,
- policyMapping);
- RFC3280CertPathUtilities.prepareNextCertG(certPath, index, nameConstraintValidator);
- // (h)
- explicitPolicy = RFC3280CertPathUtilities.prepareNextCertH1(certPath, index, explicitPolicy);
- policyMapping = RFC3280CertPathUtilities.prepareNextCertH2(certPath, index, policyMapping);
- inhibitAnyPolicy = RFC3280CertPathUtilities.prepareNextCertH3(certPath, index, inhibitAnyPolicy);
- //
- // (i)
- //
- explicitPolicy = RFC3280CertPathUtilities.prepareNextCertI1(certPath, index, explicitPolicy);
- policyMapping = RFC3280CertPathUtilities.prepareNextCertI2(certPath, index, policyMapping);
- // (j)
- inhibitAnyPolicy = RFC3280CertPathUtilities.prepareNextCertJ(certPath, index, inhibitAnyPolicy);
- // (k)
- RFC3280CertPathUtilities.prepareNextCertK(certPath, index);
- // (l)
- maxPathLength = RFC3280CertPathUtilities.prepareNextCertL(certPath, index, maxPathLength);
- // (m)
- maxPathLength = RFC3280CertPathUtilities.prepareNextCertM(certPath, index, maxPathLength);
- // (n)
- RFC3280CertPathUtilities.prepareNextCertN(certPath, index);
- Set criticalExtensions = cert.getCriticalExtensionOIDs();
- if (criticalExtensions != null)
- {
- criticalExtensions = new HashSet(criticalExtensions);
- // these extensions are handled by the algorithm
- criticalExtensions.remove(RFC3280CertPathUtilities.KEY_USAGE);
- criticalExtensions.remove(RFC3280CertPathUtilities.CERTIFICATE_POLICIES);
- criticalExtensions.remove(RFC3280CertPathUtilities.POLICY_MAPPINGS);
- criticalExtensions.remove(RFC3280CertPathUtilities.INHIBIT_ANY_POLICY);
- criticalExtensions.remove(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT);
- criticalExtensions.remove(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR);
- criticalExtensions.remove(RFC3280CertPathUtilities.POLICY_CONSTRAINTS);
- criticalExtensions.remove(RFC3280CertPathUtilities.BASIC_CONSTRAINTS);
- criticalExtensions.remove(RFC3280CertPathUtilities.SUBJECT_ALTERNATIVE_NAME);
- criticalExtensions.remove(RFC3280CertPathUtilities.NAME_CONSTRAINTS);
- }
- else
- {
- criticalExtensions = new HashSet();
- }
- // (o)
- RFC3280CertPathUtilities.prepareNextCertO(certPath, index, criticalExtensions, pathCheckers);
-
- // set signing certificate for next round
- sign = cert;
- // (c)
- workingIssuerName = CertPathValidatorUtilities.getSubjectPrincipal(sign);
- // (d)
- try
- {
- workingPublicKey = CertPathValidatorUtilities.getNextWorkingKey(certPath.getCertificates(), index);
- }
- catch (CertPathValidatorException e)
- {
- throw new CertPathValidatorException("Next working key could not be retrieved.", e, certPath, index);
- }
- workingAlgId = CertPathValidatorUtilities.getAlgorithmIdentifier(workingPublicKey);
- // (f)
- workingPublicKeyAlgorithm = workingAlgId.getObjectId();
- // (e)
- workingPublicKeyParameters = workingAlgId.getParameters();
- }
- }
- //
- // 6.1.5 Wrap-up procedure
- //
- explicitPolicy = RFC3280CertPathUtilities.wrapupCertA(explicitPolicy, cert);
- explicitPolicy = RFC3280CertPathUtilities.wrapupCertB(certPath, index + 1, explicitPolicy);
- //
- // (c) (d) and (e) are already done
- //
- //
- // (f)
- //
- Set criticalExtensions = cert.getCriticalExtensionOIDs();
- if (criticalExtensions != null)
- {
- criticalExtensions = new HashSet(criticalExtensions);
- // these extensions are handled by the algorithm
- criticalExtensions.remove(RFC3280CertPathUtilities.KEY_USAGE);
- criticalExtensions.remove(RFC3280CertPathUtilities.CERTIFICATE_POLICIES);
- criticalExtensions.remove(RFC3280CertPathUtilities.POLICY_MAPPINGS);
- criticalExtensions.remove(RFC3280CertPathUtilities.INHIBIT_ANY_POLICY);
- criticalExtensions.remove(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT);
- criticalExtensions.remove(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR);
- criticalExtensions.remove(RFC3280CertPathUtilities.POLICY_CONSTRAINTS);
- criticalExtensions.remove(RFC3280CertPathUtilities.BASIC_CONSTRAINTS);
- criticalExtensions.remove(RFC3280CertPathUtilities.SUBJECT_ALTERNATIVE_NAME);
- criticalExtensions.remove(RFC3280CertPathUtilities.NAME_CONSTRAINTS);
- criticalExtensions.remove(RFC3280CertPathUtilities.CRL_DISTRIBUTION_POINTS);
- }
- else
- {
- criticalExtensions = new HashSet();
- }
- RFC3280CertPathUtilities.wrapupCertF(certPath, index + 1, pathCheckers, criticalExtensions);
- PKIXPolicyNode intersection = RFC3280CertPathUtilities.wrapupCertG(certPath, paramsPKIX, userInitialPolicySet,
- index + 1, policyNodes, validPolicyTree, acceptablePolicies);
- if ((explicitPolicy > 0) || (intersection != null))
- {
- return new PKIXCertPathValidatorResult(trust, intersection, cert.getPublicKey());
- }
- throw new CertPathValidatorException("Path processing failed on policy.", null, certPath, index);
- }
- }