Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions src/SignatureXAdES_B.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,11 +544,8 @@ void SignatureXAdES_B::validate(const string &policy) const
if(!signatureref.empty())
EXCEPTION_ADD(exception, "Manifest references and signature references do not match");

try { checkKeyInfo(); }
catch(const Exception& e) { exception.addCause(e); }

try { checkSigningCertificate(policy == POLv1); }
catch(const Exception& e) { exception.addCause(e); }
auto signingCertificate = checkSigningCertificate(policy == POLv1);
checkKeyInfo(signingCertificate);
} catch(const Exception &e) {
exception.addCause(e);
} catch(...) {
Expand Down Expand Up @@ -595,9 +592,8 @@ void SignatureXAdES_B::checkDigest(XMLNode digest, const vector<unsigned char> &
* Verify if SigningCertificate matches with
* XAdES::SigningCertificate/SigningCertificateV2 Digest and IssuerSerial info
*/
void SignatureXAdES_B::checkKeyInfo() const
void SignatureXAdES_B::checkKeyInfo(const X509Cert &x509) const
{
X509Cert x509 = signingCertificate();
if(auto sigCert = signedSignatureProperties()/"SigningCertificate")
{
if(auto certs = sigCert/"Cert"; certs || !(certs + 1))
Expand Down Expand Up @@ -626,21 +622,30 @@ void SignatureXAdES_B::checkKeyInfo() const
* Check if signing certificate was issued by trusted party.
* @throws Exception on a problem with signing certificate
*/
void SignatureXAdES_B::checkSigningCertificate(bool noqscd) const
X509Cert SignatureXAdES_B::checkSigningCertificate(bool noqscd, tm validation_time) const
{
try
X509Cert signingCertificate;
vector<X509Cert> untrusted;
for(auto x509Data = signature/"KeyInfo"/"X509Data"; x509Data; x509Data++)
{
X509Cert signingCert = signingCertificate();
vector<X509Cert::KeyUsage> usage = signingCert.keyUsage();
if(!contains(usage, X509Cert::NonRepudiation))
THROW("Signing certificate does not contain NonRepudiation key usage flag");
if(!signingCertificate().verify(noqscd))
THROW("Unable to verify signing certificate");
}
catch(const Exception &e)
{
THROW_CAUSE( e, "Unable to verify signing certificate" );
for(auto x509Cert = x509Data/"X509Certificate"; x509Cert; x509Cert++)
{
vector<unsigned char> cert = x509Cert;
if(cert.empty())
continue;
if(!signingCertificate)
signingCertificate = X509Cert(cert);
else
untrusted.emplace_back(cert);
}
}
if(!signingCertificate)
THROW("Signature does not contain signer certificate");
if(!contains(signingCertificate.keyUsage(), X509Cert::NonRepudiation))
THROW("Signing certificate does not contain NonRepudiation key usage flag");
if(!signingCertificate.verify(noqscd, validation_time, untrusted))
THROW("Unable to verify signing certificate");
return signingCertificate;
}

void SignatureXAdES_B::addDataObjectFormat(const string &uri, const string &mime)
Expand Down
4 changes: 2 additions & 2 deletions src/SignatureXAdES_B.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ namespace digidoc
constexpr XMLNode signedSignatureProperties() const noexcept;
static void checkCertID(XMLNode certID, const X509Cert &cert);
static void checkDigest(XMLNode digest, const std::vector<unsigned char> &data);
X509Cert checkSigningCertificate(bool noqscd, tm validation_time = {}) const;

XMLNode signature;
ASiContainer *bdoc {};
Expand All @@ -116,7 +117,6 @@ namespace digidoc
constexpr XMLNode V1orV2(std::string_view v1, std::string_view v2) const noexcept;

// offline checks
void checkSigningCertificate(bool noqscd) const;
void checkKeyInfo() const;
void checkKeyInfo(const X509Cert &x509) const;
};
}
2 changes: 1 addition & 1 deletion src/SignatureXAdES_T.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void SignatureXAdES_T::validate(const std::string &policy) const
signatures->c14n(digest, canonicalizationMethod, signatureValue());
});

if(!signingCertificate().verify(policy == POLv1, tsa.time()))
if(!checkSigningCertificate(policy == POLv1, tsa.time()))
THROW("Signing certificate was not valid on signing time");

auto completeCertRefs = usp/"CompleteCertificateRefs";
Expand Down
1 change: 0 additions & 1 deletion src/crypto/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

#include <openssl/x509.h>

#include <algorithm>
#include <map>
#include <optional>

Expand Down
4 changes: 3 additions & 1 deletion src/crypto/Signer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

#pragma once

#include "../Exception.h"
#include "../Exports.h"

#include <memory>
#include <string>
#include <vector>

namespace digidoc
{
Expand Down
13 changes: 11 additions & 2 deletions src/crypto/X509Cert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ X509Cert::X509Cert(X509Cert &&other) noexcept = default;
/**
* Clean up underlying X509 data.
*/
X509Cert::~X509Cert() = default;
X509Cert::~X509Cert() noexcept = default;

/**
* Encodes the X509 certificate using DER encoding.
Expand Down Expand Up @@ -510,7 +510,16 @@ bool X509Cert::isValid(time_t *t) const
*/
bool X509Cert::verify(bool noqscd, tm validation_time) const
{
return X509CertStore::instance()->verify(*this, noqscd, validation_time);
return X509CertStore::instance()->verify(*this, noqscd, validation_time, {});
}

/**
* Returns true if certificate is signed by trusted issuer
* @throws Exception if error
*/
bool X509Cert::verify(bool noqscd, tm validation_time, const vector<X509Cert> &untrusted) const
{
return X509CertStore::instance()->verify(*this, noqscd, validation_time, untrusted);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/X509Cert.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ namespace digidoc
explicit X509Cert(const std::string &path, Format format = Pem);
X509Cert(X509Cert &&other) noexcept;
X509Cert(const X509Cert &other);
~X509Cert();
~X509Cert() noexcept;

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

X509* handle() const;
operator std::vector<unsigned char>() const;
Expand Down
9 changes: 6 additions & 3 deletions src/crypto/X509CertStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ X509CertStore::X509CertStore()
/**
* Release all certificates.
*/
X509CertStore::~X509CertStore() = default;
X509CertStore::~X509CertStore() noexcept = default;

void X509CertStore::activate(const X509Cert &cert) const
{
Expand Down Expand Up @@ -194,14 +194,17 @@ int X509CertStore::validate(int ok, X509_STORE_CTX *ctx)
* Check if X509Cert is signed by trusted issuer
* @throw Exception if error
*/
bool X509CertStore::verify(const X509Cert &cert, bool noqscd, tm validation_time) const
bool X509CertStore::verify(const X509Cert &cert, bool noqscd, tm validation_time, const vector<X509Cert> &untrusted) const
{
activate(cert);
if(util::date::is_empty(validation_time))
ASN1_TIME_to_tm(X509_get0_notBefore(cert.handle()), &validation_time);
auto store = createStore(X509CertStore::CA, validation_time);
auto csc = make_unique_ptr<X509_STORE_CTX_free>(X509_STORE_CTX_new());
if(!X509_STORE_CTX_init(csc.get(), store.get(), cert.handle(), nullptr))
auto stack = make_unique_ptr(sk_X509_new_null(), [](auto *sk) { sk_X509_free(sk); });
for(const X509Cert &i: untrusted)
sk_X509_push(stack.get(), i.handle());
if(!X509_STORE_CTX_init(csc.get(), store.get(), cert.handle(), stack.get()))
THROW_OPENSSLEXCEPTION("Failed to init X509_STORE_CTX");
if(X509_verify_cert(csc.get()) <= 0)
{
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/X509CertStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ namespace digidoc
X509Cert findIssuer(const X509Cert &cert, const Type &type) const;
static X509Cert issuerFromAIA(const X509Cert &cert);
static unique_free_t<X509_STORE> createStore(const Type &type, tm &tm);
bool verify(const X509Cert &cert, bool noqscd, tm validation_time = {}) const;
bool verify(const X509Cert &cert, bool noqscd, tm validation_time, const std::vector<X509Cert> &untrusted) const;

private:
X509CertStore();
~X509CertStore();
~X509CertStore() noexcept;
DISABLE_COPY(X509CertStore);

static int validate(int ok, X509_STORE_CTX *ctx);
Expand Down
Loading