Skip to content

Commit 9e31559

Browse files
committed
Fetch additional intermediate certificates for validation
IB-7992 Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent 4b6d0be commit 9e31559

8 files changed

Lines changed: 49 additions & 21 deletions

File tree

src/SignatureXAdES_B.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -544,10 +544,27 @@ void SignatureXAdES_B::validate(const string &policy) const
544544
if(!signatureref.empty())
545545
EXCEPTION_ADD(exception, "Manifest references and signature references do not match");
546546

547-
try { checkKeyInfo(); }
547+
X509Cert signingCertificate;
548+
vector<X509Cert> untrusted;
549+
for(auto x509Data = signature/"KeyInfo"/"X509Data"; x509Data; x509Data++)
550+
{
551+
for(auto x509Cert = x509Data/"X509Certificate"; x509Cert; x509Cert++)
552+
{
553+
vector<unsigned char> cert = x509Cert;
554+
if(cert.empty())
555+
continue;
556+
if(!signingCertificate)
557+
signingCertificate = X509Cert(cert);
558+
else
559+
untrusted.emplace_back(cert);
560+
}
561+
}
562+
if(!signingCertificate)
563+
THROW("Signature does not contain signer certificate");
564+
try { checkKeyInfo(signingCertificate); }
548565
catch(const Exception& e) { exception.addCause(e); }
549566

550-
try { checkSigningCertificate(policy == POLv1); }
567+
try { checkSigningCertificate(signingCertificate, policy == POLv1, untrusted); }
551568
catch(const Exception& e) { exception.addCause(e); }
552569
} catch(const Exception &e) {
553570
exception.addCause(e);
@@ -595,9 +612,8 @@ void SignatureXAdES_B::checkDigest(XMLNode digest, const vector<unsigned char> &
595612
* Verify if SigningCertificate matches with
596613
* XAdES::SigningCertificate/SigningCertificateV2 Digest and IssuerSerial info
597614
*/
598-
void SignatureXAdES_B::checkKeyInfo() const
615+
void SignatureXAdES_B::checkKeyInfo(const X509Cert &x509) const
599616
{
600-
X509Cert x509 = signingCertificate();
601617
if(auto sigCert = signedSignatureProperties()/"SigningCertificate")
602618
{
603619
if(auto certs = sigCert/"Cert"; certs || !(certs + 1))
@@ -626,15 +642,13 @@ void SignatureXAdES_B::checkKeyInfo() const
626642
* Check if signing certificate was issued by trusted party.
627643
* @throws Exception on a problem with signing certificate
628644
*/
629-
void SignatureXAdES_B::checkSigningCertificate(bool noqscd) const
645+
void SignatureXAdES_B::checkSigningCertificate(const X509Cert &x509, bool noqscd, const vector<X509Cert> &untrusted) const
630646
{
631647
try
632648
{
633-
X509Cert signingCert = signingCertificate();
634-
vector<X509Cert::KeyUsage> usage = signingCert.keyUsage();
635-
if(!contains(usage, X509Cert::NonRepudiation))
649+
if(!contains(x509.keyUsage(), X509Cert::NonRepudiation))
636650
THROW("Signing certificate does not contain NonRepudiation key usage flag");
637-
if(!signingCertificate().verify(noqscd))
651+
if(!x509.verify(noqscd, {}, untrusted))
638652
THROW("Unable to verify signing certificate");
639653
}
640654
catch(const Exception &e)

src/SignatureXAdES_B.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ namespace digidoc
116116
constexpr XMLNode V1orV2(std::string_view v1, std::string_view v2) const noexcept;
117117

118118
// offline checks
119-
void checkSigningCertificate(bool noqscd) const;
120-
void checkKeyInfo() const;
119+
void checkSigningCertificate(const X509Cert &x509, bool noqscd, const std::vector<X509Cert> &untrusted) const;
120+
void checkKeyInfo(const X509Cert &x509) const;
121121
};
122122
}

src/crypto/Signer.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
#include <openssl/x509.h>
3030

31-
#include <algorithm>
3231
#include <map>
3332
#include <optional>
3433

src/crypto/Signer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919

2020
#pragma once
2121

22-
#include "../Exception.h"
22+
#include "../Exports.h"
2323

2424
#include <memory>
25+
#include <string>
26+
#include <vector>
2527

2628
namespace digidoc
2729
{

src/crypto/X509Cert.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ X509Cert::X509Cert(X509Cert &&other) noexcept = default;
272272
/**
273273
* Clean up underlying X509 data.
274274
*/
275-
X509Cert::~X509Cert() = default;
275+
X509Cert::~X509Cert() noexcept = default;
276276

277277
/**
278278
* Encodes the X509 certificate using DER encoding.
@@ -510,7 +510,16 @@ bool X509Cert::isValid(time_t *t) const
510510
*/
511511
bool X509Cert::verify(bool noqscd, tm validation_time) const
512512
{
513-
return X509CertStore::instance()->verify(*this, noqscd, validation_time);
513+
return X509CertStore::instance()->verify(*this, noqscd, validation_time, {});
514+
}
515+
516+
/**
517+
* Returns true if certificate is signed by trusted issuer
518+
* @throws Exception if error
519+
*/
520+
bool X509Cert::verify(bool noqscd, tm validation_time, const vector<X509Cert> &untrusted) const
521+
{
522+
return X509CertStore::instance()->verify(*this, noqscd, validation_time, untrusted);
514523
}
515524

516525
/**

src/crypto/X509Cert.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace digidoc
8686
explicit X509Cert(const std::string &path, Format format = Pem);
8787
X509Cert(X509Cert &&other) noexcept;
8888
X509Cert(const X509Cert &other);
89-
~X509Cert();
89+
~X509Cert() noexcept;
9090

9191
std::string serial() const;
9292
std::string issuerName(const std::string &obj = std::string()) const;
@@ -97,6 +97,7 @@ namespace digidoc
9797
bool isCA() const;
9898
bool isValid(time_t *t = nullptr) const;
9999
bool verify(bool noqscd, tm validation_time = {}) const;
100+
bool verify(bool noqscd, tm validation_time, const std::vector<X509Cert> &untrusted) const;
100101

101102
X509* handle() const;
102103
operator std::vector<unsigned char>() const;

src/crypto/X509CertStore.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ X509CertStore::X509CertStore()
6969
/**
7070
* Release all certificates.
7171
*/
72-
X509CertStore::~X509CertStore() = default;
72+
X509CertStore::~X509CertStore() noexcept = default;
7373

7474
void X509CertStore::activate(const X509Cert &cert) const
7575
{
@@ -194,14 +194,17 @@ int X509CertStore::validate(int ok, X509_STORE_CTX *ctx)
194194
* Check if X509Cert is signed by trusted issuer
195195
* @throw Exception if error
196196
*/
197-
bool X509CertStore::verify(const X509Cert &cert, bool noqscd, tm validation_time) const
197+
bool X509CertStore::verify(const X509Cert &cert, bool noqscd, tm validation_time, const vector<X509Cert> &untrusted) const
198198
{
199199
activate(cert);
200200
if(util::date::is_empty(validation_time))
201201
ASN1_TIME_to_tm(X509_get0_notBefore(cert.handle()), &validation_time);
202202
auto store = createStore(X509CertStore::CA, validation_time);
203203
auto csc = make_unique_ptr<X509_STORE_CTX_free>(X509_STORE_CTX_new());
204-
if(!X509_STORE_CTX_init(csc.get(), store.get(), cert.handle(), nullptr))
204+
auto stack = make_unique_ptr(sk_X509_new_null(), [](auto *sk) { sk_X509_free(sk); });
205+
for(const X509Cert &i: untrusted)
206+
sk_X509_push(stack.get(), i.handle());
207+
if(!X509_STORE_CTX_init(csc.get(), store.get(), cert.handle(), stack.get()))
205208
THROW_OPENSSLEXCEPTION("Failed to init X509_STORE_CTX");
206209
if(X509_verify_cert(csc.get()) <= 0)
207210
{

src/crypto/X509CertStore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ namespace digidoc
4949
X509Cert findIssuer(const X509Cert &cert, const Type &type) const;
5050
static X509Cert issuerFromAIA(const X509Cert &cert);
5151
static unique_free_t<X509_STORE> createStore(const Type &type, tm &tm);
52-
bool verify(const X509Cert &cert, bool noqscd, tm validation_time = {}) const;
52+
bool verify(const X509Cert &cert, bool noqscd, tm validation_time, const std::vector<X509Cert> &untrusted) const;
5353

5454
private:
5555
X509CertStore();
56-
~X509CertStore();
56+
~X509CertStore() noexcept;
5757
DISABLE_COPY(X509CertStore);
5858

5959
static int validate(int ok, X509_STORE_CTX *ctx);

0 commit comments

Comments
 (0)