1 /*
2 * Copyright (C) 2004 Justin Karneges <justin@affinix.com>
3 * Copyright (C) 2006-2007 Alon Bar-Lev <alon.barlev@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 */
20
21 #include <QtCrypto>
22 #include <qcaprovider.h>
23 #include <qplatformdefs.h>
24
25 #include <QHash>
26 #include <QMutexLocker>
27 #include <QtPlugin>
28
29 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
30 #include <pkcs11-helper-1.0/pkcs11h-token.h>
31
32 using namespace QCA;
33
34 // qPrintable is ASCII only!!!
35 #define myPrintable(s) (s).toUtf8().constData()
36
certificateHash(const Certificate & cert)37 static inline QString certificateHash(const Certificate &cert)
38 {
39 if (cert.isNull()) {
40 return QString();
41 } else {
42 return Hash(QStringLiteral("sha1")).hashToString(cert.toDER());
43 }
44 }
45
46 //----------------------------------------------------------------------------
47 // pkcs11Provider
48 //----------------------------------------------------------------------------
49 class pkcs11Provider : public Provider
50 {
51 private:
52 static const int _CONFIG_MAX_PROVIDERS;
53
54 bool _lowLevelInitialized;
55 bool _slotEventsActive;
56 bool _slotEventsLowLevelActive;
57 QStringList _providers;
58
59 public:
60 bool _allowLoadRootCA;
61
62 public:
63 pkcs11Provider();
64 ~pkcs11Provider() override;
65
66 public:
67 int qcaVersion() const override;
68
69 void init() override;
70
71 void deinit() override;
72
73 QString name() const override;
74
75 QStringList features() const override;
76
77 Context *createContext(const QString &type) override;
78
79 void startSlotEvents();
80
81 void stopSlotEvents();
82
83 QVariantMap defaultConfig() const override;
84
85 void configChanged(const QVariantMap &config) override;
86
87 protected:
88 static void __logHook(void *const global_data, const unsigned flags, const char *const format, va_list args);
89
90 static void __slotEventHook(void *const global_data);
91
92 static PKCS11H_BOOL __tokenPromptHook(void *const global_data,
93 void *const user_data,
94 const pkcs11h_token_id_t token,
95 const unsigned retry);
96
97 static PKCS11H_BOOL __pinPromptHook(void *const global_data,
98 void *const user_data,
99 const pkcs11h_token_id_t token,
100 const unsigned retry,
101 char *const pin,
102 const size_t pin_max);
103
104 void _logHook(const unsigned flags, const char *const format, va_list args);
105
106 void _slotEventHook();
107
108 PKCS11H_BOOL
109 _tokenPromptHook(void *const user_data, const pkcs11h_token_id_t token);
110
111 PKCS11H_BOOL
112 _pinPromptHook(void *const user_data, const pkcs11h_token_id_t token, char *const pin, const size_t pin_max);
113 };
114
115 namespace pkcs11QCAPlugin {
116
117 class pkcs11KeyStoreEntryContext;
118
119 //----------------------------------------------------------------------------
120 // pkcs11KeyStoreListContext
121 //----------------------------------------------------------------------------
122 class pkcs11KeyStoreListContext : public KeyStoreListContext
123 {
124 Q_OBJECT
125
126 private:
127 struct pkcs11KeyStoreItem
128 {
129 protected:
130 int _id;
131 pkcs11h_token_id_t _token_id;
132 QList<Certificate> _certs;
133
134 public:
pkcs11KeyStoreItempkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem135 pkcs11KeyStoreItem(const int id, const pkcs11h_token_id_t token_id)
136 {
137 _id = id;
138 ;
139 pkcs11h_token_duplicateTokenId(&_token_id, token_id);
140 }
141
~pkcs11KeyStoreItempkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem142 ~pkcs11KeyStoreItem()
143 {
144 if (_token_id != nullptr) {
145 pkcs11h_token_freeTokenId(_token_id);
146 }
147 }
148
149 pkcs11KeyStoreItem(const pkcs11KeyStoreItem &) = delete;
150 pkcs11KeyStoreItem &operator=(const pkcs11KeyStoreItem &) = delete;
151
idpkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem152 inline int id() const
153 {
154 return _id;
155 }
156
tokenIdpkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem157 inline pkcs11h_token_id_t tokenId() const
158 {
159 return _token_id;
160 }
161
registerCertificatespkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem162 void registerCertificates(const QList<Certificate> &certs)
163 {
164 foreach (Certificate i, certs) {
165 if (std::find(_certs.begin(), _certs.end(), i) == _certs.end()) {
166 _certs += i;
167 }
168 }
169 }
170
friendlyNamespkcs11QCAPlugin::pkcs11KeyStoreListContext::pkcs11KeyStoreItem171 QMap<QString, QString> friendlyNames()
172 {
173 const QStringList names = makeFriendlyNames(_certs);
174 QMap<QString, QString> friendlyNames;
175
176 for (int i = 0; i < names.size(); i++) {
177 friendlyNames.insert(certificateHash(_certs[i]), names[i]);
178 }
179
180 return friendlyNames;
181 }
182 };
183 int _last_id;
184 typedef QList<pkcs11KeyStoreItem *> _stores_t;
185 _stores_t _stores;
186 QHash<int, pkcs11KeyStoreItem *> _storesById;
187 QMutex _mutexStores;
188 bool _initialized;
189
190 public:
191 pkcs11KeyStoreListContext(Provider *p);
192
193 ~pkcs11KeyStoreListContext() override;
194
195 Provider::Context *clone() const override;
196
197 public:
198 void start() override;
199
200 void setUpdatesEnabled(bool enabled) override;
201
202 KeyStoreEntryContext *entry(int id, const QString &entryId) override;
203
204 KeyStoreEntryContext *entryPassive(const QString &serialized) override;
205
206 KeyStore::Type type(int id) const override;
207
208 QString storeId(int id) const override;
209
210 QString name(int id) const override;
211
212 QList<KeyStoreEntry::Type> entryTypes(int id) const override;
213
214 QList<int> keyStores() override;
215
216 QList<KeyStoreEntryContext *> entryList(int id) override;
217
218 bool _tokenPrompt(void *const user_data, const pkcs11h_token_id_t token_id);
219
220 bool _pinPrompt(void *const user_data, const pkcs11h_token_id_t token_id, SecureArray &pin);
221
222 void _emit_diagnosticText(const QString &t);
223
224 private Q_SLOTS:
225 void doReady();
226
227 void doUpdated();
228
229 private:
230 pkcs11KeyStoreItem *_registerTokenId(const pkcs11h_token_id_t token_id);
231
232 void _clearStores();
233
234 pkcs11KeyStoreEntryContext *_keyStoreEntryByCertificateId(const pkcs11h_certificate_id_t certificate_id,
235 const bool has_private,
236 const CertificateChain & chain,
237 const QString & description) const;
238
239 QString _tokenId2storeId(const pkcs11h_token_id_t token_id) const;
240
241 QString _serializeCertificate(const pkcs11h_certificate_id_t certificate_id,
242 const CertificateChain & chain,
243 const bool has_private) const;
244
245 void _deserializeCertificate(const QString & from,
246 pkcs11h_certificate_id_t *const p_certificate_id,
247 bool *const p_has_private,
248 CertificateChain & chain) const;
249
250 QString _escapeString(const QString &from) const;
251
252 QString _unescapeString(const QString &from) const;
253 };
254
255 static pkcs11KeyStoreListContext *s_keyStoreList = nullptr;
256
257 //----------------------------------------------------------------------------
258 // pkcs11Exception
259 //----------------------------------------------------------------------------
260 class pkcs11Exception
261 {
262 private:
263 CK_RV _rv;
264 QString _msg;
265
266 private:
pkcs11Exception()267 pkcs11Exception()
268 {
269 }
270
271 public:
pkcs11Exception(const CK_RV rv,const QString & msg)272 pkcs11Exception(const CK_RV rv, const QString &msg)
273 {
274 _rv = rv;
275 _msg = msg;
276 }
277
278 CK_RV
rv() const279 rv() const
280 {
281 return _rv;
282 }
283
message() const284 QString message() const
285 {
286 return _msg + QStringLiteral(" ") + QString::fromLatin1(pkcs11h_getMessage(_rv));
287 }
288 };
289
290 //----------------------------------------------------------------------------
291 // pkcs11RSAContext
292 //----------------------------------------------------------------------------
293 class pkcs11RSAContext : public RSAContext
294 {
295 Q_OBJECT
296
297 private:
298 bool _has_privateKeyRole;
299 pkcs11h_certificate_id_t _pkcs11h_certificate_id;
300 pkcs11h_certificate_t _pkcs11h_certificate;
301 RSAPublicKey _pubkey;
302 QString _serialized;
303
304 struct _sign_data_s
305 {
306 SignatureAlgorithm alg;
307 Hash * hash;
308 QByteArray raw;
309
_sign_data_spkcs11QCAPlugin::pkcs11RSAContext::_sign_data_s310 _sign_data_s()
311 {
312 hash = nullptr;
313 }
314 } _sign_data;
315
316 public:
pkcs11RSAContext(Provider * p,const pkcs11h_certificate_id_t pkcs11h_certificate_id,const QString & serialized,const RSAPublicKey & pubkey)317 pkcs11RSAContext(Provider * p,
318 const pkcs11h_certificate_id_t pkcs11h_certificate_id,
319 const QString & serialized,
320 const RSAPublicKey & pubkey)
321 : RSAContext(p)
322 {
323 CK_RV rv;
324
325 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContext1 - entry"), Logger::Debug);
326
327 _has_privateKeyRole = true;
328 _pkcs11h_certificate_id = nullptr;
329 _pkcs11h_certificate = nullptr;
330 _pubkey = pubkey;
331 _serialized = serialized;
332 _clearSign();
333
334 if ((rv = pkcs11h_certificate_duplicateCertificateId(&_pkcs11h_certificate_id, pkcs11h_certificate_id)) !=
335 CKR_OK) {
336 throw pkcs11Exception(rv, QStringLiteral("Memory error"));
337 }
338
339 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContext1 - return"), Logger::Debug);
340 }
341
pkcs11RSAContext(const pkcs11RSAContext & from)342 pkcs11RSAContext(const pkcs11RSAContext &from)
343 : RSAContext(from.provider())
344 {
345 CK_RV rv;
346
347 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContextC - entry"), Logger::Debug);
348
349 _has_privateKeyRole = from._has_privateKeyRole;
350 _pkcs11h_certificate_id = nullptr;
351 _pkcs11h_certificate = nullptr;
352 _pubkey = from._pubkey;
353 _serialized = from._serialized;
354 _sign_data.hash = nullptr;
355 _clearSign();
356
357 if ((rv = pkcs11h_certificate_duplicateCertificateId(&_pkcs11h_certificate_id, from._pkcs11h_certificate_id)) !=
358 CKR_OK) {
359 throw pkcs11Exception(rv, QStringLiteral("Memory error"));
360 }
361
362 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContextC - return"), Logger::Debug);
363 }
364
~pkcs11RSAContext()365 ~pkcs11RSAContext() override
366 {
367 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::~pkcs11RSAContext - entry"), Logger::Debug);
368
369 _clearSign();
370
371 if (_pkcs11h_certificate != nullptr) {
372 pkcs11h_certificate_freeCertificate(_pkcs11h_certificate);
373 _pkcs11h_certificate = nullptr;
374 }
375
376 if (_pkcs11h_certificate_id != nullptr) {
377 pkcs11h_certificate_freeCertificateId(_pkcs11h_certificate_id);
378 _pkcs11h_certificate_id = nullptr;
379 }
380
381 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::~pkcs11RSAContext - return"), Logger::Debug);
382 }
383
clone() const384 Provider::Context *clone() const override
385 {
386 return new pkcs11RSAContext(*this);
387 }
388
389 public:
isNull() const390 bool isNull() const override
391 {
392 return _pubkey.isNull();
393 }
394
type() const395 PKey::Type type() const override
396 {
397 return _pubkey.type();
398 }
399
isPrivate() const400 bool isPrivate() const override
401 {
402 return _has_privateKeyRole;
403 }
404
canExport() const405 bool canExport() const override
406 {
407 return !_has_privateKeyRole;
408 }
409
convertToPublic()410 void convertToPublic() override
411 {
412 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::convertToPublic - entry"), Logger::Debug);
413
414 if (_has_privateKeyRole) {
415 if (_pkcs11h_certificate != nullptr) {
416 pkcs11h_certificate_freeCertificate(_pkcs11h_certificate);
417 _pkcs11h_certificate = nullptr;
418 }
419 _has_privateKeyRole = false;
420 }
421
422 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::convertToPublic - return"), Logger::Debug);
423 }
424
bits() const425 int bits() const override
426 {
427 return _pubkey.bitSize();
428 }
429
maximumEncryptSize(EncryptionAlgorithm alg) const430 int maximumEncryptSize(EncryptionAlgorithm alg) const override
431 {
432 return _pubkey.maximumEncryptSize(alg);
433 }
434
encrypt(const SecureArray & in,EncryptionAlgorithm alg)435 SecureArray encrypt(const SecureArray &in, EncryptionAlgorithm alg) override
436 {
437 return _pubkey.encrypt(in, alg);
438 }
439
decrypt(const SecureArray & in,SecureArray * out,EncryptionAlgorithm alg)440 bool decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg) override
441 {
442 bool session_locked = false;
443 bool ret = false;
444
445 QCA_logTextMessage(
446 QString::asprintf("pkcs11RSAContext::decrypt - decrypt in.size()=%d, alg=%d", in.size(), (int)alg),
447 Logger::Debug);
448
449 try {
450 CK_MECHANISM_TYPE mech;
451 CK_RV rv;
452 size_t my_size;
453
454 switch (alg) {
455 case EME_PKCS1v15:
456 mech = CKM_RSA_PKCS;
457 break;
458 case EME_PKCS1_OAEP:
459 mech = CKM_RSA_PKCS_OAEP;
460 break;
461 default:
462 throw pkcs11Exception(CKR_FUNCTION_NOT_SUPPORTED, QStringLiteral("Invalid algorithm"));
463 break;
464 }
465
466 _ensureCertificate();
467
468 if ((rv = pkcs11h_certificate_lockSession(_pkcs11h_certificate)) != CKR_OK) {
469 throw pkcs11Exception(rv, QStringLiteral("Cannot lock session"));
470 }
471 session_locked = true;
472
473 if ((rv = pkcs11h_certificate_decryptAny(_pkcs11h_certificate,
474 mech,
475 (const unsigned char *)in.constData(),
476 in.size(),
477 nullptr,
478 &my_size)) != CKR_OK) {
479 throw pkcs11Exception(rv, QStringLiteral("Decryption error"));
480 }
481
482 out->resize(my_size);
483
484 if ((rv = pkcs11h_certificate_decryptAny(_pkcs11h_certificate,
485 mech,
486 (const unsigned char *)in.constData(),
487 in.size(),
488 (unsigned char *)out->data(),
489 &my_size)) != CKR_OK) {
490 throw pkcs11Exception(rv, QStringLiteral("Decryption error"));
491 }
492
493 rv = out->resize(my_size);
494
495 if ((rv = pkcs11h_certificate_releaseSession(_pkcs11h_certificate)) != CKR_OK) {
496 throw pkcs11Exception(rv, QStringLiteral("Cannot release session"));
497 }
498 session_locked = false;
499
500 ret = true;
501 } catch (const pkcs11Exception &e) {
502 if (session_locked) {
503 pkcs11h_certificate_releaseSession(_pkcs11h_certificate);
504 session_locked = false;
505 }
506
507 if (s_keyStoreList != nullptr) {
508 s_keyStoreList->_emit_diagnosticText(
509 QString::asprintf("PKCS#11: Cannot decrypt: %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
510 }
511 }
512
513 QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::decrypt - decrypt out->size()=%d", out->size()),
514 Logger::Debug);
515
516 return ret;
517 }
518
startSign(SignatureAlgorithm alg,SignatureFormat)519 void startSign(SignatureAlgorithm alg, SignatureFormat) override
520 {
521 _clearSign();
522
523 _sign_data.alg = alg;
524
525 switch (_sign_data.alg) {
526 case EMSA3_SHA1:
527 _sign_data.hash = new Hash(QStringLiteral("sha1"));
528 break;
529 case EMSA3_MD5:
530 _sign_data.hash = new Hash(QStringLiteral("md5"));
531 break;
532 case EMSA3_MD2:
533 _sign_data.hash = new Hash(QStringLiteral("md2"));
534 break;
535 case EMSA3_Raw:
536 break;
537 case SignatureUnknown:
538 case EMSA1_SHA1:
539 case EMSA3_RIPEMD160:
540 default:
541 QCA_logTextMessage(QString::asprintf("PKCS#11: Invalid hash algorithm %d", _sign_data.alg),
542 Logger::Warning);
543 break;
544 }
545 }
546
startVerify(SignatureAlgorithm alg,SignatureFormat sf)547 void startVerify(SignatureAlgorithm alg, SignatureFormat sf) override
548 {
549 _pubkey.startVerify(alg, sf);
550 }
551
update(const MemoryRegion & in)552 void update(const MemoryRegion &in) override
553 {
554 if (_has_privateKeyRole) {
555 if (_sign_data.hash != nullptr) {
556 _sign_data.hash->update(in);
557 } else {
558 _sign_data.raw.append(in.toByteArray());
559 }
560 } else {
561 _pubkey.update(in);
562 }
563 }
564
endSign()565 QByteArray endSign() override
566 {
567 QByteArray result;
568 bool session_locked = false;
569
570 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::endSign - entry"), Logger::Debug);
571
572 try {
573 QByteArray final;
574 CK_RV rv;
575
576 // from some strange reason I got 2047... (for some) <---- BUG?!?!?!
577 int myrsa_size = (_pubkey.bitSize() + 7) / 8;
578
579 if (_sign_data.hash != nullptr) {
580 final = emsa3Encode(_sign_data.hash->type(), _sign_data.hash->final().toByteArray(), myrsa_size);
581 } else {
582 final = _sign_data.raw;
583 }
584
585 if (final.size() == 0) {
586 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot encode signature"));
587 }
588
589 _ensureCertificate();
590
591 size_t my_size;
592
593 if ((rv = pkcs11h_certificate_lockSession(_pkcs11h_certificate)) != CKR_OK) {
594 throw pkcs11Exception(rv, QStringLiteral("Cannot lock session"));
595 }
596 session_locked = true;
597
598 if ((rv = pkcs11h_certificate_signAny(_pkcs11h_certificate,
599 CKM_RSA_PKCS,
600 (const unsigned char *) final.constData(),
601 (size_t) final.size(),
602 nullptr,
603 &my_size)) != CKR_OK) {
604 throw pkcs11Exception(rv, QStringLiteral("Signature failed"));
605 }
606
607 result.resize(my_size);
608
609 if ((rv = pkcs11h_certificate_signAny(_pkcs11h_certificate,
610 CKM_RSA_PKCS,
611 (const unsigned char *) final.constData(),
612 (size_t) final.size(),
613 (unsigned char *)result.data(),
614 &my_size)) != CKR_OK) {
615 throw pkcs11Exception(rv, QStringLiteral("Signature failed"));
616 }
617
618 result.resize(my_size);
619
620 if ((rv = pkcs11h_certificate_releaseSession(_pkcs11h_certificate)) != CKR_OK) {
621 throw pkcs11Exception(rv, QStringLiteral("Cannot release session"));
622 }
623 session_locked = false;
624
625 } catch (const pkcs11Exception &e) {
626 result.clear();
627
628 if (session_locked) {
629 pkcs11h_certificate_releaseSession(_pkcs11h_certificate);
630 session_locked = false;
631 }
632
633 if (s_keyStoreList != nullptr) {
634 s_keyStoreList->_emit_diagnosticText(
635 QString::asprintf("PKCS#11: Cannot sign: %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
636 }
637 }
638
639 _clearSign();
640
641 QCA_logTextMessage(
642 QString::asprintf("pkcs11RSAContext::endSign - return result.size ()=%d", int(result.size())),
643 Logger::Debug);
644
645 return result;
646 }
647
validSignature(const QByteArray & sig)648 virtual bool validSignature(const QByteArray &sig)
649 {
650 return _pubkey.validSignature(sig);
651 }
652
createPrivate(int bits,int exp,bool block)653 void createPrivate(int bits, int exp, bool block) override
654 {
655 Q_UNUSED(bits);
656 Q_UNUSED(exp);
657 Q_UNUSED(block);
658 }
659
createPrivate(const BigInteger & n,const BigInteger & e,const BigInteger & p,const BigInteger & q,const BigInteger & d)660 void createPrivate(const BigInteger &n,
661 const BigInteger &e,
662 const BigInteger &p,
663 const BigInteger &q,
664 const BigInteger &d) override
665 {
666 Q_UNUSED(n);
667 Q_UNUSED(e);
668 Q_UNUSED(p);
669 Q_UNUSED(q);
670 Q_UNUSED(d);
671 }
672
createPublic(const BigInteger & n,const BigInteger & e)673 void createPublic(const BigInteger &n, const BigInteger &e) override
674 {
675 Q_UNUSED(n);
676 Q_UNUSED(e);
677 }
678
n() const679 BigInteger n() const override
680 {
681 return _pubkey.n();
682 }
683
e() const684 BigInteger e() const override
685 {
686 return _pubkey.e();
687 }
688
p() const689 BigInteger p() const override
690 {
691 return BigInteger();
692 }
693
q() const694 BigInteger q() const override
695 {
696 return BigInteger();
697 }
698
d() const699 BigInteger d() const override
700 {
701 return BigInteger();
702 }
703
704 public:
_publicKey() const705 PublicKey _publicKey() const
706 {
707 return _pubkey;
708 }
709
_isTokenAvailable() const710 bool _isTokenAvailable() const
711 {
712 bool ret;
713
714 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureTokenAvailable - entry"), Logger::Debug);
715
716 ret = pkcs11h_token_ensureAccess(_pkcs11h_certificate_id->token_id, nullptr, 0) == CKR_OK;
717
718 QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::_ensureTokenAvailable - return ret=%d", ret ? 1 : 0),
719 Logger::Debug);
720
721 return ret;
722 }
723
_ensureTokenAccess()724 bool _ensureTokenAccess()
725 {
726 bool ret;
727
728 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureTokenAccess - entry"), Logger::Debug);
729
730 ret = pkcs11h_token_ensureAccess(_pkcs11h_certificate_id->token_id, nullptr, PKCS11H_PROMPT_MASK_ALLOW_ALL) ==
731 CKR_OK;
732
733 QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::_ensureTokenAccess - return ret=%d", ret ? 1 : 0),
734 Logger::Debug);
735
736 return ret;
737 }
738
739 private:
_clearSign()740 void _clearSign()
741 {
742 _sign_data.raw.clear();
743 _sign_data.alg = SignatureUnknown;
744 delete _sign_data.hash;
745 _sign_data.hash = nullptr;
746 }
747
_ensureCertificate()748 void _ensureCertificate()
749 {
750 CK_RV rv;
751
752 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureCertificate - entry"), Logger::Debug);
753
754 if (_pkcs11h_certificate == nullptr) {
755 if ((rv = pkcs11h_certificate_create(_pkcs11h_certificate_id,
756 &_serialized,
757 PKCS11H_PROMPT_MASK_ALLOW_ALL,
758 PKCS11H_PIN_CACHE_INFINITE,
759 &_pkcs11h_certificate)) != CKR_OK) {
760 throw pkcs11Exception(rv, QStringLiteral("Cannot create low-level certificate"));
761 }
762 }
763
764 QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureCertificate - return"), Logger::Debug);
765 }
766 };
767
768 //----------------------------------------------------------------------------
769 // pkcs11PKeyContext
770 //----------------------------------------------------------------------------
771 class pkcs11PKeyContext : public PKeyContext
772 {
773 Q_OBJECT
774
775 private:
776 PKeyBase *_k;
777
778 public:
pkcs11PKeyContext(Provider * p)779 pkcs11PKeyContext(Provider *p)
780 : PKeyContext(p)
781 {
782 _k = nullptr;
783 }
784
~pkcs11PKeyContext()785 ~pkcs11PKeyContext() override
786 {
787 delete _k;
788 _k = nullptr;
789 }
790
clone() const791 Provider::Context *clone() const override
792 {
793 pkcs11PKeyContext *c = new pkcs11PKeyContext(*this);
794 c->_k = (PKeyBase *)_k->clone();
795 return c;
796 }
797
798 public:
supportedTypes() const799 QList<PKey::Type> supportedTypes() const override
800 {
801 QList<PKey::Type> list;
802 list += PKey::RSA;
803 return list;
804 }
805
supportedIOTypes() const806 QList<PKey::Type> supportedIOTypes() const override
807 {
808 QList<PKey::Type> list;
809 list += PKey::RSA;
810 return list;
811 }
812
supportedPBEAlgorithms() const813 QList<PBEAlgorithm> supportedPBEAlgorithms() const override
814 {
815 QList<PBEAlgorithm> list;
816 return list;
817 }
818
key()819 PKeyBase *key() override
820 {
821 return _k;
822 }
823
key() const824 const PKeyBase *key() const override
825 {
826 return _k;
827 }
828
setKey(PKeyBase * key)829 void setKey(PKeyBase *key) override
830 {
831 delete _k;
832 _k = key;
833 }
834
importKey(const PKeyBase * key)835 bool importKey(const PKeyBase *key) override
836 {
837 Q_UNUSED(key);
838 return false;
839 }
840
passphrase_cb(char * buf,int size,int rwflag,void * u)841 static int passphrase_cb(char *buf, int size, int rwflag, void *u)
842 {
843 Q_UNUSED(buf);
844 Q_UNUSED(size);
845 Q_UNUSED(rwflag);
846 Q_UNUSED(u);
847 return 0;
848 }
849
publicToDER() const850 QByteArray publicToDER() const override
851 {
852 return static_cast<pkcs11RSAContext *>(_k)->_publicKey().toDER();
853 }
854
publicToPEM() const855 QString publicToPEM() const override
856 {
857 return static_cast<pkcs11RSAContext *>(_k)->_publicKey().toPEM();
858 }
859
publicFromDER(const QByteArray & in)860 ConvertResult publicFromDER(const QByteArray &in) override
861 {
862 Q_UNUSED(in);
863 return ErrorDecode;
864 }
865
publicFromPEM(const QString & s)866 ConvertResult publicFromPEM(const QString &s) override
867 {
868 Q_UNUSED(s);
869 return ErrorDecode;
870 }
871
privateToDER(const SecureArray & passphrase,PBEAlgorithm pbe) const872 SecureArray privateToDER(const SecureArray &passphrase, PBEAlgorithm pbe) const override
873 {
874 Q_UNUSED(passphrase);
875 Q_UNUSED(pbe);
876 return SecureArray();
877 }
878
privateToPEM(const SecureArray & passphrase,PBEAlgorithm pbe) const879 QString privateToPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const override
880 {
881 Q_UNUSED(passphrase);
882 Q_UNUSED(pbe);
883 return QString();
884 }
885
privateFromDER(const SecureArray & in,const SecureArray & passphrase)886 ConvertResult privateFromDER(const SecureArray &in, const SecureArray &passphrase) override
887 {
888 Q_UNUSED(in);
889 Q_UNUSED(passphrase);
890 return ErrorDecode;
891 }
892
privateFromPEM(const QString & s,const SecureArray & passphrase)893 ConvertResult privateFromPEM(const QString &s, const SecureArray &passphrase) override
894 {
895 Q_UNUSED(s);
896 Q_UNUSED(passphrase);
897 return ErrorDecode;
898 }
899 };
900
901 //----------------------------------------------------------------------------
902 // pkcs11KeyStoreEntryContext
903 //----------------------------------------------------------------------------
904 class pkcs11KeyStoreEntryContext : public KeyStoreEntryContext
905 {
906 Q_OBJECT
907 private:
908 KeyStoreEntry::Type _item_type;
909 KeyBundle _key;
910 Certificate _cert;
911 QString _storeId;
912 QString _id;
913 QString _serialized;
914 QString _storeName;
915 QString _name;
916
917 public:
pkcs11KeyStoreEntryContext(const Certificate & cert,const QString & storeId,const QString & serialized,const QString & storeName,const QString & name,Provider * p)918 pkcs11KeyStoreEntryContext(const Certificate &cert,
919 const QString & storeId,
920 const QString & serialized,
921 const QString & storeName,
922 const QString & name,
923 Provider * p)
924 : KeyStoreEntryContext(p)
925 {
926 _item_type = KeyStoreEntry::TypeCertificate;
927 _cert = cert;
928 _storeId = storeId;
929 _id = certificateHash(_cert);
930 _serialized = serialized;
931 _storeName = storeName;
932 _name = name;
933 }
934
pkcs11KeyStoreEntryContext(const KeyBundle & key,const QString & storeId,const QString & serialized,const QString & storeName,const QString & name,Provider * p)935 pkcs11KeyStoreEntryContext(const KeyBundle &key,
936 const QString & storeId,
937 const QString & serialized,
938 const QString & storeName,
939 const QString & name,
940 Provider * p)
941 : KeyStoreEntryContext(p)
942 {
943 _item_type = KeyStoreEntry::TypeKeyBundle;
944 _key = key;
945 _storeId = storeId, _id = certificateHash(key.certificateChain().primary());
946 _serialized = serialized;
947 _storeName = storeName;
948 _name = name;
949 }
950
pkcs11KeyStoreEntryContext(const pkcs11KeyStoreEntryContext & from)951 pkcs11KeyStoreEntryContext(const pkcs11KeyStoreEntryContext &from)
952 : KeyStoreEntryContext(from)
953 {
954 _item_type = from._item_type;
955 _key = from._key;
956 _storeId = from._storeId;
957 _id = from._id;
958 _serialized = from._serialized;
959 _storeName = from._storeName;
960 _name = from._name;
961 }
962
clone() const963 Provider::Context *clone() const override
964 {
965 return new pkcs11KeyStoreEntryContext(*this);
966 }
967
968 public:
type() const969 KeyStoreEntry::Type type() const override
970 {
971 return _item_type;
972 }
973
name() const974 QString name() const override
975 {
976 return _name;
977 }
978
id() const979 QString id() const override
980 {
981 return _id;
982 }
983
keyBundle() const984 KeyBundle keyBundle() const override
985 {
986 return _key;
987 }
988
certificate() const989 Certificate certificate() const override
990 {
991 return _cert;
992 }
993
storeId() const994 QString storeId() const override
995 {
996 return _storeId;
997 }
998
storeName() const999 QString storeName() const override
1000 {
1001 return _storeName;
1002 }
1003
isAvailable() const1004 bool isAvailable() const override
1005 {
1006 return static_cast<pkcs11RSAContext *>(static_cast<PKeyContext *>(_key.privateKey().context())->key())
1007 ->_isTokenAvailable();
1008 }
1009
ensureAccess()1010 bool ensureAccess() override
1011 {
1012 return static_cast<pkcs11RSAContext *>(static_cast<PKeyContext *>(_key.privateKey().context())->key())
1013 ->_ensureTokenAccess();
1014 }
1015
serialize() const1016 QString serialize() const override
1017 {
1018 return _serialized;
1019 }
1020 };
1021
1022 //----------------------------------------------------------------------------
1023 // pkcs11QCACrypto
1024 //----------------------------------------------------------------------------
1025 class pkcs11QCACrypto
1026 {
1027 private:
_pkcs11h_crypto_qca_initialize(void * const global_data)1028 static int _pkcs11h_crypto_qca_initialize(void *const global_data)
1029 {
1030 Q_UNUSED(global_data);
1031
1032 return TRUE; // krazy:exclude=captruefalse
1033 }
1034
_pkcs11h_crypto_qca_uninitialize(void * const global_data)1035 static int _pkcs11h_crypto_qca_uninitialize(void *const global_data)
1036 {
1037 Q_UNUSED(global_data);
1038
1039 return TRUE; // krazy:exclude=captruefalse
1040 }
1041
_pkcs11h_crypto_qca_certificate_get_expiration(void * const global_data,const unsigned char * const blob,const size_t blob_size,time_t * const expiration)1042 static int _pkcs11h_crypto_qca_certificate_get_expiration(void *const global_data,
1043 const unsigned char *const blob,
1044 const size_t blob_size,
1045 time_t *const expiration)
1046 {
1047 Q_UNUSED(global_data);
1048
1049 Certificate cert = Certificate::fromDER(QByteArray((char *)blob, blob_size));
1050
1051 *expiration = cert.notValidAfter().toSecsSinceEpoch();
1052
1053 return TRUE; // krazy:exclude=captruefalse
1054 }
1055
_pkcs11h_crypto_qca_certificate_get_dn(void * const global_data,const unsigned char * const blob,const size_t blob_size,char * const dn,const size_t dn_max)1056 static int _pkcs11h_crypto_qca_certificate_get_dn(void *const global_data,
1057 const unsigned char *const blob,
1058 const size_t blob_size,
1059 char *const dn,
1060 const size_t dn_max)
1061 {
1062 Q_UNUSED(global_data);
1063
1064 Certificate cert = Certificate::fromDER(QByteArray((char *)blob, blob_size));
1065 QString qdn = cert.subjectInfoOrdered().toString();
1066
1067 if ((size_t)qdn.length() > dn_max - 1) {
1068 return FALSE; // krazy:exclude=captruefalse
1069 } else {
1070 qstrcpy(dn, myPrintable(qdn));
1071 return TRUE; // krazy:exclude=captruefalse
1072 }
1073 }
1074
_pkcs11h_crypto_qca_certificate_is_issuer(void * const global_data,const unsigned char * const signer_blob,const size_t signer_blob_size,const unsigned char * const cert_blob,const size_t cert_blob_size)1075 static int _pkcs11h_crypto_qca_certificate_is_issuer(void *const global_data,
1076 const unsigned char *const signer_blob,
1077 const size_t signer_blob_size,
1078 const unsigned char *const cert_blob,
1079 const size_t cert_blob_size)
1080 {
1081 Q_UNUSED(global_data);
1082
1083 Certificate signer = Certificate::fromDER(QByteArray((char *)signer_blob, signer_blob_size));
1084
1085 Certificate cert = Certificate::fromDER(QByteArray((char *)cert_blob, cert_blob_size));
1086
1087 return signer.isIssuerOf(cert);
1088 }
1089
1090 public:
1091 static pkcs11h_engine_crypto_t crypto;
1092 };
1093
1094 pkcs11h_engine_crypto_t pkcs11QCACrypto::crypto = {nullptr,
1095 _pkcs11h_crypto_qca_initialize,
1096 _pkcs11h_crypto_qca_uninitialize,
1097 _pkcs11h_crypto_qca_certificate_get_expiration,
1098 _pkcs11h_crypto_qca_certificate_get_dn,
1099 _pkcs11h_crypto_qca_certificate_is_issuer};
1100
1101 //----------------------------------------------------------------------------
1102 // pkcs11KeyStoreListContext
1103 //----------------------------------------------------------------------------
pkcs11KeyStoreListContext(Provider * p)1104 pkcs11KeyStoreListContext::pkcs11KeyStoreListContext(Provider *p)
1105 : KeyStoreListContext(p)
1106 {
1107 QCA_logTextMessage(
1108 QString::asprintf("pkcs11KeyStoreListContext::pkcs11KeyStoreListContext - entry Provider=%p", (void *)p),
1109 Logger::Debug);
1110
1111 _last_id = 0;
1112 _initialized = false;
1113
1114 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::pkcs11KeyStoreListContext - return"), Logger::Debug);
1115 }
1116
~pkcs11KeyStoreListContext()1117 pkcs11KeyStoreListContext::~pkcs11KeyStoreListContext()
1118 {
1119 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::~pkcs11KeyStoreListContext - entry"), Logger::Debug);
1120
1121 s_keyStoreList = nullptr;
1122 _clearStores();
1123
1124 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::~pkcs11KeyStoreListContext - return"), Logger::Debug);
1125 }
1126
clone() const1127 Provider::Context *pkcs11KeyStoreListContext::clone() const
1128 {
1129 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::clone - entry/return"), Logger::Debug);
1130 return nullptr;
1131 }
1132
start()1133 void pkcs11KeyStoreListContext::start()
1134 {
1135 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::start - entry"), Logger::Debug);
1136
1137 QMetaObject::invokeMethod(this, "doReady", Qt::QueuedConnection);
1138
1139 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::start - return"), Logger::Debug);
1140 }
1141
setUpdatesEnabled(bool enabled)1142 void pkcs11KeyStoreListContext::setUpdatesEnabled(bool enabled)
1143 {
1144 QCA_logTextMessage(
1145 QString::asprintf("pkcs11KeyStoreListContext::setUpdatesEnabled - entry enabled=%d", enabled ? 1 : 0),
1146 Logger::Debug);
1147
1148 try {
1149 pkcs11Provider *p = static_cast<pkcs11Provider *>(provider());
1150 if (enabled) {
1151 p->startSlotEvents();
1152 } else {
1153 p->stopSlotEvents();
1154 }
1155 } catch (const pkcs11Exception &e) {
1156 s_keyStoreList->_emit_diagnosticText(
1157 QString::asprintf("PKCS#11: Start event failed %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1158 }
1159
1160 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::setUpdatesEnabled - return"), Logger::Debug);
1161 }
1162
entry(int id,const QString & entryId)1163 KeyStoreEntryContext *pkcs11KeyStoreListContext::entry(int id, const QString &entryId)
1164 {
1165 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::entry - entry/return id=%d entryId='%s'",
1166 id,
1167 myPrintable(entryId)),
1168 Logger::Debug);
1169
1170 Q_UNUSED(id);
1171 Q_UNUSED(entryId);
1172 return nullptr;
1173 }
1174
entryPassive(const QString & serialized)1175 KeyStoreEntryContext *pkcs11KeyStoreListContext::entryPassive(const QString &serialized)
1176 {
1177 KeyStoreEntryContext * entry = nullptr;
1178 pkcs11h_certificate_id_t certificate_id = nullptr;
1179
1180 QCA_logTextMessage(
1181 QString::asprintf("pkcs11KeyStoreListContext::entryPassive - entry serialized='%s'", myPrintable(serialized)),
1182 Logger::Debug);
1183
1184 try {
1185 if (serialized.startsWith(QLatin1String("qca-pkcs11/"))) {
1186 CertificateChain chain;
1187 bool has_private;
1188
1189 _deserializeCertificate(serialized, &certificate_id, &has_private, chain);
1190 pkcs11KeyStoreItem *sentry = _registerTokenId(certificate_id->token_id);
1191 sentry->registerCertificates(chain);
1192 QMap<QString, QString> friendlyNames = sentry->friendlyNames();
1193
1194 entry = _keyStoreEntryByCertificateId(
1195 certificate_id, has_private, chain, friendlyNames[certificateHash(chain.primary())]);
1196 }
1197 } catch (const pkcs11Exception &e) {
1198 s_keyStoreList->_emit_diagnosticText(
1199 QString::asprintf("PKCS#11: Add key store entry %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1200 }
1201
1202 if (certificate_id != nullptr) {
1203 pkcs11h_certificate_freeCertificateId(certificate_id);
1204 certificate_id = nullptr;
1205 }
1206
1207 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::entryPassive - return entry=%p", (void *)entry),
1208 Logger::Debug);
1209
1210 return entry;
1211 }
1212
type(int id) const1213 KeyStore::Type pkcs11KeyStoreListContext::type(int id) const
1214 {
1215 Q_UNUSED(id);
1216
1217 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::type - entry/return id=%d", id), Logger::Debug);
1218
1219 return KeyStore::SmartCard;
1220 }
1221
storeId(int id) const1222 QString pkcs11KeyStoreListContext::storeId(int id) const
1223 {
1224 QString ret;
1225
1226 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::storeId - entry id=%d", id), Logger::Debug);
1227
1228 if (_storesById.contains(id)) {
1229 ret = _tokenId2storeId(_storesById[id]->tokenId());
1230 }
1231
1232 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::storeId - return ret=%s", myPrintable(ret)),
1233 Logger::Debug);
1234
1235 return ret;
1236 }
1237
name(int id) const1238 QString pkcs11KeyStoreListContext::name(int id) const
1239 {
1240 QString ret;
1241
1242 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::name - entry id=%d", id), Logger::Debug);
1243
1244 if (_storesById.contains(id)) {
1245 ret = QString::fromLatin1(_storesById[id]->tokenId()->label);
1246 }
1247
1248 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::name - return ret=%s", myPrintable(ret)),
1249 Logger::Debug);
1250
1251 return ret;
1252 }
1253
entryTypes(int id) const1254 QList<KeyStoreEntry::Type> pkcs11KeyStoreListContext::entryTypes(int id) const
1255 {
1256 Q_UNUSED(id);
1257
1258 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::entryTypes - entry/return id=%d", id),
1259 Logger::Debug);
1260
1261 QList<KeyStoreEntry::Type> list;
1262 list += KeyStoreEntry::TypeKeyBundle;
1263 list += KeyStoreEntry::TypeCertificate;
1264 return list;
1265 }
1266
keyStores()1267 QList<int> pkcs11KeyStoreListContext::keyStores()
1268 {
1269 pkcs11h_token_id_list_t tokens = nullptr;
1270 QList<int> out;
1271
1272 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::keyStores - entry"), Logger::Debug);
1273
1274 try {
1275 CK_RV rv;
1276
1277 /*
1278 * Get available tokens
1279 */
1280 if ((rv = pkcs11h_token_enumTokenIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, &tokens)) != CKR_OK) {
1281 throw pkcs11Exception(rv, QStringLiteral("Enumerating tokens"));
1282 }
1283
1284 /*
1285 * Register all tokens, unmark
1286 * them from remove list
1287 */
1288 QList<int> to_remove = _storesById.keys();
1289 for (pkcs11h_token_id_list_t entry = tokens; entry != nullptr; entry = entry->next) {
1290 pkcs11KeyStoreItem *item = _registerTokenId(entry->token_id);
1291 out += item->id();
1292 to_remove.removeAll(item->id());
1293 }
1294
1295 /*
1296 * Remove all items
1297 * that were not discovered
1298 */
1299 {
1300 QMutexLocker l(&_mutexStores);
1301
1302 foreach (int i, to_remove) {
1303 pkcs11KeyStoreItem *item = _storesById[i];
1304
1305 _storesById.remove(item->id());
1306 _stores.removeAll(item);
1307
1308 delete item;
1309 item = nullptr;
1310 }
1311 }
1312 } catch (const pkcs11Exception &e) {
1313 s_keyStoreList->_emit_diagnosticText(
1314 QString::asprintf("PKCS#11: Cannot get key stores: %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1315 }
1316
1317 if (tokens != nullptr) {
1318 pkcs11h_token_freeTokenIdList(tokens);
1319 }
1320
1321 QCA_logTextMessage(
1322 QString::asprintf("pkcs11KeyStoreListContext::keyStores - return out.size()=%d", int(out.size())),
1323 Logger::Debug);
1324
1325 return out;
1326 }
1327
entryList(int id)1328 QList<KeyStoreEntryContext *> pkcs11KeyStoreListContext::entryList(int id)
1329 {
1330 pkcs11h_certificate_id_list_t certs = nullptr;
1331 QList<KeyStoreEntryContext *> out;
1332
1333 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::entryList - entry id=%d", id), Logger::Debug);
1334
1335 try {
1336 CK_RV rv;
1337
1338 if (_storesById.contains(id)) {
1339 pkcs11KeyStoreItem *entry = _storesById[id];
1340
1341 pkcs11h_certificate_id_list_t issuers = nullptr;
1342 pkcs11h_certificate_id_list_t current = nullptr;
1343 QList<Certificate> listCerts;
1344 QList<Certificate> listIssuers;
1345 int i = 0;
1346
1347 if ((rv = pkcs11h_certificate_enumTokenCertificateIds(entry->tokenId(),
1348 PKCS11H_ENUM_METHOD_CACHE,
1349 nullptr,
1350 PKCS11H_PROMPT_MASK_ALLOW_ALL,
1351 &issuers,
1352 &certs)) != CKR_OK) {
1353 throw pkcs11Exception(rv, QStringLiteral("Enumerate certificates"));
1354 }
1355
1356 for (current = certs; current != nullptr; current = current->next) {
1357 if (current->certificate_id->certificate_blob_size > 0) {
1358 listCerts += Certificate::fromDER(QByteArray((char *)current->certificate_id->certificate_blob,
1359 current->certificate_id->certificate_blob_size));
1360 }
1361 }
1362
1363 for (current = issuers; current != nullptr; current = current->next) {
1364 if (current->certificate_id->certificate_blob_size > 0) {
1365 listIssuers += Certificate::fromDER(QByteArray((char *)current->certificate_id->certificate_blob,
1366 current->certificate_id->certificate_blob_size));
1367 }
1368 }
1369
1370 entry->registerCertificates(listIssuers + listCerts);
1371 QMap<QString, QString> friendlyNames = entry->friendlyNames();
1372
1373 QList<Certificate> listIssuersForComplete;
1374 if (dynamic_cast<pkcs11Provider *>(provider())->_allowLoadRootCA) {
1375 listIssuersForComplete = listIssuers;
1376 } else {
1377 foreach (Certificate c, listIssuers) {
1378 if (!c.isSelfSigned()) {
1379 listIssuersForComplete += c;
1380 }
1381 }
1382 }
1383
1384 for (i = 0, current = issuers; current != nullptr; i++, current = current->next) {
1385 try {
1386 if (listIssuers[i].isNull()) {
1387 throw pkcs11Exception(CKR_ARGUMENTS_BAD, QStringLiteral("Invalid certificate"));
1388 }
1389
1390 if (listIssuers[i].isSelfSigned() && dynamic_cast<pkcs11Provider *>(provider())->_allowLoadRootCA) {
1391 CertificateChain chain = CertificateChain(listIssuers[i]).complete(listIssuersForComplete);
1392 out += _keyStoreEntryByCertificateId(
1393 current->certificate_id, false, chain, friendlyNames[certificateHash(chain.primary())]);
1394 }
1395 } catch (const pkcs11Exception &e) {
1396 s_keyStoreList->_emit_diagnosticText(QString::asprintf(
1397 "PKCS#11: Add key store entry %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1398 }
1399 }
1400
1401 for (i = 0, current = certs; current != nullptr; i++, current = current->next) {
1402 try {
1403 if (listCerts[i].isNull()) {
1404 throw pkcs11Exception(CKR_ARGUMENTS_BAD, QStringLiteral("Invalid certificate"));
1405 }
1406
1407 CertificateChain chain = CertificateChain(listCerts[i]).complete(listIssuersForComplete);
1408 out += _keyStoreEntryByCertificateId(
1409 current->certificate_id, true, chain, friendlyNames[certificateHash(chain.primary())]);
1410 } catch (const pkcs11Exception &e) {
1411 s_keyStoreList->_emit_diagnosticText(QString::asprintf(
1412 "PKCS#11: Add key store entry %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1413 }
1414 }
1415 }
1416 } catch (const pkcs11Exception &e) {
1417 s_keyStoreList->_emit_diagnosticText(
1418 QString::asprintf("PKCS#11: Enumerating store failed %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
1419 }
1420
1421 if (certs != nullptr) {
1422 pkcs11h_certificate_freeCertificateIdList(certs);
1423 }
1424
1425 QCA_logTextMessage(
1426 QString::asprintf("pkcs11KeyStoreListContext::entryList - return out.size()=%d", int(out.size())),
1427 Logger::Debug);
1428
1429 return out;
1430 }
1431
_tokenPrompt(void * const user_data,const pkcs11h_token_id_t token_id)1432 bool pkcs11KeyStoreListContext::_tokenPrompt(void *const user_data, const pkcs11h_token_id_t token_id)
1433 {
1434 KeyStoreEntry entry;
1435 KeyStoreEntryContext *context = nullptr;
1436 QString storeId, storeName;
1437 bool ret = false;
1438
1439 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_tokenPrompt - entry user_data=%p, token_id=%p",
1440 user_data,
1441 (void *)token_id),
1442 Logger::Debug);
1443
1444 if (user_data != nullptr) {
1445 QString *serialized = (QString *)user_data;
1446 context = entryPassive(*serialized);
1447 storeId = context->storeId();
1448 storeName = context->storeName();
1449 entry.change(context);
1450 } else {
1451 _registerTokenId(token_id);
1452 storeId = _tokenId2storeId(token_id);
1453 storeName = QString::fromLatin1(token_id->label);
1454 }
1455
1456 TokenAsker asker;
1457 asker.ask(KeyStoreInfo(KeyStore::SmartCard, storeId, storeName), entry, context);
1458 asker.waitForResponse();
1459 if (asker.accepted()) {
1460 ret = true;
1461 }
1462
1463 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_tokenPrompt - return ret=%d", ret ? 1 : 0),
1464 Logger::Debug);
1465
1466 return ret;
1467 }
1468
_pinPrompt(void * const user_data,const pkcs11h_token_id_t token_id,SecureArray & pin)1469 bool pkcs11KeyStoreListContext::_pinPrompt(void *const user_data, const pkcs11h_token_id_t token_id, SecureArray &pin)
1470 {
1471 KeyStoreEntry entry;
1472 KeyStoreEntryContext *context = nullptr;
1473 QString storeId, storeName;
1474 bool ret = false;
1475
1476 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_pinPrompt - entry user_data=%p, token_id=%p",
1477 user_data,
1478 (void *)token_id),
1479 Logger::Debug);
1480
1481 pin = SecureArray();
1482
1483 if (user_data != nullptr) {
1484 QString *serialized = (QString *)user_data;
1485 context = entryPassive(*serialized);
1486 storeId = context->storeId();
1487 storeName = context->storeName();
1488 entry.change(context);
1489 } else {
1490 _registerTokenId(token_id);
1491 storeId = _tokenId2storeId(token_id);
1492 storeName = QString::fromLatin1(token_id->label);
1493 }
1494
1495 PasswordAsker asker;
1496 asker.ask(Event::StylePIN, KeyStoreInfo(KeyStore::SmartCard, storeId, storeName), entry, context);
1497 asker.waitForResponse();
1498 if (asker.accepted()) {
1499 ret = true;
1500 pin = asker.password();
1501 }
1502
1503 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_pinPrompt - return ret=%d", ret ? 1 : 0),
1504 Logger::Debug);
1505
1506 return ret;
1507 }
1508
_emit_diagnosticText(const QString & t)1509 void pkcs11KeyStoreListContext::_emit_diagnosticText(const QString &t)
1510 {
1511 QCA_logTextMessage(
1512 QString::asprintf("pkcs11KeyStoreListContext::_emit_diagnosticText - entry t='%s'", myPrintable(t)),
1513 Logger::Debug);
1514
1515 QCA_logTextMessage(t, Logger::Warning);
1516
1517 emit diagnosticText(t);
1518
1519 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::_emit_diagnosticText - return"), Logger::Debug);
1520 }
1521
doReady()1522 void pkcs11KeyStoreListContext::doReady()
1523 {
1524 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::doReady - entry"), Logger::Debug);
1525
1526 emit busyEnd();
1527
1528 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::doReady - return"), Logger::Debug);
1529 }
1530
doUpdated()1531 void pkcs11KeyStoreListContext::doUpdated()
1532 {
1533 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::doUpdated - entry"), Logger::Debug);
1534
1535 emit updated();
1536
1537 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::doUpdated - return"), Logger::Debug);
1538 }
1539
1540 pkcs11KeyStoreListContext::pkcs11KeyStoreItem *
_registerTokenId(const pkcs11h_token_id_t token_id)1541 pkcs11KeyStoreListContext::_registerTokenId(const pkcs11h_token_id_t token_id)
1542 {
1543 QCA_logTextMessage(
1544 QString::asprintf("pkcs11KeyStoreListContext::_registerTokenId - entry token_id=%p", (void *)token_id),
1545 Logger::Debug);
1546
1547 QMutexLocker l(&_mutexStores);
1548
1549 _stores_t::iterator i = _stores.begin();
1550
1551 while (i != _stores.end() && !pkcs11h_token_sameTokenId(token_id, (*i)->tokenId())) {
1552 i++;
1553 }
1554
1555 pkcs11KeyStoreItem *entry = nullptr;
1556
1557 if (i == _stores.end()) {
1558 /*
1559 * Deal with last_id overlap
1560 */
1561 while (_storesById.find(++_last_id) != _storesById.end())
1562 ;
1563
1564 entry = new pkcs11KeyStoreItem(_last_id, token_id);
1565
1566 _stores += entry;
1567 _storesById.insert(entry->id(), entry);
1568 } else {
1569 entry = (*i);
1570 }
1571
1572 QCA_logTextMessage(
1573 QString::asprintf("pkcs11KeyStoreListContext::_registerTokenId - return entry=%p", (void *)token_id),
1574 Logger::Debug);
1575
1576 return entry;
1577 }
1578
_clearStores()1579 void pkcs11KeyStoreListContext::_clearStores()
1580 {
1581 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::_clearStores - entry"), Logger::Debug);
1582
1583 QMutexLocker l(&_mutexStores);
1584
1585 _storesById.clear();
1586 foreach (pkcs11KeyStoreItem *i, _stores) {
1587 delete i;
1588 }
1589
1590 _stores.clear();
1591
1592 QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::_clearStores - return"), Logger::Debug);
1593 }
1594
1595 pkcs11KeyStoreEntryContext *
_keyStoreEntryByCertificateId(const pkcs11h_certificate_id_t certificate_id,const bool has_private,const CertificateChain & chain,const QString & _description) const1596 pkcs11KeyStoreListContext::_keyStoreEntryByCertificateId(const pkcs11h_certificate_id_t certificate_id,
1597 const bool has_private,
1598 const CertificateChain & chain,
1599 const QString & _description) const
1600 {
1601 pkcs11KeyStoreEntryContext *entry = nullptr;
1602
1603 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_keyStoreEntryByCertificateId - entry "
1604 "certificate_id=%p, has_private=%d, chain.size()=%d",
1605 (void *)certificate_id,
1606 has_private ? 1 : 0,
1607 int(chain.size())),
1608 Logger::Debug);
1609
1610 if (certificate_id == nullptr) {
1611 throw pkcs11Exception(CKR_ARGUMENTS_BAD, QStringLiteral("Missing certificate object"));
1612 }
1613
1614 QString serialized = _serializeCertificate(certificate_id, chain, has_private);
1615
1616 QString description = _description;
1617 const Certificate &cert = chain.primary();
1618 if (description.isEmpty()) {
1619 description = cert.subjectInfoOrdered().toString() + QStringLiteral(" by ") +
1620 cert.issuerInfo().value(CommonName, QStringLiteral("Unknown"));
1621 }
1622
1623 if (has_private) {
1624 pkcs11RSAContext *rsakey =
1625 new pkcs11RSAContext(provider(), certificate_id, serialized, cert.subjectPublicKey().toRSA());
1626
1627 pkcs11PKeyContext *pkc = new pkcs11PKeyContext(provider());
1628 pkc->setKey(rsakey);
1629 PrivateKey privkey;
1630 privkey.change(pkc);
1631 KeyBundle key;
1632 key.setCertificateChainAndKey(chain, privkey);
1633
1634 entry = new pkcs11KeyStoreEntryContext(key,
1635 _tokenId2storeId(certificate_id->token_id),
1636 serialized,
1637 QString::fromLatin1(certificate_id->token_id->label),
1638 description,
1639 provider());
1640 } else {
1641 entry = new pkcs11KeyStoreEntryContext(cert,
1642 _tokenId2storeId(certificate_id->token_id),
1643 serialized,
1644 QString::fromLatin1(certificate_id->token_id->label),
1645 description,
1646 provider());
1647 }
1648
1649 QCA_logTextMessage(
1650 QString::asprintf("pkcs11KeyStoreListContext::_keyStoreEntryByCertificateId - return entry=%p", (void *)entry),
1651 Logger::Debug);
1652
1653 return entry;
1654 }
1655
_tokenId2storeId(const pkcs11h_token_id_t token_id) const1656 QString pkcs11KeyStoreListContext::_tokenId2storeId(const pkcs11h_token_id_t token_id) const
1657 {
1658 QString storeId;
1659 size_t len;
1660
1661 QCA_logTextMessage(
1662 QString::asprintf("pkcs11KeyStoreListContext::_tokenId2storeId - entry token_id=%p", (void *)token_id),
1663 Logger::Debug);
1664
1665 if (pkcs11h_token_serializeTokenId(nullptr, &len, token_id) != CKR_OK) {
1666 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot serialize token id"));
1667 }
1668
1669 QByteArray buf;
1670 buf.resize((int)len);
1671
1672 if (pkcs11h_token_serializeTokenId(buf.data(), &len, token_id) != CKR_OK) {
1673 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot serialize token id"));
1674 }
1675
1676 buf.resize((int)len);
1677
1678 storeId = QStringLiteral("qca-pkcs11/") + _escapeString(QString::fromUtf8(buf));
1679
1680 QCA_logTextMessage(
1681 QString::asprintf("pkcs11KeyStoreListContext::_tokenId2storeId - return storeId='%s'", myPrintable(storeId)),
1682 Logger::Debug);
1683
1684 return storeId;
1685 }
1686
_serializeCertificate(const pkcs11h_certificate_id_t certificate_id,const CertificateChain & chain,const bool has_private) const1687 QString pkcs11KeyStoreListContext::_serializeCertificate(const pkcs11h_certificate_id_t certificate_id,
1688 const CertificateChain & chain,
1689 const bool has_private) const
1690 {
1691 QString serialized;
1692 size_t len;
1693
1694 QCA_logTextMessage(
1695 QString::asprintf(
1696 "pkcs11KeyStoreListContext::_serializeCertificate - entry certificate_id=%p, xx, has_private=%d",
1697 (void *)certificate_id,
1698 has_private ? 1 : 0),
1699 Logger::Debug);
1700
1701 if (pkcs11h_certificate_serializeCertificateId(nullptr, &len, certificate_id) != CKR_OK) {
1702 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot serialize certificate id"));
1703 }
1704
1705 QByteArray buf;
1706 buf.resize((int)len);
1707
1708 if (pkcs11h_certificate_serializeCertificateId(buf.data(), &len, certificate_id) != CKR_OK) {
1709 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot serialize certificate id"));
1710 }
1711
1712 buf.resize((int)len);
1713
1714 serialized = QString::asprintf(
1715 "qca-pkcs11/0/%s/%d/", myPrintable(_escapeString(QString::fromUtf8(buf))), has_private ? 1 : 0);
1716
1717 QStringList list;
1718 foreach (Certificate i, chain) {
1719 list += _escapeString(Base64().arrayToString(i.toDER()));
1720 }
1721
1722 serialized.append(list.join(QStringLiteral("/")));
1723
1724 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_serializeCertificate - return serialized='%s'",
1725 myPrintable(serialized)),
1726 Logger::Debug);
1727
1728 return serialized;
1729 }
1730
_deserializeCertificate(const QString & from,pkcs11h_certificate_id_t * const p_certificate_id,bool * const p_has_private,CertificateChain & chain) const1731 void pkcs11KeyStoreListContext::_deserializeCertificate(const QString & from,
1732 pkcs11h_certificate_id_t *const p_certificate_id,
1733 bool *const p_has_private,
1734 CertificateChain & chain) const
1735 {
1736 pkcs11h_certificate_id_t certificate_id = nullptr;
1737 chain.clear();
1738
1739 QCA_logTextMessage(QString::asprintf("pkcs11KeyStoreListContext::_deserializeCertificate - entry from='%s', "
1740 "p_certificate_id=%p, p_has_private=%p",
1741 myPrintable(from),
1742 (void *)p_certificate_id,
1743 (void *)p_has_private),
1744 Logger::Debug);
1745
1746 try {
1747 int n = 0;
1748 CK_RV rv;
1749
1750 *p_certificate_id = nullptr;
1751 *p_has_private = false;
1752
1753 const QStringList list = from.split(QStringLiteral("/"));
1754
1755 if (list.size() < 5) {
1756 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Invalid serialization"));
1757 }
1758
1759 if (list[n++] != QLatin1String("qca-pkcs11")) {
1760 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Invalid serialization"));
1761 }
1762
1763 if (list[n++].toInt() != 0) {
1764 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Invalid serialization version"));
1765 }
1766
1767 if ((rv = pkcs11h_certificate_deserializeCertificateId(&certificate_id,
1768 myPrintable(_unescapeString(list[n++])))) != CKR_OK) {
1769 throw pkcs11Exception(rv, QStringLiteral("Invalid serialization"));
1770 }
1771
1772 *p_has_private = list[n++].toInt() != 0;
1773
1774 const QByteArray endCertificateBytes = Base64().stringToArray(_unescapeString(list[n++])).toByteArray();
1775 Certificate endCertificate = Certificate::fromDER(endCertificateBytes);
1776
1777 if (endCertificate.isNull()) {
1778 throw pkcs11Exception(rv, QStringLiteral("Invalid certificate"));
1779 }
1780
1781 if ((rv = pkcs11h_certificate_setCertificateIdCertificateBlob(certificate_id,
1782 (const unsigned char *)endCertificateBytes.data(),
1783 (size_t)endCertificateBytes.size())) != CKR_OK) {
1784 throw pkcs11Exception(rv, QStringLiteral("Invalid serialization"));
1785 }
1786
1787 chain = endCertificate;
1788 while (n < list.size()) {
1789 Certificate cert = Certificate::fromDER(Base64().stringToArray(_unescapeString(list[n++])).toByteArray());
1790 if (cert.isNull()) {
1791 throw pkcs11Exception(rv, QStringLiteral("Invalid certificate"));
1792 }
1793 chain += cert;
1794 }
1795
1796 *p_certificate_id = certificate_id;
1797 certificate_id = nullptr;
1798 } catch (...) {
1799 if (certificate_id != nullptr) {
1800 pkcs11h_certificate_freeCertificateId(certificate_id);
1801 certificate_id = nullptr;
1802 }
1803 throw;
1804 }
1805
1806 QCA_logTextMessage(
1807 QString::asprintf(
1808 "pkcs11KeyStoreListContext::_deserializeCertificate - return *p_certificate_id=%p, chain.size()=%d",
1809 (void *)*p_certificate_id,
1810 int(chain.size())),
1811 Logger::Debug);
1812 }
1813
_escapeString(const QString & from) const1814 QString pkcs11KeyStoreListContext::_escapeString(const QString &from) const
1815 {
1816 QString to;
1817
1818 foreach (QChar c, from) {
1819 if (c == QLatin1Char('/') || c == QLatin1Char('\\')) {
1820 to += QString::asprintf("\\x%04x", c.unicode());
1821 } else {
1822 to += c;
1823 }
1824 }
1825
1826 return to;
1827 }
1828
_unescapeString(const QString & from) const1829 QString pkcs11KeyStoreListContext::_unescapeString(const QString &from) const
1830 {
1831 QString to;
1832
1833 for (int i = 0; i < from.size(); i++) {
1834 QChar c = from[i];
1835
1836 if (c == QLatin1Char('\\')) {
1837 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
1838 to += QChar((ushort)QStringView(from).mid(i + 2, 4).toInt(nullptr, 16));
1839 #else
1840 to += QChar((ushort)from.midRef(i + 2, 4).toInt(nullptr, 16));
1841 #endif
1842 i += 5;
1843 } else {
1844 to += c;
1845 }
1846 }
1847
1848 return to;
1849 }
1850
1851 }
1852
1853 using namespace pkcs11QCAPlugin;
1854
1855 const int pkcs11Provider::_CONFIG_MAX_PROVIDERS = 10;
1856
1857 //----------------------------------------------------------------------------
1858 // pkcs11Provider
1859 //----------------------------------------------------------------------------
pkcs11Provider()1860 pkcs11Provider::pkcs11Provider()
1861 {
1862 QCA_logTextMessage(QStringLiteral("pkcs11Provider::pkcs11Provider - entry"), Logger::Debug);
1863
1864 _lowLevelInitialized = false;
1865 _slotEventsActive = false;
1866 _slotEventsLowLevelActive = false;
1867 _allowLoadRootCA = false;
1868
1869 QCA_logTextMessage(QStringLiteral("pkcs11Provider::pkcs11Provider - return"), Logger::Debug);
1870 }
1871
~pkcs11Provider()1872 pkcs11Provider::~pkcs11Provider()
1873 {
1874 QCA_logTextMessage(QStringLiteral("pkcs11Provider::~pkcs11Provider - entry/return"), Logger::Debug);
1875 }
1876
qcaVersion() const1877 int pkcs11Provider::qcaVersion() const
1878 {
1879 QCA_logTextMessage(QStringLiteral("pkcs11Provider::qcaVersion - entry/return"), Logger::Debug);
1880
1881 return QCA_VERSION;
1882 }
1883
init()1884 void pkcs11Provider::init()
1885 {
1886 QCA_logTextMessage(QStringLiteral("pkcs11Provider::init - entry"), Logger::Debug);
1887
1888 try {
1889 CK_RV rv;
1890
1891 if ((rv = pkcs11h_engine_setCrypto(&pkcs11QCACrypto::crypto)) != CKR_OK) {
1892 throw pkcs11Exception(rv, QStringLiteral("Cannot set crypto"));
1893 }
1894
1895 if ((rv = pkcs11h_initialize()) != CKR_OK) {
1896 throw pkcs11Exception(rv, QStringLiteral("Cannot initialize"));
1897 }
1898
1899 if ((rv = pkcs11h_setLogHook(__logHook, this)) != CKR_OK) {
1900 throw pkcs11Exception(rv, QStringLiteral("Cannot set hook"));
1901 }
1902
1903 pkcs11h_setLogLevel(0);
1904
1905 if ((rv = pkcs11h_setTokenPromptHook(__tokenPromptHook, this)) != CKR_OK) {
1906 throw pkcs11Exception(rv, QStringLiteral("Cannot set hook"));
1907 }
1908
1909 if ((rv = pkcs11h_setPINPromptHook(__pinPromptHook, this)) != CKR_OK) {
1910 throw pkcs11Exception(rv, QStringLiteral("Cannot set hook"));
1911 }
1912
1913 _lowLevelInitialized = true;
1914 } catch (const pkcs11Exception &e) {
1915 QCA_logTextMessage(e.message(), Logger::Error);
1916 appendPluginDiagnosticText(
1917 QString::asprintf("An error %s during initialization of qca-pkcs11 plugin\n", myPrintable(e.message())));
1918 } catch (...) {
1919 QCA_logTextMessage(QStringLiteral("PKCS#11: Unknown error during provider initialization"), Logger::Error);
1920 appendPluginDiagnosticText(QStringLiteral("Unknown error during initialization of qca-pkcs11 plugin\n"));
1921 }
1922
1923 QCA_logTextMessage(QStringLiteral("pkcs11Provider::init - return"), Logger::Debug);
1924 }
1925
deinit()1926 void pkcs11Provider::deinit()
1927 {
1928 QCA_logTextMessage(QStringLiteral("pkcs11Provider::deinit - entry"), Logger::Debug);
1929
1930 delete s_keyStoreList;
1931 s_keyStoreList = nullptr;
1932
1933 pkcs11h_terminate();
1934
1935 QCA_logTextMessage(QStringLiteral("pkcs11Provider::deinit - return"), Logger::Debug);
1936 }
1937
name() const1938 QString pkcs11Provider::name() const
1939 {
1940 QCA_logTextMessage(QStringLiteral("pkcs11Provider::name - entry/return"), Logger::Debug);
1941
1942 return QStringLiteral("qca-pkcs11");
1943 }
1944
features() const1945 QStringList pkcs11Provider::features() const
1946 {
1947 QCA_logTextMessage(QStringLiteral("pkcs11Provider::features - entry/return"), Logger::Debug);
1948
1949 QStringList list;
1950 list += QStringLiteral("smartcard"); // indicator, not algorithm
1951 list += QStringLiteral("pkey");
1952 list += QStringLiteral("keystorelist");
1953 return list;
1954 }
1955
createContext(const QString & type)1956 Provider::Context *pkcs11Provider::createContext(const QString &type)
1957 {
1958 Provider::Context *context = nullptr;
1959
1960 QCA_logTextMessage(QString::asprintf("pkcs11Provider::createContext - entry type='%s'", myPrintable(type)),
1961 Logger::Debug);
1962
1963 if (_lowLevelInitialized) {
1964 if (type == QLatin1String("keystorelist")) {
1965 if (s_keyStoreList == nullptr) {
1966 s_keyStoreList = new pkcs11KeyStoreListContext(this);
1967 }
1968 context = s_keyStoreList;
1969 }
1970 }
1971
1972 QCA_logTextMessage(QString::asprintf("pkcs11Provider::createContext - return context=%p", (void *)context),
1973 Logger::Debug);
1974
1975 return context;
1976 }
1977
startSlotEvents()1978 void pkcs11Provider::startSlotEvents()
1979 {
1980 CK_RV rv;
1981
1982 QCA_logTextMessage(QStringLiteral("pkcs11Provider::startSlotEvents - entry"), Logger::Debug);
1983
1984 if (_lowLevelInitialized) {
1985 if (!_slotEventsLowLevelActive) {
1986 if ((rv = pkcs11h_setSlotEventHook(__slotEventHook, this)) != CKR_OK) {
1987 throw pkcs11Exception(rv, QStringLiteral("Cannot start slot events"));
1988 }
1989
1990 _slotEventsLowLevelActive = true;
1991 }
1992
1993 _slotEventsActive = true;
1994 }
1995
1996 QCA_logTextMessage(QStringLiteral("pkcs11Provider::startSlotEvents - return"), Logger::Debug);
1997 }
1998
stopSlotEvents()1999 void pkcs11Provider::stopSlotEvents()
2000 {
2001 QCA_logTextMessage(QStringLiteral("pkcs11Provider::stopSlotEvents - entry/return"), Logger::Debug);
2002
2003 _slotEventsActive = false;
2004 }
2005
defaultConfig() const2006 QVariantMap pkcs11Provider::defaultConfig() const
2007 {
2008 QVariantMap mytemplate;
2009
2010 QCA_logTextMessage(QStringLiteral("pkcs11Provider::defaultConfig - entry/return"), Logger::Debug);
2011
2012 mytemplate[QStringLiteral("formtype")] = QStringLiteral("http://affinix.com/qca/forms/qca-pkcs11#1.0");
2013 mytemplate[QStringLiteral("allow_load_rootca")] = false;
2014 mytemplate[QStringLiteral("allow_protected_authentication")] = true;
2015 mytemplate[QStringLiteral("pin_cache")] = PKCS11H_PIN_CACHE_INFINITE;
2016 mytemplate[QStringLiteral("log_level")] = 0;
2017 for (int i = 0; i < _CONFIG_MAX_PROVIDERS; i++) {
2018 mytemplate[QString::asprintf("provider_%02d_enabled", i)] = false;
2019 mytemplate[QString::asprintf("provider_%02d_name", i)] = QLatin1String("");
2020 mytemplate[QString::asprintf("provider_%02d_library", i)] = QLatin1String("");
2021 mytemplate[QString::asprintf("provider_%02d_allow_protected_authentication", i)] = true;
2022 mytemplate[QString::asprintf("provider_%02d_cert_private", i)] = false;
2023 mytemplate[QString::asprintf("provider_%02d_private_mask", i)] = PKCS11H_PRIVATEMODE_MASK_AUTO;
2024 mytemplate[QString::asprintf("provider_%02d_slotevent_method", i)] = QStringLiteral("auto");
2025 mytemplate[QString::asprintf("provider_%02d_slotevent_timeout", i)] = 0;
2026 }
2027
2028 return mytemplate;
2029 }
2030
configChanged(const QVariantMap & config)2031 void pkcs11Provider::configChanged(const QVariantMap &config)
2032 {
2033 CK_RV rv = CKR_OK;
2034
2035 QCA_logTextMessage(QStringLiteral("pkcs11Provider::configChanged - entry"), Logger::Debug);
2036
2037 if (!_lowLevelInitialized) {
2038 QCA_logTextMessage(QStringLiteral("PKCS#11: Not initialized"), Logger::Error);
2039 return;
2040 }
2041
2042 _allowLoadRootCA = config[QStringLiteral("allow_load_rootca")].toBool();
2043
2044 pkcs11h_setLogLevel(config[QStringLiteral("log_level")].toInt());
2045 pkcs11h_setProtectedAuthentication(config[QStringLiteral("allow_protected_authentication")].toBool() != false
2046 ? TRUE
2047 : FALSE // krazy:exclude=captruefalse
2048 );
2049 pkcs11h_setPINCachePeriod(config[QStringLiteral("pin_cache")].toInt());
2050
2051 /*
2052 * Remove current providers
2053 */
2054 foreach (QString i, _providers) {
2055 pkcs11h_removeProvider(myPrintable(i));
2056 }
2057 _providers.clear();
2058
2059 /*
2060 * Add new providers
2061 */
2062 for (int i = 0; i < _CONFIG_MAX_PROVIDERS; i++) {
2063 bool enabled = config[QString::asprintf("provider_%02d_enabled", i)].toBool();
2064 QString provider = config[QString::asprintf("provider_%02d_library", i)].toString();
2065 QString name = config[QString::asprintf("provider_%02d_name", i)].toString();
2066 QString qslotevent = config[QString::asprintf("provider_%02d_slotevent_method", i)].toString();
2067 unsigned slotevent = PKCS11H_SLOTEVENT_METHOD_AUTO;
2068 if (qslotevent == QLatin1String("trigger")) {
2069 slotevent = PKCS11H_SLOTEVENT_METHOD_TRIGGER;
2070 } else if (qslotevent == QLatin1String("poll")) {
2071 slotevent = PKCS11H_SLOTEVENT_METHOD_POLL;
2072 }
2073
2074 if (name.isEmpty()) {
2075 name = provider;
2076 }
2077
2078 if (enabled && !provider.isEmpty()) {
2079 QCA_logTextMessage(
2080 QString::asprintf("Loading PKCS#11 provider '%s' (%s)", myPrintable(name), myPrintable(provider)),
2081 Logger::Information);
2082
2083 if ((rv = pkcs11h_addProvider(
2084 myPrintable(name),
2085 myPrintable(provider),
2086 config[QString::asprintf("provider_%02d_allow_protected_authentication", i)].toBool() != false
2087 ? TRUE
2088 : FALSE, // krazy:exclude=captruefalse
2089 (unsigned)config[QString::asprintf("provider_%02d_private_mask", i)].toInt(),
2090 slotevent,
2091 (unsigned)config[QString::asprintf("provider_%02d_slotevent_timeout", i)].toInt(),
2092 config[QString::asprintf("provider_%02d_cert_private", i)].toBool() != false
2093 ? TRUE
2094 : FALSE // krazy:exclude=captruefalse
2095 )) != CKR_OK) {
2096 QCA_logTextMessage(QString::asprintf("PKCS#11: Cannot log provider '%s'-'%s' %lu-'%s'.\n",
2097 myPrintable(name),
2098 myPrintable(provider),
2099 rv,
2100 pkcs11h_getMessage(rv)),
2101 Logger::Error);
2102 appendPluginDiagnosticText(QString::asprintf("Cannot load PKCS#11 provider '%s'\n", myPrintable(name)));
2103 } else {
2104 _providers += provider;
2105 }
2106 }
2107 }
2108
2109 QCA_logTextMessage(QStringLiteral("pkcs11Provider::configChanged - return"), Logger::Debug);
2110 }
2111
__logHook(void * const global_data,const unsigned flags,const char * const format,va_list args)2112 void pkcs11Provider::__logHook(void *const global_data, const unsigned flags, const char *const format, va_list args)
2113 {
2114 pkcs11Provider *me = (pkcs11Provider *)global_data;
2115 me->_logHook(flags, format, args);
2116 }
2117
__slotEventHook(void * const global_data)2118 void pkcs11Provider::__slotEventHook(void *const global_data)
2119 {
2120 pkcs11Provider *me = (pkcs11Provider *)global_data;
2121 me->_slotEventHook();
2122 }
2123
2124 PKCS11H_BOOL
__tokenPromptHook(void * const global_data,void * const user_data,const pkcs11h_token_id_t token,const unsigned retry)2125 pkcs11Provider::__tokenPromptHook(void *const global_data,
2126 void *const user_data,
2127 const pkcs11h_token_id_t token,
2128 const unsigned retry)
2129 {
2130 Q_UNUSED(retry);
2131
2132 pkcs11Provider *me = (pkcs11Provider *)global_data;
2133 return me->_tokenPromptHook(user_data, token);
2134 }
2135
2136 PKCS11H_BOOL
__pinPromptHook(void * const global_data,void * const user_data,const pkcs11h_token_id_t token,const unsigned retry,char * const pin,const size_t pin_max)2137 pkcs11Provider::__pinPromptHook(void *const global_data,
2138 void *const user_data,
2139 const pkcs11h_token_id_t token,
2140 const unsigned retry,
2141 char *const pin,
2142 const size_t pin_max)
2143 {
2144 Q_UNUSED(retry);
2145
2146 pkcs11Provider *me = (pkcs11Provider *)global_data;
2147 return me->_pinPromptHook(user_data, token, pin, pin_max);
2148 }
2149
_logHook(const unsigned flags,const char * const format,va_list args)2150 void pkcs11Provider::_logHook(const unsigned flags, const char *const format, va_list args)
2151 {
2152 Logger::Severity severity;
2153
2154 switch (flags) {
2155 case PKCS11H_LOG_DEBUG2:
2156 case PKCS11H_LOG_DEBUG1:
2157 severity = Logger::Debug;
2158 break;
2159 case PKCS11H_LOG_INFO:
2160 severity = Logger::Information;
2161 break;
2162 case PKCS11H_LOG_WARN:
2163 severity = Logger::Warning;
2164 break;
2165 case PKCS11H_LOG_ERROR:
2166 severity = Logger::Error;
2167 break;
2168 default:
2169 severity = Logger::Debug;
2170 break;
2171 }
2172
2173 //@BEGIN-WORKAROUND
2174 // Qt vsprintf cannot can NULL for %s as vsprintf does.
2175 // QCA_logTextMessage (QString ().vsprintf (format, args), severity);
2176 char buffer[2048];
2177 qvsnprintf(buffer, sizeof(buffer) - 1, format, args);
2178 buffer[sizeof(buffer) - 1] = '\x0';
2179 QCA_logTextMessage(QString::fromLatin1(buffer), severity);
2180 //@END-WORKAROUND
2181 }
2182
_slotEventHook()2183 void pkcs11Provider::_slotEventHook()
2184 {
2185 /*
2186 * This is called from a separate
2187 * thread.
2188 */
2189 if (s_keyStoreList != nullptr && _slotEventsActive) {
2190 QMetaObject::invokeMethod(s_keyStoreList, "doUpdated", Qt::QueuedConnection);
2191 }
2192 }
2193
2194 PKCS11H_BOOL
_tokenPromptHook(void * const user_data,const pkcs11h_token_id_t token)2195 pkcs11Provider::_tokenPromptHook(void *const user_data, const pkcs11h_token_id_t token)
2196 {
2197 if (s_keyStoreList != nullptr) {
2198 return s_keyStoreList->_tokenPrompt(user_data, token) ? TRUE : FALSE; // krazy:exclude=captruefalse
2199 }
2200
2201 return FALSE; // krazy:exclude=captruefalse
2202 }
2203
2204 PKCS11H_BOOL
_pinPromptHook(void * const user_data,const pkcs11h_token_id_t token,char * const pin,const size_t pin_max)2205 pkcs11Provider::_pinPromptHook(void *const user_data,
2206 const pkcs11h_token_id_t token,
2207 char *const pin,
2208 const size_t pin_max)
2209 {
2210 PKCS11H_BOOL ret = FALSE; // krazy:exclude=captruefalse
2211
2212 if (s_keyStoreList != nullptr) {
2213 SecureArray qpin;
2214
2215 if (s_keyStoreList->_pinPrompt(user_data, token, qpin)) {
2216 if ((size_t)qpin.size() < pin_max - 1) {
2217 memmove(pin, qpin.constData(), qpin.size());
2218 pin[qpin.size()] = '\0';
2219 ret = TRUE; // krazy:exclude=captruefalse
2220 }
2221 }
2222 }
2223
2224 return ret; // krazy:exclude=captruefalse
2225 }
2226
2227 class pkcs11Plugin : public QObject, public QCAPlugin
2228 {
2229 Q_OBJECT
2230 Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0")
2231 Q_INTERFACES(QCAPlugin)
2232
2233 public:
createProvider()2234 Provider *createProvider() override
2235 {
2236 return new pkcs11Provider;
2237 }
2238 };
2239
2240 #include "qca-pkcs11.moc"
2241