1/*
2 * Copyright (C) 2004-2007 Justin Karneges <justin@affinix.com>
3 * Copyright (C) 2004-2006 Brad Hards <bradh@frogmouth.net>
4 * Copyright (C) 2013-2016 Ivan Romanov <drizt@land.ru>
5 * Copyright (C) 2017 Fabian Vogt <fabian@ritter-vogt.de>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 */
22
23#include <QDebug>
24#include <QElapsedTimer>
25#include <QtCrypto>
26#include <QtPlugin>
27#include <qcaprovider.h>
28
29#include <openssl/evp.h>
30#include <openssl/hmac.h>
31
32#include <cstdio>
33#include <cstdlib>
34#include <iostream>
35#include <memory>
36
37#include <openssl/err.h>
38#include <openssl/opensslv.h>
39#include <openssl/pem.h>
40#include <openssl/pkcs12.h>
41#include <openssl/rand.h>
42#include <openssl/ssl.h>
43#include <openssl/x509v3.h>
44#ifdef OPENSSL_VERSION_MAJOR
45#include <openssl/provider.h>
46#endif
47
48#include <openssl/kdf.h>
49
50using namespace QCA;
51
52namespace {
53struct DsaDeleter
54{
55 void operator()(DSA *pointer)
56 {
57 if (pointer)
58 DSA_free(r: pointer);
59 }
60};
61
62static bool s_legacyProviderAvailable = false;
63} // end of anonymous namespace
64
65namespace opensslQCAPlugin {
66
67//----------------------------------------------------------------------------
68// Util
69//----------------------------------------------------------------------------
70static SecureArray bio2buf(BIO *b)
71{
72 SecureArray buf;
73 while (true) {
74 SecureArray block(1024);
75 int ret = BIO_read(b, data: block.data(), dlen: block.size());
76 if (ret <= 0)
77 break;
78 block.resize(size: ret);
79 buf.append(a: block);
80 if (ret != 1024)
81 break;
82 }
83 BIO_free(a: b);
84 return buf;
85}
86
87static QByteArray bio2ba(BIO *b)
88{
89 QByteArray buf;
90 while (true) {
91 QByteArray block(1024, 0);
92 int ret = BIO_read(b, data: block.data(), dlen: block.size());
93 if (ret <= 0)
94 break;
95 block.resize(size: ret);
96 buf.append(a: block);
97 if (ret != 1024)
98 break;
99 }
100 BIO_free(a: b);
101 return buf;
102}
103
104static BigInteger bn2bi(const BIGNUM *n)
105{
106 SecureArray buf(BN_num_bytes(n) + 1);
107 buf[0] = 0; // positive
108 BN_bn2bin(a: n, to: (unsigned char *)buf.data() + 1);
109 return BigInteger(buf);
110}
111
112static BigInteger bn2bi_free(BIGNUM *n)
113{
114 BigInteger bi = bn2bi(n);
115 BN_free(a: n);
116 return bi;
117}
118
119static BIGNUM *bi2bn(const BigInteger &n)
120{
121 SecureArray buf = n.toArray();
122 return BN_bin2bn(s: (const unsigned char *)buf.data(), len: buf.size(), ret: nullptr);
123}
124
125// take lowest bytes of BIGNUM to fit
126// pad with high byte zeroes to fit
127static SecureArray bn2fixedbuf(const BIGNUM *n, int size)
128{
129 SecureArray buf(BN_num_bytes(n));
130 BN_bn2bin(a: n, to: (unsigned char *)buf.data());
131
132 SecureArray out(size);
133 memset(s: out.data(), c: 0, n: size);
134 int len = qMin(a: size, b: buf.size());
135 memcpy(dest: out.data() + (size - len), src: buf.data(), n: len);
136 return out;
137}
138
139static SecureArray dsasig_der_to_raw(const SecureArray &in)
140{
141 DSA_SIG *sig = DSA_SIG_new();
142 const unsigned char *inp = (const unsigned char *)in.data();
143 d2i_DSA_SIG(a: &sig, in: &inp, len: in.size());
144
145 const BIGNUM *bnr, *bns;
146 DSA_SIG_get0(sig, pr: &bnr, ps: &bns);
147
148 SecureArray part_r = bn2fixedbuf(n: bnr, size: 20);
149 SecureArray part_s = bn2fixedbuf(n: bns, size: 20);
150 SecureArray result;
151 result.append(a: part_r);
152 result.append(a: part_s);
153
154 DSA_SIG_free(a: sig);
155 return result;
156}
157
158static SecureArray dsasig_raw_to_der(const SecureArray &in)
159{
160 if (in.size() != 40)
161 return SecureArray();
162
163 DSA_SIG *sig = DSA_SIG_new();
164 SecureArray part_r(20);
165 BIGNUM *bnr;
166 SecureArray part_s(20);
167 BIGNUM *bns;
168 memcpy(dest: part_r.data(), src: in.data(), n: 20);
169 memcpy(dest: part_s.data(), src: in.data() + 20, n: 20);
170 bnr = BN_bin2bn(s: (const unsigned char *)part_r.data(), len: part_r.size(), ret: nullptr);
171 bns = BN_bin2bn(s: (const unsigned char *)part_s.data(), len: part_s.size(), ret: nullptr);
172
173 if (DSA_SIG_set0(sig, r: bnr, s: bns) == 0)
174 return SecureArray();
175 // Not documented what happens in the failure case, free bnr and bns?
176
177 int len = i2d_DSA_SIG(a: sig, out: nullptr);
178 SecureArray result(len);
179 unsigned char *p = (unsigned char *)result.data();
180 i2d_DSA_SIG(a: sig, out: &p);
181
182 DSA_SIG_free(a: sig);
183 return result;
184}
185
186static int passphrase_cb(char *buf, int size, int rwflag, void *u)
187{
188 Q_UNUSED(buf);
189 Q_UNUSED(size);
190 Q_UNUSED(rwflag);
191 Q_UNUSED(u);
192 return 0;
193}
194
195/*static bool is_basic_constraint(const ConstraintType &t)
196{
197 bool basic = false;
198 switch(t.known())
199 {
200 case DigitalSignature:
201 case NonRepudiation:
202 case KeyEncipherment:
203 case DataEncipherment:
204 case KeyAgreement:
205 case KeyCertificateSign:
206 case CRLSign:
207 case EncipherOnly:
208 case DecipherOnly:
209 basic = true;
210 break;
211
212 case ServerAuth:
213 case ClientAuth:
214 case CodeSigning:
215 case EmailProtection:
216 case IPSecEndSystem:
217 case IPSecTunnel:
218 case IPSecUser:
219 case TimeStamping:
220 case OCSPSigning:
221 break;
222 }
223 return basic;
224}
225
226static Constraints basic_only(const Constraints &list)
227{
228 Constraints out;
229 for(int n = 0; n < list.count(); ++n)
230 {
231 if(is_basic_constraint(list[n]))
232 out += list[n];
233 }
234 return out;
235}
236
237static Constraints ext_only(const Constraints &list)
238{
239 Constraints out;
240 for(int n = 0; n < list.count(); ++n)
241 {
242 if(!is_basic_constraint(list[n]))
243 out += list[n];
244 }
245 return out;
246}*/
247
248// logic from Botan
249/*static Constraints find_constraints(const PKeyContext &key, const Constraints &orig)
250{
251 Constraints constraints;
252
253 if(key.key()->type() == PKey::RSA)
254 constraints += KeyEncipherment;
255
256 if(key.key()->type() == PKey::DH)
257 constraints += KeyAgreement;
258
259 if(key.key()->type() == PKey::RSA || key.key()->type() == PKey::DSA)
260 {
261 constraints += DigitalSignature;
262 constraints += NonRepudiation;
263 }
264
265 Constraints limits = basic_only(orig);
266 Constraints the_rest = ext_only(orig);
267
268 if(!limits.isEmpty())
269 {
270 Constraints reduced;
271 for(int n = 0; n < constraints.count(); ++n)
272 {
273 if(limits.contains(constraints[n]))
274 reduced += constraints[n];
275 }
276 constraints = reduced;
277 }
278
279 constraints += the_rest;
280
281 return constraints;
282}*/
283
284static void try_add_name_item(X509_NAME **name, int nid, const QString &val)
285{
286 if (val.isEmpty())
287 return;
288 const QByteArray buf = val.toLatin1();
289 if (!(*name))
290 *name = X509_NAME_new();
291 X509_NAME_add_entry_by_NID(name: *name, nid, MBSTRING_ASC, bytes: (const unsigned char *)buf.data(), len: buf.size(), loc: -1, set: 0);
292}
293
294static X509_NAME *new_cert_name(const CertificateInfo &info)
295{
296 X509_NAME *name = nullptr;
297 // FIXME support multiple items of each type
298 try_add_name_item(name: &name, NID_commonName, val: info.value(key: CommonName));
299 try_add_name_item(name: &name, NID_countryName, val: info.value(key: Country));
300 try_add_name_item(name: &name, NID_localityName, val: info.value(key: Locality));
301 try_add_name_item(name: &name, NID_stateOrProvinceName, val: info.value(key: State));
302 try_add_name_item(name: &name, NID_organizationName, val: info.value(key: Organization));
303 try_add_name_item(name: &name, NID_organizationalUnitName, val: info.value(key: OrganizationalUnit));
304 return name;
305}
306
307static void try_get_name_item(X509_NAME *name, int nid, const CertificateInfoType &t, CertificateInfo *info)
308{
309 int loc;
310 loc = -1;
311 while ((loc = X509_NAME_get_index_by_NID(name, nid, lastpos: loc)) != -1) {
312 X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, loc);
313 ASN1_STRING *data = X509_NAME_ENTRY_get_data(ne);
314 QByteArray cs((const char *)data->data, data->length);
315 info->insert(key: t, value: QString::fromLatin1(ba: cs));
316 }
317}
318
319static void
320try_get_name_item_by_oid(X509_NAME *name, const QString &oidText, const CertificateInfoType &t, CertificateInfo *info)
321{
322 ASN1_OBJECT *oid = OBJ_txt2obj(s: oidText.toLatin1().data(), no_name: 1); // 1 = only accept dotted input
323 if (!oid)
324 return;
325
326 int loc;
327 loc = -1;
328 while ((loc = X509_NAME_get_index_by_OBJ(name, obj: oid, lastpos: loc)) != -1) {
329 X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, loc);
330 ASN1_STRING *data = X509_NAME_ENTRY_get_data(ne);
331 QByteArray cs((const char *)data->data, data->length);
332 info->insert(key: t, value: QString::fromLatin1(ba: cs));
333 qDebug() << "oid: " << oidText << ", result: " << cs;
334 }
335 ASN1_OBJECT_free(a: oid);
336}
337
338static CertificateInfo get_cert_name(X509_NAME *name)
339{
340 CertificateInfo info;
341 try_get_name_item(name, NID_commonName, t: CommonName, info: &info);
342 try_get_name_item(name, NID_countryName, t: Country, info: &info);
343 try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.3"), t: IncorporationCountry, info: &info);
344 try_get_name_item(name, NID_localityName, t: Locality, info: &info);
345 try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.1"), t: IncorporationLocality, info: &info);
346 try_get_name_item(name, NID_stateOrProvinceName, t: State, info: &info);
347 try_get_name_item_by_oid(name, QStringLiteral("1.3.6.1.4.1.311.60.2.1.2"), t: IncorporationState, info: &info);
348 try_get_name_item(name, NID_organizationName, t: Organization, info: &info);
349 try_get_name_item(name, NID_organizationalUnitName, t: OrganizationalUnit, info: &info);
350
351 // legacy email
352 {
353 CertificateInfo p9_info;
354 try_get_name_item(name, NID_pkcs9_emailAddress, t: EmailLegacy, info: &p9_info);
355 const QList<QString> emails = info.values(key: Email);
356#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
357 QMultiMapIterator<CertificateInfoType, QString> it(p9_info);
358#else
359 QMapIterator<CertificateInfoType, QString> it(p9_info);
360#endif
361 while (it.hasNext()) {
362 it.next();
363 if (!emails.contains(str: it.value()))
364 info.insert(key: Email, value: it.value());
365 }
366 }
367
368 return info;
369}
370
371static X509_EXTENSION *new_subject_key_id(X509 *cert)
372{
373 X509V3_CTX ctx;
374 X509V3_set_ctx_nodb(&ctx);
375 X509V3_set_ctx(ctx: &ctx, issuer: nullptr, subject: cert, req: nullptr, crl: nullptr, flags: 0);
376 X509_EXTENSION *ex = X509V3_EXT_conf_nid(conf: nullptr, ctx: &ctx, NID_subject_key_identifier, value: (char *)"hash");
377 return ex;
378}
379
380static X509_EXTENSION *new_basic_constraints(bool ca, int pathlen)
381{
382 BASIC_CONSTRAINTS *bs = BASIC_CONSTRAINTS_new();
383 bs->ca = (ca ? 1 : 0);
384 bs->pathlen = ASN1_INTEGER_new();
385 ASN1_INTEGER_set(a: bs->pathlen, v: pathlen);
386
387 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, crit: 1, ext_struc: bs); // 1 = critical
388 BASIC_CONSTRAINTS_free(a: bs);
389 return ex;
390}
391
392static void get_basic_constraints(X509_EXTENSION *ex, bool *ca, int *pathlen)
393{
394 BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext: ex);
395 *ca = (bs->ca ? true : false);
396 if (bs->pathlen)
397 *pathlen = ASN1_INTEGER_get(a: bs->pathlen);
398 else
399 *pathlen = 0;
400 BASIC_CONSTRAINTS_free(a: bs);
401}
402
403enum ConstraintBit
404{
405 Bit_DigitalSignature = 0,
406 Bit_NonRepudiation = 1,
407 Bit_KeyEncipherment = 2,
408 Bit_DataEncipherment = 3,
409 Bit_KeyAgreement = 4,
410 Bit_KeyCertificateSign = 5,
411 Bit_CRLSign = 6,
412 Bit_EncipherOnly = 7,
413 Bit_DecipherOnly = 8
414};
415
416static QByteArray ipaddress_string_to_bytes(const QString &)
417{
418 return QByteArray(4, 0);
419}
420
421static GENERAL_NAME *new_general_name(const CertificateInfoType &t, const QString &val)
422{
423 GENERAL_NAME *name = nullptr;
424 switch (t.known()) {
425 case Email:
426 {
427 const QByteArray buf = val.toLatin1();
428
429 ASN1_IA5STRING *str = ASN1_IA5STRING_new();
430 ASN1_STRING_set(str: (ASN1_STRING *)str, data: (const unsigned char *)buf.data(), len: buf.size());
431
432 name = GENERAL_NAME_new();
433 name->type = GEN_EMAIL;
434 name->d.rfc822Name = str;
435 break;
436 }
437 case URI:
438 {
439 const QByteArray buf = val.toLatin1();
440
441 ASN1_IA5STRING *str = ASN1_IA5STRING_new();
442 ASN1_STRING_set(str: (ASN1_STRING *)str, data: (const unsigned char *)buf.data(), len: buf.size());
443
444 name = GENERAL_NAME_new();
445 name->type = GEN_URI;
446 name->d.uniformResourceIdentifier = str;
447 break;
448 }
449 case DNS:
450 {
451 const QByteArray buf = val.toLatin1();
452
453 ASN1_IA5STRING *str = ASN1_IA5STRING_new();
454 ASN1_STRING_set(str: (ASN1_STRING *)str, data: (const unsigned char *)buf.data(), len: buf.size());
455
456 name = GENERAL_NAME_new();
457 name->type = GEN_DNS;
458 name->d.dNSName = str;
459 break;
460 }
461 case IPAddress:
462 {
463 const QByteArray buf = ipaddress_string_to_bytes(val);
464
465 ASN1_OCTET_STRING *str = ASN1_OCTET_STRING_new();
466 ASN1_STRING_set(str: (ASN1_STRING *)str, data: (const unsigned char *)buf.data(), len: buf.size());
467
468 name = GENERAL_NAME_new();
469 name->type = GEN_IPADD;
470 name->d.iPAddress = str;
471 break;
472 }
473 case XMPP:
474 {
475 const QByteArray buf = val.toUtf8();
476
477 ASN1_UTF8STRING *str = ASN1_UTF8STRING_new();
478 ASN1_STRING_set(str: (ASN1_STRING *)str, data: (const unsigned char *)buf.data(), len: buf.size());
479
480 ASN1_TYPE *at = ASN1_TYPE_new();
481 at->type = V_ASN1_UTF8STRING;
482 at->value.utf8string = str;
483
484 OTHERNAME *other = OTHERNAME_new();
485 other->type_id = OBJ_txt2obj(s: "1.3.6.1.5.5.7.8.5", no_name: 1); // 1 = only accept dotted input
486 other->value = at;
487
488 name = GENERAL_NAME_new();
489 name->type = GEN_OTHERNAME;
490 name->d.otherName = other;
491 break;
492 }
493 default:
494 break;
495 }
496 return name;
497}
498
499static void try_add_general_name(GENERAL_NAMES **gn, const CertificateInfoType &t, const QString &val)
500{
501 if (val.isEmpty())
502 return;
503 GENERAL_NAME *name = new_general_name(t, val);
504 if (name) {
505 if (!(*gn))
506 *gn = sk_GENERAL_NAME_new_null();
507 sk_GENERAL_NAME_push(*gn, name);
508 }
509}
510
511static X509_EXTENSION *new_cert_subject_alt_name(const CertificateInfo &info)
512{
513 GENERAL_NAMES *gn = nullptr;
514 // FIXME support multiple items of each type
515 try_add_general_name(gn: &gn, t: Email, val: info.value(key: Email));
516 try_add_general_name(gn: &gn, t: URI, val: info.value(key: URI));
517 try_add_general_name(gn: &gn, t: DNS, val: info.value(key: DNS));
518 try_add_general_name(gn: &gn, t: IPAddress, val: info.value(key: IPAddress));
519 try_add_general_name(gn: &gn, t: XMPP, val: info.value(key: XMPP));
520 if (!gn)
521 return nullptr;
522
523 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_subject_alt_name, crit: 0, ext_struc: gn);
524 sk_GENERAL_NAME_pop_free(gn, GENERAL_NAME_free);
525 return ex;
526}
527
528static GENERAL_NAME *find_next_general_name(GENERAL_NAMES *names, int type, int *pos)
529{
530 int temp = *pos;
531 GENERAL_NAME *gn = nullptr;
532 *pos = -1;
533 for (int n = temp; n < sk_GENERAL_NAME_num(names); ++n) {
534 GENERAL_NAME *i = sk_GENERAL_NAME_value(names, n);
535 if (i->type == type) {
536 gn = i;
537 *pos = n;
538 break;
539 }
540 }
541 return gn;
542}
543
544static QByteArray qca_ASN1_STRING_toByteArray(ASN1_STRING *x)
545{
546 return QByteArray(reinterpret_cast<const char *>(ASN1_STRING_get0_data(x)), ASN1_STRING_length(x));
547}
548
549static void try_get_general_name(GENERAL_NAMES *names, const CertificateInfoType &t, CertificateInfo *info)
550{
551 switch (t.known()) {
552 case Email:
553 {
554 int pos = 0;
555 while (pos != -1) {
556 GENERAL_NAME *gn = find_next_general_name(names, GEN_EMAIL, pos: &pos);
557 if (pos != -1) {
558 const QByteArray cs = qca_ASN1_STRING_toByteArray(x: gn->d.rfc822Name);
559 info->insert(key: t, value: QString::fromLatin1(ba: cs));
560 ++pos;
561 }
562 }
563 break;
564 }
565 case URI:
566 {
567 int pos = 0;
568 while (pos != -1) {
569 GENERAL_NAME *gn = find_next_general_name(names, GEN_URI, pos: &pos);
570 if (pos != -1) {
571 const QByteArray cs = qca_ASN1_STRING_toByteArray(x: gn->d.uniformResourceIdentifier);
572 info->insert(key: t, value: QString::fromLatin1(ba: cs));
573 ++pos;
574 }
575 }
576 break;
577 }
578 case DNS:
579 {
580 int pos = 0;
581 while (pos != -1) {
582 GENERAL_NAME *gn = find_next_general_name(names, GEN_DNS, pos: &pos);
583 if (pos != -1) {
584 const QByteArray cs = qca_ASN1_STRING_toByteArray(x: gn->d.dNSName);
585 info->insert(key: t, value: QString::fromLatin1(ba: cs));
586 ++pos;
587 }
588 }
589 break;
590 }
591 case IPAddress:
592 {
593 int pos = 0;
594 while (pos != -1) {
595 GENERAL_NAME *gn = find_next_general_name(names, GEN_IPADD, pos: &pos);
596 if (pos != -1) {
597 ASN1_OCTET_STRING *str = gn->d.iPAddress;
598 const QByteArray buf = qca_ASN1_STRING_toByteArray(x: str);
599
600 QString out;
601 // IPv4 (TODO: handle IPv6)
602 if (buf.size() == 4) {
603 out = QStringLiteral("0.0.0.0");
604 } else
605 break;
606 info->insert(key: t, value: out);
607 ++pos;
608 }
609 }
610 break;
611 }
612 case XMPP:
613 {
614 int pos = 0;
615 while (pos != -1) {
616 GENERAL_NAME *gn = find_next_general_name(names, GEN_OTHERNAME, pos: &pos);
617 if (pos != -1) {
618 OTHERNAME *other = gn->d.otherName;
619 if (!other)
620 break;
621
622 ASN1_OBJECT *obj = OBJ_txt2obj(s: "1.3.6.1.5.5.7.8.5", no_name: 1); // 1 = only accept dotted input
623 if (OBJ_cmp(a: other->type_id, b: obj) != 0)
624 break;
625 ASN1_OBJECT_free(a: obj);
626
627 ASN1_TYPE *at = other->value;
628 if (at->type != V_ASN1_UTF8STRING)
629 break;
630
631 ASN1_UTF8STRING *str = at->value.utf8string;
632 const QByteArray buf = qca_ASN1_STRING_toByteArray(x: str);
633 info->insert(key: t, value: QString::fromUtf8(ba: buf));
634 ++pos;
635 }
636 }
637 break;
638 }
639 default:
640 break;
641 }
642}
643
644static CertificateInfo get_cert_alt_name(X509_EXTENSION *ex)
645{
646 CertificateInfo info;
647 GENERAL_NAMES *gn = (GENERAL_NAMES *)X509V3_EXT_d2i(ext: ex);
648 try_get_general_name(names: gn, t: Email, info: &info);
649 try_get_general_name(names: gn, t: URI, info: &info);
650 try_get_general_name(names: gn, t: DNS, info: &info);
651 try_get_general_name(names: gn, t: IPAddress, info: &info);
652 try_get_general_name(names: gn, t: XMPP, info: &info);
653 GENERAL_NAMES_free(a: gn);
654 return info;
655}
656
657static X509_EXTENSION *new_cert_key_usage(const Constraints &constraints)
658{
659 ASN1_BIT_STRING *keyusage = nullptr;
660 for (int n = 0; n < constraints.count(); ++n) {
661 int bit = -1;
662 switch (constraints[n].known()) {
663 case DigitalSignature:
664 bit = Bit_DigitalSignature;
665 break;
666 case NonRepudiation:
667 bit = Bit_NonRepudiation;
668 break;
669 case KeyEncipherment:
670 bit = Bit_KeyEncipherment;
671 break;
672 case DataEncipherment:
673 bit = Bit_DataEncipherment;
674 break;
675 case KeyAgreement:
676 bit = Bit_KeyAgreement;
677 break;
678 case KeyCertificateSign:
679 bit = Bit_KeyCertificateSign;
680 break;
681 case CRLSign:
682 bit = Bit_CRLSign;
683 break;
684 case EncipherOnly:
685 bit = Bit_EncipherOnly;
686 break;
687 case DecipherOnly:
688 bit = Bit_DecipherOnly;
689 break;
690 default:
691 break;
692 }
693 if (bit != -1) {
694 if (!keyusage)
695 keyusage = ASN1_BIT_STRING_new();
696 ASN1_BIT_STRING_set_bit(a: keyusage, n: bit, value: 1);
697 }
698 }
699 if (!keyusage)
700 return nullptr;
701
702 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_key_usage, crit: 1, ext_struc: keyusage); // 1 = critical
703 ASN1_BIT_STRING_free(a: keyusage);
704 return ex;
705}
706
707static Constraints get_cert_key_usage(X509_EXTENSION *ex)
708{
709 Constraints constraints;
710 int bit_table[9] = {DigitalSignature,
711 NonRepudiation,
712 KeyEncipherment,
713 DataEncipherment,
714 KeyAgreement,
715 KeyCertificateSign,
716 CRLSign,
717 EncipherOnly,
718 DecipherOnly};
719
720 ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ext: ex);
721 for (int n = 0; n < 9; ++n) {
722 if (ASN1_BIT_STRING_get_bit(a: keyusage, n))
723 constraints += ConstraintType((ConstraintTypeKnown)bit_table[n]);
724 }
725 ASN1_BIT_STRING_free(a: keyusage);
726 return constraints;
727}
728
729static X509_EXTENSION *new_cert_ext_key_usage(const Constraints &constraints)
730{
731 EXTENDED_KEY_USAGE *extkeyusage = nullptr;
732 for (int n = 0; n < constraints.count(); ++n) {
733 int nid = -1;
734 // TODO: don't use known/nid, and instead just use OIDs
735 switch (constraints[n].known()) {
736 case ServerAuth:
737 nid = NID_server_auth;
738 break;
739 case ClientAuth:
740 nid = NID_client_auth;
741 break;
742 case CodeSigning:
743 nid = NID_code_sign;
744 break;
745 case EmailProtection:
746 nid = NID_email_protect;
747 break;
748 case IPSecEndSystem:
749 nid = NID_ipsecEndSystem;
750 break;
751 case IPSecTunnel:
752 nid = NID_ipsecTunnel;
753 break;
754 case IPSecUser:
755 nid = NID_ipsecUser;
756 break;
757 case TimeStamping:
758 nid = NID_time_stamp;
759 break;
760 case OCSPSigning:
761 nid = NID_OCSP_sign;
762 break;
763 default:
764 break;
765 }
766 if (nid != -1) {
767 if (!extkeyusage)
768 extkeyusage = sk_ASN1_OBJECT_new_null();
769 ASN1_OBJECT *obj = OBJ_nid2obj(n: nid);
770 sk_ASN1_OBJECT_push(extkeyusage, obj);
771 }
772 }
773 if (!extkeyusage)
774 return nullptr;
775
776 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_ext_key_usage, crit: 0, ext_struc: extkeyusage); // 0 = not critical
777 sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);
778 return ex;
779}
780
781static Constraints get_cert_ext_key_usage(X509_EXTENSION *ex)
782{
783 Constraints constraints;
784
785 EXTENDED_KEY_USAGE *extkeyusage = (EXTENDED_KEY_USAGE *)X509V3_EXT_d2i(ext: ex);
786 for (int n = 0; n < sk_ASN1_OBJECT_num(extkeyusage); ++n) {
787 ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(extkeyusage, n);
788 int nid = OBJ_obj2nid(o: obj);
789 if (nid == NID_undef)
790 continue;
791
792 // TODO: don't use known/nid, and instead just use OIDs
793 int t = -1;
794 switch (nid) {
795 case NID_server_auth:
796 t = ServerAuth;
797 break;
798 case NID_client_auth:
799 t = ClientAuth;
800 break;
801 case NID_code_sign:
802 t = CodeSigning;
803 break;
804 case NID_email_protect:
805 t = EmailProtection;
806 break;
807 case NID_ipsecEndSystem:
808 t = IPSecEndSystem;
809 break;
810 case NID_ipsecTunnel:
811 t = IPSecTunnel;
812 break;
813 case NID_ipsecUser:
814 t = IPSecUser;
815 break;
816 case NID_time_stamp:
817 t = TimeStamping;
818 break;
819 case NID_OCSP_sign:
820 t = OCSPSigning;
821 break;
822 };
823
824 if (t == -1)
825 continue;
826
827 constraints.append(t: ConstraintType((ConstraintTypeKnown)t));
828 }
829 sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);
830 return constraints;
831}
832
833static X509_EXTENSION *new_cert_policies(const QStringList &policies)
834{
835 STACK_OF(POLICYINFO) *pols = nullptr;
836 for (int n = 0; n < policies.count(); ++n) {
837 const QByteArray cs = policies[n].toLatin1();
838 ASN1_OBJECT *obj = OBJ_txt2obj(s: cs.data(), no_name: 1); // 1 = only accept dotted input
839 if (!obj)
840 continue;
841 if (!pols)
842 pols = sk_POLICYINFO_new_null();
843 POLICYINFO *pol = POLICYINFO_new();
844 pol->policyid = obj;
845 sk_POLICYINFO_push(pols, pol);
846 }
847 if (!pols)
848 return nullptr;
849
850 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, crit: 0, ext_struc: pols); // 0 = not critical
851 sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
852 return ex;
853}
854
855static QStringList get_cert_policies(X509_EXTENSION *ex)
856{
857 QStringList out;
858 STACK_OF(POLICYINFO) *pols = (STACK_OF(POLICYINFO) *)X509V3_EXT_d2i(ext: ex);
859 for (int n = 0; n < sk_POLICYINFO_num(pols); ++n) {
860 POLICYINFO *pol = sk_POLICYINFO_value(pols, n);
861 QByteArray buf(128, 0);
862 const auto len = OBJ_obj2txt(buf: (char *)buf.data(), buf_len: buf.size(), a: pol->policyid, no_name: 1); // 1 = only accept dotted input
863 if (len > 0)
864 out += QString::fromLatin1(ba: buf.left(len));
865 }
866 sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
867 return out;
868}
869
870static QByteArray get_cert_subject_key_id(X509_EXTENSION *ex)
871{
872 ASN1_OCTET_STRING *skid = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext: ex);
873 const QByteArray out = qca_ASN1_STRING_toByteArray(x: skid);
874 ASN1_OCTET_STRING_free(a: skid);
875 return out;
876}
877
878// If you get any more crashes in this code, please provide a copy
879// of the cert to bradh AT frogmouth.net
880static QByteArray get_cert_issuer_key_id(X509_EXTENSION *ex)
881{
882 AUTHORITY_KEYID *akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext: ex);
883 QByteArray out;
884 if (akid->keyid)
885 out = qca_ASN1_STRING_toByteArray(x: akid->keyid);
886 AUTHORITY_KEYID_free(a: akid);
887 return out;
888}
889
890static Validity convert_verify_error(int err)
891{
892 // TODO: ErrorExpiredCA
893 Validity rc;
894 switch (err) {
895 case X509_V_ERR_CERT_REJECTED:
896 rc = ErrorRejected;
897 break;
898 case X509_V_ERR_CERT_UNTRUSTED:
899 rc = ErrorUntrusted;
900 break;
901 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
902 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
903 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
904 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
905 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
906 rc = ErrorSignatureFailed;
907 break;
908 case X509_V_ERR_INVALID_CA:
909 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
910 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
911 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
912 rc = ErrorInvalidCA;
913 break;
914 case X509_V_ERR_INVALID_PURPOSE: // note: not used by store verify
915 rc = ErrorInvalidPurpose;
916 break;
917 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
918 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
919 rc = ErrorSelfSigned;
920 break;
921 case X509_V_ERR_CERT_REVOKED:
922 rc = ErrorRevoked;
923 break;
924 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
925 rc = ErrorPathLengthExceeded;
926 break;
927 case X509_V_ERR_CERT_NOT_YET_VALID:
928 case X509_V_ERR_CERT_HAS_EXPIRED:
929 case X509_V_ERR_CRL_NOT_YET_VALID:
930 case X509_V_ERR_CRL_HAS_EXPIRED:
931 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
932 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
933 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
934 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
935 rc = ErrorExpired;
936 break;
937 case X509_V_ERR_APPLICATION_VERIFICATION:
938 case X509_V_ERR_OUT_OF_MEM:
939 case X509_V_ERR_UNABLE_TO_GET_CRL:
940 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
941 default:
942 rc = ErrorValidityUnknown;
943 break;
944 }
945 return rc;
946}
947
948EVP_PKEY *qca_d2i_PKCS8PrivateKey(const SecureArray &in, EVP_PKEY **x, pem_password_cb *cb, void *u)
949{
950 PKCS8_PRIV_KEY_INFO *p8inf;
951
952 // first try unencrypted form
953 BIO *bi = BIO_new(type: BIO_s_mem());
954 BIO_write(b: bi, data: in.data(), dlen: in.size());
955 p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(bp: bi, p8inf: nullptr);
956 BIO_free(a: bi);
957 if (!p8inf) {
958 X509_SIG *p8;
959
960 // now try encrypted form
961 bi = BIO_new(type: BIO_s_mem());
962 BIO_write(b: bi, data: in.data(), dlen: in.size());
963 p8 = d2i_PKCS8_bio(bp: bi, p8: nullptr);
964 BIO_free(a: bi);
965 if (!p8)
966 return nullptr;
967
968 // get passphrase
969 char psbuf[PEM_BUFSIZE];
970 int klen;
971 if (cb)
972 klen = cb(psbuf, PEM_BUFSIZE, 0, u);
973 else
974 klen = PEM_def_callback(buf: psbuf, PEM_BUFSIZE, rwflag: 0, userdata: u);
975 if (klen <= 0) {
976 PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);
977 X509_SIG_free(a: p8);
978 return nullptr;
979 }
980
981 // decrypt it
982 p8inf = PKCS8_decrypt(p8, pass: psbuf, passlen: klen);
983 X509_SIG_free(a: p8);
984 if (!p8inf)
985 return nullptr;
986 }
987
988 EVP_PKEY *ret = EVP_PKCS82PKEY(p8: p8inf);
989 PKCS8_PRIV_KEY_INFO_free(a: p8inf);
990 if (!ret)
991 return nullptr;
992 if (x) {
993 if (*x)
994 EVP_PKEY_free(pkey: *x);
995 *x = ret;
996 }
997 return ret;
998}
999
1000class opensslHashContext : public HashContext
1001{
1002 Q_OBJECT
1003public:
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(ctx: m_context, type: 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(out: m_context, in: other.m_context);
1018 }
1019
1020 ~opensslHashContext() override
1021 {
1022 EVP_MD_CTX_free(ctx: m_context);
1023 }
1024
1025 void clear() override
1026 {
1027 EVP_MD_CTX_free(ctx: m_context);
1028 m_context = EVP_MD_CTX_new();
1029 EVP_DigestInit(ctx: m_context, type: m_algorithm);
1030 }
1031
1032 void update(const MemoryRegion &a) override
1033 {
1034 EVP_DigestUpdate(ctx: m_context, d: (unsigned char *)a.data(), cnt: a.size());
1035 }
1036
1037 MemoryRegion final() override
1038 {
1039 SecureArray a(EVP_MD_size(md: m_algorithm));
1040 EVP_DigestFinal(ctx: m_context, md: (unsigned char *)a.data(), s: nullptr);
1041 return a;
1042 }
1043
1044 Provider::Context *clone() const override
1045 {
1046 return new opensslHashContext(*this);
1047 }
1048
1049protected:
1050 const EVP_MD *m_algorithm;
1051 EVP_MD_CTX *m_context;
1052};
1053
1054class opensslPbkdf1Context : public KDFContext
1055{
1056 Q_OBJECT
1057public:
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(ctx: m_context, type: 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(out: m_context, in: other.m_context);
1073 }
1074
1075 ~opensslPbkdf1Context() override
1076 {
1077 EVP_MD_CTX_free(ctx: 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(md: 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(ctx: m_context, d: (unsigned char *)secret.data(), cnt: secret.size());
1114 EVP_DigestUpdate(ctx: m_context, d: (unsigned char *)salt.data(), cnt: salt.size());
1115 SecureArray a(EVP_MD_size(md: m_algorithm));
1116 EVP_DigestFinal(ctx: m_context, md: (unsigned char *)a.data(), s: nullptr);
1117
1118 // calculate T_2 up to T_c
1119 for (unsigned int i = 2; i <= iterationCount; ++i) {
1120 EVP_DigestInit(ctx: m_context, type: m_algorithm);
1121 EVP_DigestUpdate(ctx: m_context, d: (unsigned char *)a.data(), cnt: a.size());
1122 EVP_DigestFinal(ctx: m_context, md: (unsigned char *)a.data(), s: nullptr);
1123 }
1124
1125 // shrink a to become DK, of the required length
1126 a.resize(size: 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(md: 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(ctx: m_context, d: (unsigned char *)secret.data(), cnt: secret.size());
1169 EVP_DigestUpdate(ctx: m_context, d: (unsigned char *)salt.data(), cnt: salt.size());
1170 SecureArray a(EVP_MD_size(md: m_algorithm));
1171 EVP_DigestFinal(ctx: m_context, md: (unsigned char *)a.data(), s: 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(ctx: m_context, type: m_algorithm);
1179 EVP_DigestUpdate(ctx: m_context, d: (unsigned char *)a.data(), cnt: a.size());
1180 EVP_DigestFinal(ctx: m_context, md: (unsigned char *)a.data(), s: nullptr);
1181 ++(*iterationCount);
1182 }
1183
1184 // shrink a to become DK, of the required length
1185 a.resize(size: keyLength);
1186
1187 /*
1188 3. Output the derived key DK.
1189 */
1190 return a;
1191 }
1192
1193protected:
1194 const EVP_MD *m_algorithm;
1195 EVP_MD_CTX *m_context;
1196};
1197
1198class opensslPbkdf2Context : public KDFContext
1199{
1200 Q_OBJECT
1201public:
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(pass: (char *)secret.data(),
1219 passlen: secret.size(),
1220 salt: (unsigned char *)salt.data(),
1221 saltlen: salt.size(),
1222 iter: iterationCount,
1223 keylen: keyLength,
1224 out: (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(pass: (char *)secret.data(),
1246 passlen: secret.size(),
1247 salt: (unsigned char *)salt.data(),
1248 saltlen: salt.size(),
1249 iter: 1,
1250 keylen: keyLength,
1251 out: (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: *iterationCount);
1258
1259 return out;
1260 }
1261
1262protected:
1263};
1264
1265class opensslHkdfContext : public HKDFContext
1266{
1267 Q_OBJECT
1268public:
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, e: nullptr);
1286 EVP_PKEY_derive_init(ctx: pctx);
1287 EVP_PKEY_CTX_set_hkdf_md(ctx: pctx, md: EVP_sha256());
1288 EVP_PKEY_CTX_set1_hkdf_salt(ctx: pctx, salt: (const unsigned char *)salt.data(), saltlen: int(salt.size()));
1289 EVP_PKEY_CTX_set1_hkdf_key(ctx: pctx, key: (const unsigned char *)secret.data(), keylen: int(secret.size()));
1290 EVP_PKEY_CTX_add1_hkdf_info(ctx: pctx, info: (const unsigned char *)info.data(), infolen: int(info.size()));
1291 size_t outlen = out.size();
1292 EVP_PKEY_derive(ctx: pctx, key: reinterpret_cast<unsigned char *>(out.data()), keylen: &outlen);
1293 EVP_PKEY_CTX_free(ctx: pctx);
1294 return out;
1295 }
1296};
1297
1298class opensslHMACContext : public MACContext
1299{
1300 Q_OBJECT
1301public:
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(dctx: m_context, sctx: other.m_context);
1315 }
1316
1317 ~opensslHMACContext() override
1318 {
1319 HMAC_CTX_free(ctx: m_context);
1320 }
1321
1322 void setup(const SymmetricKey &key) override
1323 {
1324 HMAC_Init_ex(ctx: m_context, key: key.data(), len: key.size(), md: m_algorithm, impl: 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(ctx: m_context, data: (unsigned char *)a.data(), len: a.size());
1335 }
1336
1337 void final(MemoryRegion *out) override
1338 {
1339 SecureArray sa(EVP_MD_size(md: m_algorithm), 0);
1340 HMAC_Final(ctx: m_context, md: (unsigned char *)sa.data(), len: nullptr);
1341 HMAC_CTX_reset(ctx: m_context);
1342 *out = sa;
1343 }
1344
1345 Provider::Context *clone() const override
1346 {
1347 return new opensslHMACContext(*this);
1348 }
1349
1350protected:
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
1360class EVPKey
1361{
1362public:
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(out: mdctx, in: from.mdctx);
1393 }
1394
1395 EVPKey &operator=(const EVPKey &from) = delete;
1396
1397 ~EVPKey()
1398 {
1399 reset();
1400 EVP_MD_CTX_free(ctx: 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(flen: raw.size(),
1466 from: (unsigned char *)raw.data(),
1467 to: (unsigned char *)out.data(),
1468 rsa: (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(ctx: mdctx, md: (unsigned char *)out.data(), s: &len, pkey)) {
1482 state = SignError;
1483 return SecureArray();
1484 }
1485 }
1486 out.resize(size: 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(flen: sig.size(),
1505 from: (unsigned char *)sig.data(),
1506 to: (unsigned char *)out.data(),
1507 rsa: (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(size: len);
1521
1522 if (out != raw) {
1523 state = VerifyError;
1524 return false;
1525 }
1526 } else {
1527 if (EVP_VerifyFinal(ctx: mdctx, sigbuf: (unsigned char *)sig.data(), siglen: (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
1544static 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
1552static 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
1565static 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
1591static const char *JCE_512_SEED = "B869C82B 35D70E1B 1FF91B28 E37A62EC DC34409B";
1592static const int JCE_512_COUNTER = 123;
1593
1594static const char *JCE_768_SEED = "77D0F8C4 DAD15EB8 C4F2F8D6 726CEFD9 6D5BB399";
1595static const int JCE_768_COUNTER = 263;
1596
1597static const char *JCE_1024_SEED = "8D515589 4229D5E6 89EE01E6 018A237E 2CAE64CD";
1598static const int JCE_1024_COUNTER = 92;
1599#endif
1600
1601static 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(hexString: str);
1609}
1610
1611static BigInteger decode(const QByteArray &prime)
1612{
1613 QByteArray a(1, 0); // 1 byte of zero padding
1614 a.append(a: dehex(hex: prime));
1615 return BigInteger(SecureArray(a));
1616}
1617
1618#ifndef OPENSSL_FIPS
1619static QByteArray decode_seed(const QByteArray &hex_seed)
1620{
1621 return dehex(hex: hex_seed);
1622}
1623#endif
1624
1625class DLParams
1626{
1627public:
1628 BigInteger p, q, g;
1629};
1630
1631#ifndef OPENSSL_FIPS
1632
1633static 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: dsa.get(), bits, seed: (const unsigned char *)seed.data(), seed_len: seed.size(), counter_ret: &ret_counter, h_ret: nullptr, cb: 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(d: dsa.get(), p: &bnp, q: &bnq, g: &bng);
1649 params->p = bn2bi(n: bnp);
1650 params->q = bn2bi(n: bnq);
1651 params->g = bn2bi(n: bng);
1652
1653 return true;
1654}
1655#endif
1656
1657static 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
1665class DLGroupMaker : public QThread
1666{
1667 Q_OBJECT
1668public:
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(seed: decode_seed(hex_seed: JCE_512_SEED), bits: 512, counter: JCE_512_COUNTER, params: &params);
1689 break;
1690
1691 case DSA_768:
1692 ok = make_dlgroup(seed: decode_seed(hex_seed: JCE_768_SEED), bits: 768, counter: JCE_768_COUNTER, params: &params);
1693 break;
1694
1695 case DSA_1024:
1696 ok = make_dlgroup(seed: decode_seed(hex_seed: JCE_1024_SEED), bits: 1024, counter: JCE_1024_COUNTER, params: &params);
1697 break;
1698#endif
1699
1700 case IETF_1024:
1701 ok = get_dlgroup(p: decode(prime: IETF_1024_PRIME), g: 2, params: &params);
1702 break;
1703
1704 case IETF_2048:
1705 ok = get_dlgroup(p: decode(prime: IETF_2048_PRIME), g: 2, params: &params);
1706 break;
1707
1708 case IETF_4096:
1709 ok = get_dlgroup(p: decode(prime: IETF_4096_PRIME), g: 2, params: &params);
1710 break;
1711
1712 default:
1713 ok = false;
1714 break;
1715 }
1716 }
1717};
1718
1719class MyDLGroup : public DLGroupContext
1720{
1721 Q_OBJECT
1722public:
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(sender: gm, signal: &DLGroupMaker::finished, context: this, slot: &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
1797private 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//----------------------------------------------------------------------------
1820namespace {
1821static const auto RsaDeleter = [](RSA *pointer) {
1822 if (pointer)
1823 RSA_free(r: (RSA *)pointer);
1824};
1825
1826static const auto BnDeleter = [](BIGNUM *pointer) {
1827 if (pointer)
1828 BN_free(a: (BIGNUM *)pointer);
1829};
1830} // end of anonymous namespace
1831
1832class RSAKeyMaker : public QThread
1833{
1834 Q_OBJECT
1835public:
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(r: 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(a: e.get());
1865 if (BN_set_word(a: e.get(), w: exp) != 1)
1866 return;
1867
1868 if (RSA_generate_key_ex(rsa: rsa.get(), bits, e: e.get(), cb: 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
1883class RSAKey : public RSAContext
1884{
1885 Q_OBJECT
1886public:
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(pkey: evp.pkey);
1944 int len = i2d_RSAPublicKey(a: rsa_pkey, out: nullptr);
1945 SecureArray result(len);
1946 unsigned char *p = (unsigned char *)result.data();
1947 i2d_RSAPublicKey(a: rsa_pkey, out: &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(a: nullptr, in: (const unsigned char **)&p, len: 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(pkey: evp.pkey);
1961 }
1962
1963 int maximumEncryptSize(EncryptionAlgorithm alg) const override
1964 {
1965 const RSA *rsa = EVP_PKEY_get0_RSA(pkey: 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(pkey: evp.pkey);
1988 SecureArray buf = in;
1989 int max = maximumEncryptSize(alg);
1990
1991 if (buf.size() > max)
1992 buf.resize(size: 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 flen: buf.size(), from: (unsigned char *)buf.data(), to: (unsigned char *)result.data(), rsa: (RSA *)rsa, padding: pad);
2022 else
2023 ret = RSA_public_encrypt(
2024 flen: buf.size(), from: (unsigned char *)buf.data(), to: (unsigned char *)result.data(), rsa: (RSA *)rsa, padding: pad);
2025
2026 if (ret < 0)
2027 return SecureArray();
2028 result.resize(size: 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(pkey: 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 flen: in.size(), from: (unsigned char *)in.data(), to: (unsigned char *)result.data(), rsa: (RSA *)rsa, padding: pad);
2065 else
2066 ret = RSA_public_decrypt(
2067 flen: in.size(), from: (unsigned char *)in.data(), to: (unsigned char *)result.data(), rsa: (RSA *)rsa, padding: pad);
2068
2069 if (ret < 0)
2070 return false;
2071 result.resize(size: 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(type: 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(type: 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(sender: keymaker, signal: &RSAKeyMaker::finished, context: this, slot: &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(r: rsa, n: bi2bn(n), e: bi2bn(n: e), d: bi2bn(n: d)) == 0 || RSA_set0_factors(r: rsa, p: bi2bn(n: p), q: bi2bn(n: q)) == 0) {
2174 // Free BIGNUMS?
2175 RSA_free(r: 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(r: rsa, n: bi2bn(n), e: bi2bn(n: e), d: nullptr) == 0) {
2196 RSA_free(r: 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(pkey: evp.pkey);
2208 const BIGNUM *bnn;
2209 RSA_get0_key(r: rsa, n: &bnn, e: nullptr, d: nullptr);
2210 return bn2bi(n: bnn);
2211 }
2212
2213 BigInteger e() const override
2214 {
2215 const RSA *rsa = EVP_PKEY_get0_RSA(pkey: evp.pkey);
2216 const BIGNUM *bne;
2217 RSA_get0_key(r: rsa, n: nullptr, e: &bne, d: nullptr);
2218 return bn2bi(n: bne);
2219 }
2220
2221 BigInteger p() const override
2222 {
2223 const RSA *rsa = EVP_PKEY_get0_RSA(pkey: evp.pkey);
2224 const BIGNUM *bnp;
2225 RSA_get0_factors(r: rsa, p: &bnp, q: nullptr);
2226 return bn2bi(n: bnp);
2227 }
2228
2229 BigInteger q() const override
2230 {
2231 const RSA *rsa = EVP_PKEY_get0_RSA(pkey: evp.pkey);
2232 const BIGNUM *bnq;
2233 RSA_get0_factors(r: rsa, p: nullptr, q: &bnq);
2234 return bn2bi(n: bnq);
2235 }
2236
2237 BigInteger d() const override
2238 {
2239 const RSA *rsa = EVP_PKEY_get0_RSA(pkey: evp.pkey);
2240 const BIGNUM *bnd;
2241 RSA_get0_key(r: rsa, n: nullptr, e: nullptr, d: &bnd);
2242 return bn2bi(n: bnd);
2243 }
2244
2245private 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//----------------------------------------------------------------------------
2269class DSAKeyMaker : public QThread
2270{
2271 Q_OBJECT
2272public:
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(r: result);
2288 }
2289
2290 void run() override
2291 {
2292 std::unique_ptr<DSA, DsaDeleter> dsa(DSA_new());
2293 BIGNUM *pne = bi2bn(n: domain.p()), *qne = bi2bn(n: domain.q()), *gne = bi2bn(n: domain.g());
2294
2295 if (!DSA_set0_pqg(d: dsa.get(), p: pne, q: qne, g: gne)) {
2296 return;
2297 }
2298 if (!DSA_generate_key(a: 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(a: pne) < 2048) {
2309 int dummy;
2310 dsa.reset(p: DSA_new());
2311 if (DSA_generate_parameters_ex(
2312 dsa: dsa.get(), bits: 512, seed: (const unsigned char *)"THIS_IS_A_DUMMY_SEED", seed_len: 20, counter_ret: &dummy, h_ret: nullptr, cb: nullptr) !=
2313 1) {
2314 return;
2315 }
2316 pne = bi2bn(n: domain.p());
2317 qne = bi2bn(n: domain.q());
2318 gne = bi2bn(n: domain.g());
2319 if (!DSA_set0_pqg(d: dsa.get(), p: pne, q: qne, g: gne)) {
2320 return;
2321 }
2322 if (!DSA_generate_key(a: 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
2344class DSAKey : public DSAContext
2345{
2346 Q_OBJECT
2347public:
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(pkey: evp.pkey);
2406 int len = i2d_DSAPublicKey(a: dsa_pkey, out: nullptr);
2407 SecureArray result(len);
2408 unsigned char *p = (unsigned char *)result.data();
2409 i2d_DSAPublicKey(a: dsa_pkey, out: &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(a: nullptr, in: (const unsigned char **)&p, len: 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(pkey: 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(type: 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(type: 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(in: 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(in: sig);
2466 else
2467 in = sig;
2468 return evp.endVerify(sig: 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(sender: keymaker, signal: &DSAKeyMaker::finished, context: this, slot: &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(n: domain.p());
2492 BIGNUM *bnq = bi2bn(n: domain.q());
2493 BIGNUM *bng = bi2bn(n: domain.g());
2494 BIGNUM *bnpub_key = bi2bn(n: y);
2495 BIGNUM *bnpriv_key = bi2bn(n: x);
2496
2497 if (!DSA_set0_pqg(d: dsa, p: bnp, q: bnq, g: bng) || !DSA_set0_key(d: dsa, pub_key: bnpub_key, priv_key: bnpriv_key)) {
2498 DSA_free(r: 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(n: domain.p());
2513 BIGNUM *bnq = bi2bn(n: domain.q());
2514 BIGNUM *bng = bi2bn(n: domain.g());
2515 BIGNUM *bnpub_key = bi2bn(n: y);
2516
2517 if (!DSA_set0_pqg(d: dsa, p: bnp, q: bnq, g: bng) || !DSA_set0_key(d: dsa, pub_key: bnpub_key, priv_key: nullptr)) {
2518 DSA_free(r: 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(pkey: evp.pkey);
2530 const BIGNUM *bnp, *bnq, *bng;
2531 DSA_get0_pqg(d: dsa, p: &bnp, q: &bnq, g: &bng);
2532 return DLGroup(bn2bi(n: bnp), bn2bi(n: bnq), bn2bi(n: bng));
2533 }
2534
2535 BigInteger y() const override
2536 {
2537 const DSA *dsa = EVP_PKEY_get0_DSA(pkey: evp.pkey);
2538 const BIGNUM *bnpub_key;
2539 DSA_get0_key(d: dsa, pub_key: &bnpub_key, priv_key: nullptr);
2540 return bn2bi(n: bnpub_key);
2541 }
2542
2543 BigInteger x() const override
2544 {
2545 const DSA *dsa = EVP_PKEY_get0_DSA(pkey: evp.pkey);
2546 const BIGNUM *bnpriv_key;
2547 DSA_get0_key(d: dsa, pub_key: nullptr, priv_key: &bnpriv_key);
2548 return bn2bi(n: bnpriv_key);
2549 }
2550
2551private 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//----------------------------------------------------------------------------
2575class DHKeyMaker : public QThread
2576{
2577 Q_OBJECT
2578public:
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(dh: result);
2594 }
2595
2596 void run() override
2597 {
2598 DH *dh = DH_new();
2599 BIGNUM *bnp = bi2bn(n: domain.p());
2600 BIGNUM *bng = bi2bn(n: domain.g());
2601 if (!DH_set0_pqg(dh, p: bnp, q: nullptr, g: 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
2616class DHKey : public DHContext
2617{
2618 Q_OBJECT
2619public:
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(pkey: evp.pkey);
2676 DH *dh = DH_new();
2677 const BIGNUM *bnp, *bng, *bnpub_key;
2678 DH_get0_pqg(dh: orig, p: &bnp, q: nullptr, g: &bng);
2679 DH_get0_key(dh: orig, pub_key: &bnpub_key, priv_key: nullptr);
2680
2681 DH_set0_key(dh, pub_key: BN_dup(a: bnpub_key), priv_key: nullptr);
2682 DH_set0_pqg(dh, p: BN_dup(a: bnp), q: nullptr, g: BN_dup(a: 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(pkey: evp.pkey);
2694 }
2695
2696 SymmetricKey deriveKey(const PKeyBase &theirs) override
2697 {
2698 const DH *dh = EVP_PKEY_get0_DH(pkey: evp.pkey);
2699 const DH *them = EVP_PKEY_get0_DH(pkey: static_cast<const DHKey *>(&theirs)->evp.pkey);
2700 const BIGNUM *bnpub_key;
2701 DH_get0_key(dh: them, pub_key: &bnpub_key, priv_key: nullptr);
2702
2703 SecureArray result(DH_size(dh));
2704 int ret = DH_compute_key(key: (unsigned char *)result.data(), pub_key: bnpub_key, dh: (DH *)dh);
2705 if (ret <= 0)
2706 return SymmetricKey();
2707 result.resize(size: 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(sender: keymaker, signal: &DHKeyMaker::finished, context: this, slot: &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(n: domain.p());
2732 BIGNUM *bng = bi2bn(n: domain.g());
2733 BIGNUM *bnpub_key = bi2bn(n: y);
2734 BIGNUM *bnpriv_key = bi2bn(n: x);
2735
2736 if (!DH_set0_key(dh, pub_key: bnpub_key, priv_key: bnpriv_key) || !DH_set0_pqg(dh, p: bnp, q: nullptr, g: 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(n: domain.p());
2752 BIGNUM *bng = bi2bn(n: domain.g());
2753 BIGNUM *bnpub_key = bi2bn(n: y);
2754
2755 if (!DH_set0_key(dh, pub_key: bnpub_key, priv_key: nullptr) || !DH_set0_pqg(dh, p: bnp, q: nullptr, g: 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(pkey: evp.pkey);
2768 const BIGNUM *bnp, *bng;
2769 DH_get0_pqg(dh, p: &bnp, q: nullptr, g: &bng);
2770 return DLGroup(bn2bi(n: bnp), bn2bi(n: bng));
2771 }
2772
2773 BigInteger y() const override
2774 {
2775 const DH *dh = EVP_PKEY_get0_DH(pkey: evp.pkey);
2776 const BIGNUM *bnpub_key;
2777 DH_get0_key(dh, pub_key: &bnpub_key, priv_key: nullptr);
2778 return bn2bi(n: bnpub_key);
2779 }
2780
2781 BigInteger x() const override
2782 {
2783 const DH *dh = EVP_PKEY_get0_DH(pkey: evp.pkey);
2784 const BIGNUM *bnpriv_key;
2785 DH_get0_key(dh, pub_key: nullptr, priv_key: &bnpriv_key);
2786 return bn2bi(n: bnpriv_key);
2787 }
2788
2789private 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
2815class QCA_RSA_METHOD
2816{
2817public:
2818 RSAPrivateKey key;
2819
2820 QCA_RSA_METHOD(const RSAPrivateKey &_key, RSA *rsa)
2821 {
2822 key = _key;
2823 RSA_set_method(rsa, meth: rsa_method());
2824 RSA_set_app_data(rsa, this);
2825 BIGNUM *bnn = bi2bn(n: _key.n());
2826 BIGNUM *bne = bi2bn(n: _key.e());
2827
2828 RSA_set0_key(r: rsa, n: bnn, e: bne, d: nullptr);
2829 }
2830
2831 RSA_METHOD *rsa_method()
2832 {
2833 static RSA_METHOD *ops = nullptr;
2834
2835 if (!ops) {
2836 ops = RSA_meth_dup(meth: RSA_get_default_method());
2837 RSA_meth_set_priv_enc(rsa: ops, priv_enc: nullptr); // pkcs11_rsa_encrypt
2838 RSA_meth_set_priv_dec(rsa: ops, priv_dec: rsa_priv_dec); // pkcs11_rsa_encrypt
2839 RSA_meth_set_sign(rsa: ops, sign: nullptr);
2840 RSA_meth_set_verify(rsa: ops, verify: nullptr); // pkcs11_rsa_verify
2841 RSA_meth_set_finish(rsa: ops, finish: 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(size: flen);
2863 memcpy(dest: input.data(), src: from, n: input.size());
2864
2865 QCA::SecureArray output;
2866
2867 if (self->key.decrypt(in: input, out: &output, alg: algo)) {
2868 memcpy(dest: to, src: output.data(), n: 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
2884static 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//----------------------------------------------------------------------------
2894class MyPKeyContext : public PKeyContext
2895{
2896 Q_OBJECT
2897public:
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(type: BIO_s_mem());
3011 i2d_PUBKEY_bio(bp: bo, pkey);
3012 const QByteArray buf = bio2ba(b: 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(type: BIO_s_mem());
3027 PEM_write_bio_PUBKEY(out: bo, x: pkey);
3028 const QByteArray buf = bio2ba(b: bo);
3029 return QString::fromLatin1(ba: buf);
3030 }
3031
3032 ConvertResult publicFromDER(const QByteArray &in) override
3033 {
3034 delete k;
3035 k = nullptr;
3036
3037 BIO *bi = BIO_new(type: BIO_s_mem());
3038 BIO_write(b: bi, data: in.data(), dlen: in.size());
3039 EVP_PKEY *pkey = d2i_PUBKEY_bio(bp: bi, a: nullptr);
3040 BIO_free(a: bi);
3041
3042 if (!pkey)
3043 return ErrorDecode;
3044
3045 k = pkeyToBase(pkey, sec: 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(type: BIO_s_mem());
3059 BIO_write(b: bi, data: in.data(), dlen: in.size());
3060 EVP_PKEY *pkey = PEM_read_bio_PUBKEY(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
3061 BIO_free(a: bi);
3062
3063 if (!pkey)
3064 return ErrorDecode;
3065
3066 k = pkeyToBase(pkey, sec: 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(type: BIO_s_mem());
3095 if (!passphrase.isEmpty())
3096 i2d_PKCS8PrivateKey_bio(bp: bo, x: pkey, enc: cipher, kstr: nullptr, klen: 0, cb: nullptr, u: (void *)passphrase.data());
3097 else
3098 i2d_PKCS8PrivateKey_bio(bp: bo, x: pkey, enc: nullptr, kstr: nullptr, klen: 0, cb: nullptr, u: nullptr);
3099 SecureArray buf = bio2buf(b: 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(type: BIO_s_mem());
3125 if (!passphrase.isEmpty())
3126 PEM_write_bio_PKCS8PrivateKey(bo, pkey, cipher, kstr: nullptr, klen: 0, cb: nullptr, u: (void *)passphrase.data());
3127 else
3128 PEM_write_bio_PKCS8PrivateKey(bo, pkey, nullptr, kstr: nullptr, klen: 0, cb: nullptr, u: nullptr);
3129 SecureArray buf = bio2buf(b: bo);
3130 return QString::fromLatin1(ba: 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, x: nullptr, cb: nullptr, u: (void *)passphrase.data());
3141 else
3142 pkey = qca_d2i_PKCS8PrivateKey(in, x: nullptr, cb: passphrase_cb, u: nullptr);
3143
3144 if (!pkey)
3145 return ErrorDecode;
3146
3147 k = pkeyToBase(pkey, sec: 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(type: BIO_s_mem());
3161 BIO_write(b: bi, data: in.data(), dlen: in.size());
3162 EVP_PKEY *pkey;
3163 if (!passphrase.isEmpty())
3164 pkey = PEM_read_bio_PrivateKey(out: bi, x: nullptr, cb: nullptr, u: (void *)passphrase.data());
3165 else
3166 pkey = PEM_read_bio_PrivateKey(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
3167 BIO_free(a: bi);
3168
3169 if (!pkey)
3170 return ErrorDecode;
3171
3172 k = pkeyToBase(pkey, sec: true);
3173 if (k)
3174 return ConvertGood;
3175 else
3176 return ErrorDecode;
3177 }
3178};
3179
3180//----------------------------------------------------------------------------
3181// MyCertContext
3182//----------------------------------------------------------------------------
3183class X509Item
3184{
3185public:
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(x: cert);
3227 if (req) {
3228 // Not exposed, so copy
3229 req = X509_REQ_dup(a: 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(a: cert);
3242 cert = nullptr;
3243 }
3244 if (req) {
3245 X509_REQ_free(a: req);
3246 req = nullptr;
3247 }
3248 if (crl) {
3249 X509_CRL_free(a: 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(type: BIO_s_mem());
3262 if (cert)
3263 i2d_X509_bio(bp: bo, x509: cert);
3264 else if (req)
3265 i2d_X509_REQ_bio(bp: bo, req);
3266 else if (crl)
3267 i2d_X509_CRL_bio(bp: bo, crl);
3268 const QByteArray buf = bio2ba(b: bo);
3269 return buf;
3270 }
3271
3272 QString toPEM() const
3273 {
3274 BIO *bo = BIO_new(type: BIO_s_mem());
3275 if (cert)
3276 PEM_write_bio_X509(out: bo, x: cert);
3277 else if (req)
3278 PEM_write_bio_X509_REQ(out: bo, x: req);
3279 else if (crl)
3280 PEM_write_bio_X509_CRL(out: bo, x: crl);
3281 const QByteArray buf = bio2ba(b: bo);
3282 return QString::fromLatin1(ba: buf);
3283 }
3284
3285 ConvertResult fromDER(const QByteArray &in, Type t)
3286 {
3287 reset();
3288
3289 BIO *bi = BIO_new(type: BIO_s_mem());
3290 BIO_write(b: bi, data: in.data(), dlen: in.size());
3291
3292 if (t == TypeCert)
3293 cert = d2i_X509_bio(bp: bi, x509: nullptr);
3294 else if (t == TypeReq)
3295 req = d2i_X509_REQ_bio(bp: bi, req: nullptr);
3296 else if (t == TypeCRL)
3297 crl = d2i_X509_CRL_bio(bp: bi, crl: nullptr);
3298
3299 BIO_free(a: 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(type: BIO_s_mem());
3313 BIO_write(b: bi, data: in.data(), dlen: in.size());
3314
3315 if (t == TypeCert)
3316 cert = PEM_read_bio_X509(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
3317 else if (t == TypeReq)
3318 req = PEM_read_bio_X509_REQ(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
3319 else if (t == TypeCRL)
3320 crl = PEM_read_bio_X509_CRL(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
3321
3322 BIO_free(a: 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
3335QDateTime 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(year: y + 1900, month: M, day: d);
3369 qtime.setHMS(h, m, s);
3370 qdt.setDate(qdate);
3371 qdt.setTime(qtime);
3372 if (gmt)
3373 qdt.setTimeSpec(Qt::UTC);
3374auq_err:
3375 if (isGmt)
3376 *isGmt = gmt;
3377 return qdt;
3378}
3379
3380class MyCertContext;
3381static 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
3384class MyCertContext : public CertContext
3385{
3386 Q_OBJECT
3387public:
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(in: a, t: 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, t: 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, version: 2);
3481
3482 // serial
3483 BIGNUM *bn = bi2bn(n: opts.serialNumber());
3484 BN_to_ASN1_INTEGER(bn, ai: X509_get_serialNumber(x));
3485 BN_free(a: bn);
3486
3487 // validity period
3488 ASN1_TIME_set(X509_get_notBefore(x), t: opts.notValidBefore().toSecsSinceEpoch());
3489 ASN1_TIME_set(X509_get_notAfter(x), t: opts.notValidAfter().toSecsSinceEpoch());
3490
3491 // public key
3492 X509_set_pubkey(x, pkey: 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(cert: x);
3503 {
3504 X509_add_ext(x, ex, loc: -1);
3505 X509_EXTENSION_free(a: ex);
3506 }
3507
3508 // CA mode
3509 ex = new_basic_constraints(ca: opts.isCA(), pathlen: opts.pathLimit());
3510 if (ex) {
3511 X509_add_ext(x, ex, loc: -1);
3512 X509_EXTENSION_free(a: ex);
3513 }
3514
3515 // subject alt name
3516 ex = new_cert_subject_alt_name(info);
3517 if (ex) {
3518 X509_add_ext(x, ex, loc: -1);
3519 X509_EXTENSION_free(a: ex);
3520 }
3521
3522 // key usage
3523 ex = new_cert_key_usage(constraints);
3524 if (ex) {
3525 X509_add_ext(x, ex, loc: -1);
3526 X509_EXTENSION_free(a: ex);
3527 }
3528
3529 // extended key usage
3530 ex = new_cert_ext_key_usage(constraints);
3531 if (ex) {
3532 X509_add_ext(x, ex, loc: -1);
3533 X509_EXTENSION_free(a: ex);
3534 }
3535
3536 // policies
3537 ex = new_cert_policies(policies: opts.policies());
3538 if (ex) {
3539 X509_add_ext(x, ex, loc: -1);
3540 X509_EXTENSION_free(a: ex);
3541 }
3542
3543 // finished
3544 X509_sign(x, pkey: 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(c: ac);
3565 PKeyContext *bc = other->subjectPublicKey();
3566 bkey.change(c: 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(x: item.cert);
3587 PKeyBase *kb = kc->pkeyToBase(pkey, sec: 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, trust_store: store, target: ox, untrusted: 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(ossl: chain, qca: expected))
3623 ok = true;
3624
3625 // cleanup
3626 X509_STORE_CTX_free(ctx);
3627 X509_STORE_free(v: 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(meth: nullptr, aint: ai);
3656 QString str = QString::fromLatin1(ba: rep);
3657 OPENSSL_free(rep);
3658 p.serial.fromString(s: str);
3659 }
3660
3661 p.start = ASN1_UTCTIME_QDateTime(X509_get_notBefore(x), isGmt: nullptr);
3662 p.end = ASN1_UTCTIME_QDateTime(X509_get_notAfter(x), isGmt: nullptr);
3663
3664 CertificateInfo subject, issuer;
3665
3666 subject = get_cert_name(name: X509_get_subject_name(a: x));
3667 issuer = get_cert_name(name: X509_get_issuer_name(a: x));
3668
3669 p.isSelfSigned = (X509_V_OK == X509_check_issued(issuer: x, subject: x));
3670
3671 p.isCA = false;
3672 p.pathLimit = 0;
3673 int pos = X509_get_ext_by_NID(x, NID_basic_constraints, lastpos: -1);
3674 if (pos != -1) {
3675 X509_EXTENSION *ex = X509_get_ext(x, loc: pos);
3676 if (ex)
3677 get_basic_constraints(ex, ca: &p.isCA, pathlen: &p.pathLimit);
3678 }
3679
3680 pos = X509_get_ext_by_NID(x, NID_subject_alt_name, lastpos: -1);
3681 if (pos != -1) {
3682 X509_EXTENSION *ex = X509_get_ext(x, loc: pos);
3683 if (ex)
3684 subject.unite(other: get_cert_alt_name(ex));
3685 }
3686
3687 pos = X509_get_ext_by_NID(x, NID_issuer_alt_name, lastpos: -1);
3688 if (pos != -1) {
3689 X509_EXTENSION *ex = X509_get_ext(x, loc: pos);
3690 if (ex)
3691 issuer.unite(other: get_cert_alt_name(ex));
3692 }
3693
3694 pos = X509_get_ext_by_NID(x, NID_key_usage, lastpos: -1);
3695 if (pos != -1) {
3696 X509_EXTENSION *ex = X509_get_ext(x, loc: 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, lastpos: -1);
3702 if (pos != -1) {
3703 X509_EXTENSION *ex = X509_get_ext(x, loc: 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, lastpos: -1);
3709 if (pos != -1) {
3710 X509_EXTENSION *ex = X509_get_ext(x, loc: pos);
3711 if (ex)
3712 p.policies = get_cert_policies(ex);
3713 }
3714
3715 const ASN1_BIT_STRING *signature;
3716
3717 X509_get0_signature(psig: &signature, palg: 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, lastpos: -1);
3760 if (pos != -1) {
3761 X509_EXTENSION *ex = X509_get_ext(x, loc: 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, lastpos: -1);
3767 if (pos != -1) {
3768 X509_EXTENSION *ex = X509_get_ext(x, loc: 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
3785bool 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
3804class MyCAContext : public CAContext
3805{
3806 Q_OBJECT
3807public:
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(x: 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(info: subjectOpts.info());
3881
3882 // create
3883 x = X509_new();
3884 X509_set_version(x, version: 2);
3885
3886 // serial
3887 BIGNUM *bn = bi2bn(n: props.serial);
3888 BN_to_ASN1_INTEGER(bn, ai: X509_get_serialNumber(x));
3889 BN_free(a: bn);
3890
3891 // validity period
3892 ASN1_TIME_set(X509_get_notBefore(x), t: QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
3893 ASN1_TIME_set(X509_get_notAfter(x), t: notValidAfter.toSecsSinceEpoch());
3894
3895 X509_set_pubkey(x, pkey: static_cast<const MyPKeyContext *>(req.subjectPublicKey())->get_pkey());
3896 X509_set_subject_name(x, name: subjectName);
3897 X509_set_issuer_name(x, name: X509_get_subject_name(a: caCert.cert));
3898
3899 // subject key id
3900 ex = new_subject_key_id(cert: x);
3901 {
3902 X509_add_ext(x, ex, loc: -1);
3903 X509_EXTENSION_free(a: ex);
3904 }
3905
3906 // CA mode
3907 ex = new_basic_constraints(ca: props.isCA, pathlen: props.pathLimit);
3908 if (ex) {
3909 X509_add_ext(x, ex, loc: -1);
3910 X509_EXTENSION_free(a: ex);
3911 }
3912
3913 // subject alt name
3914 ex = new_cert_subject_alt_name(info: subjectOpts.info());
3915 if (ex) {
3916 X509_add_ext(x, ex, loc: -1);
3917 X509_EXTENSION_free(a: ex);
3918 }
3919
3920 // key usage
3921 ex = new_cert_key_usage(constraints: props.constraints);
3922 if (ex) {
3923 X509_add_ext(x, ex, loc: -1);
3924 X509_EXTENSION_free(a: ex);
3925 }
3926
3927 // extended key usage
3928 ex = new_cert_ext_key_usage(constraints: props.constraints);
3929 if (ex) {
3930 X509_add_ext(x, ex, loc: -1);
3931 X509_EXTENSION_free(a: ex);
3932 }
3933
3934 // policies
3935 ex = new_cert_policies(policies: props.policies);
3936 if (ex) {
3937 X509_add_ext(x, ex, loc: -1);
3938 X509_EXTENSION_free(a: ex);
3939 }
3940
3941 if (!X509_sign(x, pkey: privateKey->get_pkey(), md)) {
3942 X509_free(a: x);
3943 delete cert;
3944 return nullptr;
3945 }
3946
3947 cert->fromX509(x);
3948 X509_free(a: 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//----------------------------------------------------------------------------
3971class MyCSRContext : public CSRContext
3972{
3973 Q_OBJECT
3974public:
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(in: a, t: 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, t: 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, pkey: pk);
4065
4066 // subject
4067 X509_NAME *name = new_cert_name(info);
4068 X509_REQ_set_subject_name(req: x, name);
4069
4070 // challenge
4071 const QByteArray cs = opts.challenge().toLatin1();
4072 if (!cs.isEmpty())
4073 X509_REQ_add1_attr_by_NID(
4074 req: x, NID_pkcs9_challengePassword, MBSTRING_UTF8, bytes: (const unsigned char *)cs.data(), len: -1);
4075
4076 STACK_OF(X509_EXTENSION) *exts = sk_X509_EXTENSION_new_null();
4077
4078 // CA mode
4079 ex = new_basic_constraints(ca: opts.isCA(), pathlen: 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(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(req: x, ext: exts);
4105 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
4106
4107 // finished
4108 X509_REQ_sign(x, pkey: 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(c: ac);
4128 PKeyContext *bc = other->subjectPublicKey();
4129 bkey.change(c: 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(req: item.req);
4143 PKeyBase *kb = kc->pkeyToBase(pkey, sec: 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(name: X509_REQ_get_subject_name(req: x));
4171
4172 STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(req: x);
4173
4174 p.isCA = false;
4175 p.pathLimit = 0;
4176 int pos = X509v3_get_ext_by_NID(x: exts, NID_basic_constraints, lastpos: -1);
4177 if (pos != -1) {
4178 X509_EXTENSION *ex = X509v3_get_ext(x: exts, loc: pos);
4179 if (ex)
4180 get_basic_constraints(ex, ca: &p.isCA, pathlen: &p.pathLimit);
4181 }
4182
4183 pos = X509v3_get_ext_by_NID(x: exts, NID_subject_alt_name, lastpos: -1);
4184 if (pos != -1) {
4185 X509_EXTENSION *ex = X509v3_get_ext(x: exts, loc: pos);
4186 if (ex)
4187 subject.unite(other: get_cert_alt_name(ex));
4188 }
4189
4190 pos = X509v3_get_ext_by_NID(x: exts, NID_key_usage, lastpos: -1);
4191 if (pos != -1) {
4192 X509_EXTENSION *ex = X509v3_get_ext(x: exts, loc: pos);
4193 if (ex)
4194 p.constraints = get_cert_key_usage(ex);
4195 }
4196
4197 pos = X509v3_get_ext_by_NID(x: exts, NID_ext_key_usage, lastpos: -1);
4198 if (pos != -1) {
4199 X509_EXTENSION *ex = X509v3_get_ext(x: exts, loc: pos);
4200 if (ex)
4201 p.constraints += get_cert_ext_key_usage(ex);
4202 }
4203
4204 pos = X509v3_get_ext_by_NID(x: exts, NID_certificate_policies, lastpos: -1);
4205 if (pos != -1) {
4206 X509_EXTENSION *ex = X509v3_get_ext(x: exts, loc: 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(req: x, psig: &signature, palg: 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(req: 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(req: 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//----------------------------------------------------------------------------
4257class MyCRLContext : public CRLContext
4258{
4259 Q_OBJECT
4260public:
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(in: a, t: 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, t: 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(crl: 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(name: X509_CRL_get_issuer(crl: x));
4353
4354 p.thisUpdate = ASN1_UTCTIME_QDateTime(tm: X509_CRL_get0_lastUpdate(crl: x), isGmt: nullptr);
4355 p.nextUpdate = ASN1_UTCTIME_QDateTime(tm: X509_CRL_get0_nextUpdate(crl: x), isGmt: nullptr);
4356
4357 STACK_OF(X509_REVOKED) *revokeStack = X509_CRL_get_REVOKED(crl: 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(n: ASN1_INTEGER_to_BN(ai: X509_REVOKED_get0_serialNumber(x: rev), bn: nullptr));
4362 QDateTime time = ASN1_UTCTIME_QDateTime(tm: X509_REVOKED_get0_revocationDate(x: rev), isGmt: nullptr);
4363 QCA::CRLEntry::Reason reason = QCA::CRLEntry::Unspecified;
4364 int pos = X509_REVOKED_get_ext_by_NID(x: rev, NID_crl_reason, lastpos: -1);
4365 if (pos != -1) {
4366 X509_EXTENSION *ex = X509_REVOKED_get_ext(x: rev, loc: pos);
4367 if (ex) {
4368 ASN1_ENUMERATED *result = (ASN1_ENUMERATED *)X509V3_EXT_d2i(ext: ex);
4369 switch (ASN1_ENUMERATED_get(a: 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(a: result);
4405 }
4406 }
4407 CRLEntry thisEntry(serial, time, reason);
4408 p.revoked.append(t: thisEntry);
4409 }
4410
4411 const ASN1_BIT_STRING *signature;
4412
4413 X509_CRL_get0_signature(crl: x, psig: &signature, palg: 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(crl: 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(crl: x);
4452 p.sigalgo = QCA::SignatureUnknown;
4453 }
4454
4455 int pos = X509_CRL_get_ext_by_NID(x, NID_authority_key_identifier, lastpos: -1);
4456 if (pos != -1) {
4457 X509_EXTENSION *ex = X509_CRL_get_ext(x, loc: 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, lastpos: -1);
4464 if (pos != -1) {
4465 X509_EXTENSION *ex = X509_CRL_get_ext(x, loc: pos);
4466 if (ex) {
4467 ASN1_INTEGER *result = (ASN1_INTEGER *)X509V3_EXT_d2i(ext: ex);
4468 p.number = ASN1_INTEGER_get(a: result);
4469 ASN1_INTEGER_free(a: 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//----------------------------------------------------------------------------
4485class MyCertCollectionContext : public CertCollectionContext
4486{
4487 Q_OBJECT
4488public:
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(type: BIO_s_mem());
4510 BIO_write(b: bi, data: a.data(), dlen: a.size());
4511 PKCS7 *p7 = d2i_PKCS7_bio(bp: bi, p7: nullptr);
4512 BIO_free(a: 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(o: 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(a: p7);
4547
4548 *certs = _certs;
4549 *crls = _crls;
4550
4551 return ConvertGood;
4552 }
4553};
4554
4555static 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(t: ServerAuth);
4568 break;
4569 case UsageTLSClient:
4570 return cc._props.constraints.contains(t: ClientAuth);
4571 break;
4572 case UsageCodeSigning:
4573 return cc._props.constraints.contains(t: CodeSigning);
4574 break;
4575 case UsageEmailProtection:
4576 return cc._props.constraints.contains(t: EmailProtection);
4577 break;
4578 case UsageTimeStamping:
4579 return cc._props.constraints.contains(t: TimeStamping);
4580 break;
4581 case UsageCRLSigning:
4582 return cc._props.constraints.contains(t: CRLSign);
4583 break;
4584 default:
4585 return true;
4586 }
4587}
4588
4589Validity 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(crl: x);
4619 crl_list.append(t: 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(ctx: store, x: crl_list[n]);
4632
4633 // the first initialization handles untrusted certs, crls, and target cert
4634 X509_STORE_CTX_init(ctx, trust_store: store, target: x, untrusted: untrusted_list);
4635
4636 // this initializes the trusted certs
4637 X509_STORE_CTX_trusted_stack(ctx, sk: 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(v: 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(a: crl_list[n]);
4653
4654 if (!ret)
4655 return convert_verify_error(err);
4656
4657 if (!usage_check(cc: *cc, u))
4658 return ErrorInvalidPurpose;
4659
4660 return ValidityGood;
4661}
4662
4663Validity 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(crl: x);
4693 crl_list.append(t: 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(ctx: store, x: crl_list[n]);
4706
4707 // the first initialization handles untrusted certs, crls, and target cert
4708 X509_STORE_CTX_init(ctx, trust_store: store, target: x, untrusted: untrusted_list);
4709
4710 // this initializes the trusted certs
4711 X509_STORE_CTX_trusted_stack(ctx, sk: 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(ossl: xchain, qca: expected))
4733 err = ErrorValidityUnknown;
4734
4735 // cleanup
4736 X509_STORE_CTX_free(ctx);
4737 X509_STORE_free(v: 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(a: crl_list[n]);
4743
4744 if (!ret)
4745 return convert_verify_error(err);
4746
4747 if (!usage_check(cc: *cc, u))
4748 return ErrorInvalidPurpose;
4749
4750 return ValidityGood;
4751}
4752
4753class MyPKCS12Context : public PKCS12Context
4754{
4755 Q_OBJECT
4756public:
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 pass: (char *)passphrase.data(), name: (char *)name.toLatin1().data(), pkey: pk.get_pkey(), cert, ca, nid_key: 0, nid_cert: 0, iter: 0, mac_iter: 0, keytype: 0);
4791 sk_X509_pop_free(ca, X509_free);
4792
4793 if (!p12)
4794 return QByteArray();
4795
4796 BIO *bo = BIO_new(type: BIO_s_mem());
4797 i2d_PKCS12_bio(bp: bo, p12);
4798 const QByteArray out = bio2ba(b: 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(type: BIO_s_mem());
4809 BIO_write(b: bi, data: in.data(), dlen: in.size());
4810 PKCS12 *p12 = d2i_PKCS12_bio(bp: bi, p12: nullptr);
4811 BIO_free(a: 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, pass: passphrase.data(), pkey: &pkey, cert: &cert, ca: &ca)) {
4819 PKCS12_free(a: p12);
4820 return ErrorDecode;
4821 }
4822 PKCS12_free(a: p12);
4823
4824 // require private key
4825 if (!pkey) {
4826 if (cert)
4827 X509_free(a: 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(x: cert, len: &aliasLength);
4837 *name = QString::fromLatin1(str: aliasData, size: aliasLength);
4838
4839 MyPKeyContext *pk = new MyPKeyContext(provider());
4840 PKeyBase *k = pk->pkeyToBase(pkey, sec: true); // does an EVP_PKEY_free()
4841 if (!k) {
4842 delete pk;
4843 if (cert)
4844 X509_free(a: 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(x: cert);
4856 certs.append(t: cc);
4857 X509_free(a: 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(t: 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(c: certs[n]);
4875 ch += cert;
4876 }
4877 certs.clear();
4878 ch = ch.complete(issuers: 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
4891static bool ssl_init = false;
4892class MyTLSContext : public TLSContext
4893{
4894 Q_OBJECT
4895public:
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(size: 0);
4973 recvQueue.resize(size: 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(meth: 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(msg: "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(s: 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(ba: SSL_CIPHER_standard_name(c: 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(plain: from_app, to_net: &result_to_net, enc: &result_encoded);
5125 if (ok)
5126 ok = priv_decode(from_net, plain: &result_plain, to_net: &result_to_net);
5127 result_result = ok ? Success : Error;
5128 } else if (mode == Closing)
5129 result_result = priv_shutdown(from_net, to_net: &result_to_net);
5130 else
5131 result_result = priv_handshake(from_net, to_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(b: rbio, data: from_net.data(), dlen: 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(b: rbio, data: from_net.data(), dlen: 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(a: plain);
5232
5233 int encoded = 0;
5234 if (sendQueue.size() > 0) {
5235 int ret = SSL_write(ssl, buf: sendQueue.data(), num: 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(s: ssl, ret_code: 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(dest: r, src: r + encoded, n: newsize);
5259 sendQueue.resize(size: newsize);
5260 }
5261
5262 if (m == Done) {
5263 sendQueue.resize(size: 0);
5264 v_eof = true;
5265 return false;
5266 }
5267 if (m == Error) {
5268 sendQueue.resize(size: 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(b: rbio, data: from_net.data(), dlen: from_net.size());
5284
5285 QByteArray a;
5286 while (!v_eof) {
5287 a.resize(size: 8192);
5288 int ret = SSL_read(ssl, buf: a.data(), num: a.size());
5289 // printf("SSL_read = %d\n", ret);
5290 if (ret > 0) {
5291 if (ret != (int)a.size())
5292 a.resize(size: 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(s: ssl, ret_code: 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(size: 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(s: 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(msg: "unexpected version response");
5398 sessInfo.version = TLS::TLS_v1;
5399 }
5400
5401 sessInfo.cipherSuite = QString::fromLatin1(ba: SSL_CIPHER_standard_name(c: SSL_get_current_cipher(s: 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(b: rbio, data: a.data(), dlen: size);
5419 if (r <= 0) {
5420 a.resize(size: 0);
5421 return a;
5422 }
5423 if (r != size)
5424 a.resize(size: 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(t: peercert);
5438 return chain;
5439 }
5440
5441 void doResultsReady()
5442 {
5443 QMetaObject::invokeMethod(obj: this, member: "resultsReady", c: Qt::QueuedConnection);
5444 }
5445
5446 bool init()
5447 {
5448 context = SSL_CTX_new(meth: 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(ctx: 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(ctx: store, x);
5469 }
5470 }
5471
5472 ssl = SSL_new(ctx: context);
5473 if (!ssl) {
5474 SSL_CTX_free(context);
5475 context = nullptr;
5476 return false;
5477 }
5478 SSL_set_ssl_method(s: 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(type: BIO_s_mem());
5491 wbio = BIO_new(type: BIO_s_mem());
5492
5493 // this passes control of the bios to ssl. we don't need to free them.
5494 SSL_set_bio(s: 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(c: 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, sec: true); // does an EVP_PKEY_free()
5514 pk->k = k;
5515 nkey.change(c: 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, x: cc->item.cert) != 1) {
5522 SSL_free(ssl);
5523 SSL_CTX_free(context);
5524 return false;
5525 }
5526 if (SSL_use_PrivateKey(ssl, pkey: 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(s: ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, callback: 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(s: 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(s: ssl);
5552 MyCertContext *cc = new MyCertContext(provider());
5553 cc->fromX509(x);
5554 Certificate cert;
5555 cert.change(c: 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(c: 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(err: 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(s: ssl, ret_code: 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(s: ssl, ret_code: 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(s: ssl);
5616 if (ret < 0) {
5617 int x = SSL_get_error(s: ssl, ret_code: 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(s: ssl);
5630 if (ret >= 1)
5631 return Good;
5632 else {
5633 if (ret == 0)
5634 return TryAgain;
5635 int x = SSL_get_error(s: ssl, ret_code: 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(b: wbio, data: a.data(), dlen: size);
5651 if (r <= 0) {
5652 a.resize(size: 0);
5653 return a;
5654 }
5655 if (r != size)
5656 a.resize(size: r);
5657 return a;
5658 }
5659};
5660
5661class CMSContext : public SMSContext
5662{
5663 Q_OBJECT
5664public:
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
5701STACK_OF(X509) * get_pk7_certs(PKCS7 *p7)
5702{
5703 int i = OBJ_obj2nid(o: 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
5712class MyMessageContextThread : public QThread
5713{
5714 Q_OBJECT
5715public:
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
5733protected:
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(signcert: cx, pkey: kx, certs: other_certs, data: bi, flags);
5742
5743 BIO_free(a: 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(type: BIO_s_mem());
5757 if (format == SecureMessage::Binary)
5758 i2d_PKCS7_bio(bp: bo, p7);
5759 else // Ascii
5760 PEM_write_bio_PKCS7(out: bo, x: p7);
5761
5762 if (SecureMessage::Detached == signMode)
5763 sig = bio2ba(b: bo);
5764 else
5765 out = bio2ba(b: bo);
5766
5767 ok = true;
5768 } else {
5769 printf(format: "bad here\n");
5770 ERR_print_errors_fp(stdout);
5771 }
5772 }
5773};
5774
5775class MyMessageContext : public MessageContext
5776{
5777 Q_OBJECT
5778public:
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(a: in);
5872 total += in.size();
5873 QMetaObject::invokeMethod(obj: this, member: "updated", c: 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(t: 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(c: 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, sec: true); // does an EVP_PKEY_free()
5916 pk->k = k;
5917 key.change(c: 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(c: this)) {
5923 // fprintf(stderr, "experimental: cert supplied by a different provider\n");
5924 cert = Certificate::fromDER(a: cert.toDER());
5925 if (cert.isNull() || !cert.context()->sameProvider(c: 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(type: BIO_s_mem());
5952 BIO_write(b: bi, data: in.data(), dlen: 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(sender: thread, signal: &MyMessageContextThread::finished, context: this, slot: &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(type: BIO_s_mem());
5989 BIO_write(b: bi, data: in.data(), dlen: in.size());
5990
5991 flags = 0;
5992 flags |= PKCS7_BINARY;
5993 p7 = PKCS7_encrypt(certs: other_certs, in: bi, cipher: EVP_des_ede3_cbc(), flags); // TODO: cipher?
5994
5995 BIO_free(a: bi);
5996 sk_X509_pop_free(other_certs, X509_free);
5997
5998 if (p7) {
5999 // FIXME: format
6000 BIO *bo = BIO_new(type: BIO_s_mem());
6001 i2d_PKCS7_bio(bp: bo, p7);
6002 // PEM_write_bio_PKCS7(bo, p7);
6003 out = bio2ba(b: bo);
6004 PKCS7_free(a: p7);
6005 } else {
6006 printf(format: "bad\n");
6007 return;
6008 }
6009 } else if (op == Verify) {
6010 // TODO: support non-detached sigs
6011
6012 BIO *out = BIO_new(type: BIO_s_mem());
6013 BIO *bi = BIO_new(type: BIO_s_mem());
6014 if (false == sig.isEmpty()) {
6015 // We have detached signature
6016 BIO_write(b: bi, data: sig.data(), dlen: sig.size());
6017 } else {
6018 BIO_write(b: bi, data: in.data(), dlen: in.size());
6019 }
6020 PKCS7 *p7;
6021 if (format == SecureMessage::Binary)
6022 p7 = d2i_PKCS7_bio(bp: bi, p7: nullptr);
6023 else // Ascii
6024 p7 = PEM_read_bio_PKCS7(out: bi, x: nullptr, cb: passphrase_cb, u: nullptr);
6025 BIO_free(a: bi);
6026
6027 if (!p7) {
6028 // TODO
6029 printf(format: "bad1\n");
6030 QMetaObject::invokeMethod(obj: this, member: "updated", c: 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, certs: other_certs, flags: 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(c: cc);
6053 // printf("signer: [%s]\n", qPrintable(cert.commonName()));
6054 signers.append(t: 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(c: cc);
6068 others.append(t: 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(obj: this, member: "updated", c: 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(issuers: 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(ctx: 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(ctx: 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(ctx: store, x);
6112 }
6113
6114 int ret;
6115 if (!sig.isEmpty()) {
6116 // Detached signMode
6117 bi = BIO_new(type: BIO_s_mem());
6118 BIO_write(b: bi, data: in.data(), dlen: in.size());
6119 ret = PKCS7_verify(p7, certs: other_certs, store, indata: bi, out: nullptr, flags: 0);
6120 BIO_free(a: bi);
6121 } else {
6122 ret = PKCS7_verify(p7, certs: other_certs, store, indata: nullptr, out, flags: 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(v: store);
6129 PKCS7_free(a: p7);
6130
6131 ver_ret = ret;
6132 // TODO
6133
6134 QMetaObject::invokeMethod(obj: this, member: "updated", c: 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(type: BIO_s_mem());
6149 BIO_write(b: bi, data: in.data(), dlen: in.size());
6150 PKCS7 *p7 = d2i_PKCS7_bio(bp: bi, p7: nullptr);
6151 BIO_free(a: bi);
6152
6153 if (!p7) {
6154 // TODO
6155 printf(format: "bad1\n");
6156 return;
6157 }
6158
6159 BIO *bo = BIO_new(type: BIO_s_mem());
6160 int ret = PKCS7_decrypt(p7, pkey: kx, cert: cx, data: bo, flags: 0);
6161 PKCS7_free(a: p7);
6162 if (!ret)
6163 continue;
6164
6165 ok = true;
6166 out = bio2ba(b: bo);
6167 break;
6168 }
6169
6170 if (!ok) {
6171 // TODO
6172 printf(format: "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(trusted: cms->trustedCerts, untrusted_crls: 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
6257private Q_SLOTS:
6258 void thread_finished()
6259 {
6260 getresults();
6261 emit updated();
6262 }
6263};
6264
6265MessageContext *CMSContext::createMessage()
6266{
6267 return new MyMessageContext(this, provider());
6268}
6269
6270class opensslCipherContext : public CipherContext
6271{
6272 Q_OBJECT
6273public:
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(out: m_context, in: 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(c: 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(ctx: m_context, cipher: m_cryptoAlgorithm, impl: nullptr, key: nullptr, iv: nullptr);
6312 EVP_CIPHER_CTX_set_key_length(x: m_context, keylen: key.size());
6313 if (m_type.endsWith(s: QLatin1String("gcm")) || m_type.endsWith(s: QLatin1String("ccm"))) {
6314 int parameter = m_type.endsWith(s: QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN;
6315 EVP_CIPHER_CTX_ctrl(ctx: m_context, type: parameter, arg: iv.size(), ptr: nullptr);
6316 }
6317 EVP_EncryptInit_ex(
6318 ctx: m_context, cipher: nullptr, impl: nullptr, key: (const unsigned char *)(key.data()), iv: (const unsigned char *)(iv.data()));
6319 } else {
6320 EVP_DecryptInit_ex(ctx: m_context, cipher: m_cryptoAlgorithm, impl: nullptr, key: nullptr, iv: nullptr);
6321 EVP_CIPHER_CTX_set_key_length(x: m_context, keylen: key.size());
6322 if (m_type.endsWith(s: QLatin1String("gcm")) || m_type.endsWith(s: QLatin1String("ccm"))) {
6323 int parameter = m_type.endsWith(s: QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_IVLEN : EVP_CTRL_CCM_SET_IVLEN;
6324 EVP_CIPHER_CTX_ctrl(ctx: m_context, type: parameter, arg: iv.size(), ptr: nullptr);
6325 }
6326 EVP_DecryptInit_ex(
6327 ctx: m_context, cipher: nullptr, impl: nullptr, key: (const unsigned char *)(key.data()), iv: (const unsigned char *)(iv.data()));
6328 }
6329
6330 EVP_CIPHER_CTX_set_padding(c: m_context, pad: 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(ctx: 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(size: in.size() + blockSize());
6356 int resultLength;
6357 if (Encode == m_direction) {
6358 if (0 ==
6359 EVP_EncryptUpdate(
6360 ctx: m_context, out: (unsigned char *)out->data(), outl: &resultLength, in: (unsigned char *)in.data(), inl: in.size())) {
6361 return false;
6362 }
6363 } else {
6364 if (0 ==
6365 EVP_DecryptUpdate(
6366 ctx: m_context, out: (unsigned char *)out->data(), outl: &resultLength, in: (unsigned char *)in.data(), inl: in.size())) {
6367 return false;
6368 }
6369 }
6370 out->resize(size: resultLength);
6371 return true;
6372 }
6373
6374 bool final(SecureArray *out) override
6375 {
6376 out->resize(size: blockSize());
6377 int resultLength;
6378 if (Encode == m_direction) {
6379 if (0 == EVP_EncryptFinal_ex(ctx: m_context, out: (unsigned char *)out->data(), outl: &resultLength)) {
6380 return false;
6381 }
6382 if (m_tag.size() && (m_type.endsWith(s: QLatin1String("gcm")) || m_type.endsWith(s: QLatin1String("ccm")))) {
6383 int parameter = m_type.endsWith(s: QLatin1String("gcm")) ? EVP_CTRL_GCM_GET_TAG : EVP_CTRL_CCM_GET_TAG;
6384 if (0 == EVP_CIPHER_CTX_ctrl(ctx: m_context, type: parameter, arg: m_tag.size(), ptr: (unsigned char *)m_tag.data())) {
6385 return false;
6386 }
6387 }
6388 } else {
6389 if (m_tag.size() && (m_type.endsWith(s: QLatin1String("gcm")) || m_type.endsWith(s: QLatin1String("ccm")))) {
6390 int parameter = m_type.endsWith(s: QLatin1String("gcm")) ? EVP_CTRL_GCM_SET_TAG : EVP_CTRL_CCM_SET_TAG;
6391 if (0 == EVP_CIPHER_CTX_ctrl(ctx: m_context, type: parameter, arg: m_tag.size(), ptr: m_tag.data())) {
6392 return false;
6393 }
6394 }
6395 if (0 == EVP_DecryptFinal_ex(ctx: m_context, outm: (unsigned char *)out->data(), outl: &resultLength)) {
6396 return false;
6397 }
6398 }
6399 out->resize(size: 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(n: 4) == QLatin1String("des-")) {
6408 return KeyLength(8, 8, 1);
6409 } else if (m_type.left(n: 5) == QLatin1String("cast5")) {
6410 return KeyLength(5, 16, 1);
6411 } else if (m_type.left(n: 8) == QLatin1String("blowfish")) {
6412 // Don't know - TODO
6413 return KeyLength(1, 32, 1);
6414 }
6415 }
6416 if (m_type.left(n: 6) == QLatin1String("aes128")) {
6417 return KeyLength(16, 16, 1);
6418 } else if (m_type.left(n: 6) == QLatin1String("aes192")) {
6419 return KeyLength(24, 24, 1);
6420 } else if (m_type.left(n: 6) == QLatin1String("aes256")) {
6421 return KeyLength(32, 32, 1);
6422 } else if (m_type.left(n: 9) == QLatin1String("tripledes")) {
6423 return KeyLength(16, 24, 1);
6424 }
6425 return KeyLength(0, 1, 1);
6426 }
6427
6428protected:
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
6437static 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
6471static 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
6541static 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
6564class opensslInfoContext : public InfoContext
6565{
6566 Q_OBJECT
6567public:
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
6594class opensslRandomContext : public RandomContext
6595{
6596 Q_OBJECT
6597public:
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(buf: (unsigned char *)(buf.data()), num: size);
6615 if (r == 1)
6616 break; // success
6617 }
6618 return buf;
6619 }
6620};
6621
6622}
6623
6624using namespace opensslQCAPlugin;
6625
6626class opensslProvider : public Provider
6627{
6628public:
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, name: "legacy", retain_fallbacks: 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(seed: time(timer: nullptr));
6653 char buf[128];
6654 for (char &n : buf)
6655 n = std::rand();
6656 RAND_seed(buf, num: 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
6936class opensslPlugin : public QObject, public QCAPlugin
6937{
6938 Q_OBJECT
6939 Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0")
6940 Q_INTERFACES(QCAPlugin)
6941public:
6942 Provider *createProvider() override
6943 {
6944 return new opensslProvider;
6945 }
6946};
6947
6948#include "qca-ossl.moc"
6949

source code of qca/plugins/qca-ossl/qca-ossl.cpp