File indexing completed on 2024-04-14 08:18:21

0001 /*
0002  * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
0003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
0004  * Copyright (C) 2014-2016  Ivan Romanov <drizt@land.ru>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0019  * 02110-1301  USA
0020  *
0021  */
0022 
0023 #include "qca_core.h"
0024 
0025 #include "qca_cert.h"
0026 #include "qca_keystore.h"
0027 #include "qca_plugin.h"
0028 #include "qca_textfilter.h"
0029 #include "qcaprovider.h"
0030 
0031 // for qAddPostRoutine
0032 #include <QCoreApplication>
0033 
0034 #include <QDir>
0035 #include <QMutex>
0036 #include <QSettings>
0037 #include <QVariantMap>
0038 #include <QWaitCondition>
0039 
0040 #ifdef Q_OS_UNIX
0041 #include <unistd.h>
0042 #endif
0043 
0044 int qcaVersion()
0045 {
0046     return QCA_VERSION;
0047 }
0048 
0049 const char *qcaVersionStr()
0050 {
0051     return QCA_VERSION_STR;
0052 }
0053 
0054 int qcaMajorVersion()
0055 {
0056     return QCA_MAJOR_VERSION;
0057 }
0058 
0059 int qcaMinorVersion()
0060 {
0061     return QCA_MINOR_VERSION;
0062 }
0063 
0064 int qcaPatchVersion()
0065 {
0066     return QCA_PATCH_VERSION;
0067 }
0068 
0069 namespace QCA {
0070 
0071 // from qca_tools
0072 bool botan_init(int prealloc, bool mmap);
0073 void botan_deinit();
0074 
0075 // from qca_default
0076 Provider *create_default_provider();
0077 
0078 //----------------------------------------------------------------------------
0079 // Global
0080 //----------------------------------------------------------------------------
0081 class Global
0082 {
0083 public:
0084     int                        refs;
0085     bool                       secmem;
0086     bool                       loaded;
0087     bool                       first_scan;
0088     QString                    app_name;
0089     QMutex                     name_mutex;
0090     ProviderManager           *manager;
0091     QMutex                     scan_mutex;
0092     Random                    *rng;
0093     QMutex                     rng_mutex;
0094     Logger                    *logger;
0095     QVariantMap                properties;
0096     QMutex                     prop_mutex;
0097     QMap<QString, QVariantMap> config;
0098     QMutex                     config_mutex;
0099     QMutex                     logger_mutex;
0100 
0101     Global()
0102     {
0103         refs       = 0;
0104         secmem     = false;
0105         loaded     = false;
0106         first_scan = false;
0107         rng        = nullptr;
0108         logger     = nullptr;
0109         manager    = new ProviderManager;
0110     }
0111 
0112     ~Global()
0113     {
0114         KeyStoreManager::shutdown();
0115         delete rng;
0116         rng = nullptr;
0117         delete manager;
0118         manager = nullptr;
0119         delete logger;
0120         logger = nullptr;
0121     }
0122 
0123     void ensure_loaded()
0124     {
0125         // probably we shouldn't overload scan mutex, or else rename it
0126         QMutexLocker locker(&scan_mutex);
0127         if (!loaded) {
0128             loaded = true;
0129             manager->setDefault(create_default_provider()); // manager owns it
0130         }
0131     }
0132 
0133     bool ensure_first_scan()
0134     {
0135         scan_mutex.lock();
0136         if (!first_scan) {
0137             first_scan = true;
0138             manager->scan();
0139             scan_mutex.unlock();
0140             return true;
0141         }
0142         scan_mutex.unlock();
0143         return false;
0144     }
0145 
0146     void scan()
0147     {
0148         scan_mutex.lock();
0149         first_scan = true;
0150         manager->scan();
0151         scan_mutex.unlock();
0152     }
0153 
0154     void ksm_scan()
0155     {
0156         KeyStoreManager::scan();
0157     }
0158 
0159     Logger *get_logger()
0160     {
0161         QMutexLocker locker(&logger_mutex);
0162         if (!logger) {
0163             logger = new Logger;
0164 
0165             // needed so deinit may delete the logger regardless
0166             //   of what thread the logger was created from
0167             logger->moveToThread(nullptr);
0168         }
0169         return logger;
0170     }
0171 
0172     void unloadAllPlugins()
0173     {
0174         KeyStoreManager::shutdown();
0175 
0176         // if the global_rng was owned by a plugin, then delete it
0177         rng_mutex.lock();
0178         if (rng && (rng->provider() != manager->find(QStringLiteral("default")))) {
0179             delete rng;
0180             rng = nullptr;
0181         }
0182         rng_mutex.unlock();
0183 
0184         manager->unloadAll();
0185     }
0186 };
0187 
0188 Q_GLOBAL_STATIC(QMutex, global_mutex)
0189 static Global *global = nullptr;
0190 
0191 static bool features_have(const QStringList &have, const QStringList &want)
0192 {
0193     foreach (const QString &i, want) {
0194         if (!have.contains(i))
0195             return false;
0196     }
0197     return true;
0198 }
0199 
0200 void init(MemoryMode mode, int prealloc)
0201 {
0202     QMutexLocker locker(global_mutex());
0203     if (global) {
0204         ++(global->refs);
0205         return;
0206     }
0207 
0208     bool allow_mmap_fallback = false;
0209     bool drop_root           = false;
0210     if (mode == Practical) {
0211         allow_mmap_fallback = true;
0212         drop_root           = true;
0213     } else if (mode == Locking)
0214         drop_root = true;
0215 
0216     bool secmem = botan_init(prealloc, allow_mmap_fallback);
0217 
0218 #if defined(Q_OS_UNIX)
0219     if ((geteuid() == 0) && drop_root) {
0220         setuid(getuid());
0221     }
0222 #endif
0223 
0224     global         = new Global;
0225     global->secmem = secmem;
0226     ++(global->refs);
0227 
0228     // for maximum setuid safety, qca should be initialized before qapp:
0229     //
0230     //   int main(int argc, char **argv)
0231     //   {
0232     //       QCA::Initializer init;
0233     //       QCoreApplication app(argc, argv);
0234     //       return 0;
0235     //   }
0236     //
0237     // however, the above code has the unfortunate side-effect of causing
0238     // qapp to deinit before qca, which can cause problems with any
0239     // plugins that have active objects (notably KeyStore).  we'll use a
0240     // post routine to force qca to deinit first.
0241     qAddPostRoutine(deinit);
0242 }
0243 
0244 void init()
0245 {
0246     init(Practical, 64);
0247 }
0248 
0249 void deinit()
0250 {
0251     QMutexLocker locker(global_mutex());
0252     if (!global)
0253         return;
0254     --(global->refs);
0255     if (global->refs == 0) {
0256         // In order to maintain symmetry with the init() function, remove the
0257         // post routine from QCoreApplication. This is needed in case when the
0258         // QCA library is unloaded before QCoreApplication instance completes:
0259         // QCoreApplication d-tor would try to execute the deinit() function,
0260         // which would no longer be there.
0261         // Note that this function is documented only in Qt 5.3 and later, but
0262         // it has been present since ancient times with the same semantics.
0263         qRemovePostRoutine(deinit);
0264 
0265         delete global;
0266         global = nullptr;
0267         botan_deinit();
0268     }
0269 }
0270 
0271 static bool global_check()
0272 {
0273     Q_ASSERT(global);
0274     if (!global)
0275         return false;
0276     return true;
0277 }
0278 
0279 static bool global_check_load()
0280 {
0281     Q_ASSERT(global);
0282     if (!global)
0283         return false;
0284     global->ensure_loaded();
0285     return true;
0286 }
0287 
0288 QMutex *global_random_mutex()
0289 {
0290     return &global->rng_mutex;
0291 }
0292 
0293 Random *global_random()
0294 {
0295     if (!global->rng)
0296         global->rng = new Random;
0297     return global->rng;
0298 }
0299 
0300 bool haveSecureMemory()
0301 {
0302     if (!global_check())
0303         return false;
0304 
0305     return global->secmem;
0306 }
0307 
0308 bool haveSecureRandom()
0309 {
0310     if (!global_check_load())
0311         return false;
0312 
0313     QMutexLocker locker(global_random_mutex());
0314     if (global_random()->provider()->name() != QLatin1String("default"))
0315         return true;
0316 
0317     return false;
0318 }
0319 
0320 bool isSupported(const QStringList &features, const QString &provider)
0321 {
0322     if (!global_check_load())
0323         return false;
0324 
0325     // single
0326     if (!provider.isEmpty()) {
0327         Provider *p = global->manager->find(provider);
0328         if (!p) {
0329             // ok, try scanning for new stuff
0330             global->scan();
0331             p = global->manager->find(provider);
0332         }
0333 
0334         if (p && features_have(p->features(), features))
0335             return true;
0336     }
0337     // all
0338     else {
0339         if (features_have(global->manager->allFeatures(), features))
0340             return true;
0341 
0342         global->manager->appendDiagnosticText(
0343             QStringLiteral("Scanning to find features: %1\n").arg(features.join(QStringLiteral(" "))));
0344 
0345         // ok, try scanning for new stuff
0346         global->scan();
0347 
0348         if (features_have(global->manager->allFeatures(), features))
0349             return true;
0350     }
0351     return false;
0352 }
0353 
0354 bool isSupported(const char *features, const QString &provider)
0355 {
0356     return isSupported(QString::fromLatin1(features).split(QLatin1Char(','), Qt::SkipEmptyParts), provider);
0357 }
0358 
0359 QStringList supportedFeatures()
0360 {
0361     if (!global_check_load())
0362         return QStringList();
0363 
0364     // query all features
0365     global->scan();
0366     return global->manager->allFeatures();
0367 }
0368 
0369 QStringList defaultFeatures()
0370 {
0371     if (!global_check_load())
0372         return QStringList();
0373 
0374     return global->manager->find(QStringLiteral("default"))->features();
0375 }
0376 
0377 ProviderList providers()
0378 {
0379     if (!global_check_load())
0380         return ProviderList();
0381 
0382     global->ensure_first_scan();
0383 
0384     return global->manager->providers();
0385 }
0386 
0387 bool insertProvider(Provider *p, int priority)
0388 {
0389     if (!global_check_load())
0390         return false;
0391 
0392     global->ensure_first_scan();
0393 
0394     return global->manager->add(p, priority);
0395 }
0396 
0397 bool unloadProvider(const QString &name)
0398 {
0399     if (!global_check_load())
0400         return false;
0401 
0402     global->ensure_first_scan();
0403 
0404     return global->manager->unload(name);
0405 }
0406 
0407 void setProviderPriority(const QString &name, int priority)
0408 {
0409     if (!global_check_load())
0410         return;
0411 
0412     global->ensure_first_scan();
0413 
0414     global->manager->changePriority(name, priority);
0415 }
0416 
0417 int providerPriority(const QString &name)
0418 {
0419     if (!global_check_load())
0420         return -1;
0421 
0422     global->ensure_first_scan();
0423 
0424     return global->manager->getPriority(name);
0425 }
0426 
0427 Provider *findProvider(const QString &name)
0428 {
0429     if (!global_check_load())
0430         return nullptr;
0431 
0432     global->ensure_first_scan();
0433 
0434     return global->manager->find(name);
0435 }
0436 
0437 Provider *defaultProvider()
0438 {
0439     if (!global_check_load())
0440         return nullptr;
0441 
0442     return global->manager->find(QStringLiteral("default"));
0443 }
0444 
0445 QStringList pluginPaths()
0446 {
0447     QStringList paths;
0448 #ifndef DEVELOPER_MODE
0449     const QByteArray qcaPluginPath = qgetenv("QCA_PLUGIN_PATH");
0450     if (!qcaPluginPath.isEmpty()) {
0451 #ifdef Q_OS_WIN
0452         char pathSep(';');
0453 #else
0454         char pathSep(':');
0455 #endif
0456         foreach (const QByteArray &path, qcaPluginPath.split(pathSep)) {
0457             const QString canonicalPath = QDir(QFile::decodeName(path)).canonicalPath();
0458             if (!canonicalPath.isEmpty())
0459                 paths << canonicalPath;
0460         }
0461     }
0462     paths += QCoreApplication::libraryPaths();
0463 #endif
0464     // In developer mode load plugins only from buildtree.
0465     // In regular mode QCA_PLUGIN_PATH is path where plugins was installed
0466     paths << QDir(QStringLiteral(QCA_PLUGIN_PATH)).canonicalPath();
0467 #ifndef DEVELOPER_MODE
0468     paths.removeDuplicates();
0469 #endif
0470     // No empty strings
0471     paths.removeAll(QString());
0472     return paths;
0473 }
0474 
0475 void scanForPlugins()
0476 {
0477     if (!global_check_load())
0478         return;
0479 
0480     global->scan();
0481     global->ksm_scan();
0482 }
0483 
0484 void unloadAllPlugins()
0485 {
0486     if (!global_check_load())
0487         return;
0488 
0489     global->unloadAllPlugins();
0490 }
0491 
0492 QString pluginDiagnosticText()
0493 {
0494     if (!global_check_load())
0495         return QString();
0496 
0497     return global->manager->diagnosticText();
0498 }
0499 
0500 void clearPluginDiagnosticText()
0501 {
0502     if (!global_check_load())
0503         return;
0504 
0505     global->manager->clearDiagnosticText();
0506 }
0507 
0508 void appendPluginDiagnosticText(const QString &text)
0509 {
0510     if (!global_check_load())
0511         return;
0512 
0513     global->manager->appendDiagnosticText(text);
0514 }
0515 
0516 void setProperty(const QString &name, const QVariant &value)
0517 {
0518     if (!global_check_load())
0519         return;
0520 
0521     QMutexLocker locker(&global->prop_mutex);
0522 
0523     global->properties[name] = value;
0524 }
0525 
0526 QVariant getProperty(const QString &name)
0527 {
0528     if (!global_check_load())
0529         return QVariant();
0530 
0531     QMutexLocker locker(&global->prop_mutex);
0532 
0533     return global->properties.value(name);
0534 }
0535 
0536 static bool configIsValid(const QVariantMap &config)
0537 {
0538     if (!config.contains(QStringLiteral("formtype")))
0539         return false;
0540     QMapIterator<QString, QVariant> it(config);
0541     while (it.hasNext()) {
0542         it.next();
0543         const QVariant &v = it.value();
0544 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0545         if (v.typeId() != QMetaType::QString && v.typeId() != QMetaType::Int && v.typeId() != QMetaType::Bool)
0546 #else
0547         if (v.type() != QVariant::String && v.type() != QVariant::Int && v.type() != QVariant::Bool)
0548 
0549 #endif
0550             return false;
0551     }
0552     return true;
0553 }
0554 
0555 static QVariantMap readConfig(const QString &name)
0556 {
0557     QSettings settings(QStringLiteral("Affinix"), QStringLiteral("QCA2"));
0558     settings.beginGroup(QStringLiteral("ProviderConfig"));
0559     const QStringList providerNames = settings.value(QStringLiteral("providerNames")).toStringList();
0560     if (!providerNames.contains(name))
0561         return QVariantMap();
0562 
0563     settings.beginGroup(name);
0564     const QStringList keys = settings.childKeys();
0565     QVariantMap       map;
0566     foreach (const QString &key, keys)
0567         map[key] = settings.value(key);
0568     settings.endGroup();
0569 
0570     if (!configIsValid(map))
0571         return QVariantMap();
0572     return map;
0573 }
0574 
0575 static bool writeConfig(const QString &name, const QVariantMap &config, bool systemWide = false)
0576 {
0577     QSettings settings(QSettings::NativeFormat,
0578                        systemWide ? QSettings::SystemScope : QSettings::UserScope,
0579                        QStringLiteral("Affinix"),
0580                        QStringLiteral("QCA2"));
0581     settings.beginGroup(QStringLiteral("ProviderConfig"));
0582 
0583     // version
0584     settings.setValue(QStringLiteral("version"), 2);
0585 
0586     // add the entry if needed
0587     QStringList providerNames = settings.value(QStringLiteral("providerNames")).toStringList();
0588     if (!providerNames.contains(name))
0589         providerNames += name;
0590     settings.setValue(QStringLiteral("providerNames"), providerNames);
0591 
0592     settings.beginGroup(name);
0593     QMapIterator<QString, QVariant> it(config);
0594     while (it.hasNext()) {
0595         it.next();
0596         settings.setValue(it.key(), it.value());
0597     }
0598     settings.endGroup();
0599 
0600     if (settings.status() == QSettings::NoError)
0601         return true;
0602     return false;
0603 }
0604 
0605 void setProviderConfig(const QString &name, const QVariantMap &config)
0606 {
0607     if (!global_check_load())
0608         return;
0609 
0610     if (!configIsValid(config))
0611         return;
0612 
0613     global->config_mutex.lock();
0614     global->config[name] = config;
0615     global->config_mutex.unlock();
0616 
0617     Provider *p = findProvider(name);
0618     if (p)
0619         p->configChanged(config);
0620 }
0621 
0622 QVariantMap getProviderConfig(const QString &name)
0623 {
0624     if (!global_check_load())
0625         return QVariantMap();
0626 
0627     QVariantMap conf;
0628 
0629     global->config_mutex.lock();
0630 
0631     // try loading from persistent storage
0632     conf = readConfig(name);
0633 
0634     // if not, load the one from memory
0635     if (conf.isEmpty())
0636         conf = global->config.value(name);
0637 
0638     global->config_mutex.unlock();
0639 
0640     // if provider doesn't exist or doesn't have a valid config form,
0641     //   use the config we loaded
0642     Provider *p = findProvider(name);
0643     if (!p)
0644         return conf;
0645     const QVariantMap pconf = p->defaultConfig();
0646     if (!configIsValid(pconf))
0647         return conf;
0648 
0649     // if the config loaded was empty, use the provider's config
0650     if (conf.isEmpty())
0651         return pconf;
0652 
0653     // if the config formtype doesn't match the provider's formtype,
0654     //   then use the provider's
0655     if (pconf[QStringLiteral("formtype")] != conf[QStringLiteral("formtype")])
0656         return pconf;
0657 
0658     // otherwise, use the config loaded
0659     return conf;
0660 }
0661 
0662 void saveProviderConfig(const QString &name)
0663 {
0664     if (!global_check_load())
0665         return;
0666 
0667     QMutexLocker locker(&global->config_mutex);
0668 
0669     QVariantMap conf = global->config.value(name);
0670     if (conf.isEmpty())
0671         return;
0672 
0673     writeConfig(name, conf);
0674 }
0675 
0676 QVariantMap getProviderConfig_internal(Provider *p)
0677 {
0678     QVariantMap   conf;
0679     const QString name = p->name();
0680 
0681     global->config_mutex.lock();
0682 
0683     // try loading from persistent storage
0684     conf = readConfig(name);
0685 
0686     // if not, load the one from memory
0687     if (conf.isEmpty())
0688         conf = global->config.value(name);
0689 
0690     global->config_mutex.unlock();
0691 
0692     // if provider doesn't exist or doesn't have a valid config form,
0693     //   use the config we loaded
0694     const QVariantMap pconf = p->defaultConfig();
0695     if (!configIsValid(pconf))
0696         return conf;
0697 
0698     // if the config loaded was empty, use the provider's config
0699     if (conf.isEmpty())
0700         return pconf;
0701 
0702     // if the config formtype doesn't match the provider's formtype,
0703     //   then use the provider's
0704     if (pconf[QStringLiteral("formtype")] != conf[QStringLiteral("formtype")])
0705         return pconf;
0706 
0707     // otherwise, use the config loaded
0708     return conf;
0709 }
0710 
0711 QString globalRandomProvider()
0712 {
0713     QMutexLocker locker(global_random_mutex());
0714     return global_random()->provider()->name();
0715 }
0716 
0717 void setGlobalRandomProvider(const QString &provider)
0718 {
0719     QMutexLocker locker(global_random_mutex());
0720     delete global->rng;
0721     global->rng = new Random(provider);
0722 }
0723 
0724 Logger *logger()
0725 {
0726     return global->get_logger();
0727 }
0728 
0729 bool haveSystemStore()
0730 {
0731     // ensure the system store is loaded
0732     KeyStoreManager::start(QStringLiteral("default"));
0733     KeyStoreManager ksm;
0734     ksm.waitForBusyFinished();
0735 
0736     const QStringList list = ksm.keyStores();
0737     for (int n = 0; n < list.count(); ++n) {
0738         KeyStore ks(list[n], &ksm);
0739         if (ks.type() == KeyStore::System && ks.holdsTrustedCertificates())
0740             return true;
0741     }
0742     return false;
0743 }
0744 
0745 CertificateCollection systemStore()
0746 {
0747     // ensure the system store is loaded
0748     KeyStoreManager::start(QStringLiteral("default"));
0749     KeyStoreManager ksm;
0750     ksm.waitForBusyFinished();
0751 
0752     CertificateCollection col;
0753     const QStringList     list = ksm.keyStores();
0754     for (int n = 0; n < list.count(); ++n) {
0755         KeyStore ks(list[n], &ksm);
0756 
0757         // system store
0758         if (ks.type() == KeyStore::System && ks.holdsTrustedCertificates()) {
0759             // extract contents
0760             const QList<KeyStoreEntry> entries = ks.entryList();
0761             for (int i = 0; i < entries.count(); ++i) {
0762                 if (entries[i].type() == KeyStoreEntry::TypeCertificate)
0763                     col.addCertificate(entries[i].certificate());
0764                 else if (entries[i].type() == KeyStoreEntry::TypeCRL)
0765                     col.addCRL(entries[i].crl());
0766             }
0767             break;
0768         }
0769     }
0770     return col;
0771 }
0772 
0773 QString appName()
0774 {
0775     if (!global_check())
0776         return QString();
0777 
0778     QMutexLocker locker(&global->name_mutex);
0779 
0780     return global->app_name;
0781 }
0782 
0783 void setAppName(const QString &s)
0784 {
0785     if (!global_check())
0786         return;
0787 
0788     QMutexLocker locker(&global->name_mutex);
0789 
0790     global->app_name = s;
0791 }
0792 
0793 QString arrayToHex(const QByteArray &a)
0794 {
0795     return Hex().arrayToString(a);
0796 }
0797 
0798 QByteArray hexToArray(const QString &str)
0799 {
0800     return Hex().stringToArray(str).toByteArray();
0801 }
0802 
0803 QString arrayToBase64(const QByteArray &a)
0804 {
0805     return Base64().arrayToString(a);
0806 }
0807 
0808 QByteArray base64ToArray(const QString &base64String)
0809 {
0810     return Base64().stringToArray(base64String).toByteArray();
0811 }
0812 
0813 static Provider *getProviderForType(const QString &type, const QString &provider)
0814 {
0815     Provider *p       = nullptr;
0816     bool      scanned = global->ensure_first_scan();
0817     if (!provider.isEmpty()) {
0818         // try using specific provider
0819         p = global->manager->findFor(provider, type);
0820         if (!p && !scanned) {
0821             // maybe this provider is new, so scan and try again
0822             global->scan();
0823             scanned = true;
0824             p       = global->manager->findFor(provider, type);
0825         }
0826     }
0827     if (!p) {
0828         // try using some other provider
0829         p = global->manager->findFor(QString(), type);
0830 
0831         // note: we used to rescan if no provider was found or if
0832         //   the only found provider was 'default'.  now we only
0833         //   rescan if no provider was found.  this optimizes lookups
0834         //   for features that are in the default provider (such as
0835         //   'sha1') when no other plugin is available.  the drawback
0836         //   is that if a plugin is installed later during runtime,
0837         //   then it won't be picked up without restarting the
0838         //   application or manually calling QCA::scanForPlugins.
0839         // if((!p || p->name() == "default") && !scanned)
0840         if (!p && !scanned) {
0841             // maybe there are new providers, so scan and try again
0842             //   before giving up or using default
0843             global->scan();
0844             scanned = true;
0845             p       = global->manager->findFor(QString(), type);
0846         }
0847     }
0848 
0849     return p;
0850 }
0851 
0852 static inline Provider::Context *doCreateContext(Provider *p, const QString &type)
0853 {
0854     return p->createContext(type);
0855 }
0856 
0857 Provider::Context *getContext(const QString &type, const QString &provider)
0858 {
0859     if (!global_check_load())
0860         return nullptr;
0861 
0862     Provider *p;
0863     {
0864         p = getProviderForType(type, provider);
0865         if (!p)
0866             return nullptr;
0867     }
0868 
0869     return doCreateContext(p, type);
0870 }
0871 
0872 Provider::Context *getContext(const QString &type, Provider *_p)
0873 {
0874     if (!global_check_load())
0875         return nullptr;
0876 
0877     Provider *p;
0878     {
0879         p = global->manager->find(_p);
0880         if (!p)
0881             return nullptr;
0882     }
0883 
0884     return doCreateContext(p, type);
0885 }
0886 
0887 //----------------------------------------------------------------------------
0888 // Initializer
0889 //----------------------------------------------------------------------------
0890 Initializer::Initializer(MemoryMode m, int prealloc)
0891 {
0892     init(m, prealloc);
0893 }
0894 
0895 Initializer::~Initializer()
0896 {
0897     deinit();
0898 }
0899 
0900 //----------------------------------------------------------------------------
0901 // Provider
0902 //----------------------------------------------------------------------------
0903 Provider::~Provider()
0904 {
0905 }
0906 
0907 void Provider::init()
0908 {
0909 }
0910 
0911 void Provider::deinit()
0912 {
0913 }
0914 
0915 int Provider::version() const
0916 {
0917     return 0;
0918 }
0919 
0920 QString Provider::credit() const
0921 {
0922     return QString();
0923 }
0924 
0925 QVariantMap Provider::defaultConfig() const
0926 {
0927     return QVariantMap();
0928 }
0929 
0930 void Provider::configChanged(const QVariantMap &)
0931 {
0932 }
0933 
0934 Provider::Context::Context(Provider *parent, const QString &type)
0935     : QObject()
0936 {
0937     _provider = parent;
0938     _type     = type;
0939 }
0940 
0941 Provider::Context::Context(const Context &from)
0942     : QObject()
0943 {
0944     _provider = from._provider;
0945     _type     = from._type;
0946 }
0947 
0948 Provider::Context::~Context()
0949 {
0950 }
0951 
0952 Provider *Provider::Context::provider() const
0953 {
0954     return _provider;
0955 }
0956 
0957 QString Provider::Context::type() const
0958 {
0959     return _type;
0960 }
0961 
0962 bool Provider::Context::sameProvider(const Context *c) const
0963 {
0964     return (c->provider() == _provider);
0965 }
0966 
0967 //----------------------------------------------------------------------------
0968 // BasicContext
0969 //----------------------------------------------------------------------------
0970 BasicContext::BasicContext(Provider *parent, const QString &type)
0971     : Context(parent, type)
0972 {
0973     moveToThread(nullptr); // no thread association
0974 }
0975 
0976 BasicContext::BasicContext(const BasicContext &from)
0977     : Context(from)
0978 {
0979     moveToThread(nullptr); // no thread association
0980 }
0981 
0982 BasicContext::~BasicContext()
0983 {
0984 }
0985 
0986 //----------------------------------------------------------------------------
0987 // InfoContext
0988 //----------------------------------------------------------------------------
0989 QStringList InfoContext::supportedHashTypes() const
0990 {
0991     return QStringList();
0992 }
0993 
0994 QStringList InfoContext::supportedCipherTypes() const
0995 {
0996     return QStringList();
0997 }
0998 
0999 QStringList InfoContext::supportedMACTypes() const
1000 {
1001     return QStringList();
1002 }
1003 
1004 //----------------------------------------------------------------------------
1005 // PKeyBase
1006 //----------------------------------------------------------------------------
1007 PKeyBase::PKeyBase(Provider *p, const QString &type)
1008     : BasicContext(p, type)
1009 {
1010 }
1011 
1012 int PKeyBase::maximumEncryptSize(EncryptionAlgorithm) const
1013 {
1014     return 0;
1015 }
1016 
1017 SecureArray PKeyBase::encrypt(const SecureArray &, EncryptionAlgorithm)
1018 {
1019     return SecureArray();
1020 }
1021 
1022 bool PKeyBase::decrypt(const SecureArray &, SecureArray *, EncryptionAlgorithm)
1023 {
1024     return false;
1025 }
1026 
1027 void PKeyBase::startSign(SignatureAlgorithm, SignatureFormat)
1028 {
1029 }
1030 
1031 void PKeyBase::startVerify(SignatureAlgorithm, SignatureFormat)
1032 {
1033 }
1034 
1035 void PKeyBase::update(const MemoryRegion &)
1036 {
1037 }
1038 
1039 QByteArray PKeyBase::endSign()
1040 {
1041     return QByteArray();
1042 }
1043 
1044 bool PKeyBase::endVerify(const QByteArray &)
1045 {
1046     return false;
1047 }
1048 
1049 SymmetricKey PKeyBase::deriveKey(const PKeyBase &)
1050 {
1051     return SymmetricKey();
1052 }
1053 
1054 //----------------------------------------------------------------------------
1055 // PKeyContext
1056 //----------------------------------------------------------------------------
1057 QByteArray PKeyContext::publicToDER() const
1058 {
1059     return QByteArray();
1060 }
1061 
1062 QString PKeyContext::publicToPEM() const
1063 {
1064     return QString();
1065 }
1066 
1067 ConvertResult PKeyContext::publicFromDER(const QByteArray &)
1068 {
1069     return ErrorDecode;
1070 }
1071 
1072 ConvertResult PKeyContext::publicFromPEM(const QString &)
1073 {
1074     return ErrorDecode;
1075 }
1076 
1077 SecureArray PKeyContext::privateToDER(const SecureArray &, PBEAlgorithm) const
1078 {
1079     return SecureArray();
1080 }
1081 
1082 QString PKeyContext::privateToPEM(const SecureArray &, PBEAlgorithm) const
1083 {
1084     return QString();
1085 }
1086 
1087 ConvertResult PKeyContext::privateFromDER(const SecureArray &, const SecureArray &)
1088 {
1089     return ErrorDecode;
1090 }
1091 
1092 ConvertResult PKeyContext::privateFromPEM(const QString &, const SecureArray &)
1093 {
1094     return ErrorDecode;
1095 }
1096 
1097 //----------------------------------------------------------------------------
1098 // KeyStoreEntryContext
1099 //----------------------------------------------------------------------------
1100 bool KeyStoreEntryContext::isAvailable() const
1101 {
1102     return true;
1103 }
1104 
1105 KeyBundle KeyStoreEntryContext::keyBundle() const
1106 {
1107     return KeyBundle();
1108 }
1109 
1110 Certificate KeyStoreEntryContext::certificate() const
1111 {
1112     return Certificate();
1113 }
1114 
1115 CRL KeyStoreEntryContext::crl() const
1116 {
1117     return CRL();
1118 }
1119 
1120 PGPKey KeyStoreEntryContext::pgpSecretKey() const
1121 {
1122     return PGPKey();
1123 }
1124 
1125 PGPKey KeyStoreEntryContext::pgpPublicKey() const
1126 {
1127     return PGPKey();
1128 }
1129 
1130 bool KeyStoreEntryContext::ensureAccess()
1131 {
1132     return true;
1133 }
1134 
1135 //----------------------------------------------------------------------------
1136 // KeyStoreListContext
1137 //----------------------------------------------------------------------------
1138 void KeyStoreListContext::start()
1139 {
1140     QMetaObject::invokeMethod(this, "busyEnd", Qt::QueuedConnection);
1141 }
1142 
1143 void KeyStoreListContext::setUpdatesEnabled(bool)
1144 {
1145 }
1146 
1147 bool KeyStoreListContext::isReadOnly(int) const
1148 {
1149     return true;
1150 }
1151 
1152 KeyStoreEntryContext *KeyStoreListContext::entry(int id, const QString &entryId)
1153 {
1154     KeyStoreEntryContext         *out  = nullptr;
1155     QList<KeyStoreEntryContext *> list = entryList(id);
1156     for (int n = 0; n < list.count(); ++n) {
1157         if (list[n]->id() == entryId) {
1158             out = list.takeAt(n);
1159             break;
1160         }
1161     }
1162     qDeleteAll(list);
1163     return out;
1164 }
1165 
1166 KeyStoreEntryContext *KeyStoreListContext::entryPassive(const QString &serialized)
1167 {
1168     Q_UNUSED(serialized);
1169     return nullptr;
1170 }
1171 
1172 QString KeyStoreListContext::writeEntry(int, const KeyBundle &)
1173 {
1174     return QString();
1175 }
1176 
1177 QString KeyStoreListContext::writeEntry(int, const Certificate &)
1178 {
1179     return QString();
1180 }
1181 
1182 QString KeyStoreListContext::writeEntry(int, const CRL &)
1183 {
1184     return QString();
1185 }
1186 
1187 QString KeyStoreListContext::writeEntry(int, const PGPKey &)
1188 {
1189     return QString();
1190 }
1191 
1192 bool KeyStoreListContext::removeEntry(int, const QString &)
1193 {
1194     return false;
1195 }
1196 
1197 //----------------------------------------------------------------------------
1198 // TLSContext
1199 //----------------------------------------------------------------------------
1200 void TLSContext::setMTU(int)
1201 {
1202 }
1203 
1204 //----------------------------------------------------------------------------
1205 // MessageContext
1206 //----------------------------------------------------------------------------
1207 QString MessageContext::diagnosticText() const
1208 {
1209     return QString();
1210 }
1211 
1212 //----------------------------------------------------------------------------
1213 // SMSContext
1214 //----------------------------------------------------------------------------
1215 void SMSContext::setTrustedCertificates(const CertificateCollection &)
1216 {
1217 }
1218 
1219 void SMSContext::setUntrustedCertificates(const CertificateCollection &)
1220 {
1221 }
1222 
1223 void SMSContext::setPrivateKeys(const QList<SecureMessageKey> &)
1224 {
1225 }
1226 
1227 //----------------------------------------------------------------------------
1228 // BufferedComputation
1229 //----------------------------------------------------------------------------
1230 BufferedComputation::~BufferedComputation()
1231 {
1232 }
1233 
1234 MemoryRegion BufferedComputation::process(const MemoryRegion &a)
1235 {
1236     clear();
1237     update(a);
1238     return final();
1239 }
1240 
1241 //----------------------------------------------------------------------------
1242 // Filter
1243 //----------------------------------------------------------------------------
1244 Filter::~Filter()
1245 {
1246 }
1247 
1248 MemoryRegion Filter::process(const MemoryRegion &a)
1249 {
1250     clear();
1251     MemoryRegion buf = update(a);
1252     if (!ok())
1253         return MemoryRegion();
1254     const MemoryRegion fin = final();
1255     if (!ok())
1256         return MemoryRegion();
1257     if (buf.isSecure() || fin.isSecure())
1258         return (SecureArray(buf) + SecureArray(fin));
1259     else
1260         return QByteArray(buf.toByteArray() + fin.toByteArray());
1261 }
1262 
1263 //----------------------------------------------------------------------------
1264 // Algorithm
1265 //----------------------------------------------------------------------------
1266 class Algorithm::Private : public QSharedData
1267 {
1268 public:
1269     Provider::Context *c;
1270 
1271     Private(Provider::Context *context)
1272     {
1273         c = context;
1274         // printf("** [%p] Algorithm Created\n", c);
1275     }
1276 
1277     Private(const Private &from)
1278         : QSharedData(from)
1279     {
1280         c = from.c->clone();
1281         // printf("** [%p] Algorithm Copied (to [%p])\n", from.c, c);
1282     }
1283 
1284     ~Private()
1285     {
1286         // printf("** [%p] Algorithm Destroyed\n", c);
1287         delete c;
1288     }
1289 };
1290 
1291 Algorithm::Algorithm()
1292 {
1293 }
1294 
1295 Algorithm::Algorithm(const QString &type, const QString &provider)
1296 {
1297     change(type, provider);
1298 }
1299 
1300 Algorithm::Algorithm(const Algorithm &from)
1301 {
1302     *this = from;
1303 }
1304 
1305 Algorithm::~Algorithm()
1306 {
1307 }
1308 
1309 Algorithm &Algorithm::operator=(const Algorithm &from)
1310 {
1311     d = from.d;
1312     return *this;
1313 }
1314 
1315 QString Algorithm::type() const
1316 {
1317     if (d)
1318         return d->c->type();
1319     else
1320         return QString();
1321 }
1322 
1323 Provider *Algorithm::provider() const
1324 {
1325     if (d)
1326         return d->c->provider();
1327     else
1328         return nullptr;
1329 }
1330 
1331 Provider::Context *Algorithm::context()
1332 {
1333     if (d)
1334         return d->c;
1335     else
1336         return nullptr;
1337 }
1338 
1339 const Provider::Context *Algorithm::context() const
1340 {
1341     if (d)
1342         return d->c;
1343     else
1344         return nullptr;
1345 }
1346 
1347 void Algorithm::change(Provider::Context *c)
1348 {
1349     if (c)
1350         d = new Private(c);
1351     else
1352         d = nullptr;
1353 }
1354 
1355 void Algorithm::change(const QString &type, const QString &provider)
1356 {
1357     if (!type.isEmpty())
1358         change(getContext(type, provider));
1359     else
1360         change(nullptr);
1361 }
1362 
1363 Provider::Context *Algorithm::takeContext()
1364 {
1365     if (d) {
1366         Provider::Context *c = d->c; // should cause a detach
1367         d->c                 = nullptr;
1368         d                    = nullptr;
1369         return c;
1370     } else
1371         return nullptr;
1372 }
1373 
1374 //----------------------------------------------------------------------------
1375 // SymmetricKey
1376 //----------------------------------------------------------------------------
1377 SymmetricKey::SymmetricKey()
1378 {
1379 }
1380 
1381 SymmetricKey::SymmetricKey(int size)
1382 {
1383     set(Random::randomArray(size));
1384 }
1385 
1386 SymmetricKey::SymmetricKey(const SecureArray &a)
1387 {
1388     set(a);
1389 }
1390 
1391 SymmetricKey::SymmetricKey(const QByteArray &a)
1392 {
1393     set(SecureArray(a));
1394 }
1395 
1396 /* from libgcrypt-1.2.0 */
1397 static const unsigned char desWeakKeyTable[64][8] = {
1398     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*w*/
1399     {0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e}, {0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0},
1400     {0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe}, {0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e}, /*sw*/
1401     {0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00}, {0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe},
1402     {0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0}, {0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0}, /*sw*/
1403     {0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe}, {0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00},
1404     {0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e}, {0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe}, /*sw*/
1405     {0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0}, {0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e},
1406     {0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00}, {0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e},
1407     {0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00}, /*sw*/
1408     {0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe}, {0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0},
1409     {0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00}, {0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e}, /*w*/
1410     {0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0}, {0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe},
1411     {0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe}, {0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0}, /*sw*/
1412     {0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e}, {0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00},
1413     {0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0}, {0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe}, /*sw*/
1414     {0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00}, {0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e},
1415     {0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0}, {0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe},
1416     {0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00}, /*sw*/
1417     {0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e}, {0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe},
1418     {0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0}, {0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e}, /*sw*/
1419     {0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00}, {0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00},
1420     {0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e}, {0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0}, /*w*/
1421     {0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe}, {0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e},
1422     {0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00}, {0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe}, /*sw*/
1423     {0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0}, {0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe},
1424     {0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0}, {0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e},
1425     {0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00}, /*sw*/
1426     {0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0}, {0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe},
1427     {0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00}, {0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e}, /*sw*/
1428     {0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e}, {0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00},
1429     {0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe}, {0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0}, /*sw*/
1430     {0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00}, {0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e},
1431     {0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0}, {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe} /*w*/
1432 };
1433 
1434 bool SymmetricKey::isWeakDESKey()
1435 {
1436     if (size() != 8)
1437         return false; // dubious
1438     SecureArray workingCopy(8);
1439     // clear parity bits
1440     for (uint i = 0; i < 8; i++)
1441         workingCopy[i] = (data()[i]) & 0xfe;
1442 
1443     for (auto n : desWeakKeyTable) {
1444         if (memcmp(workingCopy.data(), n, 8) == 0)
1445             return true;
1446     }
1447     return false;
1448 }
1449 
1450 //----------------------------------------------------------------------------
1451 // InitializationVector
1452 //----------------------------------------------------------------------------
1453 InitializationVector::InitializationVector()
1454 {
1455 }
1456 
1457 InitializationVector::InitializationVector(int size)
1458 {
1459     set(Random::randomArray(size));
1460 }
1461 
1462 InitializationVector::InitializationVector(const SecureArray &a)
1463 {
1464     set(a);
1465 }
1466 
1467 InitializationVector::InitializationVector(const QByteArray &a)
1468 {
1469     set(SecureArray(a));
1470 }
1471 
1472 //----------------------------------------------------------------------------
1473 // AuthTag
1474 //----------------------------------------------------------------------------
1475 AuthTag::AuthTag()
1476 {
1477 }
1478 
1479 AuthTag::AuthTag(int size)
1480 {
1481     resize(size);
1482 }
1483 
1484 AuthTag::AuthTag(const SecureArray &a)
1485 {
1486     set(a);
1487 }
1488 
1489 AuthTag::AuthTag(const QByteArray &a)
1490 {
1491     set(SecureArray(a));
1492 }
1493 
1494 //----------------------------------------------------------------------------
1495 // Event
1496 //----------------------------------------------------------------------------
1497 class Event::Private : public QSharedData
1498 {
1499 public:
1500     Type          type;
1501     Source        source;
1502     PasswordStyle style;
1503     KeyStoreInfo  ksi;
1504     KeyStoreEntry kse;
1505     QString       fname;
1506     void         *ptr;
1507 };
1508 
1509 Event::Event()
1510 {
1511 }
1512 
1513 Event::Event(const Event &from)
1514     : d(from.d)
1515 {
1516 }
1517 
1518 Event::~Event()
1519 {
1520 }
1521 
1522 Event &Event::operator=(const Event &from)
1523 {
1524     d = from.d;
1525     return *this;
1526 }
1527 
1528 bool Event::isNull() const
1529 {
1530     return (d ? false : true);
1531 }
1532 
1533 Event::Type Event::type() const
1534 {
1535     return d->type;
1536 }
1537 
1538 Event::Source Event::source() const
1539 {
1540     return d->source;
1541 }
1542 
1543 Event::PasswordStyle Event::passwordStyle() const
1544 {
1545     return d->style;
1546 }
1547 
1548 KeyStoreInfo Event::keyStoreInfo() const
1549 {
1550     return d->ksi;
1551 }
1552 
1553 KeyStoreEntry Event::keyStoreEntry() const
1554 {
1555     return d->kse;
1556 }
1557 
1558 QString Event::fileName() const
1559 {
1560     return d->fname;
1561 }
1562 
1563 void *Event::ptr() const
1564 {
1565     return d->ptr;
1566 }
1567 
1568 void Event::setPasswordKeyStore(PasswordStyle        pstyle,
1569                                 const KeyStoreInfo  &keyStoreInfo,
1570                                 const KeyStoreEntry &keyStoreEntry,
1571                                 void                *ptr)
1572 {
1573     if (!d)
1574         d = new Private;
1575     d->type   = Password;
1576     d->source = KeyStore;
1577     d->style  = pstyle;
1578     d->ksi    = keyStoreInfo;
1579     d->kse    = keyStoreEntry;
1580     d->fname  = QString();
1581     d->ptr    = ptr;
1582 }
1583 
1584 void Event::setPasswordData(PasswordStyle pstyle, const QString &fileName, void *ptr)
1585 {
1586     if (!d)
1587         d = new Private;
1588     d->type   = Password;
1589     d->source = Data;
1590     d->style  = pstyle;
1591     d->ksi    = KeyStoreInfo();
1592     d->kse    = KeyStoreEntry();
1593     d->fname  = fileName;
1594     d->ptr    = ptr;
1595 }
1596 
1597 void Event::setToken(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
1598 {
1599     if (!d)
1600         d = new Private;
1601     d->type   = Token;
1602     d->source = KeyStore;
1603     d->style  = StylePassword;
1604     d->ksi    = keyStoreInfo;
1605     d->kse    = keyStoreEntry;
1606     d->fname  = QString();
1607     d->ptr    = ptr;
1608 }
1609 
1610 //----------------------------------------------------------------------------
1611 // EventGlobal
1612 //----------------------------------------------------------------------------
1613 class HandlerBase : public QObject
1614 {
1615     Q_OBJECT
1616 public:
1617     HandlerBase(QObject *parent = nullptr)
1618         : QObject(parent)
1619     {
1620     }
1621 
1622 protected Q_SLOTS:
1623     virtual void ask(int id, const QCA::Event &e) = 0;
1624 };
1625 
1626 class AskerBase : public QObject
1627 {
1628     Q_OBJECT
1629 public:
1630     AskerBase(QObject *parent = nullptr)
1631         : QObject(parent)
1632     {
1633     }
1634 
1635     virtual void set_accepted(const SecureArray &password) = 0;
1636     virtual void set_rejected()                            = 0;
1637 };
1638 
1639 static void handler_add(HandlerBase *h, int pos = -1);
1640 static void handler_remove(HandlerBase *h);
1641 static void handler_accept(HandlerBase *h, int id, const SecureArray &password);
1642 static void handler_reject(HandlerBase *h, int id);
1643 static bool asker_ask(AskerBase *a, const Event &e);
1644 static void asker_cancel(AskerBase *a);
1645 
1646 Q_GLOBAL_STATIC(QMutex, g_event_mutex)
1647 
1648 class EventGlobal;
1649 static EventGlobal *g_event = nullptr;
1650 
1651 class EventGlobal
1652 {
1653 public:
1654     class HandlerItem
1655     {
1656     public:
1657         HandlerBase *h;
1658         QList<int>   ids;
1659     };
1660 
1661     class AskerItem
1662     {
1663     public:
1664         AskerBase *a;
1665         int        id;
1666         Event      event;
1667         int        handler_pos;
1668     };
1669 
1670     QList<HandlerItem> handlers;
1671     QList<AskerItem>   askers;
1672 
1673     int next_id;
1674 
1675     EventGlobal()
1676     {
1677         qRegisterMetaType<Event>("QCA::Event");
1678         qRegisterMetaType<SecureArray>("QCA::SecureArray");
1679         next_id = 0;
1680     }
1681 
1682     int findHandlerItem(HandlerBase *h)
1683     {
1684         for (int n = 0; n < handlers.count(); ++n) {
1685             if (handlers[n].h == h)
1686                 return n;
1687         }
1688         return -1;
1689     }
1690 
1691     int findAskerItem(AskerBase *a)
1692     {
1693         for (int n = 0; n < askers.count(); ++n) {
1694             if (askers[n].a == a)
1695                 return n;
1696         }
1697         return -1;
1698     }
1699 
1700     int findAskerItemById(int id)
1701     {
1702         for (int n = 0; n < askers.count(); ++n) {
1703             if (askers[n].id == id)
1704                 return n;
1705         }
1706         return -1;
1707     }
1708 
1709     void ask(int asker_at)
1710     {
1711         AskerItem &i = askers[asker_at];
1712 
1713         g_event->handlers[i.handler_pos].ids += i.id;
1714         QMetaObject::invokeMethod(
1715             handlers[i.handler_pos].h, "ask", Qt::QueuedConnection, Q_ARG(int, i.id), Q_ARG(QCA::Event, i.event));
1716     }
1717 
1718     void reject(int asker_at)
1719     {
1720         AskerItem &i = askers[asker_at];
1721 
1722         // look for the next usable handler
1723         int pos = -1;
1724         for (int n = i.handler_pos + 1; n < g_event->handlers.count(); ++n) {
1725             // handler and asker can't be in the same thread
1726             // Q_ASSERT(g_event->handlers[n].h->thread() != i.a->thread());
1727             // if(g_event->handlers[n].h->thread() != i.a->thread())
1728             //{
1729             pos = n;
1730             break;
1731             //}
1732         }
1733 
1734         // if there is one, try it
1735         if (pos != -1) {
1736             i.handler_pos = pos;
1737             ask(asker_at);
1738         }
1739         // if not, send official reject
1740         else {
1741             AskerBase *asker = i.a;
1742             askers.removeAt(asker_at);
1743 
1744             asker->set_rejected();
1745         }
1746     }
1747 };
1748 
1749 void handler_add(HandlerBase *h, int pos)
1750 {
1751     QMutexLocker locker(g_event_mutex());
1752     if (!g_event)
1753         g_event = new EventGlobal;
1754 
1755     EventGlobal::HandlerItem i;
1756     i.h = h;
1757 
1758     if (pos != -1) {
1759         g_event->handlers.insert(pos, i);
1760 
1761         // adjust handler positions
1762         for (int n = 0; n < g_event->askers.count(); ++n) {
1763             if (g_event->askers[n].handler_pos >= pos)
1764                 g_event->askers[n].handler_pos++;
1765         }
1766     } else
1767         g_event->handlers += i;
1768 }
1769 
1770 void handler_remove(HandlerBase *h)
1771 {
1772     QMutexLocker locker(g_event_mutex());
1773     Q_ASSERT(g_event);
1774     if (!g_event)
1775         return;
1776     int at = g_event->findHandlerItem(h);
1777     Q_ASSERT(at != -1);
1778     if (at == -1)
1779         return;
1780 
1781     const QList<int> ids = g_event->handlers[at].ids;
1782     g_event->handlers.removeAt(at);
1783 
1784     // adjust handler positions within askers
1785     for (int n = 0; n < g_event->askers.count(); ++n) {
1786         if (g_event->askers[n].handler_pos >= at)
1787             g_event->askers[n].handler_pos--;
1788     }
1789 
1790     // reject all askers
1791     foreach (int id, ids) {
1792         int asker_at = g_event->findAskerItemById(id);
1793         Q_ASSERT(asker_at != -1);
1794 
1795         g_event->reject(asker_at);
1796     }
1797 
1798     if (g_event->handlers.isEmpty()) {
1799         delete g_event;
1800         g_event = nullptr;
1801     }
1802 }
1803 
1804 void handler_accept(HandlerBase *h, int id, const SecureArray &password)
1805 {
1806     QMutexLocker locker(g_event_mutex());
1807     Q_ASSERT(g_event);
1808     if (!g_event)
1809         return;
1810     int at = g_event->findHandlerItem(h);
1811     Q_ASSERT(at != -1);
1812     if (at == -1)
1813         return;
1814     int asker_at = g_event->findAskerItemById(id);
1815     Q_ASSERT(asker_at != -1);
1816     if (asker_at == -1)
1817         return;
1818 
1819     g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id);
1820 
1821     AskerBase *asker = g_event->askers[asker_at].a;
1822     asker->set_accepted(password);
1823 }
1824 
1825 void handler_reject(HandlerBase *h, int id)
1826 {
1827     QMutexLocker locker(g_event_mutex());
1828     Q_ASSERT(g_event);
1829     if (!g_event)
1830         return;
1831     int at = g_event->findHandlerItem(h);
1832     Q_ASSERT(at != -1);
1833     if (at == -1)
1834         return;
1835     int asker_at = g_event->findAskerItemById(id);
1836     Q_ASSERT(asker_at != -1);
1837     if (asker_at == -1)
1838         return;
1839 
1840     g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id);
1841 
1842     g_event->reject(asker_at);
1843 }
1844 
1845 bool asker_ask(AskerBase *a, const Event &e)
1846 {
1847     QMutexLocker locker(g_event_mutex());
1848     if (!g_event)
1849         return false;
1850 
1851     int pos = -1;
1852     for (int n = 0; n < g_event->handlers.count(); ++n) {
1853         // handler and asker can't be in the same thread
1854         // Q_ASSERT(g_event->handlers[n].h->thread() != a->thread());
1855         // if(g_event->handlers[n].h->thread() != a->thread())
1856         //{
1857         pos = n;
1858         break;
1859         //}
1860     }
1861     if (pos == -1)
1862         return false;
1863 
1864     EventGlobal::AskerItem i;
1865     i.a           = a;
1866     i.id          = g_event->next_id++;
1867     i.event       = e;
1868     i.handler_pos = pos;
1869     g_event->askers += i;
1870     const int asker_at = g_event->askers.count() - 1;
1871 
1872     g_event->ask(asker_at);
1873     return true;
1874 }
1875 
1876 void asker_cancel(AskerBase *a)
1877 {
1878     QMutexLocker locker(g_event_mutex());
1879     if (!g_event)
1880         return;
1881     int at = g_event->findAskerItem(a);
1882     if (at == -1)
1883         return;
1884 
1885     for (int n = 0; n < g_event->handlers.count(); ++n)
1886         g_event->handlers[n].ids.removeAll(g_event->askers[at].id);
1887 
1888     g_event->askers.removeAt(at);
1889 }
1890 
1891 //----------------------------------------------------------------------------
1892 // EventHandler
1893 //----------------------------------------------------------------------------
1894 class EventHandler::Private : public HandlerBase
1895 {
1896     Q_OBJECT
1897 public:
1898     EventHandler *q;
1899     bool          started;
1900     QList<int>    activeIds;
1901 
1902     Private(EventHandler *_q)
1903         : HandlerBase(_q)
1904         , q(_q)
1905     {
1906         started = false;
1907     }
1908 
1909 public Q_SLOTS:
1910     void ask(int id, const QCA::Event &e) override
1911     {
1912         activeIds += id;
1913         emit q->eventReady(id, e);
1914     }
1915 };
1916 
1917 EventHandler::EventHandler(QObject *parent)
1918     : QObject(parent)
1919 {
1920     d = new Private(this);
1921 }
1922 
1923 EventHandler::~EventHandler()
1924 {
1925     if (d->started) {
1926         foreach (int id, d->activeIds)
1927             handler_reject(d, id);
1928 
1929         handler_remove(d);
1930     }
1931 
1932     delete d;
1933 }
1934 
1935 void EventHandler::start()
1936 {
1937     d->started = true;
1938     handler_add(d);
1939 }
1940 
1941 void EventHandler::submitPassword(int id, const SecureArray &password)
1942 {
1943     if (!d->activeIds.contains(id))
1944         return;
1945 
1946     d->activeIds.removeAll(id);
1947     handler_accept(d, id, password);
1948 }
1949 
1950 void EventHandler::tokenOkay(int id)
1951 {
1952     if (!d->activeIds.contains(id))
1953         return;
1954 
1955     d->activeIds.removeAll(id);
1956     handler_accept(d, id, SecureArray());
1957 }
1958 
1959 void EventHandler::reject(int id)
1960 {
1961     if (!d->activeIds.contains(id))
1962         return;
1963 
1964     d->activeIds.removeAll(id);
1965     handler_reject(d, id);
1966 }
1967 
1968 //----------------------------------------------------------------------------
1969 // PasswordAsker
1970 //----------------------------------------------------------------------------
1971 class AskerPrivate : public AskerBase
1972 {
1973     Q_OBJECT
1974 public:
1975     enum Type
1976     {
1977         Password,
1978         Token
1979     };
1980 
1981     Type           type;
1982     PasswordAsker *passwordAsker;
1983     TokenAsker    *tokenAsker;
1984 
1985     QMutex         m;
1986     QWaitCondition w;
1987 
1988     bool        accepted;
1989     SecureArray password;
1990     bool        waiting;
1991     bool        done;
1992 
1993     AskerPrivate(PasswordAsker *parent)
1994         : AskerBase(parent)
1995     {
1996         passwordAsker = parent;
1997         tokenAsker    = nullptr;
1998         type          = Password;
1999         accepted      = false;
2000         waiting       = false;
2001         done          = true;
2002     }
2003 
2004     AskerPrivate(TokenAsker *parent)
2005         : AskerBase(parent)
2006     {
2007         passwordAsker = nullptr;
2008         tokenAsker    = parent;
2009         type          = Token;
2010         accepted      = false;
2011         waiting       = false;
2012         done          = true;
2013     }
2014 
2015     void ask(const Event &e)
2016     {
2017         accepted = false;
2018         waiting  = false;
2019         done     = false;
2020         password.clear();
2021 
2022         if (!asker_ask(this, e)) {
2023             done = true;
2024             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
2025         }
2026     }
2027 
2028     void cancel()
2029     {
2030         if (!done)
2031             asker_cancel(this);
2032     }
2033 
2034     void set_accepted(const SecureArray &_password) override
2035     {
2036         QMutexLocker locker(&m);
2037         accepted = true;
2038         password = _password;
2039         done     = true;
2040         if (waiting)
2041             w.wakeOne();
2042         else
2043             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
2044     }
2045 
2046     void set_rejected() override
2047     {
2048         QMutexLocker locker(&m);
2049         done = true;
2050         if (waiting)
2051             w.wakeOne();
2052         else
2053             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
2054     }
2055 
2056     void waitForResponse()
2057     {
2058         QMutexLocker locker(&m);
2059         if (done)
2060             return;
2061         waiting = true;
2062         w.wait(&m);
2063         waiting = false;
2064     }
2065 
2066 public Q_SLOTS:
2067     virtual void emitResponseReady() = 0;
2068 };
2069 
2070 class PasswordAsker::Private : public AskerPrivate
2071 {
2072     Q_OBJECT
2073 public:
2074     Private(PasswordAsker *_q)
2075         : AskerPrivate(_q)
2076     {
2077     }
2078 
2079     void emitResponseReady() override
2080     {
2081         emit passwordAsker->responseReady();
2082     }
2083 };
2084 
2085 PasswordAsker::PasswordAsker(QObject *parent)
2086     : QObject(parent)
2087 {
2088     d = new Private(this);
2089 }
2090 
2091 PasswordAsker::~PasswordAsker()
2092 {
2093     delete d;
2094 }
2095 
2096 void PasswordAsker::ask(Event::PasswordStyle pstyle,
2097                         const KeyStoreInfo  &keyStoreInfo,
2098                         const KeyStoreEntry &keyStoreEntry,
2099                         void                *ptr)
2100 {
2101     Event e;
2102     e.setPasswordKeyStore(pstyle, keyStoreInfo, keyStoreEntry, ptr);
2103     d->ask(e);
2104 }
2105 
2106 void PasswordAsker::ask(Event::PasswordStyle pstyle, const QString &fileName, void *ptr)
2107 {
2108     Event e;
2109     e.setPasswordData(pstyle, fileName, ptr);
2110     d->ask(e);
2111 }
2112 
2113 void PasswordAsker::cancel()
2114 {
2115     d->cancel();
2116 }
2117 
2118 void PasswordAsker::waitForResponse()
2119 {
2120     d->waitForResponse();
2121 }
2122 
2123 bool PasswordAsker::accepted() const
2124 {
2125     return d->accepted;
2126 }
2127 
2128 SecureArray PasswordAsker::password() const
2129 {
2130     return d->password;
2131 }
2132 
2133 //----------------------------------------------------------------------------
2134 // TokenAsker
2135 //----------------------------------------------------------------------------
2136 class TokenAsker::Private : public AskerPrivate
2137 {
2138     Q_OBJECT
2139 public:
2140     Private(TokenAsker *_q)
2141         : AskerPrivate(_q)
2142     {
2143     }
2144 
2145     void emitResponseReady() override
2146     {
2147         emit tokenAsker->responseReady();
2148     }
2149 };
2150 
2151 TokenAsker::TokenAsker(QObject *parent)
2152     : QObject(parent)
2153 {
2154     d = new Private(this);
2155 }
2156 
2157 TokenAsker::~TokenAsker()
2158 {
2159     delete d;
2160 }
2161 
2162 void TokenAsker::ask(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
2163 {
2164     Event e;
2165     e.setToken(keyStoreInfo, keyStoreEntry, ptr);
2166     d->ask(e);
2167 }
2168 
2169 void TokenAsker::cancel()
2170 {
2171     d->cancel();
2172 }
2173 
2174 void TokenAsker::waitForResponse()
2175 {
2176     d->waitForResponse();
2177 }
2178 
2179 bool TokenAsker::accepted() const
2180 {
2181     return d->accepted;
2182 }
2183 
2184 }
2185 
2186 #include "qca_core.moc"