Example #1
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 #2
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);
}