Example usage for org.bouncycastle.cert.ocsp CertificateID getIssuerKeyHash

List of usage examples for org.bouncycastle.cert.ocsp CertificateID getIssuerKeyHash

Introduction

In this page you can find the example usage for org.bouncycastle.cert.ocsp CertificateID getIssuerKeyHash.

Prototype

public byte[] getIssuerKeyHash() 

Source Link

Usage

From source file:eu.europa.ec.markt.dss.DSSRevocationUtils.java

License:Open Source License

/**
 * fix for certId.equals methods that doesn't work very well.
 *
 * @param certId     {@code CertificateID}
 * @param singleResp {@code SingleResp}//w w  w  .  j  a v  a  2  s.  c om
 * @return true if the certificate matches this included in {@code SingleResp}
 */
public static boolean matches(final CertificateID certId, final SingleResp singleResp) {

    final CertificateID singleRespCertID = singleResp.getCertID();
    final ASN1ObjectIdentifier singleRespCertIDHashAlgOID = singleRespCertID.getHashAlgOID();
    final byte[] singleRespCertIDIssuerKeyHash = singleRespCertID.getIssuerKeyHash();
    final byte[] singleRespCertIDIssuerNameHash = singleRespCertID.getIssuerNameHash();
    final BigInteger singleRespCertIDSerialNumber = singleRespCertID.getSerialNumber();

    final ASN1ObjectIdentifier certIdHashAlgOID = certId.getHashAlgOID();
    final byte[] certIdIssuerKeyHash = certId.getIssuerKeyHash();
    final byte[] certIdIssuerNameHash = certId.getIssuerNameHash();
    final BigInteger certIdSerialNumber = certId.getSerialNumber();

    // certId.equals fails in comparing the algoIdentifier because AlgoIdentifier params in null in one case and DERNull in another case
    return singleRespCertIDHashAlgOID.equals(certIdHashAlgOID)
            && Arrays.areEqual(singleRespCertIDIssuerKeyHash, certIdIssuerKeyHash)
            && Arrays.areEqual(singleRespCertIDIssuerNameHash, certIdIssuerNameHash)
            && singleRespCertIDSerialNumber.equals(certIdSerialNumber);
}

From source file:eu.europa.esig.dss.DSSRevocationUtils.java

License:Open Source License

/**
 * fix for certId.equals methods that doesn't work very well.
 *
 * @param certId//from   w w w . ja  v a 2 s  .  co  m
 *            {@code CertificateID}
 * @param singleResp
 *            {@code SingleResp}
 * @return true if the certificate matches this included in
 *         {@code SingleResp}
 */
public static boolean matches(final CertificateID certId, final SingleResp singleResp) {

    final CertificateID singleRespCertID = singleResp.getCertID();
    final ASN1ObjectIdentifier singleRespCertIDHashAlgOID = singleRespCertID.getHashAlgOID();
    final byte[] singleRespCertIDIssuerKeyHash = singleRespCertID.getIssuerKeyHash();
    final byte[] singleRespCertIDIssuerNameHash = singleRespCertID.getIssuerNameHash();
    final BigInteger singleRespCertIDSerialNumber = singleRespCertID.getSerialNumber();

    final ASN1ObjectIdentifier certIdHashAlgOID = certId.getHashAlgOID();
    final byte[] certIdIssuerKeyHash = certId.getIssuerKeyHash();
    final byte[] certIdIssuerNameHash = certId.getIssuerNameHash();
    final BigInteger certIdSerialNumber = certId.getSerialNumber();

    // certId.equals fails in comparing the algoIdentifier because
    // AlgoIdentifier params in null in one case and DERNull in another case
    return singleRespCertIDHashAlgOID.equals(certIdHashAlgOID)
            && Arrays.areEqual(singleRespCertIDIssuerKeyHash, certIdIssuerKeyHash)
            && Arrays.areEqual(singleRespCertIDIssuerNameHash, certIdIssuerNameHash)
            && singleRespCertIDSerialNumber.equals(certIdSerialNumber);
}

From source file:org.cesecore.certificates.ocsp.cache.OcspSigningCache.java

License:Open Source License

/** @return a cache identifier based on the provided CertificateID. */
public static int getCacheIdFromCertificateID(final CertificateID certID) {
    // Use bitwise XOR of the hashcodes for IssuerNameHash and IssuerKeyHash to produce the integer.
    int result = new BigInteger(certID.getIssuerNameHash()).hashCode()
            ^ new BigInteger(certID.getIssuerKeyHash()).hashCode();
    if (log.isDebugEnabled()) {
        log.debug("Using getIssuerNameHash " + new BigInteger(certID.getIssuerNameHash()).toString(16)
                + " and getIssuerKeyHash " + new BigInteger(certID.getIssuerKeyHash()).toString(16)
                + " to produce id " + result);
    }/*w w  w . jav  a  2s .c o  m*/
    return result;
}

From source file:org.cesecore.certificates.ocsp.OcspResponseGeneratorSessionBean.java

License:Open Source License

@Override
public OcspResponseInformation getOcspResponse(final byte[] request,
        final X509Certificate[] requestCertificates, String remoteAddress, String remoteHost,
        StringBuffer requestUrl, final AuditLogger auditLogger, final TransactionLogger transactionLogger)
        throws MalformedRequestException, OCSPException {
    //Check parameters
    if (auditLogger == null) {
        throw new InvalidParameterException(
                "Illegal to pass a null audit logger to OcspResponseSession.getOcspResponse");
    }/*from   w  w  w.ja  va  2  s  . c  o  m*/
    if (transactionLogger == null) {
        throw new InvalidParameterException(
                "Illegal to pass a null transaction logger to OcspResponseSession.getOcspResponse");
    }
    // Validate byte array.
    if (request.length > MAX_REQUEST_SIZE) {
        final String msg = intres.getLocalizedMessage("request.toolarge", MAX_REQUEST_SIZE, request.length);
        throw new MalformedRequestException(msg);
    }
    byte[] respBytes = null;
    final Date startTime = new Date();
    OCSPResp ocspResponse = null;
    // Start logging process time after we have received the request
    if (transactionLogger.isEnabled()) {
        transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
    }
    if (auditLogger.isEnabled()) {
        auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        auditLogger.paramPut(AuditLogger.OCSPREQUEST, new String(Hex.encode(request)));
    }
    OCSPReq req;
    long maxAge = OcspConfiguration.getMaxAge(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);
    OCSPRespBuilder responseGenerator = new OCSPRespBuilder();
    try {
        req = translateRequestFromByteArray(request, remoteAddress, transactionLogger);
        // Get the certificate status requests that are inside this OCSP req
        Req[] ocspRequests = req.getRequestList();
        if (ocspRequests.length <= 0) {
            String infoMsg = intres.getLocalizedMessage("ocsp.errornoreqentities");
            log.info(infoMsg);
            throw new MalformedRequestException(infoMsg);
        }
        final int maxRequests = 100;
        if (ocspRequests.length > maxRequests) {
            String infoMsg = intres.getLocalizedMessage("ocsp.errortoomanyreqentities", maxRequests);
            log.info(infoMsg);
            throw new MalformedRequestException(infoMsg);
        }
        if (log.isDebugEnabled()) {
            log.debug("The OCSP request contains " + ocspRequests.length + " simpleRequests.");
        }
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.NUM_CERT_ID, ocspRequests.length);
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
        }
        OcspSigningCacheEntry ocspSigningCacheEntry = null;
        long nextUpdate = OcspConfiguration
                .getUntilNextUpdate(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);
        // Add standard response extensions
        Map<ASN1ObjectIdentifier, Extension> responseExtensions = getStandardResponseExtensions(req);
        // Look for extension OIDs
        final Collection<String> extensionOids = OcspConfiguration.getExtensionOids();
        // Look over the status requests
        List<OCSPResponseItem> responseList = new ArrayList<OCSPResponseItem>();
        boolean addExtendedRevokedExtension = false;
        Date producedAt = null;
        for (Req ocspRequest : ocspRequests) {
            CertificateID certId = ocspRequest.getCertID();
            ASN1ObjectIdentifier certIdhash = certId.getHashAlgOID();
            if (!OIWObjectIdentifiers.idSHA1.equals(certIdhash)
                    && !NISTObjectIdentifiers.id_sha256.equals(certIdhash)) {
                throw new InvalidAlgorithmException(
                        "CertID with SHA1 and SHA256 are supported, not: " + certIdhash.getId());
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.SERIAL_NOHEX,
                        certId.getSerialNumber().toByteArray());
                transactionLogger.paramPut(TransactionLogger.DIGEST_ALGOR, certId.getHashAlgOID().toString());
                transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
                transactionLogger.paramPut(TransactionLogger.ISSUER_KEY, certId.getIssuerKeyHash());
            }
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(AuditLogger.SERIAL_NOHEX, certId.getSerialNumber().toByteArray());
                auditLogger.paramPut(AuditLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
            }
            byte[] hashbytes = certId.getIssuerNameHash();
            String hash = null;
            if (hashbytes != null) {
                hash = new String(Hex.encode(hashbytes));
            }
            String infoMsg = intres.getLocalizedMessage("ocsp.inforeceivedrequest",
                    certId.getSerialNumber().toString(16), hash, remoteAddress);
            log.info(infoMsg);
            // Locate the CA which gave out the certificate
            ocspSigningCacheEntry = OcspSigningCache.INSTANCE.getEntry(certId);
            if (ocspSigningCacheEntry == null) {
                //Could it be that we haven't updated the OCSP Signing Cache?
                ocspSigningCacheEntry = findAndAddMissingCacheEntry(certId);
            }
            if (ocspSigningCacheEntry != null) {
                if (transactionLogger.isEnabled()) {
                    // This will be the issuer DN of the signing certificate, whether an OCSP responder or an internal CA  
                    String issuerNameDn = CertTools
                            .getIssuerDN(ocspSigningCacheEntry.getFullCertificateChain().get(0));
                    transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_DN, issuerNameDn);
                }
            } else {
                /*
                 * if the certId was issued by an unknown CA 
                 * 
                 * The algorithm here: 
                 * We will sign the response with the CA that issued the last certificate(certId) in the request. If the issuing CA is not available on 
                 * this server, we sign the response with the default responderId (from params in web.xml). We have to look up the ca-certificate for 
                 * each certId in the request though, as we will check for revocation on the ca-cert as well when checking for revocation on the certId.
                 */
                // We could not find certificate for this request so get certificate for default responder
                ocspSigningCacheEntry = OcspSigningCache.INSTANCE.getDefaultEntry();
                if (ocspSigningCacheEntry != null) {
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacertusedefault",
                            new String(Hex.encode(certId.getIssuerNameHash())));
                    log.info(errMsg);
                    // If we can not find the CA, answer UnknowStatus
                    responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                OCSPResponseItem.OCSP_UNKNOWN);
                        transactionLogger.writeln();
                    }
                    continue;
                } else {
                    GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                            .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
                    String defaultResponder = ocspConfiguration.getOcspDefaultResponderReference();
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacert",
                            new String(Hex.encode(certId.getIssuerNameHash())), defaultResponder);
                    log.error(errMsg);
                    // If we are responding to multiple requests, the last found ocspSigningCacheEntry will be used in the end
                    // so even if there are not any one now, it might be later when it is time to sign the responses.
                    // Since we only will sign the entire response once if there is at least one valid ocspSigningCacheEntry
                    // we might as well include the unknown requests.
                    responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                    continue;
                }
            }

            final org.bouncycastle.cert.ocsp.CertificateStatus certStatus;
            // Check if the cacert (or the default responderid) is revoked
            X509Certificate caCertificate = ocspSigningCacheEntry.getIssuerCaCertificate();
            final CertificateStatus signerIssuerCertStatus = ocspSigningCacheEntry
                    .getIssuerCaCertificateStatus();
            final String caCertificateSubjectDn = CertTools.getSubjectDN(caCertificate);
            CertificateStatusHolder certificateStatusHolder = null;
            if (signerIssuerCertStatus.equals(CertificateStatus.REVOKED)) {
                /*
                 * According to chapter 2.7 in RFC2560:
                 * 
                 * 2.7 CA Key Compromise If an OCSP responder knows that a particular CA's private key has been compromised, it MAY return the revoked
                 * state for all certificates issued by that CA.
                 */
                // If we've ended up here it's because the signer issuer certificate was revoked. 
                certStatus = new RevokedStatus(
                        new RevokedInfo(new ASN1GeneralizedTime(signerIssuerCertStatus.revocationDate),
                                CRLReason.lookup(signerIssuerCertStatus.revocationReason)));
                infoMsg = intres.getLocalizedMessage("ocsp.signcertissuerrevoked",
                        CertTools.getSerialNumberAsString(caCertificate),
                        CertTools.getSubjectDN(caCertificate));
                log.info(infoMsg);
                responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));
                if (transactionLogger.isEnabled()) {
                    transactionLogger.paramPut(TransactionLogger.CERT_STATUS, OCSPResponseItem.OCSP_REVOKED);
                    transactionLogger.writeln();
                }
            } else {
                /**
                 * Here is the actual check for the status of the sought certificate (easy to miss). Here we grab just the status if there aren't
                 * any OIDs defined (default case), but if there are we'll probably need the certificate as well. If that's the case, we'll grab
                 * the certificate in the same transaction.
                 */
                final CertificateStatus status;
                if (extensionOids.isEmpty()) {
                    status = certificateStoreSession.getStatus(caCertificateSubjectDn,
                            certId.getSerialNumber());
                } else {
                    certificateStatusHolder = certificateStoreSession
                            .getCertificateAndStatus(caCertificateSubjectDn, certId.getSerialNumber());
                    status = certificateStatusHolder.getCertificateStatus();
                }
                // If we have an OcspKeyBinding configured for this request, we override the default value
                if (ocspSigningCacheEntry.isUsingSeparateOcspSigningCertificate()) {
                    nextUpdate = ocspSigningCacheEntry.getOcspKeyBinding().getUntilNextUpdate() * 1000L;
                }
                // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                        && OcspConfiguration.isUntilNextUpdateConfigured(status.certificateProfileId)) {
                    nextUpdate = OcspConfiguration.getUntilNextUpdate(status.certificateProfileId);
                }
                // If we have an OcspKeyBinding configured for this request, we override the default value
                if (ocspSigningCacheEntry.isUsingSeparateOcspSigningCertificate()) {
                    maxAge = ocspSigningCacheEntry.getOcspKeyBinding().getMaxAge() * 1000L;
                }
                // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                        && OcspConfiguration.isMaxAgeConfigured(status.certificateProfileId)) {
                    maxAge = OcspConfiguration.getMaxAge(status.certificateProfileId);
                }

                final String sStatus;
                boolean addArchiveCutoff = false;
                if (status.equals(CertificateStatus.NOT_AVAILABLE)) {
                    // No revocation info available for this cert, handle it
                    if (log.isDebugEnabled()) {
                        log.debug("Unable to find revocation information for certificate with serial '"
                                + certId.getSerialNumber().toString(16) + "'" + " from issuer '"
                                + caCertificateSubjectDn + "'");
                    }
                    /* 
                     * If we do not treat non existing certificates as good or revoked
                     * OR
                     * we don't actually handle requests for the CA issuing the certificate asked about
                     * then we return unknown 
                     * */
                    if (OcspConfigurationCache.INSTANCE.isNonExistingGood(requestUrl,
                            ocspSigningCacheEntry.getOcspKeyBinding())
                            && OcspSigningCache.INSTANCE.getEntry(certId) != null) {
                        sStatus = "good";
                        certStatus = null; // null means "good" in OCSP
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_GOOD);
                        }
                    } else if (OcspConfigurationCache.INSTANCE.isNonExistingRevoked(requestUrl,
                            ocspSigningCacheEntry.getOcspKeyBinding())
                            && OcspSigningCache.INSTANCE.getEntry(certId) != null) {
                        sStatus = "revoked";
                        certStatus = new RevokedStatus(new RevokedInfo(new ASN1GeneralizedTime(new Date(0)),
                                CRLReason.lookup(CRLReason.certificateHold)));
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_REVOKED);
                        }
                        addExtendedRevokedExtension = true;
                    } else {
                        sStatus = "unknown";
                        certStatus = new UnknownStatus();
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_UNKNOWN);
                        }
                    }
                } else if (status.equals(CertificateStatus.REVOKED)) {
                    // Revocation info available for this cert, handle it
                    sStatus = "revoked";
                    certStatus = new RevokedStatus(
                            new RevokedInfo(new ASN1GeneralizedTime(status.revocationDate),
                                    CRLReason.lookup(status.revocationReason)));
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                OCSPResponseItem.OCSP_REVOKED);
                    }
                    // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                    if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                            && OcspConfiguration
                                    .isRevokedUntilNextUpdateConfigured(status.certificateProfileId)) {
                        nextUpdate = OcspConfiguration.getRevokedUntilNextUpdate(status.certificateProfileId);
                    }
                    // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                    if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                            && OcspConfiguration.isRevokedMaxAgeConfigured(status.certificateProfileId)) {
                        maxAge = OcspConfiguration.getRevokedMaxAge(status.certificateProfileId);
                    }
                } else {
                    sStatus = "good";
                    certStatus = null;
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS, OCSPResponseItem.OCSP_GOOD);
                    }
                    addArchiveCutoff = checkAddArchiveCuttoff(caCertificateSubjectDn, certId);
                }

                if (log.isDebugEnabled()) {
                    log.debug("Set nextUpdate=" + nextUpdate + ", and maxAge=" + maxAge
                            + " for certificateProfileId=" + status.certificateProfileId);
                }

                infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", sStatus,
                        certId.getSerialNumber().toString(16), caCertificateSubjectDn);
                log.info(infoMsg);
                OCSPResponseItem respItem = new OCSPResponseItem(certId, certStatus, nextUpdate);
                if (addArchiveCutoff) {
                    addArchiveCutoff(respItem);
                    producedAt = new Date();
                }
                responseList.add(respItem);
                if (transactionLogger.isEnabled()) {
                    transactionLogger.writeln();
                }
            }
            for (String oidstr : extensionOids) {
                boolean useAlways = false;
                if (oidstr.startsWith("*")) {
                    oidstr = oidstr.substring(1, oidstr.length());
                    useAlways = true;
                }
                ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidstr);
                Extension extension = null;
                if (!useAlways) {
                    // Only check if extension exists if we are not already bound to use it
                    if (req.hasExtensions()) {
                        extension = req.getExtension(oid);
                    }
                }
                //If found, or if it should be used anyway
                if (useAlways || extension != null) {
                    // We found an extension, call the extension class
                    if (log.isDebugEnabled()) {
                        log.debug("Found OCSP extension oid: " + oidstr);
                    }
                    OCSPExtension extObj = OcspExtensionsCache.INSTANCE.getExtensions().get(oidstr);
                    if (extObj != null) {
                        // Find the certificate from the certId
                        if (certificateStatusHolder != null
                                && certificateStatusHolder.getCertificate() != null) {
                            X509Certificate cert = (X509Certificate) certificateStatusHolder.getCertificate();
                            // Call the OCSP extension
                            Map<ASN1ObjectIdentifier, Extension> retext = extObj.process(requestCertificates,
                                    remoteAddress, remoteHost, cert, certStatus);
                            if (retext != null) {
                                // Add the returned X509Extensions to the responseExtension we will add to the basic OCSP response
                                responseExtensions.putAll(retext);
                            } else {
                                String errMsg = intres.getLocalizedMessage("ocsp.errorprocessextension",
                                        extObj.getClass().getName(),
                                        Integer.valueOf(extObj.getLastErrorCode()));
                                log.error(errMsg);
                            }
                        }
                    }
                }
            }
        }
        if (addExtendedRevokedExtension) {
            // id-pkix-ocsp-extended-revoke OBJECT IDENTIFIER ::= {id-pkix-ocsp 9}
            final ASN1ObjectIdentifier extendedRevokedOID = new ASN1ObjectIdentifier(
                    OCSPObjectIdentifiers.id_pkix_ocsp + ".9");
            try {
                responseExtensions.put(extendedRevokedOID,
                        new Extension(extendedRevokedOID, false, DERNull.INSTANCE.getEncoded()));
            } catch (IOException e) {
                throw new IllegalStateException("Could not get encodig from DERNull.", e);
            }
        }
        if (ocspSigningCacheEntry != null) {
            // Add responseExtensions
            Extensions exts = new Extensions(responseExtensions.values().toArray(new Extension[0]));
            // generate the signed response object
            BasicOCSPResp basicresp = signOcspResponse(req, responseList, exts, ocspSigningCacheEntry,
                    producedAt);
            ocspResponse = responseGenerator.build(OCSPRespBuilder.SUCCESSFUL, basicresp);
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
            }
        } else {
            // Only unknown CAs in requests and no default responder's cert, return an unsigned response
            if (log.isDebugEnabled()) {
                log.debug(intres.getLocalizedMessage("ocsp.errornocacreateresp"));
            }
            ocspResponse = responseGenerator.build(OCSPRespBuilder.UNAUTHORIZED, null);
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            }
        }
    } catch (SignRequestException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.SIG_REQUIRED, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SIG_REQUIRED);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SIG_REQUIRED);
        }
    } catch (SignRequestSignatureException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.UNAUTHORIZED, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
        }
    } catch (InvalidAlgorithmException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.MALFORMED_REQUEST, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST);
        }
    } catch (NoSuchAlgorithmException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    } catch (CertificateException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    } catch (CryptoTokenOfflineException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    }
    try {
        respBytes = ocspResponse.getEncoded();
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.OCSPRESPONSE, new String(Hex.encode(respBytes)));
            auditLogger.writeln();
            auditLogger.flush();
        }
        if (transactionLogger.isEnabled()) {
            transactionLogger.flush();
        }
        if (OcspConfiguration.getLogSafer()) {
            // See if the Errorhandler has found any problems
            if (hasErrorHandlerFailedSince(startTime)) {
                log.info("ProbableErrorhandler reported error, cannot answer request");
                // RFC 2560: responseBytes are not set on error.
                ocspResponse = responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null);

            }
            // See if the Appender has reported any problems
            if (!CanLogCache.INSTANCE.canLog()) {
                log.info("SaferDailyRollingFileAppender reported error, cannot answer request");
                // RFC 2560: responseBytes are not set on error.
                ocspResponse = responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null);
            }
        }
    } catch (IOException e) {
        log.error("Unexpected IOException caught.", e);
        if (transactionLogger.isEnabled()) {
            transactionLogger.flush();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.flush();
        }
    }
    return new OcspResponseInformation(ocspResponse, maxAge);
}

From source file:org.jruby.ext.openssl.OCSPBasicResponse.java

License:Common Public License

private boolean matchIssuerId(X509Cert signerCA, CertificateID certId, List<SingleResp> singleResponses)
        throws IOException {
    Ruby runtime = getRuntime();// ww w.ja  v a2s.co m
    if (certId == null) {
        //gotta check em all
        for (SingleResp resp : singleResponses) {
            CertificateID tempId = resp.getCertID();
            if (!matchIssuerId(signerCA, tempId, null))
                return false;
        }
        return true;
    } else {
        // we have a matching cid
        ASN1ObjectIdentifier alg = certId.getHashAlgOID();
        String sym = ASN1.oid2Sym(runtime, alg);
        MessageDigest md = Digest.getDigest(runtime, sym);
        byte[] issuerNameDigest = md.digest(signerCA.getIssuer().getX500Name().getEncoded());
        byte[] issuerKeyDigest = md.digest(signerCA.getAuxCert().getPublicKey().getEncoded());
        if (!issuerNameDigest.equals(certId.getIssuerNameHash()))
            return false;
        if (!issuerKeyDigest.equals(certId.getIssuerKeyHash()))
            return false;
        return true;
    }
}

From source file:org.keycloak.common.util.OCSPUtils.java

License:Apache License

private static boolean compareCertIDs(JcaCertificateID idLeft, CertificateID idRight) {
    if (idLeft == idRight)
        return true;
    if (idLeft == null || idRight == null)
        return false;

    return Arrays.equals(idLeft.getIssuerKeyHash(), idRight.getIssuerKeyHash())
            && Arrays.equals(idLeft.getIssuerNameHash(), idRight.getIssuerNameHash())
            && idLeft.getSerialNumber().equals(idRight.getSerialNumber());
}

From source file:org.xipki.ocsp.client.impl.AbstractOCSPRequestor.java

License:Open Source License

@Override
public OCSPResp ask(final X509Certificate issuerCert, final BigInteger[] serialNumbers, final URL responderUrl,
        final RequestOptions requestOptions, final RequestResponseDebug debug)
        throws OCSPResponseException, OCSPRequestorException {
    if (requestOptions == null) {
        throw new IllegalArgumentException("requestOptions could not be null");
    }//w  ww  .  j av  a  2  s  .  c o m

    byte[] nonce = null;
    if (requestOptions.isUseNonce()) {
        nonce = nextNonce(requestOptions.getNonceLen());
    }

    OCSPReq ocspReq = buildRequest(issuerCert, serialNumbers, nonce, requestOptions);
    byte[] encodedReq;
    try {
        encodedReq = ocspReq.getEncoded();
    } catch (IOException e) {
        throw new OCSPRequestorException("could not encode OCSP request: " + e.getMessage(), e);
    }

    RequestResponsePair msgPair = null;
    if (debug != null) {
        msgPair = new RequestResponsePair();
        debug.add(msgPair);
        msgPair.setRequest(encodedReq);
    }

    byte[] encodedResp;
    try {
        encodedResp = send(encodedReq, responderUrl, requestOptions);
    } catch (IOException e) {
        throw new ResponderUnreachableException("IOException: " + e.getMessage(), e);
    }

    if (debug != null) {
        msgPair.setRequest(encodedResp);
    }

    OCSPResp ocspResp;
    try {
        ocspResp = new OCSPResp(encodedResp);
    } catch (IOException e) {
        throw new InvalidOCSPResponseException("IOException: " + e.getMessage(), e);
    }

    Object respObject;
    try {
        respObject = ocspResp.getResponseObject();
    } catch (OCSPException e) {
        throw new InvalidOCSPResponseException("responseObject is invalid");
    }

    if (ocspResp.getStatus() != 0) {
        return ocspResp;
    }

    if (respObject instanceof BasicOCSPResp == false) {
        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) == false) {
            throw new OCSPNonceUnmatchedException(nonce, receivedNonce);
        }
    }

    SingleResp[] singleResponses = basicOCSPResp.getResponses();
    final int countSingleResponses = singleResponses == null ? 0 : singleResponses.length;
    if (countSingleResponses != serialNumbers.length) {
        StringBuilder sb = new StringBuilder(100);
        sb.append("response with ").append(countSingleResponses).append(" singleRessponse");
        if (countSingleResponses > 1) {
            sb.append("s");
        }
        sb.append(" is returned, expected is ").append(serialNumbers.length);
        throw new OCSPTargetUnmatchedException(sb.toString());
    }

    CertificateID certID = ocspReq.getRequestList()[0].getCertID();
    ASN1ObjectIdentifier issuerHashAlg = certID.getHashAlgOID();
    byte[] issuerKeyHash = certID.getIssuerKeyHash();
    byte[] issuerNameHash = certID.getIssuerNameHash();

    if (serialNumbers.length == 1) {
        SingleResp m = singleResponses[0];
        CertificateID cid = m.getCertID();
        boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID())
                && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash())
                && Arrays.equals(issuerNameHash, cid.getIssuerNameHash());

        if (issuerMatch == false) {
            throw new OCSPTargetUnmatchedException("the issuer is not requested");
        }

        BigInteger serialNumber = cid.getSerialNumber();
        if (serialNumbers[0].equals(serialNumber) == false) {
            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 < singleResponses.length; i++) {
            SingleResp m = singleResponses[i];
            CertificateID cid = m.getCertID();
            boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID())
                    && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash())
                    && Arrays.equals(issuerNameHash, cid.getIssuerNameHash());

            if (issuerMatch == false) {
                throw new OCSPTargetUnmatchedException(
                        "the issuer specified in singleResponse[" + i + "] is not requested");
            }

            BigInteger serialNumber = cid.getSerialNumber();
            if (tmpSerials2.remove(serialNumber) == false) {
                if (tmpSerials1.contains(serialNumber)) {
                    throw new OCSPTargetUnmatchedException(
                            "serialNumber " + serialNumber + "is contained in at least two singleResponses");
                } else {
                    throw new OCSPTargetUnmatchedException(
                            "the serialNumber specified in singleResponse[" + i + "] is not requested");
                }
            }
        }
    }

    return ocspResp;
}

From source file:org.xipki.ocsp.server.impl.OcspServer.java

License:Open Source License

public OcspRespWithCacheInfo answer(final Responder responder, final OCSPReq request,
        final AuditEvent auditEvent, final boolean viaGet) {
    ResponderOption responderOption = responder.getResponderOption();
    RequestOption requestOption = responder.getRequestOption();
    ResponseOption responseOption = responder.getResponseOption();
    ResponderSigner signer = responder.getSigner();
    AuditOption auditOption = responder.getAuditOption();
    CertprofileOption certprofileOption = responder.getCertprofileOption();

    int version = request.getVersionNumber();
    if (requestOption.isVersionAllowed(version) == false) {
        String message = "invalid request version " + version;
        LOG.warn(message);// w  w  w.  j  a  v  a2  s  .c  o m
        if (auditEvent != null) {
            fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message);
        }
        return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
    }

    try {
        OcspRespWithCacheInfo resp = checkSignature(request, requestOption, auditEvent);
        if (resp != null) {
            return resp;
        }

        boolean couldCacheInfo = viaGet;

        List<Extension> responseExtensions = new ArrayList<>(2);

        Req[] requestList = request.getRequestList();
        int n = requestList.length;

        Set<ASN1ObjectIdentifier> criticalExtensionOIDs = new HashSet<>();
        Set<?> tmp = request.getCriticalExtensionOIDs();
        if (tmp != null) {
            for (Object oid : tmp) {
                criticalExtensionOIDs.add((ASN1ObjectIdentifier) oid);
            }
        }

        RespID respID = new RespID(signer.getResponderId());
        BasicOCSPRespBuilder basicOcspBuilder = new BasicOCSPRespBuilder(respID);
        ASN1ObjectIdentifier extensionType = OCSPObjectIdentifiers.id_pkix_ocsp_nonce;
        criticalExtensionOIDs.remove(extensionType);
        Extension nonceExtn = request.getExtension(extensionType);
        if (nonceExtn != null) {
            byte[] nonce = nonceExtn.getExtnValue().getOctets();
            int len = nonce.length;
            int min = requestOption.getNonceMinLen();
            int max = requestOption.getNonceMaxLen();

            if (len < min || len > max) {
                LOG.warn("length of nonce {} not within [{},{}]", new Object[] { len, min, max });
                if (auditEvent != null) {
                    StringBuilder sb = new StringBuilder();
                    sb.append("length of nonce ").append(len);
                    sb.append(" not within [").append(min).append(", ").append(max);
                    fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, sb.toString());
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            }

            couldCacheInfo = false;
            responseExtensions.add(nonceExtn);
        } else if (requestOption.isNonceRequired()) {
            String message = "nonce required, but is not present in the request";
            LOG.warn(message);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message);
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
        }

        boolean includeExtendedRevokeExtension = false;

        long cacheThisUpdate = 0;
        long cacheNextUpdate = Long.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            AuditChildEvent childAuditEvent = null;
            if (auditEvent != null) {
                childAuditEvent = new AuditChildEvent();
                auditEvent.addChildAuditEvent(childAuditEvent);
            }

            Req req = requestList[i];
            CertificateID certID = req.getCertID();
            String certIdHashAlgo = certID.getHashAlgOID().getId();
            HashAlgoType reqHashAlgo = HashAlgoType.getHashAlgoType(certIdHashAlgo);
            if (reqHashAlgo == null) {
                LOG.warn("unknown CertID.hashAlgorithm {}", certIdHashAlgo);
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED,
                            "unknown CertID.hashAlgorithm " + certIdHashAlgo);
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            } else if (requestOption.allows(reqHashAlgo) == false) {
                LOG.warn("CertID.hashAlgorithm {} not allowed", certIdHashAlgo);
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED,
                            "CertID.hashAlgorithm " + certIdHashAlgo + " not allowed");
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            }

            CertStatusInfo certStatusInfo = null;
            CertStatusStore answeredStore = null;
            boolean exceptionOccurs = false;

            for (CertStatusStore store : responder.getStores()) {
                try {
                    certStatusInfo = store.getCertStatus(reqHashAlgo, certID.getIssuerNameHash(),
                            certID.getIssuerKeyHash(), certID.getSerialNumber(),
                            responseOption.isIncludeCerthash(), responseOption.getCertHashAlgo(),
                            certprofileOption);
                    if (certStatusInfo.getCertStatus() != CertStatus.ISSUER_UNKNOWN) {
                        answeredStore = store;
                        break;
                    }
                } catch (CertStatusStoreException e) {
                    exceptionOccurs = true;
                    final String message = "getCertStatus() of CertStatusStore " + store.getName();
                    if (LOG.isErrorEnabled()) {
                        LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(),
                                e.getMessage());
                    }
                    LOG.debug(message, e);
                }
            }

            if (certStatusInfo == null) {
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                            "no CertStatusStore can answer the request");
                }
                if (exceptionOccurs) {
                    return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater);
                } else {
                    certStatusInfo = CertStatusInfo.getIssuerUnknownCertStatusInfo(new Date(), null);
                }
            } else if (answeredStore != null) {
                if (responderOption.isInheritCaRevocation()) {
                    CertRevocationInfo caRevInfo = answeredStore.getCARevocationInfo(reqHashAlgo,
                            certID.getIssuerNameHash(), certID.getIssuerKeyHash());
                    if (caRevInfo != null) {
                        CertStatus certStatus = certStatusInfo.getCertStatus();
                        boolean replaced = false;
                        if (certStatus == CertStatus.GOOD || certStatus == CertStatus.UNKNOWN) {
                            replaced = true;
                        } else if (certStatus == CertStatus.REVOKED) {
                            if (certStatusInfo.getRevocationInfo().getRevocationTime()
                                    .after(caRevInfo.getRevocationTime())) {
                                replaced = true;
                            }
                        }

                        if (replaced) {
                            CertRevocationInfo newRevInfo;
                            if (caRevInfo.getReason() == CRLReason.CA_COMPROMISE) {
                                newRevInfo = caRevInfo;
                            } else {
                                newRevInfo = new CertRevocationInfo(CRLReason.CA_COMPROMISE,
                                        caRevInfo.getRevocationTime(), caRevInfo.getInvalidityTime());
                            }
                            certStatusInfo = CertStatusInfo.getRevokedCertStatusInfo(newRevInfo,
                                    certStatusInfo.getCertHashAlgo(), certStatusInfo.getCertHash(),
                                    certStatusInfo.getThisUpdate(), certStatusInfo.getNextUpdate(),
                                    certStatusInfo.getCertprofile());
                        }
                    }
                }
            }

            if (childAuditEvent != null) {
                String certprofile = certStatusInfo.getCertprofile();
                String auditCertType;
                if (certprofile != null) {
                    auditCertType = auditOption.getCertprofileMapping().get(certprofile);
                    if (auditCertType == null) {
                        auditCertType = certprofile;
                    }
                } else {
                    auditCertType = "UNKNOWN";
                }

                childAuditEvent.addEventData(new AuditEventData("certType", auditCertType));
            }

            // certStatusInfo could not be null in any case, since at least one store is configured
            Date thisUpdate = certStatusInfo.getThisUpdate();
            if (thisUpdate == null) {
                thisUpdate = new Date();
            }
            Date nextUpdate = certStatusInfo.getNextUpdate();

            List<Extension> extensions = new LinkedList<>();
            boolean unknownAsRevoked = false;
            CertificateStatus bcCertStatus = null;
            switch (certStatusInfo.getCertStatus()) {
            case GOOD:
                bcCertStatus = null;
                break;

            case ISSUER_UNKNOWN:
                couldCacheInfo = false;
                bcCertStatus = new UnknownStatus();
                break;

            case UNKNOWN:
            case IGNORE:
                couldCacheInfo = false;
                if (responderOption.getMode() == OCSPMode.RFC2560) {
                    bcCertStatus = new UnknownStatus();
                } else// (ocspMode == OCSPMode.RFC6960)
                {
                    unknownAsRevoked = true;
                    includeExtendedRevokeExtension = true;
                    bcCertStatus = new RevokedStatus(new Date(0L), CRLReason.CERTIFICATE_HOLD.getCode());
                }
                break;
            case REVOKED:
                CertRevocationInfo revInfo = certStatusInfo.getRevocationInfo();
                ASN1GeneralizedTime revTime = new ASN1GeneralizedTime(revInfo.getRevocationTime());
                org.bouncycastle.asn1.x509.CRLReason _reason = null;
                if (responseOption.isIncludeRevReason()) {
                    _reason = org.bouncycastle.asn1.x509.CRLReason.lookup(revInfo.getReason().getCode());
                }
                RevokedInfo _revInfo = new RevokedInfo(revTime, _reason);
                bcCertStatus = new RevokedStatus(_revInfo);

                Date invalidityDate = revInfo.getInvalidityTime();
                if (responseOption.isIncludeInvalidityDate() && invalidityDate != null
                        && invalidityDate.equals(revTime) == false) {
                    Extension extension = new Extension(Extension.invalidityDate, false,
                            new ASN1GeneralizedTime(invalidityDate).getEncoded());
                    extensions.add(extension);
                }
                break;
            }

            byte[] certHash = certStatusInfo.getCertHash();
            if (certHash != null) {
                ASN1ObjectIdentifier hashAlgoOid = new ASN1ObjectIdentifier(
                        certStatusInfo.getCertHashAlgo().getOid());
                AlgorithmIdentifier aId = new AlgorithmIdentifier(hashAlgoOid, DERNull.INSTANCE);
                CertHash bcCertHash = new CertHash(aId, certHash);

                byte[] encodedCertHash;
                try {
                    encodedCertHash = bcCertHash.getEncoded();
                } catch (IOException e) {
                    final String message = "answer() bcCertHash.getEncoded";
                    if (LOG.isErrorEnabled()) {
                        LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(),
                                e.getMessage());
                    }
                    LOG.debug(message, e);
                    if (childAuditEvent != null) {
                        fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                                "CertHash.getEncoded() with IOException");
                    }
                    return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
                }

                Extension extension = new Extension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash, false,
                        encodedCertHash);

                extensions.add(extension);
            }

            if (certStatusInfo.getArchiveCutOff() != null) {
                Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff, false,
                        new ASN1GeneralizedTime(certStatusInfo.getArchiveCutOff()).getEncoded());
                extensions.add(extension);
            }

            String certStatusText;
            if (bcCertStatus instanceof UnknownStatus) {
                certStatusText = "unknown";
            } else if (bcCertStatus instanceof RevokedStatus) {
                certStatusText = unknownAsRevoked ? "unknown_as_revoked" : "revoked";
            } else if (bcCertStatus == null) {
                certStatusText = "good";
            } else {
                certStatusText = "should-not-happen";
            }

            if (childAuditEvent != null) {
                childAuditEvent.setLevel(AuditLevel.INFO);
                childAuditEvent.setStatus(AuditStatus.SUCCESSFUL);
                childAuditEvent.addEventData(new AuditEventData("certStatus", certStatusText));
            }

            if (LOG.isDebugEnabled()) {
                StringBuilder sb = new StringBuilder();
                sb.append("certHashAlgo: ").append(certID.getHashAlgOID().getId()).append(", ");

                String hexCertHash = null;
                if (certHash != null) {
                    hexCertHash = Hex.toHexString(certHash).toUpperCase();
                }

                sb.append("issuerKeyHash: ").append(Hex.toHexString(certID.getIssuerKeyHash()).toUpperCase())
                        .append(", ");
                sb.append("issuerNameHash: ").append(Hex.toHexString(certID.getIssuerNameHash()).toUpperCase())
                        .append(", ");
                sb.append("serialNumber: ").append(certID.getSerialNumber()).append(", ");
                sb.append("certStatus: ").append(certStatusText).append(", ");
                sb.append("thisUpdate: ").append(thisUpdate).append(", ");
                sb.append("nextUpdate: ").append(nextUpdate).append(", ");
                sb.append("certHash: ").append(hexCertHash);
                LOG.debug(sb.toString());
            }

            basicOcspBuilder.addResponse(certID, bcCertStatus, thisUpdate, nextUpdate,
                    CollectionUtil.isEmpty(extensions) ? null
                            : new Extensions(extensions.toArray(new Extension[0])));
            cacheThisUpdate = Math.max(cacheThisUpdate, thisUpdate.getTime());
            if (nextUpdate != null) {
                cacheNextUpdate = Math.min(cacheNextUpdate, nextUpdate.getTime());
            }
        }

        if (includeExtendedRevokeExtension) {
            responseExtensions.add(new Extension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke, true,
                    DERNull.INSTANCE.getEncoded()));
        }

        if (CollectionUtil.isNotEmpty(responseExtensions)) {
            basicOcspBuilder
                    .setResponseExtensions(new Extensions(responseExtensions.toArray(new Extension[0])));
        }

        ConcurrentContentSigner concurrentSigner = null;
        if (responderOption.getMode() != OCSPMode.RFC2560) {
            extensionType = ObjectIdentifiers.id_pkix_ocsp_prefSigAlgs;
            criticalExtensionOIDs.remove(extensionType);
            Extension ext = request.getExtension(extensionType);
            if (ext != null) {
                ASN1Sequence preferredSigAlgs = ASN1Sequence.getInstance(ext.getParsedValue());
                concurrentSigner = signer.getSignerForPreferredSigAlgs(preferredSigAlgs);
            }
        }

        if (CollectionUtil.isNotEmpty(criticalExtensionOIDs)) {
            return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
        }

        if (concurrentSigner == null) {
            concurrentSigner = signer.getFirstSigner();
        }

        ContentSigner singleSigner;
        try {
            singleSigner = concurrentSigner.borrowContentSigner();
        } catch (NoIdleSignerException e) {
            return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater);
        }

        X509CertificateHolder[] certsInResp;
        EmbedCertsMode certsMode = responseOption.getEmbedCertsMode();
        if (certsMode == null || certsMode == EmbedCertsMode.SIGNER) {
            certsInResp = new X509CertificateHolder[] { signer.getBcCertificate() };
        } else if (certsMode == EmbedCertsMode.SIGNER_AND_CA) {
            certsInResp = signer.getBcCertificateChain();
        } else {
            // NONE
            certsInResp = null;
        }

        BasicOCSPResp basicOcspResp;
        try {
            basicOcspResp = basicOcspBuilder.build(singleSigner, certsInResp, new Date());
        } catch (OCSPException e) {
            final String message = "answer() basicOcspBuilder.build";
            if (LOG.isErrorEnabled()) {
                LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage());
            }
            LOG.debug(message, e);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                        "BasicOCSPRespBuilder.build() with OCSPException");
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
        } finally {
            concurrentSigner.returnContentSigner(singleSigner);
        }

        OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
        try {
            OCSPResp ocspResp = ocspRespBuilder.build(OcspResponseStatus.successfull.getStatus(),
                    basicOcspResp);

            if (couldCacheInfo) {
                ResponseCacheInfo cacheInfo = new ResponseCacheInfo(cacheThisUpdate);
                if (cacheNextUpdate != Long.MAX_VALUE) {
                    cacheInfo.setNextUpdate(cacheNextUpdate);
                }
                return new OcspRespWithCacheInfo(ocspResp, cacheInfo);
            } else {
                return new OcspRespWithCacheInfo(ocspResp, null);
            }
        } catch (OCSPException e) {
            final String message = "answer() ocspRespBuilder.build";
            if (LOG.isErrorEnabled()) {
                LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage());
            }
            LOG.debug(message, e);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                        "OCSPRespBuilder.build() with OCSPException");
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
        }

    } catch (Throwable t) {
        final String message = "Throwable";
        if (LOG.isErrorEnabled()) {
            LOG.error(LogUtil.buildExceptionLogFormat(message), t.getClass().getName(), t.getMessage());
        }
        LOG.debug(message, t);

        if (auditEvent != null) {
            fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "internal error");
        }

        return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
    }
}

From source file:org.xipki.pki.ocsp.client.impl.AbstractOcspRequestor.java

License:Open Source License

@Override
public OCSPResp ask(final X509Certificate issuerCert, final BigInteger[] serialNumbers, final URL responderUrl,
        final RequestOptions requestOptions, final 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());
    }// ww  w .  j ava2  s .c o m

    OCSPReq 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);
        msgPair.setRequest(encodedReq);
    }

    byte[] encodedResp;
    try {
        encodedResp = send(encodedReq, responderUrl, requestOptions);
    } catch (IOException ex) {
        throw new ResponderUnreachableException("IOException: " + ex.getMessage(), ex);
    }

    if (msgPair != null) {
        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) {
        StringBuilder sb = new StringBuilder(100);
        sb.append("response with no singleResponse is returned, expected is ");
        sb.append(serialNumbers.length);
        throw new OcspTargetUnmatchedException(sb.toString());
    }

    final int countSingleResponses = singleResponses.length;

    if (countSingleResponses != serialNumbers.length) {
        StringBuilder sb = new StringBuilder(100);
        sb.append("response with ").append(countSingleResponses).append(" singleResponse");
        if (countSingleResponses > 1) {
            sb.append("s");
        }
        sb.append(" is returned, expected is ").append(serialNumbers.length);
        throw new OcspTargetUnmatchedException(sb.toString());
    }

    CertificateID certId = ocspReq.getRequestList()[0].getCertID();
    ASN1ObjectIdentifier issuerHashAlg = certId.getHashAlgOID();
    byte[] issuerKeyHash = certId.getIssuerKeyHash();
    byte[] issuerNameHash = certId.getIssuerNameHash();

    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
    } // end if

    return ocspResp;
}

From source file:org.xipki.pki.ocsp.client.shell.OcspStatusCmd.java

License:Open Source License

@Override
protected Object processResponse(final OCSPResp response, final X509Certificate respIssuer,
        final IssuerHash issuerHash, final List<BigInteger> serialNumbers,
        final Map<BigInteger, byte[]> encodedCerts) throws Exception {
    ParamUtil.requireNonNull("response", response);
    ParamUtil.requireNonNull("issuerHash", issuerHash);
    ParamUtil.requireNonNull("serialNumbers", serialNumbers);

    BasicOCSPResp basicResp = OcspUtils.extractBasicOcspResp(response);

    boolean extendedRevoke = basicResp.getExtension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke) != null;

    SingleResp[] singleResponses = basicResp.getResponses();

    if (singleResponses == null || singleResponses.length == 0) {
        throw new CmdFailure("received no status from server");
    }//from w w  w  .  ja v  a 2 s  . c  o m

    final int n = singleResponses.length;
    if (n != serialNumbers.size()) {
        throw new CmdFailure("received status with " + n + " single responses from server, but "
                + serialNumbers.size() + " were requested");
    }

    Date[] thisUpdates = new Date[n];
    for (int i = 0; i < n; i++) {
        thisUpdates[i] = singleResponses[i].getThisUpdate();
    }

    // check the signature if available
    if (null == basicResp.getSignature()) {
        println("response is not signed");
    } else {
        X509CertificateHolder[] responderCerts = basicResp.getCerts();
        if (responderCerts == null || responderCerts.length < 1) {
            throw new CmdFailure("no responder certificate is contained in the response");
        }

        ResponderID respId = basicResp.getResponderId().toASN1Primitive();
        X500Name respIdByName = respId.getName();
        byte[] respIdByKey = respId.getKeyHash();

        X509CertificateHolder respSigner = null;
        for (X509CertificateHolder cert : responderCerts) {
            if (respIdByName != null) {
                if (cert.getSubject().equals(respIdByName)) {
                    respSigner = cert;
                }
            } else {
                byte[] spkiSha1 = HashAlgoType.SHA1
                        .hash(cert.getSubjectPublicKeyInfo().getPublicKeyData().getBytes());
                if (Arrays.equals(respIdByKey, spkiSha1)) {
                    respSigner = cert;
                }
            }

            if (respSigner != null) {
                break;
            }
        }

        if (respSigner == null) {
            throw new CmdFailure("no responder certificate match the ResponderId");
        }

        boolean validOn = true;
        for (Date thisUpdate : thisUpdates) {
            validOn = respSigner.isValidOn(thisUpdate);
            if (!validOn) {
                throw new CmdFailure("responder certificate is not valid on " + thisUpdate);
            }
        }

        if (validOn) {
            PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo());
            ContentVerifierProvider cvp = securityFactory.getContentVerifierProvider(responderPubKey);
            boolean sigValid = basicResp.isSignatureValid(cvp);

            if (!sigValid) {
                throw new CmdFailure("response is equipped with invalid signature");
            }

            // verify the OCSPResponse signer
            if (respIssuer != null) {
                boolean certValid = true;
                X509Certificate jceRespSigner = X509Util.toX509Cert(respSigner.toASN1Structure());
                if (X509Util.issues(respIssuer, jceRespSigner)) {
                    try {
                        jceRespSigner.verify(respIssuer.getPublicKey());
                    } catch (SignatureException ex) {
                        certValid = false;
                    }
                }

                if (!certValid) {
                    throw new CmdFailure("response is equipped with valid signature but the"
                            + " OCSP signer is not trusted");
                }
            } else {
                println("response is equipped with valid signature");
            } // end if(respIssuer)
        } // end if(validOn)

        if (verbose.booleanValue()) {
            println("responder is " + X509Util.getRfc4519Name(responderCerts[0].getSubject()));
        }
    } // end if

    for (int i = 0; i < n; i++) {
        if (n > 1) {
            println("---------------------------- " + i + "----------------------------");
        }
        SingleResp singleResp = singleResponses[i];
        CertificateStatus singleCertStatus = singleResp.getCertStatus();

        String status;
        if (singleCertStatus == null) {
            status = "good";
        } else if (singleCertStatus instanceof RevokedStatus) {
            RevokedStatus revStatus = (RevokedStatus) singleCertStatus;
            Date revTime = revStatus.getRevocationTime();
            Date invTime = null;
            Extension ext = singleResp.getExtension(Extension.invalidityDate);
            if (ext != null) {
                invTime = ASN1GeneralizedTime.getInstance(ext.getParsedValue()).getDate();
            }

            if (revStatus.hasRevocationReason()) {
                int reason = revStatus.getRevocationReason();
                if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode()
                        && revTime.getTime() == 0) {
                    status = "unknown (RFC6960)";
                } else {
                    StringBuilder sb = new StringBuilder("revoked, reason = ");
                    sb.append(CrlReason.forReasonCode(reason).getDescription());
                    sb.append(", revocationTime = ").append(revTime);
                    if (invTime != null) {
                        sb.append(", invalidityTime = ").append(invTime);
                    }
                    status = sb.toString();
                }
            } else {
                status = "revoked, no reason, revocationTime = " + revTime;
            }
        } else if (singleCertStatus instanceof UnknownStatus) {
            status = "unknown (RFC2560)";
        } else {
            status = "ERROR";
        }

        StringBuilder msg = new StringBuilder();

        CertificateID certId = singleResp.getCertID();
        HashAlgoType hashAlgo = HashAlgoType.getNonNullHashAlgoType(certId.getHashAlgOID());
        boolean issuerMatch = issuerHash.match(hashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash());
        BigInteger serialNumber = certId.getSerialNumber();

        msg.append("issuer matched: ").append(issuerMatch);
        msg.append("\nserialNumber: ").append(LogUtil.formatCsn(serialNumber));
        msg.append("\nCertificate status: ").append(status);

        if (verbose.booleanValue()) {
            msg.append("\nthisUpdate: ").append(singleResp.getThisUpdate());
            msg.append("\nnextUpdate: ").append(singleResp.getNextUpdate());

            Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash);
            if (extension != null) {
                msg.append("\nCertHash is provided:\n");
                ASN1Encodable extensionValue = extension.getParsedValue();
                CertHash certHash = CertHash.getInstance(extensionValue);
                ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm();
                byte[] hashValue = certHash.getCertificateHash();

                msg.append("\tHash algo : ").append(hashAlgOid.getId()).append("\n");
                msg.append("\tHash value: ").append(Hex.toHexString(hashValue)).append("\n");

                if (encodedCerts != null) {
                    byte[] encodedCert = encodedCerts.get(serialNumber);
                    MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId());
                    byte[] expectedHashValue = md.digest(encodedCert);
                    if (Arrays.equals(expectedHashValue, hashValue)) {
                        msg.append("\tThis matches the requested certificate");
                    } else {
                        msg.append("\tThis differs from the requested certificate");
                    }
                }
            } // end if (extension != null)

            extension = singleResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff);
            if (extension != null) {
                ASN1Encodable extensionValue = extension.getParsedValue();
                ASN1GeneralizedTime time = ASN1GeneralizedTime.getInstance(extensionValue);
                msg.append("\nArchive-CutOff: ");
                msg.append(time.getTimeString());
            }

            AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID();
            if (sigAlg == null) {
                msg.append(("\nresponse is not signed"));
            } else {
                String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg);
                if (sigAlgName == null) {
                    sigAlgName = "unknown";
                }
                msg.append("\nresponse is signed with ").append(sigAlgName);
            }

            // extensions
            msg.append("\nExtensions: ");

            List<?> extensionOids = basicResp.getExtensionOIDs();
            if (extensionOids == null || extensionOids.size() == 0) {
                msg.append("-");
            } else {
                int size = extensionOids.size();
                for (int j = 0; j < size; j++) {
                    ASN1ObjectIdentifier extensionOid = (ASN1ObjectIdentifier) extensionOids.get(j);
                    String name = EXTENSION_OIDNAME_MAP.get(extensionOid);
                    if (name == null) {
                        msg.append(extensionOid.getId());
                    } else {
                        msg.append(name);
                    }
                    if (j != size - 1) {
                        msg.append(", ");
                    }
                }
            }
        } // end if (verbose.booleanValue())

        println(msg.toString());
    } // end for
    println("");

    return null;
}