diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 03a0c1377..4c59f5594 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -179,6 +179,10 @@ jobs:
architecture: ${{ matrix.platform }}
- name: Build xsd
run: .\prepare_win_build_environment.ps1 -xsd
+ - name: Install WiX
+ run: |
+ dotnet tool install -g wix
+ wix extension -g add WixToolset.UI.wixext
- name: Setup dev env
uses: ilammy/msvc-dev-cmd@v1
with:
diff --git a/build.ps1 b/build.ps1
index d70bcea53..9b72e3375 100644
--- a/build.ps1
+++ b/build.ps1
@@ -11,10 +11,7 @@ param(
[string]$cmake = "cmake.exe",
[string]$generator = "NMake Makefiles",
[string]$vcvars = "vcvarsall",
- [string]$wix = "$env:WIX",
- [string]$heat = "$wix\bin\heat.exe",
- [string]$candle = "$wix\bin\candle.exe",
- [string]$light = "$wix\bin\light.exe",
+ [string]$wix = "wix.exe",
[string]$swig = $null,
[string]$doxygen = $null,
[switch]$boost = $false,
@@ -22,18 +19,21 @@ param(
[string]$sign = $null
)
+# Hack to fetch heat.exe tool
+& dotnet new console -o wix-heat --force
+& dotnet add wix-heat package WixToolset.Heat
+$heat = Get-ChildItem "$env:USERPROFILE\.nuget\packages\WixToolset.Heat" -Include heat.exe -Recurse
+
$cmakeext = @()
-$candleext = @()
-$lightext = @()
+$wixext = @()
$target = @("all")
if($swig) {
$cmakeext += "-DSWIG_EXECUTABLE=$swig"
- $candleext += "-dswig=$swig"
+ $wixext += "-d", "swig=$swig"
}
if($doxygen) {
$cmakeext += "-DDOXYGEN_EXECUTABLE=$doxygen"
- $candleext += "-ddocLocation=$platform/share/doc/libdigidocpp", "DocFilesFragment.wxs"
- $lightext += "DocFilesFragment.wixobj"
+ $wixext += "-d", "docLocation=$platform/share/doc/libdigidocpp", "DocFilesFragment.wxs"
}
if($boost) {
$cmakeext += "-DVCPKG_MANIFEST_FEATURES=tests"
@@ -54,16 +54,21 @@ foreach($type in @("Debug", "RelWithDebInfo")) {
}
if($doxygen) {
- & $heat dir $platform/share/doc/libdigidocpp -nologo -cg Documentation -gg -scom -sreg -sfrag -srd -dr DocumentationFolder -var var.docLocation -out DocFilesFragment.wxs
+ & $heat[0] dir $platform/share/doc/libdigidocpp -nologo -cg Documentation -gg -scom -sreg -sfrag -srd -dr DocumentationFolder -var var.docLocation -out DocFilesFragment.wxs
}
-& $heat dir $platform/include -nologo -cg Headers -gg -scom -sreg -sfrag -srd -dr HeadersFolder -var var.headersLocation -out HeadersFragment.wxs
-& $candle -nologo -arch $platform "-dICON=$libdigidocpp/cmake/modules/ID.ico" "-dMSI_VERSION=$msiversion" `
- "-dvcpkg=$vcpkg_installed\vcpkg_installed_$platform\$platform-windows" "-dheadersLocation=$platform/include" `
- "-dlibdigidocpp=$platform" $candleext $libdigidocpp\libdigidocpp.wxs HeadersFragment.wxs
-& $light -nologo -out $msi_name -ext WixUIExtension `
- "-dWixUIBannerBmp=$libdigidocpp/cmake/modules/banner.bmp" `
- "-dWixUIDialogBmp=$libdigidocpp/cmake/modules/dlgbmp.bmp" `
- $lightext libdigidocpp.wixobj HeadersFragment.wixobj
+
+& $heat[0] dir $platform/include -nologo -cg Headers -gg -scom -sreg -sfrag -srd -dr HeadersFolder -var var.headersLocation -out HeadersFragment.wxs
+& $wix build -nologo -arch $platform -out $msi_name $wixext `
+ -ext WixToolset.UI.wixext `
+ -bv "WixUIBannerBmp=$libdigidocpp/cmake/modules/banner.bmp" `
+ -bv "WixUIDialogBmp=$libdigidocpp/cmake/modules/dlgbmp.bmp" `
+ -d "ICON=$libdigidocpp/cmake/modules/ID.ico" `
+ -d "MSI_VERSION=$msiversion" `
+ -d "vcpkg=$vcpkg_installed/vcpkg_installed_$platform/$platform-windows" `
+ -d "libdigidocpp=$platform" `
+ -d "headersLocation=$platform/include" `
+ HeadersFragment.wxs `
+ $libdigidocpp\libdigidocpp.wxs
if($sign) {
signtool.exe sign /a /v /s MY /n "$sign" /fd SHA256 /du http://installer.id.ee `
diff --git a/cmake b/cmake
index 712a5c282..da3cafb07 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit 712a5c2828c01282150b657ff6932cc32fc17947
+Subproject commit da3cafb0712eac8fbfddd7d37343016430b65b44
diff --git a/libdigidocpp.wxs b/libdigidocpp.wxs
index 0b49336f6..9fa9f7038 100644
--- a/libdigidocpp.wxs
+++ b/libdigidocpp.wxs
@@ -1,17 +1,14 @@
-
-
+
-
-
@@ -25,118 +22,117 @@
-
-
-
-
-
-
+
+
+
+
+
+
+ "A newer version of [ProductName] is already installed. If you are trying to downgrade, please uninstall the newer version first." />
-
- 1
- 1
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/prepare_win_build_environment.ps1 b/prepare_win_build_environment.ps1
index 76de9cf75..07d778d97 100644
--- a/prepare_win_build_environment.ps1
+++ b/prepare_win_build_environment.ps1
@@ -3,10 +3,11 @@ param(
[string]$vcpkg = "vcpkg\vcpkg.exe",
[string]$git = "git.exe",
[switch]$xsd = $false,
+ [switch]$wix = $false,
[switch]$dependencies = $false
)
-function xsd() {
+if($xsd) {
$client = new-object System.Net.WebClient
& mkdir xsd
foreach($xsdver in @("xsd-4.2.0-x86_64-windows10", "libxsd-4.2.0-windows")) {
@@ -17,8 +18,9 @@ function xsd() {
}
}
-if($xsd) {
- xsd
+if($wix) {
+ & dotnet tool install --global wix
+ & wix extension add -g WixToolset.UI.wixext
}
if($dependencies) {
@@ -31,7 +33,3 @@ if($dependencies) {
& $vcpkg install --clean-after-build --triplet x64-windows --x-feature=tests --x-install-root=vcpkg_installed_x64
}
-if(!$xsd -and !$dependencies) {
- xsd
-}
-
diff --git a/src/SignatureXAdES_B.cpp b/src/SignatureXAdES_B.cpp
index 17e64670c..99fbee19f 100644
--- a/src/SignatureXAdES_B.cpp
+++ b/src/SignatureXAdES_B.cpp
@@ -244,7 +244,7 @@ SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Sig
// Signature->SignedInfo
auto signedInfo = make_unique(
- make_unique(/*URI_ID_EXC_C14N_NOC*/URI_ID_C14N11_NOC),
+ make_unique(URI_ID_C14N11_NOC),
make_unique(X509Crypto(c).isRSAKey() ?
Digest::toRsaUri(signer->method()) : Digest::toEcUri(signer->method())));
@@ -291,14 +291,16 @@ SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Sig
string digestMethod = Conf::instance()->digestUri();
for(const DataFile *f: bdoc->dataFiles())
{
- string referenceId = addReference(File::toUriPath(f->fileName()), digestMethod, f->calcDigest(digestMethod), {});
+ string referenceId = addReference(File::toUriPath(f->fileName()), digestMethod, f->calcDigest(digestMethod));
addDataObjectFormat("#" + referenceId, f->mediaType());
}
signatures->reloadDOM();
Digest calc(digestMethod);
- calcDigestOnNode(&calc, Signatures::XADES_NAMESPACE, u"SignedProperties");
- addReference("#" + nr +"-SignedProperties", calc.uri(), calc.result(), "http://uri.etsi.org/01903#SignedProperties");
+ calcDigestOnNode(&calc, Signatures::XADES_NAMESPACE, u"SignedProperties",
+ signature->signedInfo().canonicalizationMethod().algorithm());
+ addReference("#" + nr +"-SignedProperties", calc.uri(), calc.result(), "http://uri.etsi.org/01903#SignedProperties",
+ signature->signedInfo().canonicalizationMethod().algorithm());
signatures->reloadDOM();
}
@@ -543,7 +545,7 @@ void SignatureXAdES_B::validate(const string &policy) const
m_errStr.sbXMLChIn((const XMLCh*)u"");
if(!DSIGReference::verifyReferenceList(sig->getReferenceList(), m_errStr))
- //if(!sig->verify()) //xml-security-c < 2.0.0 does not support URI_ID_C14N11_NOC canonicalization
+ //if(!sig->verify()) //xml-security-c does not support URI_RSA_PSS_SHA
{
//string s = xml::transcode(sig->getErrMsgs())
string s = xml::transcode(m_errStr.rawXMLChBuffer());
@@ -672,7 +674,8 @@ vector SignatureXAdES_B::dataToSign() const
{
// Calculate SHA digest of the Signature->SignedInfo node.
Digest calc(signatureMethod());
- calcDigestOnNode(&calc, URI_ID_DSIG, u"SignedInfo");
+ calcDigestOnNode(&calc, URI_ID_DSIG, u"SignedInfo",
+ signature->signedInfo().canonicalizationMethod().algorithm());
return calc.result();
}
@@ -801,15 +804,21 @@ void SignatureXAdES_B::addDataObjectFormat(const string &uri, const string &mime
* @throws SignatureException throws exception if the digest method is not supported.
*/
string SignatureXAdES_B::addReference(const string& uri, const string& digestUri,
- const vector &digestValue, const string& type)
+ const vector &digestValue, const string &type, const string &canon)
{
auto reference = make_unique(make_unique(digestUri), toBase64(digestValue));
- reference->uRI(uri);
+ reference->uRI(make_unique(uri));
if(!type.empty())
reference->type(type);
+ if(!canon.empty())
+ {
+ reference->transforms(make_unique());
+ reference->transforms()->transform().push_back(make_unique(canon));
+ }
+
SignedInfoType::ReferenceSequence &seq = signature->signedInfo().reference();
- reference->id(id() + Log::format("-RefId%zu", seq.size()));
+ reference->id(make_unique(id() + Log::format("-RefId%zu", seq.size())));
seq.push_back(std::move(reference));
return seq.back().id().get();
@@ -994,18 +1003,16 @@ vector SignatureXAdES_B::getSignatureValue() const
* @param ns signature tag namespace.
* @param tagName signature tag name.
*/
-void SignatureXAdES_B::calcDigestOnNode(Digest* calc, const string& ns,
+void SignatureXAdES_B::calcDigestOnNode(Digest* calc, string_view ns,
u16string_view tagName, string_view canonicalizationMethod) const
{
try
{
auto *element = signatures->element(id());
- DOMNodeList *nodeList = element->getElementsByTagNameNS(xml::string(ns).c_str(), tagName.data());
+ DOMNodeList *nodeList = element->getElementsByTagNameNS(xml::string(ns.data()).c_str(), tagName.data());
if(nodeList->getLength() != 1)
- THROW("Could not find '%s' node which is in '%s' namespace in signature XML.",
- xml::transcode(tagName.data()).data(), ns.c_str());
- if(canonicalizationMethod.empty())
- canonicalizationMethod = signature->signedInfo().canonicalizationMethod().algorithm();
+ THROW("Could not find '%s' node which is in '%.*s' namespace in signature XML.",
+ xml::transcode(tagName.data()).c_str(), int(ns.size()), ns.data());
SecureDOMParser::calcDigestOnNode(calc, canonicalizationMethod, nodeList->item(0));
}
catch(const Exception& e)
diff --git a/src/SignatureXAdES_B.h b/src/SignatureXAdES_B.h
index a3b72c95a..77f10e552 100644
--- a/src/SignatureXAdES_B.h
+++ b/src/SignatureXAdES_B.h
@@ -91,7 +91,7 @@ namespace digidoc
std::vector signerRoles() const override;
std::string addReference(const std::string& uri, const std::string& digestUri,
- const std::vector &digestValue, const std::string& type = {});
+ const std::vector &digestValue, const std::string& type = {}, const std::string &canon = {});
void addDataObjectFormat(const std::string& uri, const std::string& mime);
std::shared_ptr signatures;
@@ -100,8 +100,8 @@ namespace digidoc
std::vector getSignatureValue() const;
xades::QualifyingPropertiesType& qualifyingProperties() const;
xades::SignedSignaturePropertiesType& getSignedSignatureProperties() const;
- void calcDigestOnNode(Digest* calc, const std::string& ns,
- std::u16string_view tagName, std::string_view canonicalizationMethod = {}) const;
+ void calcDigestOnNode(Digest* calc, std::string_view ns,
+ std::u16string_view tagName, std::string_view canonicalizationMethod) const;
static void checkCertID(const xades::CertIDType &certID, const X509Cert &cert);
static void checkDigest(const xades::DigestAlgAndValueType &digest, const std::vector &data);
diff --git a/src/xml/SecureDOMParser.cpp b/src/xml/SecureDOMParser.cpp
index 785d8eba6..7733cdfd2 100644
--- a/src/xml/SecureDOMParser.cpp
+++ b/src/xml/SecureDOMParser.cpp
@@ -91,6 +91,14 @@ SecureDOMParser::SecureDOMParser(const string &schema_location, bool dont_valida
void SecureDOMParser::calcDigestOnNode(Digest *calc,
string_view algorithmType, DOMNode *node)
{
+ /*
+ * https://www.w3.org/TR/xmldsig-core1/
+ * The Reference Processing Model (section 4.4.3.2 The Reference Processing Model) requires use of
+ * Canonical XML 1.0 [XML-C14N] as default processing behavior when a transformation is expecting an octet-stream.
+ */
+ if(algorithmType.empty())
+ algorithmType = URI_ID_C14N_NOC;
+
XSECC14n20010315 c14n(node->getOwnerDocument(), node);
c14n.setCommentsProcessing(false);
c14n.setUseNamespaceStack(true);
@@ -113,7 +121,7 @@ void SecureDOMParser::calcDigestOnNode(Digest *calc,
c14n.setInclusive11();
c14n.setCommentsProcessing(true);
} else {
- THROW("Unsupported canonicalization method '%s'", algorithmType.data());
+ THROW("Unsupported canonicalization method '%.*s'", int(algorithmType.size()), algorithmType.data());
}
array buffer{};