File indexing completed on 2024-05-05 04:45:09

0001 /*
0002  * Copyright (C) 2004-2007  Justin Karneges <justin@affinix.com>
0003  * Copyright (C) 2004-2006  Brad Hards <bradh@frogmouth.net>
0004  * Copyright (C) 2013-2016  Ivan Romanov <drizt@land.ru>
0005  * Copyright (C) 2017       Fabian Vogt <fabian@ritter-vogt.de>
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Lesser General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2.1 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
0020  *
0021  */
0022 
0023 #include <QDebug>
0024 #include <QElapsedTimer>
0025 #include <QtCrypto>
0026 #include <QtPlugin>
0027 #include <qcaprovider.h>
0028 
0029 #include <openssl/evp.h>
0030 #include <openssl/hmac.h>
0031 
0032 #include <cstdio>
0033 #include <cstdlib>
0034 #include <iostream>
0035 #include <memory>
0036 
0037 #include <openssl/err.h>
0038 #include <openssl/opensslv.h>
0039 #include <openssl/pem.h>
0040 #include <openssl/pkcs12.h>
0041 #include <openssl/rand.h>
0042 #include <openssl/ssl.h>
0043 #include <openssl/x509v3.h>
0044 #ifdef OPENSSL_VERSION_MAJOR
0045 #include <openssl/provider.h>
0046 #endif
0047 
0048 #include <openssl/kdf.h>
0049 
0050 using namespace QCA;
0051 
0052 namespace {
0053 struct DsaDeleter
0054 {
0055     void operator()(DSA *pointer)
0056     {
0057         if (pointer)
0058             DSA_free(pointer);
0059     }
0060 };
0061 
0062 static bool s_legacyProviderAvailable = false;
0063 } // end of anonymous namespace
0064 
0065 namespace opensslQCAPlugin {
0066 
0067 //----------------------------------------------------------------------------
0068 // Util
0069 //----------------------------------------------------------------------------
0070 static SecureArray bio2buf(BIO *b)
0071 {
0072     SecureArray buf;
0073     while (true) {
0074         SecureArray block(1024);
0075         int         ret = BIO_read(b, block.data(), block.size());
0076         if (ret <= 0)
0077             break;
0078         block.resize(ret);
0079         buf.append(block);
0080         if (ret != 1024)
0081             break;
0082     }
0083     BIO_free(b);
0084     return buf;
0085 }
0086 
0087 static QByteArray bio2ba(BIO *b)
0088 {
0089     QByteArray buf;
0090     while (true) {
0091         QByteArray block(1024, 0);
0092         int        ret = BIO_read(b, block.data(), block.size());
0093         if (ret <= 0)
0094             break;
0095         block.resize(ret);
0096         buf.append(block);
0097         if (ret != 1024)
0098             break;
0099     }
0100     BIO_free(b);
0101     return buf;
0102 }
0103 
0104 static BigInteger bn2bi(const BIGNUM *n)
0105 {
0106     SecureArray buf(BN_num_bytes(n) + 1);
0107     buf[0] = 0; // positive
0108     BN_bn2bin(n, (unsigned char *)buf.data() + 1);
0109     return BigInteger(buf);
0110 }
0111 
0112 static BigInteger bn2bi_free(BIGNUM *n)
0113 {
0114     BigInteger bi = bn2bi(n);
0115     BN_free(n);
0116     return bi;
0117 }
0118 
0119 static BIGNUM *bi2bn(const BigInteger &n)
0120 {
0121     SecureArray buf = n.toArray();
0122     return BN_bin2bn((const unsigned char *)buf.data(), buf.size(), nullptr);
0123 }
0124 
0125 // take lowest bytes of BIGNUM to fit
0126 // pad with high byte zeroes to fit
0127 static SecureArray bn2fixedbuf(const BIGNUM *n, int size)
0128 {
0129     SecureArray buf(BN_num_bytes(n));
0130     BN_bn2bin(n, (unsigned char *)buf.data());
0131 
0132     SecureArray out(size);
0133     memset(out.data(), 0, size);
0134     int len = qMin(size, buf.size());
0135     memcpy(out.data() + (size - len), buf.data(), len);
0136     return out;
0137 }
0138 
0139 static SecureArray dsasig_der_to_raw(const SecureArray &in)
0140 {
0141     DSA_SIG             *sig = DSA_SIG_new();
0142     const unsigned char *inp = (const unsigned char *)in.data();
0143     d2i_DSA_SIG(&sig, &inp, in.size());
0144 
0145     const BIGNUM *bnr, *bns;
0146     DSA_SIG_get0(sig, &bnr, &bns);
0147 
0148     SecureArray part_r = bn2fixedbuf(bnr, 20);
0149     SecureArray part_s = bn2fixedbuf(bns, 20);
0150     SecureArray result;
0151     result.append(part_r);
0152     result.append(part_s);
0153 
0154     DSA_SIG_free(sig);
0155     return result;
0156 }
0157 
0158 static SecureArray dsasig_raw_to_der(const SecureArray &in)
0159 {
0160     if (in.size() != 40)
0161         return SecureArray();
0162 
0163     DSA_SIG    *sig = DSA_SIG_new();
0164     SecureArray part_r(20);
0165     BIGNUM     *bnr;
0166     SecureArray part_s(20);
0167     BIGNUM     *bns;
0168     memcpy(part_r.data(), in.data(), 20);
0169     memcpy(part_s.data(), in.data() + 20, 20);
0170     bnr = BN_bin2bn((const unsigned char *)part_r.data(), part_r.size(), nullptr);
0171     bns = BN_bin2bn((const unsigned char *)part_s.data(), part_s.size(), nullptr);
0172 
0173     if (DSA_SIG_set0(sig, bnr, bns) == 0)
0174         return SecureArray();
0175     // Not documented what happens in the failure case, free bnr and bns?
0176 
0177     int            len = i2d_DSA_SIG(sig, nullptr);
0178     SecureArray    result(len);
0179     unsigned char *p = (unsigned char *)result.data();
0180     i2d_DSA_SIG(sig, &p);
0181 
0182     DSA_SIG_free(sig);
0183     return result;
0184 }
0185 
0186 static int passphrase_cb(char *buf, int size, int rwflag, void *u)
0187 {
0188     Q_UNUSED(buf);
0189     Q_UNUSED(size);
0190     Q_UNUSED(rwflag);
0191     Q_UNUSED(u);
0192     return 0;
0193 }
0194 
0195 /*static bool is_basic_constraint(const ConstraintType &t)
0196 {
0197     bool basic = false;
0198     switch(t.known())
0199     {
0200         case DigitalSignature:
0201         case NonRepudiation:
0202         case KeyEncipherment:
0203         case DataEncipherment:
0204         case KeyAgreement:
0205         case KeyCertificateSign:
0206         case CRLSign:
0207         case EncipherOnly:
0208         case DecipherOnly:
0209             basic = true;
0210             break;
0211 
0212         case ServerAuth:
0213         case ClientAuth:
0214         case CodeSigning:
0215         case EmailProtection:
0216         case IPSecEndSystem:
0217         case IPSecTunnel:
0218         case IPSecUser:
0219         case TimeStamping:
0220         case OCSPSigning:
0221             break;
0222     }
0223     return basic;
0224 }
0225 
0226 static Constraints basic_only(const Constraints &list)
0227 {
0228     Constraints out;
0229     for(int n = 0; n < list.count(); ++n)
0230     {
0231         if(is_basic_constraint(list[n]))
0232             out += list[n];
0233     }
0234     return out;
0235 }
0236 
0237 static Constraints ext_only(const Constraints &list)
0238 {
0239     Constraints out;
0240     for(int n = 0; n < list.count(); ++n)
0241     {
0242         if(!is_basic_constraint(list[n]))
0243             out += list[n];
0244     }
0245     return out;
0246 }*/
0247 
0248 // logic from Botan
0249 /*static Constraints find_constraints(const PKeyContext &key, const Constraints &orig)
0250 {
0251     Constraints constraints;
0252 
0253     if(key.key()->type() == PKey::RSA)
0254         constraints += KeyEncipherment;
0255 
0256     if(key.key()->type() == PKey::DH)
0257         constraints += KeyAgreement;
0258 
0259     if(key.key()->type() == PKey::RSA || key.key()->type() == PKey::DSA)
0260     {
0261         constraints += DigitalSignature;
0262         constraints += NonRepudiation;
0263     }
0264 
0265     Constraints limits = basic_only(orig);
0266     Constraints the_rest = ext_only(orig);
0267 
0268     if(!limits.isEmpty())
0269     {
0270         Constraints reduced;
0271         for(int n = 0; n < constraints.count(); ++n)
0272         {
0273             if(limits.contains(constraints[n]))
0274                 reduced += constraints[n];
0275         }
0276         constraints = reduced;
0277     }
0278 
0279     constraints += the_rest;
0280 
0281     return constraints;
0282 }*/
0283 
0284 static void try_add_name_item(X509_NAME **name, int nid, const QString &val)
0285 {
0286     if (val.isEmpty())
0287         return;
0288     const QByteArray buf = val.toLatin1();
0289     if (!(*name))
0290         *name = X509_NAME_new();
0291     X509_NAME_add_entry_by_NID(*name, nid, MBSTRING_ASC, (const unsigned char *)buf.data(), buf.size(), -1, 0);
0292 }
0293 
0294 static X509_NAME *new_cert_name(const CertificateInfo &info)
0295 {
0296     X509_NAME *name = nullptr;
0297     // FIXME support multiple items of each type
0298     try_add_name_item(&name, NID_commonName, info.value(CommonName));
0299     try_add_name_item(&name, NID_countryName, info.value(Country));
0300     try_add_name_item(&name, NID_localityName, info.value(Locality));
0301     try_add_name_item(&name, NID_stateOrProvinceName, info.value(State));
0302     try_add_name_item(&name, NID_organizationName, info.value(Organization));
0303     try_add_name_item(&name, NID_organizationalUnitName, info.value(OrganizationalUnit));
0304     return name;
0305 }
0306 
0307 static void try_get_name_item(X509_NAME *name, int nid, const CertificateInfoType &t, CertificateInfo *info)
0308 {
0309     int loc;
0310     loc = -1;
0311     while ((loc = X509_NAME_get_index_by_NID(name, nid, loc)) != -1) {
0312         X509_NAME_ENTRY *ne   = X509_NAME_get_entry(name, loc);
0313         ASN1_STRING     *data = X509_NAME_ENTRY_get_data(ne);
0314         QByteArray       cs((const char *)data->data, data->length);
0315         info->insert(t, QString::fromLatin1(cs));
0316     }
0317 }
0318 
0319 static void
0320 try_get_name_item_by_oid(X509_NAME *name, const QString &oidText, const CertificateInfoType &t, CertificateInfo *info)
0321 {
0322     ASN1_OBJECT *oid = OBJ_txt2obj(oidText.toLatin1().data(), 1); // 1 = only accept dotted input
0323     if (!oid)
0324         return;
0325 
0326     int loc;
0327     loc = -1;
0328     while ((loc = X509_NAME_get_index_by_OBJ(name, oid, loc)) != -1) {
0329         X509_NAME_ENTRY *ne   = X509_NAME_get_entry(name, loc);
0330         ASN1_STRING     *data = X509_NAME_ENTRY_get_data(ne);
0331         QByteArray       cs((const char *)data->data, data->length);
0332         info->insert(t, QString::fromLatin1(cs));
0333         qDebug() << "oid: " << oidText << ",  result: " << cs;
0334     }
0335     ASN1_OBJECT_free(oid);
0336 }
0337 
0338 static CertificateInfo get_cert_name(X509_NAME *name)
0339 {
0340     CertificateInfo info;
0341     try_get_name_item(name, NID_commonName, CommonName, &info);
0342     try_get_name_item(name, NID_countryName, Country, &info);
0343     try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.3"), IncorporationCountry, &info);
0344     try_get_name_item(name, NID_localityName, Locality, &info);
0345     try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.1"), IncorporationLocality, &info);
0346     try_get_name_item(name, NID_stateOrProvinceName, State, &info);
0347     try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.2"), IncorporationState, &info);
0348     try_get_name_item(name, NID_organizationName, Organization, &info);
0349     try_get_name_item(name, NID_organizationalUnitName, OrganizationalUnit, &info);
0350 
0351     // legacy email
0352     {
0353         CertificateInfo p9_info;
0354         try_get_name_item(name, NID_pkcs9_emailAddress, EmailLegacy, &p9_info);
0355         const QList<QString> emails = info.values(Email);
0356 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0357         QMultiMapIterator<CertificateInfoType, QString> it(p9_info);
0358 #else
0359         QMapIterator<CertificateInfoType, QString> it(p9_info);
0360 #endif
0361         while (it.hasNext()) {
0362             it.next();
0363             if (!emails.contains(it.value()))
0364                 info.insert(Email, it.value());
0365         }
0366     }
0367 
0368     return info;
0369 }
0370 
0371 static X509_EXTENSION *new_subject_key_id(X509 *cert)
0372 {
0373     X509V3_CTX ctx;
0374     X509V3_set_ctx_nodb(&ctx);
0375     X509V3_set_ctx(&ctx, nullptr, cert, nullptr, nullptr, 0);
0376     X509_EXTENSION *ex = X509V3_EXT_conf_nid(nullptr, &ctx, NID_subject_key_identifier, (char *)"hash");
0377     return ex;
0378 }
0379 
0380 static X509_EXTENSION *new_basic_constraints(bool ca, int pathlen)
0381 {
0382     BASIC_CONSTRAINTS *bs = BASIC_CONSTRAINTS_new();
0383     bs->ca                = (ca ? 1 : 0);
0384     bs->pathlen           = ASN1_INTEGER_new();
0385     ASN1_INTEGER_set(bs->pathlen, pathlen);
0386 
0387     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, 1, bs); // 1 = critical
0388     BASIC_CONSTRAINTS_free(bs);
0389     return ex;
0390 }
0391 
0392 static void get_basic_constraints(X509_EXTENSION *ex, bool *ca, int *pathlen)
0393 {
0394     BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ex);
0395     *ca                   = (bs->ca ? true : false);
0396     if (bs->pathlen)
0397         *pathlen = ASN1_INTEGER_get(bs->pathlen);
0398     else
0399         *pathlen = 0;
0400     BASIC_CONSTRAINTS_free(bs);
0401 }
0402 
0403 enum ConstraintBit
0404 {
0405     Bit_DigitalSignature   = 0,
0406     Bit_NonRepudiation     = 1,
0407     Bit_KeyEncipherment    = 2,
0408     Bit_DataEncipherment   = 3,
0409     Bit_KeyAgreement       = 4,
0410     Bit_KeyCertificateSign = 5,
0411     Bit_CRLSign            = 6,
0412     Bit_EncipherOnly       = 7,
0413     Bit_DecipherOnly       = 8
0414 };
0415 
0416 static QByteArray ipaddress_string_to_bytes(const QString &)
0417 {
0418     return QByteArray(4, 0);
0419 }
0420 
0421 static GENERAL_NAME *new_general_name(const CertificateInfoType &t, const QString &val)
0422 {
0423     GENERAL_NAME *name = nullptr;
0424     switch (t.known()) {
0425     case Email:
0426     {
0427         const QByteArray buf = val.toLatin1();
0428 
0429         ASN1_IA5STRING *str = ASN1_IA5STRING_new();
0430         ASN1_STRING_set((ASN1_STRING *)str, (const unsigned char *)buf.data(), buf.size());
0431 
0432         name               = GENERAL_NAME_new();
0433         name->type         = GEN_EMAIL;
0434         name->d.rfc822Name = str;
0435         break;
0436     }
0437     case URI:
0438     {
0439         const QByteArray buf = val.toLatin1();
0440 
0441         ASN1_IA5STRING *str = ASN1_IA5STRING_new();
0442         ASN1_STRING_set((ASN1_STRING *)str, (const unsigned char *)buf.data(), buf.size());
0443 
0444         name                              = GENERAL_NAME_new();
0445         name->type                        = GEN_URI;
0446         name->d.uniformResourceIdentifier = str;
0447         break;
0448     }
0449     case DNS:
0450     {
0451         const QByteArray buf = val.toLatin1();
0452 
0453         ASN1_IA5STRING *str = ASN1_IA5STRING_new();
0454         ASN1_STRING_set((ASN1_STRING *)str, (const unsigned char *)buf.data(), buf.size());
0455 
0456         name            = GENERAL_NAME_new();
0457         name->type      = GEN_DNS;
0458         name->d.dNSName = str;
0459         break;
0460     }
0461     case IPAddress:
0462     {
0463         const QByteArray buf = ipaddress_string_to_bytes(val);
0464 
0465         ASN1_OCTET_STRING *str = ASN1_OCTET_STRING_new();
0466         ASN1_STRING_set((ASN1_STRING *)str, (const unsigned char *)buf.data(), buf.size());
0467 
0468         name              = GENERAL_NAME_new();
0469         name->type        = GEN_IPADD;
0470         name->d.iPAddress = str;
0471         break;
0472     }
0473     case XMPP:
0474     {
0475         const QByteArray buf = val.toUtf8();
0476 
0477         ASN1_UTF8STRING *str = ASN1_UTF8STRING_new();
0478         ASN1_STRING_set((ASN1_STRING *)str, (const unsigned char *)buf.data(), buf.size());
0479 
0480         ASN1_TYPE *at        = ASN1_TYPE_new();
0481         at->type             = V_ASN1_UTF8STRING;
0482         at->value.utf8string = str;
0483 
0484         OTHERNAME *other = OTHERNAME_new();
0485         other->type_id   = OBJ_txt2obj("1.3.6.1.5.5.7.8.5", 1); // 1 = only accept dotted input
0486         other->value     = at;
0487 
0488         name              = GENERAL_NAME_new();
0489         name->type        = GEN_OTHERNAME;
0490         name->d.otherName = other;
0491         break;
0492     }
0493     default:
0494         break;
0495     }
0496     return name;
0497 }
0498 
0499 static void try_add_general_name(GENERAL_NAMES **gn, const CertificateInfoType &t, const QString &val)
0500 {
0501     if (val.isEmpty())
0502         return;
0503     GENERAL_NAME *name = new_general_name(t, val);
0504     if (name) {
0505         if (!(*gn))
0506             *gn = sk_GENERAL_NAME_new_null();
0507         sk_GENERAL_NAME_push(*gn, name);
0508     }
0509 }
0510 
0511 static X509_EXTENSION *new_cert_subject_alt_name(const CertificateInfo &info)
0512 {
0513     GENERAL_NAMES *gn = nullptr;
0514     // FIXME support multiple items of each type
0515     try_add_general_name(&gn, Email, info.value(Email));
0516     try_add_general_name(&gn, URI, info.value(URI));
0517     try_add_general_name(&gn, DNS, info.value(DNS));
0518     try_add_general_name(&gn, IPAddress, info.value(IPAddress));
0519     try_add_general_name(&gn, XMPP, info.value(XMPP));
0520     if (!gn)
0521         return nullptr;
0522 
0523     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_subject_alt_name, 0, gn);
0524     sk_GENERAL_NAME_pop_free(gn, GENERAL_NAME_free);
0525     return ex;
0526 }
0527 
0528 static GENERAL_NAME *find_next_general_name(GENERAL_NAMES *names, int type, int *pos)
0529 {
0530     int           temp = *pos;
0531     GENERAL_NAME *gn   = nullptr;
0532     *pos               = -1;
0533     for (int n = temp; n < sk_GENERAL_NAME_num(names); ++n) {
0534         GENERAL_NAME *i = sk_GENERAL_NAME_value(names, n);
0535         if (i->type == type) {
0536             gn   = i;
0537             *pos = n;
0538             break;
0539         }
0540     }
0541     return gn;
0542 }
0543 
0544 static QByteArray qca_ASN1_STRING_toByteArray(ASN1_STRING *x)
0545 {
0546     return QByteArray(reinterpret_cast<const char *>(ASN1_STRING_get0_data(x)), ASN1_STRING_length(x));
0547 }
0548 
0549 static void try_get_general_name(GENERAL_NAMES *names, const CertificateInfoType &t, CertificateInfo *info)
0550 {
0551     switch (t.known()) {
0552     case Email:
0553     {
0554         int pos = 0;
0555         while (pos != -1) {
0556             GENERAL_NAME *gn = find_next_general_name(names, GEN_EMAIL, &pos);
0557             if (pos != -1) {
0558                 const QByteArray cs = qca_ASN1_STRING_toByteArray(gn->d.rfc822Name);
0559                 info->insert(t, QString::fromLatin1(cs));
0560                 ++pos;
0561             }
0562         }
0563         break;
0564     }
0565     case URI:
0566     {
0567         int pos = 0;
0568         while (pos != -1) {
0569             GENERAL_NAME *gn = find_next_general_name(names, GEN_URI, &pos);
0570             if (pos != -1) {
0571                 const QByteArray cs = qca_ASN1_STRING_toByteArray(gn->d.uniformResourceIdentifier);
0572                 info->insert(t, QString::fromLatin1(cs));
0573                 ++pos;
0574             }
0575         }
0576         break;
0577     }
0578     case DNS:
0579     {
0580         int pos = 0;
0581         while (pos != -1) {
0582             GENERAL_NAME *gn = find_next_general_name(names, GEN_DNS, &pos);
0583             if (pos != -1) {
0584                 const QByteArray cs = qca_ASN1_STRING_toByteArray(gn->d.dNSName);
0585                 info->insert(t, QString::fromLatin1(cs));
0586                 ++pos;
0587             }
0588         }
0589         break;
0590     }
0591     case IPAddress:
0592     {
0593         int pos = 0;
0594         while (pos != -1) {
0595             GENERAL_NAME *gn = find_next_general_name(names, GEN_IPADD, &pos);
0596             if (pos != -1) {
0597                 ASN1_OCTET_STRING *str = gn->d.iPAddress;
0598                 const QByteArray   buf = qca_ASN1_STRING_toByteArray(str);
0599 
0600                 QString out;
0601                 // IPv4 (TODO: handle IPv6)
0602                 if (buf.size() == 4) {
0603                     out = QStringLiteral("0.0.0.0");
0604                 } else
0605                     break;
0606                 info->insert(t, out);
0607                 ++pos;
0608             }
0609         }
0610         break;
0611     }
0612     case XMPP:
0613     {
0614         int pos = 0;
0615         while (pos != -1) {
0616             GENERAL_NAME *gn = find_next_general_name(names, GEN_OTHERNAME, &pos);
0617             if (pos != -1) {
0618                 OTHERNAME *other = gn->d.otherName;
0619                 if (!other)
0620                     break;
0621 
0622                 ASN1_OBJECT *obj = OBJ_txt2obj("1.3.6.1.5.5.7.8.5", 1); // 1 = only accept dotted input
0623                 if (OBJ_cmp(other->type_id, obj) != 0)
0624                     break;
0625                 ASN1_OBJECT_free(obj);
0626 
0627                 ASN1_TYPE *at = other->value;
0628                 if (at->type != V_ASN1_UTF8STRING)
0629                     break;
0630 
0631                 ASN1_UTF8STRING *str = at->value.utf8string;
0632                 const QByteArray buf = qca_ASN1_STRING_toByteArray(str);
0633                 info->insert(t, QString::fromUtf8(buf));
0634                 ++pos;
0635             }
0636         }
0637         break;
0638     }
0639     default:
0640         break;
0641     }
0642 }
0643 
0644 static CertificateInfo get_cert_alt_name(X509_EXTENSION *ex)
0645 {
0646     CertificateInfo info;
0647     GENERAL_NAMES  *gn = (GENERAL_NAMES *)X509V3_EXT_d2i(ex);
0648     try_get_general_name(gn, Email, &info);
0649     try_get_general_name(gn, URI, &info);
0650     try_get_general_name(gn, DNS, &info);
0651     try_get_general_name(gn, IPAddress, &info);
0652     try_get_general_name(gn, XMPP, &info);
0653     GENERAL_NAMES_free(gn);
0654     return info;
0655 }
0656 
0657 static X509_EXTENSION *new_cert_key_usage(const Constraints &constraints)
0658 {
0659     ASN1_BIT_STRING *keyusage = nullptr;
0660     for (int n = 0; n < constraints.count(); ++n) {
0661         int bit = -1;
0662         switch (constraints[n].known()) {
0663         case DigitalSignature:
0664             bit = Bit_DigitalSignature;
0665             break;
0666         case NonRepudiation:
0667             bit = Bit_NonRepudiation;
0668             break;
0669         case KeyEncipherment:
0670             bit = Bit_KeyEncipherment;
0671             break;
0672         case DataEncipherment:
0673             bit = Bit_DataEncipherment;
0674             break;
0675         case KeyAgreement:
0676             bit = Bit_KeyAgreement;
0677             break;
0678         case KeyCertificateSign:
0679             bit = Bit_KeyCertificateSign;
0680             break;
0681         case CRLSign:
0682             bit = Bit_CRLSign;
0683             break;
0684         case EncipherOnly:
0685             bit = Bit_EncipherOnly;
0686             break;
0687         case DecipherOnly:
0688             bit = Bit_DecipherOnly;
0689             break;
0690         default:
0691             break;
0692         }
0693         if (bit != -1) {
0694             if (!keyusage)
0695                 keyusage = ASN1_BIT_STRING_new();
0696             ASN1_BIT_STRING_set_bit(keyusage, bit, 1);
0697         }
0698     }
0699     if (!keyusage)
0700         return nullptr;
0701 
0702     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_key_usage, 1, keyusage); // 1 = critical
0703     ASN1_BIT_STRING_free(keyusage);
0704     return ex;
0705 }
0706 
0707 static Constraints get_cert_key_usage(X509_EXTENSION *ex)
0708 {
0709     Constraints constraints;
0710     int         bit_table[9] = {DigitalSignature,
0711                                 NonRepudiation,
0712                                 KeyEncipherment,
0713                                 DataEncipherment,
0714                                 KeyAgreement,
0715                                 KeyCertificateSign,
0716                                 CRLSign,
0717                                 EncipherOnly,
0718                                 DecipherOnly};
0719 
0720     ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ex);
0721     for (int n = 0; n < 9; ++n) {
0722         if (ASN1_BIT_STRING_get_bit(keyusage, n))
0723             constraints += ConstraintType((ConstraintTypeKnown)bit_table[n]);
0724     }
0725     ASN1_BIT_STRING_free(keyusage);
0726     return constraints;
0727 }
0728 
0729 static X509_EXTENSION *new_cert_ext_key_usage(const Constraints &constraints)
0730 {
0731     EXTENDED_KEY_USAGE *extkeyusage = nullptr;
0732     for (int n = 0; n < constraints.count(); ++n) {
0733         int nid = -1;
0734         // TODO: don't use known/nid, and instead just use OIDs
0735         switch (constraints[n].known()) {
0736         case ServerAuth:
0737             nid = NID_server_auth;
0738             break;
0739         case ClientAuth:
0740             nid = NID_client_auth;
0741             break;
0742         case CodeSigning:
0743             nid = NID_code_sign;
0744             break;
0745         case EmailProtection:
0746             nid = NID_email_protect;
0747             break;
0748         case IPSecEndSystem:
0749             nid = NID_ipsecEndSystem;
0750             break;
0751         case IPSecTunnel:
0752             nid = NID_ipsecTunnel;
0753             break;
0754         case IPSecUser:
0755             nid = NID_ipsecUser;
0756             break;
0757         case TimeStamping:
0758             nid = NID_time_stamp;
0759             break;
0760         case OCSPSigning:
0761             nid = NID_OCSP_sign;
0762             break;
0763         default:
0764             break;
0765         }
0766         if (nid != -1) {
0767             if (!extkeyusage)
0768                 extkeyusage = sk_ASN1_OBJECT_new_null();
0769             ASN1_OBJECT *obj = OBJ_nid2obj(nid);
0770             sk_ASN1_OBJECT_push(extkeyusage, obj);
0771         }
0772     }
0773     if (!extkeyusage)
0774         return nullptr;
0775 
0776     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_ext_key_usage, 0, extkeyusage); // 0 = not critical
0777     sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);
0778     return ex;
0779 }
0780 
0781 static Constraints get_cert_ext_key_usage(X509_EXTENSION *ex)
0782 {
0783     Constraints constraints;
0784 
0785     EXTENDED_KEY_USAGE *extkeyusage = (EXTENDED_KEY_USAGE *)X509V3_EXT_d2i(ex);
0786     for (int n = 0; n < sk_ASN1_OBJECT_num(extkeyusage); ++n) {
0787         ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(extkeyusage, n);
0788         int          nid = OBJ_obj2nid(obj);
0789         if (nid == NID_undef)
0790             continue;
0791 
0792         // TODO: don't use known/nid, and instead just use OIDs
0793         int t = -1;
0794         switch (nid) {
0795         case NID_server_auth:
0796             t = ServerAuth;
0797             break;
0798         case NID_client_auth:
0799             t = ClientAuth;
0800             break;
0801         case NID_code_sign:
0802             t = CodeSigning;
0803             break;
0804         case NID_email_protect:
0805             t = EmailProtection;
0806             break;
0807         case NID_ipsecEndSystem:
0808             t = IPSecEndSystem;
0809             break;
0810         case NID_ipsecTunnel:
0811             t = IPSecTunnel;
0812             break;
0813         case NID_ipsecUser:
0814             t = IPSecUser;
0815             break;
0816         case NID_time_stamp:
0817             t = TimeStamping;
0818             break;
0819         case NID_OCSP_sign:
0820             t = OCSPSigning;
0821             break;
0822         };
0823 
0824         if (t == -1)
0825             continue;
0826 
0827         constraints.append(ConstraintType((ConstraintTypeKnown)t));
0828     }
0829     sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);
0830     return constraints;
0831 }
0832 
0833 static X509_EXTENSION *new_cert_policies(const QStringList &policies)
0834 {
0835     STACK_OF(POLICYINFO) *pols = nullptr;
0836     for (int n = 0; n < policies.count(); ++n) {
0837         const QByteArray cs  = policies[n].toLatin1();
0838         ASN1_OBJECT     *obj = OBJ_txt2obj(cs.data(), 1); // 1 = only accept dotted input
0839         if (!obj)
0840             continue;
0841         if (!pols)
0842             pols = sk_POLICYINFO_new_null();
0843         POLICYINFO *pol = POLICYINFO_new();
0844         pol->policyid   = obj;
0845         sk_POLICYINFO_push(pols, pol);
0846     }
0847     if (!pols)
0848         return nullptr;
0849 
0850     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0, pols); // 0 = not critical
0851     sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
0852     return ex;
0853 }
0854 
0855 static QStringList get_cert_policies(X509_EXTENSION *ex)
0856 {
0857     QStringList out;
0858     STACK_OF(POLICYINFO) *pols = (STACK_OF(POLICYINFO) *)X509V3_EXT_d2i(ex);
0859     for (int n = 0; n < sk_POLICYINFO_num(pols); ++n) {
0860         POLICYINFO *pol = sk_POLICYINFO_value(pols, n);
0861         QByteArray  buf(128, 0);
0862         const auto  len = OBJ_obj2txt((char *)buf.data(), buf.size(), pol->policyid, 1); // 1 = only accept dotted input
0863         if (len > 0)
0864             out += QString::fromLatin1(buf.left(len));
0865     }
0866     sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
0867     return out;
0868 }
0869 
0870 static QByteArray get_cert_subject_key_id(X509_EXTENSION *ex)
0871 {
0872     ASN1_OCTET_STRING *skid = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ex);
0873     const QByteArray   out  = qca_ASN1_STRING_toByteArray(skid);
0874     ASN1_OCTET_STRING_free(skid);
0875     return out;
0876 }
0877 
0878 // If you get any more crashes in this code, please provide a copy
0879 // of the cert to bradh AT frogmouth.net
0880 static QByteArray get_cert_issuer_key_id(X509_EXTENSION *ex)
0881 {
0882     AUTHORITY_KEYID *akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ex);
0883     QByteArray       out;
0884     if (akid->keyid)
0885         out = qca_ASN1_STRING_toByteArray(akid->keyid);
0886     AUTHORITY_KEYID_free(akid);
0887     return out;
0888 }
0889 
0890 static Validity convert_verify_error(int err)
0891 {
0892     // TODO: ErrorExpiredCA
0893     Validity rc;
0894     switch (err) {
0895     case X509_V_ERR_CERT_REJECTED:
0896         rc = ErrorRejected;
0897         break;
0898     case X509_V_ERR_CERT_UNTRUSTED:
0899         rc = ErrorUntrusted;
0900         break;
0901     case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
0902     case X509_V_ERR_CERT_SIGNATURE_FAILURE:
0903     case X509_V_ERR_CRL_SIGNATURE_FAILURE:
0904     case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
0905     case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
0906         rc = ErrorSignatureFailed;
0907         break;
0908     case X509_V_ERR_INVALID_CA:
0909     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
0910     case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
0911     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
0912         rc = ErrorInvalidCA;
0913         break;
0914     case X509_V_ERR_INVALID_PURPOSE: // note: not used by store verify
0915         rc = ErrorInvalidPurpose;
0916         break;
0917     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
0918     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
0919         rc = ErrorSelfSigned;
0920         break;
0921     case X509_V_ERR_CERT_REVOKED:
0922         rc = ErrorRevoked;
0923         break;
0924     case X509_V_ERR_PATH_LENGTH_EXCEEDED:
0925         rc = ErrorPathLengthExceeded;
0926         break;
0927     case X509_V_ERR_CERT_NOT_YET_VALID:
0928     case X509_V_ERR_CERT_HAS_EXPIRED:
0929     case X509_V_ERR_CRL_NOT_YET_VALID:
0930     case X509_V_ERR_CRL_HAS_EXPIRED:
0931     case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
0932     case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
0933     case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
0934     case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
0935         rc = ErrorExpired;
0936         break;
0937     case X509_V_ERR_APPLICATION_VERIFICATION:
0938     case X509_V_ERR_OUT_OF_MEM:
0939     case X509_V_ERR_UNABLE_TO_GET_CRL:
0940     case X509_V_ERR_CERT_CHAIN_TOO_LONG:
0941     default:
0942         rc = ErrorValidityUnknown;
0943         break;
0944     }
0945     return rc;
0946 }
0947 
0948 EVP_PKEY *qca_d2i_PKCS8PrivateKey(const SecureArray &in, EVP_PKEY **x, pem_password_cb *cb, void *u)
0949 {
0950     PKCS8_PRIV_KEY_INFO *p8inf;
0951 
0952     // first try unencrypted form
0953     BIO *bi = BIO_new(BIO_s_mem());
0954     BIO_write(bi, in.data(), in.size());
0955     p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(bi, nullptr);
0956     BIO_free(bi);
0957     if (!p8inf) {
0958         X509_SIG *p8;
0959 
0960         // now try encrypted form
0961         bi = BIO_new(BIO_s_mem());
0962         BIO_write(bi, in.data(), in.size());
0963         p8 = d2i_PKCS8_bio(bi, nullptr);
0964         BIO_free(bi);
0965         if (!p8)
0966             return nullptr;
0967 
0968         // get passphrase
0969         char psbuf[PEM_BUFSIZE];
0970         int  klen;
0971         if (cb)
0972             klen = cb(psbuf, PEM_BUFSIZE, 0, u);
0973         else
0974             klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
0975         if (klen <= 0) {
0976             PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);
0977             X509_SIG_free(p8);
0978             return nullptr;
0979         }
0980 
0981         // decrypt it
0982         p8inf = PKCS8_decrypt(p8, psbuf, klen);
0983         X509_SIG_free(p8);
0984         if (!p8inf)
0985             return nullptr;
0986     }
0987 
0988     EVP_PKEY *ret = EVP_PKCS82PKEY(p8inf);
0989     PKCS8_PRIV_KEY_INFO_free(p8inf);
0990     if (!ret)
0991         return nullptr;
0992     if (x) {
0993         if (*x)
0994             EVP_PKEY_free(*x);
0995         *x = ret;
0996     }
0997     return ret;
0998 }
0999 
1000 class opensslHashContext : public HashContext
1001 {
1002     Q_OBJECT
1003 public:
1004     opensslHashContext(const EVP_MD *algorithm, Provider *p, const QString &type)
1005         : HashContext(p, type)
1006     {
1007         m_algorithm = algorithm;
1008         m_context   = EVP_MD_CTX_new();
1009         EVP_DigestInit(m_context, m_algorithm);
1010     }
1011 
1012     opensslHashContext(const opensslHashContext &other)
1013         : HashContext(other)
1014     {
1015         m_algorithm = other.m_algorithm;
1016         m_context   = EVP_MD_CTX_new();
1017         EVP_MD_CTX_copy_ex(m_context, other.m_context);
1018     }
1019 
1020     ~opensslHashContext() override
1021     {
1022         EVP_MD_CTX_free(m_context);
1023     }
1024 
1025     void clear() override
1026     {
1027         EVP_MD_CTX_free(m_context);
1028         m_context = EVP_MD_CTX_new();
1029         EVP_DigestInit(m_context, m_algorithm);
1030     }
1031 
1032     void update(const MemoryRegion &a) override
1033     {
1034         EVP_DigestUpdate(m_context, (unsigned char *)a.data(), a.size());
1035     }
1036 
1037     MemoryRegion final() override
1038     {
1039         SecureArray a(EVP_MD_size(m_algorithm));
1040         EVP_DigestFinal(m_context, (unsigned char *)a.data(), nullptr);
1041         return a;
1042     }
1043 
1044     Provider::Context *clone() const override
1045     {
1046         return new opensslHashContext(*this);
1047     }
1048 
1049 protected:
1050     const EVP_MD *m_algorithm;
1051     EVP_MD_CTX   *m_context;
1052 };
1053 
1054 class opensslPbkdf1Context : public KDFContext
1055 {
1056     Q_OBJECT
1057 public:
1058     opensslPbkdf1Context(const EVP_MD *algorithm, Provider *p, const QString &type)
1059         : KDFContext(p, type)
1060     {
1061         Q_ASSERT(s_legacyProviderAvailable);
1062         m_algorithm = algorithm;
1063         m_context   = EVP_MD_CTX_new();
1064         EVP_DigestInit(m_context, m_algorithm);
1065     }
1066 
1067     opensslPbkdf1Context(const opensslPbkdf1Context &other)
1068         : KDFContext(other)
1069     {
1070         m_algorithm = other.m_algorithm;
1071         m_context   = EVP_MD_CTX_new();
1072         EVP_MD_CTX_copy(m_context, other.m_context);
1073     }
1074 
1075     ~opensslPbkdf1Context() override
1076     {
1077         EVP_MD_CTX_free(m_context);
1078     }
1079 
1080     Provider::Context *clone() const override
1081     {
1082         return new opensslPbkdf1Context(*this);
1083     }
1084 
1085     SymmetricKey makeKey(const SecureArray          &secret,
1086                          const InitializationVector &salt,
1087                          unsigned int                keyLength,
1088                          unsigned int                iterationCount) override
1089     {
1090         /* from RFC2898:
1091            Steps:
1092 
1093            1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
1094            "derived key too long" and stop.
1095         */
1096         if (keyLength > (unsigned int)EVP_MD_size(m_algorithm)) {
1097             std::cout << "derived key too long" << std::endl;
1098             return SymmetricKey();
1099         }
1100 
1101         /*
1102           2. Apply the underlying hash function Hash for c iterations to the
1103           concatenation of the password P and the salt S, then extract
1104           the first dkLen octets to produce a derived key DK:
1105 
1106           T_1 = Hash (P || S) ,
1107           T_2 = Hash (T_1) ,
1108           ...
1109           T_c = Hash (T_{c-1}) ,
1110           DK = Tc<0..dkLen-1>
1111         */
1112         // calculate T_1
1113         EVP_DigestUpdate(m_context, (unsigned char *)secret.data(), secret.size());
1114         EVP_DigestUpdate(m_context, (unsigned char *)salt.data(), salt.size());
1115         SecureArray a(EVP_MD_size(m_algorithm));
1116         EVP_DigestFinal(m_context, (unsigned char *)a.data(), nullptr);
1117 
1118         // calculate T_2 up to T_c
1119         for (unsigned int i = 2; i <= iterationCount; ++i) {
1120             EVP_DigestInit(m_context, m_algorithm);
1121             EVP_DigestUpdate(m_context, (unsigned char *)a.data(), a.size());
1122             EVP_DigestFinal(m_context, (unsigned char *)a.data(), nullptr);
1123         }
1124 
1125         // shrink a to become DK, of the required length
1126         a.resize(keyLength);
1127 
1128         /*
1129           3. Output the derived key DK.
1130         */
1131         return a;
1132     }
1133 
1134     SymmetricKey makeKey(const SecureArray          &secret,
1135                          const InitializationVector &salt,
1136                          unsigned int                keyLength,
1137                          int                         msecInterval,
1138                          unsigned int               *iterationCount) override
1139     {
1140         Q_ASSERT(iterationCount != nullptr);
1141         QElapsedTimer timer;
1142 
1143         /* from RFC2898:
1144            Steps:
1145 
1146            1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
1147            "derived key too long" and stop.
1148         */
1149         if (keyLength > (unsigned int)EVP_MD_size(m_algorithm)) {
1150             std::cout << "derived key too long" << std::endl;
1151             return SymmetricKey();
1152         }
1153 
1154         /*
1155           2. Apply the underlying hash function Hash for M milliseconds
1156           to the concatenation of the password P and the salt S, incrementing c,
1157           then extract the first dkLen octets to produce a derived key DK:
1158 
1159           time from M to 0
1160           T_1 = Hash (P || S) ,
1161           T_2 = Hash (T_1) ,
1162           ...
1163           T_c = Hash (T_{c-1}) ,
1164           when time = 0: stop,
1165           DK = Tc<0..dkLen-1>
1166         */
1167         // calculate T_1
1168         EVP_DigestUpdate(m_context, (unsigned char *)secret.data(), secret.size());
1169         EVP_DigestUpdate(m_context, (unsigned char *)salt.data(), salt.size());
1170         SecureArray a(EVP_MD_size(m_algorithm));
1171         EVP_DigestFinal(m_context, (unsigned char *)a.data(), nullptr);
1172 
1173         // calculate T_2 up to T_c
1174         *iterationCount = 2 - 1; // <- Have to remove 1, unless it computes one
1175         timer.start();           // ^  time more than the base function
1176                                  // ^  with the same iterationCount
1177         while (timer.elapsed() < msecInterval) {
1178             EVP_DigestInit(m_context, m_algorithm);
1179             EVP_DigestUpdate(m_context, (unsigned char *)a.data(), a.size());
1180             EVP_DigestFinal(m_context, (unsigned char *)a.data(), nullptr);
1181             ++(*iterationCount);
1182         }
1183 
1184         // shrink a to become DK, of the required length
1185         a.resize(keyLength);
1186 
1187         /*
1188           3. Output the derived key DK.
1189         */
1190         return a;
1191     }
1192 
1193 protected:
1194     const EVP_MD *m_algorithm;
1195     EVP_MD_CTX   *m_context;
1196 };
1197 
1198 class opensslPbkdf2Context : public KDFContext
1199 {
1200     Q_OBJECT
1201 public:
1202     opensslPbkdf2Context(Provider *p, const QString &type)
1203         : KDFContext(p, type)
1204     {
1205     }
1206 
1207     Provider::Context *clone() const override
1208     {
1209         return new opensslPbkdf2Context(*this);
1210     }
1211 
1212     SymmetricKey makeKey(const SecureArray          &secret,
1213                          const InitializationVector &salt,
1214                          unsigned int                keyLength,
1215                          unsigned int                iterationCount) override
1216     {
1217         SecureArray out(keyLength);
1218         PKCS5_PBKDF2_HMAC_SHA1((char *)secret.data(),
1219                                secret.size(),
1220                                (unsigned char *)salt.data(),
1221                                salt.size(),
1222                                iterationCount,
1223                                keyLength,
1224                                (unsigned char *)out.data());
1225         return out;
1226     }
1227 
1228     SymmetricKey makeKey(const SecureArray          &secret,
1229                          const InitializationVector &salt,
1230                          unsigned int                keyLength,
1231                          int                         msecInterval,
1232                          unsigned int               *iterationCount) override
1233     {
1234         Q_ASSERT(iterationCount != nullptr);
1235         QElapsedTimer timer;
1236         SecureArray   out(keyLength);
1237 
1238         *iterationCount = 0;
1239         timer.start();
1240 
1241         // PBKDF2 needs an iterationCount itself, unless PBKDF1.
1242         // So we need to calculate first the number of iterations for
1243         // That time interval, then feed the iterationCounts to PBKDF2
1244         while (timer.elapsed() < msecInterval) {
1245             PKCS5_PBKDF2_HMAC_SHA1((char *)secret.data(),
1246                                    secret.size(),
1247                                    (unsigned char *)salt.data(),
1248                                    salt.size(),
1249                                    1,
1250                                    keyLength,
1251                                    (unsigned char *)out.data());
1252             ++(*iterationCount);
1253         }
1254 
1255         // Now we can directely call makeKey base function,
1256         // as we now have the iterationCount
1257         out = makeKey(secret, salt, keyLength, *iterationCount);
1258 
1259         return out;
1260     }
1261 
1262 protected:
1263 };
1264 
1265 class opensslHkdfContext : public HKDFContext
1266 {
1267     Q_OBJECT
1268 public:
1269     opensslHkdfContext(Provider *p, const QString &type)
1270         : HKDFContext(p, type)
1271     {
1272     }
1273 
1274     Provider::Context *clone() const override
1275     {
1276         return new opensslHkdfContext(*this);
1277     }
1278 
1279     SymmetricKey makeKey(const SecureArray          &secret,
1280                          const InitializationVector &salt,
1281                          const InitializationVector &info,
1282                          unsigned int                keyLength) override
1283     {
1284         SecureArray   out(keyLength);
1285         EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
1286         EVP_PKEY_derive_init(pctx);
1287         EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256());
1288         EVP_PKEY_CTX_set1_hkdf_salt(pctx, (const unsigned char *)salt.data(), int(salt.size()));
1289         EVP_PKEY_CTX_set1_hkdf_key(pctx, (const unsigned char *)secret.data(), int(secret.size()));
1290         EVP_PKEY_CTX_add1_hkdf_info(pctx, (const unsigned char *)info.data(), int(info.size()));
1291         size_t outlen = out.size();
1292         EVP_PKEY_derive(pctx, reinterpret_cast<unsigned char *>(out.data()), &outlen);
1293         EVP_PKEY_CTX_free(pctx);
1294         return out;
1295     }
1296 };
1297 
1298 class opensslHMACContext : public MACContext
1299 {
1300     Q_OBJECT
1301 public:
1302     opensslHMACContext(const EVP_MD *algorithm, Provider *p, const QString &type)
1303         : MACContext(p, type)
1304     {
1305         m_algorithm = algorithm;
1306         m_context   = HMAC_CTX_new();
1307     }
1308 
1309     opensslHMACContext(const opensslHMACContext &other)
1310         : MACContext(other)
1311     {
1312         m_algorithm = other.m_algorithm;
1313         m_context   = HMAC_CTX_new();
1314         HMAC_CTX_copy(m_context, other.m_context);
1315     }
1316 
1317     ~opensslHMACContext() override
1318     {
1319         HMAC_CTX_free(m_context);
1320     }
1321 
1322     void setup(const SymmetricKey &key) override
1323     {
1324         HMAC_Init_ex(m_context, key.data(), key.size(), m_algorithm, nullptr);
1325     }
1326 
1327     KeyLength keyLength() const override
1328     {
1329         return anyKeyLength();
1330     }
1331 
1332     void update(const MemoryRegion &a) override
1333     {
1334         HMAC_Update(m_context, (unsigned char *)a.data(), a.size());
1335     }
1336 
1337     void final(MemoryRegion *out) override
1338     {
1339         SecureArray sa(EVP_MD_size(m_algorithm), 0);
1340         HMAC_Final(m_context, (unsigned char *)sa.data(), nullptr);
1341         HMAC_CTX_reset(m_context);
1342         *out = sa;
1343     }
1344 
1345     Provider::Context *clone() const override
1346     {
1347         return new opensslHMACContext(*this);
1348     }
1349 
1350 protected:
1351     HMAC_CTX     *m_context;
1352     const EVP_MD *m_algorithm;
1353 };
1354 
1355 //----------------------------------------------------------------------------
1356 // EVPKey
1357 //----------------------------------------------------------------------------
1358 
1359 // note: this class squelches processing errors, since QCA doesn't care about them
1360 class EVPKey
1361 {
1362 public:
1363     enum State
1364     {
1365         Idle,
1366         SignActive,
1367         SignError,
1368         VerifyActive,
1369         VerifyError
1370     };
1371     EVP_PKEY   *pkey;
1372     EVP_MD_CTX *mdctx;
1373     State       state;
1374     bool        raw_type;
1375     SecureArray raw;
1376 
1377     EVPKey()
1378     {
1379         pkey     = nullptr;
1380         raw_type = false;
1381         state    = Idle;
1382         mdctx    = EVP_MD_CTX_new();
1383     }
1384 
1385     EVPKey(const EVPKey &from)
1386     {
1387         pkey = from.pkey;
1388         EVP_PKEY_up_ref(pkey);
1389         raw_type = false;
1390         state    = Idle;
1391         mdctx    = EVP_MD_CTX_new();
1392         EVP_MD_CTX_copy(mdctx, from.mdctx);
1393     }
1394 
1395     EVPKey &operator=(const EVPKey &from) = delete;
1396 
1397     ~EVPKey()
1398     {
1399         reset();
1400         EVP_MD_CTX_free(mdctx);
1401     }
1402 
1403     void reset()
1404     {
1405         if (pkey)
1406             EVP_PKEY_free(pkey);
1407         pkey = nullptr;
1408         raw.clear();
1409         raw_type = false;
1410     }
1411 
1412     void startSign(const EVP_MD *type)
1413     {
1414         state = SignActive;
1415         if (!type) {
1416             raw_type = true;
1417             raw.clear();
1418         } else {
1419             raw_type = false;
1420             EVP_MD_CTX_init(mdctx);
1421             if (!EVP_SignInit_ex(mdctx, type, nullptr))
1422                 state = SignError;
1423         }
1424     }
1425 
1426     void startVerify(const EVP_MD *type)
1427     {
1428         state = VerifyActive;
1429         if (!type) {
1430             raw_type = true;
1431             raw.clear();
1432         } else {
1433             raw_type = false;
1434             EVP_MD_CTX_init(mdctx);
1435             if (!EVP_VerifyInit_ex(mdctx, type, nullptr))
1436                 state = VerifyError;
1437         }
1438     }
1439 
1440     void update(const MemoryRegion &in)
1441     {
1442         if (state == SignActive) {
1443             if (raw_type)
1444                 raw += in;
1445             else if (!EVP_SignUpdate(mdctx, in.data(), (unsigned int)in.size()))
1446                 state = SignError;
1447         } else if (state == VerifyActive) {
1448             if (raw_type)
1449                 raw += in;
1450             else if (!EVP_VerifyUpdate(mdctx, in.data(), (unsigned int)in.size()))
1451                 state = VerifyError;
1452         }
1453     }
1454 
1455     SecureArray endSign()
1456     {
1457         if (state == SignActive) {
1458             SecureArray  out(EVP_PKEY_size(pkey));
1459             unsigned int len = out.size();
1460             if (raw_type) {
1461                 int type = EVP_PKEY_id(pkey);
1462 
1463                 if (type == EVP_PKEY_RSA) {
1464                     const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
1465                     if (RSA_private_encrypt(raw.size(),
1466                                             (unsigned char *)raw.data(),
1467                                             (unsigned char *)out.data(),
1468                                             (RSA *)rsa,
1469                                             RSA_PKCS1_PADDING) == -1) {
1470                         state = SignError;
1471                         return SecureArray();
1472                     }
1473                 } else if (type == EVP_PKEY_DSA) {
1474                     state = SignError;
1475                     return SecureArray();
1476                 } else {
1477                     state = SignError;
1478                     return SecureArray();
1479                 }
1480             } else {
1481                 if (!EVP_SignFinal(mdctx, (unsigned char *)out.data(), &len, pkey)) {
1482                     state = SignError;
1483                     return SecureArray();
1484                 }
1485             }
1486             out.resize(len);
1487             state = Idle;
1488             return out;
1489         } else
1490             return SecureArray();
1491     }
1492 
1493     bool endVerify(const SecureArray &sig)
1494     {
1495         if (state == VerifyActive) {
1496             if (raw_type) {
1497                 SecureArray out(EVP_PKEY_size(pkey));
1498                 int         len = 0;
1499 
1500                 int type = EVP_PKEY_id(pkey);
1501 
1502                 if (type == EVP_PKEY_RSA) {
1503                     const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
1504                     if ((len = RSA_public_decrypt(sig.size(),
1505                                                   (unsigned char *)sig.data(),
1506                                                   (unsigned char *)out.data(),
1507                                                   (RSA *)rsa,
1508                                                   RSA_PKCS1_PADDING)) == -1) {
1509                         state = VerifyError;
1510                         return false;
1511                     }
1512                 } else if (type == EVP_PKEY_DSA) {
1513                     state = VerifyError;
1514                     return false;
1515                 } else {
1516                     state = VerifyError;
1517                     return false;
1518                 }
1519 
1520                 out.resize(len);
1521 
1522                 if (out != raw) {
1523                     state = VerifyError;
1524                     return false;
1525                 }
1526             } else {
1527                 if (EVP_VerifyFinal(mdctx, (unsigned char *)sig.data(), (unsigned int)sig.size(), pkey) != 1) {
1528                     state = VerifyError;
1529                     return false;
1530                 }
1531             }
1532             state = Idle;
1533             return true;
1534         } else
1535             return false;
1536     }
1537 };
1538 
1539 //----------------------------------------------------------------------------
1540 // MyDLGroup
1541 //----------------------------------------------------------------------------
1542 
1543 // IETF primes from Botan
1544 static const char *IETF_1024_PRIME =
1545     "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1"
1546     "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD"
1547     "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245"
1548     "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED"
1549     "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381"
1550     "FFFFFFFF FFFFFFFF";
1551 
1552 static const char *IETF_2048_PRIME =
1553     "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1"
1554     "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD"
1555     "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245"
1556     "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED"
1557     "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D"
1558     "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F"
1559     "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D"
1560     "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B"
1561     "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9"
1562     "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510"
1563     "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF";
1564 
1565 static const char *IETF_4096_PRIME =
1566     "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1"
1567     "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD"
1568     "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245"
1569     "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED"
1570     "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D"
1571     "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F"
1572     "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D"
1573     "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B"
1574     "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9"
1575     "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510"
1576     "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64"
1577     "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7"
1578     "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B"
1579     "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C"
1580     "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31"
1581     "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7"
1582     "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA"
1583     "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6"
1584     "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED"
1585     "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9"
1586     "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199"
1587     "FFFFFFFF FFFFFFFF";
1588 
1589 #ifndef OPENSSL_FIPS
1590 // JCE seeds from Botan
1591 static const char *JCE_512_SEED    = "B869C82B 35D70E1B 1FF91B28 E37A62EC DC34409B";
1592 static const int   JCE_512_COUNTER = 123;
1593 
1594 static const char *JCE_768_SEED    = "77D0F8C4 DAD15EB8 C4F2F8D6 726CEFD9 6D5BB399";
1595 static const int   JCE_768_COUNTER = 263;
1596 
1597 static const char *JCE_1024_SEED    = "8D515589 4229D5E6 89EE01E6 018A237E 2CAE64CD";
1598 static const int   JCE_1024_COUNTER = 92;
1599 #endif
1600 
1601 static QByteArray dehex(const QByteArray &hex)
1602 {
1603     QString str;
1604     for (const char c : hex) {
1605         if (c != ' ')
1606             str += QLatin1Char(c);
1607     }
1608     return hexToArray(str);
1609 }
1610 
1611 static BigInteger decode(const QByteArray &prime)
1612 {
1613     QByteArray a(1, 0); // 1 byte of zero padding
1614     a.append(dehex(prime));
1615     return BigInteger(SecureArray(a));
1616 }
1617 
1618 #ifndef OPENSSL_FIPS
1619 static QByteArray decode_seed(const QByteArray &hex_seed)
1620 {
1621     return dehex(hex_seed);
1622 }
1623 #endif
1624 
1625 class DLParams
1626 {
1627 public:
1628     BigInteger p, q, g;
1629 };
1630 
1631 #ifndef OPENSSL_FIPS
1632 
1633 static bool make_dlgroup(const QByteArray &seed, int bits, int counter, DLParams *params)
1634 {
1635     int                              ret_counter;
1636     std::unique_ptr<DSA, DsaDeleter> dsa(DSA_new());
1637     if (!dsa)
1638         return false;
1639 
1640     if (DSA_generate_parameters_ex(
1641             dsa.get(), bits, (const unsigned char *)seed.data(), seed.size(), &ret_counter, nullptr, nullptr) != 1)
1642         return false;
1643 
1644     if (ret_counter != counter)
1645         return false;
1646 
1647     const BIGNUM *bnp, *bnq, *bng;
1648     DSA_get0_pqg(dsa.get(), &bnp, &bnq, &bng);
1649     params->p = bn2bi(bnp);
1650     params->q = bn2bi(bnq);
1651     params->g = bn2bi(bng);
1652 
1653     return true;
1654 }
1655 #endif
1656 
1657 static bool get_dlgroup(const BigInteger &p, const BigInteger &g, DLParams *params)
1658 {
1659     params->p = p;
1660     params->q = BigInteger(0);
1661     params->g = g;
1662     return true;
1663 }
1664 
1665 class DLGroupMaker : public QThread
1666 {
1667     Q_OBJECT
1668 public:
1669     DLGroupSet set;
1670     bool       ok;
1671     DLParams   params;
1672 
1673     DLGroupMaker(DLGroupSet _set)
1674     {
1675         set = _set;
1676     }
1677 
1678     ~DLGroupMaker() override
1679     {
1680         wait();
1681     }
1682 
1683     void run() override
1684     {
1685         switch (set) {
1686 #ifndef OPENSSL_FIPS
1687         case DSA_512:
1688             ok = make_dlgroup(decode_seed(JCE_512_SEED), 512, JCE_512_COUNTER, &params);
1689             break;
1690 
1691         case DSA_768:
1692             ok = make_dlgroup(decode_seed(JCE_768_SEED), 768, JCE_768_COUNTER, &params);
1693             break;
1694 
1695         case DSA_1024:
1696             ok = make_dlgroup(decode_seed(JCE_1024_SEED), 1024, JCE_1024_COUNTER, &params);
1697             break;
1698 #endif
1699 
1700         case IETF_1024:
1701             ok = get_dlgroup(decode(IETF_1024_PRIME), 2, &params);
1702             break;
1703 
1704         case IETF_2048:
1705             ok = get_dlgroup(decode(IETF_2048_PRIME), 2, &params);
1706             break;
1707 
1708         case IETF_4096:
1709             ok = get_dlgroup(decode(IETF_4096_PRIME), 2, &params);
1710             break;
1711 
1712         default:
1713             ok = false;
1714             break;
1715         }
1716     }
1717 };
1718 
1719 class MyDLGroup : public DLGroupContext
1720 {
1721     Q_OBJECT
1722 public:
1723     DLGroupMaker *gm;
1724     bool          wasBlocking;
1725     DLParams      params;
1726     bool          empty;
1727 
1728     MyDLGroup(Provider *p)
1729         : DLGroupContext(p)
1730     {
1731         gm    = nullptr;
1732         empty = true;
1733     }
1734 
1735     MyDLGroup(const MyDLGroup &from)
1736         : DLGroupContext(from.provider())
1737     {
1738         gm    = nullptr;
1739         empty = true;
1740     }
1741 
1742     ~MyDLGroup() override
1743     {
1744         delete gm;
1745     }
1746 
1747     Provider::Context *clone() const override
1748     {
1749         return new MyDLGroup(*this);
1750     }
1751 
1752     QList<DLGroupSet> supportedGroupSets() const override
1753     {
1754         QList<DLGroupSet> list;
1755 
1756         // DSA_* was removed in FIPS specification
1757         // https://bugzilla.redhat.com/show_bug.cgi?id=1144655
1758 #ifndef OPENSSL_FIPS
1759         list += DSA_512;
1760         list += DSA_768;
1761         list += DSA_1024;
1762 #endif
1763         list += IETF_1024;
1764         list += IETF_2048;
1765         list += IETF_4096;
1766         return list;
1767     }
1768 
1769     bool isNull() const override
1770     {
1771         return empty;
1772     }
1773 
1774     void fetchGroup(DLGroupSet set, bool block) override
1775     {
1776         params = DLParams();
1777         empty  = true;
1778 
1779         gm          = new DLGroupMaker(set);
1780         wasBlocking = block;
1781         if (block) {
1782             gm->run();
1783             gm_finished();
1784         } else {
1785             connect(gm, &DLGroupMaker::finished, this, &MyDLGroup::gm_finished);
1786             gm->start();
1787         }
1788     }
1789 
1790     void getResult(BigInteger *p, BigInteger *q, BigInteger *g) const override
1791     {
1792         *p = params.p;
1793         *q = params.q;
1794         *g = params.g;
1795     }
1796 
1797 private Q_SLOTS:
1798     void gm_finished()
1799     {
1800         bool ok = gm->ok;
1801         if (ok) {
1802             params = gm->params;
1803             empty  = false;
1804         }
1805 
1806         if (wasBlocking)
1807             delete gm;
1808         else
1809             gm->deleteLater();
1810         gm = nullptr;
1811 
1812         if (!wasBlocking)
1813             emit finished();
1814     }
1815 };
1816 
1817 //----------------------------------------------------------------------------
1818 // RSAKey
1819 //----------------------------------------------------------------------------
1820 namespace {
1821 static const auto RsaDeleter = [](RSA *pointer) {
1822     if (pointer)
1823         RSA_free((RSA *)pointer);
1824 };
1825 
1826 static const auto BnDeleter = [](BIGNUM *pointer) {
1827     if (pointer)
1828         BN_free((BIGNUM *)pointer);
1829 };
1830 } // end of anonymous namespace
1831 
1832 class RSAKeyMaker : public QThread
1833 {
1834     Q_OBJECT
1835 public:
1836     RSA *result;
1837     int  bits, exp;
1838 
1839     RSAKeyMaker(int _bits, int _exp, QObject *parent = nullptr)
1840         : QThread(parent)
1841         , result(nullptr)
1842         , bits(_bits)
1843         , exp(_exp)
1844     {
1845     }
1846 
1847     ~RSAKeyMaker() override
1848     {
1849         wait();
1850         if (result)
1851             RSA_free(result);
1852     }
1853 
1854     void run() override
1855     {
1856         std::unique_ptr<RSA, decltype(RsaDeleter)> rsa(RSA_new(), RsaDeleter);
1857         if (!rsa)
1858             return;
1859 
1860         std::unique_ptr<BIGNUM, decltype(BnDeleter)> e(BN_new(), BnDeleter);
1861         if (!e)
1862             return;
1863 
1864         BN_clear(e.get());
1865         if (BN_set_word(e.get(), exp) != 1)
1866             return;
1867 
1868         if (RSA_generate_key_ex(rsa.get(), bits, e.get(), nullptr) == 0) {
1869             return;
1870         }
1871 
1872         result = rsa.release();
1873     }
1874 
1875     RSA *takeResult()
1876     {
1877         RSA *rsa = result;
1878         result   = nullptr;
1879         return rsa;
1880     }
1881 };
1882 
1883 class RSAKey : public RSAContext
1884 {
1885     Q_OBJECT
1886 public:
1887     EVPKey       evp;
1888     RSAKeyMaker *keymaker;
1889     bool         wasBlocking;
1890     bool         sec;
1891 
1892     RSAKey(Provider *p)
1893         : RSAContext(p)
1894     {
1895         keymaker = nullptr;
1896         sec      = false;
1897     }
1898 
1899     RSAKey(const RSAKey &from)
1900         : RSAContext(from.provider())
1901         , evp(from.evp)
1902     {
1903         keymaker = nullptr;
1904         sec      = from.sec;
1905     }
1906 
1907     ~RSAKey() override
1908     {
1909         delete keymaker;
1910     }
1911 
1912     Provider::Context *clone() const override
1913     {
1914         return new RSAKey(*this);
1915     }
1916 
1917     bool isNull() const override
1918     {
1919         return (evp.pkey ? false : true);
1920     }
1921 
1922     PKey::Type type() const override
1923     {
1924         return PKey::RSA;
1925     }
1926 
1927     bool isPrivate() const override
1928     {
1929         return sec;
1930     }
1931 
1932     bool canExport() const override
1933     {
1934         return true;
1935     }
1936 
1937     void convertToPublic() override
1938     {
1939         if (!sec)
1940             return;
1941 
1942         // extract the public key into DER format
1943         const RSA     *rsa_pkey = EVP_PKEY_get0_RSA(evp.pkey);
1944         int            len      = i2d_RSAPublicKey(rsa_pkey, nullptr);
1945         SecureArray    result(len);
1946         unsigned char *p = (unsigned char *)result.data();
1947         i2d_RSAPublicKey(rsa_pkey, &p);
1948         p = (unsigned char *)result.data();
1949 
1950         // put the DER public key back into openssl
1951         evp.reset();
1952         RSA *rsa = d2i_RSAPublicKey(nullptr, (const unsigned char **)&p, result.size());
1953         evp.pkey = EVP_PKEY_new();
1954         EVP_PKEY_assign_RSA(evp.pkey, rsa);
1955         sec = false;
1956     }
1957 
1958     int bits() const override
1959     {
1960         return EVP_PKEY_bits(evp.pkey);
1961     }
1962 
1963     int maximumEncryptSize(EncryptionAlgorithm alg) const override
1964     {
1965         const RSA *rsa  = EVP_PKEY_get0_RSA(evp.pkey);
1966         int        size = 0;
1967         switch (alg) {
1968         case EME_PKCS1v15:
1969             size = RSA_size(rsa) - 11 - 1;
1970             break;
1971         case EME_PKCS1_OAEP:
1972             size = RSA_size(rsa) - 41 - 1;
1973             break;
1974         case EME_PKCS1v15_SSL:
1975             size = RSA_size(rsa) - 11 - 1;
1976             break;
1977         case EME_NO_PADDING:
1978             size = RSA_size(rsa) - 1;
1979             break;
1980         }
1981 
1982         return size;
1983     }
1984 
1985     SecureArray encrypt(const SecureArray &in, EncryptionAlgorithm alg) override
1986     {
1987         const RSA  *rsa = EVP_PKEY_get0_RSA(evp.pkey);
1988         SecureArray buf = in;
1989         int         max = maximumEncryptSize(alg);
1990 
1991         if (buf.size() > max)
1992             buf.resize(max);
1993         SecureArray result(RSA_size(rsa));
1994 
1995         int pad;
1996         switch (alg) {
1997         case EME_PKCS1v15:
1998             pad = RSA_PKCS1_PADDING;
1999             break;
2000         case EME_PKCS1_OAEP:
2001             pad = RSA_PKCS1_OAEP_PADDING;
2002             break;
2003 // OPENSSL_VERSION_MAJOR is only defined on openssl > 3.0
2004 // that doesn't have RSA_SSLV23_PADDING so we can use it negatively here
2005 #ifndef OPENSSL_VERSION_MAJOR
2006         case EME_PKCS1v15_SSL:
2007             pad = RSA_SSLV23_PADDING;
2008             break;
2009 #endif
2010         case EME_NO_PADDING:
2011             pad = RSA_NO_PADDING;
2012             break;
2013         default:
2014             return SecureArray();
2015             break;
2016         }
2017 
2018         int ret;
2019         if (isPrivate())
2020             ret = RSA_private_encrypt(
2021                 buf.size(), (unsigned char *)buf.data(), (unsigned char *)result.data(), (RSA *)rsa, pad);
2022         else
2023             ret = RSA_public_encrypt(
2024                 buf.size(), (unsigned char *)buf.data(), (unsigned char *)result.data(), (RSA *)rsa, pad);
2025 
2026         if (ret < 0)
2027             return SecureArray();
2028         result.resize(ret);
2029 
2030         return result;
2031     }
2032 
2033     bool decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg) override
2034     {
2035         const RSA  *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2036         SecureArray result(RSA_size(rsa));
2037         int         pad;
2038 
2039         switch (alg) {
2040         case EME_PKCS1v15:
2041             pad = RSA_PKCS1_PADDING;
2042             break;
2043         case EME_PKCS1_OAEP:
2044             pad = RSA_PKCS1_OAEP_PADDING;
2045             break;
2046 // OPENSSL_VERSION_MAJOR is only defined on openssl > 3.0
2047 // that doesn't have RSA_SSLV23_PADDING so we can use it negatively here
2048 #ifndef OPENSSL_VERSION_MAJOR
2049         case EME_PKCS1v15_SSL:
2050             pad = RSA_SSLV23_PADDING;
2051             break;
2052 #endif
2053         case EME_NO_PADDING:
2054             pad = RSA_NO_PADDING;
2055             break;
2056         default:
2057             return false;
2058             break;
2059         }
2060 
2061         int ret;
2062         if (isPrivate())
2063             ret = RSA_private_decrypt(
2064                 in.size(), (unsigned char *)in.data(), (unsigned char *)result.data(), (RSA *)rsa, pad);
2065         else
2066             ret = RSA_public_decrypt(
2067                 in.size(), (unsigned char *)in.data(), (unsigned char *)result.data(), (RSA *)rsa, pad);
2068 
2069         if (ret < 0)
2070             return false;
2071         result.resize(ret);
2072 
2073         *out = result;
2074         return true;
2075     }
2076 
2077     void startSign(SignatureAlgorithm alg, SignatureFormat) override
2078     {
2079         const EVP_MD *md = nullptr;
2080         if (alg == EMSA3_SHA1)
2081             md = EVP_sha1();
2082         else if (alg == EMSA3_MD5)
2083             md = EVP_md5();
2084         else if (alg == EMSA3_SHA224)
2085             md = EVP_sha224();
2086         else if (alg == EMSA3_SHA256)
2087             md = EVP_sha256();
2088         else if (alg == EMSA3_SHA384)
2089             md = EVP_sha384();
2090         else if (alg == EMSA3_SHA512)
2091             md = EVP_sha512();
2092         else if (alg == EMSA3_Raw) {
2093             // md = 0
2094         } else if (s_legacyProviderAvailable) {
2095             if (alg == EMSA3_RIPEMD160)
2096                 md = EVP_ripemd160();
2097 #ifdef HAVE_OPENSSL_MD2
2098             else if (alg == EMSA3_MD2)
2099                 md = EVP_md2();
2100 #endif
2101         }
2102 
2103         evp.startSign(md);
2104     }
2105 
2106     void startVerify(SignatureAlgorithm alg, SignatureFormat) override
2107     {
2108         const EVP_MD *md = nullptr;
2109         if (alg == EMSA3_SHA1)
2110             md = EVP_sha1();
2111         else if (alg == EMSA3_MD5)
2112             md = EVP_md5();
2113         else if (alg == EMSA3_SHA224)
2114             md = EVP_sha224();
2115         else if (alg == EMSA3_SHA256)
2116             md = EVP_sha256();
2117         else if (alg == EMSA3_SHA384)
2118             md = EVP_sha384();
2119         else if (alg == EMSA3_SHA512)
2120             md = EVP_sha512();
2121         else if (alg == EMSA3_Raw) {
2122             // md = 0
2123         } else if (s_legacyProviderAvailable) {
2124             if (alg == EMSA3_RIPEMD160)
2125                 md = EVP_ripemd160();
2126 #ifdef HAVE_OPENSSL_MD2
2127             else if (alg == EMSA3_MD2)
2128                 md = EVP_md2();
2129 #endif
2130         }
2131         evp.startVerify(md);
2132     }
2133 
2134     void update(const MemoryRegion &in) override
2135     {
2136         evp.update(in);
2137     }
2138 
2139     QByteArray endSign() override
2140     {
2141         return evp.endSign().toByteArray();
2142     }
2143 
2144     bool endVerify(const QByteArray &sig) override
2145     {
2146         return evp.endVerify(sig);
2147     }
2148 
2149     void createPrivate(int bits, int exp, bool block) override
2150     {
2151         evp.reset();
2152 
2153         keymaker    = new RSAKeyMaker(bits, exp, !block ? this : nullptr);
2154         wasBlocking = block;
2155         if (block) {
2156             keymaker->run();
2157             km_finished();
2158         } else {
2159             connect(keymaker, &RSAKeyMaker::finished, this, &RSAKey::km_finished);
2160             keymaker->start();
2161         }
2162     }
2163 
2164     void createPrivate(const BigInteger &n,
2165                        const BigInteger &e,
2166                        const BigInteger &p,
2167                        const BigInteger &q,
2168                        const BigInteger &d) override
2169     {
2170         evp.reset();
2171 
2172         RSA *rsa = RSA_new();
2173         if (RSA_set0_key(rsa, bi2bn(n), bi2bn(e), bi2bn(d)) == 0 || RSA_set0_factors(rsa, bi2bn(p), bi2bn(q)) == 0) {
2174             // Free BIGNUMS?
2175             RSA_free(rsa);
2176             return;
2177         }
2178 
2179         // When private key has no Public Exponent (e) or Private Exponent (d)
2180         // need to disable blinding. Otherwise decryption will be broken.
2181         // http://www.mail-archive.com/openssl-users@openssl.org/msg63530.html
2182         if (e == BigInteger(0) || d == BigInteger(0))
2183             RSA_blinding_off(rsa);
2184 
2185         evp.pkey = EVP_PKEY_new();
2186         EVP_PKEY_assign_RSA(evp.pkey, rsa);
2187         sec = true;
2188     }
2189 
2190     void createPublic(const BigInteger &n, const BigInteger &e) override
2191     {
2192         evp.reset();
2193 
2194         RSA *rsa = RSA_new();
2195         if (RSA_set0_key(rsa, bi2bn(n), bi2bn(e), nullptr) == 0) {
2196             RSA_free(rsa);
2197             return;
2198         }
2199 
2200         evp.pkey = EVP_PKEY_new();
2201         EVP_PKEY_assign_RSA(evp.pkey, rsa);
2202         sec = false;
2203     }
2204 
2205     BigInteger n() const override
2206     {
2207         const RSA    *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2208         const BIGNUM *bnn;
2209         RSA_get0_key(rsa, &bnn, nullptr, nullptr);
2210         return bn2bi(bnn);
2211     }
2212 
2213     BigInteger e() const override
2214     {
2215         const RSA    *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2216         const BIGNUM *bne;
2217         RSA_get0_key(rsa, nullptr, &bne, nullptr);
2218         return bn2bi(bne);
2219     }
2220 
2221     BigInteger p() const override
2222     {
2223         const RSA    *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2224         const BIGNUM *bnp;
2225         RSA_get0_factors(rsa, &bnp, nullptr);
2226         return bn2bi(bnp);
2227     }
2228 
2229     BigInteger q() const override
2230     {
2231         const RSA    *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2232         const BIGNUM *bnq;
2233         RSA_get0_factors(rsa, nullptr, &bnq);
2234         return bn2bi(bnq);
2235     }
2236 
2237     BigInteger d() const override
2238     {
2239         const RSA    *rsa = EVP_PKEY_get0_RSA(evp.pkey);
2240         const BIGNUM *bnd;
2241         RSA_get0_key(rsa, nullptr, nullptr, &bnd);
2242         return bn2bi(bnd);
2243     }
2244 
2245 private Q_SLOTS:
2246     void km_finished()
2247     {
2248         RSA *rsa = keymaker->takeResult();
2249         if (wasBlocking)
2250             delete keymaker;
2251         else
2252             keymaker->deleteLater();
2253         keymaker = nullptr;
2254 
2255         if (rsa) {
2256             evp.pkey = EVP_PKEY_new();
2257             EVP_PKEY_assign_RSA(evp.pkey, rsa);
2258             sec = true;
2259         }
2260 
2261         if (!wasBlocking)
2262             emit finished();
2263     }
2264 };
2265 
2266 //----------------------------------------------------------------------------
2267 // DSAKey
2268 //----------------------------------------------------------------------------
2269 class DSAKeyMaker : public QThread
2270 {
2271     Q_OBJECT
2272 public:
2273     DLGroup domain;
2274     DSA    *result;
2275 
2276     DSAKeyMaker(const DLGroup &_domain, QObject *parent = nullptr)
2277         : QThread(parent)
2278         , domain(_domain)
2279         , result(nullptr)
2280     {
2281     }
2282 
2283     ~DSAKeyMaker() override
2284     {
2285         wait();
2286         if (result)
2287             DSA_free(result);
2288     }
2289 
2290     void run() override
2291     {
2292         std::unique_ptr<DSA, DsaDeleter> dsa(DSA_new());
2293         BIGNUM                          *pne = bi2bn(domain.p()), *qne = bi2bn(domain.q()), *gne = bi2bn(domain.g());
2294 
2295         if (!DSA_set0_pqg(dsa.get(), pne, qne, gne)) {
2296             return;
2297         }
2298         if (!DSA_generate_key(dsa.get())) {
2299             // OPENSSL_VERSION_MAJOR is only defined in openssl3
2300 #ifdef OPENSSL_VERSION_MAJOR
2301             // HACK
2302             // in openssl3 there is an internal flag for "legacy" values
2303             //      bits < 2048 && seed_len <= 20
2304             // set in ossl_ffc_params_FIPS186_2_generate (called by DSA_generate_parameters_ex)
2305             // that we have no way to get or set, so if the bits are smaller than 2048 we generate
2306             // a dsa from a dummy seed and then override the p/q/g with the ones we want
2307             // so we can reuse the internal flag
2308             if (BN_num_bits(pne) < 2048) {
2309                 int dummy;
2310                 dsa.reset(DSA_new());
2311                 if (DSA_generate_parameters_ex(
2312                         dsa.get(), 512, (const unsigned char *)"THIS_IS_A_DUMMY_SEED", 20, &dummy, nullptr, nullptr) !=
2313                     1) {
2314                     return;
2315                 }
2316                 pne = bi2bn(domain.p());
2317                 qne = bi2bn(domain.q());
2318                 gne = bi2bn(domain.g());
2319                 if (!DSA_set0_pqg(dsa.get(), pne, qne, gne)) {
2320                     return;
2321                 }
2322                 if (!DSA_generate_key(dsa.get())) {
2323                     return;
2324                 }
2325             } else {
2326                 return;
2327             }
2328 #else
2329             return;
2330 #endif
2331         }
2332         result = dsa.release();
2333     }
2334 
2335     DSA *takeResult()
2336     {
2337         DSA *dsa = result;
2338         result   = nullptr;
2339         return dsa;
2340     }
2341 };
2342 
2343 // note: DSA doesn't use SignatureAlgorithm, since EMSA1 is always assumed
2344 class DSAKey : public DSAContext
2345 {
2346     Q_OBJECT
2347 public:
2348     EVPKey       evp;
2349     DSAKeyMaker *keymaker;
2350     bool         wasBlocking;
2351     bool         transformsig;
2352     bool         sec;
2353 
2354     DSAKey(Provider *p)
2355         : DSAContext(p)
2356     {
2357         keymaker = nullptr;
2358         sec      = false;
2359     }
2360 
2361     DSAKey(const DSAKey &from)
2362         : DSAContext(from.provider())
2363         , evp(from.evp)
2364     {
2365         keymaker = nullptr;
2366         sec      = from.sec;
2367     }
2368 
2369     ~DSAKey() override
2370     {
2371         delete keymaker;
2372     }
2373 
2374     Provider::Context *clone() const override
2375     {
2376         return new DSAKey(*this);
2377     }
2378 
2379     bool isNull() const override
2380     {
2381         return (evp.pkey ? false : true);
2382     }
2383 
2384     PKey::Type type() const override
2385     {
2386         return PKey::DSA;
2387     }
2388 
2389     bool isPrivate() const override
2390     {
2391         return sec;
2392     }
2393 
2394     bool canExport() const override
2395     {
2396         return true;
2397     }
2398 
2399     void convertToPublic() override
2400     {
2401         if (!sec)
2402             return;
2403 
2404         // extract the public key into DER format
2405         const DSA     *dsa_pkey = EVP_PKEY_get0_DSA(evp.pkey);
2406         int            len      = i2d_DSAPublicKey(dsa_pkey, nullptr);
2407         SecureArray    result(len);
2408         unsigned char *p = (unsigned char *)result.data();
2409         i2d_DSAPublicKey(dsa_pkey, &p);
2410         p = (unsigned char *)result.data();
2411 
2412         // put the DER public key back into openssl
2413         evp.reset();
2414         DSA *dsa = d2i_DSAPublicKey(nullptr, (const unsigned char **)&p, result.size());
2415         evp.pkey = EVP_PKEY_new();
2416         EVP_PKEY_assign_DSA(evp.pkey, dsa);
2417         sec = false;
2418     }
2419 
2420     int bits() const override
2421     {
2422         return EVP_PKEY_bits(evp.pkey);
2423     }
2424 
2425     void startSign(SignatureAlgorithm, SignatureFormat format) override
2426     {
2427         // openssl native format is DER, so transform otherwise
2428         if (format != DERSequence)
2429             transformsig = true;
2430         else
2431             transformsig = false;
2432 
2433         evp.startSign(EVP_sha1());
2434     }
2435 
2436     void startVerify(SignatureAlgorithm, SignatureFormat format) override
2437     {
2438         // openssl native format is DER, so transform otherwise
2439         if (format != DERSequence)
2440             transformsig = true;
2441         else
2442             transformsig = false;
2443 
2444         evp.startVerify(EVP_sha1());
2445     }
2446 
2447     void update(const MemoryRegion &in) override
2448     {
2449         evp.update(in);
2450     }
2451 
2452     QByteArray endSign() override
2453     {
2454         SecureArray out = evp.endSign();
2455         if (transformsig)
2456             return dsasig_der_to_raw(out).toByteArray();
2457         else
2458             return out.toByteArray();
2459     }
2460 
2461     bool endVerify(const QByteArray &sig) override
2462     {
2463         SecureArray in;
2464         if (transformsig)
2465             in = dsasig_raw_to_der(sig);
2466         else
2467             in = sig;
2468         return evp.endVerify(in);
2469     }
2470 
2471     void createPrivate(const DLGroup &domain, bool block) override
2472     {
2473         evp.reset();
2474 
2475         keymaker    = new DSAKeyMaker(domain, !block ? this : nullptr);
2476         wasBlocking = block;
2477         if (block) {
2478             keymaker->run();
2479             km_finished();
2480         } else {
2481             connect(keymaker, &DSAKeyMaker::finished, this, &DSAKey::km_finished);
2482             keymaker->start();
2483         }
2484     }
2485 
2486     void createPrivate(const DLGroup &domain, const BigInteger &y, const BigInteger &x) override
2487     {
2488         evp.reset();
2489 
2490         DSA    *dsa        = DSA_new();
2491         BIGNUM *bnp        = bi2bn(domain.p());
2492         BIGNUM *bnq        = bi2bn(domain.q());
2493         BIGNUM *bng        = bi2bn(domain.g());
2494         BIGNUM *bnpub_key  = bi2bn(y);
2495         BIGNUM *bnpriv_key = bi2bn(x);
2496 
2497         if (!DSA_set0_pqg(dsa, bnp, bnq, bng) || !DSA_set0_key(dsa, bnpub_key, bnpriv_key)) {
2498             DSA_free(dsa);
2499             return;
2500         }
2501 
2502         evp.pkey = EVP_PKEY_new();
2503         EVP_PKEY_assign_DSA(evp.pkey, dsa);
2504         sec = true;
2505     }
2506 
2507     void createPublic(const DLGroup &domain, const BigInteger &y) override
2508     {
2509         evp.reset();
2510 
2511         DSA    *dsa       = DSA_new();
2512         BIGNUM *bnp       = bi2bn(domain.p());
2513         BIGNUM *bnq       = bi2bn(domain.q());
2514         BIGNUM *bng       = bi2bn(domain.g());
2515         BIGNUM *bnpub_key = bi2bn(y);
2516 
2517         if (!DSA_set0_pqg(dsa, bnp, bnq, bng) || !DSA_set0_key(dsa, bnpub_key, nullptr)) {
2518             DSA_free(dsa);
2519             return;
2520         }
2521 
2522         evp.pkey = EVP_PKEY_new();
2523         EVP_PKEY_assign_DSA(evp.pkey, dsa);
2524         sec = false;
2525     }
2526 
2527     DLGroup domain() const override
2528     {
2529         const DSA    *dsa = EVP_PKEY_get0_DSA(evp.pkey);
2530         const BIGNUM *bnp, *bnq, *bng;
2531         DSA_get0_pqg(dsa, &bnp, &bnq, &bng);
2532         return DLGroup(bn2bi(bnp), bn2bi(bnq), bn2bi(bng));
2533     }
2534 
2535     BigInteger y() const override
2536     {
2537         const DSA    *dsa = EVP_PKEY_get0_DSA(evp.pkey);
2538         const BIGNUM *bnpub_key;
2539         DSA_get0_key(dsa, &bnpub_key, nullptr);
2540         return bn2bi(bnpub_key);
2541     }
2542 
2543     BigInteger x() const override
2544     {
2545         const DSA    *dsa = EVP_PKEY_get0_DSA(evp.pkey);
2546         const BIGNUM *bnpriv_key;
2547         DSA_get0_key(dsa, nullptr, &bnpriv_key);
2548         return bn2bi(bnpriv_key);
2549     }
2550 
2551 private Q_SLOTS:
2552     void km_finished()
2553     {
2554         DSA *dsa = keymaker->takeResult();
2555         if (wasBlocking)
2556             delete keymaker;
2557         else
2558             keymaker->deleteLater();
2559         keymaker = nullptr;
2560 
2561         if (dsa) {
2562             evp.pkey = EVP_PKEY_new();
2563             EVP_PKEY_assign_DSA(evp.pkey, dsa);
2564             sec = true;
2565         }
2566 
2567         if (!wasBlocking)
2568             emit finished();
2569     }
2570 };
2571 
2572 //----------------------------------------------------------------------------
2573 // DHKey
2574 //----------------------------------------------------------------------------
2575 class DHKeyMaker : public QThread
2576 {
2577     Q_OBJECT
2578 public:
2579     DLGroup domain;
2580     DH     *result;
2581 
2582     DHKeyMaker(const DLGroup &_domain, QObject *parent = nullptr)
2583         : QThread(parent)
2584         , domain(_domain)
2585         , result(nullptr)
2586     {
2587     }
2588 
2589     ~DHKeyMaker() override
2590     {
2591         wait();
2592         if (result)
2593             DH_free(result);
2594     }
2595 
2596     void run() override
2597     {
2598         DH     *dh  = DH_new();
2599         BIGNUM *bnp = bi2bn(domain.p());
2600         BIGNUM *bng = bi2bn(domain.g());
2601         if (!DH_set0_pqg(dh, bnp, nullptr, bng) || !DH_generate_key(dh)) {
2602             DH_free(dh);
2603             return;
2604         }
2605         result = dh;
2606     }
2607 
2608     DH *takeResult()
2609     {
2610         DH *dh = result;
2611         result = nullptr;
2612         return dh;
2613     }
2614 };
2615 
2616 class DHKey : public DHContext
2617 {
2618     Q_OBJECT
2619 public:
2620     EVPKey      evp;
2621     DHKeyMaker *keymaker;
2622     bool        wasBlocking;
2623     bool        sec;
2624 
2625     DHKey(Provider *p)
2626         : DHContext(p)
2627     {
2628         keymaker = nullptr;
2629         sec      = false;
2630     }
2631 
2632     DHKey(const DHKey &from)
2633         : DHContext(from.provider())
2634         , evp(from.evp)
2635     {
2636         keymaker = nullptr;
2637         sec      = from.sec;
2638     }
2639 
2640     ~DHKey() override
2641     {
2642         delete keymaker;
2643     }
2644 
2645     Provider::Context *clone() const override
2646     {
2647         return new DHKey(*this);
2648     }
2649 
2650     bool isNull() const override
2651     {
2652         return (evp.pkey ? false : true);
2653     }
2654 
2655     PKey::Type type() const override
2656     {
2657         return PKey::DH;
2658     }
2659 
2660     bool isPrivate() const override
2661     {
2662         return sec;
2663     }
2664 
2665     bool canExport() const override
2666     {
2667         return true;
2668     }
2669 
2670     void convertToPublic() override
2671     {
2672         if (!sec)
2673             return;
2674 
2675         const DH     *orig = EVP_PKEY_get0_DH(evp.pkey);
2676         DH           *dh   = DH_new();
2677         const BIGNUM *bnp, *bng, *bnpub_key;
2678         DH_get0_pqg(orig, &bnp, nullptr, &bng);
2679         DH_get0_key(orig, &bnpub_key, nullptr);
2680 
2681         DH_set0_key(dh, BN_dup(bnpub_key), nullptr);
2682         DH_set0_pqg(dh, BN_dup(bnp), nullptr, BN_dup(bng));
2683 
2684         evp.reset();
2685 
2686         evp.pkey = EVP_PKEY_new();
2687         EVP_PKEY_assign_DH(evp.pkey, dh);
2688         sec = false;
2689     }
2690 
2691     int bits() const override
2692     {
2693         return EVP_PKEY_bits(evp.pkey);
2694     }
2695 
2696     SymmetricKey deriveKey(const PKeyBase &theirs) override
2697     {
2698         const DH     *dh   = EVP_PKEY_get0_DH(evp.pkey);
2699         const DH     *them = EVP_PKEY_get0_DH(static_cast<const DHKey *>(&theirs)->evp.pkey);
2700         const BIGNUM *bnpub_key;
2701         DH_get0_key(them, &bnpub_key, nullptr);
2702 
2703         SecureArray result(DH_size(dh));
2704         int         ret = DH_compute_key((unsigned char *)result.data(), bnpub_key, (DH *)dh);
2705         if (ret <= 0)
2706             return SymmetricKey();
2707         result.resize(ret);
2708         return SymmetricKey(result);
2709     }
2710 
2711     void createPrivate(const DLGroup &domain, bool block) override
2712     {
2713         evp.reset();
2714 
2715         keymaker    = new DHKeyMaker(domain, !block ? this : nullptr);
2716         wasBlocking = block;
2717         if (block) {
2718             keymaker->run();
2719             km_finished();
2720         } else {
2721             connect(keymaker, &DHKeyMaker::finished, this, &DHKey::km_finished);
2722             keymaker->start();
2723         }
2724     }
2725 
2726     void createPrivate(const DLGroup &domain, const BigInteger &y, const BigInteger &x) override
2727     {
2728         evp.reset();
2729 
2730         DH     *dh         = DH_new();
2731         BIGNUM *bnp        = bi2bn(domain.p());
2732         BIGNUM *bng        = bi2bn(domain.g());
2733         BIGNUM *bnpub_key  = bi2bn(y);
2734         BIGNUM *bnpriv_key = bi2bn(x);
2735 
2736         if (!DH_set0_key(dh, bnpub_key, bnpriv_key) || !DH_set0_pqg(dh, bnp, nullptr, bng)) {
2737             DH_free(dh);
2738             return;
2739         }
2740 
2741         evp.pkey = EVP_PKEY_new();
2742         EVP_PKEY_assign_DH(evp.pkey, dh);
2743         sec = true;
2744     }
2745 
2746     void createPublic(const DLGroup &domain, const BigInteger &y) override
2747     {
2748         evp.reset();
2749 
2750         DH     *dh        = DH_new();
2751         BIGNUM *bnp       = bi2bn(domain.p());
2752         BIGNUM *bng       = bi2bn(domain.g());
2753         BIGNUM *bnpub_key = bi2bn(y);
2754 
2755         if (!DH_set0_key(dh, bnpub_key, nullptr) || !DH_set0_pqg(dh, bnp, nullptr, bng)) {
2756             DH_free(dh);
2757             return;
2758         }
2759 
2760         evp.pkey = EVP_PKEY_new();
2761         EVP_PKEY_assign_DH(evp.pkey, dh);
2762         sec = false;
2763     }
2764 
2765     DLGroup domain() const override
2766     {
2767         const DH     *dh = EVP_PKEY_get0_DH(evp.pkey);
2768         const BIGNUM *bnp, *bng;
2769         DH_get0_pqg(dh, &bnp, nullptr, &bng);
2770         return DLGroup(bn2bi(bnp), bn2bi(bng));
2771     }
2772 
2773     BigInteger y() const override
2774     {
2775         const DH     *dh = EVP_PKEY_get0_DH(evp.pkey);
2776         const BIGNUM *bnpub_key;
2777         DH_get0_key(dh, &bnpub_key, nullptr);
2778         return bn2bi(bnpub_key);
2779     }
2780 
2781     BigInteger x() const override
2782     {
2783         const DH     *dh = EVP_PKEY_get0_DH(evp.pkey);
2784         const BIGNUM *bnpriv_key;
2785         DH_get0_key(dh, nullptr, &bnpriv_key);
2786         return bn2bi(bnpriv_key);
2787     }
2788 
2789 private Q_SLOTS:
2790     void km_finished()
2791     {
2792         DH *dh = keymaker->takeResult();
2793         if (wasBlocking)
2794             delete keymaker;
2795         else
2796             keymaker->deleteLater();
2797         keymaker = nullptr;
2798 
2799         if (dh) {
2800             evp.pkey = EVP_PKEY_new();
2801             EVP_PKEY_assign_DH(evp.pkey, dh);
2802             sec = true;
2803         }
2804 
2805         if (!wasBlocking)
2806             emit finished();
2807     }
2808 };
2809 
2810 //----------------------------------------------------------------------------
2811 // QCA-based RSA_METHOD
2812 //----------------------------------------------------------------------------
2813 
2814 // only supports EMSA3_Raw for now
2815 class QCA_RSA_METHOD
2816 {
2817 public:
2818     RSAPrivateKey key;
2819 
2820     QCA_RSA_METHOD(const RSAPrivateKey &_key, RSA *rsa)
2821     {
2822         key = _key;
2823         RSA_set_method(rsa, rsa_method());
2824         RSA_set_app_data(rsa, this);
2825         BIGNUM *bnn = bi2bn(_key.n());
2826         BIGNUM *bne = bi2bn(_key.e());
2827 
2828         RSA_set0_key(rsa, bnn, bne, nullptr);
2829     }
2830 
2831     RSA_METHOD *rsa_method()
2832     {
2833         static RSA_METHOD *ops = nullptr;
2834 
2835         if (!ops) {
2836             ops = RSA_meth_dup(RSA_get_default_method());
2837             RSA_meth_set_priv_enc(ops, nullptr);      // pkcs11_rsa_encrypt
2838             RSA_meth_set_priv_dec(ops, rsa_priv_dec); // pkcs11_rsa_encrypt
2839             RSA_meth_set_sign(ops, nullptr);
2840             RSA_meth_set_verify(ops, nullptr); // pkcs11_rsa_verify
2841             RSA_meth_set_finish(ops, rsa_finish);
2842         }
2843         return ops;
2844     }
2845 
2846     static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
2847     {
2848         QCA::EncryptionAlgorithm algo;
2849 
2850         if (padding == RSA_PKCS1_PADDING) {
2851             algo = QCA::EME_PKCS1v15;
2852         } else if (padding == RSA_PKCS1_OAEP_PADDING) {
2853             algo = QCA::EME_PKCS1_OAEP;
2854         } else {
2855             RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
2856             return -1;
2857         }
2858 
2859         QCA_RSA_METHOD *self = (QCA_RSA_METHOD *)RSA_get_app_data(rsa);
2860 
2861         QCA::SecureArray input;
2862         input.resize(flen);
2863         memcpy(input.data(), from, input.size());
2864 
2865         QCA::SecureArray output;
2866 
2867         if (self->key.decrypt(input, &output, algo)) {
2868             memcpy(to, output.data(), output.size());
2869             return output.size();
2870         }
2871 
2872         // XXX: An error should be set in this case too.
2873         return -1;
2874     }
2875 
2876     static int rsa_finish(RSA *rsa)
2877     {
2878         QCA_RSA_METHOD *self = (QCA_RSA_METHOD *)RSA_get_app_data(rsa);
2879         delete self;
2880         return 1;
2881     }
2882 };
2883 
2884 static RSA *createFromExisting(const RSAPrivateKey &key)
2885 {
2886     RSA *r = RSA_new();
2887     new QCA_RSA_METHOD(key, r); // will delete itself on RSA_free
2888     return r;
2889 }
2890 
2891 //----------------------------------------------------------------------------
2892 // MyPKeyContext
2893 //----------------------------------------------------------------------------
2894 class MyPKeyContext : public PKeyContext
2895 {
2896     Q_OBJECT
2897 public:
2898     PKeyBase *k;
2899 
2900     MyPKeyContext(Provider *p)
2901         : PKeyContext(p)
2902     {
2903         k = nullptr;
2904     }
2905 
2906     ~MyPKeyContext() override
2907     {
2908         delete k;
2909     }
2910 
2911     Provider::Context *clone() const override
2912     {
2913         MyPKeyContext *c = new MyPKeyContext(*this);
2914         c->k             = (PKeyBase *)k->clone();
2915         return c;
2916     }
2917 
2918     QList<PKey::Type> supportedTypes() const override
2919     {
2920         QList<PKey::Type> list;
2921         list += PKey::RSA;
2922         list += PKey::DSA;
2923         list += PKey::DH;
2924         return list;
2925     }
2926 
2927     QList<PKey::Type> supportedIOTypes() const override
2928     {
2929         QList<PKey::Type> list;
2930         list += PKey::RSA;
2931         list += PKey::DSA;
2932         return list;
2933     }
2934 
2935     QList<PBEAlgorithm> supportedPBEAlgorithms() const override
2936     {
2937         QList<PBEAlgorithm> list;
2938         list += PBES2_DES_SHA1;
2939         list += PBES2_TripleDES_SHA1;
2940         return list;
2941     }
2942 
2943     PKeyBase *key() override
2944     {
2945         return k;
2946     }
2947 
2948     const PKeyBase *key() const override
2949     {
2950         return k;
2951     }
2952 
2953     void setKey(PKeyBase *key) override
2954     {
2955         k = key;
2956     }
2957 
2958     bool importKey(const PKeyBase *key) override
2959     {
2960         Q_UNUSED(key);
2961         return false;
2962     }
2963 
2964     EVP_PKEY *get_pkey() const
2965     {
2966         PKey::Type t = k->type();
2967         if (t == PKey::RSA)
2968             return static_cast<RSAKey *>(k)->evp.pkey;
2969         else if (t == PKey::DSA)
2970             return static_cast<DSAKey *>(k)->evp.pkey;
2971         else
2972             return static_cast<DHKey *>(k)->evp.pkey;
2973     }
2974 
2975     PKeyBase *pkeyToBase(EVP_PKEY *pkey, bool sec) const
2976     {
2977         PKeyBase *nk        = nullptr;
2978         int       pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
2979         if (pkey_type == EVP_PKEY_RSA) {
2980             RSAKey *c   = new RSAKey(provider());
2981             c->evp.pkey = pkey;
2982             c->sec      = sec;
2983             nk          = c;
2984         } else if (pkey_type == EVP_PKEY_DSA) {
2985             DSAKey *c   = new DSAKey(provider());
2986             c->evp.pkey = pkey;
2987             c->sec      = sec;
2988             nk          = c;
2989         } else if (pkey_type == EVP_PKEY_DH) {
2990             DHKey *c    = new DHKey(provider());
2991             c->evp.pkey = pkey;
2992             c->sec      = sec;
2993             nk          = c;
2994         } else {
2995             EVP_PKEY_free(pkey);
2996         }
2997         return nk;
2998     }
2999 
3000     QByteArray publicToDER() const override
3001     {
3002         EVP_PKEY *pkey = get_pkey();
3003 
3004         int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
3005 
3006         // OpenSSL does not have DH import/export support
3007         if (pkey_type == EVP_PKEY_DH)
3008             return QByteArray();
3009 
3010         BIO *bo = BIO_new(BIO_s_mem());
3011         i2d_PUBKEY_bio(bo, pkey);
3012         const QByteArray buf = bio2ba(bo);
3013         return buf;
3014     }
3015 
3016     QString publicToPEM() const override
3017     {
3018         EVP_PKEY *pkey = get_pkey();
3019 
3020         int pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
3021 
3022         // OpenSSL does not have DH import/export support
3023         if (pkey_type == EVP_PKEY_DH)
3024             return QString();
3025 
3026         BIO *bo = BIO_new(BIO_s_mem());
3027         PEM_write_bio_PUBKEY(bo, pkey);
3028         const QByteArray buf = bio2ba(bo);
3029         return QString::fromLatin1(buf);
3030     }
3031 
3032     ConvertResult publicFromDER(const QByteArray &in) override
3033     {
3034         delete k;
3035         k = nullptr;
3036 
3037         BIO *bi = BIO_new(BIO_s_mem());
3038         BIO_write(bi, in.data(), in.size());
3039         EVP_PKEY *pkey = d2i_PUBKEY_bio(bi, nullptr);
3040         BIO_free(bi);
3041 
3042         if (!pkey)
3043             return ErrorDecode;
3044 
3045         k = pkeyToBase(pkey, false);
3046         if (k)
3047             return ConvertGood;
3048         else
3049             return ErrorDecode;
3050     }
3051 
3052     ConvertResult publicFromPEM(const QString &s) override
3053     {
3054         delete k;
3055         k = nullptr;
3056 
3057         const QByteArray in = s.toLatin1();
3058         BIO             *bi = BIO_new(BIO_s_mem());
3059         BIO_write(bi, in.data(), in.size());
3060         EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bi, nullptr, passphrase_cb, nullptr);
3061         BIO_free(bi);
3062 
3063         if (!pkey)
3064             return ErrorDecode;
3065 
3066         k = pkeyToBase(pkey, false);
3067         if (k)
3068             return ConvertGood;
3069         else
3070             return ErrorDecode;
3071     }
3072 
3073     SecureArray privateToDER(const SecureArray &passphrase, PBEAlgorithm pbe) const override
3074     {
3075         // if(pbe == PBEDefault)
3076         //  pbe = PBES2_TripleDES_SHA1;
3077 
3078         const EVP_CIPHER *cipher = nullptr;
3079         if (pbe == PBES2_TripleDES_SHA1)
3080             cipher = EVP_des_ede3_cbc();
3081         else if (pbe == PBES2_DES_SHA1)
3082             cipher = EVP_des_cbc();
3083 
3084         if (!cipher)
3085             return SecureArray();
3086 
3087         EVP_PKEY *pkey      = get_pkey();
3088         int       pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
3089 
3090         // OpenSSL does not have DH import/export support
3091         if (pkey_type == EVP_PKEY_DH)
3092             return SecureArray();
3093 
3094         BIO *bo = BIO_new(BIO_s_mem());
3095         if (!passphrase.isEmpty())
3096             i2d_PKCS8PrivateKey_bio(bo, pkey, cipher, nullptr, 0, nullptr, (void *)passphrase.data());
3097         else
3098             i2d_PKCS8PrivateKey_bio(bo, pkey, nullptr, nullptr, 0, nullptr, nullptr);
3099         SecureArray buf = bio2buf(bo);
3100         return buf;
3101     }
3102 
3103     QString privateToPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const override
3104     {
3105         // if(pbe == PBEDefault)
3106         //  pbe = PBES2_TripleDES_SHA1;
3107 
3108         const EVP_CIPHER *cipher = nullptr;
3109         if (pbe == PBES2_TripleDES_SHA1)
3110             cipher = EVP_des_ede3_cbc();
3111         else if (pbe == PBES2_DES_SHA1)
3112             cipher = EVP_des_cbc();
3113 
3114         if (!cipher)
3115             return QString();
3116 
3117         EVP_PKEY *pkey      = get_pkey();
3118         int       pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
3119 
3120         // OpenSSL does not have DH import/export support
3121         if (pkey_type == EVP_PKEY_DH)
3122             return QString();
3123 
3124         BIO *bo = BIO_new(BIO_s_mem());
3125         if (!passphrase.isEmpty())
3126             PEM_write_bio_PKCS8PrivateKey(bo, pkey, cipher, nullptr, 0, nullptr, (void *)passphrase.data());
3127         else
3128             PEM_write_bio_PKCS8PrivateKey(bo, pkey, nullptr, nullptr, 0, nullptr, nullptr);
3129         SecureArray buf = bio2buf(bo);
3130         return QString::fromLatin1(buf.toByteArray());
3131     }
3132 
3133     ConvertResult privateFromDER(const SecureArray &in, const SecureArray &passphrase) override
3134     {
3135         delete k;
3136         k = nullptr;
3137 
3138         EVP_PKEY *pkey;
3139         if (!passphrase.isEmpty())
3140             pkey = qca_d2i_PKCS8PrivateKey(in, nullptr, nullptr, (void *)passphrase.data());
3141         else
3142             pkey = qca_d2i_PKCS8PrivateKey(in, nullptr, passphrase_cb, nullptr);
3143 
3144         if (!pkey)
3145             return ErrorDecode;
3146 
3147         k = pkeyToBase(pkey, true);
3148         if (k)
3149             return ConvertGood;
3150         else
3151             return ErrorDecode;
3152     }
3153 
3154     ConvertResult privateFromPEM(const QString &s, const SecureArray &passphrase) override
3155     {
3156         delete k;
3157         k = nullptr;
3158 
3159         const QByteArray in = s.toLatin1();
3160         BIO             *bi = BIO_new(BIO_s_mem());
3161         BIO_write(bi, in.data(), in.size());
3162         EVP_PKEY *pkey;
3163         if (!passphrase.isEmpty())
3164             pkey = PEM_read_bio_PrivateKey(bi, nullptr, nullptr, (void *)passphrase.data());
3165         else
3166             pkey = PEM_read_bio_PrivateKey(bi, nullptr, passphrase_cb, nullptr);
3167         BIO_free(bi);
3168 
3169         if (!pkey)
3170             return ErrorDecode;
3171 
3172         k = pkeyToBase(pkey, true);
3173         if (k)
3174             return ConvertGood;
3175         else
3176             return ErrorDecode;
3177     }
3178 };
3179 
3180 //----------------------------------------------------------------------------
3181 // MyCertContext
3182 //----------------------------------------------------------------------------
3183 class X509Item
3184 {
3185 public:
3186     X509     *cert;
3187     X509_REQ *req;
3188     X509_CRL *crl;
3189 
3190     enum Type
3191     {
3192         TypeCert,
3193         TypeReq,
3194         TypeCRL
3195     };
3196 
3197     X509Item()
3198     {
3199         cert = nullptr;
3200         req  = nullptr;
3201         crl  = nullptr;
3202     }
3203 
3204     X509Item(const X509Item &from)
3205     {
3206         cert  = nullptr;
3207         req   = nullptr;
3208         crl   = nullptr;
3209         *this = from;
3210     }
3211 
3212     ~X509Item()
3213     {
3214         reset();
3215     }
3216 
3217     X509Item &operator=(const X509Item &from)
3218     {
3219         if (this != &from) {
3220             reset();
3221             cert = from.cert;
3222             req  = from.req;
3223             crl  = from.crl;
3224 
3225             if (cert)
3226                 X509_up_ref(cert);
3227             if (req) {
3228                 // Not exposed, so copy
3229                 req = X509_REQ_dup(req);
3230             }
3231             if (crl)
3232                 X509_CRL_up_ref(crl);
3233         }
3234 
3235         return *this;
3236     }
3237 
3238     void reset()
3239     {
3240         if (cert) {
3241             X509_free(cert);
3242             cert = nullptr;
3243         }
3244         if (req) {
3245             X509_REQ_free(req);
3246             req = nullptr;
3247         }
3248         if (crl) {
3249             X509_CRL_free(crl);
3250             crl = nullptr;
3251         }
3252     }
3253 
3254     bool isNull() const
3255     {
3256         return (!cert && !req && !crl);
3257     }
3258 
3259     QByteArray toDER() const
3260     {
3261         BIO *bo = BIO_new(BIO_s_mem());
3262         if (cert)
3263             i2d_X509_bio(bo, cert);
3264         else if (req)
3265             i2d_X509_REQ_bio(bo, req);
3266         else if (crl)
3267             i2d_X509_CRL_bio(bo, crl);
3268         const QByteArray buf = bio2ba(bo);
3269         return buf;
3270     }
3271 
3272     QString toPEM() const
3273     {
3274         BIO *bo = BIO_new(BIO_s_mem());
3275         if (cert)
3276             PEM_write_bio_X509(bo, cert);
3277         else if (req)
3278             PEM_write_bio_X509_REQ(bo, req);
3279         else if (crl)
3280             PEM_write_bio_X509_CRL(bo, crl);
3281         const QByteArray buf = bio2ba(bo);
3282         return QString::fromLatin1(buf);
3283     }
3284 
3285     ConvertResult fromDER(const QByteArray &in, Type t)
3286     {
3287         reset();
3288 
3289         BIO *bi = BIO_new(BIO_s_mem());
3290         BIO_write(bi, in.data(), in.size());
3291 
3292         if (t == TypeCert)
3293             cert = d2i_X509_bio(bi, nullptr);
3294         else if (t == TypeReq)
3295             req = d2i_X509_REQ_bio(bi, nullptr);
3296         else if (t == TypeCRL)
3297             crl = d2i_X509_CRL_bio(bi, nullptr);
3298 
3299         BIO_free(bi);
3300 
3301         if (isNull())
3302             return ErrorDecode;
3303 
3304         return ConvertGood;
3305     }
3306 
3307     ConvertResult fromPEM(const QString &s, Type t)
3308     {
3309         reset();
3310 
3311         const QByteArray in = s.toLatin1();
3312         BIO             *bi = BIO_new(BIO_s_mem());
3313         BIO_write(bi, in.data(), in.size());
3314 
3315         if (t == TypeCert)
3316             cert = PEM_read_bio_X509(bi, nullptr, passphrase_cb, nullptr);
3317         else if (t == TypeReq)
3318             req = PEM_read_bio_X509_REQ(bi, nullptr, passphrase_cb, nullptr);
3319         else if (t == TypeCRL)
3320             crl = PEM_read_bio_X509_CRL(bi, nullptr, passphrase_cb, nullptr);
3321 
3322         BIO_free(bi);
3323 
3324         if (isNull())
3325             return ErrorDecode;
3326 
3327         return ConvertGood;
3328     }
3329 };
3330 
3331 // (taken from kdelibs) -- Justin
3332 //
3333 // This code is mostly taken from OpenSSL v0.9.5a
3334 // by Eric Young
3335 QDateTime ASN1_UTCTIME_QDateTime(const ASN1_UTCTIME *tm, int *isGmt)
3336 {
3337     QDateTime qdt;
3338     char     *v;
3339     int       gmt = 0;
3340     int       i;
3341     int       y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
3342     QDate     qdate;
3343     QTime     qtime;
3344 
3345     i = tm->length;
3346     v = (char *)tm->data;
3347 
3348     if (i < 10)
3349         goto auq_err;
3350     if (v[i - 1] == 'Z')
3351         gmt = 1;
3352     for (i = 0; i < 10; i++)
3353         if ((v[i] > '9') || (v[i] < '0'))
3354             goto auq_err;
3355     y = (v[0] - '0') * 10 + (v[1] - '0');
3356     if (y < 50)
3357         y += 100;
3358     M = (v[2] - '0') * 10 + (v[3] - '0');
3359     if ((M > 12) || (M < 1))
3360         goto auq_err;
3361     d = (v[4] - '0') * 10 + (v[5] - '0');
3362     h = (v[6] - '0') * 10 + (v[7] - '0');
3363     m = (v[8] - '0') * 10 + (v[9] - '0');
3364     if ((v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
3365         s = (v[10] - '0') * 10 + (v[11] - '0');
3366 
3367     // localize the date and display it.
3368     qdate.setDate(y + 1900, M, d);
3369     qtime.setHMS(h, m, s);
3370     qdt.setDate(qdate);
3371     qdt.setTime(qtime);
3372     if (gmt)
3373         qdt.setTimeSpec(Qt::UTC);
3374 auq_err:
3375     if (isGmt)
3376         *isGmt = gmt;
3377     return qdt;
3378 }
3379 
3380 class MyCertContext;
3381 static bool sameChain(STACK_OF(X509) * ossl, const QList<const MyCertContext *> &qca);
3382 
3383 // TODO: support read/write of multiple info values with the same name
3384 class MyCertContext : public CertContext
3385 {
3386     Q_OBJECT
3387 public:
3388     X509Item         item;
3389     CertContextProps _props;
3390 
3391     MyCertContext(Provider *p)
3392         : CertContext(p)
3393     {
3394         // printf("[%p] ** created\n", this);
3395     }
3396 
3397     MyCertContext(const MyCertContext &from)
3398         : CertContext(from)
3399         , item(from.item)
3400         , _props(from._props)
3401     {
3402         // printf("[%p] ** created as copy (from [%p])\n", this, &from);
3403     }
3404 
3405     ~MyCertContext() override
3406     {
3407         // printf("[%p] ** deleted\n", this);
3408     }
3409 
3410     Provider::Context *clone() const override
3411     {
3412         return new MyCertContext(*this);
3413     }
3414 
3415     QByteArray toDER() const override
3416     {
3417         return item.toDER();
3418     }
3419 
3420     QString toPEM() const override
3421     {
3422         return item.toPEM();
3423     }
3424 
3425     ConvertResult fromDER(const QByteArray &a) override
3426     {
3427         _props          = CertContextProps();
3428         ConvertResult r = item.fromDER(a, X509Item::TypeCert);
3429         if (r == ConvertGood)
3430             make_props();
3431         return r;
3432     }
3433 
3434     ConvertResult fromPEM(const QString &s) override
3435     {
3436         _props          = CertContextProps();
3437         ConvertResult r = item.fromPEM(s, X509Item::TypeCert);
3438         if (r == ConvertGood)
3439             make_props();
3440         return r;
3441     }
3442 
3443     void fromX509(X509 *x)
3444     {
3445         X509_up_ref(x);
3446         item.cert = x;
3447         make_props();
3448     }
3449 
3450     bool createSelfSigned(const CertificateOptions &opts, const PKeyContext &priv) override
3451     {
3452         _props = CertContextProps();
3453         item.reset();
3454 
3455         CertificateInfo info = opts.info();
3456 
3457         // Note: removing default constraints, let the app choose these if it wants
3458         Constraints constraints = opts.constraints();
3459         // constraints - logic from Botan
3460         /*Constraints constraints;
3461         if(opts.isCA())
3462         {
3463             constraints += KeyCertificateSign;
3464             constraints += CRLSign;
3465         }
3466         else
3467             constraints = find_constraints(priv, opts.constraints());*/
3468 
3469         EVP_PKEY       *pk = static_cast<const MyPKeyContext *>(&priv)->get_pkey();
3470         X509_EXTENSION *ex;
3471 
3472         const EVP_MD *md;
3473         if (priv.key()->type() == PKey::RSA || priv.key()->type() == PKey::DSA)
3474             md = EVP_sha256();
3475         else
3476             return false;
3477 
3478         // create
3479         X509 *x = X509_new();
3480         X509_set_version(x, 2);
3481 
3482         // serial
3483         BIGNUM *bn = bi2bn(opts.serialNumber());
3484         BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(x));
3485         BN_free(bn);
3486 
3487         // validity period
3488         ASN1_TIME_set(X509_get_notBefore(x), opts.notValidBefore().toSecsSinceEpoch());
3489         ASN1_TIME_set(X509_get_notAfter(x), opts.notValidAfter().toSecsSinceEpoch());
3490 
3491         // public key
3492         X509_set_pubkey(x, pk);
3493 
3494         // subject
3495         X509_NAME *name = new_cert_name(info);
3496         X509_set_subject_name(x, name);
3497 
3498         // issuer == subject
3499         X509_set_issuer_name(x, name);
3500 
3501         // subject key id
3502         ex = new_subject_key_id(x);
3503         {
3504             X509_add_ext(x, ex, -1);
3505             X509_EXTENSION_free(ex);
3506         }
3507 
3508         // CA mode
3509         ex = new_basic_constraints(opts.isCA(), opts.pathLimit());
3510         if (ex) {
3511             X509_add_ext(x, ex, -1);
3512             X509_EXTENSION_free(ex);
3513         }
3514 
3515         // subject alt name
3516         ex = new_cert_subject_alt_name(info);
3517         if (ex) {
3518             X509_add_ext(x, ex, -1);
3519             X509_EXTENSION_free(ex);
3520         }
3521 
3522         // key usage
3523         ex = new_cert_key_usage(constraints);
3524         if (ex) {
3525             X509_add_ext(x, ex, -1);
3526             X509_EXTENSION_free(ex);
3527         }
3528 
3529         // extended key usage
3530         ex = new_cert_ext_key_usage(constraints);
3531         if (ex) {
3532             X509_add_ext(x, ex, -1);
3533             X509_EXTENSION_free(ex);
3534         }
3535 
3536         // policies
3537         ex = new_cert_policies(opts.policies());
3538         if (ex) {
3539             X509_add_ext(x, ex, -1);
3540             X509_EXTENSION_free(ex);
3541         }
3542 
3543         // finished
3544         X509_sign(x, pk, md);
3545 
3546         item.cert = x;
3547         make_props();
3548         return true;
3549     }
3550 
3551     const CertContextProps *props() const override
3552     {
3553         // printf("[%p] grabbing props\n", this);
3554         return &_props;
3555     }
3556 
3557     bool compare(const CertContext *other) const override
3558     {
3559         const CertContextProps *a = &_props;
3560         const CertContextProps *b = other->props();
3561 
3562         PublicKey    akey, bkey;
3563         PKeyContext *ac = subjectPublicKey();
3564         akey.change(ac);
3565         PKeyContext *bc = other->subjectPublicKey();
3566         bkey.change(bc);
3567 
3568         // logic from Botan
3569         if (a->sig != b->sig || a->sigalgo != b->sigalgo || akey != bkey)
3570             return false;
3571 
3572         if (a->issuer != b->issuer || a->subject != b->subject)
3573             return false;
3574         if (a->serial != b->serial || a->version != b->version)
3575             return false;
3576         if (a->start != b->start || a->end != b->end)
3577             return false;
3578 
3579         return true;
3580     }
3581 
3582     // does a new
3583     PKeyContext *subjectPublicKey() const override
3584     {
3585         MyPKeyContext *kc   = new MyPKeyContext(provider());
3586         EVP_PKEY      *pkey = X509_get_pubkey(item.cert);
3587         PKeyBase      *kb   = kc->pkeyToBase(pkey, false);
3588         kc->setKey(kb);
3589         return kc;
3590     }
3591 
3592     bool isIssuerOf(const CertContext *other) const override
3593     {
3594         // to check a single issuer, we make a list of 1
3595         STACK_OF(X509) *untrusted_list = sk_X509_new_null();
3596 
3597         const MyCertContext *our_cc = this;
3598         X509                *x      = our_cc->item.cert;
3599         X509_up_ref(x);
3600         sk_X509_push(untrusted_list, x);
3601 
3602         const MyCertContext *other_cc = static_cast<const MyCertContext *>(other);
3603         X509                *ox       = other_cc->item.cert;
3604 
3605         X509_STORE *store = X509_STORE_new();
3606 
3607         X509_STORE_CTX *ctx = X509_STORE_CTX_new();
3608         X509_STORE_CTX_init(ctx, store, ox, untrusted_list);
3609 
3610         // we don't care about the verify result here
3611         X509_verify_cert(ctx);
3612 
3613         // grab the chain, which may not be fully populated
3614         STACK_OF(X509) *chain = X509_STORE_CTX_get_chain(ctx);
3615 
3616         bool ok = false;
3617 
3618         // chain should be exactly 2 items
3619         QList<const MyCertContext *> expected;
3620         expected += other_cc;
3621         expected += our_cc;
3622         if (chain && sameChain(chain, expected))
3623             ok = true;
3624 
3625         // cleanup
3626         X509_STORE_CTX_free(ctx);
3627         X509_STORE_free(store);
3628         sk_X509_pop_free(untrusted_list, X509_free);
3629 
3630         return ok;
3631     }
3632 
3633     // implemented later because it depends on MyCRLContext
3634     Validity validate(const QList<CertContext *> &trusted,
3635                       const QList<CertContext *> &untrusted,
3636                       const QList<CRLContext *>  &crls,
3637                       UsageMode                   u,
3638                       ValidateFlags               vf) const override;
3639 
3640     Validity validate_chain(const QList<CertContext *> &chain,
3641                             const QList<CertContext *> &trusted,
3642                             const QList<CRLContext *>  &crls,
3643                             UsageMode                   u,
3644                             ValidateFlags               vf) const override;
3645 
3646     void make_props()
3647     {
3648         X509            *x = item.cert;
3649         CertContextProps p;
3650 
3651         p.version = X509_get_version(x);
3652 
3653         ASN1_INTEGER *ai = X509_get_serialNumber(x);
3654         if (ai) {
3655             char   *rep = i2s_ASN1_INTEGER(nullptr, ai);
3656             QString str = QString::fromLatin1(rep);
3657             OPENSSL_free(rep);
3658             p.serial.fromString(str);
3659         }
3660 
3661         p.start = ASN1_UTCTIME_QDateTime(X509_get_notBefore(x), nullptr);
3662         p.end   = ASN1_UTCTIME_QDateTime(X509_get_notAfter(x), nullptr);
3663 
3664         CertificateInfo subject, issuer;
3665 
3666         subject = get_cert_name(X509_get_subject_name(x));
3667         issuer  = get_cert_name(X509_get_issuer_name(x));
3668 
3669         p.isSelfSigned = (X509_V_OK == X509_check_issued(x, x));
3670 
3671         p.isCA      = false;
3672         p.pathLimit = 0;
3673         int pos     = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
3674         if (pos != -1) {
3675             X509_EXTENSION *ex = X509_get_ext(x, pos);
3676             if (ex)
3677                 get_basic_constraints(ex, &p.isCA, &p.pathLimit);
3678         }
3679 
3680         pos = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
3681         if (pos != -1) {
3682             X509_EXTENSION *ex = X509_get_ext(x, pos);
3683             if (ex)
3684                 subject.unite(get_cert_alt_name(ex));
3685         }
3686 
3687         pos = X509_get_ext_by_NID(x, NID_issuer_alt_name, -1);
3688         if (pos != -1) {
3689             X509_EXTENSION *ex = X509_get_ext(x, pos);
3690             if (ex)
3691                 issuer.unite(get_cert_alt_name(ex));
3692         }
3693 
3694         pos = X509_get_ext_by_NID(x, NID_key_usage, -1);
3695         if (pos != -1) {
3696             X509_EXTENSION *ex = X509_get_ext(x, pos);
3697             if (ex)
3698                 p.constraints = get_cert_key_usage(ex);
3699         }
3700 
3701         pos = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
3702         if (pos != -1) {
3703             X509_EXTENSION *ex = X509_get_ext(x, pos);
3704             if (ex)
3705                 p.constraints += get_cert_ext_key_usage(ex);
3706         }
3707 
3708         pos = X509_get_ext_by_NID(x, NID_certificate_policies, -1);
3709         if (pos != -1) {
3710             X509_EXTENSION *ex = X509_get_ext(x, pos);
3711             if (ex)
3712                 p.policies = get_cert_policies(ex);
3713         }
3714 
3715         const ASN1_BIT_STRING *signature;
3716 
3717         X509_get0_signature(&signature, nullptr, x);
3718         if (signature) {
3719             p.sig = QByteArray(signature->length, 0);
3720             for (int i = 0; i < signature->length; i++)
3721                 p.sig[i] = signature->data[i];
3722         }
3723 
3724         switch (X509_get_signature_nid(x)) {
3725         case NID_sha1WithRSAEncryption:
3726             p.sigalgo = QCA::EMSA3_SHA1;
3727             break;
3728         case NID_md5WithRSAEncryption:
3729             p.sigalgo = QCA::EMSA3_MD5;
3730             break;
3731 #ifdef HAVE_OPENSSL_MD2
3732         case NID_md2WithRSAEncryption:
3733             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_MD2 : QCA::SignatureUnknown;
3734             break;
3735 #endif
3736         case NID_ripemd160WithRSA:
3737             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_RIPEMD160 : QCA::SignatureUnknown;
3738             break;
3739         case NID_dsaWithSHA1:
3740             p.sigalgo = QCA::EMSA1_SHA1;
3741             break;
3742         case NID_sha224WithRSAEncryption:
3743             p.sigalgo = QCA::EMSA3_SHA224;
3744             break;
3745         case NID_sha256WithRSAEncryption:
3746             p.sigalgo = QCA::EMSA3_SHA256;
3747             break;
3748         case NID_sha384WithRSAEncryption:
3749             p.sigalgo = QCA::EMSA3_SHA384;
3750             break;
3751         case NID_sha512WithRSAEncryption:
3752             p.sigalgo = QCA::EMSA3_SHA512;
3753             break;
3754         default:
3755             qDebug() << "Unknown signature value: " << X509_get_signature_nid(x);
3756             p.sigalgo = QCA::SignatureUnknown;
3757         }
3758 
3759         pos = X509_get_ext_by_NID(x, NID_subject_key_identifier, -1);
3760         if (pos != -1) {
3761             X509_EXTENSION *ex = X509_get_ext(x, pos);
3762             if (ex)
3763                 p.subjectId += get_cert_subject_key_id(ex);
3764         }
3765 
3766         pos = X509_get_ext_by_NID(x, NID_authority_key_identifier, -1);
3767         if (pos != -1) {
3768             X509_EXTENSION *ex = X509_get_ext(x, pos);
3769             if (ex)
3770                 p.issuerId += get_cert_issuer_key_id(ex);
3771         }
3772 
3773         // FIXME: super hack
3774         CertificateOptions opts;
3775         opts.setInfo(subject);
3776         p.subject = opts.infoOrdered();
3777         opts.setInfo(issuer);
3778         p.issuer = opts.infoOrdered();
3779 
3780         _props = p;
3781         // printf("[%p] made props: [%s]\n", this, _props.subject[CommonName].toLatin1().data());
3782     }
3783 };
3784 
3785 bool sameChain(STACK_OF(X509) * ossl, const QList<const MyCertContext *> &qca)
3786 {
3787     if (sk_X509_num(ossl) != qca.count())
3788         return false;
3789 
3790     for (int n = 0; n < sk_X509_num(ossl); ++n) {
3791         X509 *a = sk_X509_value(ossl, n);
3792         X509 *b = qca[n]->item.cert;
3793         if (X509_cmp(a, b) != 0)
3794             return false;
3795     }
3796 
3797     return true;
3798 }
3799 
3800 //----------------------------------------------------------------------------
3801 // MyCAContext
3802 //----------------------------------------------------------------------------
3803 // Thanks to Pascal Patry
3804 class MyCAContext : public CAContext
3805 {
3806     Q_OBJECT
3807 public:
3808     X509Item       caCert;
3809     MyPKeyContext *privateKey;
3810 
3811     MyCAContext(Provider *p)
3812         : CAContext(p)
3813     {
3814         privateKey = nullptr;
3815     }
3816 
3817     MyCAContext(const MyCAContext &from)
3818         : CAContext(from)
3819         , caCert(from.caCert)
3820     {
3821         privateKey = static_cast<MyPKeyContext *>(from.privateKey->clone());
3822     }
3823 
3824     ~MyCAContext() override
3825     {
3826         delete privateKey;
3827     }
3828 
3829     CertContext *certificate() const override
3830     {
3831         MyCertContext *cert = new MyCertContext(provider());
3832 
3833         cert->fromX509(caCert.cert);
3834         return cert;
3835     }
3836 
3837     CertContext *createCertificate(const PKeyContext &pub, const CertificateOptions &opts) const override
3838     {
3839         // TODO: implement
3840         Q_UNUSED(pub)
3841         Q_UNUSED(opts)
3842         return nullptr;
3843     }
3844 
3845     CRLContext *createCRL(const QDateTime &nextUpdate) const override
3846     {
3847         // TODO: implement
3848         Q_UNUSED(nextUpdate)
3849         return nullptr;
3850     }
3851 
3852     void setup(const CertContext &cert, const PKeyContext &priv) override
3853     {
3854         caCert = static_cast<const MyCertContext &>(cert).item;
3855         delete privateKey;
3856         privateKey = nullptr;
3857         privateKey = static_cast<MyPKeyContext *>(priv.clone());
3858     }
3859 
3860     CertContext *signRequest(const CSRContext &req, const QDateTime &notValidAfter) const override
3861     {
3862         MyCertContext          *cert  = nullptr;
3863         const EVP_MD           *md    = nullptr;
3864         X509                   *x     = nullptr;
3865         const CertContextProps &props = *req.props();
3866         CertificateOptions      subjectOpts;
3867         X509_NAME              *subjectName = nullptr;
3868         X509_EXTENSION         *ex          = nullptr;
3869 
3870         if (privateKey->key()->type() == PKey::RSA)
3871             md = EVP_sha1();
3872         else if (privateKey->key()->type() == PKey::DSA)
3873             md = EVP_sha1();
3874         else
3875             return nullptr;
3876 
3877         cert = new MyCertContext(provider());
3878 
3879         subjectOpts.setInfoOrdered(props.subject);
3880         subjectName = new_cert_name(subjectOpts.info());
3881 
3882         // create
3883         x = X509_new();
3884         X509_set_version(x, 2);
3885 
3886         // serial
3887         BIGNUM *bn = bi2bn(props.serial);
3888         BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(x));
3889         BN_free(bn);
3890 
3891         // validity period
3892         ASN1_TIME_set(X509_get_notBefore(x), QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
3893         ASN1_TIME_set(X509_get_notAfter(x), notValidAfter.toSecsSinceEpoch());
3894 
3895         X509_set_pubkey(x, static_cast<const MyPKeyContext *>(req.subjectPublicKey())->get_pkey());
3896         X509_set_subject_name(x, subjectName);
3897         X509_set_issuer_name(x, X509_get_subject_name(caCert.cert));
3898 
3899         // subject key id
3900         ex = new_subject_key_id(x);
3901         {
3902             X509_add_ext(x, ex, -1);
3903             X509_EXTENSION_free(ex);
3904         }
3905 
3906         // CA mode
3907         ex = new_basic_constraints(props.isCA, props.pathLimit);
3908         if (ex) {
3909             X509_add_ext(x, ex, -1);
3910             X509_EXTENSION_free(ex);
3911         }
3912 
3913         // subject alt name
3914         ex = new_cert_subject_alt_name(subjectOpts.info());
3915         if (ex) {
3916             X509_add_ext(x, ex, -1);
3917             X509_EXTENSION_free(ex);
3918         }
3919 
3920         // key usage
3921         ex = new_cert_key_usage(props.constraints);
3922         if (ex) {
3923             X509_add_ext(x, ex, -1);
3924             X509_EXTENSION_free(ex);
3925         }
3926 
3927         // extended key usage
3928         ex = new_cert_ext_key_usage(props.constraints);
3929         if (ex) {
3930             X509_add_ext(x, ex, -1);
3931             X509_EXTENSION_free(ex);
3932         }
3933 
3934         // policies
3935         ex = new_cert_policies(props.policies);
3936         if (ex) {
3937             X509_add_ext(x, ex, -1);
3938             X509_EXTENSION_free(ex);
3939         }
3940 
3941         if (!X509_sign(x, privateKey->get_pkey(), md)) {
3942             X509_free(x);
3943             delete cert;
3944             return nullptr;
3945         }
3946 
3947         cert->fromX509(x);
3948         X509_free(x);
3949         return cert;
3950     }
3951 
3952     CRLContext *
3953     updateCRL(const CRLContext &crl, const QList<CRLEntry> &entries, const QDateTime &nextUpdate) const override
3954     {
3955         // TODO: implement
3956         Q_UNUSED(crl)
3957         Q_UNUSED(entries)
3958         Q_UNUSED(nextUpdate)
3959         return nullptr;
3960     }
3961 
3962     Provider::Context *clone() const override
3963     {
3964         return new MyCAContext(*this);
3965     }
3966 };
3967 
3968 //----------------------------------------------------------------------------
3969 // MyCSRContext
3970 //----------------------------------------------------------------------------
3971 class MyCSRContext : public CSRContext
3972 {
3973     Q_OBJECT
3974 public:
3975     X509Item         item;
3976     CertContextProps _props;
3977 
3978     MyCSRContext(Provider *p)
3979         : CSRContext(p)
3980     {
3981     }
3982 
3983     MyCSRContext(const MyCSRContext &from)
3984         : CSRContext(from)
3985         , item(from.item)
3986         , _props(from._props)
3987     {
3988     }
3989 
3990     Provider::Context *clone() const override
3991     {
3992         return new MyCSRContext(*this);
3993     }
3994 
3995     QByteArray toDER() const override
3996     {
3997         return item.toDER();
3998     }
3999 
4000     QString toPEM() const override
4001     {
4002         return item.toPEM();
4003     }
4004 
4005     ConvertResult fromDER(const QByteArray &a) override
4006     {
4007         _props          = CertContextProps();
4008         ConvertResult r = item.fromDER(a, X509Item::TypeReq);
4009         if (r == ConvertGood)
4010             make_props();
4011         return r;
4012     }
4013 
4014     ConvertResult fromPEM(const QString &s) override
4015     {
4016         _props          = CertContextProps();
4017         ConvertResult r = item.fromPEM(s, X509Item::TypeReq);
4018         if (r == ConvertGood)
4019             make_props();
4020         return r;
4021     }
4022 
4023     bool canUseFormat(CertificateRequestFormat f) const override
4024     {
4025         if (f == PKCS10)
4026             return true;
4027         return false;
4028     }
4029 
4030     bool createRequest(const CertificateOptions &opts, const PKeyContext &priv) override
4031     {
4032         _props = CertContextProps();
4033         item.reset();
4034 
4035         CertificateInfo info = opts.info();
4036 
4037         // Note: removing default constraints, let the app choose these if it wants
4038         Constraints constraints = opts.constraints();
4039         // constraints - logic from Botan
4040         /*Constraints constraints;
4041         if(opts.isCA())
4042         {
4043             constraints += KeyCertificateSign;
4044             constraints += CRLSign;
4045         }
4046         else
4047             constraints = find_constraints(priv, opts.constraints());*/
4048 
4049         EVP_PKEY       *pk = static_cast<const MyPKeyContext *>(&priv)->get_pkey();
4050         X509_EXTENSION *ex;
4051 
4052         const EVP_MD *md;
4053         if (priv.key()->type() == PKey::RSA)
4054             md = EVP_sha1();
4055         else if (priv.key()->type() == PKey::DSA)
4056             md = EVP_sha1();
4057         else
4058             return false;
4059 
4060         // create
4061         X509_REQ *x = X509_REQ_new();
4062 
4063         // public key
4064         X509_REQ_set_pubkey(x, pk);
4065 
4066         // subject
4067         X509_NAME *name = new_cert_name(info);
4068         X509_REQ_set_subject_name(x, name);
4069 
4070         // challenge
4071         const QByteArray cs = opts.challenge().toLatin1();
4072         if (!cs.isEmpty())
4073             X509_REQ_add1_attr_by_NID(
4074                 x, NID_pkcs9_challengePassword, MBSTRING_UTF8, (const unsigned char *)cs.data(), -1);
4075 
4076         STACK_OF(X509_EXTENSION) *exts = sk_X509_EXTENSION_new_null();
4077 
4078         // CA mode
4079         ex = new_basic_constraints(opts.isCA(), opts.pathLimit());
4080         if (ex)
4081             sk_X509_EXTENSION_push(exts, ex);
4082 
4083         // subject alt name
4084         ex = new_cert_subject_alt_name(info);
4085         if (ex)
4086             sk_X509_EXTENSION_push(exts, ex);
4087 
4088         // key usage
4089         ex = new_cert_key_usage(constraints);
4090         if (ex)
4091             sk_X509_EXTENSION_push(exts, ex);
4092 
4093         // extended key usage
4094         ex = new_cert_ext_key_usage(constraints);
4095         if (ex)
4096             sk_X509_EXTENSION_push(exts, ex);
4097 
4098         // policies
4099         ex = new_cert_policies(opts.policies());
4100         if (ex)
4101             sk_X509_EXTENSION_push(exts, ex);
4102 
4103         if (sk_X509_EXTENSION_num(exts) > 0)
4104             X509_REQ_add_extensions(x, exts);
4105         sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
4106 
4107         // finished
4108         X509_REQ_sign(x, pk, md);
4109 
4110         item.req = x;
4111         make_props();
4112         return true;
4113     }
4114 
4115     const CertContextProps *props() const override
4116     {
4117         return &_props;
4118     }
4119 
4120     bool compare(const CSRContext *other) const override
4121     {
4122         const CertContextProps *a = &_props;
4123         const CertContextProps *b = other->props();
4124 
4125         PublicKey    akey, bkey;
4126         PKeyContext *ac = subjectPublicKey();
4127         akey.change(ac);
4128         PKeyContext *bc = other->subjectPublicKey();
4129         bkey.change(bc);
4130 
4131         if (a->sig != b->sig || a->sigalgo != b->sigalgo || akey != bkey)
4132             return false;
4133 
4134         // TODO: Anything else we should compare?
4135 
4136         return true;
4137     }
4138 
4139     PKeyContext *subjectPublicKey() const override // does a new
4140     {
4141         MyPKeyContext *kc   = new MyPKeyContext(provider());
4142         EVP_PKEY      *pkey = X509_REQ_get_pubkey(item.req);
4143         PKeyBase      *kb   = kc->pkeyToBase(pkey, false);
4144         kc->setKey(kb);
4145         return kc;
4146     }
4147 
4148     QString toSPKAC() const override
4149     {
4150         return QString();
4151     }
4152 
4153     ConvertResult fromSPKAC(const QString &s) override
4154     {
4155         Q_UNUSED(s);
4156         return ErrorDecode;
4157     }
4158 
4159     void make_props()
4160     {
4161         X509_REQ        *x = item.req;
4162         CertContextProps p;
4163 
4164         // TODO: QString challenge;
4165 
4166         p.format = PKCS10;
4167 
4168         CertificateInfo subject;
4169 
4170         subject = get_cert_name(X509_REQ_get_subject_name(x));
4171 
4172         STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(x);
4173 
4174         p.isCA      = false;
4175         p.pathLimit = 0;
4176         int pos     = X509v3_get_ext_by_NID(exts, NID_basic_constraints, -1);
4177         if (pos != -1) {
4178             X509_EXTENSION *ex = X509v3_get_ext(exts, pos);
4179             if (ex)
4180                 get_basic_constraints(ex, &p.isCA, &p.pathLimit);
4181         }
4182 
4183         pos = X509v3_get_ext_by_NID(exts, NID_subject_alt_name, -1);
4184         if (pos != -1) {
4185             X509_EXTENSION *ex = X509v3_get_ext(exts, pos);
4186             if (ex)
4187                 subject.unite(get_cert_alt_name(ex));
4188         }
4189 
4190         pos = X509v3_get_ext_by_NID(exts, NID_key_usage, -1);
4191         if (pos != -1) {
4192             X509_EXTENSION *ex = X509v3_get_ext(exts, pos);
4193             if (ex)
4194                 p.constraints = get_cert_key_usage(ex);
4195         }
4196 
4197         pos = X509v3_get_ext_by_NID(exts, NID_ext_key_usage, -1);
4198         if (pos != -1) {
4199             X509_EXTENSION *ex = X509v3_get_ext(exts, pos);
4200             if (ex)
4201                 p.constraints += get_cert_ext_key_usage(ex);
4202         }
4203 
4204         pos = X509v3_get_ext_by_NID(exts, NID_certificate_policies, -1);
4205         if (pos != -1) {
4206             X509_EXTENSION *ex = X509v3_get_ext(exts, pos);
4207             if (ex)
4208                 p.policies = get_cert_policies(ex);
4209         }
4210 
4211         sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
4212 
4213         const ASN1_BIT_STRING *signature;
4214 
4215         X509_REQ_get0_signature(x, &signature, nullptr);
4216         if (signature) {
4217             p.sig = QByteArray(signature->length, 0);
4218             for (int i = 0; i < signature->length; i++)
4219                 p.sig[i] = signature->data[i];
4220         }
4221 
4222         switch (X509_REQ_get_signature_nid(x)) {
4223         case NID_sha1WithRSAEncryption:
4224             p.sigalgo = QCA::EMSA3_SHA1;
4225             break;
4226         case NID_md5WithRSAEncryption:
4227             p.sigalgo = QCA::EMSA3_MD5;
4228             break;
4229 #ifdef HAVE_OPENSSL_MD2
4230         case NID_md2WithRSAEncryption:
4231             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_MD2 : QCA::SignatureUnknown;
4232             break;
4233 #endif
4234         case NID_ripemd160WithRSA:
4235             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_RIPEMD160 : QCA::SignatureUnknown;
4236             break;
4237         case NID_dsaWithSHA1:
4238             p.sigalgo = QCA::EMSA1_SHA1;
4239             break;
4240         default:
4241             qDebug() << "Unknown signature value: " << X509_REQ_get_signature_nid(x);
4242             p.sigalgo = QCA::SignatureUnknown;
4243         }
4244 
4245         // FIXME: super hack
4246         CertificateOptions opts;
4247         opts.setInfo(subject);
4248         p.subject = opts.infoOrdered();
4249 
4250         _props = p;
4251     }
4252 };
4253 
4254 //----------------------------------------------------------------------------
4255 // MyCRLContext
4256 //----------------------------------------------------------------------------
4257 class MyCRLContext : public CRLContext
4258 {
4259     Q_OBJECT
4260 public:
4261     X509Item        item;
4262     CRLContextProps _props;
4263 
4264     MyCRLContext(Provider *p)
4265         : CRLContext(p)
4266     {
4267     }
4268 
4269     MyCRLContext(const MyCRLContext &from)
4270         : CRLContext(from)
4271         , item(from.item)
4272     {
4273     }
4274 
4275     Provider::Context *clone() const override
4276     {
4277         return new MyCRLContext(*this);
4278     }
4279 
4280     QByteArray toDER() const override
4281     {
4282         return item.toDER();
4283     }
4284 
4285     QString toPEM() const override
4286     {
4287         return item.toPEM();
4288     }
4289 
4290     ConvertResult fromDER(const QByteArray &a) override
4291     {
4292         _props          = CRLContextProps();
4293         ConvertResult r = item.fromDER(a, X509Item::TypeCRL);
4294         if (r == ConvertGood)
4295             make_props();
4296         return r;
4297     }
4298 
4299     ConvertResult fromPEM(const QString &s) override
4300     {
4301         ConvertResult r = item.fromPEM(s, X509Item::TypeCRL);
4302         if (r == ConvertGood)
4303             make_props();
4304         return r;
4305     }
4306 
4307     void fromX509(X509_CRL *x)
4308     {
4309         X509_CRL_up_ref(x);
4310         item.crl = x;
4311         make_props();
4312     }
4313 
4314     const CRLContextProps *props() const override
4315     {
4316         return &_props;
4317     }
4318 
4319     bool compare(const CRLContext *other) const override
4320     {
4321         const CRLContextProps *a = &_props;
4322         const CRLContextProps *b = other->props();
4323 
4324         if (a->issuer != b->issuer)
4325             return false;
4326         if (a->number != b->number)
4327             return false;
4328         if (a->thisUpdate != b->thisUpdate)
4329             return false;
4330         if (a->nextUpdate != b->nextUpdate)
4331             return false;
4332         if (a->revoked != b->revoked)
4333             return false;
4334         if (a->sig != b->sig)
4335             return false;
4336         if (a->sigalgo != b->sigalgo)
4337             return false;
4338         if (a->issuerId != b->issuerId)
4339             return false;
4340 
4341         return true;
4342     }
4343 
4344     void make_props()
4345     {
4346         X509_CRL *x = item.crl;
4347 
4348         CRLContextProps p;
4349 
4350         CertificateInfo issuer;
4351 
4352         issuer = get_cert_name(X509_CRL_get_issuer(x));
4353 
4354         p.thisUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get0_lastUpdate(x), nullptr);
4355         p.nextUpdate = ASN1_UTCTIME_QDateTime(X509_CRL_get0_nextUpdate(x), nullptr);
4356 
4357         STACK_OF(X509_REVOKED) *revokeStack = X509_CRL_get_REVOKED(x);
4358 
4359         for (int i = 0; i < sk_X509_REVOKED_num(revokeStack); ++i) {
4360             X509_REVOKED         *rev    = sk_X509_REVOKED_value(revokeStack, i);
4361             BigInteger            serial = bn2bi_free(ASN1_INTEGER_to_BN(X509_REVOKED_get0_serialNumber(rev), nullptr));
4362             QDateTime             time   = ASN1_UTCTIME_QDateTime(X509_REVOKED_get0_revocationDate(rev), nullptr);
4363             QCA::CRLEntry::Reason reason = QCA::CRLEntry::Unspecified;
4364             int                   pos    = X509_REVOKED_get_ext_by_NID(rev, NID_crl_reason, -1);
4365             if (pos != -1) {
4366                 X509_EXTENSION *ex = X509_REVOKED_get_ext(rev, pos);
4367                 if (ex) {
4368                     ASN1_ENUMERATED *result = (ASN1_ENUMERATED *)X509V3_EXT_d2i(ex);
4369                     switch (ASN1_ENUMERATED_get(result)) {
4370                     case CRL_REASON_UNSPECIFIED:
4371                         reason = QCA::CRLEntry::Unspecified;
4372                         break;
4373                     case CRL_REASON_KEY_COMPROMISE:
4374                         reason = QCA::CRLEntry::KeyCompromise;
4375                         break;
4376                     case CRL_REASON_CA_COMPROMISE:
4377                         reason = QCA::CRLEntry::CACompromise;
4378                         break;
4379                     case CRL_REASON_AFFILIATION_CHANGED:
4380                         reason = QCA::CRLEntry::AffiliationChanged;
4381                         break;
4382                     case CRL_REASON_SUPERSEDED:
4383                         reason = QCA::CRLEntry::Superseded;
4384                         break;
4385                     case CRL_REASON_CESSATION_OF_OPERATION:
4386                         reason = QCA::CRLEntry::CessationOfOperation;
4387                         break;
4388                     case CRL_REASON_CERTIFICATE_HOLD:
4389                         reason = QCA::CRLEntry::CertificateHold;
4390                         break;
4391                     case CRL_REASON_REMOVE_FROM_CRL:
4392                         reason = QCA::CRLEntry::RemoveFromCRL;
4393                         break;
4394                     case CRL_REASON_PRIVILEGE_WITHDRAWN:
4395                         reason = QCA::CRLEntry::PrivilegeWithdrawn;
4396                         break;
4397                     case CRL_REASON_AA_COMPROMISE:
4398                         reason = QCA::CRLEntry::AACompromise;
4399                         break;
4400                     default:
4401                         reason = QCA::CRLEntry::Unspecified;
4402                         break;
4403                     }
4404                     ASN1_ENUMERATED_free(result);
4405                 }
4406             }
4407             CRLEntry thisEntry(serial, time, reason);
4408             p.revoked.append(thisEntry);
4409         }
4410 
4411         const ASN1_BIT_STRING *signature;
4412 
4413         X509_CRL_get0_signature(x, &signature, nullptr);
4414         if (signature) {
4415             p.sig = QByteArray(signature->length, 0);
4416             for (int i = 0; i < signature->length; i++)
4417                 p.sig[i] = signature->data[i];
4418         }
4419 
4420         switch (X509_CRL_get_signature_nid(x)) {
4421         case NID_sha1WithRSAEncryption:
4422             p.sigalgo = QCA::EMSA3_SHA1;
4423             break;
4424         case NID_md5WithRSAEncryption:
4425             p.sigalgo = QCA::EMSA3_MD5;
4426             break;
4427 #ifdef HAVE_OPENSSL_MD2
4428         case NID_md2WithRSAEncryption:
4429             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_MD2 : QCA::SignatureUnknown;
4430             break;
4431 #endif
4432         case NID_ripemd160WithRSA:
4433             p.sigalgo = s_legacyProviderAvailable ? QCA::EMSA3_RIPEMD160 : QCA::SignatureUnknown;
4434             break;
4435         case NID_dsaWithSHA1:
4436             p.sigalgo = QCA::EMSA1_SHA1;
4437             break;
4438         case NID_sha224WithRSAEncryption:
4439             p.sigalgo = QCA::EMSA3_SHA224;
4440             break;
4441         case NID_sha256WithRSAEncryption:
4442             p.sigalgo = QCA::EMSA3_SHA256;
4443             break;
4444         case NID_sha384WithRSAEncryption:
4445             p.sigalgo = QCA::EMSA3_SHA384;
4446             break;
4447         case NID_sha512WithRSAEncryption:
4448             p.sigalgo = QCA::EMSA3_SHA512;
4449             break;
4450         default:
4451             qWarning() << "Unknown signature value: " << X509_CRL_get_signature_nid(x);
4452             p.sigalgo = QCA::SignatureUnknown;
4453         }
4454 
4455         int pos = X509_CRL_get_ext_by_NID(x, NID_authority_key_identifier, -1);
4456         if (pos != -1) {
4457             X509_EXTENSION *ex = X509_CRL_get_ext(x, pos);
4458             if (ex)
4459                 p.issuerId += get_cert_issuer_key_id(ex);
4460         }
4461 
4462         p.number = -1;
4463         pos      = X509_CRL_get_ext_by_NID(x, NID_crl_number, -1);
4464         if (pos != -1) {
4465             X509_EXTENSION *ex = X509_CRL_get_ext(x, pos);
4466             if (ex) {
4467                 ASN1_INTEGER *result = (ASN1_INTEGER *)X509V3_EXT_d2i(ex);
4468                 p.number             = ASN1_INTEGER_get(result);
4469                 ASN1_INTEGER_free(result);
4470             }
4471         }
4472 
4473         // FIXME: super hack
4474         CertificateOptions opts;
4475         opts.setInfo(issuer);
4476         p.issuer = opts.infoOrdered();
4477 
4478         _props = p;
4479     }
4480 };
4481 
4482 //----------------------------------------------------------------------------
4483 // MyCertCollectionContext
4484 //----------------------------------------------------------------------------
4485 class MyCertCollectionContext : public CertCollectionContext
4486 {
4487     Q_OBJECT
4488 public:
4489     MyCertCollectionContext(Provider *p)
4490         : CertCollectionContext(p)
4491     {
4492     }
4493 
4494     Provider::Context *clone() const override
4495     {
4496         return new MyCertCollectionContext(*this);
4497     }
4498 
4499     QByteArray toPKCS7(const QList<CertContext *> &certs, const QList<CRLContext *> &crls) const override
4500     {
4501         // TODO: implement
4502         Q_UNUSED(certs);
4503         Q_UNUSED(crls);
4504         return QByteArray();
4505     }
4506 
4507     ConvertResult fromPKCS7(const QByteArray &a, QList<CertContext *> *certs, QList<CRLContext *> *crls) const override
4508     {
4509         BIO *bi = BIO_new(BIO_s_mem());
4510         BIO_write(bi, a.data(), a.size());
4511         PKCS7 *p7 = d2i_PKCS7_bio(bi, nullptr);
4512         BIO_free(bi);
4513         if (!p7)
4514             return ErrorDecode;
4515 
4516         STACK_OF(X509) *xcerts    = nullptr;
4517         STACK_OF(X509_CRL) *xcrls = nullptr;
4518 
4519         int i = OBJ_obj2nid(p7->type);
4520         if (i == NID_pkcs7_signed) {
4521             xcerts = p7->d.sign->cert;
4522             xcrls  = p7->d.sign->crl;
4523         } else if (i == NID_pkcs7_signedAndEnveloped) {
4524             xcerts = p7->d.signed_and_enveloped->cert;
4525             xcrls  = p7->d.signed_and_enveloped->crl;
4526         }
4527 
4528         QList<CertContext *> _certs;
4529         QList<CRLContext *>  _crls;
4530 
4531         if (xcerts) {
4532             for (int n = 0; n < sk_X509_num(xcerts); ++n) {
4533                 MyCertContext *cc = new MyCertContext(provider());
4534                 cc->fromX509(sk_X509_value(xcerts, n));
4535                 _certs += cc;
4536             }
4537         }
4538         if (xcrls) {
4539             for (int n = 0; n < sk_X509_CRL_num(xcrls); ++n) {
4540                 MyCRLContext *cc = new MyCRLContext(provider());
4541                 cc->fromX509(sk_X509_CRL_value(xcrls, n));
4542                 _crls += cc;
4543             }
4544         }
4545 
4546         PKCS7_free(p7);
4547 
4548         *certs = _certs;
4549         *crls  = _crls;
4550 
4551         return ConvertGood;
4552     }
4553 };
4554 
4555 static bool usage_check(const MyCertContext &cc, UsageMode u)
4556 {
4557     if (cc._props.constraints.isEmpty()) {
4558         // then any usage is OK
4559         return true;
4560     }
4561 
4562     switch (u) {
4563     case UsageAny:
4564         return true;
4565         break;
4566     case UsageTLSServer:
4567         return cc._props.constraints.contains(ServerAuth);
4568         break;
4569     case UsageTLSClient:
4570         return cc._props.constraints.contains(ClientAuth);
4571         break;
4572     case UsageCodeSigning:
4573         return cc._props.constraints.contains(CodeSigning);
4574         break;
4575     case UsageEmailProtection:
4576         return cc._props.constraints.contains(EmailProtection);
4577         break;
4578     case UsageTimeStamping:
4579         return cc._props.constraints.contains(TimeStamping);
4580         break;
4581     case UsageCRLSigning:
4582         return cc._props.constraints.contains(CRLSign);
4583         break;
4584     default:
4585         return true;
4586     }
4587 }
4588 
4589 Validity MyCertContext::validate(const QList<CertContext *> &trusted,
4590                                  const QList<CertContext *> &untrusted,
4591                                  const QList<CRLContext *>  &crls,
4592                                  UsageMode                   u,
4593                                  ValidateFlags               vf) const
4594 {
4595     // TODO
4596     Q_UNUSED(vf);
4597 
4598     STACK_OF(X509) *trusted_list   = sk_X509_new_null();
4599     STACK_OF(X509) *untrusted_list = sk_X509_new_null();
4600     QList<X509_CRL *> crl_list;
4601 
4602     int n;
4603     for (n = 0; n < trusted.count(); ++n) {
4604         const MyCertContext *cc = static_cast<const MyCertContext *>(trusted[n]);
4605         X509                *x  = cc->item.cert;
4606         X509_up_ref(x);
4607         sk_X509_push(trusted_list, x);
4608     }
4609     for (n = 0; n < untrusted.count(); ++n) {
4610         const MyCertContext *cc = static_cast<const MyCertContext *>(untrusted[n]);
4611         X509                *x  = cc->item.cert;
4612         X509_up_ref(x);
4613         sk_X509_push(untrusted_list, x);
4614     }
4615     for (n = 0; n < crls.count(); ++n) {
4616         const MyCRLContext *cc = static_cast<const MyCRLContext *>(crls[n]);
4617         X509_CRL           *x  = cc->item.crl;
4618         X509_CRL_up_ref(x);
4619         crl_list.append(x);
4620     }
4621 
4622     const MyCertContext *cc = this;
4623     X509                *x  = cc->item.cert;
4624 
4625     // verification happens through a store "context"
4626     X509_STORE_CTX *ctx = X509_STORE_CTX_new();
4627 
4628     // make a store of crls
4629     X509_STORE *store = X509_STORE_new();
4630     for (int n = 0; n < crl_list.count(); ++n)
4631         X509_STORE_add_crl(store, crl_list[n]);
4632 
4633     // the first initialization handles untrusted certs, crls, and target cert
4634     X509_STORE_CTX_init(ctx, store, x, untrusted_list);
4635 
4636     // this initializes the trusted certs
4637     X509_STORE_CTX_trusted_stack(ctx, trusted_list);
4638 
4639     // verify!
4640     int ret = X509_verify_cert(ctx);
4641     int err = -1;
4642     if (!ret)
4643         err = X509_STORE_CTX_get_error(ctx);
4644 
4645     // cleanup
4646     X509_STORE_CTX_free(ctx);
4647     X509_STORE_free(store);
4648 
4649     sk_X509_pop_free(trusted_list, X509_free);
4650     sk_X509_pop_free(untrusted_list, X509_free);
4651     for (int n = 0; n < crl_list.count(); ++n)
4652         X509_CRL_free(crl_list[n]);
4653 
4654     if (!ret)
4655         return convert_verify_error(err);
4656 
4657     if (!usage_check(*cc, u))
4658         return ErrorInvalidPurpose;
4659 
4660     return ValidityGood;
4661 }
4662 
4663 Validity MyCertContext::validate_chain(const QList<CertContext *> &chain,
4664                                        const QList<CertContext *> &trusted,
4665                                        const QList<CRLContext *>  &crls,
4666                                        UsageMode                   u,
4667                                        ValidateFlags               vf) const
4668 {
4669     // TODO
4670     Q_UNUSED(vf);
4671 
4672     STACK_OF(X509) *trusted_list   = sk_X509_new_null();
4673     STACK_OF(X509) *untrusted_list = sk_X509_new_null();
4674     QList<X509_CRL *> crl_list;
4675 
4676     int n;
4677     for (n = 0; n < trusted.count(); ++n) {
4678         const MyCertContext *cc = static_cast<const MyCertContext *>(trusted[n]);
4679         X509                *x  = cc->item.cert;
4680         X509_up_ref(x);
4681         sk_X509_push(trusted_list, x);
4682     }
4683     for (n = 1; n < chain.count(); ++n) {
4684         const MyCertContext *cc = static_cast<const MyCertContext *>(chain[n]);
4685         X509                *x  = cc->item.cert;
4686         X509_up_ref(x);
4687         sk_X509_push(untrusted_list, x);
4688     }
4689     for (n = 0; n < crls.count(); ++n) {
4690         const MyCRLContext *cc = static_cast<const MyCRLContext *>(crls[n]);
4691         X509_CRL           *x  = cc->item.crl;
4692         X509_CRL_up_ref(x);
4693         crl_list.append(x);
4694     }
4695 
4696     const MyCertContext *cc = static_cast<const MyCertContext *>(chain[0]);
4697     X509                *x  = cc->item.cert;
4698 
4699     // verification happens through a store "context"
4700     X509_STORE_CTX *ctx = X509_STORE_CTX_new();
4701 
4702     // make a store of crls
4703     X509_STORE *store = X509_STORE_new();
4704     for (int n = 0; n < crl_list.count(); ++n)
4705         X509_STORE_add_crl(store, crl_list[n]);
4706 
4707     // the first initialization handles untrusted certs, crls, and target cert
4708     X509_STORE_CTX_init(ctx, store, x, untrusted_list);
4709 
4710     // this initializes the trusted certs
4711     X509_STORE_CTX_trusted_stack(ctx, trusted_list);
4712 
4713     // verify!
4714     int ret = X509_verify_cert(ctx);
4715     int err = -1;
4716     if (!ret)
4717         err = X509_STORE_CTX_get_error(ctx);
4718 
4719     // grab the chain, which may not be fully populated
4720     STACK_OF(X509) *xchain = X509_STORE_CTX_get_chain(ctx);
4721 
4722     // make sure the chain is what we expect.  the reason we need to do
4723     //   this is because I don't think openssl cares about the order of
4724     //   input.  that is, if there's a chain A<-B<-C, and we input A as
4725     //   the base cert, with B and C as the issuers, we will get a
4726     //   successful validation regardless of whether the issuer list is
4727     //   in the order B,C or C,B.  we don't want an input chain of A,C,B
4728     //   to be considered correct, so we must account for that here.
4729     QList<const MyCertContext *> expected;
4730     for (int n = 0; n < chain.count(); ++n)
4731         expected += static_cast<const MyCertContext *>(chain[n]);
4732     if (!xchain || !sameChain(xchain, expected))
4733         err = ErrorValidityUnknown;
4734 
4735     // cleanup
4736     X509_STORE_CTX_free(ctx);
4737     X509_STORE_free(store);
4738 
4739     sk_X509_pop_free(trusted_list, X509_free);
4740     sk_X509_pop_free(untrusted_list, X509_free);
4741     for (int n = 0; n < crl_list.count(); ++n)
4742         X509_CRL_free(crl_list[n]);
4743 
4744     if (!ret)
4745         return convert_verify_error(err);
4746 
4747     if (!usage_check(*cc, u))
4748         return ErrorInvalidPurpose;
4749 
4750     return ValidityGood;
4751 }
4752 
4753 class MyPKCS12Context : public PKCS12Context
4754 {
4755     Q_OBJECT
4756 public:
4757     MyPKCS12Context(Provider *p)
4758         : PKCS12Context(p)
4759     {
4760     }
4761 
4762     ~MyPKCS12Context() override
4763     {
4764     }
4765 
4766     Provider::Context *clone() const override
4767     {
4768         return nullptr;
4769     }
4770 
4771     QByteArray toPKCS12(const QString                    &name,
4772                         const QList<const CertContext *> &chain,
4773                         const PKeyContext                &priv,
4774                         const SecureArray                &passphrase) const override
4775     {
4776         if (chain.count() < 1)
4777             return QByteArray();
4778 
4779         X509 *cert         = static_cast<const MyCertContext *>(chain[0])->item.cert;
4780         STACK_OF(X509) *ca = sk_X509_new_null();
4781         if (chain.count() > 1) {
4782             for (int n = 1; n < chain.count(); ++n) {
4783                 X509 *x = static_cast<const MyCertContext *>(chain[n])->item.cert;
4784                 X509_up_ref(x);
4785                 sk_X509_push(ca, x);
4786             }
4787         }
4788         const MyPKeyContext &pk  = static_cast<const MyPKeyContext &>(priv);
4789         PKCS12              *p12 = PKCS12_create(
4790             (char *)passphrase.data(), (char *)name.toLatin1().data(), pk.get_pkey(), cert, ca, 0, 0, 0, 0, 0);
4791         sk_X509_pop_free(ca, X509_free);
4792 
4793         if (!p12)
4794             return QByteArray();
4795 
4796         BIO *bo = BIO_new(BIO_s_mem());
4797         i2d_PKCS12_bio(bo, p12);
4798         const QByteArray out = bio2ba(bo);
4799         return out;
4800     }
4801 
4802     ConvertResult fromPKCS12(const QByteArray     &in,
4803                              const SecureArray    &passphrase,
4804                              QString              *name,
4805                              QList<CertContext *> *chain,
4806                              PKeyContext         **priv) const override
4807     {
4808         BIO *bi = BIO_new(BIO_s_mem());
4809         BIO_write(bi, in.data(), in.size());
4810         PKCS12 *p12 = d2i_PKCS12_bio(bi, nullptr);
4811         BIO_free(bi);
4812         if (!p12)
4813             return ErrorDecode;
4814 
4815         EVP_PKEY *pkey;
4816         X509     *cert;
4817         STACK_OF(X509) *ca = nullptr;
4818         if (!PKCS12_parse(p12, passphrase.data(), &pkey, &cert, &ca)) {
4819             PKCS12_free(p12);
4820             return ErrorDecode;
4821         }
4822         PKCS12_free(p12);
4823 
4824         // require private key
4825         if (!pkey) {
4826             if (cert)
4827                 X509_free(cert);
4828             if (ca)
4829                 sk_X509_pop_free(ca, X509_free);
4830             return ErrorDecode;
4831         }
4832 
4833         // TODO: require cert
4834 
4835         int   aliasLength;
4836         char *aliasData = (char *)X509_alias_get0(cert, &aliasLength);
4837         *name           = QString::fromLatin1(aliasData, aliasLength);
4838 
4839         MyPKeyContext *pk = new MyPKeyContext(provider());
4840         PKeyBase      *k  = pk->pkeyToBase(pkey, true); // does an EVP_PKEY_free()
4841         if (!k) {
4842             delete pk;
4843             if (cert)
4844                 X509_free(cert);
4845             if (ca)
4846                 sk_X509_pop_free(ca, X509_free);
4847             return ErrorDecode;
4848         }
4849         pk->k = k;
4850         *priv = pk;
4851 
4852         QList<CertContext *> certs;
4853         if (cert) {
4854             MyCertContext *cc = new MyCertContext(provider());
4855             cc->fromX509(cert);
4856             certs.append(cc);
4857             X509_free(cert);
4858         }
4859         if (ca) {
4860             // TODO: reorder in chain-order?
4861             // TODO: throw out certs that don't fit the chain?
4862             for (int n = 0; n < sk_X509_num(ca); ++n) {
4863                 MyCertContext *cc = new MyCertContext(provider());
4864                 cc->fromX509(sk_X509_value(ca, n));
4865                 certs.append(cc);
4866             }
4867             sk_X509_pop_free(ca, X509_free);
4868         }
4869 
4870         // reorder, throw out
4871         QCA::CertificateChain ch;
4872         for (int n = 0; n < certs.count(); ++n) {
4873             QCA::Certificate cert;
4874             cert.change(certs[n]);
4875             ch += cert;
4876         }
4877         certs.clear();
4878         ch = ch.complete(QList<QCA::Certificate>());
4879         for (int n = 0; n < ch.count(); ++n) {
4880             MyCertContext *cc = (MyCertContext *)ch[n].context();
4881             certs += (new MyCertContext(*cc));
4882         }
4883         ch.clear();
4884 
4885         *chain = certs;
4886         return ConvertGood;
4887     }
4888 };
4889 
4890 // TODO: test to ensure there is no cert-test lag
4891 static bool ssl_init = false;
4892 class MyTLSContext : public TLSContext
4893 {
4894     Q_OBJECT
4895 public:
4896     enum
4897     {
4898         Good,
4899         TryAgain,
4900         Bad
4901     };
4902     enum
4903     {
4904         Idle,
4905         Connect,
4906         Accept,
4907         Handshake,
4908         Active,
4909         Closing
4910     };
4911 
4912     bool       serv; // true if we are acting as a server
4913     int        mode;
4914     QByteArray sendQueue;
4915     QByteArray recvQueue;
4916 
4917     CertificateCollection trusted;
4918     Certificate           cert, peercert; // TODO: support cert chains
4919     PrivateKey            key;
4920     QString               targetHostName;
4921 
4922     Result     result_result;
4923     QByteArray result_to_net;
4924     int        result_encoded;
4925     QByteArray result_plain;
4926 
4927     SSL              *ssl;
4928     const SSL_METHOD *method;
4929     SSL_CTX          *context;
4930     BIO              *rbio, *wbio;
4931     Validity          vr;
4932     bool              v_eof;
4933 
4934     MyTLSContext(Provider *p)
4935         : TLSContext(p, QStringLiteral("tls"))
4936     {
4937         if (!ssl_init) {
4938             SSL_library_init();
4939             SSL_load_error_strings();
4940             ssl_init = true;
4941         }
4942 
4943         ssl     = nullptr;
4944         context = nullptr;
4945         reset();
4946     }
4947 
4948     ~MyTLSContext() override
4949     {
4950         reset();
4951     }
4952 
4953     Provider::Context *clone() const override
4954     {
4955         return nullptr;
4956     }
4957 
4958     void reset() override
4959     {
4960         if (ssl) {
4961             SSL_free(ssl);
4962             ssl = nullptr;
4963         }
4964         if (context) {
4965             SSL_CTX_free(context);
4966             context = nullptr;
4967         }
4968 
4969         cert = Certificate();
4970         key  = PrivateKey();
4971 
4972         sendQueue.resize(0);
4973         recvQueue.resize(0);
4974         mode     = Idle;
4975         peercert = Certificate();
4976         vr       = ErrorValidityUnknown;
4977         v_eof    = false;
4978     }
4979 
4980     // dummy verification function for SSL_set_verify()
4981     static int ssl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
4982     {
4983         Q_UNUSED(preverify_ok);
4984         Q_UNUSED(x509_ctx);
4985 
4986         // don't terminate handshake in case of verification failure
4987         return 1;
4988     }
4989 
4990     QStringList supportedCipherSuites(const TLS::Version &version) const override
4991     {
4992         OpenSSL_add_ssl_algorithms();
4993         SSL_CTX *ctx = nullptr;
4994         switch (version) {
4995 #ifndef OPENSSL_NO_SSL3_METHOD
4996         case TLS::SSL_v3:
4997             // Here should be used TLS_client_method() but on Fedora
4998             // it doesn't return any SSL ciphers.
4999             ctx = SSL_CTX_new(SSLv3_client_method());
5000             SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
5001             SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION);
5002             break;
5003 #endif
5004         case TLS::TLS_v1:
5005             ctx = SSL_CTX_new(TLS_client_method());
5006             SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
5007             SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
5008             break;
5009         case TLS::DTLS_v1:
5010         default:
5011             /* should not happen - should be in a "dtls" provider*/
5012             qWarning("Unexpected enum in cipherSuites");
5013             ctx = nullptr;
5014         }
5015         if (nullptr == ctx)
5016             return QStringList();
5017 
5018         SSL *ssl = SSL_new(ctx);
5019         if (nullptr == ssl) {
5020             SSL_CTX_free(ctx);
5021             return QStringList();
5022         }
5023 
5024         STACK_OF(SSL_CIPHER) *sk = SSL_get1_supported_ciphers(ssl);
5025         QStringList cipherList;
5026         for (int i = 0; i < sk_SSL_CIPHER_num(sk); ++i) {
5027             const SSL_CIPHER *thisCipher = sk_SSL_CIPHER_value(sk, i);
5028             cipherList += QString::fromLatin1(SSL_CIPHER_standard_name(thisCipher));
5029         }
5030         sk_SSL_CIPHER_free(sk);
5031 
5032         SSL_free(ssl);
5033         SSL_CTX_free(ctx);
5034 
5035         return cipherList;
5036     }
5037 
5038     bool canCompress() const override
5039     {
5040         // TODO
5041         return false;
5042     }
5043 
5044     bool canSetHostName() const override
5045     {
5046         // TODO
5047         return false;
5048     }
5049 
5050     int maxSSF() const override
5051     {
5052         // TODO
5053         return 256;
5054     }
5055 
5056     void setConstraints(int minSSF, int maxSSF) override
5057     {
5058         // TODO
5059         Q_UNUSED(minSSF);
5060         Q_UNUSED(maxSSF);
5061     }
5062 
5063     void setConstraints(const QStringList &cipherSuiteList) override
5064     {
5065         // TODO
5066         Q_UNUSED(cipherSuiteList);
5067     }
5068 
5069     void setup(bool serverMode, const QString &hostName, bool compress) override
5070     {
5071         serv = serverMode;
5072         if (false == serverMode) {
5073             // client
5074             targetHostName = hostName;
5075         }
5076         Q_UNUSED(compress); // TODO
5077     }
5078 
5079     void setTrustedCertificates(const CertificateCollection &_trusted) override
5080     {
5081         trusted = _trusted;
5082     }
5083 
5084     void setIssuerList(const QList<CertificateInfoOrdered> &issuerList) override
5085     {
5086         Q_UNUSED(issuerList); // TODO
5087     }
5088 
5089     void setCertificate(const CertificateChain &_cert, const PrivateKey &_key) override
5090     {
5091         if (!_cert.isEmpty())
5092             cert = _cert.primary(); // TODO: take the whole chain
5093         key = _key;
5094     }
5095 
5096     void setSessionId(const TLSSessionContext &id) override
5097     {
5098         // TODO
5099         Q_UNUSED(id);
5100     }
5101 
5102     void shutdown() override
5103     {
5104         mode = Closing;
5105     }
5106 
5107     void start() override
5108     {
5109         bool ok;
5110         if (serv)
5111             ok = priv_startServer();
5112         else
5113             ok = priv_startClient();
5114         result_result = ok ? Success : Error;
5115 
5116         doResultsReady();
5117     }
5118 
5119     void update(const QByteArray &from_net, const QByteArray &from_app) override
5120     {
5121         if (mode == Active) {
5122             bool ok = true;
5123             if (!from_app.isEmpty())
5124                 ok = priv_encode(from_app, &result_to_net, &result_encoded);
5125             if (ok)
5126                 ok = priv_decode(from_net, &result_plain, &result_to_net);
5127             result_result = ok ? Success : Error;
5128         } else if (mode == Closing)
5129             result_result = priv_shutdown(from_net, &result_to_net);
5130         else
5131             result_result = priv_handshake(from_net, &result_to_net);
5132 
5133         // printf("update (from_net=%d, to_net=%d, from_app=%d, to_app=%d)\n", from_net.size(), result_to_net.size(),
5134         // from_app.size(), result_plain.size());
5135 
5136         doResultsReady();
5137     }
5138 
5139     bool priv_startClient()
5140     {
5141         // serv = false;
5142         method = SSLv23_client_method();
5143         if (!init())
5144             return false;
5145         mode = Connect;
5146         return true;
5147     }
5148 
5149     bool priv_startServer()
5150     {
5151         // serv = true;
5152         method = SSLv23_server_method();
5153         if (!init())
5154             return false;
5155         mode = Accept;
5156         return true;
5157     }
5158 
5159     Result priv_handshake(const QByteArray &from_net, QByteArray *to_net)
5160     {
5161         if (!from_net.isEmpty())
5162             BIO_write(rbio, from_net.data(), from_net.size());
5163 
5164         if (mode == Connect) {
5165             int ret = doConnect();
5166             if (ret == Good) {
5167                 mode = Handshake;
5168             } else if (ret == Bad) {
5169                 reset();
5170                 return Error;
5171             }
5172         }
5173 
5174         if (mode == Accept) {
5175             int ret = doAccept();
5176             if (ret == Good) {
5177                 getCert();
5178                 mode = Active;
5179             } else if (ret == Bad) {
5180                 reset();
5181                 return Error;
5182             }
5183         }
5184 
5185         if (mode == Handshake) {
5186             int ret = doHandshake();
5187             if (ret == Good) {
5188                 getCert();
5189                 mode = Active;
5190             } else if (ret == Bad) {
5191                 reset();
5192                 return Error;
5193             }
5194         }
5195 
5196         // process outgoing
5197         *to_net = readOutgoing();
5198 
5199         if (mode == Active)
5200             return Success;
5201         else
5202             return Continue;
5203     }
5204 
5205     Result priv_shutdown(const QByteArray &from_net, QByteArray *to_net)
5206     {
5207         if (!from_net.isEmpty())
5208             BIO_write(rbio, from_net.data(), from_net.size());
5209 
5210         int ret = doShutdown();
5211         if (ret == Bad) {
5212             reset();
5213             return Error;
5214         }
5215 
5216         *to_net = readOutgoing();
5217 
5218         if (ret == Good) {
5219             mode = Idle;
5220             return Success;
5221         } else {
5222             // mode = Closing;
5223             return Continue;
5224         }
5225     }
5226 
5227     bool priv_encode(const QByteArray &plain, QByteArray *to_net, int *enc)
5228     {
5229         if (mode != Active)
5230             return false;
5231         sendQueue.append(plain);
5232 
5233         int encoded = 0;
5234         if (sendQueue.size() > 0) {
5235             int ret = SSL_write(ssl, sendQueue.data(), sendQueue.size());
5236 
5237             enum
5238             {
5239                 Good,
5240                 Continue,
5241                 Done,
5242                 Error
5243             };
5244             int m;
5245             if (ret <= 0) {
5246                 int x = SSL_get_error(ssl, ret);
5247                 if (x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5248                     m = Continue;
5249                 else if (x == SSL_ERROR_ZERO_RETURN)
5250                     m = Done;
5251                 else
5252                     m = Error;
5253             } else {
5254                 m             = Good;
5255                 encoded       = ret;
5256                 int   newsize = sendQueue.size() - encoded;
5257                 char *r       = sendQueue.data();
5258                 memmove(r, r + encoded, newsize);
5259                 sendQueue.resize(newsize);
5260             }
5261 
5262             if (m == Done) {
5263                 sendQueue.resize(0);
5264                 v_eof = true;
5265                 return false;
5266             }
5267             if (m == Error) {
5268                 sendQueue.resize(0);
5269                 return false;
5270             }
5271         }
5272 
5273         *to_net += readOutgoing();
5274         *enc = encoded;
5275         return true;
5276     }
5277 
5278     bool priv_decode(const QByteArray &from_net, QByteArray *plain, QByteArray *to_net)
5279     {
5280         if (mode != Active)
5281             return false;
5282         if (!from_net.isEmpty())
5283             BIO_write(rbio, from_net.data(), from_net.size());
5284 
5285         QByteArray a;
5286         while (!v_eof) {
5287             a.resize(8192);
5288             int ret = SSL_read(ssl, a.data(), a.size());
5289             // printf("SSL_read = %d\n", ret);
5290             if (ret > 0) {
5291                 if (ret != (int)a.size())
5292                     a.resize(ret);
5293                 // printf("SSL_read chunk: [%s]\n", qPrintable(arrayToHex(a)));
5294                 recvQueue.append(a);
5295             } else if (ret <= 0) {
5296                 ERR_print_errors_fp(stdout);
5297                 int x = SSL_get_error(ssl, ret);
5298                 // printf("SSL_read error = %d\n", x);
5299                 if (x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5300                     break;
5301                 else if (x == SSL_ERROR_ZERO_RETURN)
5302                     v_eof = true;
5303                 else
5304                     return false;
5305             }
5306         }
5307 
5308         *plain = recvQueue;
5309         recvQueue.resize(0);
5310 
5311         // could be outgoing data also
5312         *to_net += readOutgoing();
5313         return true;
5314     }
5315 
5316     bool waitForResultsReady(int msecs) override
5317     {
5318         // TODO: for now, all operations block anyway
5319         Q_UNUSED(msecs);
5320         return true;
5321     }
5322 
5323     Result result() const override
5324     {
5325         return result_result;
5326     }
5327 
5328     QByteArray to_net() override
5329     {
5330         const QByteArray a = result_to_net;
5331         result_to_net.clear();
5332         return a;
5333     }
5334 
5335     int encoded() const override
5336     {
5337         return result_encoded;
5338     }
5339 
5340     QByteArray to_app() override
5341     {
5342         const QByteArray a = result_plain;
5343         result_plain.clear();
5344         return a;
5345     }
5346 
5347     bool eof() const override
5348     {
5349         return v_eof;
5350     }
5351 
5352     bool clientHelloReceived() const override
5353     {
5354         // TODO
5355         return false;
5356     }
5357 
5358     bool serverHelloReceived() const override
5359     {
5360         // TODO
5361         return false;
5362     }
5363 
5364     QString hostName() const override
5365     {
5366         // TODO
5367         return QString();
5368     }
5369 
5370     bool certificateRequested() const override
5371     {
5372         // TODO
5373         return false;
5374     }
5375 
5376     QList<CertificateInfoOrdered> issuerList() const override
5377     {
5378         // TODO
5379         return QList<CertificateInfoOrdered>();
5380     }
5381 
5382     SessionInfo sessionInfo() const override
5383     {
5384         SessionInfo sessInfo;
5385 
5386         SSL_SESSION *session  = SSL_get0_session(ssl);
5387         sessInfo.isCompressed = (0 != SSL_SESSION_get_compress_id(session));
5388         int ssl_version       = SSL_version(ssl);
5389 
5390         if (ssl_version == TLS1_VERSION)
5391             sessInfo.version = TLS::TLS_v1;
5392         else if (ssl_version == SSL3_VERSION)
5393             sessInfo.version = TLS::SSL_v3;
5394         else if (ssl_version == SSL2_VERSION)
5395             sessInfo.version = TLS::SSL_v2;
5396         else {
5397             qDebug("unexpected version response");
5398             sessInfo.version = TLS::TLS_v1;
5399         }
5400 
5401         sessInfo.cipherSuite = QString::fromLatin1(SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl)));
5402 
5403         sessInfo.cipherMaxBits = SSL_get_cipher_bits(ssl, &(sessInfo.cipherBits));
5404 
5405         sessInfo.id = nullptr; // TODO: session resuming
5406 
5407         return sessInfo;
5408     }
5409 
5410     QByteArray unprocessed() override
5411     {
5412         QByteArray a;
5413         int        size = BIO_pending(rbio);
5414         if (size <= 0)
5415             return a;
5416         a.resize(size);
5417 
5418         int r = BIO_read(rbio, a.data(), size);
5419         if (r <= 0) {
5420             a.resize(0);
5421             return a;
5422         }
5423         if (r != size)
5424             a.resize(r);
5425         return a;
5426     }
5427 
5428     Validity peerCertificateValidity() const override
5429     {
5430         return vr;
5431     }
5432 
5433     CertificateChain peerCertificateChain() const override
5434     {
5435         // TODO: support whole chain
5436         CertificateChain chain;
5437         chain.append(peercert);
5438         return chain;
5439     }
5440 
5441     void doResultsReady()
5442     {
5443         QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection);
5444     }
5445 
5446     bool init()
5447     {
5448         context = SSL_CTX_new(method);
5449         if (!context)
5450             return false;
5451 
5452         // setup the cert store
5453         {
5454             X509_STORE              *store     = SSL_CTX_get_cert_store(context);
5455             const QList<Certificate> cert_list = trusted.certificates();
5456             const QList<CRL>         crl_list  = trusted.crls();
5457             int                      n;
5458             for (n = 0; n < cert_list.count(); ++n) {
5459                 const MyCertContext *cc = static_cast<const MyCertContext *>(cert_list[n].context());
5460                 X509                *x  = cc->item.cert;
5461                 // CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
5462                 X509_STORE_add_cert(store, x);
5463             }
5464             for (n = 0; n < crl_list.count(); ++n) {
5465                 const MyCRLContext *cc = static_cast<const MyCRLContext *>(crl_list[n].context());
5466                 X509_CRL           *x  = cc->item.crl;
5467                 // CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
5468                 X509_STORE_add_crl(store, x);
5469             }
5470         }
5471 
5472         ssl = SSL_new(context);
5473         if (!ssl) {
5474             SSL_CTX_free(context);
5475             context = nullptr;
5476             return false;
5477         }
5478         SSL_set_ssl_method(ssl, method); // can this return error?
5479 
5480 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5481         if (targetHostName.isEmpty() == false) {
5482             // we have a target
5483             // this might fail, but we ignore that for now
5484             char *hostname = targetHostName.toLatin1().data();
5485             SSL_set_tlsext_host_name(ssl, hostname);
5486         }
5487 #endif
5488 
5489         // setup the memory bio
5490         rbio = BIO_new(BIO_s_mem());
5491         wbio = BIO_new(BIO_s_mem());
5492 
5493         // this passes control of the bios to ssl.  we don't need to free them.
5494         SSL_set_bio(ssl, rbio, wbio);
5495 
5496         // FIXME: move this to after server hello
5497         // setup the cert to send
5498         if (!cert.isNull() && !key.isNull()) {
5499             PrivateKey nkey = key;
5500 
5501             const PKeyContext *tmp_kc = static_cast<const PKeyContext *>(nkey.context());
5502 
5503             if (!tmp_kc->sameProvider(this)) {
5504                 // fprintf(stderr, "experimental: private key supplied by a different provider\n");
5505 
5506                 // make a pkey pointing to the existing private key
5507                 EVP_PKEY *pkey;
5508                 pkey = EVP_PKEY_new();
5509                 EVP_PKEY_assign_RSA(pkey, createFromExisting(nkey.toRSA()));
5510 
5511                 // make a new private key object to hold it
5512                 MyPKeyContext *pk = new MyPKeyContext(provider());
5513                 PKeyBase      *k  = pk->pkeyToBase(pkey, true); // does an EVP_PKEY_free()
5514                 pk->k             = k;
5515                 nkey.change(pk);
5516             }
5517 
5518             const MyCertContext *cc = static_cast<const MyCertContext *>(cert.context());
5519             const MyPKeyContext *kc = static_cast<const MyPKeyContext *>(nkey.context());
5520 
5521             if (SSL_use_certificate(ssl, cc->item.cert) != 1) {
5522                 SSL_free(ssl);
5523                 SSL_CTX_free(context);
5524                 return false;
5525             }
5526             if (SSL_use_PrivateKey(ssl, kc->get_pkey()) != 1) {
5527                 SSL_free(ssl);
5528                 SSL_CTX_free(context);
5529                 return false;
5530             }
5531         }
5532 
5533         // request a certificate from the client, if in server mode
5534         if (serv) {
5535             SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, ssl_verify_callback);
5536         }
5537 
5538         return true;
5539     }
5540 
5541     void getCert()
5542     {
5543         // verify the certificate
5544         Validity code           = ErrorValidityUnknown;
5545         STACK_OF(X509) *x_chain = SSL_get_peer_cert_chain(ssl);
5546         // X509 *x = SSL_get_peer_certificate(ssl);
5547         if (x_chain) {
5548             CertificateChain chain;
5549 
5550             if (serv) {
5551                 X509          *x  = SSL_get_peer_certificate(ssl);
5552                 MyCertContext *cc = new MyCertContext(provider());
5553                 cc->fromX509(x);
5554                 Certificate cert;
5555                 cert.change(cc);
5556                 chain += cert;
5557             }
5558 
5559             for (int n = 0; n < sk_X509_num(x_chain); ++n) {
5560                 X509          *x  = sk_X509_value(x_chain, n);
5561                 MyCertContext *cc = new MyCertContext(provider());
5562                 cc->fromX509(x);
5563                 Certificate cert;
5564                 cert.change(cc);
5565                 chain += cert;
5566             }
5567 
5568             peercert = chain.primary();
5569 
5570 #ifdef Q_OS_MAC
5571             code = chain.validate(trusted);
5572 #else
5573             int ret = SSL_get_verify_result(ssl);
5574             if (ret == X509_V_OK)
5575                 code = ValidityGood;
5576             else
5577                 code = convert_verify_error(ret);
5578 #endif
5579         } else {
5580             peercert = Certificate();
5581         }
5582         vr = code;
5583     }
5584 
5585     int doConnect()
5586     {
5587         int ret = SSL_connect(ssl);
5588         if (ret < 0) {
5589             int x = SSL_get_error(ssl, ret);
5590             if (x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5591                 return TryAgain;
5592             else
5593                 return Bad;
5594         } else if (ret == 0)
5595             return Bad;
5596         return Good;
5597     }
5598 
5599     int doAccept()
5600     {
5601         int ret = SSL_accept(ssl);
5602         if (ret < 0) {
5603             int x = SSL_get_error(ssl, ret);
5604             if (x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5605                 return TryAgain;
5606             else
5607                 return Bad;
5608         } else if (ret == 0)
5609             return Bad;
5610         return Good;
5611     }
5612 
5613     int doHandshake()
5614     {
5615         int ret = SSL_do_handshake(ssl);
5616         if (ret < 0) {
5617             int x = SSL_get_error(ssl, ret);
5618             if (x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5619                 return TryAgain;
5620             else
5621                 return Bad;
5622         } else if (ret == 0)
5623             return Bad;
5624         return Good;
5625     }
5626 
5627     int doShutdown()
5628     {
5629         int ret = SSL_shutdown(ssl);
5630         if (ret >= 1)
5631             return Good;
5632         else {
5633             if (ret == 0)
5634                 return TryAgain;
5635             int x = SSL_get_error(ssl, ret);
5636             if (x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
5637                 return TryAgain;
5638             return Bad;
5639         }
5640     }
5641 
5642     QByteArray readOutgoing()
5643     {
5644         QByteArray a;
5645         int        size = BIO_pending(wbio);
5646         if (size <= 0)
5647             return a;
5648         a.resize(size);
5649 
5650         int r = BIO_read(wbio, a.data(), size);
5651         if (r <= 0) {
5652             a.resize(0);
5653             return a;
5654         }
5655         if (r != size)
5656             a.resize(r);
5657         return a;
5658     }
5659 };
5660 
5661 class CMSContext : public SMSContext
5662 {
5663     Q_OBJECT
5664 public:
5665     CertificateCollection   trustedCerts;
5666     CertificateCollection   untrustedCerts;
5667     QList<SecureMessageKey> privateKeys;
5668 
5669     CMSContext(Provider *p)
5670         : SMSContext(p, QStringLiteral("cms"))
5671     {
5672     }
5673 
5674     ~CMSContext() override
5675     {
5676     }
5677 
5678     Provider::Context *clone() const override
5679     {
5680         return nullptr;
5681     }
5682 
5683     void setTrustedCertificates(const CertificateCollection &trusted) override
5684     {
5685         trustedCerts = trusted;
5686     }
5687 
5688     void setUntrustedCertificates(const CertificateCollection &untrusted) override
5689     {
5690         untrustedCerts = untrusted;
5691     }
5692 
5693     void setPrivateKeys(const QList<SecureMessageKey> &keys) override
5694     {
5695         privateKeys = keys;
5696     }
5697 
5698     MessageContext *createMessage() override;
5699 };
5700 
5701 STACK_OF(X509) * get_pk7_certs(PKCS7 *p7)
5702 {
5703     int i = OBJ_obj2nid(p7->type);
5704     if (i == NID_pkcs7_signed)
5705         return p7->d.sign->cert;
5706     else if (i == NID_pkcs7_signedAndEnveloped)
5707         return p7->d.signed_and_enveloped->cert;
5708     else
5709         return nullptr;
5710 }
5711 
5712 class MyMessageContextThread : public QThread
5713 {
5714     Q_OBJECT
5715 public:
5716     SecureMessage::Format   format;
5717     SecureMessage::SignMode signMode;
5718     Certificate             cert;
5719     PrivateKey              key;
5720     STACK_OF(X509) * other_certs;
5721     BIO       *bi;
5722     int        flags;
5723     PKCS7     *p7;
5724     bool       ok;
5725     QByteArray out, sig;
5726 
5727     MyMessageContextThread(QObject *parent = nullptr)
5728         : QThread(parent)
5729         , ok(false)
5730     {
5731     }
5732 
5733 protected:
5734     void run() override
5735     {
5736         MyCertContext *cc = static_cast<MyCertContext *>(cert.context());
5737         MyPKeyContext *kc = static_cast<MyPKeyContext *>(key.context());
5738         X509          *cx = cc->item.cert;
5739         EVP_PKEY      *kx = kc->get_pkey();
5740 
5741         p7 = PKCS7_sign(cx, kx, other_certs, bi, flags);
5742 
5743         BIO_free(bi);
5744         sk_X509_pop_free(other_certs, X509_free);
5745 
5746         if (p7) {
5747             // printf("good\n");
5748             BIO *bo;
5749 
5750             // BIO *bo = BIO_new(BIO_s_mem());
5751             // i2d_PKCS7_bio(bo, p7);
5752             // PEM_write_bio_PKCS7(bo, p7);
5753             // SecureArray buf = bio2buf(bo);
5754             // printf("[%s]\n", buf.data());
5755 
5756             bo = BIO_new(BIO_s_mem());
5757             if (format == SecureMessage::Binary)
5758                 i2d_PKCS7_bio(bo, p7);
5759             else // Ascii
5760                 PEM_write_bio_PKCS7(bo, p7);
5761 
5762             if (SecureMessage::Detached == signMode)
5763                 sig = bio2ba(bo);
5764             else
5765                 out = bio2ba(bo);
5766 
5767             ok = true;
5768         } else {
5769             printf("bad here\n");
5770             ERR_print_errors_fp(stdout);
5771         }
5772     }
5773 };
5774 
5775 class MyMessageContext : public MessageContext
5776 {
5777     Q_OBJECT
5778 public:
5779     CMSContext             *cms;
5780     SecureMessageKey        signer;
5781     SecureMessageKeyList    to;
5782     SecureMessage::SignMode signMode;
5783     bool                    bundleSigner;
5784     bool                    smime;
5785     SecureMessage::Format   format;
5786 
5787     Operation op;
5788     bool      _finished;
5789 
5790     QByteArray in, out;
5791     QByteArray sig;
5792     int        total;
5793 
5794     CertificateChain signerChain;
5795     int              ver_ret;
5796 
5797     MyMessageContextThread *thread;
5798 
5799     MyMessageContext(CMSContext *_cms, Provider *p)
5800         : MessageContext(p, QStringLiteral("cmsmsg"))
5801     {
5802         cms = _cms;
5803 
5804         total = 0;
5805 
5806         ver_ret = 0;
5807 
5808         thread = nullptr;
5809     }
5810 
5811     ~MyMessageContext() override
5812     {
5813     }
5814 
5815     Provider::Context *clone() const override
5816     {
5817         return nullptr;
5818     }
5819 
5820     bool canSignMultiple() const override
5821     {
5822         return false;
5823     }
5824 
5825     SecureMessage::Type type() const override
5826     {
5827         return SecureMessage::CMS;
5828     }
5829 
5830     void reset() override
5831     {
5832     }
5833 
5834     void setupEncrypt(const SecureMessageKeyList &keys) override
5835     {
5836         to = keys;
5837     }
5838 
5839     void setupSign(const SecureMessageKeyList &keys, SecureMessage::SignMode m, bool bundleSigner, bool smime) override
5840     {
5841         signer             = keys.first();
5842         signMode           = m;
5843         this->bundleSigner = bundleSigner;
5844         this->smime        = smime;
5845     }
5846 
5847     void setupVerify(const QByteArray &detachedSig) override
5848     {
5849         // TODO
5850         sig = detachedSig;
5851     }
5852 
5853     void start(SecureMessage::Format f, Operation op) override
5854     {
5855         format    = f;
5856         _finished = false;
5857 
5858         // TODO: other operations
5859         // if(op == Sign)
5860         //{
5861         this->op = op;
5862         //}
5863         // else if(op == Encrypt)
5864         //{
5865         //  this->op = op;
5866         //}
5867     }
5868 
5869     void update(const QByteArray &in) override
5870     {
5871         this->in.append(in);
5872         total += in.size();
5873         QMetaObject::invokeMethod(this, "updated", Qt::QueuedConnection);
5874     }
5875 
5876     QByteArray read() override
5877     {
5878         return out;
5879     }
5880 
5881     int written() override
5882     {
5883         int x = total;
5884         total = 0;
5885         return x;
5886     }
5887 
5888     void end() override
5889     {
5890         _finished = true;
5891 
5892         // sign
5893         if (op == Sign) {
5894             const CertificateChain chain = signer.x509CertificateChain();
5895             Certificate            cert  = chain.primary();
5896             QList<Certificate>     nonroots;
5897             if (chain.count() > 1) {
5898                 for (int n = 1; n < chain.count(); ++n)
5899                     nonroots.append(chain[n]);
5900             }
5901             PrivateKey key = signer.x509PrivateKey();
5902 
5903             const PKeyContext *tmp_kc = static_cast<const PKeyContext *>(key.context());
5904 
5905             if (!tmp_kc->sameProvider(this)) {
5906                 // fprintf(stderr, "experimental: private key supplied by a different provider\n");
5907 
5908                 // make a pkey pointing to the existing private key
5909                 EVP_PKEY *pkey;
5910                 pkey = EVP_PKEY_new();
5911                 EVP_PKEY_assign_RSA(pkey, createFromExisting(key.toRSA()));
5912 
5913                 // make a new private key object to hold it
5914                 MyPKeyContext *pk = new MyPKeyContext(provider());
5915                 PKeyBase      *k  = pk->pkeyToBase(pkey, true); // does an EVP_PKEY_free()
5916                 pk->k             = k;
5917                 key.change(pk);
5918             }
5919 
5920             // allow different cert provider.  this is just a
5921             //   quick hack, enough to please qca-test
5922             if (!cert.context()->sameProvider(this)) {
5923                 // fprintf(stderr, "experimental: cert supplied by a different provider\n");
5924                 cert = Certificate::fromDER(cert.toDER());
5925                 if (cert.isNull() || !cert.context()->sameProvider(this)) {
5926                     // fprintf(stderr, "error converting cert\n");
5927                 }
5928             }
5929 
5930             // MyCertContext *cc = static_cast<MyCertContext *>(cert.context());
5931             // MyPKeyContext *kc = static_cast<MyPKeyContext *>(key.context());
5932 
5933             // X509 *cx = cc->item.cert;
5934             // EVP_PKEY *kx = kc->get_pkey();
5935 
5936             STACK_OF(X509) * other_certs;
5937             BIO *bi;
5938             int  flags;
5939             // PKCS7 *p7;
5940 
5941             // nonroots
5942             other_certs = sk_X509_new_null();
5943             for (int n = 0; n < nonroots.count(); ++n) {
5944                 X509 *x = static_cast<MyCertContext *>(nonroots[n].context())->item.cert;
5945                 X509_up_ref(x);
5946                 sk_X509_push(other_certs, x);
5947             }
5948 
5949             // printf("bundling %d other_certs\n", sk_X509_num(other_certs));
5950 
5951             bi = BIO_new(BIO_s_mem());
5952             BIO_write(bi, in.data(), in.size());
5953 
5954             flags = 0;
5955             flags |= PKCS7_BINARY;
5956             if (SecureMessage::Detached == signMode) {
5957                 flags |= PKCS7_DETACHED;
5958             }
5959             if (false == bundleSigner)
5960                 flags |= PKCS7_NOCERTS;
5961 
5962             if (thread)
5963                 delete thread;
5964             thread              = new MyMessageContextThread(this);
5965             thread->format      = format;
5966             thread->signMode    = signMode;
5967             thread->cert        = cert;
5968             thread->key         = key;
5969             thread->other_certs = other_certs;
5970             thread->bi          = bi;
5971             thread->flags       = flags;
5972             connect(thread, &MyMessageContextThread::finished, this, &MyMessageContext::thread_finished);
5973             thread->start();
5974         } else if (op == Encrypt) {
5975             // TODO: support multiple recipients
5976             Certificate target = to.first().x509CertificateChain().primary();
5977 
5978             STACK_OF(X509) * other_certs;
5979             BIO   *bi;
5980             int    flags;
5981             PKCS7 *p7;
5982 
5983             other_certs = sk_X509_new_null();
5984             X509 *x     = static_cast<MyCertContext *>(target.context())->item.cert;
5985             X509_up_ref(x);
5986             sk_X509_push(other_certs, x);
5987 
5988             bi = BIO_new(BIO_s_mem());
5989             BIO_write(bi, in.data(), in.size());
5990 
5991             flags = 0;
5992             flags |= PKCS7_BINARY;
5993             p7 = PKCS7_encrypt(other_certs, bi, EVP_des_ede3_cbc(), flags); // TODO: cipher?
5994 
5995             BIO_free(bi);
5996             sk_X509_pop_free(other_certs, X509_free);
5997 
5998             if (p7) {
5999                 // FIXME: format
6000                 BIO *bo = BIO_new(BIO_s_mem());
6001                 i2d_PKCS7_bio(bo, p7);
6002                 // PEM_write_bio_PKCS7(bo, p7);
6003                 out = bio2ba(bo);
6004                 PKCS7_free(p7);
6005             } else {
6006                 printf("bad\n");
6007                 return;
6008             }
6009         } else if (op == Verify) {
6010             // TODO: support non-detached sigs
6011 
6012             BIO *out = BIO_new(BIO_s_mem());
6013             BIO *bi  = BIO_new(BIO_s_mem());
6014             if (false == sig.isEmpty()) {
6015                 // We have detached signature
6016                 BIO_write(bi, sig.data(), sig.size());
6017             } else {
6018                 BIO_write(bi, in.data(), in.size());
6019             }
6020             PKCS7 *p7;
6021             if (format == SecureMessage::Binary)
6022                 p7 = d2i_PKCS7_bio(bi, nullptr);
6023             else // Ascii
6024                 p7 = PEM_read_bio_PKCS7(bi, nullptr, passphrase_cb, nullptr);
6025             BIO_free(bi);
6026 
6027             if (!p7) {
6028                 // TODO
6029                 printf("bad1\n");
6030                 QMetaObject::invokeMethod(this, "updated", Qt::QueuedConnection);
6031                 return;
6032             }
6033 
6034             // intermediates/signers that may not be in the blob
6035             STACK_OF(X509) *other_certs       = sk_X509_new_null();
6036             QList<Certificate> untrusted_list = cms->untrustedCerts.certificates();
6037             const QList<CRL>   untrusted_crls = cms->untrustedCerts.crls(); // we'll use the crls later
6038             for (int n = 0; n < untrusted_list.count(); ++n) {
6039                 X509 *x = static_cast<MyCertContext *>(untrusted_list[n].context())->item.cert;
6040                 X509_up_ref(x);
6041                 sk_X509_push(other_certs, x);
6042             }
6043 
6044             // get the possible message signers
6045             QList<Certificate> signers;
6046             STACK_OF(X509) *xs = PKCS7_get0_signers(p7, other_certs, 0);
6047             if (xs) {
6048                 for (int n = 0; n < sk_X509_num(xs); ++n) {
6049                     MyCertContext *cc = new MyCertContext(provider());
6050                     cc->fromX509(sk_X509_value(xs, n));
6051                     Certificate cert;
6052                     cert.change(cc);
6053                     // printf("signer: [%s]\n", qPrintable(cert.commonName()));
6054                     signers.append(cert);
6055                 }
6056                 sk_X509_free(xs);
6057             }
6058 
6059             // get the rest of the certificates lying around
6060             QList<Certificate> others;
6061             xs = get_pk7_certs(p7); // don't free
6062             if (xs) {
6063                 for (int n = 0; n < sk_X509_num(xs); ++n) {
6064                     MyCertContext *cc = new MyCertContext(provider());
6065                     cc->fromX509(sk_X509_value(xs, n));
6066                     Certificate cert;
6067                     cert.change(cc);
6068                     others.append(cert);
6069                     // printf("other: [%s]\n", qPrintable(cert.commonName()));
6070                 }
6071             }
6072 
6073             // signer needs to be supplied in the message itself
6074             //   or via cms->untrustedCerts
6075             if (signers.isEmpty()) {
6076                 QMetaObject::invokeMethod(this, "updated", Qt::QueuedConnection);
6077                 return;
6078             }
6079 
6080             // FIXME: handle more than one signer
6081             CertificateChain chain;
6082             chain += signers[0];
6083 
6084             // build chain
6085             chain = chain.complete(others);
6086 
6087             signerChain = chain;
6088 
6089             X509_STORE              *store     = X509_STORE_new();
6090             const QList<Certificate> cert_list = cms->trustedCerts.certificates();
6091             QList<CRL>               crl_list  = cms->trustedCerts.crls();
6092             for (int n = 0; n < cert_list.count(); ++n) {
6093                 // printf("trusted: [%s]\n", qPrintable(cert_list[n].commonName()));
6094                 const MyCertContext *cc = static_cast<const MyCertContext *>(cert_list[n].context());
6095                 X509                *x  = cc->item.cert;
6096                 // CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
6097                 X509_STORE_add_cert(store, x);
6098             }
6099             for (int n = 0; n < crl_list.count(); ++n) {
6100                 const MyCRLContext *cc = static_cast<const MyCRLContext *>(crl_list[n].context());
6101                 X509_CRL           *x  = cc->item.crl;
6102                 // CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
6103                 X509_STORE_add_crl(store, x);
6104             }
6105             // add these crls also
6106             crl_list = untrusted_crls;
6107             for (int n = 0; n < crl_list.count(); ++n) {
6108                 const MyCRLContext *cc = static_cast<const MyCRLContext *>(crl_list[n].context());
6109                 X509_CRL           *x  = cc->item.crl;
6110                 // CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
6111                 X509_STORE_add_crl(store, x);
6112             }
6113 
6114             int ret;
6115             if (!sig.isEmpty()) {
6116                 // Detached signMode
6117                 bi = BIO_new(BIO_s_mem());
6118                 BIO_write(bi, in.data(), in.size());
6119                 ret = PKCS7_verify(p7, other_certs, store, bi, nullptr, 0);
6120                 BIO_free(bi);
6121             } else {
6122                 ret = PKCS7_verify(p7, other_certs, store, nullptr, out, 0);
6123                 // qDebug() << "Verify: " << ret;
6124             }
6125             // if(!ret)
6126             //  ERR_print_errors_fp(stdout);
6127             sk_X509_pop_free(other_certs, X509_free);
6128             X509_STORE_free(store);
6129             PKCS7_free(p7);
6130 
6131             ver_ret = ret;
6132             // TODO
6133 
6134             QMetaObject::invokeMethod(this, "updated", Qt::QueuedConnection);
6135         } else if (op == Decrypt) {
6136             bool ok = false;
6137             for (int n = 0; n < cms->privateKeys.count(); ++n) {
6138                 CertificateChain chain = cms->privateKeys[n].x509CertificateChain();
6139                 Certificate      cert  = chain.primary();
6140                 PrivateKey       key   = cms->privateKeys[n].x509PrivateKey();
6141 
6142                 MyCertContext *cc = static_cast<MyCertContext *>(cert.context());
6143                 MyPKeyContext *kc = static_cast<MyPKeyContext *>(key.context());
6144 
6145                 X509     *cx = cc->item.cert;
6146                 EVP_PKEY *kx = kc->get_pkey();
6147 
6148                 BIO *bi = BIO_new(BIO_s_mem());
6149                 BIO_write(bi, in.data(), in.size());
6150                 PKCS7 *p7 = d2i_PKCS7_bio(bi, nullptr);
6151                 BIO_free(bi);
6152 
6153                 if (!p7) {
6154                     // TODO
6155                     printf("bad1\n");
6156                     return;
6157                 }
6158 
6159                 BIO *bo  = BIO_new(BIO_s_mem());
6160                 int  ret = PKCS7_decrypt(p7, kx, cx, bo, 0);
6161                 PKCS7_free(p7);
6162                 if (!ret)
6163                     continue;
6164 
6165                 ok  = true;
6166                 out = bio2ba(bo);
6167                 break;
6168             }
6169 
6170             if (!ok) {
6171                 // TODO
6172                 printf("bad2\n");
6173                 return;
6174             }
6175         }
6176     }
6177 
6178     bool finished() const override
6179     {
6180         return _finished;
6181     }
6182 
6183     bool waitForFinished(int msecs) override
6184     {
6185         // TODO
6186         Q_UNUSED(msecs);
6187 
6188         if (thread) {
6189             thread->wait();
6190             getresults();
6191         }
6192         return true;
6193     }
6194 
6195     bool success() const override
6196     {
6197         // TODO
6198         return true;
6199     }
6200 
6201     SecureMessage::Error errorCode() const override
6202     {
6203         // TODO
6204         return SecureMessage::ErrorUnknown;
6205     }
6206 
6207     QByteArray signature() const override
6208     {
6209         return sig;
6210     }
6211 
6212     QString hashName() const override
6213     {
6214         // TODO
6215         return QStringLiteral("sha1");
6216     }
6217 
6218     SecureMessageSignatureList signers() const override
6219     {
6220         // only report signers for verify
6221         if (op != Verify)
6222             return SecureMessageSignatureList();
6223 
6224         SecureMessageKey key;
6225         if (!signerChain.isEmpty())
6226             key.setX509CertificateChain(signerChain);
6227 
6228         // TODO/FIXME !!! InvalidSignature might be used here even
6229         //   if the signature is just fine, and the key is invalid
6230         //   (we need to use InvalidKey instead).
6231 
6232         Validity vr = ErrorValidityUnknown;
6233         if (!signerChain.isEmpty())
6234             vr = signerChain.validate(cms->trustedCerts, cms->untrustedCerts.crls());
6235 
6236         SecureMessageSignature::IdentityResult ir;
6237         if (vr == ValidityGood)
6238             ir = SecureMessageSignature::Valid;
6239         else
6240             ir = SecureMessageSignature::InvalidKey;
6241 
6242         if (!ver_ret)
6243             ir = SecureMessageSignature::InvalidSignature;
6244 
6245         SecureMessageSignature s(ir, vr, key, QDateTime::currentDateTime());
6246 
6247         // TODO
6248         return SecureMessageSignatureList() << s;
6249     }
6250 
6251     void getresults()
6252     {
6253         sig = thread->sig;
6254         out = thread->out;
6255     }
6256 
6257 private Q_SLOTS:
6258     void thread_finished()
6259     {
6260         getresults();
6261         emit updated();
6262     }
6263 };
6264 
6265 MessageContext *CMSContext::createMessage()
6266 {
6267     return new MyMessageContext(this, provider());
6268 }
6269 
6270 class opensslCipherContext : public CipherContext
6271 {
6272     Q_OBJECT
6273 public:
6274     opensslCipherContext(const EVP_CIPHER *algorithm, const int pad, Provider *p, const QString &type)
6275         : CipherContext(p, type)
6276     {
6277         m_cryptoAlgorithm = algorithm;
6278         m_context         = EVP_CIPHER_CTX_new();
6279         EVP_CIPHER_CTX_init(m_context);
6280         m_pad  = pad;
6281         m_type = type;
6282     }
6283 
6284     opensslCipherContext(const opensslCipherContext &other)
6285         : CipherContext(other)
6286     {
6287         m_cryptoAlgorithm = other.m_cryptoAlgorithm;
6288         m_context         = EVP_CIPHER_CTX_new();
6289         EVP_CIPHER_CTX_copy(m_context, other.m_context);
6290         m_direction = other.m_direction;
6291         m_pad       = other.m_pad;
6292         m_type      = other.m_type;
6293         m_tag       = other.m_tag;
6294     }
6295 
6296     ~opensslCipherContext() override
6297     {
6298         EVP_CIPHER_CTX_cleanup(m_context);
6299         EVP_CIPHER_CTX_free(m_context);
6300     }
6301 
6302     void setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv, const AuthTag &tag) override
6303     {
6304         m_tag       = tag;
6305         m_direction = dir;
6306         if ((m_cryptoAlgorithm == EVP_des_ede3()) && (key.size() == 16)) {
6307             // this is really a two key version of triple DES.
6308             m_cryptoAlgorithm = EVP_des_ede();
6309         }
6310         if (Encode == m_direction) {
6311             EVP_EncryptInit_ex(m_context, m_cryptoAlgorithm, nullptr, nullptr, nullptr);
6312             EVP_CIPHER_CTX_set_key_length(m_context, key.size());
6313             if (m_type.endsWith(QLatin1String("gcm")) || m_type.endsWith(QLatin1String("ccm"))) {
6314                 int parameter = m_type.endsWith(QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN;
6315                 EVP_CIPHER_CTX_ctrl(m_context, parameter, iv.size(), nullptr);
6316             }
6317             EVP_EncryptInit_ex(
6318                 m_context, nullptr, nullptr, (const unsigned char *)(key.data()), (const unsigned char *)(iv.data()));
6319         } else {
6320             EVP_DecryptInit_ex(m_context, m_cryptoAlgorithm, nullptr, nullptr, nullptr);
6321             EVP_CIPHER_CTX_set_key_length(m_context, key.size());
6322             if (m_type.endsWith(QLatin1String("gcm")) || m_type.endsWith(QLatin1String("ccm"))) {
6323                 int parameter = m_type.endsWith(QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN;
6324                 EVP_CIPHER_CTX_ctrl(m_context, parameter, iv.size(), nullptr);
6325             }
6326             EVP_DecryptInit_ex(
6327                 m_context, nullptr, nullptr, (const unsigned char *)(key.data()), (const unsigned char *)(iv.data()));
6328         }
6329 
6330         EVP_CIPHER_CTX_set_padding(m_context, m_pad);
6331     }
6332 
6333     Provider::Context *clone() const override
6334     {
6335         return new opensslCipherContext(*this);
6336     }
6337 
6338     int blockSize() const override
6339     {
6340         return EVP_CIPHER_CTX_block_size(m_context);
6341     }
6342 
6343     AuthTag tag() const override
6344     {
6345         return m_tag;
6346     }
6347 
6348     bool update(const SecureArray &in, SecureArray *out) override
6349     {
6350         // This works around a problem in OpenSSL, where it asserts if
6351         // there is nothing to encrypt.
6352         if (0 == in.size())
6353             return true;
6354 
6355         out->resize(in.size() + blockSize());
6356         int resultLength;
6357         if (Encode == m_direction) {
6358             if (0 ==
6359                 EVP_EncryptUpdate(
6360                     m_context, (unsigned char *)out->data(), &resultLength, (unsigned char *)in.data(), in.size())) {
6361                 return false;
6362             }
6363         } else {
6364             if (0 ==
6365                 EVP_DecryptUpdate(
6366                     m_context, (unsigned char *)out->data(), &resultLength, (unsigned char *)in.data(), in.size())) {
6367                 return false;
6368             }
6369         }
6370         out->resize(resultLength);
6371         return true;
6372     }
6373 
6374     bool final(SecureArray *out) override
6375     {
6376         out->resize(blockSize());
6377         int resultLength;
6378         if (Encode == m_direction) {
6379             if (0 == EVP_EncryptFinal_ex(m_context, (unsigned char *)out->data(), &resultLength)) {
6380                 return false;
6381             }
6382             if (m_tag.size() && (m_type.endsWith(QLatin1String("gcm")) || m_type.endsWith(QLatin1String("ccm")))) {
6383                 int parameter = m_type.endsWith(QLatin1String("gcm")) ? EVP_CTRL_GCM_GET_TAG : EVP_CTRL_CCM_GET_TAG;
6384                 if (0 == EVP_CIPHER_CTX_ctrl(m_context, parameter, m_tag.size(), (unsigned char *)m_tag.data())) {
6385                     return false;
6386                 }
6387             }
6388         } else {
6389             if (m_tag.size() && (m_type.endsWith(QLatin1String("gcm")) || m_type.endsWith(QLatin1String("ccm")))) {
6390                 int parameter = m_type.endsWith(QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_TAG : EVP_CTRL_CCM_SET_TAG;
6391                 if (0 == EVP_CIPHER_CTX_ctrl(m_context, parameter, m_tag.size(), m_tag.data())) {
6392                     return false;
6393                 }
6394             }
6395             if (0 == EVP_DecryptFinal_ex(m_context, (unsigned char *)out->data(), &resultLength)) {
6396                 return false;
6397             }
6398         }
6399         out->resize(resultLength);
6400         return true;
6401     }
6402 
6403     // Change cipher names
6404     KeyLength keyLength() const override
6405     {
6406         if (s_legacyProviderAvailable) {
6407             if (m_type.left(4) == QLatin1String("des-")) {
6408                 return KeyLength(8, 8, 1);
6409             } else if (m_type.left(5) == QLatin1String("cast5")) {
6410                 return KeyLength(5, 16, 1);
6411             } else if (m_type.left(8) == QLatin1String("blowfish")) {
6412                 // Don't know - TODO
6413                 return KeyLength(1, 32, 1);
6414             }
6415         }
6416         if (m_type.left(6) == QLatin1String("aes128")) {
6417             return KeyLength(16, 16, 1);
6418         } else if (m_type.left(6) == QLatin1String("aes192")) {
6419             return KeyLength(24, 24, 1);
6420         } else if (m_type.left(6) == QLatin1String("aes256")) {
6421             return KeyLength(32, 32, 1);
6422         } else if (m_type.left(9) == QLatin1String("tripledes")) {
6423             return KeyLength(16, 24, 1);
6424         }
6425         return KeyLength(0, 1, 1);
6426     }
6427 
6428 protected:
6429     EVP_CIPHER_CTX   *m_context;
6430     const EVP_CIPHER *m_cryptoAlgorithm;
6431     Direction         m_direction;
6432     int               m_pad;
6433     QString           m_type;
6434     AuthTag           m_tag;
6435 };
6436 
6437 static QStringList all_hash_types()
6438 {
6439     QStringList list;
6440     list += QStringLiteral("sha1");
6441 #ifdef HAVE_OPENSSL_SHA0
6442     list += QStringLiteral("sha0");
6443 #endif
6444     list += QStringLiteral("md5");
6445 #ifdef SHA224_DIGEST_LENGTH
6446     list += QStringLiteral("sha224");
6447 #endif
6448 #ifdef SHA256_DIGEST_LENGTH
6449     list += QStringLiteral("sha256");
6450 #endif
6451 #ifdef SHA384_DIGEST_LENGTH
6452     list += QStringLiteral("sha384");
6453 #endif
6454 #ifdef SHA512_DIGEST_LENGTH
6455     list += QStringLiteral("sha512");
6456 #endif
6457     if (s_legacyProviderAvailable) {
6458         list += QStringLiteral("ripemd160");
6459 #ifdef HAVE_OPENSSL_MD2
6460         list += QStringLiteral("md2");
6461 #endif
6462         list += QStringLiteral("md4");
6463 #ifdef OBJ_whirlpool
6464         list += QStringLiteral("whirlpool");
6465 #endif
6466     }
6467 
6468     return list;
6469 }
6470 
6471 static QStringList all_cipher_types()
6472 {
6473     QStringList list;
6474     list += QStringLiteral("aes128-ecb");
6475     list += QStringLiteral("aes128-cfb");
6476     list += QStringLiteral("aes128-cbc");
6477     list += QStringLiteral("aes128-cbc-pkcs7");
6478     list += QStringLiteral("aes128-ofb");
6479 #ifdef HAVE_OPENSSL_AES_CTR
6480     list += QStringLiteral("aes128-ctr");
6481 #endif
6482 #ifdef HAVE_OPENSSL_AES_GCM
6483     list += QStringLiteral("aes128-gcm");
6484 #endif
6485 #ifdef HAVE_OPENSSL_AES_CCM
6486     list += QStringLiteral("aes128-ccm");
6487 #endif
6488     list += QStringLiteral("aes192-ecb");
6489     list += QStringLiteral("aes192-cfb");
6490     list += QStringLiteral("aes192-cbc");
6491     list += QStringLiteral("aes192-cbc-pkcs7");
6492     list += QStringLiteral("aes192-ofb");
6493 #ifdef HAVE_OPENSSL_AES_CTR
6494     list += QStringLiteral("aes192-ctr");
6495 #endif
6496 #ifdef HAVE_OPENSSL_AES_GCM
6497     list += QStringLiteral("aes192-gcm");
6498 #endif
6499 #ifdef HAVE_OPENSSL_AES_CCM
6500     list += QStringLiteral("aes192-ccm");
6501 #endif
6502     list += QStringLiteral("aes256-ecb");
6503     list += QStringLiteral("aes256-cbc");
6504     list += QStringLiteral("aes256-cbc-pkcs7");
6505     list += QStringLiteral("aes256-cfb");
6506     list += QStringLiteral("aes256-ofb");
6507 #ifdef HAVE_OPENSSL_AES_CTR
6508     list += QStringLiteral("aes256-ctr");
6509 #endif
6510 #ifdef HAVE_OPENSSL_AES_GCM
6511     list += QStringLiteral("aes256-gcm");
6512 #endif
6513 #ifdef HAVE_OPENSSL_AES_CCM
6514     list += QStringLiteral("aes256-ccm");
6515 #endif
6516     list += QStringLiteral("tripledes-ecb");
6517     list += QStringLiteral("tripledes-cbc");
6518     if (s_legacyProviderAvailable) {
6519         list += QStringLiteral("blowfish-ecb");
6520         list += QStringLiteral("blowfish-cbc-pkcs7");
6521         list += QStringLiteral("blowfish-cbc");
6522         list += QStringLiteral("blowfish-cfb");
6523         list += QStringLiteral("blowfish-ofb");
6524         list += QStringLiteral("des-ecb");
6525         list += QStringLiteral("des-ecb-pkcs7");
6526         list += QStringLiteral("des-cbc");
6527         list += QStringLiteral("des-cbc-pkcs7");
6528         list += QStringLiteral("des-cfb");
6529         list += QStringLiteral("des-ofb");
6530 #ifndef OPENSSL_NO_CAST
6531         list += QStringLiteral("cast5-ecb");
6532         list += QStringLiteral("cast5-cbc");
6533         list += QStringLiteral("cast5-cbc-pkcs7");
6534         list += QStringLiteral("cast5-cfb");
6535         list += QStringLiteral("cast5-ofb");
6536 #endif
6537     }
6538     return list;
6539 }
6540 
6541 static QStringList all_mac_types()
6542 {
6543     QStringList list;
6544     list += QStringLiteral("hmac(md5)");
6545     list += QStringLiteral("hmac(sha1)");
6546 #ifdef SHA224_DIGEST_LENGTH
6547     list += QStringLiteral("hmac(sha224)");
6548 #endif
6549 #ifdef SHA256_DIGEST_LENGTH
6550     list += QStringLiteral("hmac(sha256)");
6551 #endif
6552 #ifdef SHA384_DIGEST_LENGTH
6553     list += QStringLiteral("hmac(sha384)");
6554 #endif
6555 #ifdef SHA512_DIGEST_LENGTH
6556     list += QStringLiteral("hmac(sha512)");
6557 #endif
6558     if (s_legacyProviderAvailable) {
6559         list += QStringLiteral("hmac(ripemd160)");
6560     }
6561     return list;
6562 }
6563 
6564 class opensslInfoContext : public InfoContext
6565 {
6566     Q_OBJECT
6567 public:
6568     opensslInfoContext(Provider *p)
6569         : InfoContext(p)
6570     {
6571     }
6572 
6573     Provider::Context *clone() const override
6574     {
6575         return new opensslInfoContext(*this);
6576     }
6577 
6578     QStringList supportedHashTypes() const override
6579     {
6580         return all_hash_types();
6581     }
6582 
6583     QStringList supportedCipherTypes() const override
6584     {
6585         return all_cipher_types();
6586     }
6587 
6588     QStringList supportedMACTypes() const override
6589     {
6590         return all_mac_types();
6591     }
6592 };
6593 
6594 class opensslRandomContext : public RandomContext
6595 {
6596     Q_OBJECT
6597 public:
6598     opensslRandomContext(QCA::Provider *p)
6599         : RandomContext(p)
6600     {
6601     }
6602 
6603     Context *clone() const override
6604     {
6605         return new opensslRandomContext(*this);
6606     }
6607 
6608     QCA::SecureArray nextBytes(int size) override
6609     {
6610         QCA::SecureArray buf(size);
6611         int              r;
6612         // FIXME: loop while we don't have enough random bytes.
6613         while (true) {
6614             r = RAND_bytes((unsigned char *)(buf.data()), size);
6615             if (r == 1)
6616                 break; // success
6617         }
6618         return buf;
6619     }
6620 };
6621 
6622 }
6623 
6624 using namespace opensslQCAPlugin;
6625 
6626 class opensslProvider : public Provider
6627 {
6628 public:
6629     bool openssl_initted;
6630 
6631     opensslProvider()
6632     {
6633         openssl_initted = false;
6634 // OPENSSL_VERSION_MAJOR is only defined in openssl3
6635 #ifdef OPENSSL_VERSION_MAJOR
6636         /* Load the legacy providers into the default (NULL) library context */
6637         if (OSSL_PROVIDER_try_load(nullptr, "legacy", 1)) {
6638             s_legacyProviderAvailable = true;
6639         }
6640 #else
6641         s_legacyProviderAvailable = true;
6642 #endif
6643     }
6644 
6645     void init() override
6646     {
6647         OpenSSL_add_all_algorithms();
6648         ERR_load_crypto_strings();
6649 
6650         // seed the RNG if it's not seeded yet
6651         if (RAND_status() == 0) {
6652             std::srand(time(nullptr));
6653             char buf[128];
6654             for (char &n : buf)
6655                 n = std::rand();
6656             RAND_seed(buf, 128);
6657         }
6658 
6659         openssl_initted = true;
6660     }
6661 
6662     ~opensslProvider() override
6663     {
6664         // FIXME: ?  for now we never deinit, in case other libs/code
6665         //   are using openssl
6666         /*if(!openssl_initted)
6667             return;
6668         // todo: any other shutdown?
6669         EVP_cleanup();
6670         //ENGINE_cleanup();
6671         CRYPTO_cleanup_all_ex_data();
6672         ERR_remove_state(0);
6673         ERR_free_strings();*/
6674     }
6675 
6676     int qcaVersion() const override
6677     {
6678         return QCA_VERSION;
6679     }
6680 
6681     QString name() const override
6682     {
6683         return QStringLiteral("qca-ossl");
6684     }
6685 
6686     QString credit() const override
6687     {
6688         return QStringLiteral(
6689             "This product includes cryptographic software "
6690             "written by Eric Young (eay@cryptsoft.com)");
6691     }
6692 
6693     QStringList features() const override
6694     {
6695         QStringList list;
6696         list += QStringLiteral("random");
6697         list += all_hash_types();
6698         list += all_mac_types();
6699         list += all_cipher_types();
6700         if (s_legacyProviderAvailable) {
6701 #ifdef HAVE_OPENSSL_MD2
6702             list += QStringLiteral("pbkdf1(md2)");
6703 #endif
6704             list += QStringLiteral("pbkdf1(sha1)");
6705         }
6706         list += QStringLiteral("pkcs12");
6707         list += QStringLiteral("pbkdf2(sha1)");
6708         list += QStringLiteral("hkdf(sha256)");
6709         list += QStringLiteral("pkey");
6710         list += QStringLiteral("dlgroup");
6711         list += QStringLiteral("rsa");
6712         list += QStringLiteral("dsa");
6713         list += QStringLiteral("dh");
6714         list += QStringLiteral("cert");
6715         list += QStringLiteral("csr");
6716         list += QStringLiteral("crl");
6717         list += QStringLiteral("certcollection");
6718         list += QStringLiteral("tls");
6719         list += QStringLiteral("cms");
6720         list += QStringLiteral("ca");
6721 
6722         return list;
6723     }
6724 
6725     Context *createContext(const QString &type) override
6726     {
6727         // OpenSSL_add_all_digests();
6728         if (type == QLatin1String("random"))
6729             return new opensslRandomContext(this);
6730         else if (type == QLatin1String("info"))
6731             return new opensslInfoContext(this);
6732         else if (type == QLatin1String("sha1"))
6733             return new opensslHashContext(EVP_sha1(), this, type);
6734 #ifdef HAVE_OPENSSL_SHA0
6735         else if (type == QLatin1String("sha0"))
6736             return new opensslHashContext(EVP_sha(), this, type);
6737 #endif
6738         else if (type == QLatin1String("md5"))
6739             return new opensslHashContext(EVP_md5(), this, type);
6740 #ifdef SHA224_DIGEST_LENGTH
6741         else if (type == QLatin1String("sha224"))
6742             return new opensslHashContext(EVP_sha224(), this, type);
6743 #endif
6744 #ifdef SHA256_DIGEST_LENGTH
6745         else if (type == QLatin1String("sha256"))
6746             return new opensslHashContext(EVP_sha256(), this, type);
6747 #endif
6748 #ifdef SHA384_DIGEST_LENGTH
6749         else if (type == QLatin1String("sha384"))
6750             return new opensslHashContext(EVP_sha384(), this, type);
6751 #endif
6752 #ifdef SHA512_DIGEST_LENGTH
6753         else if (type == QLatin1String("sha512"))
6754             return new opensslHashContext(EVP_sha512(), this, type);
6755 #endif
6756         else if (type == QLatin1String("pbkdf2(sha1)"))
6757             return new opensslPbkdf2Context(this, type);
6758         else if (type == QLatin1String("hkdf(sha256)"))
6759             return new opensslHkdfContext(this, type);
6760         else if (type == QLatin1String("hmac(md5)"))
6761             return new opensslHMACContext(EVP_md5(), this, type);
6762         else if (type == QLatin1String("hmac(sha1)"))
6763             return new opensslHMACContext(EVP_sha1(), this, type);
6764 #ifdef SHA224_DIGEST_LENGTH
6765         else if (type == QLatin1String("hmac(sha224)"))
6766             return new opensslHMACContext(EVP_sha224(), this, type);
6767 #endif
6768 #ifdef SHA256_DIGEST_LENGTH
6769         else if (type == QLatin1String("hmac(sha256)"))
6770             return new opensslHMACContext(EVP_sha256(), this, type);
6771 #endif
6772 #ifdef SHA384_DIGEST_LENGTH
6773         else if (type == QLatin1String("hmac(sha384)"))
6774             return new opensslHMACContext(EVP_sha384(), this, type);
6775 #endif
6776 #ifdef SHA512_DIGEST_LENGTH
6777         else if (type == QLatin1String("hmac(sha512)"))
6778             return new opensslHMACContext(EVP_sha512(), this, type);
6779 #endif
6780         else if (type == QLatin1String("aes128-ecb"))
6781             return new opensslCipherContext(EVP_aes_128_ecb(), 0, this, type);
6782         else if (type == QLatin1String("aes128-cfb"))
6783             return new opensslCipherContext(EVP_aes_128_cfb(), 0, this, type);
6784         else if (type == QLatin1String("aes128-cbc"))
6785             return new opensslCipherContext(EVP_aes_128_cbc(), 0, this, type);
6786         else if (type == QLatin1String("aes128-cbc-pkcs7"))
6787             return new opensslCipherContext(EVP_aes_128_cbc(), 1, this, type);
6788         else if (type == QLatin1String("aes128-ofb"))
6789             return new opensslCipherContext(EVP_aes_128_ofb(), 0, this, type);
6790 #ifdef HAVE_OPENSSL_AES_CTR
6791         else if (type == QLatin1String("aes128-ctr"))
6792             return new opensslCipherContext(EVP_aes_128_ctr(), 0, this, type);
6793 #endif
6794 #ifdef HAVE_OPENSSL_AES_GCM
6795         else if (type == QLatin1String("aes128-gcm"))
6796             return new opensslCipherContext(EVP_aes_128_gcm(), 0, this, type);
6797 #endif
6798 #ifdef HAVE_OPENSSL_AES_CCM
6799         else if (type == QLatin1String("aes128-ccm"))
6800             return new opensslCipherContext(EVP_aes_128_ccm(), 0, this, type);
6801 #endif
6802         else if (type == QLatin1String("aes192-ecb"))
6803             return new opensslCipherContext(EVP_aes_192_ecb(), 0, this, type);
6804         else if (type == QLatin1String("aes192-cfb"))
6805             return new opensslCipherContext(EVP_aes_192_cfb(), 0, this, type);
6806         else if (type == QLatin1String("aes192-cbc"))
6807             return new opensslCipherContext(EVP_aes_192_cbc(), 0, this, type);
6808         else if (type == QLatin1String("aes192-cbc-pkcs7"))
6809             return new opensslCipherContext(EVP_aes_192_cbc(), 1, this, type);
6810         else if (type == QLatin1String("aes192-ofb"))
6811             return new opensslCipherContext(EVP_aes_192_ofb(), 0, this, type);
6812 #ifdef HAVE_OPENSSL_AES_CTR
6813         else if (type == QLatin1String("aes192-ctr"))
6814             return new opensslCipherContext(EVP_aes_192_ctr(), 0, this, type);
6815 #endif
6816 #ifdef HAVE_OPENSSL_AES_GCM
6817         else if (type == QLatin1String("aes192-gcm"))
6818             return new opensslCipherContext(EVP_aes_192_gcm(), 0, this, type);
6819 #endif
6820 #ifdef HAVE_OPENSSL_AES_CCM
6821         else if (type == QLatin1String("aes192-ccm"))
6822             return new opensslCipherContext(EVP_aes_192_ccm(), 0, this, type);
6823 #endif
6824         else if (type == QLatin1String("aes256-ecb"))
6825             return new opensslCipherContext(EVP_aes_256_ecb(), 0, this, type);
6826         else if (type == QLatin1String("aes256-cfb"))
6827             return new opensslCipherContext(EVP_aes_256_cfb(), 0, this, type);
6828         else if (type == QLatin1String("aes256-cbc"))
6829             return new opensslCipherContext(EVP_aes_256_cbc(), 0, this, type);
6830         else if (type == QLatin1String("aes256-cbc-pkcs7"))
6831             return new opensslCipherContext(EVP_aes_256_cbc(), 1, this, type);
6832         else if (type == QLatin1String("aes256-ofb"))
6833             return new opensslCipherContext(EVP_aes_256_ofb(), 0, this, type);
6834 #ifdef HAVE_OPENSSL_AES_CTR
6835         else if (type == QLatin1String("aes256-ctr"))
6836             return new opensslCipherContext(EVP_aes_256_ctr(), 0, this, type);
6837 #endif
6838 #ifdef HAVE_OPENSSL_AES_GCM
6839         else if (type == QLatin1String("aes256-gcm"))
6840             return new opensslCipherContext(EVP_aes_256_gcm(), 0, this, type);
6841 #endif
6842 #ifdef HAVE_OPENSSL_AES_CCM
6843         else if (type == QLatin1String("aes256-ccm"))
6844             return new opensslCipherContext(EVP_aes_256_ccm(), 0, this, type);
6845 #endif
6846         else if (type == QLatin1String("pkey"))
6847             return new MyPKeyContext(this);
6848         else if (type == QLatin1String("dlgroup"))
6849             return new MyDLGroup(this);
6850         else if (type == QLatin1String("rsa"))
6851             return new RSAKey(this);
6852         else if (type == QLatin1String("dsa"))
6853             return new DSAKey(this);
6854         else if (type == QLatin1String("dh"))
6855             return new DHKey(this);
6856         else if (type == QLatin1String("cert"))
6857             return new MyCertContext(this);
6858         else if (type == QLatin1String("csr"))
6859             return new MyCSRContext(this);
6860         else if (type == QLatin1String("crl"))
6861             return new MyCRLContext(this);
6862         else if (type == QLatin1String("certcollection"))
6863             return new MyCertCollectionContext(this);
6864         else if (type == QLatin1String("tls"))
6865             return new MyTLSContext(this);
6866         else if (type == QLatin1String("cms"))
6867             return new CMSContext(this);
6868         else if (type == QLatin1String("ca"))
6869             return new MyCAContext(this);
6870         else if (type == QLatin1String("tripledes-ecb"))
6871             return new opensslCipherContext(EVP_des_ede3(), 0, this, type);
6872         else if (type == QLatin1String("tripledes-cbc"))
6873             return new opensslCipherContext(EVP_des_ede3_cbc(), 0, this, type);
6874         else if (type == QLatin1String("pkcs12"))
6875             return new MyPKCS12Context(this);
6876 
6877         else if (s_legacyProviderAvailable) {
6878             if (type == QLatin1String("blowfish-ecb"))
6879                 return new opensslCipherContext(EVP_bf_ecb(), 0, this, type);
6880             else if (type == QLatin1String("blowfish-cfb"))
6881                 return new opensslCipherContext(EVP_bf_cfb(), 0, this, type);
6882             else if (type == QLatin1String("blowfish-ofb"))
6883                 return new opensslCipherContext(EVP_bf_ofb(), 0, this, type);
6884             else if (type == QLatin1String("blowfish-cbc"))
6885                 return new opensslCipherContext(EVP_bf_cbc(), 0, this, type);
6886             else if (type == QLatin1String("blowfish-cbc-pkcs7"))
6887                 return new opensslCipherContext(EVP_bf_cbc(), 1, this, type);
6888             else if (type == QLatin1String("des-ecb"))
6889                 return new opensslCipherContext(EVP_des_ecb(), 0, this, type);
6890             else if (type == QLatin1String("des-ecb-pkcs7"))
6891                 return new opensslCipherContext(EVP_des_ecb(), 1, this, type);
6892             else if (type == QLatin1String("des-cbc"))
6893                 return new opensslCipherContext(EVP_des_cbc(), 0, this, type);
6894             else if (type == QLatin1String("des-cbc-pkcs7"))
6895                 return new opensslCipherContext(EVP_des_cbc(), 1, this, type);
6896             else if (type == QLatin1String("des-cfb"))
6897                 return new opensslCipherContext(EVP_des_cfb(), 0, this, type);
6898             else if (type == QLatin1String("des-ofb"))
6899                 return new opensslCipherContext(EVP_des_ofb(), 0, this, type);
6900 #ifndef OPENSSL_NO_CAST
6901             else if (type == QLatin1String("cast5-ecb"))
6902                 return new opensslCipherContext(EVP_cast5_ecb(), 0, this, type);
6903             else if (type == QLatin1String("cast5-cbc"))
6904                 return new opensslCipherContext(EVP_cast5_cbc(), 0, this, type);
6905             else if (type == QLatin1String("cast5-cbc-pkcs7"))
6906                 return new opensslCipherContext(EVP_cast5_cbc(), 1, this, type);
6907             else if (type == QLatin1String("cast5-cfb"))
6908                 return new opensslCipherContext(EVP_cast5_cfb(), 0, this, type);
6909             else if (type == QLatin1String("cast5-ofb"))
6910                 return new opensslCipherContext(EVP_cast5_ofb(), 0, this, type);
6911 #endif
6912             else if (type == QLatin1String("hmac(ripemd160)"))
6913                 return new opensslHMACContext(EVP_ripemd160(), this, type);
6914             else if (type == QLatin1String("ripemd160"))
6915                 return new opensslHashContext(EVP_ripemd160(), this, type);
6916 #ifdef HAVE_OPENSSL_MD2
6917             else if (type == QLatin1String("md2"))
6918                 return new opensslHashContext(EVP_md2(), this, type);
6919             else if (type == QLatin1String("pbkdf1(md2)"))
6920                 return new opensslPbkdf1Context(EVP_md2(), this, type);
6921 #endif
6922             else if (type == QLatin1String("md4"))
6923                 return new opensslHashContext(EVP_md4(), this, type);
6924 #ifdef OBJ_whirlpool
6925             else if (type == QLatin1String("whirlpool"))
6926                 return new opensslHashContext(EVP_whirlpool(), this, type);
6927 #endif
6928             else if (type == QLatin1String("pbkdf1(sha1)"))
6929                 return new opensslPbkdf1Context(EVP_sha1(), this, type);
6930         }
6931 
6932         return nullptr;
6933     }
6934 };
6935 
6936 class opensslPlugin : public QObject, public QCAPlugin
6937 {
6938     Q_OBJECT
6939     Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0")
6940     Q_INTERFACES(QCAPlugin)
6941 public:
6942     Provider *createProvider() override
6943     {
6944         return new opensslProvider;
6945     }
6946 };
6947 
6948 #include "qca-ossl.moc"