Search in sources :

Example 1 with CertID

use of com.github.zhenwei.core.asn1.ocsp.CertID in project snowflake-jdbc by snowflakedb.

the class SFTrustManager method executeOneRevocationStatusCheck.

/**
 * Executes a single revocation status check
 *
 * @param pairIssuerSubject a pair of issuer and subject certificate
 * @param currentTimeSecond the current timestamp
 * @throws CertificateException if certificate exception is raised.
 */
private void executeOneRevocationStatusCheck(SFPair<Certificate, Certificate> pairIssuerSubject, long currentTimeSecond, String peerHost) throws CertificateException {
    OCSPReq req;
    OcspResponseCacheKey keyOcspResponse;
    try {
        req = createRequest(pairIssuerSubject);
        CertID cid = req.getRequestList()[0].getCertID().toASN1Primitive();
        keyOcspResponse = new OcspResponseCacheKey(cid.getIssuerNameHash().getEncoded(), cid.getIssuerKeyHash().getEncoded(), cid.getSerialNumber().getValue());
    } catch (IOException ex) {
        throw new CertificateException(ex.getMessage(), ex);
    }
    long sleepTime = INITIAL_SLEEPING_TIME_IN_MILLISECONDS;
    DecorrelatedJitterBackoff backoff = new DecorrelatedJitterBackoff(sleepTime, MAX_SLEEPING_TIME_IN_MILLISECONDS);
    CertificateException error;
    boolean success = false;
    String ocspLog;
    OCSPTelemetryData telemetryData = new OCSPTelemetryData();
    telemetryData.setSfcPeerHost(peerHost);
    telemetryData.setCertId(encodeCacheKey(keyOcspResponse));
    telemetryData.setCacheEnabled(useOCSPResponseCacheServer());
    telemetryData.setOCSPMode(ocspMode);
    Throwable cause = null;
    try {
        final int maxRetryCounter = isOCSPFailOpen() ? 1 : 2;
        for (int retry = 0; retry < maxRetryCounter; ++retry) {
            try {
                if (ssdManager.getSSDSupportStatus()) {
                    // Look for Host Specific SSD in SSD Cache
                    success = checkSSD(keyOcspResponse, peerHost);
                    if (success) {
                        break;
                    }
                }
                SFPair<Long, String> value0 = OCSP_RESPONSE_CACHE.get(keyOcspResponse);
                OCSPResp ocspResp;
                try {
                    try {
                        if (value0 == null) {
                            telemetryData.setCacheHit(false);
                            ocspResp = fetchOcspResponse(pairIssuerSubject, req, encodeCacheKey(keyOcspResponse), peerHost, telemetryData);
                            OCSP_RESPONSE_CACHE.put(keyOcspResponse, SFPair.of(currentTimeSecond, ocspResponseToB64(ocspResp)));
                            WAS_CACHE_UPDATED.set(true);
                            value0 = SFPair.of(currentTimeSecond, ocspResponseToB64(ocspResp));
                        } else {
                            telemetryData.setCacheHit(true);
                        }
                    } catch (Throwable ex) {
                        LOGGER.debug("Exception occurred while trying to fetch OCSP Response - {}", ex.getMessage());
                        throw new SFOCSPException(OCSPErrorCode.OCSP_RESPONSE_FETCH_FAILURE, "Exception occurred while trying to fetch OCSP Response", ex);
                    }
                    LOGGER.debug("validating. {}", CertificateIDToString(req.getRequestList()[0].getCertID()));
                    try {
                        validateRevocationStatusMain(pairIssuerSubject, value0.right);
                        success = true;
                        break;
                    } catch (SFOCSPException ex) {
                        if (ex.getErrorCode() != OCSPErrorCode.REVOCATION_CHECK_FAILURE) {
                            throw ex;
                        }
                        if (ssdManager.getSSDSupportStatus() && this.processOCSPBypassSSD(value0.right, keyOcspResponse, peerHost)) {
                            // Failed processing OCSP response. Try processing cache value as SSD
                            success = true;
                            break;
                        } else {
                            throw new CertificateException(ex.getMessage(), ex);
                        }
                    }
                } catch (SFOCSPException ex) {
                    if (ex.getErrorCode() == OCSPErrorCode.CERTIFICATE_STATUS_REVOKED) {
                        throw ex;
                    } else {
                        throw new CertificateException(ex.getMessage(), ex);
                    }
                }
            } catch (CertificateException ex) {
                WAS_CACHE_UPDATED.set(OCSP_RESPONSE_CACHE.remove(keyOcspResponse) != null);
                if (WAS_CACHE_UPDATED.get()) {
                    LOGGER.debug("deleting the invalid OCSP cache.");
                }
                cause = ex;
                LOGGER.debug("Retrying {}/{} after sleeping {}(ms)", retry + 1, maxRetryCounter, sleepTime);
                try {
                    if (retry + 1 < maxRetryCounter) {
                        Thread.sleep(sleepTime);
                        sleepTime = backoff.nextSleepTime(sleepTime);
                    }
                } catch (InterruptedException ex0) {
                // nop
                }
            }
        }
    } catch (SFOCSPException ex) {
        // Revoked Certificate
        error = new CertificateException(ex);
        ocspLog = telemetryData.generateTelemetry(SF_OCSP_EVENT_TYPE_REVOKED_CERTIFICATE_ERROR, error);
        LOGGER.error(ocspLog);
        throw error;
    }
    if (!success) {
        if (// cause is set in the above catch block
        cause != null) {
            error = new CertificateException("Certificate Revocation check failed. Could not retrieve OCSP Response.", cause);
            LOGGER.debug(cause.getMessage());
        } else {
            error = new CertificateException("Certificate Revocation check failed. Could not retrieve OCSP Response.");
            LOGGER.debug(error.getMessage());
        }
        ocspLog = telemetryData.generateTelemetry(SF_OCSP_EVENT_TYPE_VALIDATION_ERROR, error);
        if (isOCSPFailOpen()) {
            // Log includes fail-open warning.
            LOGGER.error(generateFailOpenLog(ocspLog));
        } else {
            // still not success, raise an error.
            LOGGER.debug(ocspLog);
            throw error;
        }
    }
}
Also used : CertID(org.bouncycastle.asn1.ocsp.CertID) CertificateException(java.security.cert.CertificateException) IOException(java.io.IOException) DecorrelatedJitterBackoff(net.snowflake.client.util.DecorrelatedJitterBackoff)

Example 2 with CertID

use of com.github.zhenwei.core.asn1.ocsp.CertID in project snowflake-jdbc by snowflakedb.

the class SFTrustManager method isCached.

/**
 * Is OCSP Response cached?
 *
 * @param pairIssuerSubjectList a list of pair of issuer and subject certificates
 * @return true if all of OCSP response are cached else false
 */
private boolean isCached(List<SFPair<Certificate, Certificate>> pairIssuerSubjectList) {
    long currentTimeSecond = new Date().getTime() / 1000L;
    boolean isCached = true;
    try {
        for (SFPair<Certificate, Certificate> pairIssuerSubject : pairIssuerSubjectList) {
            OCSPReq req = createRequest(pairIssuerSubject);
            CertificateID certificateId = req.getRequestList()[0].getCertID();
            LOGGER.debug(CertificateIDToString(certificateId));
            CertID cid = certificateId.toASN1Primitive();
            OcspResponseCacheKey k = new OcspResponseCacheKey(cid.getIssuerNameHash().getEncoded(), cid.getIssuerKeyHash().getEncoded(), cid.getSerialNumber().getValue());
            SFPair<Long, String> res = OCSP_RESPONSE_CACHE.get(k);
            if (res == null) {
                LOGGER.debug("Not all OCSP responses for the certificate is in the cache.");
                isCached = false;
                break;
            } else if (currentTimeSecond - CACHE_EXPIRATION_IN_SECONDS > res.left) {
                LOGGER.debug("Cache for CertID expired.");
                isCached = false;
                break;
            } else {
                try {
                    validateRevocationStatusMain(pairIssuerSubject, res.right);
                } catch (SFOCSPException ex) {
                    LOGGER.debug("Cache includes invalid OCSPResponse. " + "Will download the OCSP cache from Snowflake OCSP server");
                    isCached = false;
                }
            }
        }
    } catch (IOException ex) {
        LOGGER.debug("Failed to encode CertID.");
    }
    return isCached;
}
Also used : CertID(org.bouncycastle.asn1.ocsp.CertID) IOException(java.io.IOException) X509Certificate(java.security.cert.X509Certificate) Certificate(org.bouncycastle.asn1.x509.Certificate)

Example 3 with CertID

use of com.github.zhenwei.core.asn1.ocsp.CertID in project xipki by xipki.

the class AbstractOcspRequestor method ask.

@Override
public OCSPResp ask(X509Certificate issuerCert, BigInteger[] serialNumbers, URL responderUrl, RequestOptions requestOptions, RequestResponseDebug debug) throws OcspResponseException, OcspRequestorException {
    ParamUtil.requireNonNull("issuerCert", issuerCert);
    ParamUtil.requireNonNull("requestOptions", requestOptions);
    ParamUtil.requireNonNull("responderUrl", responderUrl);
    byte[] nonce = null;
    if (requestOptions.isUseNonce()) {
        nonce = nextNonce(requestOptions.getNonceLen());
    }
    OCSPRequest ocspReq = buildRequest(issuerCert, serialNumbers, nonce, requestOptions);
    byte[] encodedReq;
    try {
        encodedReq = ocspReq.getEncoded();
    } catch (IOException ex) {
        throw new OcspRequestorException("could not encode OCSP request: " + ex.getMessage(), ex);
    }
    RequestResponsePair msgPair = null;
    if (debug != null) {
        msgPair = new RequestResponsePair();
        debug.add(msgPair);
        if (debug.saveRequest()) {
            msgPair.setRequest(encodedReq);
        }
    }
    byte[] encodedResp;
    try {
        encodedResp = send(encodedReq, responderUrl, requestOptions);
    } catch (IOException ex) {
        throw new ResponderUnreachableException("IOException: " + ex.getMessage(), ex);
    }
    if (msgPair != null && debug.saveResponse()) {
        msgPair.setResponse(encodedResp);
    }
    OCSPResp ocspResp;
    try {
        ocspResp = new OCSPResp(encodedResp);
    } catch (IOException ex) {
        throw new InvalidOcspResponseException("IOException: " + ex.getMessage(), ex);
    }
    Object respObject;
    try {
        respObject = ocspResp.getResponseObject();
    } catch (OCSPException ex) {
        throw new InvalidOcspResponseException("responseObject is invalid");
    }
    if (ocspResp.getStatus() != 0) {
        return ocspResp;
    }
    if (!(respObject instanceof BasicOCSPResp)) {
        return ocspResp;
    }
    BasicOCSPResp basicOcspResp = (BasicOCSPResp) respObject;
    if (nonce != null) {
        Extension nonceExtn = basicOcspResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
        if (nonceExtn == null) {
            throw new OcspNonceUnmatchedException(nonce, null);
        }
        byte[] receivedNonce = nonceExtn.getExtnValue().getOctets();
        if (!Arrays.equals(nonce, receivedNonce)) {
            throw new OcspNonceUnmatchedException(nonce, receivedNonce);
        }
    }
    SingleResp[] singleResponses = basicOcspResp.getResponses();
    if (singleResponses == null || singleResponses.length == 0) {
        String msg = StringUtil.concat("response with no singleResponse is returned, expected is ", Integer.toString(serialNumbers.length));
        throw new OcspTargetUnmatchedException(msg);
    }
    final int countSingleResponses = singleResponses.length;
    if (countSingleResponses != serialNumbers.length) {
        String msg = StringUtil.concat("response with ", Integer.toString(countSingleResponses), " singleResponse", (countSingleResponses > 1 ? "s" : ""), " is returned, expected is ", Integer.toString(serialNumbers.length));
        throw new OcspTargetUnmatchedException(msg);
    }
    Request reqAt0 = Request.getInstance(ocspReq.getTbsRequest().getRequestList().getObjectAt(0));
    CertID certId = reqAt0.getReqCert();
    ASN1ObjectIdentifier issuerHashAlg = certId.getHashAlgorithm().getAlgorithm();
    byte[] issuerKeyHash = certId.getIssuerKeyHash().getOctets();
    byte[] issuerNameHash = certId.getIssuerNameHash().getOctets();
    if (serialNumbers.length == 1) {
        SingleResp singleResp = singleResponses[0];
        CertificateID cid = singleResp.getCertID();
        boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID()) && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash()) && Arrays.equals(issuerNameHash, cid.getIssuerNameHash());
        if (!issuerMatch) {
            throw new OcspTargetUnmatchedException("the issuer is not requested");
        }
        BigInteger serialNumber = cid.getSerialNumber();
        if (!serialNumbers[0].equals(serialNumber)) {
            throw new OcspTargetUnmatchedException("the serialNumber is not requested");
        }
    } else {
        List<BigInteger> tmpSerials1 = Arrays.asList(serialNumbers);
        List<BigInteger> tmpSerials2 = new ArrayList<>(tmpSerials1);
        for (int i = 0; i < countSingleResponses; i++) {
            SingleResp singleResp = singleResponses[i];
            CertificateID cid = singleResp.getCertID();
            boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID()) && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash()) && Arrays.equals(issuerNameHash, cid.getIssuerNameHash());
            if (!issuerMatch) {
                throw new OcspTargetUnmatchedException("the issuer specified in singleResponse[" + i + "] is not requested");
            }
            BigInteger serialNumber = cid.getSerialNumber();
            if (!tmpSerials2.remove(serialNumber)) {
                if (tmpSerials1.contains(serialNumber)) {
                    throw new OcspTargetUnmatchedException("serialNumber " + LogUtil.formatCsn(serialNumber) + "is contained in at least two singleResponses");
                } else {
                    throw new OcspTargetUnmatchedException("serialNumber " + LogUtil.formatCsn(serialNumber) + " specified in singleResponse[" + i + "] is not requested");
                }
            }
        }
    // end for
    }
    return ocspResp;
}
Also used : CertID(org.bouncycastle.asn1.ocsp.CertID) ArrayList(java.util.ArrayList) DEROctetString(org.bouncycastle.asn1.DEROctetString) OCSPResp(org.bouncycastle.cert.ocsp.OCSPResp) BasicOCSPResp(org.bouncycastle.cert.ocsp.BasicOCSPResp) OCSPException(org.bouncycastle.cert.ocsp.OCSPException) OcspNonceUnmatchedException(org.xipki.ocsp.client.api.OcspNonceUnmatchedException) SingleResp(org.bouncycastle.cert.ocsp.SingleResp) OcspRequestorException(org.xipki.ocsp.client.api.OcspRequestorException) RequestResponsePair(org.xipki.common.RequestResponsePair) CertificateID(org.bouncycastle.cert.ocsp.CertificateID) Request(org.bouncycastle.asn1.ocsp.Request) OCSPRequest(org.bouncycastle.asn1.ocsp.OCSPRequest) IOException(java.io.IOException) Extension(org.bouncycastle.asn1.x509.Extension) ResponderUnreachableException(org.xipki.ocsp.client.api.ResponderUnreachableException) BasicOCSPResp(org.bouncycastle.cert.ocsp.BasicOCSPResp) OcspTargetUnmatchedException(org.xipki.ocsp.client.api.OcspTargetUnmatchedException) BigInteger(java.math.BigInteger) InvalidOcspResponseException(org.xipki.ocsp.client.api.InvalidOcspResponseException) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) OCSPRequest(org.bouncycastle.asn1.ocsp.OCSPRequest)

Example 4 with CertID

use of com.github.zhenwei.core.asn1.ocsp.CertID in project jruby-openssl by jruby.

the class OCSPSingleResponse method certid.

@JRubyMethod(name = "certid")
public IRubyObject certid(ThreadContext context) {
    Ruby runtime = context.runtime;
    CertID bcCertId = bcSingleResponse.getCertID();
    OCSPCertificateId rubyCertId = new OCSPCertificateId(runtime);
    try {
        rubyCertId.initialize(context, RubyString.newString(runtime, bcCertId.getEncoded()));
    } catch (IOException e) {
        throw newOCSPError(runtime, e);
    }
    return rubyCertId;
}
Also used : CertID(org.bouncycastle.asn1.ocsp.CertID) IOException(java.io.IOException) Ruby(org.jruby.Ruby) JRubyMethod(org.jruby.anno.JRubyMethod)

Example 5 with CertID

use of com.github.zhenwei.core.asn1.ocsp.CertID in project jruby-openssl by jruby.

the class OCSPBasicResponse method add_status.

@JRubyMethod(name = "add_status", rest = true)
public OCSPBasicResponse add_status(final ThreadContext context, IRubyObject[] args) {
    Ruby runtime = context.getRuntime();
    Arity.checkArgumentCount(runtime, args, 7, 7);
    IRubyObject certificateId = args[0];
    IRubyObject status = args[1];
    IRubyObject reason = args[2];
    IRubyObject revocation_time = args[3];
    IRubyObject this_update = args[4];
    IRubyObject next_update = args[5];
    IRubyObject extensions = args[6];
    CertStatus certStatus = null;
    switch(RubyFixnum.fix2int((RubyFixnum) status)) {
        case 0:
            certStatus = new CertStatus();
            break;
        case 1:
            ASN1GeneralizedTime revTime = rubyIntOrTimeToGenTime(revocation_time);
            RevokedInfo revokedInfo = new RevokedInfo(revTime, CRLReason.lookup(RubyFixnum.fix2int((RubyFixnum) reason)));
            certStatus = new CertStatus(revokedInfo);
            break;
        case 2:
            certStatus = new CertStatus(2, DERNull.INSTANCE);
            break;
        default:
            break;
    }
    ASN1GeneralizedTime thisUpdate = rubyIntOrTimeToGenTime(this_update);
    ASN1GeneralizedTime nextUpdate = rubyIntOrTimeToGenTime(next_update);
    Extensions singleExtensions = convertRubyExtensions(extensions);
    CertID certID = ((OCSPCertificateId) certificateId).getCertID();
    SingleResponse ocspSingleResp = new SingleResponse(certID, certStatus, thisUpdate, nextUpdate, singleExtensions);
    OCSPSingleResponse rubySingleResp = new OCSPSingleResponse(runtime);
    try {
        rubySingleResp.initialize(context, RubyString.newString(runtime, ocspSingleResp.getEncoded()));
        singleResponses.add(rubySingleResp);
    } catch (IOException e) {
        throw newOCSPError(runtime, e);
    }
    return this;
}
Also used : CertStatus(org.bouncycastle.asn1.ocsp.CertStatus) SingleResponse(org.bouncycastle.asn1.ocsp.SingleResponse) CertID(org.bouncycastle.asn1.ocsp.CertID) ASN1GeneralizedTime(org.bouncycastle.asn1.ASN1GeneralizedTime) IOException(java.io.IOException) IRubyObject(org.jruby.runtime.builtin.IRubyObject) RevokedInfo(org.bouncycastle.asn1.ocsp.RevokedInfo) Extensions(org.bouncycastle.asn1.x509.Extensions) Ruby(org.jruby.Ruby) JRubyMethod(org.jruby.anno.JRubyMethod)

Aggregations

IOException (java.io.IOException)19 CertID (org.bouncycastle.asn1.ocsp.CertID)15 ASN1EncodableVector (com.github.zhenwei.core.asn1.ASN1EncodableVector)13 DERSequence (com.github.zhenwei.core.asn1.DERSequence)11 CertificateException (java.security.cert.CertificateException)7 X509Certificate (java.security.cert.X509Certificate)7 ASN1OctetString (com.github.zhenwei.core.asn1.ASN1OctetString)6 DEROctetString (com.github.zhenwei.core.asn1.DEROctetString)6 BigInteger (java.math.BigInteger)6 CertificateEncodingException (java.security.cert.CertificateEncodingException)6 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)5 NoSuchProviderException (java.security.NoSuchProviderException)5 ASN1BMPString (com.github.zhenwei.core.asn1.ASN1BMPString)4 ASN1ObjectIdentifier (com.github.zhenwei.core.asn1.ASN1ObjectIdentifier)4 DERBMPString (com.github.zhenwei.core.asn1.DERBMPString)4 Extension (org.bouncycastle.asn1.x509.Extension)4 ASN1Sequence (com.github.zhenwei.core.asn1.ASN1Sequence)3 BEROctetString (com.github.zhenwei.core.asn1.BEROctetString)3 DERTaggedObject (com.github.zhenwei.core.asn1.DERTaggedObject)3 CertID (com.github.zhenwei.core.asn1.ocsp.CertID)3