Skip to content

Commit d499a3b

Browse files
metsmakristelmerilain
authored andcommitted
Update OpenSSL 3.5.2 and libxml2 to 2.14.5 and patch xmlsec1
IB-8570, IB-8565, IB-8566 Signed-off-by: Raul Metsma <[email protected]>
1 parent 9491bcc commit d499a3b

File tree

12 files changed

+403
-58
lines changed

12 files changed

+403
-58
lines changed

.github/workflows/build.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,24 @@ jobs:
8282
steps:
8383
- name: Checkout
8484
uses: actions/checkout@v4
85+
- name: Expose Android NDK env
86+
shell: bash
87+
run: |
88+
echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
89+
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
90+
- name: Cache vcpkg
91+
uses: actions/cache@v4
92+
with:
93+
path: ${{ github.workspace }}/vcpkg_cache
94+
key: vcpkg-${{ matrix.target }}-${{ hashFiles('.github/workflows/*', 'vcpkg.json', 'vcpkg-ports/**', 'CMakeLists.txt', '**/CMakeLists.txt', 'CMakePresets.json') }}
8595
- name: Prepare vcpkg
8696
uses: lukka/run-vcpkg@v11
8797
with:
88-
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
98+
vcpkgGitCommitId: 98e7cd3a7ba579efc543f8854af800d033031eae
8999
vcpkgJsonGlob: ./vcpkg.json
90100
runVcpkgInstall: true
91101
env:
102+
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
92103
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
93104
- name: Build
94105
run: |
@@ -179,14 +190,20 @@ jobs:
179190
steps:
180191
- name: Checkout
181192
uses: actions/checkout@v4
193+
- name: Cache vcpkg
194+
uses: actions/cache@v4
195+
with:
196+
path: ${{ github.workspace }}/vcpkg_cache
197+
key: vcpkg-${{ matrix.toolset }}-${{ matrix.platform }}-${{ hashFiles('.github/workflows/*', 'vcpkg.json', 'vcpkg-ports/**', 'CMakeLists.txt', '**/CMakeLists.txt', 'CMakePresets.json') }}
182198
- name: Prepare vcpkg
183199
uses: lukka/run-vcpkg@v11
184200
with:
185-
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
201+
vcpkgGitCommitId: 98e7cd3a7ba579efc543f8854af800d033031eae
186202
vcpkgJsonGlob: ./vcpkg.json
187203
runVcpkgInstall: true
188204
runVcpkgFormatString: "[`install`, `--recurse`, `--clean-after-build`, `--x-install-root`, `$[env.VCPKG_INSTALLED_DIR]`, `--triplet`, `$[env.VCPKG_DEFAULT_TRIPLET]`, `--x-feature`, `tests`]"
189205
env:
206+
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
190207
VCPKG_DEFAULT_TRIPLET: ${{ matrix.platform }}-windows
191208
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/vcpkg_installed_${{ matrix.platform }}
192209
- name: Install dependencies

examples/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
mavenCentral()
66
}
77
dependencies {
8-
classpath 'com.android.tools.build:gradle:8.12.0'
8+
classpath 'com.android.tools.build:gradle:8.12.2'
99
}
1010
}
1111

examples/ios/libdigidocpp/Info.plist

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
<key>CFBundleDocumentTypes</key>
66
<array>
77
<dict>
8-
<key>CFBundleTypeIconFiles</key>
9-
<array/>
108
<key>CFBundleTypeName</key>
119
<string>DigiDoc signed document</string>
1210
<key>CFBundleTypeRole</key>

libdigidocpp.wxs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@
8080
<?endif?>
8181
</ComponentGroup>
8282

83-
<ComponentGroup Id="DependenciesDev" Source="$(var.vcpkg)\debug\bin">
84-
<File Name="zlibd1.dll" />
85-
</ComponentGroup>
86-
8783
<ComponentGroup Id="LibrariesDev" Source="$(var.libdigidocpp)">
8884
<Files Include="*.pdb" />
8985
<File Name="digidocpp.lib" />
@@ -105,7 +101,7 @@
105101
<Files Directory="INSTALLFOLDER" Subdirectory="schema" Include="$(var.libdigidocpp)\etc\digidocpp\schema\*.xsd" />
106102
<Feature Id="InstallDevel" Level="1" Title="Development">
107103
<ComponentGroupRef Id="RuntimeDev" />
108-
<ComponentGroupRef Id="DependenciesDev" />
104+
<File Directory="INSTALLFOLDER" Source="$(var.vcpkg)\debug\bin\zlibd1.dll" />
109105
<ComponentGroupRef Id="LibrariesDev" />
110106
<Files Directory="INSTALLFOLDER" Subdirectory="include" Include="$(var.libdigidocpp)\include\**" />
111107
<Files Directory="INSTALLFOLDER" Subdirectory="cmake\libdigidocpp" Include="$(var.libdigidocpp)\cmake\libdigidocpp\**" />

prepare_osx_build_environment.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22
set -e
33

4-
OPENSSL_DIR=openssl-3.5.1
4+
OPENSSL_DIR=openssl-3.5.2
55
XMLSEC_DIR=xmlsec1-1.3.7
66
ARGS="$@"
77

@@ -59,6 +59,7 @@ function xmlsec {
5959
cd ${XMLSEC_DIR}
6060
patch -Np1 -i ../vcpkg-ports/xmlsec/xmlsec1-1.3.5.legacy.patch
6161
patch -Np1 -i ../vcpkg-ports/xmlsec/xmlsec1-1.3.7.rsapss.patch
62+
patch -Np1 -i ../vcpkg-ports/xmlsec/xmlsec1-1.3.7.ecdsa-sig.patch
6263
case "${ARGS}" in
6364
*iphone*) CONFIGURE="--host=aarch64-apple-darwin --enable-static --disable-shared --without-libxslt" ;;
6465
*) CONFIGURE="--disable-static --enable-shared" ;;

src/XMLDocument.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <xmlsec/xmltree.h>
3131
#include <xmlsec/xmldsig.h>
3232
#include <xmlsec/crypto.h>
33+
#include <xmlsec/parser.h>
3334

3435
#include <openssl/evp.h>
3536

@@ -45,7 +46,7 @@ static std::vector<unsigned char> from_base64(std::string_view data)
4546
std::vector<unsigned char> result(EVP_DECODE_LENGTH(data.size()), 0);
4647
size_t dataPos = 0;
4748
int size = 0;
48-
auto ctx = make_unique_ptr(EVP_ENCODE_CTX_new(), EVP_ENCODE_CTX_free);
49+
auto ctx = make_unique_ptr<EVP_ENCODE_CTX_free>(EVP_ENCODE_CTX_new());
4950
EVP_DecodeInit(ctx.get());
5051

5152
for(auto pos = data.find_first_of(whitespace);
@@ -71,7 +72,7 @@ static std::vector<unsigned char> from_base64(std::string_view data)
7172
static std::string to_base64(const std::vector<unsigned char> &data)
7273
{
7374
std::string result(EVP_ENCODE_LENGTH(data.size()), 0);
74-
auto ctx = make_unique_ptr(EVP_ENCODE_CTX_new(), EVP_ENCODE_CTX_free);
75+
auto ctx = make_unique_ptr<EVP_ENCODE_CTX_free>(EVP_ENCODE_CTX_new());
7576
EVP_EncodeInit(ctx.get());
7677
int size{};
7778
if(EVP_EncodeUpdate(ctx.get(), (unsigned char*)result.data(), &size, data.data(), int(data.size())) < 1)
@@ -305,19 +306,27 @@ struct XMLDocument: public unique_free_t<xmlDoc>, public XMLNode
305306

306307
static XMLDocument openStream(std::istream &is, const XMLName &name = {}, bool hugeFile = false)
307308
{
308-
auto ctxt = make_unique_ptr(xmlCreateIOParserCtxt(nullptr, nullptr, [](void *context, char *buffer, int len) -> int {
309+
auto ctxt = make_unique_ptr<xmlFreeParserCtxt>(xmlCreateIOParserCtxt(nullptr, nullptr, [](void *context, char *buffer, int len) -> int {
309310
auto *is = static_cast<std::istream *>(context);
310311
is->read(buffer, len);
311312
return is->good() || is->eof() ? int(is->gcount()) : -1;
312-
}, nullptr, &is, XML_CHAR_ENCODING_NONE), xmlFreeParserCtxt);
313-
ctxt->linenumbers = 1;
313+
}, nullptr, &is, XML_CHAR_ENCODING_NONE));
314+
#if VERSION_CHECK(XMLSEC_VERSION_MAJOR, XMLSEC_VERSION_MINOR, XMLSEC_VERSION_SUBMINOR) >= VERSION_CHECK(1, 3, 0)
315+
ctxt->options |= xmlSecParserGetDefaultOptions();
316+
#else
314317
ctxt->options |= XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_DTDATTR|XML_PARSE_NONET;
318+
#endif
315319
ctxt->loadsubset |= XML_DETECT_IDS|XML_COMPLETE_ATTRS;
316320
if(hugeFile)
317321
ctxt->options |= XML_PARSE_HUGE;
318322
auto result = xmlParseDocument(ctxt.get());
319323
if(result != 0 || !ctxt->wellFormed)
320-
THROW("%s", ctxt->lastError.message);
324+
{
325+
if(const xmlError *lastError = xmlCtxtGetLastError(ctxt.get()))
326+
THROW("%s", lastError->message);
327+
else
328+
THROW("Failed to parse XML document from stream");
329+
}
321330
return {ctxt->myDoc, name};
322331
}
323332

@@ -358,11 +367,11 @@ struct XMLDocument: public unique_free_t<xmlDoc>, public XMLNode
358367
}
359368
else if(!algo.empty())
360369
THROW("Unsupported canonicalization method '%.*s'", int(algo.size()), algo.data());
361-
auto buf = make_unique_ptr(xmlOutputBufferCreateIO([](void *context, const char *buffer, int len) {
370+
auto buf = make_unique_ptr<xmlOutputBufferClose>(xmlOutputBufferCreateIO([](void *context, const char *buffer, int len) {
362371
auto *digest = static_cast<Digest *>(context);
363372
digest->update(pcxmlChar(buffer), size_t(len));
364373
return len;
365-
}, nullptr, const_cast<Digest*>(&digest), nullptr), xmlOutputBufferClose);
374+
}, nullptr, const_cast<Digest*>(&digest), nullptr));
366375
int size = xmlC14NExecute(get(), [](void *root, xmlNodePtr node, xmlNodePtr parent) constexpr noexcept {
367376
if(root == node)
368377
return 1;
@@ -396,14 +405,14 @@ struct XMLDocument: public unique_free_t<xmlDoc>, public XMLNode
396405

397406
void validateSchema(const std::string &schemaPath) const
398407
{
399-
auto parser = make_unique_ptr(xmlSchemaNewParserCtxt(schemaPath.c_str()), xmlSchemaFreeParserCtxt);
408+
auto parser = make_unique_ptr<xmlSchemaFreeParserCtxt>(xmlSchemaNewParserCtxt(schemaPath.c_str()));
400409
if(!parser)
401410
THROW("Failed to create schema parser context %s", schemaPath.c_str());
402411
xmlSchemaSetParserErrors(parser.get(), schemaValidationError, schemaValidationWarning, nullptr);
403-
auto schema = make_unique_ptr(xmlSchemaParse(parser.get()), xmlSchemaFree);
412+
auto schema = make_unique_ptr<xmlSchemaFree>(xmlSchemaParse(parser.get()));
404413
if(!schema)
405414
THROW("Failed to parse schema %s", schemaPath.c_str());
406-
auto validate = make_unique_ptr(xmlSchemaNewValidCtxt(schema.get()), xmlSchemaFreeValidCtxt);
415+
auto validate = make_unique_ptr<xmlSchemaFreeValidCtxt>(xmlSchemaNewValidCtxt(schema.get()));
407416
if(!validate)
408417
THROW("Failed to create schema validation context %s", schemaPath.c_str());
409418
Exception e(EXCEPTION_PARAMS("Failed to XML with schema"));
@@ -414,12 +423,12 @@ struct XMLDocument: public unique_free_t<xmlDoc>, public XMLNode
414423

415424
static bool verifySignature(XMLNode signature, [[maybe_unused]] Exception *e = {}) noexcept
416425
{
417-
auto mngr = make_unique_ptr(xmlSecKeysMngrCreate(), xmlSecKeysMngrDestroy);
426+
auto mngr = make_unique_ptr<xmlSecKeysMngrDestroy>(xmlSecKeysMngrCreate());
418427
if(!mngr)
419428
return false;
420429
if(xmlSecCryptoAppDefaultKeysMngrInit(mngr.get()) < 0)
421430
return false;
422-
auto ctx = make_unique_ptr(xmlSecDSigCtxCreate(mngr.get()), xmlSecDSigCtxDestroy);
431+
auto ctx = make_unique_ptr<xmlSecDSigCtxDestroy>(xmlSecDSigCtxCreate(mngr.get()));
423432
if(!ctx)
424433
return false;
425434
ctx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;

src/crypto/X509Cert.cpp

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@
2929
using namespace digidoc;
3030
using namespace std;
3131

32+
// RFC 3739: NameRegistrationAuthorities is SEQUENCE OF GeneralName
33+
using NameRegistrationAuthorities = STACK_OF(GENERAL_NAME);
34+
3235
/**
3336
* SemanticsInformation ::= SEQUENCE {
3437
* semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
3538
* nameRegistrationAuthorities NameRegistrationAuthorities OPTIONAL
3639
* }
3740
*/
38-
using SemanticsInformation = struct SemanticsInformation_st {
41+
struct SemanticsInformation {
3942
ASN1_OBJECT *semanticsIdentifier;
40-
//NameRegistrationAuthorities nameRegistrationAuthorities
43+
NameRegistrationAuthorities *nameRegistrationAuthorities;
4144
};
4245
DECLARE_ASN1_FUNCTIONS(SemanticsInformation)
4346

@@ -52,7 +55,7 @@ DECLARE_ASN1_FUNCTIONS(QcType)
5255
* statementId OBJECT IDENTIFIER,
5356
* statementInfo ANY DEFINED BY statementId OPTIONAL}
5457
*/
55-
using QCStatement = struct QCStatement_st {
58+
struct QCStatement {
5659
ASN1_OBJECT *statementId;
5760
#ifndef TEMPLATE
5861
ASN1_TYPE *statementInfo;
@@ -297,8 +300,7 @@ string X509Cert::serial() const
297300
return {};
298301
if(auto bn = make_unique_ptr<BN_free>(ASN1_INTEGER_to_BN(X509_get_serialNumber(cert.get()), nullptr)))
299302
{
300-
auto openssl_free = [](char *data) { OPENSSL_free(data); };
301-
if(auto str = unique_ptr<char,decltype(openssl_free)>(BN_bn2dec(bn.get()), openssl_free))
303+
if(auto str = make_unique_ptr(BN_bn2dec(bn.get()), [](char *data) { OPENSSL_free(data); }))
302304
return str.get();
303305
}
304306
return {};
@@ -316,15 +318,19 @@ string X509Cert::issuerName(const string &obj) const
316318
return toString<X509_get_issuer_name>(obj);
317319
}
318320

321+
template<auto Func>
322+
constexpr auto X509Cert::extension(int nid) const noexcept
323+
{
324+
return make_unique_cast<Func>(cert ? X509_get_ext_d2i(cert.get(), nid, nullptr, nullptr) : nullptr);
325+
}
326+
319327
/**
320328
* Returns current certificate key usage bits
321329
*/
322330
vector<X509Cert::KeyUsage> X509Cert::keyUsage() const
323331
{
324332
vector<KeyUsage> usage;
325-
if(!cert)
326-
return usage;
327-
auto keyusage = make_unique_cast<ASN1_BIT_STRING_free>(X509_get_ext_d2i(cert.get(), NID_key_usage, nullptr, nullptr));
333+
auto keyusage = extension<ASN1_BIT_STRING_free>(NID_key_usage);
328334
if(!keyusage)
329335
return usage;
330336

@@ -342,9 +348,7 @@ vector<X509Cert::KeyUsage> X509Cert::keyUsage() const
342348
vector<string> X509Cert::certificatePolicies() const
343349
{
344350
vector<string> pol;
345-
if(!cert)
346-
return pol;
347-
auto cp = make_unique_cast<CERTIFICATEPOLICIES_free>(X509_get_ext_d2i(cert.get(), NID_certificate_policies, nullptr, nullptr));
351+
auto cp = extension<CERTIFICATEPOLICIES_free>(NID_certificate_policies);
348352
if(!cp)
349353
return pol;
350354
for(int i = 0; i < sk_POLICYINFO_num(cp.get()); ++i)
@@ -375,30 +379,22 @@ vector<string> X509Cert::qcStatements() const
375379
if(oid == QC_SYNTAX2)
376380
{
377381
#ifndef TEMPLATE
378-
if(!s->statementInfo)
379-
continue;
380-
auto si = make_unique_cast<SemanticsInformation_free>(ASN1_item_unpack(s->statementInfo->value.sequence, ASN1_ITEM_rptr(SemanticsInformation)));
381-
if(!si)
382-
continue;
383-
result.push_back(toOID(si->semanticsIdentifier));
382+
if(auto si = make_unique_cast<SemanticsInformation_free>(ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SemanticsInformation), s->statementInfo)))
383+
result.push_back(toOID(si->semanticsIdentifier));
384384
#else
385385
result.push_back(toOID(s->statementInfo.semanticsInformation->semanticsIdentifier));
386386
#endif
387387
}
388388
else if(oid == QC_QCT)
389389
{
390390
#ifndef TEMPLATE
391-
if(!s->statementInfo)
392-
continue;
393-
auto qct = make_unique_cast<QcType_free>(ASN1_item_unpack(s->statementInfo->value.sequence, ASN1_ITEM_rptr(QcType)));
391+
auto qct = make_unique_cast<QcType_free>(ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(QcType), s->statementInfo));
394392
if(!qct)
395393
continue;
396394
for(int j = 0; j < sk_ASN1_OBJECT_num(qct.get()); ++j)
397-
{
398395
result.push_back(toOID(sk_ASN1_OBJECT_value(qct.get(), j)));
399396
#else
400397
#endif
401-
}
402398
}
403399
else
404400
result.push_back(std::move(oid));
@@ -487,9 +483,7 @@ X509* X509Cert::handle() const
487483
*/
488484
bool X509Cert::isCA() const
489485
{
490-
if(!cert)
491-
return false;
492-
auto cons = make_unique_cast<BASIC_CONSTRAINTS_free>(X509_get_ext_d2i(cert.get(), NID_basic_constraints, nullptr, nullptr));
486+
auto cons = extension<BASIC_CONSTRAINTS_free>(NID_basic_constraints);
493487
return cons && cons->ca > 0;
494488
}
495489

@@ -532,19 +526,19 @@ X509Cert& X509Cert::operator =(X509Cert &&other) noexcept = default;
532526
*/
533527
bool X509Cert::operator ==(X509 *other) const
534528
{
535-
return operator==(X509Cert(other));
529+
if(cert.get() == other)
530+
return true;
531+
if(!cert || !other)
532+
return false;
533+
return X509_cmp(cert.get(), other) == 0;
536534
}
537535

538536
/**
539537
* Equal operator to compare two objects
540538
*/
541539
bool X509Cert::operator ==(const X509Cert &other) const
542540
{
543-
if(cert == other.cert)
544-
return true;
545-
if(!cert || !other.cert)
546-
return false;
547-
return X509_cmp(cert.get(), other.cert.get()) == 0;
541+
return operator==(other.cert.get());
548542
}
549543

550544
/**
@@ -556,8 +550,8 @@ bool X509Cert::operator !=(const X509Cert &other) const
556550
}
557551

558552
ASN1_SEQUENCE(SemanticsInformation) = {
559-
ASN1_OPT(SemanticsInformation, semanticsIdentifier, ASN1_OBJECT)
560-
//ASN1_OPT(SemanticsInformation, nameRegistrationAuthorities, NameRegistrationAuthorities)
553+
ASN1_OPT(SemanticsInformation, semanticsIdentifier, ASN1_OBJECT),
554+
ASN1_SEQUENCE_OF_OPT(SemanticsInformation, nameRegistrationAuthorities, GENERAL_NAME)
561555
} ASN1_SEQUENCE_END(SemanticsInformation)
562556
IMPLEMENT_ASN1_FUNCTIONS(SemanticsInformation)
563557

src/crypto/X509Cert.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ namespace digidoc
111111
static std::string toOID(ASN1_OBJECT *obj);
112112
template<auto Func>
113113
std::string toString(const std::string &obj) const;
114+
template<auto Func>
115+
constexpr auto extension(int nid) const noexcept;
114116
std::shared_ptr<X509> cert;
115117
};
116118
}

vcpkg-ports/xmlsec/portfile.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ vcpkg_from_github(
1111
pkgconfig_fixes.patch
1212
xmlsec1-1.3.5.legacy.patch
1313
xmlsec1-1.3.7.rsapss.patch
14+
xmlsec1-1.3.7.ecdsa-sig.patch
1415
)
1516

1617
file(COPY "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" DESTINATION "${SOURCE_PATH}")

vcpkg-ports/xmlsec/vcpkg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "xmlsec",
33
"version": "1.3.7",
4+
"port-version": 1,
45
"description": "XML Security Library is a C library based on LibXML2. The library supports major XML security standards.",
56
"homepage": "https://www.aleksey.com/xmlsec/",
67
"license": "X11 AND MPL-1.1",

0 commit comments

Comments
 (0)