4
0
mirror of https://github.com/QuasarApp/qca.git synced 2025-05-10 01:39:34 +00:00

botan: Check if ciphers are supported before saying they are

Now all tests pass :)
This commit is contained in:
Albert Astals Cid 2020-01-20 19:10:18 +01:00
parent acb45eeb84
commit a77ea02b8d

@ -282,17 +282,114 @@ protected:
};
#endif
static void qcaCipherToBotanCipher(const QString &type, std::string *algoName, std::string *algoMode, std::string *algoPadding)
{
if (type == "aes128-ecb" ) {
*algoName = "AES-128";
*algoMode = "ECB";
*algoPadding = "NoPadding";
} else if ( type == "aes128-cbc" ) {
*algoName = "AES-128";
*algoMode = "CBC";
*algoPadding = "NoPadding";
} else if ( type == "aes128-cfb" ) {
*algoName = "AES-128";
*algoMode = "CFB";
*algoPadding = "NoPadding";
} else if ( type == "aes128-ofb" ) {
*algoName = "AES-128";
*algoMode = "OFB";
*algoPadding = "NoPadding";
} else if ( type == "aes192-ecb" ) {
*algoName = "AES-192";
*algoMode = "ECB";
*algoPadding = "NoPadding";
} else if ( type == "aes192-cbc" ) {
*algoName = "AES-192";
*algoMode = "CBC";
*algoPadding = "NoPadding";
} else if ( type == "aes192-cfb" ) {
*algoName = "AES-192";
*algoMode = "CFB";
*algoPadding = "NoPadding";
} else if ( type == "aes192-ofb" ) {
*algoName = "AES-192";
*algoMode = "OFB";
*algoPadding = "NoPadding";
} else if ( type == "aes256-ecb" ) {
*algoName = "AES-256";
*algoMode = "ECB";
*algoPadding = "NoPadding";
} else if ( type == "aes256-cbc" ) {
*algoName = "AES-256";
*algoMode = "CBC";
*algoPadding = "NoPadding";
} else if ( type == "aes256-cfb" ) {
*algoName = "AES-256";
*algoMode = "CFB";
*algoPadding = "NoPadding";
} else if ( type == "aes256-ofb" ) {
*algoName = "AES-256";
*algoMode = "OFB";
*algoPadding = "NoPadding";
} else if ( type == "blowfish-ecb" ) {
*algoName = "Blowfish";
*algoMode = "ECB";
*algoPadding = "NoPadding";
} else if ( type == "blowfish-cbc" ) {
*algoName = "Blowfish";
*algoMode = "CBC";
*algoPadding = "NoPadding";
} else if ( type == "blowfish-cbc-pkcs7" ) {
*algoName = "Blowfish";
*algoMode = "CBC";
*algoPadding = "PKCS7";
} else if ( type == "blowfish-cfb" ) {
*algoName = "Blowfish";
*algoMode = "CFB";
*algoPadding = "NoPadding";
} else if ( type == "blowfish-ofb" ) {
*algoName = "Blowfish";
*algoMode = "OFB";
*algoPadding = "NoPadding";
} else if ( type == "des-ecb" ) {
*algoName = "DES";
*algoMode = "ECB";
*algoPadding = "NoPadding";
} else if ( type == "des-ecb-pkcs7" ) {
*algoName = "DES";
*algoMode = "ECB";
*algoPadding = "PKCS7";
} else if ( type == "des-cbc" ) {
*algoName = "DES";
*algoMode = "CBC";
*algoPadding = "NoPadding";
} else if ( type == "des-cbc-pkcs7" ) {
*algoName = "DES";
*algoMode = "CBC";
*algoPadding = "PKCS7";
} else if ( type == "des-cfb" ) {
*algoName = "DES";
*algoMode = "CFB";
*algoPadding = "NoPadding";
} else if ( type == "des-ofb" ) {
*algoName = "DES";
*algoMode = "OFB";
*algoPadding = "NoPadding";
} else if ( type == "tripledes-ecb" ) {
*algoName = "TripleDES";
*algoMode = "ECB";
*algoPadding = "NoPadding";
}
}
//-----------------------------------------------------------
class BotanCipherContext : public QCA::CipherContext
{
public:
BotanCipherContext( const QString &algo, const QString &mode, const QString &padding,
QCA::Provider *p, const QString &type) : QCA::CipherContext(p, type)
BotanCipherContext( QCA::Provider *p, const QString &type) : QCA::CipherContext(p, type)
{
m_algoName = algo.toStdString();
m_algoMode = mode.toStdString();
m_algoPadding = padding.toStdString();
qcaCipherToBotanCipher( type, &m_algoName, &m_algoMode, &m_algoPadding );
}
void setup(QCA::Direction dir,
@ -463,34 +560,24 @@ public:
return "qca-botan";
}
QStringList features() const override
const QStringList &pbkdfTypes() const
{
static QStringList list;
if (list.isEmpty()) {
list += "random";
list += "md2";
list += "md4";
list += "md5";
list += "sha1";
list += "sha256";
list += "sha384";
list += "sha512";
list += "ripemd160";
list += "hmac(md5)";
list += "hmac(sha1)";
// HMAC with SHA2 doesn't appear to work correctly in Botan.
// list += "hmac(sha256)";
// list += "hmac(sha384)";
// list += "hmac(sha512)";
list += "hmac(ripemd160)";
list += "pbkdf1(sha1)";
std::unique_ptr<BotanPBKDFContext> pbkdf1md2(new BotanPBKDFContext( qcaPbkdfToBotanPbkdf("pbkdf1(md2)"), nullptr, "pbkdf1(md2)"));
if (pbkdf1md2->isOk())
list += "pbkdf1(md2)";
list += "pbkdf2(sha1)";
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
list += "hkdf(sha256)";
#endif
}
return list;
}
const QStringList &cipherTypes() const
{
static QStringList supported;
if (supported.isEmpty()) {
QStringList list;
list += "aes128-ecb";
list += "aes128-cbc";
list += "aes128-cfb";
@ -515,6 +602,46 @@ public:
list += "blowfish-cbc-pkcs7";
list += "blowfish-cfb";
list += "blowfish-ofb";
for (const QString &cipher : qAsConst(list)) {
std::string algoName, algoMode, algoPadding;
qcaCipherToBotanCipher(cipher, &algoName, &algoMode, &algoPadding);
try {
std::unique_ptr<Botan::Keyed_Filter> enc(Botan::get_cipher(algoName+'/'+algoMode+'/'+algoPadding, Botan::ENCRYPTION));
std::unique_ptr<Botan::Keyed_Filter> dec(Botan::get_cipher(algoName+'/'+algoMode+'/'+algoPadding, Botan::DECRYPTION));
supported += cipher;
} catch (Botan::Exception& e) {
}
}
}
return supported;
}
QStringList features() const override
{
static QStringList list;
if (list.isEmpty()) {
list += "random";
list += "md2";
list += "md4";
list += "md5";
list += "sha1";
list += "sha256";
list += "sha384";
list += "sha512";
list += "ripemd160";
list += "hmac(md5)";
list += "hmac(sha1)";
// HMAC with SHA2 doesn't appear to work correctly in Botan.
// list += "hmac(sha256)";
// list += "hmac(sha384)";
// list += "hmac(sha512)";
list += "hmac(ripemd160)";
list += pbkdfTypes();
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
list += "hkdf(sha256)";
#endif
list += cipherTypes();
}
return list;
}
@ -551,62 +678,16 @@ public:
return new BotanHMACContext( QString("SHA-512"), this, type );
else if ( type == "hmac(ripemd160)" )
return new BotanHMACContext( QString("RIPEMD-160"), this, type );
else if ( type.startsWith(QLatin1String("pbkdf")) )
else if ( pbkdfTypes().contains(type) )
return new BotanPBKDFContext( qcaPbkdfToBotanPbkdf(type), this, type );
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
else if ( type == "hkdf(sha256)" )
return new BotanHKDFContext( QString("SHA-256"), this, type );
#endif
else if ( type == "aes128-ecb" )
return new BotanCipherContext( QString("AES-128"), QString("ECB"), QString("NoPadding"), this, type );
else if ( type == "aes128-cbc" )
return new BotanCipherContext( QString("AES-128"), QString("CBC"), QString("NoPadding"), this, type );
else if ( type == "aes128-cfb" )
return new BotanCipherContext( QString("AES-128"), QString("CFB"), QString("NoPadding"), this, type );
else if ( type == "aes128-ofb" )
return new BotanCipherContext( QString("AES-128"), QString("OFB"), QString("NoPadding"), this, type );
else if ( type == "aes192-ecb" )
return new BotanCipherContext( QString("AES-192"), QString("ECB"), QString("NoPadding"), this, type );
else if ( type == "aes192-cbc" )
return new BotanCipherContext( QString("AES-192"), QString("CBC"), QString("NoPadding"), this, type );
else if ( type == "aes192-cfb" )
return new BotanCipherContext( QString("AES-192"), QString("CFB"), QString("NoPadding"), this, type );
else if ( type == "aes192-ofb" )
return new BotanCipherContext( QString("AES-192"), QString("OFB"), QString("NoPadding"), this, type );
else if ( type == "aes256-ecb" )
return new BotanCipherContext( QString("AES-256"), QString("ECB"), QString("NoPadding"), this, type );
else if ( type == "aes256-cbc" )
return new BotanCipherContext( QString("AES-256"), QString("CBC"), QString("NoPadding"), this, type );
else if ( type == "aes256-cfb" )
return new BotanCipherContext( QString("AES-256"), QString("CFB"), QString("NoPadding"), this, type );
else if ( type == "aes256-ofb" )
return new BotanCipherContext( QString("AES-256"), QString("OFB"), QString("NoPadding"), this, type );
else if ( type == "blowfish-ecb" )
return new BotanCipherContext( QString("Blowfish"), QString("ECB"), QString("NoPadding"), this, type );
else if ( type == "blowfish-cbc" )
return new BotanCipherContext( QString("Blowfish"), QString("CBC"), QString("NoPadding"), this, type );
else if ( type == "blowfish-cbc-pkcs7" )
return new BotanCipherContext( QString("Blowfish"), QString("CBC"), QString("PKCS7"), this, type );
else if ( type == "blowfish-cfb" )
return new BotanCipherContext( QString("Blowfish"), QString("CFB"), QString("NoPadding"), this, type );
else if ( type == "blowfish-ofb" )
return new BotanCipherContext( QString("Blowfish"), QString("OFB"), QString("NoPadding"), this, type );
else if ( type == "des-ecb" )
return new BotanCipherContext( QString("DES"), QString("ECB"), QString("NoPadding"), this, type );
else if ( type == "des-ecb-pkcs7" )
return new BotanCipherContext( QString("DES"), QString("ECB"), QString("PKCS7"), this, type );
else if ( type == "des-cbc" )
return new BotanCipherContext( QString("DES"), QString("CBC"), QString("NoPadding"), this, type );
else if ( type == "des-cbc-pkcs7" )
return new BotanCipherContext( QString("DES"), QString("CBC"), QString("PKCS7"), this, type );
else if ( type == "des-cfb" )
return new BotanCipherContext( QString("DES"), QString("CFB"), QString("NoPadding"), this, type );
else if ( type == "des-ofb" )
return new BotanCipherContext( QString("DES"), QString("OFB"), QString("NoPadding"), this, type );
else if ( type == "tripledes-ecb" )
return new BotanCipherContext( QString("TripleDES"), QString("ECB"), QString("NoPadding"), this, type );
else if ( cipherTypes().contains( type ) )
return new BotanCipherContext( this, type );
else
return 0;
return nullptr;
}
private:
#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)