Example #1
0
bdoc::OCSP* bdoc::SignatureValidator::prepare()
{
    _signingCert = _sig->getSigningCertificate();

    std::string issuer = _signingCert.getIssuerName();
    int pos = issuer.find("CN=", 0) + 3;
    std::string issure_cn =
        issuer.substr(pos, issuer.find(",", pos) - pos);
    if (!_conf->hasOCSPConf(issure_cn)) {
        THROW_STACK_EXCEPTION("Failed to find ocsp responder.");
    }

    OCSPConf ocspConf = _conf->getOCSPConf(issure_cn);

    _issuerX509 = _conf->getCertStore()->
                  getCert(*(_signingCert.getIssuerNameAsn1()));
    if (_issuerX509 == NULL) {
        THROW_STACK_EXCEPTION("Failed to load issuer certificate.");
    }

    _ocspCerts = X509Cert::loadX509Stack(ocspConf.cert);

    OCSP *ocsp = new OCSP(ocspConf.url);
    ocsp->setSkew(ocspConf.skew);
    ocsp->setMaxAge(ocspConf.maxAge);
    ocsp->setOCSPCerts(_ocspCerts);

    return ocsp;
}
Example #2
0
/**
 *
 * return
 * @throws SignatureException
 */
digidoc::OCSP::CertStatus digidoc::SignatureBES::validateOnline() const throw(SignatureException)
{
    // FIXME: Add exception handling.

    // Get signing signature.
    X509Cert cert = getSigningCertificate();

    // Get issuer certificate.
    X509* issuerCert = X509CertStore::getInstance()->getCert(*(cert.getIssuerNameAsn1()));
    X509_scope issuerCertScope(&issuerCert);
    if(issuerCert == NULL)
    {
        THROW_SIGNATUREEXCEPTION("Failed to load issuer certificate.");
    }

    Conf* conf = Conf::getInstance();

    // Get OCSP responder certificate.
    // FIXME: throws IOException, handle it
    Conf::OCSPConf ocspConf = conf->getOCSP(cert.getIssuerName());
    if(ocspConf.issuer.empty())
    {
        SignatureException e(__FILE__, __LINE__, "Failed to find ocsp responder.");
        e.setCode( Exception::OCSPResponderMissing );
        throw e;
    }
    STACK_OF(X509)* ocspCerts = X509Cert::loadX509Stack(ocspConf.cert);
    X509Stack_scope ocspCertsScope(&ocspCerts);

    // Check the certificate validity from OCSP server.
    try
    {
        OCSP ocsp;
        ocsp.setSkew(120);//XXX: load from conf
        ocsp.setOCSPCerts(ocspCerts);
        ocsp.setUrl(ocspConf.url);
        std::auto_ptr<Digest> calc = Digest::create();
        calc->update(getSignatureValue());
        return ocsp.checkCert(cert.getX509(), issuerCert, calc->getDigest());
    }
    catch(const IOException& e)
    {
        THROW_SIGNATUREEXCEPTION("Failed to check the certificate validity from OCSP server.");
    }
    catch(const OCSPException& e)
    {
        THROW_SIGNATUREEXCEPTION("Failed to check the certificate validity from OCSP server.");
    }
    return digidoc::OCSP::GOOD;
}
Example #3
0
/**
 * Do TM offline validations.
 * <ul>
 *   <li>Validate BES offline</li>
 *   <li>Check OCSP response (RevocationValues) was signed by trusted OCSP server</li>
 *   <li>Check that nonce field in OCSP response is same as CompleteRevocationRefs-&gt;DigestValue</li>
 *   <li>Recalculate hash of signature and compare with nonce</li>
 * </ul>
 * @throws SignatureException if signature is not valid
 */
void digidoc::SignatureTM::validateOffline() const throw(SignatureException)
{
    SignatureBES::validateOffline();

//       1. Check OCSP response (RevocationValues) was signed by OCSP server
//       2. OCSP server certificate is trusted?
//       3. Check that nonce field in OCSP response is same as CompleteRevocationRefs->DigestValue
//       4. Recalculate hash of signature and compare with nonce

#if 0
    Conf* conf = Conf::getInstance();
    Conf::OCSPConf ocspConf = conf->getOCSP(getSigningCertificate().getIssuerName());
    if(ocspConf.issuer.empty())
    {
        SignatureException e(__FILE__, __LINE__, "Failed to find ocsp responder.");
        e.setCode( Exception::OCSPResponderMissing );
        throw e;
    }
    OCSP ocsp(ocspConf.url);
    STACK_OF(X509)* ocspCerts = 0;
    try
    {
        ocspCerts = X509Cert::loadX509Stack(ocspConf.cert);
    }
    catch( const Exception &e )
    {
        SignatureException exception(__FILE__, __LINE__, "OCSP certificate loading failed", e);
        exception.setCode( Exception::OCSPCertMissing );
        throw exception;
	}
    X509Stack_scope x509StackScope(&ocspCerts);
    ocsp.setOCSPCerts(ocspCerts);
#else
    OCSP ocsp;
    ocsp.setCertStore(digidoc::X509CertStore::getInstance()->getCertStore());
    ocsp.setOCSPCerts(digidoc::X509CertStore::getInstance()->getCerts());
#endif
    std::vector<unsigned char> respBuf;
    try
    {
        getOCSPResponseValue(respBuf);
        ocsp.verifyResponse(respBuf);
    }
    catch( const Exception &e )
    {
        THROW_SIGNATUREEXCEPTION_CAUSE( e, "OCSP response verfiy failed" );
    }
    DEBUG("OCSP response was signed by trusted OCSP responder");



    std::vector<unsigned char> respNonce = ocsp.getNonce(respBuf);

    xml_schema::Uri method = unsignedSignatureProperties()->completeRevocationRefs()[0].oCSPRefs()
        ->oCSPRef()[0].digestAlgAndValue()->digestMethod().algorithm();

    std::auto_ptr<Digest> calc = Digest::create(std::string(method));
    calc->update(getSignatureValue());
    std::vector<unsigned char> nonce = calc->getDigest();

    if(nonce != respNonce)
    {
        DEBUGMEM("Calculated signature HASH", &nonce[0], nonce.size());
        DEBUGMEM("Response nonce", &respNonce[0], respNonce.size());
        THROW_SIGNATUREEXCEPTION("Calculated signature hash doesn't match to OCSP responder nonce field");
    }



    std::vector<unsigned char> revocationOCSPRefValue(0);
    std::string ocspResponseHashUri;
    getRevocationOCSPRef(revocationOCSPRefValue, ocspResponseHashUri);

    std::auto_ptr<Digest> ocspResponseCalc = Digest::create(ocspResponseHashUri);
    DEBUG("Calculating digest on %d bytes", respBuf.size());
    ocspResponseCalc->update(respBuf);
    std::vector<unsigned char> ocspResponseHash = ocspResponseCalc->getDigest();

    if(ocspResponseHash != revocationOCSPRefValue)
    {
        DEBUGMEM("Document   ocspResponse HASH:", &revocationOCSPRefValue[0], revocationOCSPRefValue.size());
        DEBUGMEM("Calculated ocspResponse HASH:", &ocspResponseHash[0], ocspResponseHash.size());
        THROW_SIGNATUREEXCEPTION("OCSPRef value doesn't match with hash of OCSP response");
    }
    else
    {
        DEBUG("TM signature valid");
    }

}
Example #4
0
/**
 *
 * @param signer
 * @throws SignatureException
 */
void digidoc::SignatureTM::sign(Signer* signer) throw(SignatureException, SignException)
{
    DEBUG("SignatureTM::sign()");

    // Sign with BES profile.
    SignatureBES::sign(signer);
    DEBUG("BES signature successful.");

    // Calculate NONCE value.
    std::auto_ptr<Digest> calc = Digest::create();
    calc->update(getSignatureValue());
    std::vector<unsigned char> nonce = calc->getDigest();
    DEBUGMEM("Calculated signature HASH (nonce):", &nonce[0], nonce.size());

    // Get issuer certificate from certificate store.
    X509* cert = signer->getCert();
    X509Cert cert_(cert);
    X509* issuer = X509CertStore::getInstance()->getCert(*(cert_.getIssuerNameAsn1())); X509_scope issuerScope(&issuer);
    if(issuer == NULL)
    {
    	THROW_SIGNATUREEXCEPTION("Could not find certificate '%s' issuer '%s' in certificate store.",
    			cert_.getSubject().c_str(), cert_.getIssuerName().c_str());
    }

    DEBUG("Signing with X.509 cert {serial=%ld, subject=%s, issuer=%s})",
    		cert_.getSerial(), cert_.getSubject().c_str(), cert_.getIssuerName().c_str());

    // Initialize OCSP.
    DEBUG("Making OCSP request.");
    Conf* conf = Conf::getInstance();
    Conf::OCSPConf ocspConf = conf->getOCSP(cert_.getIssuerName());
    if(ocspConf.issuer.empty())
    {
        SignatureException e(__FILE__, __LINE__, "Failed to find ocsp responder.");
        e.setCode( Exception::OCSPResponderMissing );
        throw e;
    }

    STACK_OF(X509)* ocspCerts = 0;
    try
    {
        ocspCerts = X509Cert::loadX509Stack(ocspConf.cert);
    }
    catch(const IOException& e)
    {
        THROW_SIGNATUREEXCEPTION_CAUSE(e, "Failed to load OCSP certificate");
    }
    X509Stack_scope ocspCertsScope(&ocspCerts);

    OCSP::CertStatus status = OCSP::UNKNOWN;
    std::vector<unsigned char> ocspResponse;
    struct tm producedAt;
    try
    {
        OCSP ocsp;
        ocsp.setOCSPCerts(ocspCerts);
        ocsp.setUrl(ocspConf.url);
        ocsp.setMaxAge(2*60); // FIXME: remove or move to conf
        ocsp.setSkew(15*60); // FIXME: remove or move to conf
        status = ocsp.checkCert(cert, issuer, nonce, ocspResponse, producedAt);
    }
    catch(const IOException& e)
    {
        THROW_SIGNATUREEXCEPTION_CAUSE(e, "Failed to get OCSP response");
    }
    catch(const OCSPException& e)
    {
        THROW_SIGNATUREEXCEPTION_CAUSE(e, "Failed to get OCSP response");
    }

    switch(status)
    {
    case digidoc::OCSP::GOOD: DEBUG("OCSP status: GOOD"); break;
    case digidoc::OCSP::REVOKED:
    {
        DEBUG("OCSP status: REVOKED");
        SignatureException e( __FILE__, __LINE__, "Certificate status: revoked" );
        e.setCode( Exception::CertificateRevoked );
        throw e;
        break;
    }
    case digidoc::OCSP::UNKNOWN:
    {
        DEBUG("OCSP status: UNKNOWN");
        SignatureException e( __FILE__, __LINE__, "Certificate status: unknown" );
        e.setCode( Exception::CertificateUnknown );
        throw e;
        break;
    }
    }
    DEBUG("OCSP response size %d", ocspResponse.size());

    // FIXME: get from ocsp instead
    // FIXME: This file can contain multiple certs. X509Cert class supports only one cert per file
    // loadX509Stack loads multiple certs from one file
    // X509* ocspCert = X509Cert::loadX509(Conf::getInstance()->getOCSPCertPath()); X509_scope ocspCertScope(&ocspCert);
    if(sk_X509_num(ocspCerts) > 1)
    {
        ERR("More than one OCSP cert in file.");
    }
    X509Cert ocspCert_(sk_X509_value(ocspCerts, 0));

    std::auto_ptr<Digest> ocspResponseCalc = Digest::create();
    ocspResponseCalc->update(ocspResponse);
    std::vector<unsigned char> ocspResponseHash = ocspResponseCalc->getDigest();
    DEBUGMEM("Calculated ocspResponse HASH:", &ocspResponseHash[0], ocspResponseHash.size());

    // Set TM profile signature parameters.
    createTMProperties();
    setOCSPCertificate(ocspCert_);
    setCACertificate(X509Cert(issuer));
    setCompleteRevocationRefs(ocspCert_.getIssuerName(), calc->getUri(), ocspResponseHash, producedAt);
    setOCSPResponseValue(ocspResponse);
}