File indexing completed on 2024-04-28 04:43:50
0001 /* 0002 * Copyright (C) 2007 Alon Bar-Lev <alon.barlev@gmail.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public 0015 * License along with this library; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 0017 * 0018 */ 0019 0020 #include <QFile> 0021 #include <QHash> 0022 #include <QtCrypto> 0023 #include <QtPlugin> 0024 0025 using namespace QCA; 0026 0027 // qPrintable is ASCII only!!! 0028 #define myPrintable(s) (s).toUtf8().constData() 0029 0030 namespace softstoreQCAPlugin { 0031 0032 class softstoreKeyStoreListContext; 0033 static softstoreKeyStoreListContext *s_keyStoreList = nullptr; 0034 0035 enum KeyType 0036 { 0037 keyTypeInvalid, 0038 keyTypePKCS12, 0039 keyTypePKCS8Inline, 0040 keyTypePKCS8FilePEM, 0041 keyTypePKCS8FileDER 0042 }; 0043 0044 enum PublicType 0045 { 0046 publicTypeInvalid, 0047 publicTypeX509Chain 0048 }; 0049 0050 struct SoftStoreEntry 0051 { 0052 QString name; 0053 CertificateChain chain; 0054 KeyType keyReferenceType; 0055 QString keyReference; 0056 bool noPassphrase; 0057 int unlockTimeout; 0058 }; 0059 0060 class softstorePKeyBase : public PKeyBase 0061 { 0062 Q_OBJECT 0063 0064 private: 0065 bool _has_privateKeyRole; 0066 SoftStoreEntry _entry; 0067 QString _serialized; 0068 PrivateKey _privkey; 0069 PrivateKey _privkeySign; 0070 PublicKey _pubkey; 0071 QDateTime dueTime; 0072 0073 public: 0074 static inline QString typeToString(PKey::Type t) 0075 { 0076 switch (t) { 0077 case PKey::RSA: 0078 return QStringLiteral("rsa"); 0079 case PKey::DSA: 0080 return QStringLiteral("dsa"); 0081 case PKey::DH: 0082 return QStringLiteral("dh"); 0083 default: 0084 return QLatin1String(""); 0085 } 0086 } 0087 0088 softstorePKeyBase(const SoftStoreEntry &entry, const QString &serialized, Provider *p) 0089 : PKeyBase(p, QStringLiteral("rsa") /*typeToString (entry.chain.primary ().subjectPublicKey ().type ())*/) 0090 { 0091 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::softstorePKeyBase1 - entry"), Logger::Debug); 0092 0093 _has_privateKeyRole = true; 0094 _entry = entry; 0095 _serialized = serialized; 0096 _pubkey = _entry.chain.primary().subjectPublicKey(); 0097 0098 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::softstorePKeyBase1 - return"), Logger::Debug); 0099 } 0100 0101 softstorePKeyBase(const softstorePKeyBase &from) 0102 : PKeyBase(from.provider(), QStringLiteral("rsa") /*typeToString (from._pubkey.type ())*/) 0103 { 0104 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::softstorePKeyBaseC - entry"), Logger::Debug); 0105 0106 _has_privateKeyRole = from._has_privateKeyRole; 0107 _entry = from._entry; 0108 _serialized = from._serialized; 0109 _pubkey = from._pubkey; 0110 _privkey = from._privkey; 0111 0112 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::softstorePKeyBaseC - return"), Logger::Debug); 0113 } 0114 0115 ~softstorePKeyBase() override 0116 { 0117 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::~softstorePKeyBase - entry"), Logger::Debug); 0118 0119 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::~softstorePKeyBase - return"), Logger::Debug); 0120 } 0121 0122 Provider::Context *clone() const override 0123 { 0124 return new softstorePKeyBase(*this); 0125 } 0126 0127 public: 0128 bool isNull() const override 0129 { 0130 return _pubkey.isNull(); 0131 } 0132 0133 PKey::Type type() const override 0134 { 0135 return _pubkey.type(); 0136 } 0137 0138 bool isPrivate() const override 0139 { 0140 return _has_privateKeyRole; 0141 } 0142 0143 bool canExport() const override 0144 { 0145 return !_has_privateKeyRole; 0146 } 0147 0148 void convertToPublic() override 0149 { 0150 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::convertToPublic - entry"), Logger::Debug); 0151 0152 if (_has_privateKeyRole) { 0153 _has_privateKeyRole = false; 0154 } 0155 0156 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::convertToPublic - return"), Logger::Debug); 0157 } 0158 0159 int bits() const override 0160 { 0161 return _pubkey.bitSize(); 0162 } 0163 0164 int maximumEncryptSize(EncryptionAlgorithm alg) const override 0165 { 0166 return _pubkey.maximumEncryptSize(alg); 0167 } 0168 0169 SecureArray encrypt(const SecureArray &in, EncryptionAlgorithm alg) override 0170 { 0171 return _pubkey.encrypt(in, alg); 0172 } 0173 0174 bool decrypt(const SecureArray &in, SecureArray *out, EncryptionAlgorithm alg) override 0175 { 0176 if (_ensureAccess()) { 0177 return _privkey.decrypt(in, out, alg); 0178 } else { 0179 return false; 0180 } 0181 } 0182 0183 void startSign(SignatureAlgorithm alg, SignatureFormat format) override 0184 { 0185 if (_ensureAccess()) { 0186 /* 0187 * We must use one object thought 0188 * signing, so it won't expire by 0189 * it-self or during passphrase. 0190 */ 0191 _privkeySign = _privkey; 0192 _privkeySign.startSign(alg, format); 0193 } 0194 } 0195 0196 void startVerify(SignatureAlgorithm alg, SignatureFormat sf) override 0197 { 0198 _pubkey.startVerify(alg, sf); 0199 } 0200 0201 void update(const MemoryRegion &in) override 0202 { 0203 if (_has_privateKeyRole) { 0204 _privkeySign.update(in); 0205 } else { 0206 _pubkey.update(in); 0207 } 0208 } 0209 0210 QByteArray endSign() override 0211 { 0212 const QByteArray r = _privkeySign.signature(); 0213 _privkeySign = PrivateKey(); 0214 return r; 0215 } 0216 0217 virtual bool validSignature(const QByteArray &sig) 0218 { 0219 return _pubkey.validSignature(sig); 0220 } 0221 0222 virtual void createPrivate(int bits, int exp, bool block) 0223 { 0224 Q_UNUSED(bits); 0225 Q_UNUSED(exp); 0226 Q_UNUSED(block); 0227 } 0228 0229 virtual void createPrivate(const BigInteger &n, 0230 const BigInteger &e, 0231 const BigInteger &p, 0232 const BigInteger &q, 0233 const BigInteger &d) 0234 { 0235 Q_UNUSED(n); 0236 Q_UNUSED(e); 0237 Q_UNUSED(p); 0238 Q_UNUSED(q); 0239 Q_UNUSED(d); 0240 } 0241 0242 virtual void createPublic(const BigInteger &n, const BigInteger &e) 0243 { 0244 Q_UNUSED(n); 0245 Q_UNUSED(e); 0246 } 0247 0248 public: 0249 PublicKey _publicKey() const 0250 { 0251 return _pubkey; 0252 } 0253 0254 bool _ensureAccess() 0255 { 0256 bool ret = false; 0257 0258 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::_ensureAccess - entry"), Logger::Debug); 0259 0260 if (_entry.unlockTimeout != -1) { 0261 if (dueTime >= QDateTime::currentDateTime()) { 0262 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::_ensureAccess - dueTime reached, clearing"), 0263 Logger::Debug); 0264 _privkey = PrivateKey(); 0265 } 0266 } 0267 0268 if (!_privkey.isNull()) { 0269 ret = true; 0270 } else { 0271 KeyStoreEntry entry; 0272 KeyStoreEntryContext *context = nullptr; 0273 QString storeId, storeName; 0274 ConvertResult cresult; 0275 0276 QCA_logTextMessage(QStringLiteral("softstorePKeyBase::_ensureAccess - no current key, creating"), 0277 Logger::Debug); 0278 0279 // too lazy to create scope 0280 context = reinterpret_cast<KeyStoreListContext *>(s_keyStoreList)->entryPassive(_serialized); 0281 if (context != nullptr) { 0282 storeId = context->storeId(); 0283 storeName = context->storeName(); 0284 entry.change(context); 0285 } 0286 0287 while (!ret) { 0288 SecureArray passphrase; 0289 0290 switch (_entry.keyReferenceType) { 0291 case keyTypeInvalid: 0292 case keyTypePKCS8Inline: 0293 break; 0294 case keyTypePKCS12: 0295 case keyTypePKCS8FilePEM: 0296 case keyTypePKCS8FileDER: 0297 { 0298 QFile file(_entry.keyReference); 0299 while (!file.open(QIODevice::ReadOnly)) { 0300 TokenAsker asker; 0301 asker.ask(KeyStoreInfo(KeyStore::SmartCard, storeId, storeName), entry, context); 0302 asker.waitForResponse(); 0303 if (!asker.accepted()) { 0304 goto cleanup1; 0305 } 0306 } 0307 } break; 0308 } 0309 0310 if (!_entry.noPassphrase) { 0311 PasswordAsker asker; 0312 asker.ask(Event::StylePassphrase, KeyStoreInfo(KeyStore::User, storeId, storeName), entry, context); 0313 asker.waitForResponse(); 0314 passphrase = asker.password(); 0315 if (!asker.accepted()) { 0316 goto cleanup1; 0317 } 0318 } 0319 0320 switch (_entry.keyReferenceType) { 0321 case keyTypeInvalid: 0322 break; 0323 case keyTypePKCS12: 0324 { 0325 KeyBundle bundle = KeyBundle::fromFile(_entry.keyReference, passphrase, &cresult); 0326 if (cresult == ConvertGood) { 0327 _privkey = bundle.privateKey(); 0328 ret = true; 0329 } 0330 } break; 0331 case keyTypePKCS8Inline: 0332 { 0333 PrivateKey k = 0334 PrivateKey::fromDER(Base64().stringToArray(_entry.keyReference), passphrase, &cresult); 0335 if (cresult == ConvertGood) { 0336 _privkey = k; 0337 ret = true; 0338 } 0339 } break; 0340 case keyTypePKCS8FilePEM: 0341 { 0342 PrivateKey k = PrivateKey::fromPEMFile(_entry.keyReference, passphrase, &cresult); 0343 if (cresult == ConvertGood) { 0344 _privkey = k; 0345 ret = true; 0346 } 0347 } break; 0348 case keyTypePKCS8FileDER: 0349 { 0350 QFile file(_entry.keyReference); 0351 if (file.open(QIODevice::ReadOnly)) { 0352 const QByteArray contents = file.readAll(); 0353 0354 PrivateKey k = PrivateKey::fromDER(contents, passphrase, &cresult); 0355 if (cresult == ConvertGood) { 0356 _privkey = k; 0357 ret = true; 0358 } 0359 } 0360 } break; 0361 } 0362 } 0363 0364 if (_entry.unlockTimeout != -1) { 0365 dueTime = QDateTime::currentDateTime().addSecs(_entry.unlockTimeout); 0366 } 0367 0368 cleanup1:; 0369 } 0370 0371 QCA_logTextMessage(QString::asprintf("softstorePKeyBase::_ensureAccess - return ret=%d", ret ? 1 : 0), 0372 Logger::Debug); 0373 0374 return ret; 0375 } 0376 }; 0377 0378 class softstorePKeyContext : public PKeyContext 0379 { 0380 Q_OBJECT 0381 0382 private: 0383 PKeyBase *_k; 0384 0385 public: 0386 softstorePKeyContext(Provider *p) 0387 : PKeyContext(p) 0388 { 0389 _k = nullptr; 0390 } 0391 0392 ~softstorePKeyContext() override 0393 { 0394 delete _k; 0395 _k = nullptr; 0396 } 0397 0398 Provider::Context *clone() const override 0399 { 0400 softstorePKeyContext *c = new softstorePKeyContext(*this); 0401 c->_k = (PKeyBase *)_k->clone(); 0402 return c; 0403 } 0404 0405 public: 0406 QList<PKey::Type> supportedTypes() const override 0407 { 0408 QList<PKey::Type> list; 0409 list += static_cast<softstorePKeyBase *>(_k)->_publicKey().type(); 0410 return list; 0411 } 0412 0413 QList<PKey::Type> supportedIOTypes() const override 0414 { 0415 QList<PKey::Type> list; 0416 list += static_cast<softstorePKeyBase *>(_k)->_publicKey().type(); 0417 return list; 0418 } 0419 0420 QList<PBEAlgorithm> supportedPBEAlgorithms() const override 0421 { 0422 QList<PBEAlgorithm> list; 0423 return list; 0424 } 0425 0426 PKeyBase *key() override 0427 { 0428 return _k; 0429 } 0430 0431 const PKeyBase *key() const override 0432 { 0433 return _k; 0434 } 0435 0436 void setKey(PKeyBase *key) override 0437 { 0438 delete _k; 0439 _k = key; 0440 } 0441 0442 bool importKey(const PKeyBase *key) override 0443 { 0444 Q_UNUSED(key); 0445 return false; 0446 } 0447 0448 static int passphrase_cb(char *buf, int size, int rwflag, void *u) 0449 { 0450 Q_UNUSED(buf); 0451 Q_UNUSED(size); 0452 Q_UNUSED(rwflag); 0453 Q_UNUSED(u); 0454 return 0; 0455 } 0456 0457 QByteArray publicToDER() const override 0458 { 0459 return static_cast<softstorePKeyBase *>(_k)->_publicKey().toDER(); 0460 } 0461 0462 QString publicToPEM() const override 0463 { 0464 return static_cast<softstorePKeyBase *>(_k)->_publicKey().toPEM(); 0465 } 0466 0467 ConvertResult publicFromDER(const QByteArray &in) override 0468 { 0469 Q_UNUSED(in); 0470 return ErrorDecode; 0471 } 0472 0473 ConvertResult publicFromPEM(const QString &s) override 0474 { 0475 Q_UNUSED(s); 0476 return ErrorDecode; 0477 } 0478 0479 SecureArray privateToDER(const SecureArray &passphrase, PBEAlgorithm pbe) const override 0480 { 0481 Q_UNUSED(passphrase); 0482 Q_UNUSED(pbe); 0483 return SecureArray(); 0484 } 0485 0486 QString privateToPEM(const SecureArray &passphrase, PBEAlgorithm pbe) const override 0487 { 0488 Q_UNUSED(passphrase); 0489 Q_UNUSED(pbe); 0490 return QString(); 0491 } 0492 0493 ConvertResult privateFromDER(const SecureArray &in, const SecureArray &passphrase) override 0494 { 0495 Q_UNUSED(in); 0496 Q_UNUSED(passphrase); 0497 return ErrorDecode; 0498 } 0499 0500 ConvertResult privateFromPEM(const QString &s, const SecureArray &passphrase) override 0501 { 0502 Q_UNUSED(s); 0503 Q_UNUSED(passphrase); 0504 return ErrorDecode; 0505 } 0506 }; 0507 0508 class softstoreKeyStoreEntryContext : public KeyStoreEntryContext 0509 { 0510 Q_OBJECT 0511 private: 0512 KeyStoreEntry::Type _item_type; 0513 KeyBundle _key; 0514 SoftStoreEntry _entry; 0515 QString _serialized; 0516 0517 public: 0518 softstoreKeyStoreEntryContext(const KeyBundle &key, 0519 const SoftStoreEntry &entry, 0520 const QString &serialized, 0521 Provider *p) 0522 : KeyStoreEntryContext(p) 0523 { 0524 _item_type = KeyStoreEntry::TypeKeyBundle; 0525 _key = key; 0526 _entry = entry; 0527 _serialized = serialized; 0528 } 0529 0530 softstoreKeyStoreEntryContext(const softstoreKeyStoreEntryContext &from) 0531 : KeyStoreEntryContext(from) 0532 { 0533 _item_type = from._item_type; 0534 _key = from._key; 0535 _entry = from._entry; 0536 _serialized = from._serialized; 0537 } 0538 0539 Provider::Context *clone() const override 0540 { 0541 return new softstoreKeyStoreEntryContext(*this); 0542 } 0543 0544 public: 0545 KeyStoreEntry::Type type() const override 0546 { 0547 return KeyStoreEntry::TypeKeyBundle; 0548 } 0549 0550 QString name() const override 0551 { 0552 return _entry.name; 0553 } 0554 0555 QString id() const override 0556 { 0557 return _entry.name; 0558 } 0559 0560 KeyBundle keyBundle() const override 0561 { 0562 return _key; 0563 } 0564 0565 Certificate certificate() const override 0566 { 0567 return _entry.chain.primary(); 0568 } 0569 0570 QString storeId() const override 0571 { 0572 return QString::asprintf("%s/%s", "qca-softstore", myPrintable(_entry.name)); 0573 } 0574 0575 QString storeName() const override 0576 { 0577 return _entry.name; 0578 } 0579 0580 bool ensureAccess() override 0581 { 0582 return static_cast<softstorePKeyBase *>(static_cast<PKeyContext *>(_key.privateKey().context())->key()) 0583 ->_ensureAccess(); 0584 } 0585 0586 QString serialize() const override 0587 { 0588 return _serialized; 0589 } 0590 }; 0591 0592 class softstoreKeyStoreListContext : public KeyStoreListContext 0593 { 0594 Q_OBJECT 0595 0596 private: 0597 int _last_id; 0598 QList<SoftStoreEntry> _entries; 0599 0600 public: 0601 softstoreKeyStoreListContext(Provider *p) 0602 : KeyStoreListContext(p) 0603 { 0604 QCA_logTextMessage( 0605 QString::asprintf("softstoreKeyStoreListContext::softstoreKeyStoreListContext - entry Provider=%p", 0606 (void *)p), 0607 Logger::Debug); 0608 0609 _last_id = 0; 0610 0611 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::softstoreKeyStoreListContext - return"), 0612 Logger::Debug); 0613 } 0614 0615 ~softstoreKeyStoreListContext() override 0616 { 0617 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::~softstoreKeyStoreListContext - entry"), 0618 Logger::Debug); 0619 0620 s_keyStoreList = nullptr; 0621 0622 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::~softstoreKeyStoreListContext - return"), 0623 Logger::Debug); 0624 } 0625 0626 Provider::Context *clone() const override 0627 { 0628 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::clone - entry/return"), Logger::Debug); 0629 return nullptr; 0630 } 0631 0632 public: 0633 void start() override 0634 { 0635 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::start - entry"), Logger::Debug); 0636 0637 QMetaObject::invokeMethod(this, "doReady", Qt::QueuedConnection); 0638 0639 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::start - return"), Logger::Debug); 0640 } 0641 0642 void setUpdatesEnabled(bool enabled) override 0643 { 0644 QCA_logTextMessage( 0645 QString::asprintf("softstoreKeyStoreListContext::setUpdatesEnabled - entry/return enabled=%d", 0646 enabled ? 1 : 0), 0647 Logger::Debug); 0648 } 0649 0650 KeyStoreEntryContext *entry(int id, const QString &entryId) override 0651 { 0652 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::entry - entry/return id=%d entryId='%s'", 0653 id, 0654 myPrintable(entryId)), 0655 Logger::Debug); 0656 0657 Q_UNUSED(id); 0658 Q_UNUSED(entryId); 0659 return nullptr; 0660 } 0661 0662 KeyStoreEntryContext *entryPassive(const QString &serialized) override 0663 { 0664 KeyStoreEntryContext *entry = nullptr; 0665 0666 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::entryPassive - entry serialized='%s'", 0667 myPrintable(serialized)), 0668 Logger::Debug); 0669 0670 if (serialized.startsWith(QLatin1String("qca-softstore/"))) { 0671 SoftStoreEntry sentry; 0672 0673 if (_deserializeSoftStoreEntry(serialized, sentry)) { 0674 entry = _keyStoreEntryBySoftStoreEntry(sentry); 0675 } 0676 } 0677 0678 QCA_logTextMessage( 0679 QString::asprintf("softstoreKeyStoreListContext::entryPassive - return entry=%p", (void *)entry), 0680 Logger::Debug); 0681 0682 return entry; 0683 } 0684 0685 KeyStore::Type type(int id) const override 0686 { 0687 Q_UNUSED(id); 0688 0689 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::type - entry/return id=%d", id), 0690 Logger::Debug); 0691 0692 return KeyStore::User; 0693 } 0694 0695 QString storeId(int id) const override 0696 { 0697 QString ret; 0698 0699 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::storeId - entry id=%d", id), Logger::Debug); 0700 0701 ret = QStringLiteral("qca-softstore"); 0702 0703 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::storeId - return ret=%s", myPrintable(ret)), 0704 Logger::Debug); 0705 0706 return ret; 0707 } 0708 0709 QString name(int id) const override 0710 { 0711 QString ret; 0712 0713 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::name - entry id=%d", id), Logger::Debug); 0714 0715 ret = QStringLiteral("User Software Store"); 0716 0717 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::name - return ret=%s", myPrintable(ret)), 0718 Logger::Debug); 0719 0720 return ret; 0721 } 0722 0723 QList<KeyStoreEntry::Type> entryTypes(int id) const override 0724 { 0725 Q_UNUSED(id); 0726 0727 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::entryTypes - entry/return id=%d", id), 0728 Logger::Debug); 0729 0730 QList<KeyStoreEntry::Type> list; 0731 list += KeyStoreEntry::TypeKeyBundle; 0732 list += KeyStoreEntry::TypeCertificate; 0733 return list; 0734 } 0735 0736 QList<int> keyStores() override 0737 { 0738 QList<int> list; 0739 0740 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::keyStores - entry"), Logger::Debug); 0741 0742 list += _last_id; 0743 0744 QCA_logTextMessage( 0745 QString::asprintf("softstoreKeyStoreListContext::keyStores - return out.size()=%d", int(list.size())), 0746 Logger::Debug); 0747 0748 return list; 0749 } 0750 0751 QList<KeyStoreEntryContext *> entryList(int id) override 0752 { 0753 QList<KeyStoreEntryContext *> list; 0754 0755 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::entryList - entry id=%d", id), 0756 Logger::Debug); 0757 0758 foreach (const SoftStoreEntry &e, _entries) { 0759 list += _keyStoreEntryBySoftStoreEntry(e); 0760 } 0761 0762 QCA_logTextMessage( 0763 QString::asprintf("softstoreKeyStoreListContext::entryList - return out.size()=%d", int(list.size())), 0764 Logger::Debug); 0765 0766 return list; 0767 } 0768 0769 void _emit_diagnosticText(const QString &t) 0770 { 0771 QCA_logTextMessage( 0772 QString::asprintf("softstoreKeyStoreListContext::_emit_diagnosticText - entry t='%s'", myPrintable(t)), 0773 Logger::Debug); 0774 0775 QCA_logTextMessage(t, Logger::Warning); 0776 0777 emit diagnosticText(t); 0778 0779 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::_emit_diagnosticText - return"), 0780 Logger::Debug); 0781 } 0782 0783 private Q_SLOTS: 0784 void doReady() 0785 { 0786 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::doReady - entry"), Logger::Debug); 0787 0788 emit busyEnd(); 0789 0790 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::doReady - return"), Logger::Debug); 0791 } 0792 0793 void doUpdated() 0794 { 0795 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::doUpdated - entry"), Logger::Debug); 0796 0797 emit updated(); 0798 0799 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::doUpdated - return"), Logger::Debug); 0800 } 0801 0802 public: 0803 void _updateConfig(const QVariantMap &config, const int maxEntries) 0804 { 0805 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::_updateConfig - entry"), Logger::Debug); 0806 0807 QMap<QString, KeyType> keyTypeMap; 0808 keyTypeMap[QStringLiteral("pkcs12")] = keyTypePKCS12; 0809 keyTypeMap[QStringLiteral("pkcs8")] = keyTypePKCS8Inline; 0810 keyTypeMap[QStringLiteral("pkcs8-file-pem")] = keyTypePKCS8FilePEM; 0811 keyTypeMap[QStringLiteral("pkcs8-file-der")] = keyTypePKCS8FileDER; 0812 0813 QMap<QString, PublicType> publicTypeMap; 0814 publicTypeMap[QStringLiteral("x509chain")] = publicTypeX509Chain; 0815 0816 _last_id++; 0817 _entries.clear(); 0818 0819 for (int i = 0; i < maxEntries; i++) { 0820 if (config[QString::asprintf("entry_%02d_enabled", i)].toBool()) { 0821 ConvertResult cresult; 0822 SoftStoreEntry entry; 0823 PublicType publicType = publicTypeInvalid; 0824 0825 entry.name = config[QString::asprintf("entry_%02d_name", i)].toString(); 0826 const QString stringReferenceType = config[QString::asprintf("entry_%02d_private_type", i)].toString(); 0827 const QString stringPublicType = config[QString::asprintf("entry_%02d_public_type", i)].toString(); 0828 entry.noPassphrase = config[QString::asprintf("entry_%02d_no_passphrase", i)].toBool(); 0829 entry.unlockTimeout = config[QString::asprintf("entry_%02d_unlock_timeout", i)].toInt(); 0830 0831 if (publicTypeMap.contains(stringPublicType)) { 0832 publicType = publicTypeMap[stringPublicType]; 0833 } else { 0834 _emit_diagnosticText(QString::asprintf("Software Store: Bad public key type of '%s' entry.\n", 0835 myPrintable(entry.name))); 0836 goto cleanup1; 0837 } 0838 0839 if (keyTypeMap.contains(stringReferenceType)) { 0840 entry.keyReferenceType = keyTypeMap[stringReferenceType]; 0841 } else { 0842 _emit_diagnosticText(QString::asprintf("Software Store: Bad private key type of '%s' entry.\n", 0843 myPrintable(entry.name))); 0844 goto cleanup1; 0845 } 0846 0847 entry.keyReference = config[QString::asprintf("entry_%02d_private", i)].toString(); 0848 0849 switch (publicType) { 0850 case publicTypeInvalid: 0851 goto cleanup1; 0852 break; 0853 case publicTypeX509Chain: 0854 const QStringList base64certs = 0855 config[QString::asprintf("entry_%02d_public", i)].toString().split(QStringLiteral("!")); 0856 0857 foreach (const QString &s, base64certs) { 0858 entry.chain += Certificate::fromDER(Base64().stringToArray(s).toByteArray(), &cresult); 0859 } 0860 0861 if (cresult != ConvertGood) { 0862 _emit_diagnosticText(QString::asprintf( 0863 "Software Store: Cannot load certificate of '%s' entry.\n", myPrintable(entry.name))); 0864 goto cleanup1; 0865 } 0866 break; 0867 } 0868 0869 _entries += entry; 0870 0871 cleanup1:; // nothing to do for this entry. 0872 } 0873 } 0874 0875 QMetaObject::invokeMethod(s_keyStoreList, "doUpdated", Qt::QueuedConnection); 0876 0877 QCA_logTextMessage(QStringLiteral("softstoreKeyStoreListContext::_updateConfig - return"), Logger::Debug); 0878 } 0879 0880 private: 0881 QString _serializeSoftStoreEntry(const SoftStoreEntry &entry) const 0882 { 0883 QString serialized; 0884 0885 QCA_logTextMessage(QString::asprintf("softstoreKeyStoreListContext::_serializeSoftStoreEntry - entry name=%s", 0886 myPrintable(entry.name)), 0887 Logger::Debug); 0888 0889 serialized = QString::asprintf("qca-softstore/0/%s/%d/%s/%d/%d/x509chain/", 0890 myPrintable(_escapeString(entry.name)), 0891 entry.keyReferenceType, 0892 myPrintable(_escapeString(entry.keyReference)), 0893 entry.noPassphrase ? 1 : 0, 0894 entry.unlockTimeout); 0895 0896 QStringList list; 0897 foreach (const Certificate &i, entry.chain) { 0898 list += _escapeString(Base64().arrayToString(i.toDER())); 0899 } 0900 0901 serialized.append(list.join(QStringLiteral("/"))); 0902 0903 QCA_logTextMessage( 0904 QString::asprintf("softstoreKeyStoreListContext::_serializeSoftStoreEntry - return serialized='%s'", 0905 myPrintable(serialized)), 0906 Logger::Debug); 0907 0908 return serialized; 0909 } 0910 0911 bool _deserializeSoftStoreEntry(const QString &serialized, SoftStoreEntry &entry) const 0912 { 0913 bool ret = false; 0914 0915 QCA_logTextMessage( 0916 QString::asprintf("softstoreKeyStoreListContext::_deserializeSoftStoreEntry - entry from='%s'", 0917 myPrintable(serialized)), 0918 Logger::Debug); 0919 0920 entry = SoftStoreEntry(); 0921 0922 const QStringList list = serialized.split(QStringLiteral("/")); 0923 int n = 0; 0924 0925 if (list.size() < 8) { 0926 goto cleanup; 0927 } 0928 0929 if (list[n++] != QLatin1String("qca-softstore")) { 0930 goto cleanup; 0931 } 0932 0933 if (list[n++].toInt() != 0) { 0934 goto cleanup; 0935 } 0936 0937 entry.name = _unescapeString(list[n++]); 0938 entry.keyReferenceType = (KeyType)list[n++].toInt(); 0939 entry.keyReference = _unescapeString(list[n++]); 0940 entry.noPassphrase = list[n++].toInt() != 0; 0941 entry.unlockTimeout = list[n++].toInt(); 0942 n++; // skip public key for now. 0943 0944 while (n < list.size()) { 0945 Certificate cert = Certificate::fromDER(Base64().stringToArray(_unescapeString(list[n++])).toByteArray()); 0946 if (cert.isNull()) { 0947 goto cleanup; 0948 } 0949 entry.chain += cert; 0950 } 0951 0952 ret = true; 0953 0954 cleanup: 0955 0956 QCA_logTextMessage( 0957 QString::asprintf( 0958 "softstoreKeyStoreListContext::_deserializeSoftStoreEntry - return ret=%d chain.size()=%d", 0959 ret ? 1 : 0, 0960 int(entry.chain.size())), 0961 Logger::Debug); 0962 0963 return ret; 0964 } 0965 0966 softstoreKeyStoreEntryContext *_keyStoreEntryBySoftStoreEntry(const SoftStoreEntry &sentry) const 0967 { 0968 softstoreKeyStoreEntryContext *entry = nullptr; 0969 0970 QCA_logTextMessage( 0971 QString::asprintf("softstoreKeyStoreListContext::_keyStoreEntryBySoftStoreEntry - entry name=%s", 0972 myPrintable(sentry.name)), 0973 Logger::Debug); 0974 0975 QString serialized = _serializeSoftStoreEntry(sentry); 0976 0977 softstorePKeyBase *pkey = new softstorePKeyBase(sentry, serialized, provider()); 0978 0979 softstorePKeyContext *pkc = new softstorePKeyContext(provider()); 0980 pkc->setKey(pkey); 0981 PrivateKey privkey; 0982 privkey.change(pkc); 0983 KeyBundle key; 0984 key.setCertificateChainAndKey(sentry.chain, privkey); 0985 0986 entry = new softstoreKeyStoreEntryContext(key, sentry, serialized, provider()); 0987 0988 QCA_logTextMessage( 0989 QString::asprintf("softstoreKeyStoreListContext::_keyStoreEntryBySoftStoreEntry - return entry=%p", 0990 (void *)entry), 0991 Logger::Debug); 0992 0993 return entry; 0994 } 0995 0996 QString _escapeString(const QString &from) const 0997 { 0998 QString to; 0999 1000 foreach (const QChar &c, from) { 1001 if (c == QLatin1Char('/') || c == QLatin1Char('\\')) { 1002 to += QString::asprintf("\\x%04x", c.unicode()); 1003 } else { 1004 to += c; 1005 } 1006 } 1007 1008 return to; 1009 } 1010 1011 QString _unescapeString(const QString &from) const 1012 { 1013 QString to; 1014 1015 for (int i = 0; i < from.size(); i++) { 1016 QChar c = from[i]; 1017 1018 if (c == QLatin1Char('\\')) { 1019 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2) 1020 to += QChar((ushort)QStringView(from).mid(i + 2, 4).toInt(nullptr, 16)); 1021 #else 1022 to += QChar((ushort)from.midRef(i + 2, 4).toInt(nullptr, 16)); 1023 #endif 1024 i += 5; 1025 } else { 1026 to += c; 1027 } 1028 } 1029 1030 return to; 1031 } 1032 }; 1033 1034 } 1035 1036 using namespace softstoreQCAPlugin; 1037 1038 class softstoreProvider : public Provider 1039 { 1040 private: 1041 static const int _CONFIG_MAX_ENTRIES; 1042 1043 QVariantMap _config; 1044 1045 public: 1046 softstoreProvider() 1047 { 1048 } 1049 1050 ~softstoreProvider() override 1051 { 1052 } 1053 1054 public: 1055 int qcaVersion() const override 1056 { 1057 return QCA_VERSION; 1058 } 1059 1060 void init() override 1061 { 1062 } 1063 1064 QString name() const override 1065 { 1066 return QStringLiteral("qca-softstore"); 1067 } 1068 1069 QStringList features() const override 1070 { 1071 QCA_logTextMessage(QStringLiteral("softstoreProvider::features - entry/return"), Logger::Debug); 1072 1073 QStringList list; 1074 list += QStringLiteral("pkey"); 1075 list += QStringLiteral("keystorelist"); 1076 return list; 1077 } 1078 1079 Context *createContext(const QString &type) override 1080 { 1081 Provider::Context *context = nullptr; 1082 1083 QCA_logTextMessage(QString::asprintf("softstoreProvider::createContext - entry type='%s'", myPrintable(type)), 1084 Logger::Debug); 1085 1086 if (type == QLatin1String("keystorelist")) { 1087 if (s_keyStoreList == nullptr) { 1088 s_keyStoreList = new softstoreKeyStoreListContext(this); 1089 s_keyStoreList->_updateConfig(_config, _CONFIG_MAX_ENTRIES); 1090 } 1091 context = s_keyStoreList; 1092 } 1093 1094 QCA_logTextMessage(QString::asprintf("softstoreProvider::createContext - return context=%p", (void *)context), 1095 Logger::Debug); 1096 1097 return context; 1098 } 1099 1100 QVariantMap defaultConfig() const override 1101 { 1102 QVariantMap mytemplate; 1103 1104 QCA_logTextMessage(QStringLiteral("softstoreProvider::defaultConfig - entry/return"), Logger::Debug); 1105 1106 mytemplate[QStringLiteral("formtype")] = QStringLiteral("http://affinix.com/qca/forms/qca-softstore#1.0"); 1107 for (int i = 0; i < _CONFIG_MAX_ENTRIES; i++) { 1108 mytemplate[QString::asprintf("entry_%02d_enabled", i)] = false; 1109 mytemplate[QString::asprintf("entry_%02d_name", i)] = QLatin1String(""); 1110 mytemplate[QString::asprintf("entry_%02d_public_type", i)] = QLatin1String(""); 1111 mytemplate[QString::asprintf("entry_%02d_private_type", i)] = QLatin1String(""); 1112 mytemplate[QString::asprintf("entry_%02d_public", i)] = QLatin1String(""); 1113 mytemplate[QString::asprintf("entry_%02d_private", i)] = QLatin1String(""); 1114 mytemplate[QString::asprintf("entry_%02d_unlock_timeout", i)] = -1; 1115 mytemplate[QString::asprintf("entry_%02d_no_passphrase", i)] = false; 1116 } 1117 1118 return mytemplate; 1119 } 1120 1121 void configChanged(const QVariantMap &config) override 1122 { 1123 QCA_logTextMessage(QStringLiteral("softstoreProvider::configChanged - entry"), Logger::Debug); 1124 1125 _config = config; 1126 1127 if (s_keyStoreList != nullptr) { 1128 s_keyStoreList->_updateConfig(_config, _CONFIG_MAX_ENTRIES); 1129 } 1130 1131 QCA_logTextMessage(QStringLiteral("softstoreProvider::configChanged - return"), Logger::Debug); 1132 } 1133 }; 1134 1135 const int softstoreProvider::_CONFIG_MAX_ENTRIES = 50; 1136 1137 class softstorePlugin : public QObject, public QCAPlugin 1138 { 1139 Q_OBJECT 1140 Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0") 1141 Q_INTERFACES(QCAPlugin) 1142 1143 public: 1144 Provider *createProvider() override 1145 { 1146 return new softstoreProvider; 1147 } 1148 }; 1149 1150 #include "qca-softstore.moc"