Skip to content

Commit

Permalink
Fetch Issuer certificate from AIA extension when not found from TSL (#…
Browse files Browse the repository at this point in the history
…404)

IB-6883

Signed-off-by: Raul Metsma <raul@metsma.ee>
  • Loading branch information
metsma authored Jun 30, 2021
1 parent 6c5cb9b commit a2fea2d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 43 deletions.
7 changes: 4 additions & 3 deletions src/SignatureXAdES_LT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ SignatureXAdES_LT::SignatureXAdES_LT(istream &sigdata, ASiContainer *bdoc, bool
THROW("Could not find certificate issuer '%s' in certificate store.",
cert.issuerName().c_str());

OCSP ocsp(cert, issuer, vector<unsigned char>(), bdoc->mediaType(), false);
OCSP ocsp(cert, issuer, {}, bdoc->mediaType(), false);
addOCSPValue(id().replace(0, 1, "N"), ocsp);
}
} catch(const Exception &) {
Expand Down Expand Up @@ -224,7 +224,9 @@ void SignatureXAdES_LT::extendSignatureProfile(const std::string &profile)
X509Cert cert = signingCertificate();
X509Cert issuer = X509CertStore::instance()->findIssuer(cert, X509CertStore::CA);
if(!issuer)
THROW("Could not find certificate issuer '%s' in certificate store.",
issuer = X509CertStore::instance()->issuerFromAIA(cert);
if(!issuer)
THROW("Could not find certificate issuer '%s' in certificate store or from AIA.",
cert.issuerName().c_str());

OCSP ocsp(cert, issuer, nonce, bdoc->mediaType(), profile.find(ASiC_E::ASIC_TM_PROFILE) != string::npos);
Expand Down Expand Up @@ -305,7 +307,6 @@ OCSP SignatureXAdES_LT::getOCSPResponseValue() const
for(const OCSPValuesType::EncapsulatedOCSPValueType &resp: t.oCSPValues()->encapsulatedOCSPValue())
{
try {
vector<unsigned char> data(resp.begin(), resp.end());
OCSP ocsp((const unsigned char*)resp.data(), resp.size());
ocsp.verifyResponse(signingCertificate());
return ocsp;
Expand Down
65 changes: 25 additions & 40 deletions src/crypto/X509CertStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "Conf.h"
#include "log.h"
#include "crypto/Connect.h"
#include "crypto/OpenSSLHelpers.h"
#include "crypto/TSL.h"
#include "util/DateTime.h"
Expand Down Expand Up @@ -122,12 +123,6 @@ X509CertStore* X509CertStore::instance()
return &INSTANCE;
}


/**
* Return STACK_OF(X509) containing all certs loaded from directory
* @return STACK_OF(X509) all certs in store.
* throws IOException
*/
vector<X509Cert> X509CertStore::certs(const set<string> &type) const
{
vector<X509Cert> certs;
Expand All @@ -139,41 +134,41 @@ vector<X509Cert> X509CertStore::certs(const set<string> &type) const
return certs;
}

/**
* Searches certificate by subject and returns a copy of it if found.
* If not found returns <code>NULL</code>.
* NB! The returned certificate must be freed with OpenSSL function X509_free(X509* cert).
*
* @param subject certificate subject.
* @return returns copy of found certificate or <code>NULL</code> if certificate was not found.
* @throws IOException exception is thrown if copying certificate failed.
*/
X509Cert X509CertStore::findIssuer(const X509Cert &cert, const set<string> &type) const
{
activate(cert.issuerName("C"));
SCOPE(AUTHORITY_KEYID, akid, X509_get_ext_d2i(cert.handle(), NID_authority_key_identifier, nullptr, nullptr));
for(const TSL::Service &s: *d)
{
if(type.find(s.type) == type.cend())
continue;
for(const X509Cert &i: s.certs)
{
if(!akid || !akid->keyid)
{
if(X509_NAME_cmp(X509_get_subject_name(i.handle()), X509_get_issuer_name(cert.handle())))
return i;
}
else
{
SCOPE(ASN1_OCTET_STRING, skid, X509_get_ext_d2i(i.handle(), NID_subject_key_identifier, nullptr, nullptr));
if(skid && ASN1_OCTET_STRING_cmp(akid->keyid, skid.get()) == 0)
return i;
}
if(X509_check_issued(i.handle(), cert.handle()) == X509_V_OK)
return i;
}
}
return X509Cert();
}

X509Cert X509CertStore::issuerFromAIA(const X509Cert &cert) const
{
SCOPE(AUTHORITY_INFO_ACCESS, aia, X509_get_ext_d2i(cert.handle(), NID_info_access, nullptr, nullptr));
if(!aia)
return X509Cert();
string url;
for(int i = 0; i < sk_ACCESS_DESCRIPTION_num(aia.get()); ++i)
{
ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(aia.get(), i);
if(ad->location->type == GEN_URI &&
OBJ_obj2nid(ad->method) == NID_ad_ca_issuers)
url.assign((const char*)ad->location->d.uniformResourceIdentifier->data, ad->location->d.uniformResourceIdentifier->length);
}
if(url.empty())
return X509Cert();
Connect::Result result = Connect(url, "GET", 0, {}).exec();
return X509Cert((const unsigned char*)result.content.c_str(), result.content.size());
}

X509_STORE* X509CertStore::createStore(const set<string> &type, const time_t *t)
{
SCOPE(X509_STORE, store, X509_STORE_new());
Expand Down Expand Up @@ -205,25 +200,15 @@ int X509CertStore::validate(int ok, X509_STORE_CTX *ctx, const set<string> &type
case X509_V_ERR_CERT_UNTRUSTED:
{
X509 *x509 = X509_STORE_CTX_get0_cert(ctx);
SCOPE(AUTHORITY_KEYID, akid, X509_get_ext_d2i(x509, NID_authority_key_identifier, nullptr, nullptr));
for(const TSL::Service &s: *instance()->d)
{
if(type.find(s.type) == type.cend())
continue;
if(!any_of(s.certs.cbegin(), s.certs.cend(), [&](const X509Cert &issuer){
if(none_of(s.certs.cbegin(), s.certs.cend(), [&](const X509Cert &issuer){
if(issuer == x509)
return true;
if(!akid || !akid->keyid)
{
if(X509_NAME_cmp(X509_get_subject_name(issuer.handle()), X509_get_issuer_name(x509)) != 0)
return false;
}
else
{
SCOPE(ASN1_OCTET_STRING, skid, X509_get_ext_d2i(issuer.handle(), NID_subject_key_identifier, nullptr, nullptr));
if(!skid || ASN1_OCTET_STRING_cmp(akid->keyid, skid.get()) != 0)
return false;
}
if(X509_check_issued(issuer.handle(), x509) != X509_V_OK)
return false;
SCOPE(EVP_PKEY, pub, X509_get_pubkey(issuer.handle()));
if(X509_verify(x509, pub.get()) == 1)
return true;
Expand Down
1 change: 1 addition & 0 deletions src/crypto/X509CertStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace digidoc
void activate(const std::string &territory) const;
std::vector<X509Cert> certs(const std::set<std::string> &type) const;
X509Cert findIssuer(const X509Cert &cert, const std::set<std::string> &type) const;
X509Cert issuerFromAIA(const X509Cert &cert) const;
static X509_STORE* createStore(const std::set<std::string> &type, const time_t *t = nullptr);
bool verify(const X509Cert &cert, bool qscd) const;

Expand Down

0 comments on commit a2fea2d

Please sign in to comment.