aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-10-26 20:31:30 -0400
committerJack Lloyd <[email protected]>2017-10-26 22:26:15 -0400
commite6d45052efedfe49e99adb6318aaf56e0a9e8d7b (patch)
treec6c3ccd3cff3d04285940bf1d518c809e0653947 /src
parent315b002ecf00f6b6bb0f0d5200d1f39a83527e8f (diff)
Add checks that keyed algorithms are actually keyed before use
Previously calling update or encrypt without calling set_key first would result in invalid outputs or else crashing.
Diffstat (limited to 'src')
-rw-r--r--src/lib/base/sym_algo.h7
-rw-r--r--src/lib/block/aes/aes.cpp12
-rw-r--r--src/lib/block/blowfish/blowfish.cpp4
-rw-r--r--src/lib/block/camellia/camellia.cpp6
-rw-r--r--src/lib/block/cast/cast128.cpp4
-rw-r--r--src/lib/block/cast/cast256.cpp4
-rw-r--r--src/lib/block/des/des.cpp8
-rw-r--r--src/lib/block/des/desx.cpp4
-rw-r--r--src/lib/block/gost_28147/gost_28147.cpp4
-rw-r--r--src/lib/block/idea/idea.cpp4
-rw-r--r--src/lib/block/kasumi/kasumi.cpp4
-rw-r--r--src/lib/block/lion/lion.cpp16
-rw-r--r--src/lib/block/misty1/misty1.cpp4
-rw-r--r--src/lib/block/noekeon/noekeon.cpp4
-rw-r--r--src/lib/block/seed/seed.cpp4
-rw-r--r--src/lib/block/serpent/serpent.cpp4
-rw-r--r--src/lib/block/shacal2/shacal2.cpp4
-rw-r--r--src/lib/block/sm4/sm4.cpp4
-rw-r--r--src/lib/block/threefish/threefish.cpp6
-rw-r--r--src/lib/block/twofish/twofish.cpp4
-rw-r--r--src/lib/block/xtea/xtea.cpp4
-rw-r--r--src/lib/mac/cbc_mac/cbc_mac.cpp9
-rw-r--r--src/lib/mac/hmac/hmac.cpp2
-rw-r--r--src/lib/mac/poly1305/poly1305.cpp4
-rw-r--r--src/lib/mac/siphash/siphash.cpp6
-rw-r--r--src/lib/mac/x919_mac/x919_mac.cpp8
-rw-r--r--src/lib/modes/aead/gcm/ghash.cpp2
-rw-r--r--src/lib/prov/openssl/openssl_block.cpp15
-rw-r--r--src/lib/prov/openssl/openssl_rc4.cpp5
-rw-r--r--src/lib/stream/chacha/chacha.cpp2
-rw-r--r--src/lib/stream/ctr/ctr.cpp7
-rw-r--r--src/lib/stream/rc4/rc4.cpp2
-rw-r--r--src/lib/stream/salsa20/salsa20.cpp2
-rw-r--r--src/lib/stream/shake_cipher/shake_cipher.cpp10
-rw-r--r--src/lib/utils/exceptn.cpp4
-rw-r--r--src/lib/utils/exceptn.h6
-rw-r--r--src/tests/test_block.cpp47
-rw-r--r--src/tests/test_hash.cpp13
-rw-r--r--src/tests/test_mac.cpp35
-rw-r--r--src/tests/test_stream.cpp23
40 files changed, 287 insertions, 30 deletions
diff --git a/src/lib/base/sym_algo.h b/src/lib/base/sym_algo.h
index a596f5932..a0ebac626 100644
--- a/src/lib/base/sym_algo.h
+++ b/src/lib/base/sym_algo.h
@@ -91,6 +91,13 @@ class BOTAN_PUBLIC_API(2,0) SymmetricAlgorithm
*/
virtual std::string name() const = 0;
+ protected:
+ void verify_key_set(bool cond) const
+ {
+ if(cond == false)
+ throw Key_Not_Set(name());
+ }
+
private:
/**
* Run the key schedule
diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp
index 8a82ad942..9c375c362 100644
--- a/src/lib/block/aes/aes.cpp
+++ b/src/lib/block/aes/aes.cpp
@@ -452,6 +452,8 @@ size_t AES_256::parallelism() const { return aes_parallelism(); }
void AES_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
@@ -478,6 +480,8 @@ void AES_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
void AES_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
@@ -531,6 +535,8 @@ void AES_128::clear()
void AES_192::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
@@ -557,6 +563,8 @@ void AES_192::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
void AES_192::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
@@ -610,6 +618,8 @@ void AES_192::clear()
void AES_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
@@ -636,6 +646,8 @@ void AES_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
void AES_256::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
diff --git a/src/lib/block/blowfish/blowfish.cpp b/src/lib/block/blowfish/blowfish.cpp
index 68d73cafd..c2634bba4 100644
--- a/src/lib/block/blowfish/blowfish.cpp
+++ b/src/lib/block/blowfish/blowfish.cpp
@@ -197,6 +197,8 @@ const uint32_t S_INIT[1024] = {
*/
void Blowfish::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_S.empty() == false);
+
const uint32_t* S1 = &m_S[0];
const uint32_t* S2 = &m_S[256];
const uint32_t* S3 = &m_S[512];
@@ -229,6 +231,8 @@ void Blowfish::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void Blowfish::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_S.empty() == false);
+
const uint32_t* S1 = &m_S[0];
const uint32_t* S2 = &m_S[256];
const uint32_t* S3 = &m_S[512];
diff --git a/src/lib/block/camellia/camellia.cpp b/src/lib/block/camellia/camellia.cpp
index 89db6f8b9..9281cd859 100644
--- a/src/lib/block/camellia/camellia.cpp
+++ b/src/lib/block/camellia/camellia.cpp
@@ -854,31 +854,37 @@ void key_schedule(secure_vector<uint64_t>& SK, const uint8_t key[], size_t lengt
void Camellia_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::encrypt(in, out, blocks, m_SK, 9);
}
void Camellia_192::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::encrypt(in, out, blocks, m_SK, 12);
}
void Camellia_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::encrypt(in, out, blocks, m_SK, 12);
}
void Camellia_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::decrypt(in, out, blocks, m_SK, 9);
}
void Camellia_192::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::decrypt(in, out, blocks, m_SK, 12);
}
void Camellia_256::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SK.empty() == false);
Camellia_F::decrypt(in, out, blocks, m_SK, 12);
}
diff --git a/src/lib/block/cast/cast128.cpp b/src/lib/block/cast/cast128.cpp
index 5ad732eb3..f7910f034 100644
--- a/src/lib/block/cast/cast128.cpp
+++ b/src/lib/block/cast/cast128.cpp
@@ -50,6 +50,8 @@ inline uint32_t R3(uint32_t R, uint32_t MK, uint8_t RK)
*/
void CAST_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
{
uint32_t L, R;
@@ -81,6 +83,8 @@ void CAST_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void CAST_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
{
uint32_t L, R;
diff --git a/src/lib/block/cast/cast256.cpp b/src/lib/block/cast/cast256.cpp
index b4aa49166..cd5175dd7 100644
--- a/src/lib/block/cast/cast256.cpp
+++ b/src/lib/block/cast/cast256.cpp
@@ -50,6 +50,8 @@ void round3(uint32_t& out, uint32_t in, uint32_t MK, uint32_t RK)
*/
void CAST_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t A = load_be<uint32_t>(in, 0);
@@ -94,6 +96,8 @@ void CAST_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void CAST_256::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t A = load_be<uint32_t>(in, 0);
diff --git a/src/lib/block/des/des.cpp b/src/lib/block/des/des.cpp
index 15c2adb66..2881cfa9a 100644
--- a/src/lib/block/des/des.cpp
+++ b/src/lib/block/des/des.cpp
@@ -144,6 +144,8 @@ void des_decrypt(uint32_t& L, uint32_t& R,
*/
void DES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
for(size_t i = 0; i < blocks; ++i)
{
uint64_t T = (DES_IPTAB1[in[8*i+0]] ) | (DES_IPTAB1[in[8*i+1]] << 1) |
@@ -171,6 +173,8 @@ void DES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void DES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
for(size_t i = 0; i < blocks; ++i)
{
uint64_t T = (DES_IPTAB1[in[BLOCK_SIZE*i+0]] ) | (DES_IPTAB1[in[BLOCK_SIZE*i+1]] << 1) |
@@ -213,6 +217,8 @@ void DES::clear()
*/
void TripleDES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint64_t T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
@@ -246,6 +252,8 @@ void TripleDES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) cons
*/
void TripleDES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint64_t T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
diff --git a/src/lib/block/des/desx.cpp b/src/lib/block/des/desx.cpp
index 7c9995523..e869b3ebf 100644
--- a/src/lib/block/des/desx.cpp
+++ b/src/lib/block/des/desx.cpp
@@ -14,6 +14,8 @@ namespace Botan {
*/
void DESX::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_K1.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
xor_buf(out, in, m_K1.data(), BLOCK_SIZE);
@@ -30,6 +32,8 @@ void DESX::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void DESX::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_K1.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
xor_buf(out, in, m_K2.data(), BLOCK_SIZE);
diff --git a/src/lib/block/gost_28147/gost_28147.cpp b/src/lib/block/gost_28147/gost_28147.cpp
index ffe9b5d66..b46d162de 100644
--- a/src/lib/block/gost_28147/gost_28147.cpp
+++ b/src/lib/block/gost_28147/gost_28147.cpp
@@ -111,6 +111,8 @@ std::string GOST_28147_89::name() const
*/
void GOST_28147_89::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t N1 = load_le<uint32_t>(in, 0);
@@ -141,6 +143,8 @@ void GOST_28147_89::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks)
*/
void GOST_28147_89::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t N1 = load_le<uint32_t>(in, 0);
diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp
index c0364b325..26bd24690 100644
--- a/src/lib/block/idea/idea.cpp
+++ b/src/lib/block/idea/idea.cpp
@@ -137,6 +137,8 @@ std::string IDEA::provider() const
*/
void IDEA::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
#if defined(BOTAN_HAS_IDEA_SSE2)
if(CPUID::has_sse2())
{
@@ -158,6 +160,8 @@ void IDEA::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void IDEA::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
#if defined(BOTAN_HAS_IDEA_SSE2)
if(CPUID::has_sse2())
{
diff --git a/src/lib/block/kasumi/kasumi.cpp b/src/lib/block/kasumi/kasumi.cpp
index a9b5d8274..a40a9d9d5 100644
--- a/src/lib/block/kasumi/kasumi.cpp
+++ b/src/lib/block/kasumi/kasumi.cpp
@@ -110,6 +110,8 @@ uint16_t FI(uint16_t I, uint16_t K)
*/
void KASUMI::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint16_t B0 = load_be<uint16_t>(in, 0);
@@ -154,6 +156,8 @@ void KASUMI::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void KASUMI::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint16_t B0 = load_be<uint16_t>(in, 0);
diff --git a/src/lib/block/lion/lion.cpp b/src/lib/block/lion/lion.cpp
index 7959de585..cd7d25d9c 100644
--- a/src/lib/block/lion/lion.cpp
+++ b/src/lib/block/lion/lion.cpp
@@ -14,6 +14,8 @@ namespace Botan {
*/
void Lion::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_key1.empty() == false);
+
const size_t LEFT_SIZE = left_size();
const size_t RIGHT_SIZE = right_size();
@@ -44,6 +46,8 @@ void Lion::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void Lion::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_key1.empty() == false);
+
const size_t LEFT_SIZE = left_size();
const size_t RIGHT_SIZE = right_size();
@@ -77,6 +81,11 @@ void Lion::key_schedule(const uint8_t key[], size_t length)
clear();
const size_t half = length / 2;
+
+ m_key1.resize(left_size());
+ m_key2.resize(left_size());
+ clear_mem(m_key1.data(), m_key1.size());
+ clear_mem(m_key2.data(), m_key2.size());
copy_mem(m_key1.data(), key, half);
copy_mem(m_key2.data(), key + half, half);
}
@@ -104,8 +113,8 @@ BlockCipher* Lion::clone() const
*/
void Lion::clear()
{
- zeroise(m_key1);
- zeroise(m_key2);
+ zap(m_key1);
+ zap(m_key2);
m_hash->clear();
m_cipher->clear();
}
@@ -123,9 +132,6 @@ Lion::Lion(HashFunction* hash, StreamCipher* cipher, size_t bs) :
if(!m_cipher->valid_keylength(left_size()))
throw Invalid_Argument(name() + ": This stream/hash combo is invalid");
-
- m_key1.resize(left_size());
- m_key2.resize(left_size());
}
}
diff --git a/src/lib/block/misty1/misty1.cpp b/src/lib/block/misty1/misty1.cpp
index eaef86c8c..e7ebffa6e 100644
--- a/src/lib/block/misty1/misty1.cpp
+++ b/src/lib/block/misty1/misty1.cpp
@@ -103,6 +103,8 @@ uint16_t FI(uint16_t input, uint16_t key7, uint16_t key9)
*/
void MISTY1::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint16_t B0 = load_be<uint16_t>(in, 0);
@@ -153,6 +155,8 @@ void MISTY1::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void MISTY1::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint16_t B0 = load_be<uint16_t>(in, 2);
diff --git a/src/lib/block/noekeon/noekeon.cpp b/src/lib/block/noekeon/noekeon.cpp
index a7f60a0fd..5fd5be82a 100644
--- a/src/lib/block/noekeon/noekeon.cpp
+++ b/src/lib/block/noekeon/noekeon.cpp
@@ -110,6 +110,8 @@ const uint8_t Noekeon::RC[] = {
*/
void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
#if defined(BOTAN_HAS_NOEKEON_SIMD)
if(CPUID::has_simd_32())
{
@@ -161,6 +163,8 @@ void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_DK.empty() == false);
+
#if defined(BOTAN_HAS_NOEKEON_SIMD)
if(CPUID::has_simd_32())
{
diff --git a/src/lib/block/seed/seed.cpp b/src/lib/block/seed/seed.cpp
index 700283042..81194e44a 100644
--- a/src/lib/block/seed/seed.cpp
+++ b/src/lib/block/seed/seed.cpp
@@ -208,6 +208,8 @@ inline uint32_t SEED_G(uint32_t X)
*/
void SEED::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_K.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t B0 = load_be<uint32_t>(in, 0);
@@ -246,6 +248,8 @@ void SEED::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void SEED::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_K.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t B0 = load_be<uint32_t>(in, 0);
diff --git a/src/lib/block/serpent/serpent.cpp b/src/lib/block/serpent/serpent.cpp
index 6e1d79766..39968e87e 100644
--- a/src/lib/block/serpent/serpent.cpp
+++ b/src/lib/block/serpent/serpent.cpp
@@ -57,6 +57,8 @@ inline void i_transform(uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3)
*/
void Serpent::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
#if defined(BOTAN_HAS_SERPENT_SIMD)
if(CPUID::has_simd_32())
{
@@ -117,6 +119,8 @@ void Serpent::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void Serpent::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_round_key.empty() == false);
+
#if defined(BOTAN_HAS_SERPENT_SIMD)
if(CPUID::has_simd_32())
{
diff --git a/src/lib/block/shacal2/shacal2.cpp b/src/lib/block/shacal2/shacal2.cpp
index 12c87c426..dd4224ed4 100644
--- a/src/lib/block/shacal2/shacal2.cpp
+++ b/src/lib/block/shacal2/shacal2.cpp
@@ -44,6 +44,8 @@ inline void SHACAL2_Rev(uint32_t A, uint32_t B, uint32_t C, uint32_t& D,
*/
void SHACAL2::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
#if defined(BOTAN_HAS_SHACAL2_X86)
if(CPUID::has_intel_sha())
{
@@ -99,6 +101,8 @@ void SHACAL2::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void SHACAL2::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
#if defined(BOTAN_HAS_SHACAL2_SIMD)
if(CPUID::has_simd_32())
{
diff --git a/src/lib/block/sm4/sm4.cpp b/src/lib/block/sm4/sm4.cpp
index 2902d514c..7c409d40f 100644
--- a/src/lib/block/sm4/sm4.cpp
+++ b/src/lib/block/sm4/sm4.cpp
@@ -124,6 +124,8 @@ inline uint32_t SM4_Tp(uint32_t b)
*/
void SM4::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t B0 = load_be<uint32_t>(in, 0);
@@ -152,6 +154,8 @@ void SM4::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void SM4::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_RK.empty() == false);
+
for(size_t i = 0; i != blocks; ++i)
{
uint32_t B0 = load_be<uint32_t>(in, 0);
diff --git a/src/lib/block/threefish/threefish.cpp b/src/lib/block/threefish/threefish.cpp
index 804d6003a..60f793d64 100644
--- a/src/lib/block/threefish/threefish.cpp
+++ b/src/lib/block/threefish/threefish.cpp
@@ -124,8 +124,7 @@ std::string Threefish_512::provider() const
void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
- BOTAN_ASSERT(m_K.size() == 9, "Key was set");
- BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
+ verify_key_set(m_K.empty() == false);
#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
if(CPUID::has_avx2())
@@ -161,8 +160,7 @@ void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks)
void Threefish_512::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
- BOTAN_ASSERT(m_K.size() == 9, "Key was set");
- BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
+ verify_key_set(m_K.empty() == false);
#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
if(CPUID::has_avx2())
diff --git a/src/lib/block/twofish/twofish.cpp b/src/lib/block/twofish/twofish.cpp
index 3a09af8da..496c31a36 100644
--- a/src/lib/block/twofish/twofish.cpp
+++ b/src/lib/block/twofish/twofish.cpp
@@ -19,6 +19,8 @@ namespace Botan {
*/
void Twofish::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SB.empty() == false);
+
BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
{
uint32_t A, B, C, D;
@@ -70,6 +72,8 @@ void Twofish::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void Twofish::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_SB.empty() == false);
+
BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
{
uint32_t A, B, C, D;
diff --git a/src/lib/block/xtea/xtea.cpp b/src/lib/block/xtea/xtea.cpp
index b53de448b..679ad4cfb 100644
--- a/src/lib/block/xtea/xtea.cpp
+++ b/src/lib/block/xtea/xtea.cpp
@@ -15,6 +15,8 @@ namespace Botan {
*/
void XTEA::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
const uint32_t* EK = &m_EK[0];
const size_t blocks4 = blocks / 4;
@@ -61,6 +63,8 @@ void XTEA::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
*/
void XTEA::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
{
+ verify_key_set(m_EK.empty() == false);
+
const uint32_t* EK = &m_EK[0];
const size_t blocks4 = blocks / 4;
diff --git a/src/lib/mac/cbc_mac/cbc_mac.cpp b/src/lib/mac/cbc_mac/cbc_mac.cpp
index b272fe3bc..ba403b564 100644
--- a/src/lib/mac/cbc_mac/cbc_mac.cpp
+++ b/src/lib/mac/cbc_mac/cbc_mac.cpp
@@ -14,6 +14,8 @@ namespace Botan {
*/
void CBC_MAC::add_data(const uint8_t input[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
size_t xored = std::min(output_length() - m_position, length);
xor_buf(&m_state[m_position], input, xored);
m_position += xored;
@@ -41,6 +43,8 @@ void CBC_MAC::add_data(const uint8_t input[], size_t length)
*/
void CBC_MAC::final_result(uint8_t mac[])
{
+ verify_key_set(m_state.empty() == false);
+
if(m_position)
m_cipher->encrypt(m_state);
@@ -54,6 +58,7 @@ void CBC_MAC::final_result(uint8_t mac[])
*/
void CBC_MAC::key_schedule(const uint8_t key[], size_t length)
{
+ m_state.resize(m_cipher->block_size());
m_cipher->set_key(key, length);
}
@@ -63,7 +68,7 @@ void CBC_MAC::key_schedule(const uint8_t key[], size_t length)
void CBC_MAC::clear()
{
m_cipher->clear();
- zeroise(m_state);
+ zap(m_state);
m_position = 0;
}
@@ -87,7 +92,7 @@ MessageAuthenticationCode* CBC_MAC::clone() const
* CBC-MAC Constructor
*/
CBC_MAC::CBC_MAC(BlockCipher* cipher) :
- m_cipher(cipher), m_state(cipher->block_size())
+ m_cipher(cipher)
{
}
diff --git a/src/lib/mac/hmac/hmac.cpp b/src/lib/mac/hmac/hmac.cpp
index 32f62f0c2..244946d88 100644
--- a/src/lib/mac/hmac/hmac.cpp
+++ b/src/lib/mac/hmac/hmac.cpp
@@ -15,6 +15,7 @@ namespace Botan {
*/
void HMAC::add_data(const uint8_t input[], size_t length)
{
+ verify_key_set(m_ikey.empty() == false);
m_hash->update(input, length);
}
@@ -23,6 +24,7 @@ void HMAC::add_data(const uint8_t input[], size_t length)
*/
void HMAC::final_result(uint8_t mac[])
{
+ verify_key_set(m_okey.empty() == false);
m_hash->final(mac);
m_hash->update(m_okey);
m_hash->update(mac, output_length());
diff --git a/src/lib/mac/poly1305/poly1305.cpp b/src/lib/mac/poly1305/poly1305.cpp
index 9fe0bad0a..639aa88c0 100644
--- a/src/lib/mac/poly1305/poly1305.cpp
+++ b/src/lib/mac/poly1305/poly1305.cpp
@@ -155,7 +155,7 @@ void Poly1305::key_schedule(const uint8_t key[], size_t)
void Poly1305::add_data(const uint8_t input[], size_t length)
{
- BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized");
+ verify_key_set(m_poly.size() == 8);
if(m_buf_pos)
{
@@ -182,7 +182,7 @@ void Poly1305::add_data(const uint8_t input[], size_t length)
void Poly1305::final_result(uint8_t out[])
{
- BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized");
+ verify_key_set(m_poly.size() == 8);
if(m_buf_pos != 0)
{
diff --git a/src/lib/mac/siphash/siphash.cpp b/src/lib/mac/siphash/siphash.cpp
index 255a35493..80acc4d60 100644
--- a/src/lib/mac/siphash/siphash.cpp
+++ b/src/lib/mac/siphash/siphash.cpp
@@ -39,6 +39,8 @@ void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r)
void SipHash::add_data(const uint8_t input[], size_t length)
{
+ verify_key_set(m_V.empty() == false);
+
// SipHash counts the message length mod 256
m_words += static_cast<uint8_t>(length);
@@ -76,6 +78,8 @@ void SipHash::add_data(const uint8_t input[], size_t length)
void SipHash::final_result(uint8_t mac[])
{
+ verify_key_set(m_V.empty() == false);
+
m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<uint64_t>(m_words) << 56);
SipRounds(m_mbuf, m_V, m_C);
@@ -103,7 +107,7 @@ void SipHash::key_schedule(const uint8_t key[], size_t)
void SipHash::clear()
{
- m_V.clear();
+ zap(m_V);
m_mbuf = 0;
m_mbuf_pos = 0;
m_words = 0;
diff --git a/src/lib/mac/x919_mac/x919_mac.cpp b/src/lib/mac/x919_mac/x919_mac.cpp
index 189108377..ef1e78602 100644
--- a/src/lib/mac/x919_mac/x919_mac.cpp
+++ b/src/lib/mac/x919_mac/x919_mac.cpp
@@ -14,6 +14,8 @@ namespace Botan {
*/
void ANSI_X919_MAC::add_data(const uint8_t input[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
size_t xored = std::min(8 - m_position, length);
xor_buf(&m_state[m_position], input, xored);
m_position += xored;
@@ -53,6 +55,8 @@ void ANSI_X919_MAC::final_result(uint8_t mac[])
*/
void ANSI_X919_MAC::key_schedule(const uint8_t key[], size_t length)
{
+ m_state.resize(8);
+
m_des1->set_key(key, 8);
if(length == 16)
@@ -68,7 +72,7 @@ void ANSI_X919_MAC::clear()
{
m_des1->clear();
m_des2->clear();
- zeroise(m_state);
+ zap(m_state);
m_position = 0;
}
@@ -88,7 +92,7 @@ MessageAuthenticationCode* ANSI_X919_MAC::clone() const
ANSI_X919_MAC::ANSI_X919_MAC() :
m_des1(BlockCipher::create("DES")),
m_des2(BlockCipher::create("DES")),
- m_state(8), m_position(0)
+ m_position(0)
{
}
diff --git a/src/lib/modes/aead/gcm/ghash.cpp b/src/lib/modes/aead/gcm/ghash.cpp
index 51477f43a..482eec335 100644
--- a/src/lib/modes/aead/gcm/ghash.cpp
+++ b/src/lib/modes/aead/gcm/ghash.cpp
@@ -199,7 +199,7 @@ void GHASH::set_associated_data(const uint8_t input[], size_t length)
void GHASH::update_associated_data(const uint8_t ad[], size_t length)
{
- BOTAN_ASSERT(m_ghash.size() == GCM_BS, "Key was set");
+ verify_key_set(m_ghash.size() == GCM_BS);
m_ad_len += length;
ghash_update(m_ghash, ad, length);
}
diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp
index 33cd9b8cc..3cf203961 100644
--- a/src/lib/prov/openssl/openssl_block.cpp
+++ b/src/lib/prov/openssl/openssl_block.cpp
@@ -36,6 +36,7 @@ class OpenSSL_BlockCipher final : public BlockCipher
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
{
+ verify_key_set(m_key_set);
int out_len = 0;
if(!EVP_EncryptUpdate(m_encrypt, out, &out_len, in, blocks * m_block_sz))
throw OpenSSL_Error("EVP_EncryptUpdate");
@@ -43,6 +44,7 @@ class OpenSSL_BlockCipher final : public BlockCipher
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
{
+ verify_key_set(m_key_set);
int out_len = 0;
if(!EVP_DecryptUpdate(m_decrypt, out, &out_len, in, blocks * m_block_sz))
throw OpenSSL_Error("EVP_DecryptUpdate");
@@ -55,13 +57,15 @@ class OpenSSL_BlockCipher final : public BlockCipher
std::string m_cipher_name;
EVP_CIPHER_CTX *m_encrypt;
EVP_CIPHER_CTX *m_decrypt;
+ bool m_key_set;
};
OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
const EVP_CIPHER* algo) :
m_block_sz(EVP_CIPHER_block_size(algo)),
m_cipher_key_spec(EVP_CIPHER_key_length(algo)),
- m_cipher_name(algo_name)
+ m_cipher_name(algo_name),
+ m_key_set(false)
{
if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
@@ -92,7 +96,8 @@ OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
size_t key_mod) :
m_block_sz(EVP_CIPHER_block_size(algo)),
m_cipher_key_spec(key_min, key_max, key_mod),
- m_cipher_name(algo_name)
+ m_cipher_name(algo_name),
+ m_key_set(false)
{
if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
@@ -134,15 +139,19 @@ void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length)
full_key += std::make_pair(key, 8);
}
else
+ {
if(EVP_CIPHER_CTX_set_key_length(m_encrypt, length) == 0 ||
EVP_CIPHER_CTX_set_key_length(m_decrypt, length) == 0)
throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " +
m_cipher_name);
+ }
if(!EVP_EncryptInit_ex(m_encrypt, nullptr, nullptr, full_key.data(), nullptr))
throw OpenSSL_Error("EVP_EncryptInit_ex");
if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr))
throw OpenSSL_Error("EVP_DecryptInit_ex");
+
+ m_key_set = true;
}
/*
@@ -164,6 +173,8 @@ void OpenSSL_BlockCipher::clear()
{
const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_encrypt);
+ m_key_set = false;
+
if(!EVP_CIPHER_CTX_cleanup(m_encrypt))
throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt");
if(!EVP_CIPHER_CTX_cleanup(m_decrypt))
diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp
index 5fb2a68f5..b24760f45 100644
--- a/src/lib/prov/openssl/openssl_rc4.cpp
+++ b/src/lib/prov/openssl/openssl_rc4.cpp
@@ -21,7 +21,7 @@ namespace {
class OpenSSL_RC4 final : public StreamCipher
{
public:
- void clear() override { clear_mem(&m_rc4, 1); }
+ void clear() override { clear_mem(&m_rc4, 1); m_key_set = false; }
std::string provider() const override { return "openssl"; }
@@ -61,6 +61,7 @@ class OpenSSL_RC4 final : public StreamCipher
private:
void cipher(const uint8_t in[], uint8_t out[], size_t length) override
{
+ verify_key_set(m_key_set);
::RC4(&m_rc4, length, in, out);
}
@@ -70,10 +71,12 @@ class OpenSSL_RC4 final : public StreamCipher
uint8_t d = 0;
for(size_t i = 0; i != m_skip; ++i)
::RC4(&m_rc4, 1, &d, &d);
+ m_key_set = true;
}
size_t m_skip;
RC4_KEY m_rc4;
+ bool m_key_set;
};
}
diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp
index 0bbb47bcb..52e5eaaf4 100644
--- a/src/lib/stream/chacha/chacha.cpp
+++ b/src/lib/stream/chacha/chacha.cpp
@@ -116,6 +116,8 @@ void ChaCha::chacha_x4(uint8_t output[64*4], uint32_t input[16], size_t rounds)
*/
void ChaCha::cipher(const uint8_t in[], uint8_t out[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
while(length >= m_buffer.size() - m_position)
{
xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp
index 99a589bb9..463119caf 100644
--- a/src/lib/stream/ctr/ctr.cpp
+++ b/src/lib/stream/ctr/ctr.cpp
@@ -17,7 +17,6 @@ CTR_BE::CTR_BE(BlockCipher* ciph) :
m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
m_counter(m_cipher->parallel_bytes()),
m_pad(m_counter.size()),
- m_iv(m_cipher->block_size()),
m_pad_pos(0)
{
}
@@ -29,7 +28,6 @@ CTR_BE::CTR_BE(BlockCipher* cipher, size_t ctr_size) :
m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
m_counter(m_cipher->parallel_bytes()),
m_pad(m_counter.size()),
- m_iv(m_cipher->block_size()),
m_pad_pos(0)
{
if(m_ctr_size < 4 || m_ctr_size > m_block_size)
@@ -41,7 +39,7 @@ void CTR_BE::clear()
m_cipher->clear();
zeroise(m_pad);
zeroise(m_counter);
- zeroise(m_iv);
+ zap(m_iv);
m_pad_pos = 0;
}
@@ -64,6 +62,8 @@ std::string CTR_BE::name() const
void CTR_BE::cipher(const uint8_t in[], uint8_t out[], size_t length)
{
+ verify_key_set(m_iv.empty() == false);
+
const uint8_t* pad_bits = &m_pad[0];
const size_t pad_size = m_pad.size();
@@ -105,6 +105,7 @@ void CTR_BE::set_iv(const uint8_t iv[], size_t iv_len)
if(!valid_iv_length(iv_len))
throw Invalid_IV_Length(name(), iv_len);
+ m_iv.resize(m_cipher->block_size());
zeroise(m_iv);
buffer_insert(m_iv, 0, iv, iv_len);
diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp
index 208b2f560..60565d445 100644
--- a/src/lib/stream/rc4/rc4.cpp
+++ b/src/lib/stream/rc4/rc4.cpp
@@ -15,6 +15,8 @@ namespace Botan {
*/
void RC4::cipher(const uint8_t in[], uint8_t out[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
while(length >= m_buffer.size() - m_position)
{
xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp
index e27b2d2bb..3f93cee94 100644
--- a/src/lib/stream/salsa20/salsa20.cpp
+++ b/src/lib/stream/salsa20/salsa20.cpp
@@ -103,6 +103,8 @@ void salsa20(uint8_t output[64], const uint32_t input[16])
*/
void Salsa20::cipher(const uint8_t in[], uint8_t out[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
while(length >= m_buffer.size() - m_position)
{
xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
diff --git a/src/lib/stream/shake_cipher/shake_cipher.cpp b/src/lib/stream/shake_cipher/shake_cipher.cpp
index 4f79777f4..72a8fd885 100644
--- a/src/lib/stream/shake_cipher/shake_cipher.cpp
+++ b/src/lib/stream/shake_cipher/shake_cipher.cpp
@@ -12,13 +12,13 @@
namespace Botan {
SHAKE_128_Cipher::SHAKE_128_Cipher() :
- m_state(25),
- m_buffer((1600 - 256) / 8),
m_buf_pos(0)
{}
void SHAKE_128_Cipher::cipher(const uint8_t in[], uint8_t out[], size_t length)
{
+ verify_key_set(m_state.empty() == false);
+
while(length >= m_buffer.size() - m_buf_pos)
{
xor_buf(out, in, &m_buffer[m_buf_pos], m_buffer.size() - m_buf_pos);
@@ -37,6 +37,8 @@ void SHAKE_128_Cipher::cipher(const uint8_t in[], uint8_t out[], size_t length)
void SHAKE_128_Cipher::key_schedule(const uint8_t key[], size_t length)
{
+ m_state.resize(25);
+ m_buffer.resize((1600 - 256) / 8);
zeroise(m_state);
for(size_t i = 0; i < length/8; ++i)
@@ -53,8 +55,8 @@ void SHAKE_128_Cipher::key_schedule(const uint8_t key[], size_t length)
void SHAKE_128_Cipher::clear()
{
- zeroise(m_state);
- zeroise(m_buffer);
+ zap(m_state);
+ zap(m_buffer);
m_buf_pos = 0;
}
diff --git a/src/lib/utils/exceptn.cpp b/src/lib/utils/exceptn.cpp
index 240742602..3fa7dfd3e 100644
--- a/src/lib/utils/exceptn.cpp
+++ b/src/lib/utils/exceptn.cpp
@@ -44,6 +44,10 @@ Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, size_t bad_len) :
" is invalid for " + mode)
{}
+Key_Not_Set::Key_Not_Set(const std::string& algo) :
+ Invalid_State("Key not set in " + algo)
+ {}
+
Policy_Violation::Policy_Violation(const std::string& err) :
Invalid_State("Policy violation: " + err) {}
diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h
index b9b94a8f8..e82889b5a 100644
--- a/src/lib/utils/exceptn.h
+++ b/src/lib/utils/exceptn.h
@@ -62,6 +62,12 @@ class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception
explicit Invalid_State(const std::string& err) : Exception(err) {}
};
+class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State
+ {
+ public:
+ explicit Key_Not_Set(const std::string& algo);
+ };
+
/**
* Lookup_Error Exception
*/
diff --git a/src/tests/test_block.cpp b/src/tests/test_block.cpp
index 535556a90..02115b66a 100644
--- a/src/tests/test_block.cpp
+++ b/src/tests/test_block.cpp
@@ -53,8 +53,31 @@ class Block_Cipher_Tests final : public Text_Based_Test
result.test_gte(provider, cipher->block_size(), 8);
result.test_gte(provider, cipher->parallel_bytes(), cipher->block_size() * cipher->parallelism());
+ // Test that trying to encrypt or decrypt with now key set throws Botan::Invalid_State
+ try
+ {
+ std::vector<uint8_t> block(cipher->block_size());
+ cipher->encrypt(block);
+ result.test_failure("Was able to encrypt without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to encrypt with no key set fails");
+ }
+
+ try
+ {
+ std::vector<uint8_t> block(cipher->block_size());
+ cipher->decrypt(block);
+ result.test_failure("Was able to decrypt without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to encrypt with no key set fails");
+ }
+
// Test to make sure clear() resets what we need it to
- cipher->set_key(Test::rng().random_vec(cipher->key_spec().minimum_keylength()));
+ cipher->set_key(Test::rng().random_vec(cipher->key_spec().maximum_keylength()));
Botan::secure_vector<uint8_t> garbage = Test::rng().random_vec(cipher->block_size());
cipher->encrypt(garbage);
cipher->clear();
@@ -89,6 +112,28 @@ class Block_Cipher_Tests final : public Text_Based_Test
result.test_eq(provider, "decrypt", buf, input);
+ try
+ {
+ std::vector<uint8_t> block(cipher->block_size());
+ cipher->encrypt(block);
+ result.test_failure("Was able to encrypt without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to encrypt with no key set (after clear) fails");
+ }
+
+ try
+ {
+ std::vector<uint8_t> block(cipher->block_size());
+ cipher->decrypt(block);
+ result.test_failure("Was able to decrypt without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to decrypt with no key set (after clear) fails");
+ }
+
}
return result;
diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp
index 2116cade4..39b13de32 100644
--- a/src/tests/test_hash.cpp
+++ b/src/tests/test_hash.cpp
@@ -68,7 +68,6 @@ class Hash_Function_Tests final : public Text_Based_Test
result.test_eq(provider, "hashing after clear", hash->final(), expected);
- // TODO: feed in random pieces to fully test buffering
if(input.size() > 5)
{
hash->update(input[0]);
@@ -77,7 +76,17 @@ class Hash_Function_Tests final : public Text_Based_Test
// verify fork copy doesn't affect original computation
fork->update(&input[1], input.size() - 2);
- hash->update(&input[1], input.size() - 1);
+ size_t so_far = 1;
+ while(so_far < input.size())
+ {
+ size_t take = Test::rng().next_byte() % (input.size() - so_far);
+
+ if(input.size() - so_far == 1)
+ take = 1;
+
+ hash->update(&input[so_far], take);
+ so_far += take;
+ }
result.test_eq(provider, "hashing split", hash->final(), expected);
fork->update(&input[input.size() - 1], 1);
diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp
index f4e3e4268..18ba82b30 100644
--- a/src/tests/test_mac.cpp
+++ b/src/tests/test_mac.cpp
@@ -59,6 +59,17 @@ class Message_Auth_Tests final : public Text_Based_Test
result.test_is_nonempty("provider", provider);
result.test_eq(provider, mac->name(), algo);
+ try
+ {
+ std::vector<uint8_t> buf(128);
+ mac->update(buf.data(), buf.size());
+ result.test_failure("Was able to MAC without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to MAC with no key set fails");
+ }
+
mac->set_key(key);
mac->start(iv);
@@ -108,6 +119,30 @@ class Message_Auth_Tests final : public Text_Based_Test
result.test_eq(provider + " split mac", mac->verify_mac(expected.data(), expected.size()), true);
}
+
+ mac->clear();
+
+ try
+ {
+ std::vector<uint8_t> buf(128);
+ mac->update(buf.data(), buf.size());
+ result.test_failure("Was able to MAC without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to MAC with no key set (after clear) fails");
+ }
+
+ try
+ {
+ std::vector<uint8_t> buf(mac->output_length());
+ mac->final(buf.data());
+ result.test_failure("Was able to MAC without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to MAC with no key set (after clear) fails");
+ }
}
return result;
diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp
index 50012fe97..357b8c769 100644
--- a/src/tests/test_stream.cpp
+++ b/src/tests/test_stream.cpp
@@ -56,6 +56,18 @@ class Stream_Cipher_Tests final : public Text_Based_Test
const std::string provider(cipher->provider());
result.test_is_nonempty("provider", provider);
result.test_eq(provider, cipher->name(), algo);
+
+ try
+ {
+ std::vector<uint8_t> buf(128);
+ cipher->cipher1(buf.data(), buf.size());
+ result.test_failure("Was able to encrypt without a key being set");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to encrypt with no key set fails");
+ }
+
cipher->set_key(key);
if(nonce.size())
@@ -96,6 +108,17 @@ class Stream_Cipher_Tests final : public Text_Based_Test
cipher->clear();
+ try
+ {
+ std::vector<uint8_t> buf(128);
+ cipher->cipher1(buf.data(), buf.size());
+ result.test_failure("Was able to encrypt without a key being set (after clear)");
+ }
+ catch(Botan::Invalid_State&)
+ {
+ result.test_success("Trying to encrypt with no key set (after clear) fails");
+ }
+
result.test_eq(provider, "encrypt", buf, expected);
}