org.cesecore.certificates.ocsp.standalone.StandaloneOcspResponseGeneratorSessionTest.java Source code

Java tutorial

Introduction

Here is the source code for org.cesecore.certificates.ocsp.standalone.StandaloneOcspResponseGeneratorSessionTest.java

Source

/*************************************************************************
 *                                                                       *
 *  CESeCore: CE Security Core                                           *
 *                                                                       *
 *  This software is free software; you can redistribute it and/or       *
 *  modify it under the terms of the GNU Lesser General Public           *
 *  License as published by the Free Software Foundation; either         *
 *  version 2.1 of the License, or any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/
package org.cesecore.certificates.ocsp.standalone;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.OCSPException;
import org.bouncycastle.cert.ocsp.OCSPReq;
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
import org.bouncycastle.cert.ocsp.RevokedStatus;
import org.bouncycastle.cert.ocsp.SingleResp;
import org.bouncycastle.cert.ocsp.UnknownStatus;
import org.bouncycastle.cert.ocsp.jcajce.JcaCertificateID;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.BufferingContentSigner;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.cesecore.authentication.tokens.AuthenticationToken;
import org.cesecore.certificates.ca.CAConstants;
import org.cesecore.certificates.ca.CAInfo;
import org.cesecore.certificates.ca.CaSessionRemote;
import org.cesecore.certificates.ca.X509CA;
import org.cesecore.certificates.ca.X509CAInfo;
import org.cesecore.certificates.ca.catoken.CAToken;
import org.cesecore.certificates.certificate.CertificateConstants;
import org.cesecore.certificates.certificate.CertificateCreateSessionRemote;
import org.cesecore.certificates.certificate.CertificateStoreSessionRemote;
import org.cesecore.certificates.certificate.InternalCertificateStoreSessionRemote;
import org.cesecore.certificates.certificate.request.SimpleRequestMessage;
import org.cesecore.certificates.certificate.request.X509ResponseMessage;
import org.cesecore.certificates.certificateprofile.CertificateProfileConstants;
import org.cesecore.certificates.crl.RevokedCertInfo;
import org.cesecore.certificates.endentity.EndEntityConstants;
import org.cesecore.certificates.endentity.EndEntityInformation;
import org.cesecore.certificates.endentity.EndEntityType;
import org.cesecore.certificates.endentity.EndEntityTypes;
import org.cesecore.certificates.ocsp.OcspResponseGeneratorSessionRemote;
import org.cesecore.certificates.ocsp.OcspResponseInformation;
import org.cesecore.certificates.ocsp.OcspTestUtils;
import org.cesecore.certificates.ocsp.SHA1DigestCalculator;
import org.cesecore.certificates.ocsp.exception.MalformedRequestException;
import org.cesecore.certificates.ocsp.logging.AuditLogger;
import org.cesecore.certificates.ocsp.logging.GuidHolder;
import org.cesecore.certificates.ocsp.logging.TransactionCounter;
import org.cesecore.certificates.ocsp.logging.TransactionLogger;
import org.cesecore.certificates.util.AlgorithmConstants;
import org.cesecore.config.ConfigurationHolder;
import org.cesecore.config.GlobalOcspConfiguration;
import org.cesecore.config.OcspConfiguration;
import org.cesecore.configuration.CesecoreConfigurationProxySessionRemote;
import org.cesecore.configuration.GlobalConfigurationSessionRemote;
import org.cesecore.junit.util.CryptoTokenRule;
import org.cesecore.junit.util.CryptoTokenTestRunner;
import org.cesecore.keybind.InternalKeyBinding;
import org.cesecore.keybind.InternalKeyBindingMgmtSessionRemote;
import org.cesecore.keybind.InternalKeyBindingStatus;
import org.cesecore.keybind.InternalKeyBindingTrustEntry;
import org.cesecore.keybind.impl.OcspKeyBinding;
import org.cesecore.keys.token.CryptoTokenManagementSessionRemote;
import org.cesecore.keys.token.CryptoTokenTestUtils;
import org.cesecore.keys.token.NullCryptoToken;
import org.cesecore.keys.util.KeyTools;
import org.cesecore.mock.authentication.tokens.TestAlwaysAllowLocalAuthenticationToken;
import org.cesecore.util.CertTools;
import org.cesecore.util.EjbRemoteHelper;
import org.cesecore.util.TraceLogMethodsRule;
import org.ejbca.core.ejb.ca.sign.SignSessionRemote;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;

/**
 * Functional tests for StandaloneOcspResponseGeneratorSessionBean
 * 
 * @version $Id: StandaloneOcspResponseGeneratorSessionTest.java 20516 2015-01-08 17:26:01Z mikekushner $
 * 
 */
@RunWith(CryptoTokenTestRunner.class)
public class StandaloneOcspResponseGeneratorSessionTest {

    private static final String TESTCLASSNAME = StandaloneOcspResponseGeneratorSessionTest.class.getSimpleName();
    private static final Logger log = Logger.getLogger(StandaloneOcspResponseGeneratorSessionTest.class);

    private String originalSigningTruststoreValidTime;

    private final CaSessionRemote caSession = EjbRemoteHelper.INSTANCE.getRemoteSession(CaSessionRemote.class);
    private final CertificateCreateSessionRemote certificateCreateSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(CertificateCreateSessionRemote.class);
    private final CertificateStoreSessionRemote certificateStoreSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(CertificateStoreSessionRemote.class);
    private final CesecoreConfigurationProxySessionRemote cesecoreConfigurationProxySession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(CesecoreConfigurationProxySessionRemote.class, EjbRemoteHelper.MODULE_TEST);
    private final CryptoTokenManagementSessionRemote cryptoTokenManagementSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(CryptoTokenManagementSessionRemote.class);
    private final GlobalConfigurationSessionRemote globalConfigurationSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(GlobalConfigurationSessionRemote.class);
    private final InternalCertificateStoreSessionRemote internalCertificateStoreSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(InternalCertificateStoreSessionRemote.class, EjbRemoteHelper.MODULE_TEST);
    private final InternalKeyBindingMgmtSessionRemote internalKeyBindingMgmtSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(InternalKeyBindingMgmtSessionRemote.class);
    private final OcspResponseGeneratorSessionRemote ocspResponseGeneratorSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(OcspResponseGeneratorSessionRemote.class);
    private final SignSessionRemote signSession = EjbRemoteHelper.INSTANCE
            .getRemoteSession(SignSessionRemote.class);

    private final AuthenticationToken authenticationToken = new TestAlwaysAllowLocalAuthenticationToken(
            TESTCLASSNAME);

    private X509CA x509ca;
    private int internalKeyBindingId;
    private int cryptoTokenId;
    private X509Certificate ocspSigningCertificate;
    private X509Certificate caCertificate;
    private static String originalDefaultResponder;

    @BeforeClass
    public static void beforeClass() throws Exception {
        GlobalConfigurationSessionRemote globalConfigurationSession = EjbRemoteHelper.INSTANCE
                .getRemoteSession(GlobalConfigurationSessionRemote.class);
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        originalDefaultResponder = ocspConfiguration.getOcspDefaultResponderReference();

    }

    @Rule
    public TestRule traceLogMethodsRule = new TraceLogMethodsRule();

    @ClassRule
    public static CryptoTokenRule cryptoTokenRule = new CryptoTokenRule();

    @Before
    public void setUp() throws Exception {
        x509ca = cryptoTokenRule.createX509Ca();
        originalSigningTruststoreValidTime = cesecoreConfigurationProxySession
                .getConfigurationValue(OcspConfiguration.SIGNING_TRUSTSTORE_VALID_TIME);
        //Make sure timers don't run while we debug
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNING_TRUSTSTORE_VALID_TIME,
                Integer.toString(Integer.MAX_VALUE / 1000));
        //Create an independent cryptotoken
        cryptoTokenId = cryptoTokenRule.createCryptoToken();
        internalKeyBindingId = OcspTestUtils.createInternalKeyBinding(authenticationToken, cryptoTokenId,
                OcspKeyBinding.IMPLEMENTATION_ALIAS, TESTCLASSNAME, "RSA2048",
                AlgorithmConstants.SIGALG_SHA1_WITH_RSA);
        String signerDN = "CN=ocspTestSigner";
        caCertificate = (X509Certificate) x509ca.getCACertificate();
        ocspSigningCertificate = OcspTestUtils.createOcspSigningCertificate(authenticationToken,
                OcspTestUtils.OCSP_END_USER_NAME, signerDN, internalKeyBindingId, x509ca.getCAId());
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED, "false");

    }

    @After
    public void tearDown() throws Exception {
        cryptoTokenRule.cleanUp();
        try {
            internalCertificateStoreSession.removeCertificate(ocspSigningCertificate);
        } catch (Exception e) {
            //Ignore any failures.
        }
        internalKeyBindingMgmtSession.deleteInternalKeyBinding(authenticationToken, internalKeyBindingId);
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNING_TRUSTSTORE_VALID_TIME,
                originalSigningTruststoreValidTime);
        //Make sure default responder is restored
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        ocspConfiguration.setOcspDefaultResponderReference(originalDefaultResponder);
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);
    }

    /** Tests the basic case of a standalone OCSP installation, i.e where this is a classic VA */
    @Test
    public void testStandAloneOcspResponseSanity() throws Exception {
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        activateKeyBinding(internalKeyBindingId);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        // Do the OCSP request
        final OCSPReq ocspRequest = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp response = sendRequest(ocspRequest);
        assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
        validateSuccessfulResponse((BasicOCSPResp) response.getResponseObject(),
                ocspSigningCertificate.getPublicKey());
    }

    /** 
     * Tests the case of a standalone OCSP responder with a revoked certificate
     */
    @Test
    public void testResponseWithRevokedResponder() throws Exception {
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        activateKeyBinding(internalKeyBindingId);
        //Revoke the responder cert
        certificateStoreSession.setRevokeStatus(authenticationToken, ocspSigningCertificate,
                RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE, null);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        // Do the OCSP request
        final OCSPReq ocspRequest = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp response = sendRequest(ocspRequest);
        BasicOCSPResp basicOcspResponse = (BasicOCSPResp) response.getResponseObject();
        SingleResp[] singleResponses = basicOcspResponse.getResponses();
        assertEquals("Delivered some thing else than one and exactly one response.", 1, singleResponses.length);
        assertEquals("Response cert did not match up with request cert", ocspSigningCertificate.getSerialNumber(),
                singleResponses[0].getCertID().getSerialNumber());
        Object status = singleResponses[0].getCertStatus();
        assertTrue("Status is not RevokedStatus", status instanceof RevokedStatus);
        RevokedStatus rev = (RevokedStatus) status;
        assertTrue("Status does not have reason", rev.hasRevocationReason());
        int reason = rev.getRevocationReason();
        assertEquals("Wrong revocation reason", reason, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);
    }

    /** 
     * Tests the case of a standalone OCSP responder with a revoked certificate issuer.
     * 
     * This should respond revoked, as from the RFC:
     * 
     *  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.
     */
    @Test
    public void testResponseWithRevokedResponderIssuer() throws Exception {
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        activateKeyBinding(internalKeyBindingId);
        //Revoke the issuer cert
        certificateStoreSession.setRevokeStatus(authenticationToken, caCertificate,
                RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE, null);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        // Do the OCSP request
        final OCSPReq ocspRequest = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp response = sendRequest(ocspRequest);
        BasicOCSPResp basicOcspResponse = (BasicOCSPResp) response.getResponseObject();
        SingleResp[] singleResponses = basicOcspResponse.getResponses();
        assertEquals("Delivered some thing else than one and exactly one response.", 1, singleResponses.length);
        assertEquals("Response cert did not match up with request cert", ocspSigningCertificate.getSerialNumber(),
                singleResponses[0].getCertID().getSerialNumber());
        Object status = singleResponses[0].getCertStatus();
        assertTrue("Status is not RevokedStatus", status instanceof RevokedStatus);
        RevokedStatus rev = (RevokedStatus) status;
        assertTrue("Status does not have reason", rev.hasRevocationReason());
        int reason = rev.getRevocationReason();
        assertEquals("Wrong revocation reason", reason, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);
    }

    /** Tests using the default responder for external CAs for a good certificate. */
    @Test
    public void testResponseWithDefaultResponderForExternal() throws Exception {
        // Make sure that a default responder is set
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        final String originalDefaultResponder = ocspConfiguration.getOcspDefaultResponderReference();
        ocspConfiguration.setOcspDefaultResponderReference(CertTools.getIssuerDN(ocspSigningCertificate));
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);
        try {
            //Make default responder standalone
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Now, construct an external CA. 
            final String externalCaName = "testStandAloneOcspResponseExternalCa";
            final String externalCaSubjectDn = "CN=" + externalCaName;
            long validity = 3650L;
            KeyPair externalCaKeys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
            Certificate externalCaCertificate = CertTools.genSelfCert(externalCaSubjectDn, validity, null,
                    externalCaKeys.getPrivate(), externalCaKeys.getPublic(),
                    AlgorithmConstants.SIGALG_SHA1_WITH_RSA, true);
            X509CAInfo externalCaInfo = new X509CAInfo(externalCaSubjectDn, externalCaName, CAConstants.CA_EXTERNAL,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, validity, CAInfo.SELFSIGNED, null, null);
            CAToken token = new CAToken(externalCaInfo.getCAId(), new NullCryptoToken().getProperties());
            X509CA externalCa = new X509CA(externalCaInfo);
            externalCa.setCAToken(token);
            externalCa.setCertificateChain(Arrays.asList(externalCaCertificate));
            caSession.addCA(authenticationToken, externalCa);
            certificateStoreSession.storeCertificate(authenticationToken, externalCaCertificate, externalCaName,
                    "1234", CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ROOTCA,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, null, new Date().getTime());
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            try {
                final String externalUsername = "testStandAloneOcspResponseExternalUser";
                final String externalSubjectDn = "CN=" + externalUsername;
                // Create a certificate signed by the external CA and stuff it in the database (we can pretend it was imported)
                Date firstDate = new Date();
                firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
                Date lastDate = new Date();
                lastDate.setTime(lastDate.getTime() + (24 * 60 * 60 * 1000));
                byte[] serno = new byte[8];
                SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
                random.setSeed(new Date().getTime());
                random.nextBytes(serno);
                KeyPair certificateKeyPair = KeyTools.genKeys("1024", "RSA");
                final SubjectPublicKeyInfo pkinfo = new SubjectPublicKeyInfo(
                        (ASN1Sequence) ASN1Primitive.fromByteArray(certificateKeyPair.getPublic().getEncoded()));
                X509v3CertificateBuilder certbuilder = new X509v3CertificateBuilder(
                        CertTools.stringToBcX500Name(externalCaSubjectDn, false), new BigInteger(serno).abs(),
                        firstDate, lastDate, CertTools.stringToBcX500Name(externalSubjectDn, false), pkinfo);
                final ContentSigner signer = new BufferingContentSigner(new JcaContentSignerBuilder("SHA256WithRSA")
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(externalCaKeys.getPrivate()), 20480);
                final X509CertificateHolder certHolder = certbuilder.build(signer);
                X509Certificate importedCertificate = (X509Certificate) CertTools
                        .getCertfromByteArray(certHolder.getEncoded());
                certificateStoreSession.storeCertificate(authenticationToken, importedCertificate, externalUsername,
                        "1234", CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ENDENTITY,
                        CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER, null, new Date().getTime());
                try {
                    //Now everything is in place. Perform a request, make sure that the default responder signed it. 
                    final OCSPReq ocspRequest = buildOcspRequest(null, null,
                            (X509Certificate) externalCaCertificate, importedCertificate.getSerialNumber());
                    final OCSPResp response = sendRequest(ocspRequest);
                    assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
                    final BasicOCSPResp basicOcspResponse = (BasicOCSPResp) response.getResponseObject();
                    assertNotNull("Signed request generated null-response.", basicOcspResponse);
                    assertTrue("OCSP response was not signed correctly.", basicOcspResponse.isSignatureValid(
                            new JcaContentVerifierProviderBuilder().build(ocspSigningCertificate.getPublicKey())));
                    final SingleResp[] singleResponses = basicOcspResponse.getResponses();
                    assertEquals("Delivered some thing else than one and exactly one response.", 1,
                            singleResponses.length);
                    assertEquals("Response cert did not match up with request cert",
                            importedCertificate.getSerialNumber(),
                            singleResponses[0].getCertID().getSerialNumber());
                    assertEquals("Status is not null (good)", null, singleResponses[0].getCertStatus());
                } finally {
                    internalCertificateStoreSession.removeCertificate(importedCertificate);
                }
            } finally {
                caSession.removeCA(authenticationToken, externalCa.getCAId());
                internalCertificateStoreSession.removeCertificate(externalCaCertificate);
            }
        } finally {
            GlobalOcspConfiguration restoredOcspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                    .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
            ocspConfiguration.setOcspDefaultResponderReference(originalDefaultResponder);
            globalConfigurationSession.saveConfiguration(authenticationToken, restoredOcspConfiguration);
        }
    }

    /** Tests using the default responder for external CAs for a good certificate. */
    @Test
    public void testResponseWithDefaultResponderForExternalNoDefaultSet() throws Exception {
        // Make sure that a default responder is set
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        ocspConfiguration.setOcspDefaultResponderReference("");
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);
        String originalNoneExistingIsGood = cesecoreConfigurationProxySession
                .getConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD);
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD, "false");
        try {
            //Make default responder standalone
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Now, construct an external CA. 
            final String externalCaName = "testStandAloneOcspResponseExternalCa";
            final String externalCaSubjectDn = "CN=" + externalCaName;
            long validity = 3650L;
            KeyPair externalCaKeys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
            Certificate externalCaCertificate = CertTools.genSelfCert(externalCaSubjectDn, validity, null,
                    externalCaKeys.getPrivate(), externalCaKeys.getPublic(),
                    AlgorithmConstants.SIGALG_SHA1_WITH_RSA, true);
            X509CAInfo externalCaInfo = new X509CAInfo(externalCaSubjectDn, externalCaName, CAConstants.CA_EXTERNAL,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, validity, CAInfo.SELFSIGNED, null, null);
            CAToken token = new CAToken(externalCaInfo.getCAId(), new NullCryptoToken().getProperties());
            X509CA externalCa = new X509CA(externalCaInfo);
            externalCa.setCAToken(token);
            externalCa.setCertificateChain(Arrays.asList(externalCaCertificate));
            caSession.addCA(authenticationToken, externalCa);
            certificateStoreSession.storeCertificate(authenticationToken, externalCaCertificate, externalCaName,
                    "1234", CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ROOTCA,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, null, new Date().getTime());
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            try {
                final String externalUsername = "testStandAloneOcspResponseExternalUser";
                final String externalSubjectDn = "CN=" + externalUsername;
                // Create a certificate signed by the external CA and stuff it in the database (we can pretend it was imported)
                Date firstDate = new Date();
                firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
                Date lastDate = new Date();
                lastDate.setTime(lastDate.getTime() + (24 * 60 * 60 * 1000));
                byte[] serno = new byte[8];
                SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
                random.setSeed(new Date().getTime());
                random.nextBytes(serno);
                KeyPair certificateKeyPair = KeyTools.genKeys("1024", "RSA");
                final SubjectPublicKeyInfo pkinfo = new SubjectPublicKeyInfo(
                        (ASN1Sequence) ASN1Primitive.fromByteArray(certificateKeyPair.getPublic().getEncoded()));
                X509v3CertificateBuilder certbuilder = new X509v3CertificateBuilder(
                        CertTools.stringToBcX500Name(externalCaSubjectDn, false), new BigInteger(serno).abs(),
                        firstDate, lastDate, CertTools.stringToBcX500Name(externalSubjectDn, false), pkinfo);
                final ContentSigner signer = new BufferingContentSigner(new JcaContentSignerBuilder("SHA256WithRSA")
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(externalCaKeys.getPrivate()), 20480);
                final X509CertificateHolder certHolder = certbuilder.build(signer);
                X509Certificate importedCertificate = (X509Certificate) CertTools
                        .getCertfromByteArray(certHolder.getEncoded());
                certificateStoreSession.storeCertificate(authenticationToken, importedCertificate, externalUsername,
                        "1234", CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ENDENTITY,
                        CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER, null, new Date().getTime());
                try {
                    //Now everything is in place. Perform a request, make sure that the default responder signed it. 
                    final OCSPReq ocspRequest = buildOcspRequest(null, null,
                            (X509Certificate) externalCaCertificate, importedCertificate.getSerialNumber());
                    final OCSPResp response = sendRequest(ocspRequest);
                    assertEquals("Response status not OCSPRespBuilder.UNAUTHORIZED.", response.getStatus(),
                            OCSPRespBuilder.UNAUTHORIZED);
                    assertNull("Response should not have contained a response object.",
                            response.getResponseObject());
                } finally {
                    internalCertificateStoreSession.removeCertificate(importedCertificate);
                }
            } finally {
                caSession.removeCA(authenticationToken, externalCa.getCAId());
                internalCertificateStoreSession.removeCertificate(externalCaCertificate);
            }
        } finally {
            cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD,
                    originalNoneExistingIsGood);
        }
    }

    /** Tests using the default responder for external CAs, tests with a revoked cert */
    @Test
    public void testResponseWithDefaultResponderForExternalRevoked() throws Exception {
        // Make sure that a default responder is set
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        ocspConfiguration.setOcspDefaultResponderReference(CertTools.getIssuerDN(ocspSigningCertificate));
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);
        String originalNoneExistingIsGood = cesecoreConfigurationProxySession
                .getConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD);
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD, "false");
        try {
            //Make default responder standalone
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Now, construct an external CA. 
            final String externalCaName = "testStandAloneOcspResponseExternalCa";
            final String externalCaSubjectDn = "CN=" + externalCaName;
            long validity = 3650L;
            KeyPair externalCaKeys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
            Certificate externalCaCertificate = CertTools.genSelfCert(externalCaSubjectDn, validity, null,
                    externalCaKeys.getPrivate(), externalCaKeys.getPublic(),
                    AlgorithmConstants.SIGALG_SHA1_WITH_RSA, true);
            X509CAInfo externalCaInfo = new X509CAInfo(externalCaSubjectDn, externalCaName, CAConstants.CA_EXTERNAL,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, validity, CAInfo.SELFSIGNED, null, null);
            CAToken token = new CAToken(externalCaInfo.getCAId(), new NullCryptoToken().getProperties());
            X509CA externalCa = new X509CA(externalCaInfo);
            externalCa.setCAToken(token);
            externalCa.setCertificateChain(Arrays.asList(externalCaCertificate));
            caSession.addCA(authenticationToken, externalCa);
            certificateStoreSession.storeCertificate(authenticationToken, externalCaCertificate, externalCaName,
                    "1234", CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ROOTCA,
                    CertificateProfileConstants.CERTPROFILE_NO_PROFILE, null, new Date().getTime());
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            try {
                final String externalUsername = "testStandAloneOcspResponseExternalUser";
                final String externalSubjectDn = "CN=" + externalUsername;
                // Create a certificate signed by the external CA and stuff it in the database (we can pretend it was imported)
                Date firstDate = new Date();
                firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
                Date lastDate = new Date();
                lastDate.setTime(lastDate.getTime() + (24 * 60 * 60 * 1000));
                byte[] serno = new byte[8];
                SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
                random.setSeed(new Date().getTime());
                random.nextBytes(serno);
                KeyPair certificateKeyPair = KeyTools.genKeys("1024", "RSA");
                final SubjectPublicKeyInfo pkinfo = new SubjectPublicKeyInfo(
                        (ASN1Sequence) ASN1Primitive.fromByteArray(certificateKeyPair.getPublic().getEncoded()));
                X509v3CertificateBuilder certbuilder = new X509v3CertificateBuilder(
                        CertTools.stringToBcX500Name(externalCaSubjectDn, false), new BigInteger(serno).abs(),
                        firstDate, lastDate, CertTools.stringToBcX500Name(externalSubjectDn, false), pkinfo);
                final ContentSigner signer = new BufferingContentSigner(new JcaContentSignerBuilder("SHA256WithRSA")
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(externalCaKeys.getPrivate()), 20480);
                final X509CertificateHolder certHolder = certbuilder.build(signer);
                X509Certificate importedCertificate = (X509Certificate) CertTools
                        .getCertfromByteArray(certHolder.getEncoded());
                certificateStoreSession.storeCertificate(authenticationToken, importedCertificate, externalUsername,
                        "1234", CertificateConstants.CERT_REVOKED, CertificateConstants.CERTTYPE_ENDENTITY,
                        CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER, null, new Date().getTime());
                try {
                    //Now everything is in place. Perform a request, make sure that the default responder signed it. 
                    final OCSPReq ocspRequest = buildOcspRequest(null, null,
                            (X509Certificate) externalCaCertificate, importedCertificate.getSerialNumber());
                    final OCSPResp response = sendRequest(ocspRequest);
                    assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
                    final BasicOCSPResp basicOcspResponse = (BasicOCSPResp) response.getResponseObject();
                    assertNotNull("Signed request generated null-response.", basicOcspResponse);
                    assertTrue("OCSP response was not signed correctly.", basicOcspResponse.isSignatureValid(
                            new JcaContentVerifierProviderBuilder().build(ocspSigningCertificate.getPublicKey())));
                    final SingleResp[] singleResponses = basicOcspResponse.getResponses();
                    assertEquals("Delivered some thing else than one and exactly one response.", 1,
                            singleResponses.length);
                    assertEquals("Response cert did not match up with request cert",
                            importedCertificate.getSerialNumber(),
                            singleResponses[0].getCertID().getSerialNumber());
                    assertTrue("Status is not revoked",
                            singleResponses[0].getCertStatus() instanceof RevokedStatus);
                } finally {
                    internalCertificateStoreSession.removeCertificate(importedCertificate);
                }
            } finally {
                caSession.removeCA(authenticationToken, externalCa.getCAId());
                internalCertificateStoreSession.removeCertificate(externalCaCertificate);
            }
        } finally {
            cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.NONE_EXISTING_IS_GOOD,
                    originalNoneExistingIsGood);
        }
    }

    /**
     * This tests the use case where a key binding has been added but the cache hasn't been updated yet, due to long update times.
     * OcspResponseGeneratorSession should handle this without problems. 
     */
    @Test
    public void testCacheMissHandling() throws Exception {
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        activateKeyBinding(internalKeyBindingId);
        final OCSPReq ocspRequest = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp response = sendRequest(ocspRequest);
        assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
        validateSuccessfulResponse((BasicOCSPResp) response.getResponseObject(),
                ocspSigningCertificate.getPublicKey());
    }

    /** Tests asking about an unknown CA, and making sure that the response is correctly signed */
    @Test
    public void testStandAloneOcspResponseDefaultResponder() throws Exception {
        // Make sure that a default responder is set
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        ocspConfiguration.setOcspDefaultResponderReference(CertTools.getIssuerDN(ocspSigningCertificate));
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);
        cesecoreConfigurationProxySession.setConfigurationValue("ocsp.nonexistingisgood", "false");
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            // Do the OCSP request
            final KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
            final X509Certificate fakeIssuerCertificate = CertTools.genSelfCert("CN=fakeCA", 365, null,
                    keys.getPrivate(), keys.getPublic(), AlgorithmConstants.SIGALG_SHA1_WITH_RSA, true);
            final BigInteger fakeSerialNumber = new BigInteger("4711");
            final OCSPReq ocspRequest = buildOcspRequest(null, null, fakeIssuerCertificate, fakeSerialNumber);
            final OCSPResp response = sendRequest(ocspRequest);
            assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
            BasicOCSPResp basicOcspResponse = (BasicOCSPResp) response.getResponseObject();
            //Response will be signed with the OCSP signing certificate, because that certificate's issuing CA was given as a default responder.
            assertTrue("OCSP response was not signed correctly.", basicOcspResponse.isSignatureValid(
                    new JcaContentVerifierProviderBuilder().build(ocspSigningCertificate.getPublicKey())));
            SingleResp[] singleResponses = basicOcspResponse.getResponses();
            assertEquals("Delivered some thing else than one and exactly one response.", 1, singleResponses.length);
            assertEquals("Response cert did not match up with request cert", fakeSerialNumber,
                    singleResponses[0].getCertID().getSerialNumber());
            assertTrue(singleResponses[0].getCertStatus() instanceof UnknownStatus);
        } finally {
            cesecoreConfigurationProxySession.setConfigurationValue("ocsp.nonexistingisgood", "false");
        }
    }

    /** Tests the case where there exists both a CA and a key binding for that CA on the same machine. The Key Binding should have priority. */
    @Test
    public void testStandAloneOcspResponseWithBothCaAndInternalKeyBinding() throws Exception {
        //Note: The CA never gets deleted in this test, so there exists both a CA and a key binding at the same time. 
        activateKeyBinding(internalKeyBindingId);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        // Do the OCSP request
        final OCSPReq ocspRequest = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp response = sendRequest(ocspRequest);
        assertEquals("Response status not zero.", OCSPResp.SUCCESSFUL, response.getStatus());
        validateSuccessfulResponse((BasicOCSPResp) response.getResponseObject(),
                ocspSigningCertificate.getPublicKey());
    }

    /** Test that trust settings are properly persisted */
    @Test
    public void testTrustPersistance() throws Exception {
        // Configure the OcspKeyBinding to require a signature (by any certificate)
        final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
        ocspKeyBinding.setRequireTrustedSignature(true);
        addTrustEntry(ocspKeyBinding, -1, new BigInteger("3"));
        addTrustEntry(ocspKeyBinding, -2, null);
        addTrustEntry(ocspKeyBinding, x509ca.getCAId(), new BigInteger("0"));
        internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
        // Clear caches must always be run over localhost and not through a configured proxy
        final int responseCode = ((HttpURLConnection) new URL(
                "http://localhost:8080/ejbca/clearcache/?command=clearcaches").openConnection()).getResponseCode();
        assertEquals("Failed to invoked clear cache servlet.", HttpURLConnection.HTTP_OK, responseCode);
        final OcspKeyBinding ocspKeyBindingLoaded = (OcspKeyBinding) internalKeyBindingMgmtSession
                .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
        assertTrue("RequireTrustedSignature setting was not persisted.",
                ocspKeyBindingLoaded.getRequireTrustedSignature());
        final List<InternalKeyBindingTrustEntry> trustEntries = ocspKeyBindingLoaded
                .getTrustedCertificateReferences();
        assertEquals("Not the same number of entries in list of trusted requestors", 3, trustEntries.size());
        boolean found = false;
        for (final InternalKeyBindingTrustEntry trustEntry : trustEntries) {
            log.debug("Comparing " + trustEntry.getCaId() + " " + trustEntry.fetchCertificateSerialNumber());
            if (trustEntry.getCaId() == x509ca.getCAId() && trustEntry.fetchCertificateSerialNumber() != null
                    && trustEntry.fetchCertificateSerialNumber().equals(new BigInteger("0"))) {
                found = true;
            }
        }
        assertTrue("Configured trust entry was no longer present after cache flush", found);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
    }

    /**
     * Request signature requirement: ANY known certificate.
     * Request signature:             None.
     * Expected outcome:              5 (OCSPResp.SIG_REQUIRED)
     */
    @Test
    public void testAnySignatureRequiredNoSignature() throws Exception {
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        activateKeyBinding(internalKeyBindingId);
        // Configure the OcspKeyBinding to require a signature (by any certificate)
        final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
        ocspKeyBinding.setRequireTrustedSignature(true);
        internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
        ocspResponseGeneratorSession.reloadOcspSigningCache();
        // Try to send an unsigned OCSP requests
        final OCSPReq ocspRequestUnsigned = buildOcspRequest(null, null, caCertificate,
                ocspSigningCertificate.getSerialNumber());
        final OCSPResp ocspResponseUnsigned = sendRequest(ocspRequestUnsigned);
        assertEquals("We expected a 'Signature Required' status code: ", OCSPResp.SIG_REQUIRED,
                ocspResponseUnsigned.getStatus());
        assertNull("We expected the response object to be null when 'Signature Required' is recieved.",
                ocspResponseUnsigned.getResponseObject());
    }

    /**
     * Request signature requirement: None.
     * Request signature:             Present.
     * Expected outcome:              0 (OCSPResp.SUCCESSFUL)
     */
    @Test
    public void testNoSignatureRequiredButSignaturePresent() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature (by any certificate)
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(false);
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Successful' status code: ", OCSPResp.SUCCESSFUL,
                    ocspResponseSigned.getStatus());
            validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(),
                    ocspSigningCertificate.getPublicKey());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: ANY known certificate.
     * Request signature:             By a known certificate.
     * Expected outcome:              0 (OCSPResp.SUCCESSFUL)
     */
    @Test
    public void testAnySignatureRequiredSignature() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature (by any certificate)
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Successful' status code: ", OCSPResp.SUCCESSFUL,
                    ocspResponseSigned.getStatus());
            validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(),
                    ocspSigningCertificate.getPublicKey());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: ANY certificate issued by a CA with caId=-1.
     * Request signature:             By a known certificate issued by a CA with caId!=-1.
     * Expected outcome:              6 (OCSPResp.UNAUTHORIZED)
     */
    @Test
    public void testSpecificIssuerSignatureRequiredWrongSignatureIssuer() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature (by any certificate)
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from CA with id -1 (should not exist)
            addTrustEntry(ocspKeyBinding, -1, null);
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Unauthorized' status code: ", OCSPResp.UNAUTHORIZED,
                    ocspResponseSigned.getStatus());
            assertNull("Unauthorized signed request did not generate null-response.",
                    ocspResponseSigned.getResponseObject());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: ANY certificate issued by a our test CA.
     * Request signature:             By a known certificate issued by our test CA.
     * Expected outcome:              0 (OCSPResp.SUCCESSFUL)
     */
    @Test
    public void testSpecificIssuerSignatureRequiredRightSignatureIssuer() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA
            addTrustEntry(ocspKeyBinding, x509ca.getCAId(), null);
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("Expected a 'Successful' status code: ", OCSPResp.SUCCESSFUL,
                    ocspResponseSigned.getStatus());
            validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(),
                    ocspSigningCertificate.getPublicKey());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: A certificate issued by a our test CA with certificate serialnumer=0.
     * Request signature:             By a known certificate issued by our test CA with certificate serialnumer!=0.
     * Expected outcome:              6 (OCSPResp.UNAUTHORIZED)
     */
    @Test
    public void testSpecificSignerSignatureRequiredWrongSignatureCert() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature (by any certificate)
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA and certificate serial number "0" (that should be the one we are using)
            addTrustEntry(ocspKeyBinding, x509ca.getCAId(), new BigInteger("0"));
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Unauthorized' status code: ", OCSPResp.UNAUTHORIZED,
                    ocspResponseSigned.getStatus());
            assertNull("Unauthorized signed request did not generate null-response.",
                    ocspResponseSigned.getResponseObject());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: A certificate issued by a our test CA with the certificate's serialnumber.
     * Request signature:             By the required certificate.
     * Expected outcome:              0 (OCSPResp.SUCCESSFUL)
     */
    @Test
    public void testSpecificSignerSignatureRequiredRightSignatureCert() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA and the certificate serial number from our auth cert
            addTrustEntry(ocspKeyBinding, x509ca.getCAId(), ocspAuthenticationCertificate.getSerialNumber());
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Successful' status code: ", OCSPResp.SUCCESSFUL,
                    ocspResponseSigned.getStatus());
            validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(),
                    ocspSigningCertificate.getPublicKey());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: A certificate issued by a our test CA with the certificate's serialnumber.
     * Request signature:             By the required certificate, which happens to be revoked. 
     * Expected outcome:              UNAUTHORIZED
     */
    @Test
    public void testSpecificSignerSignatureRequiredRevokedSignatureCert() throws Exception {
        //Create a special issuer.
        X509CA signatureIssuerCa = CryptoTokenTestUtils.createTestCAWithSoftCryptoToken(authenticationToken,
                "CN=RevokedSignatureIssuer");
        int cryptoTokenId = signatureIssuerCa.getCAToken().getCryptoTokenId();
        cryptoTokenManagementSession.createKeyPair(authenticationToken, cryptoTokenId, "signKeyAlias", "1024");
        X509Certificate signerIssuerCaCertificate = (X509Certificate) signatureIssuerCa.getCACertificate();
        //Store the CA Certificate.
        certificateStoreSession.storeCertificate(authenticationToken, signerIssuerCaCertificate, "foo", "1234",
                CertificateConstants.CERT_ACTIVE, CertificateConstants.CERTTYPE_ROOTCA,
                CertificateProfileConstants.CERTPROFILE_FIXED_ROOTCA, "footag", new Date().getTime());
        final String signatureRequired = cesecoreConfigurationProxySession
                .getConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED);
        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED, "true");

        try {
            final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
            final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
            final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                    signatureIssuerCa.getCAId(), ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());

            try {
                //Now delete the original CA, making this test completely standalone.
                OcspTestUtils.deleteCa(authenticationToken, x509ca);
                activateKeyBinding(internalKeyBindingId);
                // Configure the OcspKeyBinding to require a signature
                final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                        .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
                ocspKeyBinding.setRequireTrustedSignature(true);
                // Trust signatures from our test CA and the certificate serial number from our auth cert
                addTrustEntry(ocspKeyBinding, x509ca.getCAId(), ocspAuthenticationCertificate.getSerialNumber());
                internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
                ocspResponseGeneratorSession.reloadOcspSigningCache();
                internalCertificateStoreSession.reloadCaCertificateCache();
                // Try to send a signed OCSP requests
                final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                        ocspAuthenticationKeyPair.getPrivate(), (X509Certificate) x509ca.getCACertificate(),
                        ocspSigningCertificate.getSerialNumber());
                certificateStoreSession.setRevokeStatus(authenticationToken, ocspAuthenticationCertificate,
                        RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE, null);
                final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
                assertEquals("We expected an 'UNAUTHORIZED' status code: ", OCSPResp.UNAUTHORIZED,
                        ocspResponseSigned.getStatus());
                //   validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(), ocspSigningCertificate.getPublicKey());
            } finally {
                internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
            }
        } finally {
            cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED,
                    signatureRequired);
            OcspTestUtils.deleteCa(authenticationToken, signatureIssuerCa);
        }
    }

    /**
     * Request signature requirement: Multiple options.
     * Request signature:             By a known certificate issued by our test CA, not matching any of the configured trust entries.
     * Expected outcome:              6 (OCSPResp.UNAUTHORIZED)
     */
    @Test
    public void testOneOfManySignatureRequiredWrongSignatureCert() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA and the certificate serial number from our auth cert
            addTrustEntry(ocspKeyBinding, -1, ocspAuthenticationCertificate.getSerialNumber());
            addTrustEntry(ocspKeyBinding, -2, null);
            addTrustEntry(ocspKeyBinding, x509ca.getCAId(), new BigInteger("0"));
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Unauthorized' status code: ", OCSPResp.UNAUTHORIZED,
                    ocspResponseSigned.getStatus());
            assertNull("Unauthorized signed request did not generate null-response.",
                    ocspResponseSigned.getResponseObject());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Request signature requirement: Multiple options where one is the CA and serialnumber of the issued authentication certificate.
     * Request signature:             By a known certificate issued by our test CA.
     * Expected outcome:              0 (OCSPResp.SUCCESSFUL)
     */
    @Test
    public void testOneOfManySignatureRequiredRightSignatureCert() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA and the certificate serial number from our auth cert
            addTrustEntry(ocspKeyBinding, -1, ocspAuthenticationCertificate.getSerialNumber());
            addTrustEntry(ocspKeyBinding, -2, null);
            addTrustEntry(ocspKeyBinding, x509ca.getCAId(), ocspAuthenticationCertificate.getSerialNumber());
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Successful' status code: ", OCSPResp.SUCCESSFUL,
                    ocspResponseSigned.getStatus());
            validateSuccessfulResponse((BasicOCSPResp) ocspResponseSigned.getResponseObject(),
                    ocspSigningCertificate.getPublicKey());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);
        }
    }

    /**
     * Tests the case where signature is required, but requester is not authorized to make it.
     */
    @Test
    public void testUnauthorizedRequester() throws Exception {
        // Issue a request authentication certificate while we still have the CA
        final String ocspAuthenticationUsername = Thread.currentThread().getStackTrace()[1].getMethodName();
        final KeyPair ocspAuthenticationKeyPair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);
        final X509Certificate ocspAuthenticationCertificate = issueOcspAuthenticationCertificate(
                ocspAuthenticationUsername, ocspAuthenticationKeyPair.getPublic());
        try {
            //Now delete the original CA, making this test completely standalone.
            OcspTestUtils.deleteCa(authenticationToken, x509ca);
            activateKeyBinding(internalKeyBindingId);
            // Configure the OcspKeyBinding to require a signature
            final OcspKeyBinding ocspKeyBinding = (OcspKeyBinding) internalKeyBindingMgmtSession
                    .getInternalKeyBinding(authenticationToken, internalKeyBindingId);
            ocspKeyBinding.setRequireTrustedSignature(true);
            // Trust signatures from our test CA and the certificate serial number from our auth cert
            addTrustEntry(ocspKeyBinding, 4711, new BigInteger("4711"));
            internalKeyBindingMgmtSession.persistInternalKeyBinding(authenticationToken, ocspKeyBinding);
            ocspResponseGeneratorSession.reloadOcspSigningCache();
            internalCertificateStoreSession.reloadCaCertificateCache();
            // Try to send a signed OCSP requests
            final OCSPReq ocspRequestSigned = buildOcspRequest(ocspAuthenticationCertificate,
                    ocspAuthenticationKeyPair.getPrivate(), caCertificate,
                    ocspSigningCertificate.getSerialNumber());
            final OCSPResp ocspResponseSigned = sendRequest(ocspRequestSigned);
            assertEquals("We expected a 'Unauthorized' status code: ", OCSPResp.UNAUTHORIZED,
                    ocspResponseSigned.getStatus());
        } finally {
            internalCertificateStoreSession.removeCertificate(ocspAuthenticationCertificate);

        }
    }

    @Test
    public void testGetOcspResponseWithIncorrectDefaultResponder() throws Exception {
        // Set a fake value
        GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
        ocspConfiguration.setOcspDefaultResponderReference("CN=FancyPants");
        globalConfigurationSession.saveConfiguration(authenticationToken, ocspConfiguration);

        cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED, "true");

        // An OCSP request
        OCSPReqBuilder gen = new OCSPReqBuilder();
        gen.addRequest(new JcaCertificateID(SHA1DigestCalculator.buildSha1Instance(), ocspSigningCertificate,
                ocspSigningCertificate.getSerialNumber()));
        Extension[] extensions = new Extension[1];
        extensions[0] = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false,
                new DEROctetString("123456789".getBytes()));
        gen.setRequestExtensions(new Extensions(extensions));
        //Create a signed request in order to test all aspects 
        KeyPair keys = KeyTools.genKeys("512", "RSA");
        // Issue a certificate to a test user
        final String endEntityName = "testGetOcspResponseWithIncorrectDefaultResponder";
        final EndEntityInformation user = new EndEntityInformation(endEntityName, "CN=" + endEntityName,
                x509ca.getCAId(), null, null, new EndEntityType(EndEntityTypes.ENDUSER), 1,
                CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER, EndEntityConstants.TOKEN_USERGEN, 0, null);
        user.setStatus(EndEntityConstants.STATUS_NEW);
        user.setPassword("foo123");
        final SimpleRequestMessage certreq = new SimpleRequestMessage(keys.getPublic(), user.getUsername(),
                user.getPassword());
        final X509ResponseMessage resp = (X509ResponseMessage) certificateCreateSession.createCertificate(
                authenticationToken, user, certreq, X509ResponseMessage.class, signSession.fetchCertGenParams());
        final X509Certificate ocspTestCert = (X509Certificate) resp.getCertificate();

        X509CertificateHolder chain[] = new JcaX509CertificateHolder[2];
        chain[0] = new JcaX509CertificateHolder(ocspTestCert);
        chain[1] = new JcaX509CertificateHolder(caCertificate);
        gen.setRequestorName(chain[0].getSubject());
        OCSPReq req = gen.build(new BufferingContentSigner(new JcaContentSignerBuilder("SHA1withRSA")
                .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(keys.getPrivate()), 20480), chain);
        //Now delete the original CA, making this test completely standalone.
        OcspTestUtils.deleteCa(authenticationToken, x509ca);
        activateKeyBinding(internalKeyBindingId);
        ocspResponseGeneratorSession.reloadOcspSigningCache();

        try {
            final int localTransactionId = TransactionCounter.INSTANCE.getTransactionNumber();
            // Create the transaction logger for this transaction.
            TransactionLogger transactionLogger = new TransactionLogger(localTransactionId,
                    GuidHolder.INSTANCE.getGlobalUid(), "");
            // Create the audit logger for this transaction.
            AuditLogger auditLogger = new AuditLogger("", localTransactionId, GuidHolder.INSTANCE.getGlobalUid(),
                    "");
            byte[] responseBytes = ocspResponseGeneratorSession
                    .getOcspResponse(req.getEncoded(), null, "", "", null, auditLogger, transactionLogger)
                    .getOcspResponse();
            //We're expecting back an unsigned reply saying unauthorized, as per RFC2690 Section 2.3
            assertNotNull("OCSP responder replied null", responseBytes);
            OCSPResp response = new OCSPResp(responseBytes);
            assertEquals("Response status not OCSPRespBuilder.UNAUTHORIZED.", response.getStatus(),
                    OCSPRespBuilder.UNAUTHORIZED);
            assertNull("Response should not have contained a response object.", response.getResponseObject());
        } finally {
            try {
                if (ocspTestCert != null)
                    internalCertificateStoreSession.removeCertificate(ocspTestCert);
            } catch (Exception e) {
                //NOPMD: Ignore
            }
            cesecoreConfigurationProxySession.setConfigurationValue(OcspConfiguration.SIGNATUREREQUIRED, "false");
        }
    }

    // Trusting a certificateSerialNumber of null means any certificate from the CA
    private void addTrustEntry(InternalKeyBinding internalKeyBinding, int caId,
            BigInteger certificateSerialNumber) {
        final List<InternalKeyBindingTrustEntry> trustList = new ArrayList<InternalKeyBindingTrustEntry>(
                internalKeyBinding.getTrustedCertificateReferences());
        trustList.add(new InternalKeyBindingTrustEntry(caId, certificateSerialNumber));
        internalKeyBinding.setTrustedCertificateReferences(trustList);
    }

    /** Ask the OcspKeyBinding to search the database for the latest certificate matching its public key and set the status to ACTIVE */
    private void activateKeyBinding(int internalKeyBindingId) throws Exception {
        // Ask the key binding to search the database for a new certificate matching its public key
        final String ocspSigningCertificateFingerprint = internalKeyBindingMgmtSession
                .updateCertificateForInternalKeyBinding(authenticationToken, internalKeyBindingId);
        if (!CertTools.getFingerprintAsString(ocspSigningCertificate).equals(ocspSigningCertificateFingerprint)) {
            throw new Error("Wrong certificate was found for InternalKeyBinding");
        }
        OcspTestUtils.setInternalKeyBindingStatus(authenticationToken, internalKeyBindingId,
                InternalKeyBindingStatus.ACTIVE);
    }

    /**
     * Build an OCSP request, that will optionally be signed if authentication parameters are specified
     * 
     * @param ocspAuthenticationCertificate signing certificate
     * @param ocspAuthenticationPrivateKey private key to sign with
     * @param caCertificate issuer of the queried certificate
     * @param certificateSerialnumber serial number of the certificate to be queried
     * @return
     * @throws Exception
     */
    private OCSPReq buildOcspRequest(final X509Certificate ocspAuthenticationCertificate,
            final PrivateKey ocspAuthenticationPrivateKey, final X509Certificate caCertificate,
            final BigInteger certificateSerialnumber) throws Exception {
        final OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
        if (ocspAuthenticationCertificate != null) {
            // Signed requests are required to have an OCSPRequest.TBSRequest.requestorName
            ocspReqBuilder.setRequestorName(new X500Name(ocspAuthenticationCertificate.getSubjectDN().getName()));
        }
        ocspReqBuilder.addRequest(new JcaCertificateID(SHA1DigestCalculator.buildSha1Instance(), caCertificate,
                certificateSerialnumber));
        ocspReqBuilder.setRequestExtensions(
                new Extensions(new Extension[] { new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false,
                        new DEROctetString("123456789".getBytes())) }));
        if (ocspAuthenticationCertificate != null && ocspAuthenticationPrivateKey != null) {
            // Create a signed request
            final ContentSigner signer = new BufferingContentSigner(
                    new JcaContentSignerBuilder(AlgorithmConstants.SIGALG_SHA1_WITH_RSA)
                            .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(ocspAuthenticationPrivateKey),
                    20480);
            return ocspReqBuilder.build(signer, new X509CertificateHolder[] {
                    new X509CertificateHolder(ocspAuthenticationCertificate.getEncoded()) });
        } else {
            // Create an unsigned request
            return ocspReqBuilder.build();
        }
    }

    private X509Certificate issueOcspAuthenticationCertificate(final String username, final PublicKey publicKey)
            throws Exception {
        return issueOcspAuthenticationCertificate(x509ca.getCAId(), username, publicKey);
    }

    /** Issue a plain end user certificate from the test CA for the provided public key */
    private X509Certificate issueOcspAuthenticationCertificate(final int caid, final String username,
            final PublicKey publicKey) throws Exception {
        final EndEntityInformation user = new EndEntityInformation(username, "CN=" + username, caid, null, null,
                new EndEntityType(EndEntityTypes.ENDUSER), 0, CertificateProfileConstants.CERTPROFILE_FIXED_ENDUSER,
                EndEntityConstants.TOKEN_USERGEN, 0, null);
        user.setStatus(EndEntityConstants.STATUS_NEW);
        user.setPassword("foo123");
        final SimpleRequestMessage req = new SimpleRequestMessage(publicKey, user.getUsername(),
                user.getPassword());
        final X509ResponseMessage resp = (X509ResponseMessage) certificateCreateSession.createCertificate(
                authenticationToken, user, req,
                org.cesecore.certificates.certificate.request.X509ResponseMessage.class,
                signSession.fetchCertGenParams());
        final X509Certificate cert = (X509Certificate) resp.getCertificate();
        assertNotNull("Failed to create certificate", cert);
        assertTrue("Issued certificate was not for the requested public key.",
                cert.getPublicKey().equals(publicKey));
        return cert;
    }

    /** Perform OCSP requests over remote EJB interface and assert the the response is not null. */
    private OCSPResp sendRequest(final OCSPReq ocspRequest)
            throws MalformedRequestException, IOException, OCSPException {
        final int localTransactionId = TransactionCounter.INSTANCE.getTransactionNumber();
        // Create the transaction and audit logger for this transaction.
        ConfigurationHolder.updateConfiguration("ocsp.trx-log", "true");
        final TransactionLogger transactionLogger = new TransactionLogger(localTransactionId,
                GuidHolder.INSTANCE.getGlobalUid(), "");
        final AuditLogger auditLogger = new AuditLogger("", localTransactionId, GuidHolder.INSTANCE.getGlobalUid(),
                "");
        final OcspResponseInformation responseInformation = ocspResponseGeneratorSession
                .getOcspResponse(ocspRequest.getEncoded(), null, "", "", null, auditLogger, transactionLogger);
        byte[] responseBytes = responseInformation.getOcspResponse();
        assertNotNull("OCSP responder replied null", responseBytes);
        return new OCSPResp(responseBytes);
    }

    private void validateSuccessfulResponse(final BasicOCSPResp basicOcspResponse, final PublicKey publicKey)
            throws Exception {
        assertNotNull("Signed request generated null-response.", basicOcspResponse);
        assertTrue("OCSP response was not signed correctly.",
                basicOcspResponse.isSignatureValid(new JcaContentVerifierProviderBuilder().build(publicKey)));
        final SingleResp[] singleResponses = basicOcspResponse.getResponses();
        assertEquals("Delivered some thing else than one and exactly one response.", 1, singleResponses.length);
        assertEquals("Response cert did not match up with request cert", ocspSigningCertificate.getSerialNumber(),
                singleResponses[0].getCertID().getSerialNumber());
        assertEquals("Status is not null (good)", null, singleResponses[0].getCertStatus());
    }

}