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);
}
}
}
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.");
}
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);
}
}
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;
}
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;
}
Aggregations