File indexing completed on 2024-05-19 15:50:35

0001 /*
0002  * Copyright (C) 2004  Justin Karneges  <justin@affinix.com>
0003  * Copyright (C) 2006-2007  Alon Bar-Lev <alon.barlev@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library; if not, write to the Free Software
0017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
0018  *
0019  */
0020 
0021 #include <QtCrypto>
0022 #include <qcaprovider.h>
0023 #include <qplatformdefs.h>
0024 
0025 #include <QHash>
0026 #include <QMutexLocker>
0027 #include <QtPlugin>
0028 
0029 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
0030 #include <pkcs11-helper-1.0/pkcs11h-token.h>
0031 
0032 using namespace QCA;
0033 
0034 // qPrintable is ASCII only!!!
0035 #define myPrintable(s) (s).toUtf8().constData()
0036 
0037 static inline QString certificateHash(const Certificate &cert)
0038 {
0039     if (cert.isNull()) {
0040         return QString();
0041     } else {
0042         return Hash(QStringLiteral("sha1")).hashToString(cert.toDER());
0043     }
0044 }
0045 
0046 //----------------------------------------------------------------------------
0047 // pkcs11Provider
0048 //----------------------------------------------------------------------------
0049 class pkcs11Provider : public Provider
0050 {
0051 private:
0052     static const int _CONFIG_MAX_PROVIDERS;
0053 
0054     bool        _lowLevelInitialized;
0055     bool        _slotEventsActive;
0056     bool        _slotEventsLowLevelActive;
0057     QStringList _providers;
0058 
0059 public:
0060     bool _allowLoadRootCA;
0061 
0062 public:
0063     pkcs11Provider();
0064     ~pkcs11Provider() override;
0065 
0066 public:
0067     int qcaVersion() const override;
0068 
0069     void init() override;
0070 
0071     void deinit() override;
0072 
0073     QString name() const override;
0074 
0075     QStringList features() const override;
0076 
0077     Context *createContext(const QString &type) override;
0078 
0079     void startSlotEvents();
0080 
0081     void stopSlotEvents();
0082 
0083     QVariantMap defaultConfig() const override;
0084 
0085     void configChanged(const QVariantMap &config) override;
0086 
0087 protected:
0088     static void __logHook(void *const global_data, const unsigned flags, const char *const format, va_list args);
0089 
0090     static void __slotEventHook(void *const global_data);
0091 
0092     static PKCS11H_BOOL __tokenPromptHook(void *const              global_data,
0093                                           void *const              user_data,
0094                                           const pkcs11h_token_id_t token,
0095                                           const unsigned           retry);
0096 
0097     static PKCS11H_BOOL __pinPromptHook(void *const              global_data,
0098                                         void *const              user_data,
0099                                         const pkcs11h_token_id_t token,
0100                                         const unsigned           retry,
0101                                         char *const              pin,
0102                                         const size_t             pin_max);
0103 
0104     void _logHook(const unsigned flags, const char *const format, va_list args);
0105 
0106     void _slotEventHook();
0107 
0108     PKCS11H_BOOL
0109     _tokenPromptHook(void *const user_data, const pkcs11h_token_id_t token);
0110 
0111     PKCS11H_BOOL
0112     _pinPromptHook(void *const user_data, const pkcs11h_token_id_t token, char *const pin, const size_t pin_max);
0113 };
0114 
0115 namespace pkcs11QCAPlugin {
0116 
0117 class pkcs11KeyStoreEntryContext;
0118 
0119 //----------------------------------------------------------------------------
0120 // pkcs11KeyStoreListContext
0121 //----------------------------------------------------------------------------
0122 class pkcs11KeyStoreListContext : public KeyStoreListContext
0123 {
0124     Q_OBJECT
0125 
0126 private:
0127     struct pkcs11KeyStoreItem
0128     {
0129     protected:
0130         int                _id;
0131         pkcs11h_token_id_t _token_id;
0132         QList<Certificate> _certs;
0133 
0134     public:
0135         pkcs11KeyStoreItem(const int id, const pkcs11h_token_id_t token_id)
0136         {
0137             _id = id;
0138             ;
0139             pkcs11h_token_duplicateTokenId(&_token_id, token_id);
0140         }
0141 
0142         ~pkcs11KeyStoreItem()
0143         {
0144             if (_token_id != nullptr) {
0145                 pkcs11h_token_freeTokenId(_token_id);
0146             }
0147         }
0148 
0149         pkcs11KeyStoreItem(const pkcs11KeyStoreItem &)            = delete;
0150         pkcs11KeyStoreItem &operator=(const pkcs11KeyStoreItem &) = delete;
0151 
0152         inline int id() const
0153         {
0154             return _id;
0155         }
0156 
0157         inline pkcs11h_token_id_t tokenId() const
0158         {
0159             return _token_id;
0160         }
0161 
0162         void registerCertificates(const QList<Certificate> &certs)
0163         {
0164             foreach (Certificate i, certs) {
0165                 if (std::find(_certs.begin(), _certs.end(), i) == _certs.end()) {
0166                     _certs += i;
0167                 }
0168             }
0169         }
0170 
0171         QMap<QString, QString> friendlyNames()
0172         {
0173             const QStringList      names = makeFriendlyNames(_certs);
0174             QMap<QString, QString> friendlyNames;
0175 
0176             for (int i = 0; i < names.size(); i++) {
0177                 friendlyNames.insert(certificateHash(_certs[i]), names[i]);
0178             }
0179 
0180             return friendlyNames;
0181         }
0182     };
0183     int                                 _last_id;
0184     typedef QList<pkcs11KeyStoreItem *> _stores_t;
0185     _stores_t                           _stores;
0186     QHash<int, pkcs11KeyStoreItem *>    _storesById;
0187     QMutex                              _mutexStores;
0188     bool                                _initialized;
0189 
0190 public:
0191     pkcs11KeyStoreListContext(Provider *p);
0192 
0193     ~pkcs11KeyStoreListContext() override;
0194 
0195     Provider::Context *clone() const override;
0196 
0197 public:
0198     void start() override;
0199 
0200     void setUpdatesEnabled(bool enabled) override;
0201 
0202     KeyStoreEntryContext *entry(int id, const QString &entryId) override;
0203 
0204     KeyStoreEntryContext *entryPassive(const QString &serialized) override;
0205 
0206     KeyStore::Type type(int id) const override;
0207 
0208     QString storeId(int id) const override;
0209 
0210     QString name(int id) const override;
0211 
0212     QList<KeyStoreEntry::Type> entryTypes(int id) const override;
0213 
0214     QList<int> keyStores() override;
0215 
0216     QList<KeyStoreEntryContext *> entryList(int id) override;
0217 
0218     bool _tokenPrompt(void *const user_data, const pkcs11h_token_id_t token_id);
0219 
0220     bool _pinPrompt(void *const user_data, const pkcs11h_token_id_t token_id, SecureArray &pin);
0221 
0222     void _emit_diagnosticText(const QString &t);
0223 
0224 private Q_SLOTS:
0225     void doReady();
0226 
0227     void doUpdated();
0228 
0229 private:
0230     pkcs11KeyStoreItem *_registerTokenId(const pkcs11h_token_id_t token_id);
0231 
0232     void _clearStores();
0233 
0234     pkcs11KeyStoreEntryContext *_keyStoreEntryByCertificateId(const pkcs11h_certificate_id_t certificate_id,
0235                                                               const bool                     has_private,
0236                                                               const CertificateChain        &chain,
0237                                                               const QString                 &description) const;
0238 
0239     QString _tokenId2storeId(const pkcs11h_token_id_t token_id) const;
0240 
0241     QString _serializeCertificate(const pkcs11h_certificate_id_t certificate_id,
0242                                   const CertificateChain        &chain,
0243                                   const bool                     has_private) const;
0244 
0245     void _deserializeCertificate(const QString                  &from,
0246                                  pkcs11h_certificate_id_t *const p_certificate_id,
0247                                  bool *const                     p_has_private,
0248                                  CertificateChain               &chain) const;
0249 
0250     QString _escapeString(const QString &from) const;
0251 
0252     QString _unescapeString(const QString &from) const;
0253 };
0254 
0255 static pkcs11KeyStoreListContext *s_keyStoreList = nullptr;
0256 
0257 //----------------------------------------------------------------------------
0258 // pkcs11Exception
0259 //----------------------------------------------------------------------------
0260 class pkcs11Exception
0261 {
0262 private:
0263     CK_RV   _rv;
0264     QString _msg;
0265 
0266 private:
0267     pkcs11Exception()
0268     {
0269     }
0270 
0271 public:
0272     pkcs11Exception(const CK_RV rv, const QString &msg)
0273     {
0274         _rv  = rv;
0275         _msg = msg;
0276     }
0277 
0278     CK_RV
0279     rv() const
0280     {
0281         return _rv;
0282     }
0283 
0284     QString message() const
0285     {
0286         return _msg + QStringLiteral(" ") + QString::fromLatin1(pkcs11h_getMessage(_rv));
0287     }
0288 };
0289 
0290 //----------------------------------------------------------------------------
0291 // pkcs11RSAContext
0292 //----------------------------------------------------------------------------
0293 class pkcs11RSAContext : public RSAContext
0294 {
0295     Q_OBJECT
0296 
0297 private:
0298     bool                     _has_privateKeyRole;
0299     pkcs11h_certificate_id_t _pkcs11h_certificate_id;
0300     pkcs11h_certificate_t    _pkcs11h_certificate;
0301     RSAPublicKey             _pubkey;
0302     QString                  _serialized;
0303 
0304     struct _sign_data_s
0305     {
0306         SignatureAlgorithm alg;
0307         Hash              *hash;
0308         QByteArray         raw;
0309 
0310         _sign_data_s()
0311         {
0312             hash = nullptr;
0313         }
0314     } _sign_data;
0315 
0316 public:
0317     pkcs11RSAContext(Provider                      *p,
0318                      const pkcs11h_certificate_id_t pkcs11h_certificate_id,
0319                      const QString                 &serialized,
0320                      const RSAPublicKey            &pubkey)
0321         : RSAContext(p)
0322     {
0323         CK_RV rv;
0324 
0325         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContext1 - entry"), Logger::Debug);
0326 
0327         _has_privateKeyRole     = true;
0328         _pkcs11h_certificate_id = nullptr;
0329         _pkcs11h_certificate    = nullptr;
0330         _pubkey                 = pubkey;
0331         _serialized             = serialized;
0332         _clearSign();
0333 
0334         if ((rv = pkcs11h_certificate_duplicateCertificateId(&_pkcs11h_certificate_id, pkcs11h_certificate_id)) !=
0335             CKR_OK) {
0336             throw pkcs11Exception(rv, QStringLiteral("Memory error"));
0337         }
0338 
0339         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContext1 - return"), Logger::Debug);
0340     }
0341 
0342     pkcs11RSAContext(const pkcs11RSAContext &from)
0343         : RSAContext(from.provider())
0344     {
0345         CK_RV rv;
0346 
0347         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContextC - entry"), Logger::Debug);
0348 
0349         _has_privateKeyRole     = from._has_privateKeyRole;
0350         _pkcs11h_certificate_id = nullptr;
0351         _pkcs11h_certificate    = nullptr;
0352         _pubkey                 = from._pubkey;
0353         _serialized             = from._serialized;
0354         _sign_data.hash         = nullptr;
0355         _clearSign();
0356 
0357         if ((rv = pkcs11h_certificate_duplicateCertificateId(&_pkcs11h_certificate_id, from._pkcs11h_certificate_id)) !=
0358             CKR_OK) {
0359             throw pkcs11Exception(rv, QStringLiteral("Memory error"));
0360         }
0361 
0362         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::pkcs11RSAContextC - return"), Logger::Debug);
0363     }
0364 
0365     ~pkcs11RSAContext() override
0366     {
0367         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::~pkcs11RSAContext - entry"), Logger::Debug);
0368 
0369         _clearSign();
0370 
0371         if (_pkcs11h_certificate != nullptr) {
0372             pkcs11h_certificate_freeCertificate(_pkcs11h_certificate);
0373             _pkcs11h_certificate = nullptr;
0374         }
0375 
0376         if (_pkcs11h_certificate_id != nullptr) {
0377             pkcs11h_certificate_freeCertificateId(_pkcs11h_certificate_id);
0378             _pkcs11h_certificate_id = nullptr;
0379         }
0380 
0381         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::~pkcs11RSAContext - return"), Logger::Debug);
0382     }
0383 
0384     Provider::Context *clone() const override
0385     {
0386         return new pkcs11RSAContext(*this);
0387     }
0388 
0389 public:
0390     bool isNull() const override
0391     {
0392         return _pubkey.isNull();
0393     }
0394 
0395     PKey::Type type() const override
0396     {
0397         return _pubkey.type();
0398     }
0399 
0400     bool isPrivate() const override
0401     {
0402         return _has_privateKeyRole;
0403     }
0404 
0405     bool canExport() const override
0406     {
0407         return !_has_privateKeyRole;
0408     }
0409 
0410     void convertToPublic() override
0411     {
0412         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::convertToPublic - entry"), Logger::Debug);
0413 
0414         if (_has_privateKeyRole) {
0415             if (_pkcs11h_certificate != nullptr) {
0416                 pkcs11h_certificate_freeCertificate(_pkcs11h_certificate);
0417                 _pkcs11h_certificate = nullptr;
0418             }
0419             _has_privateKeyRole = false;
0420         }
0421 
0422         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::convertToPublic - return"), Logger::Debug);
0423     }
0424 
0425     int bits() const override
0426     {
0427         return _pubkey.bitSize();
0428     }
0429 
0430     int maximumEncryptSize(EncryptionAlgorithm alg) const override
0431     {
0432         return _pubkey.maximumEncryptSize(alg);
0433     }
0434 
0435     SecureArray encrypt(const SecureArray &in, EncryptionAlgorithm alg) override
0436     {
0437         return _pubkey.encrypt(in, alg);
0438     }
0439 
0440     bool decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg) override
0441     {
0442         bool session_locked = false;
0443         bool ret            = false;
0444 
0445         QCA_logTextMessage(
0446             QString::asprintf("pkcs11RSAContext::decrypt - decrypt in.size()=%d, alg=%d", in.size(), (int)alg),
0447             Logger::Debug);
0448 
0449         try {
0450             CK_MECHANISM_TYPE mech;
0451             CK_RV             rv;
0452             size_t            my_size;
0453 
0454             switch (alg) {
0455             case EME_PKCS1v15:
0456                 mech = CKM_RSA_PKCS;
0457                 break;
0458             case EME_PKCS1_OAEP:
0459                 mech = CKM_RSA_PKCS_OAEP;
0460                 break;
0461             default:
0462                 throw pkcs11Exception(CKR_FUNCTION_NOT_SUPPORTED, QStringLiteral("Invalid algorithm"));
0463                 break;
0464             }
0465 
0466             _ensureCertificate();
0467 
0468             if ((rv = pkcs11h_certificate_lockSession(_pkcs11h_certificate)) != CKR_OK) {
0469                 throw pkcs11Exception(rv, QStringLiteral("Cannot lock session"));
0470             }
0471             session_locked = true;
0472 
0473             if ((rv = pkcs11h_certificate_decryptAny(_pkcs11h_certificate,
0474                                                      mech,
0475                                                      (const unsigned char *)in.constData(),
0476                                                      in.size(),
0477                                                      nullptr,
0478                                                      &my_size)) != CKR_OK) {
0479                 throw pkcs11Exception(rv, QStringLiteral("Decryption error"));
0480             }
0481 
0482             out->resize(my_size);
0483 
0484             if ((rv = pkcs11h_certificate_decryptAny(_pkcs11h_certificate,
0485                                                      mech,
0486                                                      (const unsigned char *)in.constData(),
0487                                                      in.size(),
0488                                                      (unsigned char *)out->data(),
0489                                                      &my_size)) != CKR_OK) {
0490                 throw pkcs11Exception(rv, QStringLiteral("Decryption error"));
0491             }
0492 
0493             rv = out->resize(my_size);
0494 
0495             if ((rv = pkcs11h_certificate_releaseSession(_pkcs11h_certificate)) != CKR_OK) {
0496                 throw pkcs11Exception(rv, QStringLiteral("Cannot release session"));
0497             }
0498             session_locked = false;
0499 
0500             ret = true;
0501         } catch (const pkcs11Exception &e) {
0502             if (session_locked) {
0503                 pkcs11h_certificate_releaseSession(_pkcs11h_certificate);
0504                 session_locked = false;
0505             }
0506 
0507             if (s_keyStoreList != nullptr) {
0508                 s_keyStoreList->_emit_diagnosticText(
0509                     QString::asprintf("PKCS#11: Cannot decrypt: %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
0510             }
0511         }
0512 
0513         QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::decrypt - decrypt out->size()=%d", out->size()),
0514                            Logger::Debug);
0515 
0516         return ret;
0517     }
0518 
0519     void startSign(SignatureAlgorithm alg, SignatureFormat) override
0520     {
0521         _clearSign();
0522 
0523         _sign_data.alg = alg;
0524 
0525         switch (_sign_data.alg) {
0526         case EMSA3_SHA1:
0527             _sign_data.hash = new Hash(QStringLiteral("sha1"));
0528             break;
0529         case EMSA3_MD5:
0530             _sign_data.hash = new Hash(QStringLiteral("md5"));
0531             break;
0532         case EMSA3_MD2:
0533             _sign_data.hash = new Hash(QStringLiteral("md2"));
0534             break;
0535         case EMSA3_Raw:
0536             break;
0537         case SignatureUnknown:
0538         case EMSA1_SHA1:
0539         case EMSA3_RIPEMD160:
0540         default:
0541             QCA_logTextMessage(QString::asprintf("PKCS#11: Invalid hash algorithm %d", _sign_data.alg),
0542                                Logger::Warning);
0543             break;
0544         }
0545     }
0546 
0547     void startVerify(SignatureAlgorithm alg, SignatureFormat sf) override
0548     {
0549         _pubkey.startVerify(alg, sf);
0550     }
0551 
0552     void update(const MemoryRegion &in) override
0553     {
0554         if (_has_privateKeyRole) {
0555             if (_sign_data.hash != nullptr) {
0556                 _sign_data.hash->update(in);
0557             } else {
0558                 _sign_data.raw.append(in.toByteArray());
0559             }
0560         } else {
0561             _pubkey.update(in);
0562         }
0563     }
0564 
0565     QByteArray endSign() override
0566     {
0567         QByteArray result;
0568         bool       session_locked = false;
0569 
0570         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::endSign - entry"), Logger::Debug);
0571 
0572         try {
0573             QByteArray final;
0574             CK_RV      rv;
0575 
0576             // from some strange reason I got 2047... (for some)    <---- BUG?!?!?!
0577             int myrsa_size = (_pubkey.bitSize() + 7) / 8;
0578 
0579             if (_sign_data.hash != nullptr) {
0580                 final = emsa3Encode(_sign_data.hash->type(), _sign_data.hash->final().toByteArray(), myrsa_size);
0581             } else {
0582                 final = _sign_data.raw;
0583             }
0584 
0585             if (final.size() == 0) {
0586                 throw pkcs11Exception(CKR_FUNCTION_FAILED, QStringLiteral("Cannot encode signature"));
0587             }
0588 
0589             _ensureCertificate();
0590 
0591             size_t my_size;
0592 
0593             if ((rv = pkcs11h_certificate_lockSession(_pkcs11h_certificate)) != CKR_OK) {
0594                 throw pkcs11Exception(rv, QStringLiteral("Cannot lock session"));
0595             }
0596             session_locked = true;
0597 
0598             if ((rv = pkcs11h_certificate_signAny(_pkcs11h_certificate,
0599                                                   CKM_RSA_PKCS,
0600                                                   (const unsigned char *) final.constData(),
0601                                                   (size_t) final.size(),
0602                                                   nullptr,
0603                                                   &my_size)) != CKR_OK) {
0604                 throw pkcs11Exception(rv, QStringLiteral("Signature failed"));
0605             }
0606 
0607             result.resize(my_size);
0608 
0609             if ((rv = pkcs11h_certificate_signAny(_pkcs11h_certificate,
0610                                                   CKM_RSA_PKCS,
0611                                                   (const unsigned char *) final.constData(),
0612                                                   (size_t) final.size(),
0613                                                   (unsigned char *)result.data(),
0614                                                   &my_size)) != CKR_OK) {
0615                 throw pkcs11Exception(rv, QStringLiteral("Signature failed"));
0616             }
0617 
0618             result.resize(my_size);
0619 
0620             if ((rv = pkcs11h_certificate_releaseSession(_pkcs11h_certificate)) != CKR_OK) {
0621                 throw pkcs11Exception(rv, QStringLiteral("Cannot release session"));
0622             }
0623             session_locked = false;
0624 
0625         } catch (const pkcs11Exception &e) {
0626             result.clear();
0627 
0628             if (session_locked) {
0629                 pkcs11h_certificate_releaseSession(_pkcs11h_certificate);
0630                 session_locked = false;
0631             }
0632 
0633             if (s_keyStoreList != nullptr) {
0634                 s_keyStoreList->_emit_diagnosticText(
0635                     QString::asprintf("PKCS#11: Cannot sign: %lu-'%s'.\n", e.rv(), myPrintable(e.message())));
0636             }
0637         }
0638 
0639         _clearSign();
0640 
0641         QCA_logTextMessage(
0642             QString::asprintf("pkcs11RSAContext::endSign - return result.size ()=%d", int(result.size())),
0643             Logger::Debug);
0644 
0645         return result;
0646     }
0647 
0648     virtual bool validSignature(const QByteArray &sig)
0649     {
0650         return _pubkey.validSignature(sig);
0651     }
0652 
0653     void createPrivate(int bits, int exp, bool block) override
0654     {
0655         Q_UNUSED(bits);
0656         Q_UNUSED(exp);
0657         Q_UNUSED(block);
0658     }
0659 
0660     void createPrivate(const BigInteger &n,
0661                        const BigInteger &e,
0662                        const BigInteger &p,
0663                        const BigInteger &q,
0664                        const BigInteger &d) override
0665     {
0666         Q_UNUSED(n);
0667         Q_UNUSED(e);
0668         Q_UNUSED(p);
0669         Q_UNUSED(q);
0670         Q_UNUSED(d);
0671     }
0672 
0673     void createPublic(const BigInteger &n, const BigInteger &e) override
0674     {
0675         Q_UNUSED(n);
0676         Q_UNUSED(e);
0677     }
0678 
0679     BigInteger n() const override
0680     {
0681         return _pubkey.n();
0682     }
0683 
0684     BigInteger e() const override
0685     {
0686         return _pubkey.e();
0687     }
0688 
0689     BigInteger p() const override
0690     {
0691         return BigInteger();
0692     }
0693 
0694     BigInteger q() const override
0695     {
0696         return BigInteger();
0697     }
0698 
0699     BigInteger d() const override
0700     {
0701         return BigInteger();
0702     }
0703 
0704 public:
0705     PublicKey _publicKey() const
0706     {
0707         return _pubkey;
0708     }
0709 
0710     bool _isTokenAvailable() const
0711     {
0712         bool ret;
0713 
0714         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureTokenAvailable - entry"), Logger::Debug);
0715 
0716         ret = pkcs11h_token_ensureAccess(_pkcs11h_certificate_id->token_id, nullptr, 0) == CKR_OK;
0717 
0718         QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::_ensureTokenAvailable - return ret=%d", ret ? 1 : 0),
0719                            Logger::Debug);
0720 
0721         return ret;
0722     }
0723 
0724     bool _ensureTokenAccess()
0725     {
0726         bool ret;
0727 
0728         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureTokenAccess - entry"), Logger::Debug);
0729 
0730         ret = pkcs11h_token_ensureAccess(_pkcs11h_certificate_id->token_id, nullptr, PKCS11H_PROMPT_MASK_ALLOW_ALL) ==
0731             CKR_OK;
0732 
0733         QCA_logTextMessage(QString::asprintf("pkcs11RSAContext::_ensureTokenAccess - return ret=%d", ret ? 1 : 0),
0734                            Logger::Debug);
0735 
0736         return ret;
0737     }
0738 
0739 private:
0740     void _clearSign()
0741     {
0742         _sign_data.raw.clear();
0743         _sign_data.alg = SignatureUnknown;
0744         delete _sign_data.hash;
0745         _sign_data.hash = nullptr;
0746     }
0747 
0748     void _ensureCertificate()
0749     {
0750         CK_RV rv;
0751 
0752         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureCertificate - entry"), Logger::Debug);
0753 
0754         if (_pkcs11h_certificate == nullptr) {
0755             if ((rv = pkcs11h_certificate_create(_pkcs11h_certificate_id,
0756                                                  &_serialized,
0757                                                  PKCS11H_PROMPT_MASK_ALLOW_ALL,
0758                                                  PKCS11H_PIN_CACHE_INFINITE,
0759                                                  &_pkcs11h_certificate)) != CKR_OK) {
0760                 throw pkcs11Exception(rv, QStringLiteral("Cannot create low-level certificate"));
0761             }
0762         }
0763 
0764         QCA_logTextMessage(QStringLiteral("pkcs11RSAContext::_ensureCertificate - return"), Logger::Debug);
0765     }
0766 };
0767 
0768 //----------------------------------------------------------------------------
0769 // pkcs11PKeyContext
0770 //----------------------------------------------------------------------------
0771 class pkcs11PKeyContext : public PKeyContext
0772 {
0773     Q_OBJECT
0774 
0775 private:
0776     PKeyBase *_k;
0777 
0778 public:
0779     pkcs11PKeyContext(Provider *p)
0780         : PKeyContext(p)
0781     {
0782         _k = nullptr;
0783     }
0784 
0785     ~pkcs11PKeyContext() override
0786     {
0787         delete _k;
0788         _k = nullptr;
0789     }
0790 
0791     Provider::Context *clone() const override
0792     {
0793         pkcs11PKeyContext *c = new pkcs11PKeyContext(*this);
0794         c->_k                = (PKeyBase *)_k->clone();
0795         return c;
0796     }
0797 
0798 public:
0799     QList<PKey::Type> supportedTypes() const override
0800     {
0801         QList<PKey::Type> list;
0802         list += PKey::RSA;
0803         return list;
0804     }
0805 
0806     QList<PKey::Type> supportedIOTypes() const override
0807     {
0808         QList<PKey::Type> list;
0809         list += PKey::RSA;
0810         return list;
0811     }
0812 
0813     QList<PBEAlgorithm> supportedPBEAlgorithms() const override
0814     {
0815         QList<PBEAlgorithm> list;
0816         return list;
0817     }
0818 
0819     PKeyBase *key() override
0820     {
0821         return _k;
0822     }
0823 
0824     const PKeyBase *key() const override
0825     {
0826         return _k;
0827     }
0828 
0829     void setKey(PKeyBase *key) override
0830     {
0831         delete _k;
0832         _k = key;
0833     }
0834 
0835     bool importKey(const PKeyBase *key) override
0836     {
0837         Q_UNUSED(key);
0838         return false;
0839     }
0840 
0841     static int passphrase_cb(char *buf, int size, int rwflag, void *u)
0842     {
0843         Q_UNUSED(buf);
0844         Q_UNUSED(size);
0845         Q_UNUSED(rwflag);
0846         Q_UNUSED(u);
0847         return 0;
0848     }
0849 
0850     QByteArray publicToDER() const override
0851     {
0852         return static_cast<pkcs11RSAContext *>(_k)->_publicKey().toDER();
0853     }
0854 
0855     QString publicToPEM() const override
0856     {
0857         return static_cast<pkcs11RSAContext *>(_k)->_publicKey().toPEM();
0858     }
0859 
0860     ConvertResult publicFromDER(const QByteArray &in) override
0861     {
0862         Q_UNUSED(in);
0863         return ErrorDecode;
0864     }
0865 
0866     ConvertResult publicFromPEM(const QString &s) override
0867     {
0868         Q_UNUSED(s);
0869         return ErrorDecode;
0870     }
0871 
0872     SecureArray privateToDER(const SecureArray &passphrase, PBEAlgorithm pbe) const override
0873     {
0874         Q_UNUSED(passphrase);
0875         Q_UNUSED(pbe);
0876         return SecureArray();
0877     }
0878 
0879     QString privateToPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const override
0880     {
0881         Q_UNUSED(passphrase);
0882         Q_UNUSED(pbe);
0883         return QString();
0884     }
0885 
0886     ConvertResult privateFromDER(const SecureArray &in, const SecureArray &passphrase) override
0887     {
0888         Q_UNUSED(in);
0889         Q_UNUSED(passphrase);
0890         return ErrorDecode;
0891     }
0892 
0893     ConvertResult privateFromPEM(const QString &s, const SecureArray &passphrase) override
0894     {
0895         Q_UNUSED(s);
0896         Q_UNUSED(passphrase);
0897         return ErrorDecode;
0898     }
0899 };
0900 
0901 //----------------------------------------------------------------------------
0902 // pkcs11KeyStoreEntryContext
0903 //----------------------------------------------------------------------------
0904 class pkcs11KeyStoreEntryContext : public KeyStoreEntryContext
0905 {
0906     Q_OBJECT
0907 private:
0908     KeyStoreEntry::Type _item_type;
0909     KeyBundle           _key;
0910     Certificate         _cert;
0911     QString             _storeId;
0912     QString             _id;
0913     QString             _serialized;
0914     QString             _storeName;
0915     QString             _name;
0916 
0917 public:
0918     pkcs11KeyStoreEntryContext(const Certificate &cert,
0919                                const QString     &storeId,
0920                                const QString     &serialized,
0921                                const QString     &storeName,
0922                                const QString     &name,
0923                                Provider          *p)
0924         : KeyStoreEntryContext(p)
0925     {
0926         _item_type  = KeyStoreEntry::TypeCertificate;
0927         _cert       = cert;
0928         _storeId    = storeId;
0929         _id         = certificateHash(_cert);
0930         _serialized = serialized;
0931         _storeName  = storeName;
0932         _name       = name;
0933     }
0934 
0935     pkcs11KeyStoreEntryContext(const KeyBundle &key,
0936                                const QString   &storeId,
0937                                const QString   &serialized,
0938                                const QString   &storeName,
0939                                const QString   &name,
0940                                Provider        *p)
0941         : KeyStoreEntryContext(p)
0942     {
0943         _item_type = KeyStoreEntry::TypeKeyBundle;
0944         _key       = key;
0945         _storeId = storeId, _id = certificateHash(key.certificateChain().primary());
0946         _serialized = serialized;
0947         _storeName  = storeName;
0948         _name       = name;
0949     }
0950 
0951     pkcs11KeyStoreEntryContext(const pkcs11KeyStoreEntryContext &from)
0952         : KeyStoreEntryContext(from)
0953     {
0954         _item_type  = from._item_type;
0955         _key        = from._key;
0956         _storeId    = from._storeId;
0957         _id         = from._id;
0958         _serialized = from._serialized;
0959         _storeName  = from._storeName;
0960         _name       = from._name;
0961     }
0962 
0963     Provider::Context *clone() const override
0964     {
0965         return new pkcs11KeyStoreEntryContext(*this);
0966     }
0967 
0968 public:
0969     KeyStoreEntry::Type type() const override
0970     {
0971         return _item_type;
0972     }
0973 
0974     QString name() const override
0975     {
0976         return _name;
0977     }
0978 
0979     QString id() const override
0980     {
0981         return _id;
0982     }
0983 
0984     KeyBundle keyBundle() const override
0985     {
0986         return _key;
0987     }
0988 
0989     Certificate certificate() const override
0990     {
0991         return _cert;
0992     }
0993 
0994     QString storeId() const override
0995     {
0996         return _storeId;
0997     }
0998 
0999     QString storeName() const override
1000     {
1001         return _storeName;
1002     }
1003 
1004     bool isAvailable() const override
1005     {
1006         return static_cast<pkcs11RSAContext *>(static_cast<PKeyContext *>(_key.privateKey().context())->key())
1007             ->_isTokenAvailable();
1008     }
1009 
1010     bool ensureAccess() override
1011     {
1012         return static_cast<pkcs11RSAContext *>(static_cast<PKeyContext *>(_key.privateKey().context())->key())
1013             ->_ensureTokenAccess();
1014     }
1015 
1016     QString serialize() const override
1017     {
1018         return _serialized;
1019     }
1020 };
1021 
1022 //----------------------------------------------------------------------------
1023 // pkcs11QCACrypto
1024 //----------------------------------------------------------------------------
1025 class pkcs11QCACrypto
1026 {
1027 private:
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 
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 
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 
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 
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 //----------------------------------------------------------------------------
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 
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 
1127 Provider::Context *pkcs11KeyStoreListContext::clone() const
1128 {
1129     QCA_logTextMessage(QStringLiteral("pkcs11KeyStoreListContext::clone - entry/return"), Logger::Debug);
1130     return nullptr;
1131 }
1132 
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 
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 
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 
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 
1213 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 
1222 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 
1238 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 
1254 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 
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 
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 
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 
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 
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 
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 
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 *
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 
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 *
1596 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 
1656 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 
1687 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 
1731 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 
1814 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 
1829 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 //----------------------------------------------------------------------------
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 
1872 pkcs11Provider::~pkcs11Provider()
1873 {
1874     QCA_logTextMessage(QStringLiteral("pkcs11Provider::~pkcs11Provider - entry/return"), Logger::Debug);
1875 }
1876 
1877 int pkcs11Provider::qcaVersion() const
1878 {
1879     QCA_logTextMessage(QStringLiteral("pkcs11Provider::qcaVersion - entry/return"), Logger::Debug);
1880 
1881     return QCA_VERSION;
1882 }
1883 
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 
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 
1938 QString pkcs11Provider::name() const
1939 {
1940     QCA_logTextMessage(QStringLiteral("pkcs11Provider::name - entry/return"), Logger::Debug);
1941 
1942     return QStringLiteral("qca-pkcs11");
1943 }
1944 
1945 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 
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 
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 
1999 void pkcs11Provider::stopSlotEvents()
2000 {
2001     QCA_logTextMessage(QStringLiteral("pkcs11Provider::stopSlotEvents - entry/return"), Logger::Debug);
2002 
2003     _slotEventsActive = false;
2004 }
2005 
2006 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 
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 
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 
2118 void pkcs11Provider::__slotEventHook(void *const global_data)
2119 {
2120     pkcs11Provider *me = (pkcs11Provider *)global_data;
2121     me->_slotEventHook();
2122 }
2123 
2124 PKCS11H_BOOL
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
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 
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 
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
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
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:
2234     Provider *createProvider() override
2235     {
2236         return new pkcs11Provider;
2237     }
2238 };
2239 
2240 #include "qca-pkcs11.moc"