Skip to content

Commit 520ff43

Browse files
committed
Check certificate key type and fetch certifcate when responder is missing
IB-8461 Signed-off-by: Raul Metsma <[email protected]>
1 parent efb30bc commit 520ff43

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

src/Container.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ void digidoc::initialize(const string &appInfo, const string &userAgent, initCal
120120
THROW("Error during initialisation of xmlsec. Failed to register custom callbacks.");
121121

122122
INFO("Libxml2 version: %s", LIBXML_DOTTED_VERSION);
123+
INFO("OpenSSL version: %s", OpenSSL_version(OPENSSL_VERSION_STRING));
123124
INFO("Xmlsec1 version: %s", XMLSEC_VERSION);
124125
INFO("digidocpp version: %s", VERSION_STR);
125126

src/crypto/OCSP.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
5757
string url = Conf::instance()->ocsp(cert.issuerName("CN"));
5858
if(url.empty())
5959
{
60-
STACK_OF(OPENSSL_STRING) *urls = X509_get1_ocsp(cert.handle());
61-
if(urls && sk_OPENSSL_STRING_num(urls) > 0)
62-
url = sk_OPENSSL_STRING_value(urls, 0);
63-
X509_email_free(urls);
60+
if(auto urls = make_unique_ptr<X509_email_free>(X509_get1_ocsp(cert.handle()));
61+
urls && sk_OPENSSL_STRING_num(urls.get()) > 0)
62+
url = sk_OPENSSL_STRING_value(urls.get(), 0);
6463
}
6564
DEBUG("OCSP url %s", url.c_str());
6665
if(url.empty())
@@ -70,11 +69,11 @@ OCSP::OCSP(const X509Cert &cert, const X509Cert &issuer, const std::string &user
7069
throw e;
7170
}
7271

73-
OCSP_CERTID *certId = OCSP_cert_to_id(nullptr, cert.handle(), issuer.handle());
74-
SCOPE(OCSP_REQUEST, req, OCSP_REQUEST_new());
72+
auto req = make_unique_ptr<OCSP_REQUEST_free>(OCSP_REQUEST_new());
7573
if(!req)
7674
THROW_OPENSSLEXCEPTION("Failed to create new OCSP request, out of memory?");
7775

76+
OCSP_CERTID *certId = OCSP_cert_to_id(nullptr, cert.handle(), issuer.handle());
7877
if(!OCSP_request_add0_id(req.get(), certId))
7978
THROW_OPENSSLEXCEPTION("Failed to add certificate ID to OCSP request.");
8079

@@ -143,19 +142,27 @@ bool OCSP::compareResponderCert(const X509Cert &cert) const
143142
{
144143
if(!basic || !cert)
145144
return false;
145+
146146
const ASN1_OCTET_STRING *hash {};
147147
const X509_NAME *name {};
148-
OCSP_resp_get0_id(basic.get(), &hash, &name);
149-
if(name)
150-
return X509_NAME_cmp(X509_get_subject_name(cert.handle()), name) == 0;
148+
if(OCSP_resp_get0_id(basic.get(), &hash, &name) != 1)
149+
return false;
151150
if(hash)
152151
{
153152
std::array<unsigned char,SHA_DIGEST_LENGTH> sha1{};
154153
ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(cert.handle());
155154
SHA1(key->data, size_t(key->length), sha1.data());
156-
return equal(sha1.cbegin(), sha1.cend(), hash->data, std::next(hash->data, hash->length));
155+
if(!equal(sha1.cbegin(), sha1.cend(), hash->data, std::next(hash->data, hash->length)))
156+
return false;
157157
}
158-
return false;
158+
else if(X509_NAME_cmp(X509_get_subject_name(cert.handle()), name) != 0)
159+
return false;
160+
161+
const ASN1_OBJECT *sigalg {};
162+
X509_ALGOR_get0(&sigalg, nullptr, nullptr, OCSP_resp_get0_tbs_sigalg(basic.get()));
163+
int pknid = 0;
164+
return OBJ_find_sigid_algs(OBJ_obj2nid(sigalg), nullptr, &pknid) == 1 &&
165+
EVP_PKEY_is_a(X509_get0_pubkey(cert.handle()), OBJ_nid2sn(pknid)) == 1;
159166
}
160167

161168
X509Cert OCSP::responderCert() const
@@ -191,12 +198,16 @@ void OCSP::verifyResponse(const X509Cert &cert) const
191198
THROW("Failed to verify OCSP response.");
192199

193200
tm tm = producedAt();
194-
// Some OCSP-s do not have certificates in response and stack is used for finding certificate for this
195201
auto stack = make_unique_ptr(sk_X509_new_null(), [](auto *sk) { sk_X509_free(sk); });
196-
for(const X509Cert &i: X509CertStore::instance()->certs(X509CertStore::OCSP))
202+
// Some OCSP-s do not have certificates in response and stack is used for finding certificate for this
203+
X509 *signer{};
204+
if(int rv = OCSP_resp_get0_signer(basic.get(), &signer, nullptr); rv == 0 || !signer)
197205
{
198-
if(compareResponderCert(i))
199-
sk_X509_push(stack.get(), i.handle());
206+
for(const X509Cert &i: X509CertStore::instance()->certs(X509CertStore::OCSP))
207+
{
208+
if(compareResponderCert(i))
209+
sk_X509_push(stack.get(), i.handle());
210+
}
200211
}
201212
auto store = X509CertStore::createStore(X509CertStore::OCSP, tm);
202213
if(OCSP_basic_verify(basic.get(), stack.get(), store.get(), OCSP_NOCHECKS | OCSP_PARTIAL_CHAIN) != 1)
@@ -230,7 +241,7 @@ void OCSP::verifyResponse(const X509Cert &cert) const
230241
ASN1_OBJECT *md {};
231242
if(OCSP_id_get0_info(nullptr, &md, nullptr, nullptr, const_cast<OCSP_CERTID*>(certID)) == 1)
232243
evp_md = EVP_get_digestbyobj(md);
233-
SCOPE(OCSP_CERTID, certId, OCSP_cert_to_id(evp_md, cert.handle(), issuer.handle()));
244+
auto certId = make_unique_ptr<OCSP_CERTID_free>(OCSP_cert_to_id(evp_md, cert.handle(), issuer.handle()));
234245
if(OCSP_resp_find_status(basic.get(), certId.get(), &status, nullptr, nullptr, nullptr, nullptr) == 1)
235246
break;
236247
}

0 commit comments

Comments
 (0)