예제 #1
0
/// Check if signing certificate was issued by trusted party.
/// @throws SignatureException on a problem with signing certificate
void SignatureBES::checkSigningCertificate() const
{
    try
    {
        X509Cert signingCert = signingCertificate();
        vector<X509Cert::KeyUsage> usage = signingCert.keyUsage();
        if(find(usage.begin(), usage.end(), X509Cert::NonRepudiation) == usage.end())
            THROW("Signing certificate does not contain NonRepudiation key usage flag");
        string time = trustedSigningTime();
        if(time.empty())
            THROW("SigningTime missing");
        time_t signingTime_t = util::date::string2time_t(time);
        if(!X509CertStore::instance()->verify(signingCert, &signingTime_t))
            THROW("Unable to verify signing certificate");
    }
    catch(const Exception &e)
    {
        THROW_CAUSE( e, "Unable to verify signing certificate" );
    }
}
예제 #2
0
/**
 * Check if X509Cert is signed by trusted issuer
 * @throw Exception if error
 */
bool X509CertStore::verify(const X509Cert &cert, bool noqscd) const
{
    activate(cert.issuerName("C"));
    const ASN1_TIME *asn1time = X509_get0_notBefore(cert.handle());
    time_t time = util::date::ASN1TimeToTime_t(string((const char*)asn1time->data, size_t(asn1time->length)), asn1time->type == V_ASN1_GENERALIZEDTIME);
    SCOPE(X509_STORE, store, createStore(X509CertStore::CA, &time));
    SCOPE(X509_STORE_CTX, csc, X509_STORE_CTX_new());
    if(!X509_STORE_CTX_init(csc.get(), store.get(), cert.handle(), nullptr))
        THROW_OPENSSLEXCEPTION("Failed to init X509_STORE_CTX");
    if(X509_verify_cert(csc.get()) > 0)
    {
        if(noqscd)
            return true;

        const TSL::Validity *v = static_cast<const TSL::Validity*>(X509_STORE_CTX_get_ex_data(csc.get(), 0));
        const vector<string> policies = cert.certificatePolicies();
        const vector<string> qcstatement = cert.qcStatements();
        const vector<X509Cert::KeyUsage> keyUsage = cert.keyUsage();

        bool isQCCompliant = find(qcstatement.cbegin(), qcstatement.cend(), X509Cert::QC_COMPLIANT) != qcstatement.cend();
        bool isQSCD =
            find(policies.cbegin(), policies.cend(), X509Cert::QCP_PUBLIC_WITH_SSCD) != policies.cend() ||
            find(policies.cbegin(), policies.cend(), X509Cert::QCP_LEGAL_QSCD) != policies.cend() ||
            find(policies.cbegin(), policies.cend(), X509Cert::QCP_NATURAL_QSCD) != policies.cend() ||
            find(qcstatement.cbegin(), qcstatement.cend(), X509Cert::QC_SSCD) != qcstatement.cend();

        bool isESeal =  // Special treamtent for E-Seals
            find(policies.cbegin(), policies.cend(), X509Cert::QCP_LEGAL) != policies.cend() ||
            find(qcstatement.cbegin(), qcstatement.cend(), X509Cert::QCT_ESEAL) != qcstatement.cend();
        auto matchPolicySet = [&](const vector<string> &policySet){
            return all_of(policySet.cbegin(), policySet.cend(), [&](const string &policy){
                return find(policies.cbegin(), policies.cend(), policy) != policies.cend();
            });
        };
        auto matchKeyUsageSet = [&](const map<X509Cert::KeyUsage,bool> &keyUsageSet){
            return all_of(keyUsageSet.cbegin(), keyUsageSet.cend(), [&](pair<X509Cert::KeyUsage,bool> keyUsageBit){
                return (find(keyUsage.cbegin(), keyUsage.cend(), keyUsageBit.first) != keyUsage.cend()) == keyUsageBit.second;
            });
        };

        for(const TSL::Qualifier &q: v->qualifiers)
        {
            if(q.assert_ == "all")
            {
                if(!(all_of(q.policySet.cbegin(), q.policySet.cend(), matchPolicySet) &&
                     all_of(q.keyUsage.cbegin(), q.keyUsage.cend(), matchKeyUsageSet)))
                    continue;
            }
            else if(q.assert_ == "atLeastOne")
            {
                if(!(any_of(q.policySet.cbegin(), q.policySet.cend(), matchPolicySet) ||
                     any_of(q.keyUsage.cbegin(), q.keyUsage.cend(), matchKeyUsageSet) ))
                    continue;
            }
            else
            {
                WARN("Unable to handle Qualifier assert '%s'", q.assert_.c_str());
                continue;
            }

            for(const string &qc: q.qualifiers)
            {
                if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCStatement" ||
                   qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCForESig")
                    isQCCompliant = true;
                else if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/NotQualified")
                    isQCCompliant = false;
                else if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCSSCDStatusAsInCert" ||
                        qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCQSCDStatusAsInCert")
                    continue;
                else if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCWithSSCD" ||
                        qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCWithQSCD")
                    isQSCD = true;
                else if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCNoSSCD" ||
                        qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCNoQSCD")
                    isQSCD = false;
                else if(qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCForLegalPerson" ||
                        qc == "http://uri.etsi.org/TrstSvc/TrustedList/SvcInfoExt/QCForESeal")
                    isESeal = true;
            }
        }

        if(!((isQCCompliant && isQSCD) || isESeal))
        {
            Exception e(EXCEPTION_PARAMS("Signing certificate does not meet Qualification requirements"));
            e.setCode(Exception::CertificateIssuerMissing);
            throw e;
        }

        return true;
    }

    int err = X509_STORE_CTX_get_error(csc.get());
    Exception e(EXCEPTION_PARAMS(X509_verify_cert_error_string(err)), OpenSSLException());
    switch(err)
    {
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
        e.setCode(Exception::CertificateIssuerMissing);
        throw e;
    default: throw e;
    }
}