Search in sources :

Example 1 with CertificateVerificationException

use of io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException in project module-ballerina-http by ballerina-platform.

the class OCSPResponseBuilder method generateOcspResponse.

static OCSPResp generateOcspResponse(SSLConfig sslConfig, int cacheAllocatedSize, int cacheDelay) throws IOException, KeyStoreException, CertificateVerificationException, CertificateException {
    int cacheSize = Constants.CACHE_DEFAULT_ALLOCATED_SIZE;
    int cacheDelayMins = Constants.CACHE_DEFAULT_DELAY_MINS;
    if (cacheAllocatedSize != 0 && cacheAllocatedSize > Constants.CACHE_MIN_ALLOCATED_SIZE && cacheAllocatedSize < Constants.CACHE_MAX_ALLOCATED_SIZE) {
        cacheSize = cacheAllocatedSize;
    }
    if (cacheDelay != 0 && cacheDelay > Constants.CACHE_MIN_DELAY_MINS && cacheDelay < Constants.CACHE_MAX_DELAY_MINS) {
        cacheDelayMins = cacheDelay;
    }
    OCSPCache ocspCache = OCSPCache.getCache();
    ocspCache.init(cacheSize, cacheDelayMins);
    if (sslConfig.getKeyStore() != null) {
        KeyStore keyStore = getKeyStore(sslConfig.getKeyStore(), sslConfig.getKeyStorePass(), sslConfig.getTLSStoreType());
        if (keyStore != null) {
            getUserCerAndIssuer(keyStore);
        }
    } else {
        certList = getCertInfo(sslConfig);
        userCertificate = certList.get(0);
        issuer = certList.get(1);
    }
    List<String> locations;
    if (userCertificate == null) {
        throw new CertificateVerificationException("Could not get revocation status from OCSP.");
    } else {
        // If it is there, we don't need to get it from CA.
        if (ocspCache.getOCSPCacheValue(userCertificate.getSerialNumber()) != null) {
            return ocspCache.getOCSPCacheValue(userCertificate.getSerialNumber());
        } else {
            OCSPReq request;
            request = OCSPVerifier.generateOCSPRequest(issuer, userCertificate.getSerialNumber());
            locations = getAIALocations(userCertificate);
            return getOCSPResponse(locations, request, userCertificate, ocspCache);
        }
    }
}
Also used : OCSPCache(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.ocsp.OCSPCache) CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) OCSPReq(org.bouncycastle.cert.ocsp.OCSPReq) KeyStore(java.security.KeyStore)

Example 2 with CertificateVerificationException

use of io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException in project module-ballerina-http by ballerina-platform.

the class OCSPVerifier method checkRevocationStatus.

/**
 * Gets the revocation status (Good, Revoked or Unknown) of the given peer certificate.
 *
 * @param peerCert The certificate that needs to be validated.
 * @param issuerCert Needs to create OCSP request.
 * @return Revocation status of the peer certificate.
 * @throws CertificateVerificationException Occurs when it fails to verify the ocsp status of certificate.
 */
public RevocationStatus checkRevocationStatus(X509Certificate peerCert, X509Certificate issuerCert) throws CertificateVerificationException {
    // check cache. Check inside the cache, before calling CA.
    if (cache != null) {
        SingleResp resp = cache.getCacheValue(peerCert.getSerialNumber());
        if (resp != null) {
            // If cant be casted, we have used the wrong cache.
            RevocationStatus status = getRevocationStatus(resp);
            if (LOG.isInfoEnabled()) {
                LOG.info("OCSP response taken from cache.");
            }
            return status;
        }
    }
    OCSPReq request = generateOCSPRequest(issuerCert, peerCert.getSerialNumber());
    List<String> locations = getAIALocations(peerCert);
    OCSPResp ocspResponse = null;
    for (String serviceUrl : locations) {
        SingleResp[] responses;
        try {
            ocspResponse = getOCSPResponce(serviceUrl, request);
            if (OCSPResponseStatus.SUCCESSFUL != ocspResponse.getStatus()) {
                // Server didn't give the correct response.
                continue;
            }
            BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject();
            responses = (basicResponse == null) ? null : basicResponse.getResponses();
        } catch (Exception e) {
            continue;
        }
        if (responses != null && responses.length == 1) {
            SingleResp resp = responses[0];
            RevocationStatus status = getRevocationStatus(resp);
            if (cache != null) {
                cache.setCacheValue(ocspResponse, peerCert.getSerialNumber(), resp, request, serviceUrl);
            }
            return status;
        }
    }
    throw new CertificateVerificationException("Could not get revocation status from OCSP.");
}
Also used : CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) OCSPReq(org.bouncycastle.cert.ocsp.OCSPReq) BasicOCSPResp(org.bouncycastle.cert.ocsp.BasicOCSPResp) RevocationStatus(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.RevocationStatus) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) SingleResp(org.bouncycastle.cert.ocsp.SingleResp) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) OCSPException(org.bouncycastle.cert.ocsp.OCSPException) IOException(java.io.IOException) CertificateEncodingException(java.security.cert.CertificateEncodingException) OCSPResp(org.bouncycastle.cert.ocsp.OCSPResp) BasicOCSPResp(org.bouncycastle.cert.ocsp.BasicOCSPResp)

Example 3 with CertificateVerificationException

use of io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException in project module-ballerina-http by ballerina-platform.

the class OCSPVerifier method generateOCSPRequest.

/**
 * This method generates an OCSP Request to be sent to an OCSP authority access endpoint.
 *
 * @param issuerCert the Issuer's certificate of the peer certificate we are interested in.
 * @param serialNumber of the peer certificate.
 * @return generated OCSP request.
 * @throws CertificateVerificationException if any error occurs while generating ocsp request.
 */
public static OCSPReq generateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber) throws CertificateVerificationException {
    // Programatically adding Bouncy Castle as the security provider. So no need to manually set. Once the programme
    // is over security provider will also be removed.
    Security.addProvider(new BouncyCastleProvider());
    try {
        byte[] issuerCertEnc = issuerCert.getEncoded();
        X509CertificateHolder certificateHolder = new X509CertificateHolder(issuerCertEnc);
        DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(Constants.BOUNCY_CASTLE_PROVIDER).build();
        // CertID structure is used to uniquely identify certificates that are the subject of
        // an OCSP request or response and has an ASN.1 definition. CertID structure is defined in RFC 2560.
        CertificateID id = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), certificateHolder, serialNumber);
        // basic request generation with nonce.
        OCSPReqBuilder builder = new OCSPReqBuilder();
        builder.addRequest(id);
        // create details for nonce extension. The nonce extension is used to bind
        // a request to a response to prevent re-play attacks. As the name implies,
        // the nonce value is something that the client should only use once during a reasonably small period.
        BigInteger nonce = BigInteger.valueOf(System.currentTimeMillis());
        // to create the request Extension
        builder.setRequestExtensions(new Extensions(new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, new DEROctetString(nonce.toByteArray()))));
        return builder.build();
    } catch (OCSPException | OperatorCreationException | IOException | CertificateEncodingException e) {
        throw new CertificateVerificationException("Cannot generate OCSP Request with the given certificate", e);
    }
}
Also used : CertificateID(org.bouncycastle.cert.ocsp.CertificateID) CertificateEncodingException(java.security.cert.CertificateEncodingException) IOException(java.io.IOException) Extensions(org.bouncycastle.asn1.x509.Extensions) DEROctetString(org.bouncycastle.asn1.DEROctetString) Extension(org.bouncycastle.asn1.x509.Extension) DigestCalculatorProvider(org.bouncycastle.operator.DigestCalculatorProvider) CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) OCSPException(org.bouncycastle.cert.ocsp.OCSPException) X509CertificateHolder(org.bouncycastle.cert.X509CertificateHolder) BigInteger(java.math.BigInteger) JcaDigestCalculatorProviderBuilder(org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException) OCSPReqBuilder(org.bouncycastle.cert.ocsp.OCSPReqBuilder) BouncyCastleProvider(org.bouncycastle.jce.provider.BouncyCastleProvider)

Example 4 with CertificateVerificationException

use of io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException in project module-ballerina-http by ballerina-platform.

the class CRLVerifier method getCrlDistributionPoints.

/**
 * Extracts all CRL distribution point URLs from the "CRL Distribution Point"
 * extension in a X.509 certificate. If CRL distribution point extension is
 * unavailable, returns an empty list.
 */
private List<String> getCrlDistributionPoints(X509Certificate cert) throws CertificateVerificationException {
    // Gets the DER-encoded OCTET string for the extension value for CRLDistributionPoints.
    byte[] crlDPExtensionValue = cert.getExtensionValue(Extension.cRLDistributionPoints.getId());
    if (crlDPExtensionValue == null) {
        throw new CertificateVerificationException("Certificate doesn't have CRL distribution points");
    }
    // crlDPExtensionValue is encoded in ASN.1 format.
    ASN1InputStream asn1In = new ASN1InputStream(crlDPExtensionValue);
    // DER (Distinguished Encoding Rules) is one of ASN.1 encoding rules defined in ITU-T X.690, 2002, specification.
    // ASN.1 encoding rules can be used to encode any data object into a binary file. Read the object in octets.
    CRLDistPoint distPoint;
    try {
        DEROctetString crlDEROctetString = (DEROctetString) asn1In.readObject();
        // Get Input stream in octets.
        distPoint = getOctetInputStream(crlDEROctetString);
    } catch (IOException e) {
        throw new CertificateVerificationException("Cannot read certificate to get CRL URLs", e);
    } finally {
        try {
            asn1In.close();
        } catch (IOException e) {
            LOG.error("Cannot close input stream", e);
        }
    }
    List<String> crlUrls = new ArrayList<>();
    // Loop through ASN1Encodable DistributionPoints.
    for (DistributionPoint dp : distPoint.getDistributionPoints()) {
        // get ASN1Encodable DistributionPointName.
        DistributionPointName dpn = dp.getDistributionPoint();
        if (dpn != null && dpn.getType() == DistributionPointName.FULL_NAME) {
            // Create ASN1Encodable General Names.
            GeneralName[] genNames = GeneralNames.getInstance(dpn.getName()).getNames();
            // Look for a URI
            for (GeneralName genName : genNames) {
                if (genName.getTagNo() == GeneralName.uniformResourceIdentifier) {
                    // DERIA5String contains an ascii string.
                    // A IA5String is a restricted character string type in the ASN.1 notation.
                    String url = DERIA5String.getInstance(genName.getName()).getString().trim();
                    crlUrls.add(url);
                }
            }
        }
    }
    if (crlUrls.isEmpty()) {
        throw new CertificateVerificationException("Cant get CRL urls from certificate");
    }
    return crlUrls;
}
Also used : ASN1InputStream(org.bouncycastle.asn1.ASN1InputStream) ArrayList(java.util.ArrayList) DistributionPointName(org.bouncycastle.asn1.x509.DistributionPointName) IOException(java.io.IOException) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) DEROctetString(org.bouncycastle.asn1.DEROctetString) CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) DistributionPoint(org.bouncycastle.asn1.x509.DistributionPoint) GeneralName(org.bouncycastle.asn1.x509.GeneralName) CRLDistPoint(org.bouncycastle.asn1.x509.CRLDistPoint)

Example 5 with CertificateVerificationException

use of io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException in project module-ballerina-http by ballerina-platform.

the class OCSPVerifier method getAIALocations.

/**
 * Authority Information Access (AIA) is a non-critical extension in an X509 Certificate. This contains the
 * URL of the OCSP endpoint if one is available.
 *
 * @param cert is the certificate
 * @return a lit of URLs in AIA extension of the certificate which will hopefully contain an OCSP endpoint.
 * @throws CertificateVerificationException if any error occurs while retrieving authority access points from the
 * certificate.
 */
public static List<String> getAIALocations(X509Certificate cert) throws CertificateVerificationException {
    // Gets the DER-encoded OCTET string for the extension value for Authority information access points.
    byte[] aiaExtensionValue = cert.getExtensionValue(Extension.authorityInfoAccess.getId());
    if (aiaExtensionValue == null) {
        throw new CertificateVerificationException("Certificate doesn't have Authority Information Access points");
    }
    AuthorityInformationAccess authorityInformationAccess;
    ASN1InputStream asn1InputStream = null;
    try {
        DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(aiaExtensionValue)).readObject());
        asn1InputStream = new ASN1InputStream(oct.getOctets());
        authorityInformationAccess = AuthorityInformationAccess.getInstance(asn1InputStream.readObject());
    } catch (IOException e) {
        throw new CertificateVerificationException("Cannot read certificate to get OSCP urls", e);
    } finally {
        try {
            if (asn1InputStream != null) {
                asn1InputStream.close();
            }
        } catch (IOException e) {
            LOG.error("Cannot close ASN1InputStream", e);
        }
    }
    List<String> ocspUrlList = new ArrayList<>();
    AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions();
    for (AccessDescription accessDescription : accessDescriptions) {
        GeneralName gn = accessDescription.getAccessLocation();
        if (gn.getTagNo() == GeneralName.uniformResourceIdentifier) {
            DERIA5String str = DERIA5String.getInstance(gn.getName());
            String accessLocation = str.getString();
            ocspUrlList.add(accessLocation);
        }
    }
    if (ocspUrlList.isEmpty()) {
        throw new CertificateVerificationException("Cannot get OCSP urls from certificate");
    }
    return ocspUrlList;
}
Also used : AuthorityInformationAccess(org.bouncycastle.asn1.x509.AuthorityInformationAccess) ASN1InputStream(org.bouncycastle.asn1.ASN1InputStream) ArrayList(java.util.ArrayList) IOException(java.io.IOException) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) CertificateVerificationException(io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException) ByteArrayInputStream(java.io.ByteArrayInputStream) AccessDescription(org.bouncycastle.asn1.x509.AccessDescription) GeneralName(org.bouncycastle.asn1.x509.GeneralName)

Aggregations

CertificateVerificationException (io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.CertificateVerificationException)12 IOException (java.io.IOException)5 BouncyCastleProvider (org.bouncycastle.jce.provider.BouncyCastleProvider)5 DEROctetString (org.bouncycastle.asn1.DEROctetString)4 Test (org.testng.annotations.Test)4 X509Certificate (java.security.cert.X509Certificate)3 ASN1InputStream (org.bouncycastle.asn1.ASN1InputStream)3 DERIA5String (org.bouncycastle.asn1.DERIA5String)3 BasicOCSPResp (org.bouncycastle.cert.ocsp.BasicOCSPResp)3 OCSPException (org.bouncycastle.cert.ocsp.OCSPException)3 OCSPResp (org.bouncycastle.cert.ocsp.OCSPResp)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 CertificateEncodingException (java.security.cert.CertificateEncodingException)2 ArrayList (java.util.ArrayList)2 GeneralName (org.bouncycastle.asn1.x509.GeneralName)2 OCSPReq (org.bouncycastle.cert.ocsp.OCSPReq)2 SingleResp (org.bouncycastle.cert.ocsp.SingleResp)2 OperatorCreationException (org.bouncycastle.operator.OperatorCreationException)2 RevocationStatus (io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.RevocationStatus)1 OCSPCache (io.ballerina.stdlib.http.transport.contractimpl.common.certificatevalidation.ocsp.OCSPCache)1