File indexing completed on 2024-04-28 04:43:43

0001 /*
0002  * Copyright (C) 2004  Justin Karneges <justin@affinix.com>
0003  * Copyright (C) 2004-2006  Brad Hards <bradh@frogmouth.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library; if not, write to the Free Software
0017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
0018  *
0019  */
0020 #include <QtCrypto>
0021 
0022 #include <QtCore/qplugin.h>
0023 
0024 #include <QElapsedTimer>
0025 
0026 #include <gcrypt.h>
0027 #include <iostream>
0028 #include <qstringlist.h>
0029 
0030 namespace gcryptQCAPlugin {
0031 
0032 #include "hkdf.c"
0033 #include "pkcs5.c"
0034 
0035 void check_error(const char *label, gcry_error_t err)
0036 {
0037     // we ignore the case where it is not an error, and
0038     // we also don't flag weak keys.
0039     if ((GPG_ERR_NO_ERROR != err) && (GPG_ERR_WEAK_KEY != gpg_err_code(err))) {
0040         std::cout << "Failure (" << label << "): ";
0041         std::cout << gcry_strsource(err) << "/";
0042         std::cout << gcry_strerror(err) << std::endl;
0043     }
0044 }
0045 
0046 class gcryHashContext : public QCA::HashContext
0047 {
0048     Q_OBJECT
0049 public:
0050     gcryHashContext(int hashAlgorithm, QCA::Provider *p, const QString &type)
0051         : QCA::HashContext(p, type)
0052     {
0053         m_hashAlgorithm = hashAlgorithm;
0054         err             = gcry_md_open(&context, m_hashAlgorithm, 0);
0055         if (GPG_ERR_NO_ERROR != err) {
0056             std::cout << "Failure: ";
0057             std::cout << gcry_strsource(err) << "/";
0058             std::cout << gcry_strerror(err) << std::endl;
0059         }
0060     }
0061 
0062     ~gcryHashContext() override
0063     {
0064         gcry_md_close(context);
0065     }
0066 
0067     Context *clone() const override
0068     {
0069         return new gcryHashContext(m_hashAlgorithm, provider(), type());
0070     }
0071 
0072     void clear() override
0073     {
0074         gcry_md_reset(context);
0075     }
0076 
0077     void update(const QCA::MemoryRegion &a) override
0078     {
0079         gcry_md_write(context, a.data(), a.size());
0080     }
0081 
0082     QCA::MemoryRegion final() override
0083     {
0084         unsigned char   *md;
0085         QCA::SecureArray a(gcry_md_get_algo_dlen(m_hashAlgorithm));
0086         md = gcry_md_read(context, m_hashAlgorithm);
0087         memcpy(a.data(), md, a.size());
0088         return a;
0089     }
0090 
0091 protected:
0092     gcry_md_hd_t context;
0093     gcry_error_t err;
0094     int          m_hashAlgorithm;
0095 };
0096 
0097 class gcryHMACContext : public QCA::MACContext
0098 {
0099     Q_OBJECT
0100 public:
0101     gcryHMACContext(int hashAlgorithm, QCA::Provider *p, const QString &type)
0102         : QCA::MACContext(p, type)
0103     {
0104         m_hashAlgorithm = hashAlgorithm;
0105         err             = gcry_md_open(&context, m_hashAlgorithm, GCRY_MD_FLAG_HMAC);
0106         if (GPG_ERR_NO_ERROR != err) {
0107             std::cout << "Failure: ";
0108             std::cout << gcry_strsource(err) << "/";
0109             std::cout << gcry_strerror(err) << std::endl;
0110         }
0111     }
0112 
0113     ~gcryHMACContext() override
0114     {
0115         gcry_md_close(context);
0116     }
0117 
0118     void setup(const QCA::SymmetricKey &key) override
0119     {
0120         gcry_md_setkey(context, key.data(), key.size());
0121     }
0122 
0123     Context *clone() const override
0124     {
0125         return new gcryHMACContext(m_hashAlgorithm, provider(), type());
0126     }
0127 
0128     void clear()
0129     {
0130         gcry_md_reset(context);
0131     }
0132 
0133     QCA::KeyLength keyLength() const override
0134     {
0135         return anyKeyLength();
0136     }
0137 
0138     void update(const QCA::MemoryRegion &a) override
0139     {
0140         gcry_md_write(context, a.data(), a.size());
0141     }
0142 
0143     void final(QCA::MemoryRegion *out) override
0144     {
0145         QCA::SecureArray sa(gcry_md_get_algo_dlen(m_hashAlgorithm), 0);
0146         unsigned char   *md;
0147         md = gcry_md_read(context, m_hashAlgorithm);
0148         memcpy(sa.data(), md, sa.size());
0149         *out = sa;
0150     }
0151 
0152 protected:
0153     gcry_md_hd_t context;
0154     gcry_error_t err;
0155     int          m_hashAlgorithm;
0156 };
0157 
0158 class gcryCipherContext : public QCA::CipherContext
0159 {
0160     Q_OBJECT
0161 public:
0162     gcryCipherContext(int algorithm, int mode, bool pad, QCA::Provider *p, const QString &type)
0163         : QCA::CipherContext(p, type)
0164     {
0165         m_cryptoAlgorithm = algorithm;
0166         m_mode            = mode;
0167         m_pad             = pad;
0168     }
0169 
0170     void setup(QCA::Direction                   dir,
0171                const QCA::SymmetricKey         &key,
0172                const QCA::InitializationVector &iv,
0173                const QCA::AuthTag              &tag) override
0174     {
0175         Q_UNUSED(tag);
0176         m_direction = dir;
0177         err         = gcry_cipher_open(&context, m_cryptoAlgorithm, m_mode, 0);
0178         check_error("gcry_cipher_open", err);
0179         if ((GCRY_CIPHER_3DES == m_cryptoAlgorithm) && (key.size() == 16)) {
0180             // this is triple DES with two keys, and gcrypt wants three
0181             QCA::SymmetricKey keyCopy(key);
0182             QCA::SecureArray  thirdKey(key);
0183             thirdKey.resize(8);
0184             keyCopy += thirdKey;
0185             err = gcry_cipher_setkey(context, keyCopy.data(), keyCopy.size());
0186         } else {
0187             err = gcry_cipher_setkey(context, key.data(), key.size());
0188         }
0189         check_error("gcry_cipher_setkey", err);
0190         err = gcry_cipher_setiv(context, iv.data(), iv.size());
0191         check_error("gcry_cipher_setiv", err);
0192     }
0193 
0194     Context *clone() const override
0195     {
0196         return new gcryCipherContext(*this);
0197     }
0198 
0199     int blockSize() const override
0200     {
0201         size_t blockSize;
0202         gcry_cipher_algo_info(m_cryptoAlgorithm, GCRYCTL_GET_BLKLEN, nullptr, &blockSize);
0203         return blockSize;
0204     }
0205 
0206     QCA::AuthTag tag() const override
0207     {
0208         // For future implementation
0209         return QCA::AuthTag();
0210     }
0211 
0212     bool update(const QCA::SecureArray &in, QCA::SecureArray *out) override
0213     {
0214         QCA::SecureArray result(in.size());
0215         if (QCA::Encode == m_direction) {
0216             err = gcry_cipher_encrypt(
0217                 context, (unsigned char *)result.data(), result.size(), (unsigned char *)in.data(), in.size());
0218         } else {
0219             err = gcry_cipher_decrypt(
0220                 context, (unsigned char *)result.data(), result.size(), (unsigned char *)in.data(), in.size());
0221         }
0222         check_error("update cipher encrypt/decrypt", err);
0223         result.resize(in.size());
0224         *out = result;
0225         return true;
0226     }
0227 
0228     bool final(QCA::SecureArray *out) override
0229     {
0230         QCA::SecureArray result;
0231         if (m_pad) {
0232             result.resize(blockSize());
0233             if (QCA::Encode == m_direction) {
0234                 err = gcry_cipher_encrypt(context, (unsigned char *)result.data(), result.size(), nullptr, 0);
0235             } else {
0236                 err = gcry_cipher_decrypt(context, (unsigned char *)result.data(), result.size(), nullptr, 0);
0237             }
0238             check_error("final cipher encrypt/decrypt", err);
0239         } else {
0240             // just return null
0241         }
0242         *out = result;
0243         return true;
0244     }
0245 
0246     QCA::KeyLength keyLength() const override
0247     {
0248         switch (m_cryptoAlgorithm) {
0249         case GCRY_CIPHER_DES:
0250             return QCA::KeyLength(8, 8, 1);
0251         case GCRY_CIPHER_AES128:
0252             return QCA::KeyLength(16, 16, 1);
0253         case GCRY_CIPHER_AES192:
0254             return QCA::KeyLength(24, 24, 1);
0255         case GCRY_CIPHER_3DES:
0256             // we do two and three key versions
0257             return QCA::KeyLength(16, 24, 8);
0258         case GCRY_CIPHER_AES256:
0259             return QCA::KeyLength(32, 32, 1);
0260         case GCRY_CIPHER_BLOWFISH:
0261             // Don't know - TODO
0262             return QCA::KeyLength(1, 32, 1);
0263         default:
0264             return QCA::KeyLength(0, 1, 1);
0265         }
0266     }
0267 
0268 protected:
0269     gcry_cipher_hd_t context;
0270     gcry_error_t     err;
0271     int              m_cryptoAlgorithm;
0272     QCA::Direction   m_direction;
0273     int              m_mode;
0274     bool             m_pad;
0275 };
0276 
0277 class pbkdf1Context : public QCA::KDFContext
0278 {
0279     Q_OBJECT
0280 public:
0281     pbkdf1Context(int algorithm, QCA::Provider *p, const QString &type)
0282         : QCA::KDFContext(p, type)
0283     {
0284         m_hashAlgorithm = algorithm;
0285         err             = gcry_md_open(&context, m_hashAlgorithm, 0);
0286         if (GPG_ERR_NO_ERROR != err) {
0287             std::cout << "Failure: ";
0288             std::cout << gcry_strsource(err) << "/";
0289             std::cout << gcry_strerror(err) << std::endl;
0290         }
0291     }
0292 
0293     ~pbkdf1Context() override
0294     {
0295         gcry_md_close(context);
0296     }
0297 
0298     Context *clone() const override
0299     {
0300         return new pbkdf1Context(m_hashAlgorithm, provider(), type());
0301     }
0302 
0303     QCA::SymmetricKey makeKey(const QCA::SecureArray          &secret,
0304                               const QCA::InitializationVector &salt,
0305                               unsigned int                     keyLength,
0306                               unsigned int                     iterationCount) override
0307     {
0308         /* from RFC2898:
0309            Steps:
0310 
0311            1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
0312            "derived key too long" and stop.
0313         */
0314         if (keyLength > gcry_md_get_algo_dlen(m_hashAlgorithm)) {
0315             std::cout << "derived key too long" << std::endl;
0316             return QCA::SymmetricKey();
0317         }
0318 
0319         /*
0320            2. Apply the underlying hash function Hash for c iterations to the
0321            concatenation of the password P and the salt S, then extract
0322            the first dkLen octets to produce a derived key DK:
0323 
0324            T_1 = Hash (P || S) ,
0325            T_2 = Hash (T_1) ,
0326            ...
0327            T_c = Hash (T_{c-1}) ,
0328            DK = Tc<0..dkLen-1>
0329         */
0330         // calculate T_1
0331         gcry_md_write(context, secret.data(), secret.size());
0332         gcry_md_write(context, salt.data(), salt.size());
0333         unsigned char *md;
0334         md = gcry_md_read(context, m_hashAlgorithm);
0335         QCA::SecureArray a(gcry_md_get_algo_dlen(m_hashAlgorithm));
0336         memcpy(a.data(), md, a.size());
0337 
0338         // calculate T_2 up to T_c
0339         for (unsigned int i = 2; i <= iterationCount; ++i) {
0340             gcry_md_reset(context);
0341             gcry_md_write(context, a.data(), a.size());
0342             md = gcry_md_read(context, m_hashAlgorithm);
0343             memcpy(a.data(), md, a.size());
0344         }
0345 
0346         // shrink a to become DK, of the required length
0347         a.resize(keyLength);
0348 
0349         /*
0350            3. Output the derived key DK.
0351         */
0352         return a;
0353     }
0354 
0355     QCA::SymmetricKey makeKey(const QCA::SecureArray          &secret,
0356                               const QCA::InitializationVector &salt,
0357                               unsigned int                     keyLength,
0358                               int                              msecInterval,
0359                               unsigned int                    *iterationCount) override
0360     {
0361         Q_ASSERT(iterationCount != nullptr);
0362         QElapsedTimer timer;
0363 
0364         /*
0365            from RFC2898:
0366            Steps:
0367 
0368            1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
0369            "derived key too long" and stop.
0370         */
0371         if (keyLength > gcry_md_get_algo_dlen(m_hashAlgorithm)) {
0372             std::cout << "derived key too long" << std::endl;
0373             return QCA::SymmetricKey();
0374         }
0375 
0376         /*
0377            2. Apply the underlying hash function Hash for M milliseconds
0378            to the concatenation of the password P and the salt S, incrementing c,
0379            then extract the first dkLen octets to produce a derived key DK:
0380 
0381            time from 0 to M
0382            T_1 = Hash (P || S) ,
0383            T_2 = Hash (T_1) ,
0384            ...
0385            T_c = Hash (T_{c-1}) ,
0386            when time = 0: stop,
0387            DK = Tc<0..dkLen-1>
0388         */
0389         // calculate T_1
0390         gcry_md_write(context, secret.data(), secret.size());
0391         gcry_md_write(context, salt.data(), salt.size());
0392         unsigned char *md;
0393         md = gcry_md_read(context, m_hashAlgorithm);
0394         QCA::SecureArray a(gcry_md_get_algo_dlen(m_hashAlgorithm));
0395         memcpy(a.data(), md, a.size());
0396 
0397         // calculate T_2 up to T_c
0398         *iterationCount = 2 - 1; // <- Have to remove 1, unless it computes one
0399         timer.start();           // ^  time more than the base function
0400                                  // ^  with the same iterationCount
0401         while (timer.elapsed() < msecInterval) {
0402             gcry_md_reset(context);
0403             gcry_md_write(context, a.data(), a.size());
0404             md = gcry_md_read(context, m_hashAlgorithm);
0405             memcpy(a.data(), md, a.size());
0406             ++(*iterationCount);
0407         }
0408 
0409         // shrink a to become DK, of the required length
0410         a.resize(keyLength);
0411 
0412         /*
0413            3. Output the derived key DK.
0414         */
0415         return a;
0416     }
0417 
0418 protected:
0419     gcry_md_hd_t context;
0420     gcry_error_t err;
0421     int          m_hashAlgorithm;
0422 };
0423 
0424 class pbkdf2Context : public QCA::KDFContext
0425 {
0426     Q_OBJECT
0427 public:
0428     pbkdf2Context(int algorithm, QCA::Provider *p, const QString &type)
0429         : QCA::KDFContext(p, type)
0430     {
0431         m_algorithm = algorithm;
0432     }
0433 
0434     Context *clone() const override
0435     {
0436         return new pbkdf2Context(*this);
0437     }
0438 
0439     QCA::SymmetricKey makeKey(const QCA::SecureArray          &secret,
0440                               const QCA::InitializationVector &salt,
0441                               unsigned int                     keyLength,
0442                               unsigned int                     iterationCount) override
0443     {
0444         QCA::SymmetricKey result(keyLength);
0445         gcry_error_t      retval = gcry_pbkdf2(m_algorithm,
0446                                           secret.data(),
0447                                           secret.size(),
0448                                           salt.data(),
0449                                           salt.size(),
0450                                           iterationCount,
0451                                           keyLength,
0452                                           result.data());
0453         if (retval == GPG_ERR_NO_ERROR) {
0454             return result;
0455         } else {
0456             // std::cout << "got: " << retval << std::endl;
0457             return QCA::SymmetricKey();
0458         }
0459     }
0460 
0461     QCA::SymmetricKey makeKey(const QCA::SecureArray          &secret,
0462                               const QCA::InitializationVector &salt,
0463                               unsigned int                     keyLength,
0464                               int                              msecInterval,
0465                               unsigned int                    *iterationCount) override
0466     {
0467         Q_ASSERT(iterationCount != nullptr);
0468         QCA::SymmetricKey result(keyLength);
0469         QElapsedTimer     timer;
0470 
0471         *iterationCount = 0;
0472         timer.start();
0473 
0474         while (timer.elapsed() < msecInterval) {
0475             gcry_pbkdf2(
0476                 m_algorithm, secret.data(), secret.size(), salt.data(), salt.size(), 1, keyLength, result.data());
0477             ++(*iterationCount);
0478         }
0479 
0480         return makeKey(secret, salt, keyLength, *iterationCount);
0481     }
0482 
0483 protected:
0484     int m_algorithm;
0485 };
0486 
0487 class hkdfContext : public QCA::HKDFContext
0488 {
0489     Q_OBJECT
0490 public:
0491     hkdfContext(int algorithm, QCA::Provider *p, const QString &type)
0492         : QCA::HKDFContext(p, type)
0493     {
0494         m_algorithm = algorithm;
0495     }
0496 
0497     Context *clone() const override
0498     {
0499         return new hkdfContext(*this);
0500     }
0501 
0502     QCA::SymmetricKey makeKey(const QCA::SecureArray          &secret,
0503                               const QCA::InitializationVector &salt,
0504                               const QCA::InitializationVector &info,
0505                               unsigned int                     keyLength) override
0506     {
0507         QCA::SymmetricKey result(keyLength);
0508         gcry_error_t      retval = gcry_hkdf(m_algorithm,
0509                                         secret.data(),
0510                                         secret.size(),
0511                                         salt.data(),
0512                                         salt.size(),
0513                                         info.data(),
0514                                         info.size(),
0515                                         result.data(),
0516                                         result.size());
0517         if (retval == GPG_ERR_NO_ERROR) {
0518             return result;
0519         } else {
0520             return QCA::SymmetricKey();
0521         }
0522     }
0523 
0524 protected:
0525     int m_algorithm;
0526 };
0527 
0528 }
0529 
0530 extern "C" {
0531 
0532 static void *qca_func_malloc(size_t n)
0533 {
0534     return qca_secure_alloc(n);
0535 }
0536 
0537 static void *qca_func_secure_malloc(size_t n)
0538 {
0539     return qca_secure_alloc(n);
0540 }
0541 
0542 static void *qca_func_realloc(void *oldBlock, size_t newBlockSize)
0543 {
0544     return qca_secure_realloc(oldBlock, newBlockSize);
0545 }
0546 
0547 static void qca_func_free(void *mem)
0548 {
0549     qca_secure_free(mem);
0550 }
0551 
0552 int qca_func_secure_check(const void *)
0553 {
0554     return (int)QCA::haveSecureMemory();
0555 }
0556 } // extern "C"
0557 
0558 class gcryptProvider : public QCA::Provider
0559 {
0560 public:
0561     void init() override
0562     {
0563         if (!gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) { /* No other library has already initialized libgcrypt. */
0564 
0565             if (!gcry_check_version(GCRYPT_VERSION)) {
0566                 std::cout << "libgcrypt is too old (need " << GCRYPT_VERSION;
0567                 std::cout << ", have " << gcry_check_version(nullptr) << ")" << std::endl;
0568             }
0569             gcry_set_allocation_handler(
0570                 qca_func_malloc, qca_func_secure_malloc, qca_func_secure_check, qca_func_realloc, qca_func_free);
0571             gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
0572         }
0573     }
0574 
0575     int qcaVersion() const override
0576     {
0577         return QCA_VERSION;
0578     }
0579 
0580     QString name() const override
0581     {
0582         return QStringLiteral("qca-gcrypt");
0583     }
0584 
0585     QStringList features() const override
0586     {
0587         QStringList list;
0588         list += QStringLiteral("sha1");
0589         list += QStringLiteral("md4");
0590         list += QStringLiteral("md5");
0591         list += QStringLiteral("ripemd160");
0592 #ifdef GCRY_MD_SHA224
0593         list += QStringLiteral("sha224");
0594 #endif
0595         list += QStringLiteral("sha256");
0596         list += QStringLiteral("sha384");
0597         list += QStringLiteral("sha512");
0598         list += QStringLiteral("hmac(md5)");
0599         list += QStringLiteral("hmac(sha1)");
0600 #ifdef GCRY_MD_SHA224
0601         list += QStringLiteral("hmac(sha224)");
0602 #endif
0603         list += QStringLiteral("hmac(sha256)");
0604         if (!(nullptr == gcry_check_version("1.3.0"))) {
0605             // 1.2 and earlier have broken implementation
0606             list += QStringLiteral("hmac(sha384)");
0607             list += QStringLiteral("hmac(sha512)");
0608         }
0609         list += QStringLiteral("hmac(ripemd160)");
0610         list += QStringLiteral("aes128-ecb");
0611         list += QStringLiteral("aes128-cfb");
0612         list += QStringLiteral("aes128-cbc");
0613         list += QStringLiteral("aes192-ecb");
0614         list += QStringLiteral("aes192-cfb");
0615         list += QStringLiteral("aes192-cbc");
0616         list += QStringLiteral("aes256-ecb");
0617         list += QStringLiteral("aes256-cfb");
0618         list += QStringLiteral("aes256-cbc");
0619         list += QStringLiteral("blowfish-ecb");
0620         list += QStringLiteral("blowfish-cbc");
0621         list += QStringLiteral("blowfish-cfb");
0622         list += QStringLiteral("tripledes-ecb");
0623         //  list += QStringLiteral("des-ecb");
0624         list += QStringLiteral("des-cbc");
0625         list += QStringLiteral("des-cfb");
0626         if (!(nullptr == gcry_check_version("1.3.0"))) {
0627             // 1.2 branch and earlier doesn't support OFB mode
0628             list += QStringLiteral("aes128-ofb");
0629             list += QStringLiteral("aes192-ofb");
0630             list += QStringLiteral("aes256-ofb");
0631             list += QStringLiteral("des-ofb");
0632             list += QStringLiteral("tripledes-ofb");
0633             list += QStringLiteral("blowfish-ofb");
0634         }
0635         list += QStringLiteral("pbkdf1(sha1)");
0636         list += QStringLiteral("pbkdf2(sha1)");
0637         list += QStringLiteral("hkdf(sha256)");
0638         return list;
0639     }
0640 
0641     Context *createContext(const QString &type) override
0642     {
0643         // std::cout << "type: " << qPrintable(type) << std::endl;
0644         if (type == QLatin1String("sha1"))
0645             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_SHA1, this, type);
0646         else if (type == QLatin1String("md4"))
0647             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_MD4, this, type);
0648         else if (type == QLatin1String("md5"))
0649             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_MD5, this, type);
0650         else if (type == QLatin1String("ripemd160"))
0651             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_RMD160, this, type);
0652 #ifdef GCRY_MD_SHA224
0653         else if (type == QLatin1String("sha224"))
0654             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_SHA224, this, type);
0655 #endif
0656         else if (type == QLatin1String("sha256"))
0657             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_SHA256, this, type);
0658         else if (type == QLatin1String("sha384"))
0659             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_SHA384, this, type);
0660         else if (type == QLatin1String("sha512"))
0661             return new gcryptQCAPlugin::gcryHashContext(GCRY_MD_SHA512, this, type);
0662         else if (type == QLatin1String("hmac(md5)"))
0663             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_MD5, this, type);
0664         else if (type == QLatin1String("hmac(sha1)"))
0665             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_SHA1, this, type);
0666 #ifdef GCRY_MD_SHA224
0667         else if (type == QLatin1String("hmac(sha224)"))
0668             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_SHA224, this, type);
0669 #endif
0670         else if (type == QLatin1String("hmac(sha256)"))
0671             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_SHA256, this, type);
0672         else if (type == QLatin1String("hmac(sha384)"))
0673             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_SHA384, this, type);
0674         else if (type == QLatin1String("hmac(sha512)"))
0675             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_SHA512, this, type);
0676         else if (type == QLatin1String("hmac(ripemd160)"))
0677             return new gcryptQCAPlugin::gcryHMACContext(GCRY_MD_RMD160, this, type);
0678         else if (type == QLatin1String("aes128-ecb"))
0679             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, false, this, type);
0680         else if (type == QLatin1String("aes128-cfb"))
0681             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB, false, this, type);
0682         else if (type == QLatin1String("aes128-ofb"))
0683             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_OFB, false, this, type);
0684         else if (type == QLatin1String("aes128-cbc"))
0685             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, false, this, type);
0686         else if (type == QLatin1String("aes192-ecb"))
0687             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB, false, this, type);
0688         else if (type == QLatin1String("aes192-cfb"))
0689             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB, false, this, type);
0690         else if (type == QLatin1String("aes192-ofb"))
0691             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB, false, this, type);
0692         else if (type == QLatin1String("aes192-cbc"))
0693             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC, false, this, type);
0694         else if (type == QLatin1String("aes256-ecb"))
0695             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB, false, this, type);
0696         else if (type == QLatin1String("aes256-cfb"))
0697             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB, false, this, type);
0698         else if (type == QLatin1String("aes256-ofb"))
0699             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, false, this, type);
0700         else if (type == QLatin1String("aes256-cbc"))
0701             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, false, this, type);
0702         else if (type == QLatin1String("blowfish-ecb"))
0703             return new gcryptQCAPlugin::gcryCipherContext(
0704                 GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB, false, this, type);
0705         else if (type == QLatin1String("blowfish-cbc"))
0706             return new gcryptQCAPlugin::gcryCipherContext(
0707                 GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, false, this, type);
0708         else if (type == QLatin1String("blowfish-cfb"))
0709             return new gcryptQCAPlugin::gcryCipherContext(
0710                 GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB, false, this, type);
0711         else if (type == QLatin1String("blowfish-ofb"))
0712             return new gcryptQCAPlugin::gcryCipherContext(
0713                 GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB, false, this, type);
0714         else if (type == QLatin1String("tripledes-ecb"))
0715             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB, false, this, type);
0716         else if (type == QLatin1String("tripledes-ofb"))
0717             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_OFB, false, this, type);
0718         else if (type == QLatin1String("des-ecb"))
0719             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, false, this, type);
0720         else if (type == QLatin1String("des-cbc"))
0721             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, false, this, type);
0722         else if (type == QLatin1String("des-cfb"))
0723             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB, false, this, type);
0724         else if (type == QLatin1String("des-ofb"))
0725             return new gcryptQCAPlugin::gcryCipherContext(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_OFB, false, this, type);
0726         else if (type == QLatin1String("pbkdf1(sha1)"))
0727             return new gcryptQCAPlugin::pbkdf1Context(GCRY_MD_SHA1, this, type);
0728         else if (type == QLatin1String("pbkdf2(sha1)"))
0729             return new gcryptQCAPlugin::pbkdf2Context(GCRY_MD_SHA1, this, type);
0730         else if (type == QLatin1String("hkdf(sha256)"))
0731             return new gcryptQCAPlugin::hkdfContext(GCRY_MD_SHA256, this, type);
0732         else
0733             return nullptr;
0734     }
0735 };
0736 
0737 class gcryptPlugin : public QObject, public QCAPlugin
0738 {
0739     Q_OBJECT
0740     Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0")
0741     Q_INTERFACES(QCAPlugin)
0742 public:
0743     QCA::Provider *createProvider() override
0744     {
0745         return new gcryptProvider;
0746     }
0747 };
0748 
0749 #include "qca-gcrypt.moc"