From 8d399d574abe4a552b4bf22b18eacd6d90dac13b Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Fri, 24 Jul 2026 15:45:06 +0200 Subject: [PATCH] OpenSSL version 4 compatibility. Main changes: - ASN1_STRING and subclasses are now opaque: use accessors. - Engines have been replaced by providers: use default provider where needed. - Some function results have been constified: constify our storage too. Fixes #724 --- lib/asn1int.cpp | 2 +- lib/asn1time.cpp | 17 +++++++---- lib/pkcs11.cpp | 65 +++++++++++++++++++++++++----------------- lib/pki_pkcs12.cpp | 2 +- lib/pki_scard.cpp | 7 +++-- lib/pki_x509.cpp | 2 +- lib/pki_x509req.cpp | 4 ++- lib/x509name.cpp | 15 ++++++---- lib/x509v3ext.cpp | 47 +++++++++++++++--------------- lib/x509v3ext.h | 2 +- widgets/CertDetail.cpp | 4 +-- 11 files changed, 96 insertions(+), 71 deletions(-) diff --git a/lib/asn1int.cpp b/lib/asn1int.cpp index 300b44ab..2c1b65a0 100644 --- a/lib/asn1int.cpp +++ b/lib/asn1int.cpp @@ -67,7 +67,7 @@ a1int &a1int::set(long l) QString a1int::toQString(int dec) const { QString r; - if (in->length == 0) { + if (ASN1_STRING_length(in.get()) == 0) { return r; } QSharedPointer bn(ASN1_INTEGER_to_BN(get0(), NULL), BN_free); diff --git a/lib/asn1time.cpp b/lib/asn1time.cpp index 71b7d0f7..9c151c24 100644 --- a/lib/asn1time.cpp +++ b/lib/asn1time.cpp @@ -50,7 +50,8 @@ int a1time::from_asn1(const ASN1_TIME *a) gt = ASN1_TIME_to_generalizedtime((ASN1_TIME*)a, NULL); if (!gt) return -1; - t = QString::fromLatin1((char*)gt->data, gt->length); + t = QString::fromLatin1((char*)ASN1_STRING_get0_data(gt), + ASN1_STRING_length(gt)); ASN1_GENERALIZEDTIME_free(gt); return fromPlain(t); } @@ -68,11 +69,15 @@ int a1time::fromPlain(const QString &plain) int a1time::set_asn1(const QString &str, int type) const { - if (!atime) - atime = ASN1_TIME_new(); - if (!atime) - return -1; - atime->type = type; + if (atime && ASN1_STRING_type(atime) != type) { + ASN1_STRING_free(atime); + atime = NULL; + } + if (!atime) { + atime = ASN1_STRING_type_new(type); + if (!atime) + return -1; + } if (ASN1_STRING_set(atime, str.toLatin1(), str.length())) return -1; return 0; diff --git a/lib/pkcs11.cpp b/lib/pkcs11.cpp index c4d4c9bb..b9f27d8c 100644 --- a/lib/pkcs11.cpp +++ b/lib/pkcs11.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -650,29 +649,6 @@ int pkcs11::encrypt(int flen, const unsigned char *from, return size; } -#if not defined OPENSSL_NO_EC and defined EVP_PKEY_ED25519 -// Shared between libressl and openssl -static int eng_idx = -1; -static int eng_finish(ENGINE *e) -{ - pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(e, eng_idx); - delete p11; - ENGINE_set_ex_data(e, eng_idx, NULL); - return 1; -} - -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) -static int eng_pmeth_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) -#else -static int eng_pmeth_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) -#endif -{ - void *p = EVP_PKEY_CTX_get_app_data((EVP_PKEY_CTX *)src); - EVP_PKEY_CTX_set_app_data(dst, p); - return 1; -} -#endif - static int rsa_privdata_free(RSA *rsa) { pkcs11 *priv = (pkcs11*)RSA_get_app_data(rsa); @@ -830,10 +806,35 @@ static EC_KEY_METHOD *setup_ec_key_meth() ec_set_private_proc, ec_set_public_proc); return ec_key_meth; } -#ifdef EVP_PKEY_ED25519 + + +#if defined(EVP_PKEY_ED25519) && OPENSSL_VERSION_NUMBER < 0x40000000L + +#include static EVP_PKEY_METHOD *p11_eddsa_method; +// Shared between libressl and openssl +static int eng_idx = -1; +static int eng_finish(ENGINE *e) +{ + pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(e, eng_idx); + delete p11; + ENGINE_set_ex_data(e, eng_idx, NULL); + return 1; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) +static int eng_pmeth_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) +#else +static int eng_pmeth_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +#endif +{ + void *p = EVP_PKEY_CTX_get_app_data((EVP_PKEY_CTX *)src); + EVP_PKEY_CTX_set_app_data(dst, p); + return 1; +} + static int eddsa_eng_meths(ENGINE *e, EVP_PKEY_METHOD **m, const int **nids, int nid) { static const int my_nids[] = {EVP_PKEY_ED25519 }; @@ -904,7 +905,7 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) #ifndef OPENSSL_NO_EC static EC_KEY_METHOD *ec_key_meth = NULL; EC_KEY *ec; -#ifdef EVP_PKEY_ED25519 +#if defined(EVP_PKEY_ED25519) && OPENSSL_VERSION_NUMBER < 0x40000000L static ENGINE *e = NULL; if (!e) { @@ -991,6 +992,7 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) #ifdef EVP_PKEY_ED25519 case EVP_PKEY_ED25519: size_t len; +#if OPENSSL_VERSION_NUMBER < 0x40000000L if (ENGINE_get_ex_data(e, eng_idx)) qWarning() << "We forgot to free the previous Card key."; ENGINE_set_ex_data(e, eng_idx, this); @@ -1003,6 +1005,17 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) openssl_error(); OPENSSL_free(pubkey); //EVP_PKEY_set1_engine(evp, e); +#else + p11obj = obj; + EVP_PKEY_get_raw_public_key(pub, NULL, &len); + unsigned char *pubkey = (unsigned char *)OPENSSL_malloc(len); + Q_CHECK_PTR(pubkey); + EVP_PKEY_get_raw_public_key(pub, pubkey, &len); + evp = EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX_get0_global_default(), + "ED25519", NULL, pubkey, len); + openssl_error(); + OPENSSL_free(pubkey); +#endif break; #endif #endif diff --git a/lib/pki_pkcs12.cpp b/lib/pki_pkcs12.cpp index f0599dce..fe00875e 100644 --- a/lib/pki_pkcs12.cpp +++ b/lib/pki_pkcs12.cpp @@ -85,7 +85,7 @@ pki_pkcs12::pki_pkcs12(const QString &fname) } pki_ign_openssl_error(); if (mycert) { - unsigned char *str = X509_alias_get0(mycert, NULL); + const unsigned char *str = X509_alias_get0(mycert, NULL); if (str) alias = QString::fromUtf8((const char *)str); alias = QString::fromUtf8(alias.toLatin1()); diff --git a/lib/pki_scard.cpp b/lib/pki_scard.cpp index 0034cc68..71b24e97 100644 --- a/lib/pki_scard.cpp +++ b/lib/pki_scard.cpp @@ -187,7 +187,8 @@ EVP_PKEY *pki_scard::load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const d2i_bytearray(D2I_VOID(d2i_ASN1_OCTET_STRING), ba); pki_openssl_error(); - BIGNUM *bn = BN_bin2bn(os->data, os->length, NULL); + BIGNUM *bn = BN_bin2bn(ASN1_STRING_get0_data(os), + ASN1_STRING_length(os), NULL); pki_openssl_error(); EC_POINT *point = EC_POINT_bn2point(group, bn, NULL, NULL); @@ -215,8 +216,8 @@ EVP_PKEY *pki_scard::load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const d2i_bytearray(D2I_VOID(d2i_ASN1_OCTET_STRING), ba); pki_openssl_error(); pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, - (const uint8_t *)os->data, - os->length); + (const uint8_t *)ASN1_STRING_get0_data(os), + ASN1_STRING_length(os)); pki_openssl_error(); ASN1_OCTET_STRING_free(os); pki_openssl_error(); diff --git a/lib/pki_x509.cpp b/lib/pki_x509.cpp index 35baedfb..1db99308 100644 --- a/lib/pki_x509.cpp +++ b/lib/pki_x509.cpp @@ -836,7 +836,7 @@ pki_key *pki_x509::getPubKey() const bool pki_x509::compareNameAndKey(pki_x509 *other) { int r; - X509_NAME *s1, *s2; + const X509_NAME *s1, *s2; EVP_PKEY *pub1, *pub2; if (!cert || !other->cert) diff --git a/lib/pki_x509req.cpp b/lib/pki_x509req.cpp index e51ed341..aef85851 100644 --- a/lib/pki_x509req.cpp +++ b/lib/pki_x509req.cpp @@ -204,7 +204,9 @@ void pki_x509req::addAttribute(int nid, QString content) return; ASN1_STRING *a = QStringToAsn1(content, nid); - X509_REQ_add1_attr_by_NID(request, nid, a->type, a->data, a->length); + X509_REQ_add1_attr_by_NID(request, nid, ASN1_STRING_type(a), + ASN1_STRING_get0_data(a), + ASN1_STRING_length(a)); ASN1_STRING_free(a); openssl_error_msg(QString("'%1' (%2)").arg(content).arg(OBJ_nid2ln(nid))); } diff --git a/lib/x509name.cpp b/lib/x509name.cpp index d4fe8afc..62e82d2d 100644 --- a/lib/x509name.cpp +++ b/lib/x509name.cpp @@ -89,7 +89,7 @@ QString x509name::getMostPopular() const QString x509name::getEntry(int i) const { QString ret; - ASN1_STRING *d; + const ASN1_STRING *d; if ( i<0 || i>entryCount() ) return ret; @@ -102,7 +102,7 @@ QString x509name::getEntry(int i) const QString x509name::getEntryTag(int i) const { QString s = QObject::tr("Invalid"); - ASN1_STRING *d; + const ASN1_STRING *d; if (i<0 || i>=entryCount()) i = entryCount() - 1; @@ -111,7 +111,7 @@ QString x509name::getEntryTag(int i) const if (!d) return s; - s = ASN1_tag2str(d->type); + s = ASN1_tag2str(ASN1_STRING_type(d)); return s; } @@ -154,13 +154,13 @@ QStringList x509name::entryList(int i) const int x509name::nid(int i) const { - X509_NAME_ENTRY *ne = X509_NAME_get_entry(get0(), i); + const X509_NAME_ENTRY *ne = X509_NAME_get_entry(get0(), i); return ne ? OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)) : NID_undef; } QString x509name::getOid(int i) const { - X509_NAME_ENTRY *ne = X509_NAME_get_entry(_get(), i); + const X509_NAME_ENTRY *ne = X509_NAME_get_entry(_get(), i); return ne ? OBJ_obj2QString(X509_NAME_ENTRY_get_object(ne), 1) : QString(); } @@ -258,7 +258,10 @@ void x509name::addEntryByNid(int nid, const QString &entry) if (entry.isEmpty()) return; ASN1_STRING *a = QStringToAsn1(entry.simplified(), nid); - X509_NAME_add_entry_by_NID(_get(), nid, a->type, a->data, a->length, -1, 0); + X509_NAME_add_entry_by_NID(_get(), nid, + ASN1_STRING_type(a), + ASN1_STRING_get0_data(a), + ASN1_STRING_length(a), -1, 0); ASN1_STRING_free(a); openssl_error_msg(QString("'%1' (%2)").arg(entry).arg(OBJ_nid2ln(nid))); } diff --git a/lib/x509v3ext.cpp b/lib/x509v3ext.cpp index a4aaa84c..9e83b7c6 100644 --- a/lib/x509v3ext.cpp +++ b/lib/x509v3ext.cpp @@ -49,8 +49,8 @@ x509v3ext::~x509v3ext() x509v3ext &x509v3ext::set(const X509_EXTENSION *n) { if (n) { - ASN1_OCTET_STRING *str = X509_EXTENSION_get_data((X509_EXTENSION *)n); - if (!str || !str->length) + const ASN1_OCTET_STRING *str = X509_EXTENSION_get_data((X509_EXTENSION *)n); + if (!str || !ASN1_STRING_length(str)) n = nullptr; } if (ext != nullptr) @@ -116,7 +116,7 @@ x509v3ext &x509v3ext::create_ia5(int nid, const QString &et, X509V3_CTX *ctx) const ASN1_OBJECT *x509v3ext::object() const { - ASN1_OBJECT *obj = nullptr; + const ASN1_OBJECT *obj = nullptr; if (ext) { obj = X509_EXTENSION_get_object(ext); ign_openssl_error(); @@ -166,9 +166,9 @@ int x509v3ext::getCritical() const return ext ? X509_EXTENSION_get_critical(ext) : 0; } -ASN1_OCTET_STRING *x509v3ext::getData() const +const ASN1_OCTET_STRING *x509v3ext::getData() const { - return ext ? X509_EXTENSION_get_data(ext) : nullptr;; + return ext ? X509_EXTENSION_get_data(ext) : nullptr; } QString x509v3ext::getValue() const @@ -318,7 +318,7 @@ static QString ipv6_from_binary(const unsigned char *p) static bool genName2conf(GENERAL_NAME *gen, QString tag, QString *single, QString *sect) { - unsigned char *p; + const unsigned char *p; QString ret; switch (gen->type) { @@ -335,22 +335,23 @@ genName2conf(GENERAL_NAME *gen, QString tag, QString *single, QString *sect) return true; } case GEN_IPADD: - p = gen->d.ip->data; - if (gen->d.ip->length == 4) { + p = ASN1_STRING_get0_data(gen->d.ip); + if (ASN1_STRING_length(gen->d.ip) == 4) { *single = QString("IP:%1.%2.%3.%4"). arg(p[0]).arg(p[1]).arg(p[2]).arg(p[3]); return true; - } else if(gen->d.ip->length == 8) { + } else if(ASN1_STRING_length(gen->d.ip) == 8) { *single = QString("IP:%1.%2.%3.%4/%5.%6.%7.%8"). arg(p[0]).arg(p[1]).arg(p[2]).arg(p[3]). arg(p[4]).arg(p[5]).arg(p[6]).arg(p[7]); return true; - } else if(gen->d.ip->length == 16) { - *single = "IP:" + ipv6_from_binary(gen->d.ip->data); + } else if(ASN1_STRING_length(gen->d.ip) == 16) { + *single = "IP:" + ipv6_from_binary(ASN1_STRING_get0_data(gen->d.ip)); return true; - } else if(gen->d.ip->length == 32) { - *single = "IP:" + ipv6_from_binary(gen->d.ip->data) + - "/" + ipv6_from_binary(gen->d.ip->data +16); + } else if(ASN1_STRING_length(gen->d.ip) == 32) { + *single = "IP:" + + ipv6_from_binary(ASN1_STRING_get0_data(gen->d.ip)) + + "/" + ipv6_from_binary(ASN1_STRING_get0_data(gen->d.ip) + 16); return true; } return false; @@ -372,9 +373,9 @@ genName2conf(GENERAL_NAME *gen, QString tag, QString *single, QString *sect) *single = QString("otherName:%1;FORMAT:HEX,%2"). arg(obj2SnOid(gen->d.otherName->type_id)). arg(asn1Type2Name(type)); - for (int i=0; ilength; i++) { + for (int i=0; idata[i]), 2, 16, QChar('0')); + arg((int)(ASN1_STRING_get0_data(a)[i]), 2, 16, QChar('0')); } } return true; @@ -423,12 +424,12 @@ bool x509v3ext::parse_ia5(QString *single, QString *adv) const return false; if (!str) { - const unsigned char *p = getData()->data; - str = d2i_ASN1_OCTET_STRING(NULL, &p, getData()->length); + const unsigned char *p = ASN1_STRING_get0_data(getData()); + str = d2i_ASN1_OCTET_STRING(NULL, &p, ASN1_STRING_length(getData())); if (ign_openssl_error() || !str) return false; ret = QString("%2"). - arg(asn1Type2Name(str->type)). + arg(asn1Type2Name(ASN1_STRING_type(str))). arg(QString(asn1ToQString(str))); } else { ret = QString(asn1ToQString(str)); @@ -824,10 +825,10 @@ bool x509v3ext::parse_generic(QString *, QString *adv) const const ASN1_OBJECT *o = object(); QString der, obj = o ? obj2SnOid(o) : QString("INVALID"); - ASN1_OCTET_STRING *v = getData(); + const ASN1_OCTET_STRING *v = getData(); - for (int i=0; v && i < v->length; i++) - der += QString(":%1").arg((int)(v->data[i]), 2, 16, QChar('0')); + for (int i=0; v && i < ASN1_STRING_length(v); i++) + der += QString(":%1").arg((int)(ASN1_STRING_get0_data(v)[i]), 2, 16, QChar('0')); if (adv) *adv = QString("%1=%2DER%3\n").arg(obj). @@ -1037,7 +1038,7 @@ X509_EXTENSION *x509v3ext::get() const bool x509v3ext::isValid() const { - return ext && getData() && getData()->length > 0 && + return ext && getData() && ASN1_STRING_length(getData()) > 0 && OBJ_obj2nid(X509_EXTENSION_get_object(ext)) != NID_undef; } diff --git a/lib/x509v3ext.h b/lib/x509v3ext.h index 1a3c5f9c..0776c079 100644 --- a/lib/x509v3ext.h +++ b/lib/x509v3ext.h @@ -35,7 +35,7 @@ class x509v3ext // bool operator == (const x509v3ext &x) const; QString getObject() const; int getCritical() const; - ASN1_OCTET_STRING *getData() const; + const ASN1_OCTET_STRING *getData() const; QString getValue() const; QString getHtmlValue() const; QString getConsoleValue(const QString &indent) const; diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index 631ccf21..0bedfb40 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -269,7 +269,7 @@ void CertDetail::setReq(pki_x509req *req) int count = X509_ATTRIBUTE_count(att); for (int j=0; jvalue.asn1_string); attrLayout->addWidget(label, ii, j +1); } @@ -289,7 +289,7 @@ QLabel *CertDetail::labelFromAsn1String(ASN1_STRING *s) QLabel *label; label = new CopyLabel(this); label->setText(asn1ToQString(s)); - label->setToolTip(QString(ASN1_tag2str(s->type))); + label->setToolTip(QString(ASN1_tag2str(ASN1_STRING_type(s)))); return label; }