package org.bouncycastle.cert.path.validations; import java.io.IOException; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Null; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509ContentVerifierProviderBuilder; import org.bouncycastle.cert.path.CertPathValidation; import org.bouncycastle.cert.path.CertPathValidationContext; import org.bouncycastle.cert.path.CertPathValidationException; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.util.Memoable; public class ParentCertIssuedValidation implements CertPathValidation { private X509ContentVerifierProviderBuilder contentVerifierProvider; private X500Name workingIssuerName; private SubjectPublicKeyInfo workingPublicKey; private AlgorithmIdentifier workingAlgId; public ParentCertIssuedValidation(X509ContentVerifierProviderBuilder contentVerifierProvider) { this.contentVerifierProvider = contentVerifierProvider; } public void validate(CertPathValidationContext context, X509CertificateHolder certificate) throws CertPathValidationException { if (workingIssuerName != null) { if (!workingIssuerName.equals(certificate.getIssuer())) { throw new CertPathValidationException("Certificate issue does not match parent"); } } if (workingPublicKey != null) { try { SubjectPublicKeyInfo validatingKeyInfo; if (workingPublicKey.getAlgorithm().equals(workingAlgId)) { validatingKeyInfo = workingPublicKey; } else { validatingKeyInfo = new SubjectPublicKeyInfo(workingAlgId, workingPublicKey.parsePublicKey()); } if (!certificate.isSignatureValid(contentVerifierProvider.build(validatingKeyInfo))) { throw new CertPathValidationException("Certificate signature not for public key in parent"); } } catch (OperatorCreationException e) { throw new CertPathValidationException("Unable to create verifier: " + e.getMessage(), e); } catch (CertException e) { throw new CertPathValidationException("Unable to validate signature: " + e.getMessage(), e); } catch (IOException e) { throw new CertPathValidationException("Unable to build public key: " + e.getMessage(), e); } } workingIssuerName = certificate.getSubject(); workingPublicKey = certificate.getSubjectPublicKeyInfo(); if (workingAlgId != null) { // check for inherited parameters if (workingPublicKey.getAlgorithm().getAlgorithm().equals(workingAlgId.getAlgorithm())) { if (!isNull(workingPublicKey.getAlgorithm().getParameters())) { workingAlgId = workingPublicKey.getAlgorithm(); } } else { workingAlgId = workingPublicKey.getAlgorithm(); } } else { workingAlgId = workingPublicKey.getAlgorithm(); } } private boolean isNull(ASN1Encodable obj) { return obj == null || obj instanceof ASN1Null; } public Memoable copy() { ParentCertIssuedValidation v = new ParentCertIssuedValidation(contentVerifierProvider); v.workingAlgId = this.workingAlgId; v.workingIssuerName = this.workingIssuerName; v.workingPublicKey = this.workingPublicKey; return v; } public void reset(Memoable other) { ParentCertIssuedValidation v = (ParentCertIssuedValidation)other; this.contentVerifierProvider = v.contentVerifierProvider; this.workingAlgId = v.workingAlgId; this.workingIssuerName = v.workingIssuerName; this.workingPublicKey = v.workingPublicKey; } }