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