Skip to content

Commit

Permalink
Implement LTA support
Browse files Browse the repository at this point in the history
IB-7996

Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma committed Aug 6, 2024
1 parent 79d7001 commit a24c598
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 198 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ jobs:
- name: Prepare vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: 4065f37d0a6628ef17cf6ee15385f9091f1075bc
vcpkgGitCommitId: 1de2026f28ead93ff1773e6e680387643e914ea1
vcpkgJsonGlob: ./vcpkg.json
runVcpkgInstall: true
runVcpkgFormatString: "[`install`, `--recurse`, `--clean-after-build`, `--x-install-root`, `$[env.VCPKG_INSTALLED_DIR]`, `--triplet`, `$[env.VCPKG_DEFAULT_TRIPLET]`, `--x-feature`, `tests`]"
Expand All @@ -169,9 +169,10 @@ jobs:
- name: Install dependencies
run: choco install doxygen.install -y > $null
- uses: actions/setup-python@v5
if: matrix.platform == 'x86'
with:
python-version: 3.11
architecture: ${{ matrix.platform }}
python-version: 3.12
architecture: x86
- name: Install WiX
run: |
dotnet tool install -g wix --version 5.0.0
Expand Down
1 change: 1 addition & 0 deletions etc/schema/OpenDocument_dsig.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsig="urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0">
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
<xs:import namespace="http://uri.etsi.org/01903/v1.3.2#" schemaLocation="XAdES01903v132-201601.xsd"/>
<xsd:import namespace="http://uri.etsi.org/01903/v1.4.1#" schemaLocation="XAdES01903v141-201601.xsd"/>
<xs:element name="document-signatures">
<xs:complexType>
<xs:sequence>
Expand Down
2 changes: 1 addition & 1 deletion prepare_osx_build_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

OPENSSL_DIR=openssl-3.0.14
LIBXML2_DIR=libxml2-2.12.8
LIBXML2_DIR=libxml2-2.12.9
XMLSEC_DIR=xmlsec1-1.3.5
ANDROID_NDK=android-ndk-r26d
FREETYPE_DIR=freetype-2.10.1
Expand Down
4 changes: 2 additions & 2 deletions src/ASiC_E.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ void ASiC_E::parseManifestAndLoadFiles(const ZipSerialize &z)
doc.validateSchema(File::path(Conf::instance()->xsdPath(), "OpenDocument_manifest_v1_2.xsd"));
for(auto file = doc/"file-entry"; file; file++)
{
auto full_path = file.property("full-path", MANIFEST_NS);
auto media_type = file.property("media-type", MANIFEST_NS);
auto full_path = file[{"full-path", MANIFEST_NS}];
auto media_type = file[{"media-type", MANIFEST_NS}];
DEBUG("full_path = '%s', media_type = '%s'", full_path.data(), media_type.data());

if(manifestFiles.find(full_path) != manifestFiles.end())
Expand Down
8 changes: 4 additions & 4 deletions src/SiVaContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,15 +350,15 @@ unique_ptr<istream> SiVaContainer::parseDDoc(bool useHashCode)
auto doc = XMLDocument::openStream(*d->ddoc, {}, true);
for(auto dataFile = doc/"DataFile"; dataFile; dataFile++)
{
auto contentType = dataFile.property("ContentType");
auto contentType = dataFile["ContentType"];
if(contentType == "HASHCODE")
THROW("Currently supports only content types EMBEDDED_BASE64 for DDOC format");
if(contentType != "EMBEDDED_BASE64")
continue;
d->dataFiles.push_back(new DataFilePrivate(base64_decode(dataFile),
string(dataFile.property("Filename")),
string(dataFile.property("MimeType")),
string(dataFile.property("Id"))));
string(dataFile["Filename"]),
string(dataFile["MimeType"]),
string(dataFile["Id"])));
if(!useHashCode)
continue;
Digest calc(URI_SHA1);
Expand Down
73 changes: 35 additions & 38 deletions src/SignatureXAdES_B.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ const map<string_view,SignatureXAdES_B::Policy> SignatureXAdES_B::policylist{
namespace digidoc
{

constexpr XMLName DigestMethod {"DigestMethod", DSIG_NS};
constexpr XMLName DigestValue {"DigestValue", DSIG_NS};
constexpr XMLName X509IssuerName {"X509IssuerName", DSIG_NS};
constexpr XMLName X509SerialNumber {"X509SerialNumber", DSIG_NS};

thread_local ASiContainer *cb_doc {};
thread_local Exception *cb_exception {};

Expand Down Expand Up @@ -240,14 +245,14 @@ SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Sig
signature = *signatures + XMLName{"Signature", DSIG_NS};
signature.setProperty("Id", nr);
auto signedInfo = signature + "SignedInfo";
(signedInfo + "CanonicalizationMethod").setProperty("Algorithm", canonMethod);
(signedInfo + CanonicalizationMethod).setProperty("Algorithm", canonMethod);
(signedInfo + "SignatureMethod").setProperty("Algorithm", X509Crypto(c).isRSAKey() ?
Digest::toRsaUri(signer->method()) : Digest::toEcUri(signer->method()));

(signature + "SignatureValue").setProperty("Id", nr + "-SIG");
signature + "KeyInfo" + "X509Data" + "X509Certificate" = c;

auto qualifyingProperties = signature + "Object" + XMLName{"QualifyingProperties", XADES_NS};
auto qualifyingProperties = signature + "Object" + QualifyingProperties;
qualifyingProperties.setProperty("Target", "#" + nr);

auto signedProperties = qualifyingProperties + "SignedProperties";
Expand Down Expand Up @@ -302,7 +307,7 @@ SignatureXAdES_B::SignatureXAdES_B(const std::shared_ptr<Signatures> &signatures
THROW("Signature block contains more than one 'Object' block.");

// QualifyingProperties
XMLNode qp = object/XMLName{"QualifyingProperties", XADES_NS};
XMLNode qp = object/QualifyingProperties;
if(!qp)
THROW("Signature block 'QualifyingProperties' is missing.");
if(qp + 1)
Expand Down Expand Up @@ -347,13 +352,13 @@ SignatureXAdES_B::SignatureXAdES_B(const std::shared_ptr<Signatures> &signatures

string_view SignatureXAdES_B::canonicalizationMethod() const noexcept
{
return (signature/"SignedInfo"/"CanonicalizationMethod").property("Algorithm");
return (signature/"SignedInfo"/CanonicalizationMethod)["Algorithm"];
}

string SignatureXAdES_B::policy() const
{
if(auto id = signedSignatureProperties()/"SignaturePolicyIdentifier"/"SignaturePolicyId"/"SigPolicyId"/"Identifier";
id && id.property("Qualifier") == "OIDAsURN")
id && id["Qualifier"] == "OIDAsURN")
return string(id);
return {};
}
Expand Down Expand Up @@ -430,8 +435,8 @@ void SignatureXAdES_B::validate(const string &policy) const
{
#if 0 //Disabled IB-3684
auto hash = id/"SigPolicyHash";
auto algo = hash[{"DigestMethod", DSIG_NS}].property("Algorithm");
vector<unsigned char> digest = hash[{"DigestValue", DSIG_NS}];
auto algo = (hash/DigestMethod)["Algorithm"];
vector<unsigned char> digest = hash/DigestValue;

bool valid = false;
if(algo == URI_SHA1) valid = digest == p->second.SHA1;
Expand Down Expand Up @@ -464,7 +469,7 @@ void SignatureXAdES_B::validate(const string &policy) const
for(auto data = sdop/"DataObjectFormat"; data; data++)
{
if(auto mime = data/"MimeType")
mimeinfo.emplace(data.property("ObjectReference"), mime);
mimeinfo.emplace(data["ObjectReference"], mime);
}
}
else
Expand All @@ -475,18 +480,18 @@ void SignatureXAdES_B::validate(const string &policy) const
}

map<string,string> signatureref;
string_view signedPropertiesId = sp.property("Id");
string_view signedPropertiesId = sp["Id"];
bool signedInfoFound = false;
for(auto ref = signature/"SignedInfo"/"Reference"; ref; ref++)
{
auto uri = ref.property("URI");
auto uri = ref["URI"];
if(uri.empty())
{
EXCEPTION_ADD(exception, "Reference URI missing");
continue;
}

if(auto algo = (ref/"DigestMethod").property("Algorithm");
if(auto algo = (ref/DigestMethod)["Algorithm"];
!Exception::hasWarningIgnore(Exception::ReferenceDigestWeak) &&
(algo == URI_SHA1 || algo == URI_SHA224))
{
Expand All @@ -495,18 +500,18 @@ void SignatureXAdES_B::validate(const string &policy) const
exception.addCause(e);
}

if(uri.front() == '#' && uri.substr(1) == signedPropertiesId && ref.property("Type") == REF_TYPE)
if(uri.front() == '#' && uri.substr(1) == signedPropertiesId && ref["Type"] == REF_TYPE)
signedInfoFound = true;
else if(!sdop)
continue; // DataObjectProperties is missing, no need to match later MediaTypes
else if(ref.property("Id").empty())
else if(ref["Id"].empty())
EXCEPTION_ADD(exception, "Reference '%.*s' ID missing", int(uri.size()), uri.data());
else
{
string uriPath = File::fromUriPath(uri);
if(uriPath.front() == '/')
uriPath.erase(0);
signatureref.emplace(uriPath, mimeinfo[string("#").append(ref.property("Id"))]);
signatureref.emplace(uriPath, mimeinfo[string("#").append(ref["Id"])]);
}
}
if(!signedInfoFound)
Expand Down Expand Up @@ -556,15 +561,15 @@ vector<unsigned char> SignatureXAdES_B::dataToSign() const
{
Digest calc(signatureMethod());
auto signedInfo = signature/"SignedInfo";
signatures->c14n(&calc, (signedInfo/"CanonicalizationMethod").property("Algorithm"), signedInfo);
signatures->c14n(&calc, (signedInfo/CanonicalizationMethod)["Algorithm"], signedInfo);
return calc.result();
}

void SignatureXAdES_B::checkCertID(XMLNode certID, const X509Cert &cert)
{
auto issuerSerial = certID/"IssuerSerial";
string_view certIssuerName = issuerSerial/XMLName{"X509IssuerName", DSIG_NS};
string_view certSerialNumber = issuerSerial/XMLName{"X509SerialNumber", DSIG_NS};
string_view certIssuerName = issuerSerial/X509IssuerName;
string_view certSerialNumber = issuerSerial/X509SerialNumber;
if(X509Crypto(cert).compareIssuerToString(certIssuerName) == 0 && cert.serial() == certSerialNumber)
return checkDigest(certID/"CertDigest", cert);
DEBUG("certIssuerName: \"%.*s\"", int(certIssuerName.size()), certIssuerName.data());
Expand All @@ -575,8 +580,8 @@ void SignatureXAdES_B::checkCertID(XMLNode certID, const X509Cert &cert)

void SignatureXAdES_B::checkDigest(XMLNode digest, const vector<unsigned char> &data)
{
auto calcDigest = Digest((digest/XMLName{"DigestMethod", DSIG_NS}).property("Algorithm")).result(data);
vector<unsigned char> digestValue = digest/XMLName{"DigestValue", DSIG_NS};
auto calcDigest = Digest((digest/DigestMethod)["Algorithm"]).result(data);
vector<unsigned char> digestValue = digest/DigestValue;
if(digestValue == calcDigest)
return;
DEBUGMEM("Document cert digest", digestValue.data(), digestValue.size());
Expand Down Expand Up @@ -676,8 +681,8 @@ string SignatureXAdES_B::addReference(const string& uri, const string& digestUri

if(!canon.empty())
(reference + "Transforms" + "Transform").setProperty("Algorithm", canon);
(reference + "DigestMethod").setProperty("Algorithm", digestUri);
reference + "DigestValue" = digestValue;
(reference + DigestMethod).setProperty("Algorithm", digestUri);
reference + DigestValue = digestValue;

return refId;
}
Expand All @@ -688,21 +693,21 @@ string SignatureXAdES_B::addReference(const string& uri, const string& digestUri
*
* @param cert certificate that is used for signing the signature XML.
*/
void SignatureXAdES_B::setSigningCertificate(string_view name, const X509Cert& x509) noexcept
void SignatureXAdES_B::setSigningCertificate(string_view name, const X509Cert& x509)
{
// Calculate digest of the X.509 certificate.
auto cert = signedSignatureProperties() + name.data() + "Cert";

Digest digest;
auto certDigest = cert + "CertDigest";
(certDigest + XMLName{"DigestMethod", DSIG_NS}).setProperty("Algorithm", digest.uri());
certDigest + XMLName{"DigestValue", DSIG_NS} = digest.result(x509);
(certDigest + DigestMethod).setProperty("Algorithm", digest.uri());
certDigest + DigestValue = digest.result(x509);

if(name == "SigningCertificate")
{
auto issuerSerial = cert + "IssuerSerial";
(issuerSerial + XMLName{"X509IssuerName", DSIG_NS}) = x509.issuerName();
issuerSerial + XMLName{"X509SerialNumber", DSIG_NS} = x509.serial();
(issuerSerial + X509IssuerName) = x509.issuerName();
issuerSerial + X509SerialNumber = x509.serial();
}
}

Expand Down Expand Up @@ -752,17 +757,9 @@ void SignatureXAdES_B::setSignerRoles(string_view name, const vector<string> &ro
*
* @param signatureValue signature value.
*/
void SignatureXAdES_B::setSignatureValue(const vector<unsigned char> &signatureValue)
{
signature/"SignatureValue" = signatureValue;
}

/**
* @return returns signature value.
*/
vector<unsigned char> SignatureXAdES_B::getSignatureValue() const
void SignatureXAdES_B::setSignatureValue(const vector<unsigned char> &value)
{
return signature/"SignatureValue";
signatureValue() = value;
}

string SignatureXAdES_B::city() const
Expand Down Expand Up @@ -821,12 +818,12 @@ X509Cert SignatureXAdES_B::signingCertificate() const

string SignatureXAdES_B::id() const
{
return string(signature.property("Id"));
return string(signature["Id"]);
}

string SignatureXAdES_B::signatureMethod() const
{
return string((signature/"SignedInfo"/"SignatureMethod").property("Algorithm"));
return string((signature/"SignedInfo"/"SignatureMethod")["Algorithm"]);
}

/**
Expand Down
14 changes: 10 additions & 4 deletions src/SignatureXAdES_B.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ namespace digidoc
constexpr std::string_view XADESv141_NS {"http://uri.etsi.org/01903/v1.4.1#"};
constexpr std::string_view REF_TYPE {"http://uri.etsi.org/01903#SignedProperties"};

constexpr XMLName QualifyingProperties {"QualifyingProperties", XADES_NS};
constexpr XMLName CanonicalizationMethod {"CanonicalizationMethod", DSIG_NS};

class ASiContainer;
class Signer;
class Signatures: public XMLDocument
Expand Down Expand Up @@ -63,7 +66,7 @@ namespace digidoc
void validate() const final;
void validate(const std::string &policy) const override;
std::vector<unsigned char> dataToSign() const final;
void setSignatureValue(const std::vector<unsigned char> &signatureValue) final;
void setSignatureValue(const std::vector<unsigned char> &value) final;

// Xades properties
std::string policy() const final;
Expand All @@ -80,10 +83,13 @@ namespace digidoc

protected:
std::string_view canonicalizationMethod() const noexcept;
std::vector<unsigned char> getSignatureValue() const;
constexpr XMLNode signatureValue() const noexcept
{
return signature/"SignatureValue";
}
constexpr XMLNode qualifyingProperties() const noexcept
{
return signature/"Object"/XMLName{"QualifyingProperties", XADES_NS};
return signature/"Object"/QualifyingProperties;
}
constexpr XMLNode signedSignatureProperties() const noexcept;
static void checkCertID(XMLNode certID, const X509Cert &cert);
Expand All @@ -104,7 +110,7 @@ namespace digidoc
std::string addReference(const std::string& uri, const std::string& digestUri,
const std::vector<unsigned char> &digestValue, std::string_view type = {}, std::string_view canon = {});
void addDataObjectFormat(const std::string& uri, const std::string& mime);
void setSigningCertificate(std::string_view name, const X509Cert& cert) noexcept;
void setSigningCertificate(std::string_view name, const X509Cert& cert);
void setSignatureProductionPlace(std::string_view name, const std::string &city,
const std::string &streetAddress, const std::string &stateOrProvince,
const std::string &postalCode, const std::string &countryName) noexcept;
Expand Down
4 changes: 2 additions & 2 deletions src/SignatureXAdES_LT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ SignatureXAdES_LT::SignatureXAdES_LT(const std::shared_ptr<Signatures> &signatur
{
try {
// ADOC files are default T level, take OCSP response to create temporary LT level
if(bdoc->mediaType() == ASiContainer::MIMETYPE_ADOC &&
if(container->mediaType() == ASiContainer::MIMETYPE_ADOC &&
!(unsignedSignatureProperties()/"RevocationValues"))
{
X509Cert cert = signingCertificate();
Expand Down Expand Up @@ -149,7 +149,7 @@ void SignatureXAdES_LT::validate(const string &policy) const
string method = Digest::digestInfoUri(ocsp.nonce());
if(method.empty())
THROW("Nonce digest method is missing");
vector<unsigned char> digest = Digest(method).result(getSignatureValue());
vector<unsigned char> digest = Digest(method).result(signatureValue());
vector<unsigned char> respDigest = Digest::digestInfoDigest(ocsp.nonce());
if(digest != respDigest)
{
Expand Down
Loading

0 comments on commit a24c598

Please sign in to comment.