diff --git a/libdigidocpp.dox b/libdigidocpp.dox
index bdf8d7ccf..9375cb6d5 100644
--- a/libdigidocpp.dox
+++ b/libdigidocpp.dox
@@ -1538,10 +1538,16 @@ Postal code of the place where the signature is created.
Country of origin. ISO 3166-type 2-character country codes are used (e.g. EE)
\-\-dontValidate | Optional |
diff --git a/src/crypto/Digest.cpp b/src/crypto/Digest.cpp
index fdafe6f17..ec93e21c0 100644
--- a/src/crypto/Digest.cpp
+++ b/src/crypto/Digest.cpp
@@ -26,42 +26,31 @@
#include
using namespace std;
-
-namespace digidoc
-{
-class Digest::Private: public vector
-{
-public:
- EVP_MD_CTX *ctx {};
- int method = -1;
-};
-}
-
using namespace digidoc;
/**
* Initializes OpenSSL digest calculator.
*
- * @param uri digest method URI (e.g. 'http://www.w3.org/2000/09/xmldsig#sha1' for SHA1).
- * @throws IOException throws exception if the digest calculator initialization failed.
+ * @param uri digest method URI (e.g. 'http://www.w3.org/2001/04/xmlenc#sha256' for SHA256).
+ * @throws Exception throws exception if the digest calculator initialization failed.
*/
Digest::Digest(const string &uri)
- : d(make_unique())
+ : d(SCOPE_PTR(EVP_MD_CTX, EVP_MD_CTX_new()))
{
- reset(uri);
+ if(uri.empty() && Conf::instance()->digestUri() == URI_SHA1)
+ THROW("Unsupported digest method %s", uri.c_str());
+ int method = toMethod(uri.empty() ? Conf::instance()->digestUri() : uri);
+ if(EVP_DigestInit(d.get(), EVP_get_digestbynid(method)) != 1)
+ THROW_OPENSSLEXCEPTION("Failed to initialize %s digest calculator", uri.c_str());
}
/**
* Destroys OpenSSL digest calculator.
*/
-Digest::~Digest()
-{
- EVP_MD_CTX_free(d->ctx);
-}
+Digest::~Digest() = default;
-vector Digest::addDigestInfo(const vector &digest, const string &uri)
+vector Digest::addDigestInfo(vector digest, string_view uri)
{
- vector result = digest;
vector oid;
switch(toMethod(uri))
{
@@ -73,8 +62,8 @@ vector Digest::addDigestInfo(const vector &digest,
default: break;
}
if(!oid.empty())
- result.insert(result.begin(), oid.begin(), oid.end());
- return result;
+ digest.insert(digest.begin(), oid.begin(), oid.end());
+ return digest;
}
vector Digest::digestInfoDigest(const std::vector &digest)
@@ -83,7 +72,7 @@ vector Digest::digestInfoDigest(const std::vector
SCOPE(X509_SIG, sig, d2i_X509_SIG(nullptr, &p, long(digest.size())));
if(!sig)
return {};
- const ASN1_OCTET_STRING *value = nullptr;
+ const ASN1_OCTET_STRING *value {};
X509_SIG_get0(sig.get(), nullptr, &value);
return { value->data, value->data + value->length };
}
@@ -94,7 +83,7 @@ string Digest::digestInfoUri(const std::vector &digest)
SCOPE(X509_SIG, sig, d2i_X509_SIG(nullptr, &p, long(digest.size())));
if(!sig)
return {};
- const X509_ALGOR *algor = nullptr;
+ const X509_ALGOR *algor {};
X509_SIG_get0(sig.get(), &algor, nullptr);
return toUri(OBJ_obj2nid(algor->algorithm));
}
@@ -105,45 +94,24 @@ string Digest::digestInfoUri(const std::vector &digest)
*/
string Digest::uri() const
{
- return toUri(d->method);
+ return toUri(EVP_MD_CTX_type(d.get()));
}
-/**
- *
- */
-void Digest::reset(const string &uri)
+bool Digest::isRsaPssUri(string_view uri)
{
- if(uri.empty() && Conf::instance()->digestUri() == URI_SHA1)
- THROW("Unsupported digest method");
-
- if(d->ctx)
- EVP_MD_CTX_free(d->ctx);
- d->ctx = EVP_MD_CTX_new();
- int result = -1;
- switch(d->method = toMethod(uri.empty() ? Conf::instance()->digestUri() : uri))
- {
- case NID_sha1: result = EVP_DigestInit(d->ctx, EVP_sha1()); break;
- case NID_sha224: result = EVP_DigestInit(d->ctx, EVP_sha224()); break;
- case NID_sha256: result = EVP_DigestInit(d->ctx, EVP_sha256()); break;
- case NID_sha384: result = EVP_DigestInit(d->ctx, EVP_sha384()); break;
- case NID_sha512: result = EVP_DigestInit(d->ctx, EVP_sha512()); break;
+ return
+ uri == URI_RSA_PSS_SHA224 ||
+ uri == URI_RSA_PSS_SHA256 ||
+ uri == URI_RSA_PSS_SHA384 ||
+ uri == URI_RSA_PSS_SHA512 ||
#ifndef LIBRESSL_VERSION_NUMBER
- case NID_sha3_224: result = EVP_DigestInit(d->ctx, EVP_sha3_224()); break;
- case NID_sha3_256: result = EVP_DigestInit(d->ctx, EVP_sha3_256()); break;
- case NID_sha3_384: result = EVP_DigestInit(d->ctx, EVP_sha3_384()); break;
- case NID_sha3_512: result = EVP_DigestInit(d->ctx, EVP_sha3_512()); break;
+ uri == URI_RSA_PSS_SHA3_224 ||
+ uri == URI_RSA_PSS_SHA3_256 ||
+ uri == URI_RSA_PSS_SHA3_384 ||
+ uri == URI_RSA_PSS_SHA3_512;
+#else
+ false;
#endif
- default: break;
- }
- d->clear();
- if(result != 1)
- THROW_OPENSSLEXCEPTION("Failed to initialize %s digest calculator", uri.c_str());
-}
-
-bool Digest::isRsaPssUri(const std::string &uri)
-{
- return uri == URI_RSA_PSS_SHA224 || uri == URI_RSA_PSS_SHA256 || uri == URI_RSA_PSS_SHA384 || uri == URI_RSA_PSS_SHA512 ||
- uri == URI_RSA_PSS_SHA3_224 || uri == URI_RSA_PSS_SHA3_256 || uri == URI_RSA_PSS_SHA3_384 || uri == URI_RSA_PSS_SHA3_512;
}
/**
@@ -152,14 +120,15 @@ bool Digest::isRsaPssUri(const std::string &uri)
* For available method URIs see:
*
* W3C XML Encryption Syntax and Processing (10 December 2005) http://www.w3.org/TR/xmlenc-core/
- * RFC 4051 http://www.ietf.org/rfc/rfc4051.txt
+ * RFC 4051 https://www.ietf.org/rfc/rfc4051.txt
+ * RFC 6931 https://www.ietf.org/rfc/rfc6931.txt
*
*
* @param uri digest method URI (e.g. 'http://www.w3.org/2000/09/xmldsig#sha1' for SHA1).
* @return returns digest OpenSSL method id.
- * @throws IOException throws exception if digest method is not supported.
+ * @throws Exception throws exception if digest method is not supported.
*/
-int Digest::toMethod(const string &uri)
+int Digest::toMethod(string_view uri)
{
if(uri == URI_SHA1 || uri == URI_RSA_SHA1 || uri == URI_ECDSA_SHA1) return NID_sha1;
if(uri == URI_SHA224 || uri == URI_RSA_SHA224 || uri == URI_RSA_PSS_SHA224 || uri == URI_ECDSA_SHA224) return NID_sha224;
@@ -172,11 +141,12 @@ int Digest::toMethod(const string &uri)
if(uri == URI_SHA3_384 || uri == URI_RSA_PSS_SHA3_384) return NID_sha3_384;
if(uri == URI_SHA3_512 || uri == URI_RSA_PSS_SHA3_512) return NID_sha3_512;
#endif
- THROW( "Digest method URI '%s' is not supported.", uri.c_str() );
+ THROW("Digest method URI '%.*s' is not supported.", uri.size(), uri.data());
}
string Digest::toRsaUri(const string &uri)
{
+ DEBUG("method %s", uri.c_str());
if(uri == URI_SHA1) return URI_RSA_SHA1;
if(uri == URI_SHA224) return URI_RSA_SHA224;
if(uri == URI_SHA256) return URI_RSA_SHA256;
@@ -186,33 +156,25 @@ string Digest::toRsaUri(const string &uri)
uri == URI_RSA_SHA224 ||
uri == URI_RSA_SHA256 ||
uri == URI_RSA_SHA384 ||
- uri == URI_RSA_SHA512 ||
- uri == URI_RSA_PSS_SHA224 ||
- uri == URI_RSA_PSS_SHA256 ||
- uri == URI_RSA_PSS_SHA384 ||
- uri == URI_RSA_PSS_SHA512 ||
-#ifndef LIBRESSL_VERSION_NUMBER
- uri == URI_RSA_PSS_SHA3_224 ||
- uri == URI_RSA_PSS_SHA3_256 ||
- uri == URI_RSA_PSS_SHA3_384 ||
- uri == URI_RSA_PSS_SHA3_512)
-#else
- 0)
-#endif
+ uri == URI_RSA_SHA512)
return uri;
- return {};
+ return toRsaPssUri(uri);
}
-string Digest::toRsaPssUri(const string &uri)
+string Digest::toRsaPssUri(string uri)
{
if(uri == URI_SHA224) return URI_RSA_PSS_SHA224;
if(uri == URI_SHA256) return URI_RSA_PSS_SHA256;
if(uri == URI_SHA384) return URI_RSA_PSS_SHA384;
if(uri == URI_SHA512) return URI_RSA_PSS_SHA512;
+#ifndef LIBRESSL_VERSION_NUMBER
if(uri == URI_SHA3_224) return URI_RSA_PSS_SHA3_224;
if(uri == URI_SHA3_256) return URI_RSA_PSS_SHA3_256;
if(uri == URI_SHA3_384) return URI_RSA_PSS_SHA3_384;
if(uri == URI_SHA3_512) return URI_RSA_PSS_SHA3_512;
+#endif
+ if(isRsaPssUri(uri))
+ return uri;
return {};
}
@@ -252,61 +214,40 @@ std::string Digest::toUri(int nid)
}
/**
- * Add data for digest calculation.
- *
- * @param data data to add for digest calculation.
- * @throws IOException throws exception if SHA1 update failed.
- * @see update(const unsigned char* data, unsigned long length)
- */
-void Digest::update(const vector &data)
-{
- update(data.data(), data.size());
-}
-
-/**
- * Add data for digest calculation. After calling getDigest() SHA context
+ * Add data for digest calculation. After calling result() SHA context
* is uninitialized and this method should not be called.
*
* @param data data to add for digest calculation.
* @param length length of the data.
- * @throws IOException throws exception if update failed.
- * @see getDigest()
+ * @throws Exception throws exception if update failed.
+ * @see result()
*/
void Digest::update(const unsigned char *data, size_t length)
{
if(!data)
THROW("Can not update digest value from NULL pointer.");
- if(!d->empty())
- THROW("Digest is already finalized, can not update it.");
- if(EVP_DigestUpdate(d->ctx, data, length) != 1)
+ if(EVP_DigestUpdate(d.get(), data, length) != 1)
THROW_OPENSSLEXCEPTION("Failed to update %s digest value", uri().c_str());
}
/**
* Calculate message digest. SHA context will be invalid after this call.
- * For calculating an other digest you must create new SHA1Digest class.
+ * For calculating an other digest you must create new Digest class.
*
* @return returns the calculated digest.
- * @throws IOException throws exception if update failed.
+ * @throws Exception throws exception if update failed.
*/
vector Digest::result() const
{
- if(!d->empty())
- return *d;
unsigned int size = 0;
- d->resize(size_t(EVP_MD_CTX_size(d->ctx)));
- if(EVP_DigestFinal(d->ctx, d->data(), &size) != 1)
+ vector result(size_t(EVP_MD_CTX_size(d.get())), 0);
+ if(EVP_DigestFinal_ex(d.get(), result.data(), &size) != 1)
THROW_OPENSSLEXCEPTION("Failed to create %s digest", uri().c_str());
- return *d;
+ return result;
}
vector Digest::result(const vector &data)
{
- return result(data.data(), data.size());
-}
-
-vector Digest::result(const unsigned char *data, size_t length)
-{
- update(data, length);
+ update(data.data(), data.size());
return result();
}
diff --git a/src/crypto/Digest.h b/src/crypto/Digest.h
index 5cea59f63..c0a289550 100644
--- a/src/crypto/Digest.h
+++ b/src/crypto/Digest.h
@@ -45,7 +45,6 @@
#define URI_RSA_PSS_SHA256 "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"
#define URI_RSA_PSS_SHA384 "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1"
#define URI_RSA_PSS_SHA512 "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1"
-
#define URI_RSA_PSS_SHA3_224 "http://www.w3.org/2007/05/xmldsig-more#sha3-224-rsa-MGF1"
#define URI_RSA_PSS_SHA3_256 "http://www.w3.org/2007/05/xmldsig-more#sha3-256-rsa-MGF1"
#define URI_RSA_PSS_SHA3_384 "http://www.w3.org/2007/05/xmldsig-more#sha3-384-rsa-MGF1"
@@ -57,6 +56,8 @@
#define URI_ECDSA_SHA384 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
#define URI_ECDSA_SHA512 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"
+using EVP_MD_CTX = struct evp_md_ctx_st;
+
namespace digidoc
{
/**
@@ -67,28 +68,24 @@ namespace digidoc
public:
Digest(const std::string &uri = {});
~Digest();
- void reset(const std::string &uri = {});
- void update(const std::vector &data);
void update(const unsigned char *data, size_t length);
std::vector result(const std::vector &data);
- std::vector result(const unsigned char *data, size_t length);
std::vector result() const;
std::string uri() const;
- static bool isRsaPssUri(const std::string &uri);
+ static bool isRsaPssUri(std::string_view uri);
static std::string toRsaUri(const std::string &uri);
- static std::string toRsaPssUri(const std::string &uri);
+ static std::string toRsaPssUri(std::string uri);
static std::string toEcUri(const std::string &uri);
- static int toMethod(const std::string &uri);
+ static int toMethod(std::string_view uri);
static std::string toUri(int nid);
- static std::vector addDigestInfo(const std::vector &digest, const std::string &uri);
+ static std::vector addDigestInfo(std::vector digest, std::string_view uri);
static std::vector digestInfoDigest(const std::vector &digest);
static std::string digestInfoUri(const std::vector &digest);
private:
DISABLE_COPY(Digest);
- class Private;
- std::unique_ptr d;
+ std::unique_ptr d;
};
}
diff --git a/src/crypto/PKCS11Signer.cpp b/src/crypto/PKCS11Signer.cpp
index c1ded1123..c7138943d 100644
--- a/src/crypto/PKCS11Signer.cpp
+++ b/src/crypto/PKCS11Signer.cpp
@@ -60,7 +60,7 @@ class PKCS11Signer::Private
{ return h ? (void*)GetProcAddress(h, symbol) : nullptr; }
void unload()
- { if(h) FreeLibrary(h); h = 0; }
+ { if(h) FreeLibrary(h); h = {}; }
HINSTANCE h {};
#else
@@ -71,7 +71,7 @@ class PKCS11Signer::Private
{ return h ? dlsym(h, symbol) : nullptr; }
void unload()
- { if(h) dlclose(h); h = nullptr; }
+ { if(h) dlclose(h); h = {}; }
void *h {};
#endif
@@ -222,7 +222,7 @@ X509Cert PKCS11Signer::cert() const
if(d->findObject(session, CKO_PUBLIC_KEY, id).empty())
continue;
certSlotMapping.push_back({x509, slot, id});
- certificates.push_back(move(x509));
+ certificates.push_back(std::move(x509));
}
}
if(session)
@@ -251,17 +251,19 @@ X509Cert PKCS11Signer::cert() const
string PKCS11Signer::method() const
{
- if(!d->sign.certificate || !X509Crypto(d->sign.certificate).isRSAKey())
- return Signer::method();
+ string parent = Signer::method();
+ if(!d->sign.certificate || !X509Crypto(d->sign.certificate).isRSAKey() ||
+ parent != CONF(signatureDigestUri))
+ return parent;
CK_ULONG count = 0;
CK_RV rv = d->f->C_GetMechanismList(d->sign.slot, nullptr, &count);
if(rv != CKR_OK)
- return Signer::method();
+ return parent;
vector mech(count);
rv = d->f->C_GetMechanismList(d->sign.slot, mech.data(), &count);
if(find(mech.cbegin(), mech.cend(), CKM_RSA_PKCS_PSS) != mech.cend())
- return Digest::toRsaPssUri(Signer::method());
- return Signer::method();
+ return Digest::toRsaPssUri(std::move(parent));
+ return parent;
}
/**
@@ -379,7 +381,7 @@ vector PKCS11Signer::sign(const string &method, const vectorf->C_GetAttributeValue(session, key[0], &attribute, 1);
+ d->f->C_GetAttributeValue(session, key.front(), &attribute, 1);
CK_RSA_PKCS_PSS_PARAMS pssParams { CKM_SHA_1, CKG_MGF1_SHA1, 0 };
CK_MECHANISM mech { keyType == CKK_ECDSA ? CKM_ECDSA : CKM_RSA_PKCS, nullptr, 0 };
@@ -406,8 +408,8 @@ vector PKCS11Signer::sign(const string &method, const vectorf->C_SignInit(session, &mech, key[0]) != CKR_OK)
+ data = Digest::addDigestInfo(std::move(data), method);
+ if(d->f->C_SignInit(session, &mech, key.front()) != CKR_OK)
THROW("Failed to sign digest");
CK_ULONG size = 0;
diff --git a/src/crypto/Signer.cpp b/src/crypto/Signer.cpp
index ea447a2d3..deb69d37f 100644
--- a/src/crypto/Signer.cpp
+++ b/src/crypto/Signer.cpp
@@ -22,13 +22,14 @@
#include "ASiC_E.h"
#include "Conf.h"
#include "crypto/Digest.h"
-#include "crypto/OpenSSLHelpers.h"
#include "crypto/X509Cert.h"
+#include "util/log.h"
#include
#include
#include |