Skip to content

Commit

Permalink
Make digest to movable object cleanup usage
Browse files Browse the repository at this point in the history
IB-8236

Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma committed Oct 4, 2024
1 parent 72437de commit a436256
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 69 deletions.
20 changes: 9 additions & 11 deletions src/DataFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "util/File.h"
#include "util/log.h"

#include <array>
#include <fstream>

using namespace digidoc;
Expand Down Expand Up @@ -98,19 +97,18 @@ DataFilePrivate::DataFilePrivate(unique_ptr<istream> &&is, string filename, stri
m_size = pos < 0 ? 0 : (unsigned long)pos;
}

vector<unsigned char> DataFilePrivate::calcDigest(const string &method) const
void DataFilePrivate::digest(const Digest &digest) const
{
Digest digest(method);
array<unsigned char, 10240> buf{};
m_is->clear();
m_is->seekg(0);
while(*m_is)
{
m_is->read((char*)buf.data(), streamsize(buf.size()));
if(m_is->gcount() > 0)
digest.update(buf.data(), size_t(m_is->gcount()));
}
return digest.result();
digest.update(*m_is);
}

vector<unsigned char> DataFilePrivate::calcDigest(const string &method) const
{
Digest d(method);
digest(d);
return d.result();
}

void DataFilePrivate::saveAs(const string& path) const
Expand Down
2 changes: 2 additions & 0 deletions src/DataFile_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

namespace digidoc
{
class Digest;

class DataFilePrivate final: public DataFile
{
Expand All @@ -37,6 +38,7 @@ class DataFilePrivate final: public DataFile
unsigned long fileSize() const final { return m_size; }
std::string mediaType() const final { return m_mediatype; }

void digest(const Digest &method) const;
std::vector<unsigned char> calcDigest(const std::string &method) const final;
void saveAs(std::ostream &os) const final;
void saveAs(const std::string& path) const final;
Expand Down
4 changes: 2 additions & 2 deletions src/SiVaContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void SignatureSiVa::validate(const string &policy) const
for(const Exception &exception: _exceptions)
e.addCause(exception);
if(!Exception::hasWarningIgnore(Exception::SignatureDigestWeak) &&
(_signatureMethod == URI_RSA_SHA1 || _signatureMethod == URI_ECDSA_SHA1))
Digest::isWeakDigest(_signatureMethod))
{
Exception ex(EXCEPTION_PARAMS("Signature digest weak"));
ex.setCode(Exception::SignatureDigestWeak);
Expand Down Expand Up @@ -362,7 +362,7 @@ unique_ptr<istream> SiVaContainer::parseDDoc(bool useHashCode)
if(!useHashCode)
continue;
Digest calc(URI_SHA1);
doc.c14n(&calc, XMLDocument::C14D_ID_1_0, dataFile);
doc.c14n(calc, XMLDocument::C14D_ID_1_0, dataFile);
dataFile.setProperty("ContentType", "HASHCODE");
dataFile.setProperty("DigestType", "sha1");
dataFile.setProperty("DigestValue", to_base64(calc.result()));
Expand Down
4 changes: 2 additions & 2 deletions src/SignatureTST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ void SignatureTST::validate() const
const auto *dataFile = static_cast<const DataFilePrivate*>(asicSDoc->dataFiles().front());
timestampToken->verify(dataFile->calcDigest(digestMethod));

if(digestMethod == URI_SHA1 &&
!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak))
if(!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) &&
Digest::isWeakDigest(digestMethod))
{
Exception e(EXCEPTION_PARAMS("TimeStamp '%s' digest weak", digestMethod.c_str()));
e.setCode(Exception::ReferenceDigestWeak);
Expand Down
14 changes: 6 additions & 8 deletions src/SignatureXAdES_B.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Sig
}

Digest calc(digestMethod);
signatures->c14n(&calc, canonMethod, signedProperties);
signatures->c14n(calc, canonMethod, signedProperties);
addReference("#" + nr + "-SignedProperties", calc.uri(), calc.result(), REF_TYPE, canonMethod);
}

Expand Down Expand Up @@ -417,9 +417,8 @@ void SignatureXAdES_B::validate(const string &policy) const
// It'll be only thrown in case we have a reason (cause).
Exception exception(EXCEPTION_PARAMS("Signature validation"));

if(auto method = signatureMethod();
!Exception::hasWarningIgnore(Exception::SignatureDigestWeak) &&
(method == URI_RSA_SHA1 || method == URI_ECDSA_SHA1))
if(!Exception::hasWarningIgnore(Exception::SignatureDigestWeak) &&
Digest::isWeakDigest(signatureMethod()))
{
Exception e(EXCEPTION_PARAMS("Signature digest weak"));
e.setCode(Exception::SignatureDigestWeak);
Expand Down Expand Up @@ -496,9 +495,8 @@ void SignatureXAdES_B::validate(const string &policy) const
continue;
}

if(auto algo = (ref/DigestMethod)["Algorithm"];
!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) &&
(algo == URI_SHA1 || algo == URI_SHA224))
if(!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) &&
Digest::isWeakDigest((ref/DigestMethod)["Algorithm"]))
{
Exception e(EXCEPTION_PARAMS("Reference '%.*s' digest weak", int(uri.size()), uri.data()));
e.setCode(Exception::ReferenceDigestWeak);
Expand Down Expand Up @@ -566,7 +564,7 @@ vector<unsigned char> SignatureXAdES_B::dataToSign() const
{
Digest calc(signatureMethod());
auto signedInfo = signature/"SignedInfo";
signatures->c14n(&calc, (signedInfo/CanonicalizationMethod)["Algorithm"], signedInfo);
signatures->c14n(calc, (signedInfo/CanonicalizationMethod)["Algorithm"], signedInfo);
return calc.result();
}

Expand Down
19 changes: 4 additions & 15 deletions src/SignatureXAdES_LTA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "util/File.h"

#include <algorithm>
#include <array>

using namespace digidoc;
using namespace digidoc::util;
Expand All @@ -40,8 +39,7 @@ namespace digidoc
constexpr XMLName ArchiveTimeStamp {"ArchiveTimeStamp", XADESv141_NS};
}

void SignatureXAdES_LTA::calcArchiveDigest(Digest *digest,
string_view canonicalizationMethod) const
void SignatureXAdES_LTA::calcArchiveDigest(const Digest &digest, string_view canonicalizationMethod) const
{
for(auto ref = signature/"SignedInfo"/"Reference"; ref; ref++)
{
Expand All @@ -66,16 +64,7 @@ void SignatureXAdES_LTA::calcArchiveDigest(Digest *digest,
if(file == files.cend())
THROW("Filed to find reference URI in container");

std::istream *is = static_cast<const DataFilePrivate*>(*file)->m_is.get();
array<unsigned char, 10240> buf{};
is->clear();
is->seekg(0);
while(*is)
{
is->read((char*)buf.data(), streamsize(buf.size()));
if(is->gcount() > 0)
digest->update(buf.data(), size_t(is->gcount()));
}
static_cast<const DataFilePrivate*>(*file)->digest(digest);
}

for(const auto *name: {"SignedInfo", "SignatureValue", "KeyInfo"})
Expand Down Expand Up @@ -119,7 +108,7 @@ void SignatureXAdES_LTA::extendSignatureProfile(const string &profile)
return;
Digest calc;
auto method = canonicalizationMethod();
calcArchiveDigest(&calc, method);
calcArchiveDigest(calc, method);

TS tsa(CONF(TSUrl), calc);
auto ts = unsignedSignatureProperties() + ArchiveTimeStamp;
Expand Down Expand Up @@ -168,7 +157,7 @@ void SignatureXAdES_LTA::validate(const string &policy) const
auto ts = unsignedSignatureProperties()/ArchiveTimeStamp;
if(!ts)
THROW("Missing ArchiveTimeStamp element");
verifyTS(ts, exception, [this](Digest *digest, string_view canonicalizationMethod) {
verifyTS(ts, exception, [this](const Digest &digest, string_view canonicalizationMethod) {
calcArchiveDigest(digest, canonicalizationMethod);
});
} catch(const Exception &e) {
Expand Down
3 changes: 1 addition & 2 deletions src/SignatureXAdES_LTA.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ class SignatureXAdES_LTA final: public SignatureXAdES_LT
private:
DISABLE_COPY(SignatureXAdES_LTA);

void calcArchiveDigest(Digest *digest,
std::string_view canonicalizationMethod) const;
void calcArchiveDigest(const Digest &digest, std::string_view canonicalizationMethod) const;
TS tsaFromBase64() const;
};

Expand Down
14 changes: 7 additions & 7 deletions src/SignatureXAdES_T.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void SignatureXAdES_T::extendSignatureProfile(const std::string &profile)

Digest calc;
auto method = canonicalizationMethod();
signatures->c14n(&calc, method, signatureValue());
signatures->c14n(calc, method, signatureValue());

TS tsa(CONF(TSUrl), calc);
auto ts = usp + "SignatureTimeStamp";
Expand Down Expand Up @@ -109,7 +109,7 @@ void SignatureXAdES_T::validate(const std::string &policy) const
if(ts + 1)
THROW("More than one SignatureTimeStamp is not supported");

TS tsa = verifyTS(ts, exception, [this](Digest *digest, string_view canonicalizationMethod) {
TS tsa = verifyTS(ts, exception, [this](const Digest &digest, string_view canonicalizationMethod) {
signatures->c14n(digest, canonicalizationMethod, signatureValue());
});

Expand Down Expand Up @@ -163,7 +163,7 @@ void SignatureXAdES_T::validate(const std::string &policy) const

for(auto sigAndRefsTS = usp/"SigAndRefsTimeStamp"; sigAndRefsTS; sigAndRefsTS++)
{
verifyTS(sigAndRefsTS, exception, [this, usp](Digest *digest, string_view canonicalizationMethod) {
verifyTS(sigAndRefsTS, exception, [this, usp](const Digest &digest, string_view canonicalizationMethod) {
signatures->c14n(digest, canonicalizationMethod, signatureValue());
for(const auto *name: {
"SignatureTimeStamp",
Expand Down Expand Up @@ -195,7 +195,7 @@ XMLNode SignatureXAdES_T::unsignedSignatureProperties() const
}

TS SignatureXAdES_T::verifyTS(XMLNode timestamp, digidoc::Exception &exception,
std::function<void (Digest *, std::string_view)> &&calcDigest)
std::function<void (const Digest &, std::string_view)> &&calcDigest)
{
auto ets = timestamp/EncapsulatedTimeStamp;
if(!ets)
Expand All @@ -205,11 +205,11 @@ TS SignatureXAdES_T::verifyTS(XMLNode timestamp, digidoc::Exception &exception,

TS ts(ets);
Digest calc(ts.digestMethod());
calcDigest(&calc, (timestamp/CanonicalizationMethod)["Algorithm"]);
calcDigest(calc, (timestamp/CanonicalizationMethod)["Algorithm"]);
ts.verify(calc.result());

if(ts.digestMethod() == URI_SHA1 &&
!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak))
if(!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) &&
Digest::isWeakDigest(ts.digestMethod()))
{
Exception e(EXCEPTION_PARAMS("TimeStamp '%s' digest weak", ts.digestMethod().c_str()));
e.setCode(Exception::ReferenceDigestWeak);
Expand Down
2 changes: 1 addition & 1 deletion src/SignatureXAdES_T.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class SignatureXAdES_T: public SignatureXAdES_B
TS TimeStamp() const;

static TS verifyTS(XMLNode timestamp, Exception &exception,
std::function<void (Digest *, std::string_view)> &&calcDigest);
std::function<void (const Digest &, std::string_view)> &&calcDigest);

private:
DISABLE_COPY(SignatureXAdES_T);
Expand Down
4 changes: 2 additions & 2 deletions src/XMLDocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ struct XMLDocument: public unique_xml_t<decltype(xmlFreeDoc)>, public XMLNode
return doc;
}

void c14n(Digest *digest, std::string_view algo, XMLNode node)
void c14n(const Digest &digest, std::string_view algo, XMLNode node)
{
xmlC14NMode mode = XML_C14N_1_0;
int with_comments = 0;
Expand Down Expand Up @@ -383,7 +383,7 @@ struct XMLDocument: public unique_xml_t<decltype(xmlFreeDoc)>, public XMLNode
auto *digest = static_cast<Digest *>(context);
digest->update(pcxmlChar(buffer), size_t(len));
return len;
}, nullptr, digest, nullptr), xmlOutputBufferClose);
}, nullptr, const_cast<Digest*>(&digest), nullptr), xmlOutputBufferClose);
int size = xmlC14NExecute(get(), [](void *root, xmlNodePtr node, xmlNodePtr parent) constexpr noexcept {
if(root == node)
return 1;
Expand Down
33 changes: 27 additions & 6 deletions src/crypto/Digest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <openssl/evp.h>
#include <openssl/x509.h>

#include <array>

using namespace std;
using namespace digidoc;

Expand All @@ -44,11 +46,6 @@ Digest::Digest(string_view uri)
THROW_OPENSSLEXCEPTION("Failed to initialize %.*s digest calculator", int(uri.size()), uri.data());
}

/**
* Destroys OpenSSL digest calculator.
*/
Digest::~Digest() = default;

vector<unsigned char> Digest::addDigestInfo(vector<unsigned char> digest, string_view uri)
{
switch(toMethod(uri))
Expand Down Expand Up @@ -116,6 +113,11 @@ bool Digest::isRsaPssUri(string_view uri)
#endif
}

bool Digest::isWeakDigest(string_view uri)
{
return toMethod(uri) == NID_sha1;
}

/**
* Converts digest method URI to OpenSSL method id (e.g. 'http://www.w3.org/2000/09/xmldsig#sha1' to NID_sha1,
* see openssl/obj_mac.h)
Expand Down Expand Up @@ -224,14 +226,33 @@ std::string Digest::toUri(int nid)
* @throws Exception throws exception if update failed.
* @see result()
*/
void Digest::update(const unsigned char *data, size_t length)
void Digest::update(const unsigned char *data, size_t length) const
{
if(!data)
THROW("Can not update digest value from NULL pointer.");
if(EVP_DigestUpdate(d.get(), data, length) != 1)
THROW_OPENSSLEXCEPTION("Failed to update %s digest value", uri().c_str());
}

/**
* Add data for digest calculation. After calling <code>result()</code> SHA context
* is uninitialized and this method should not be called.
*
* @param is stream to add for digest calculation.
* @throws Exception throws exception if update failed.
* @see result()
*/
void Digest::update(istream &is) const
{
array<unsigned char, 10240> buf{};
while(is)
{
is.read((char*)buf.data(), streamsize(buf.size()));
if(is.gcount() > 0)
update(buf.data(), size_t(is.gcount()));
}
}

/**
* Calculate message digest. SHA context will be invalid after this call.
* For calculating an other digest you must create new Digest class.
Expand Down
6 changes: 3 additions & 3 deletions src/crypto/Digest.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ namespace digidoc
{
public:
Digest(std::string_view uri = {});
~Digest();
void update(const unsigned char *data, size_t length);
void update(const unsigned char *data, size_t length) const;
void update(std::istream &is) const;
std::vector<unsigned char> result(const std::vector<unsigned char> &data);
std::vector<unsigned char> result() const;
std::string uri() const;

static bool isRsaPssUri(std::string_view uri);
static bool isWeakDigest(std::string_view uri);
static std::string toRsaUri(const std::string &uri);
static std::string toRsaPssUri(std::string uri);
static std::string toEcUri(const std::string &uri);
Expand All @@ -88,7 +89,6 @@ namespace digidoc
static std::string digestInfoUri(const std::vector<unsigned char> &digest);

private:
DISABLE_COPY(Digest);
std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> d;
};

Expand Down
10 changes: 2 additions & 8 deletions src/crypto/TSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,15 +611,9 @@ bool TSL::validateRemoteDigest(const string &url)
digest = File::hexToBin(r.content);
}

Digest sha(URI_RSA_SHA256);
array<unsigned char, 10240> buf{};
Digest sha(URI_SHA256);
ifstream is(path, ifstream::binary);
while(is)
{
is.read((char*)buf.data(), streamsize(buf.size()));
if(is.gcount() > 0)
sha.update(buf.data(), size_t(is.gcount()));
}
sha.update(is);

if(!digest.empty() && digest != sha.result())
THROW("TSL %s remote digest does not match local. TSL might be outdated", territory().data());
Expand Down
4 changes: 2 additions & 2 deletions test/libdigidocpp_boost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(signature, Doc, DocTypes)
BOOST_CHECK_EQUAL(d->signatures().size(), 2U);
if(s3)
{
BOOST_CHECK_EQUAL(s3->signatureMethod(), URI_ECDSA_SHA384);
BOOST_CHECK_EQUAL(s3->signatureMethod(), "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384");
BOOST_CHECK_EQUAL(s3->signingCertificate(), signer3.cert());
BOOST_CHECK_NO_THROW(s3->validate());
}
Expand Down Expand Up @@ -381,7 +381,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(signature, Doc, DocTypes)
// RSA PSS tests
d = Container::createPtr(Doc::EXT + ".tmp");
BOOST_CHECK_NO_THROW(d->addDataFile("test1.txt", "text/plain"));
signer1.setMethod(URI_RSA_PSS_SHA256);
signer1.setMethod("http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1");
BOOST_CHECK_NO_THROW(s = d->sign(&signer1));
BOOST_CHECK_NO_THROW(s->validate());
BOOST_CHECK_EQUAL(s->signatureMethod(), signer1.method());
Expand Down

0 comments on commit a436256

Please sign in to comment.