aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-26 11:38:01 -0500
committerJack Lloyd <[email protected]>2016-11-26 11:38:01 -0500
commit345f0881bc44b7a8344ea943e96b1dad4a8d484b (patch)
treed7d30b2e13abe660713eafed3e034ebf1494e7f8 /src
parentd695dfadc0daf8290d344f82697d456fd011d153 (diff)
Add test for various functions previously missed (T::clone, PBKDF::name, AEAD::output_length)
Fix a bug in CCM, GCM, and OCB decryption which caused `output_length(tag_size())` to fail even though empty plaintexts are certainly defined for all three modes.
Diffstat (limited to 'src')
-rw-r--r--src/lib/modes/aead/ccm/ccm.h2
-rw-r--r--src/lib/modes/aead/gcm/gcm.h2
-rw-r--r--src/lib/modes/aead/ocb/ocb.h2
-rw-r--r--src/tests/data/pbkdf/pbkdf1.vec2
-rw-r--r--src/tests/data/pbkdf/pbkdf2.vec8
-rw-r--r--src/tests/test_aead.cpp4
-rw-r--r--src/tests/test_block.cpp11
-rw-r--r--src/tests/test_compression.cpp2
-rw-r--r--src/tests/test_hash.cpp9
-rw-r--r--src/tests/test_kdf.cpp5
-rw-r--r--src/tests/test_mac.cpp9
-rw-r--r--src/tests/test_pbkdf.cpp12
-rw-r--r--src/tests/test_pubkey.cpp3
-rw-r--r--src/tests/test_stream.cpp12
-rw-r--r--src/tests/tests.cpp12
-rw-r--r--src/tests/tests.h2
16 files changed, 79 insertions, 18 deletions
diff --git a/src/lib/modes/aead/ccm/ccm.h b/src/lib/modes/aead/ccm/ccm.h
index 2a17595e7..9795354fc 100644
--- a/src/lib/modes/aead/ccm/ccm.h
+++ b/src/lib/modes/aead/ccm/ccm.h
@@ -116,7 +116,7 @@ class BOTAN_DLL CCM_Decryption final : public CCM_Mode
size_t output_length(size_t input_length) const override
{
- BOTAN_ASSERT(input_length > tag_size(), "Sufficient input");
+ BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
return input_length - tag_size();
}
diff --git a/src/lib/modes/aead/gcm/gcm.h b/src/lib/modes/aead/gcm/gcm.h
index 463e69a3b..65b6b0474 100644
--- a/src/lib/modes/aead/gcm/gcm.h
+++ b/src/lib/modes/aead/gcm/gcm.h
@@ -95,7 +95,7 @@ class BOTAN_DLL GCM_Decryption final : public GCM_Mode
size_t output_length(size_t input_length) const override
{
- BOTAN_ASSERT(input_length > tag_size(), "Sufficient input");
+ BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
return input_length - tag_size();
}
diff --git a/src/lib/modes/aead/ocb/ocb.h b/src/lib/modes/aead/ocb/ocb.h
index ce9d29f1b..dfdb8c18c 100644
--- a/src/lib/modes/aead/ocb/ocb.h
+++ b/src/lib/modes/aead/ocb/ocb.h
@@ -107,7 +107,7 @@ class BOTAN_DLL OCB_Decryption final : public OCB_Mode
size_t output_length(size_t input_length) const override
{
- BOTAN_ASSERT(input_length > tag_size(), "Sufficient input");
+ BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
return input_length - tag_size();
}
diff --git a/src/tests/data/pbkdf/pbkdf1.vec b/src/tests/data/pbkdf/pbkdf1.vec
index ebcad175b..a0eeba6e5 100644
--- a/src/tests/data/pbkdf/pbkdf1.vec
+++ b/src/tests/data/pbkdf/pbkdf1.vec
@@ -1,4 +1,4 @@
-[PBKDF1(SHA-1)]
+[PBKDF1(SHA-160)]
Salt = 40AC5837560251C275AF5E30A6A3074E57CED38E
Iterations = 6
Passphrase = ftlkfbxdtbjbvllvbwiw
diff --git a/src/tests/data/pbkdf/pbkdf2.vec b/src/tests/data/pbkdf/pbkdf2.vec
index 6a027721a..c8a5356be 100644
--- a/src/tests/data/pbkdf/pbkdf2.vec
+++ b/src/tests/data/pbkdf/pbkdf2.vec
@@ -1,4 +1,4 @@
-[PBKDF2(SHA-1)]
+[PBKDF2(HMAC(SHA-160))]
Salt = 0001020304050607
Iterations = 10000
Passphrase =
@@ -59,21 +59,21 @@ Passphrase = gwrxpqxumsdsmbmhfhmfdcvlcvngzkig
OutputLen = 64
Output = 4C9DB7BA24955225D5B845F65EF24EF1B0C6E86F2E39C8DDAA4B8ABD26082D1F350381FADEAEB560DC447AFC68A6B47E6EA1E7412F6CF7B2D82342FCCD11D3B4
-[PBKDF2(SHA-256)]
+[PBKDF2(HMAC(SHA-256))]
Salt = 0001020304050607
Iterations = 10000
Passphrase = xyz
OutputLen = 48
Output = DEFD2987FA26A4672F4D16D98398432AD95E896BF619F6A6B8D4ED1FAF98E8B531B39FFB66966D0E115A6CD8E70B72D0
-[PBKDF2(SHA-384)]
+[PBKDF2(HMAC(SHA-384))]
Salt = 0001020304050607
Iterations = 10000
Passphrase = xyz
OutputLen = 48
Output = 47A3AE920B24EDAA2BB53155808554B13FAB58DF62B81F043D9812E9F2881164DF20BBFFA54E5EE2489FA183B6718A74
-[PBKDF2(SHA-512)]
+[PBKDF2(HMAC(SHA-512))]
Salt = 0001020304050607
Iterations = 10000
Passphrase = xyz
diff --git a/src/tests/test_aead.cpp b/src/tests/test_aead.cpp
index 24352a536..ed94d75ba 100644
--- a/src/tests/test_aead.cpp
+++ b/src/tests/test_aead.cpp
@@ -32,6 +32,8 @@ class AEAD_Tests : public Text_Based_Test
std::unique_ptr<Botan::AEAD_Mode> enc(Botan::get_aead(algo, Botan::ENCRYPTION));
+ result.test_eq("AEAD encrypt output_length is correct", enc->output_length(input.size()), expected.size());
+
// First some tests for reset() to make sure it resets what we need it to
// set garbage values
enc->set_key(mutate_vec(key));
@@ -132,6 +134,8 @@ class AEAD_Tests : public Text_Based_Test
std::unique_ptr<Botan::AEAD_Mode> dec(Botan::get_aead(algo, Botan::DECRYPTION));
+ result.test_eq("AEAD decrypt output_length is correct", dec->output_length(input.size()), expected.size());
+
// First some tests for reset() to make sure it resets what we need it to
// set garbage values
dec->set_key(mutate_vec(key));
diff --git a/src/tests/test_block.cpp b/src/tests/test_block.cpp
index 82ab0618d..48d6230c3 100644
--- a/src/tests/test_block.cpp
+++ b/src/tests/test_block.cpp
@@ -36,7 +36,7 @@ class Block_Cipher_Tests : public Text_Based_Test
if(!cipher)
{
- result.note_missing(algo + " from " + provider_ask);
+ result.test_failure("Cipher " + algo + " supported by " + provider_ask + " but not found");
continue;
}
@@ -54,6 +54,14 @@ class Block_Cipher_Tests : public Text_Based_Test
cipher->clear();
cipher->set_key(key);
+
+ // Test that clone works and does not affect parent object
+ std::unique_ptr<Botan::BlockCipher> clone(cipher->clone());
+ result.confirm("Clone has different pointer", cipher.get() != clone.get());
+ result.test_eq("Clone has same name", cipher->name(), clone->name());
+ clone->set_key(Test::rng().random_vec(cipher->maximum_keylength()));
+
+ // have called set_key on clone: process input values
std::vector<uint8_t> buf = input;
cipher->encrypt(buf);
@@ -67,6 +75,7 @@ class Block_Cipher_Tests : public Text_Based_Test
cipher->clear();
result.test_eq(provider, "decrypt", buf, input);
+
}
return result;
diff --git a/src/tests/test_compression.cpp b/src/tests/test_compression.cpp
index d8dcdb410..e5db055a5 100644
--- a/src/tests/test_compression.cpp
+++ b/src/tests/test_compression.cpp
@@ -75,6 +75,8 @@ class Compression_Tests : public Test
continue;
}
+ result.test_ne("Not the same name", c->name(), d->name());
+
const Botan::secure_vector<uint8_t> empty;
const Botan::secure_vector<uint8_t> all_zeros(text_len, 0);
const Botan::secure_vector<uint8_t> random_binary = Test::rng().random_vec(text_len);
diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp
index dc93bb4d1..2ff74d1f2 100644
--- a/src/tests/test_hash.cpp
+++ b/src/tests/test_hash.cpp
@@ -38,7 +38,7 @@ class Hash_Function_Tests : public Text_Based_Test
if(!hash)
{
- result.note_missing(algo + " from " + provider_ask);
+ result.test_failure("Hash " + algo + " supported by " + provider_ask + " but not found");
continue;
}
@@ -63,12 +63,19 @@ class Hash_Function_Tests : 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() > 1)
{
hash->update(input[0]);
hash->update(&input[1], input.size() - 1);
result.test_eq(provider, "hashing split", hash->final(), expected);
}
+
+ if(hash->hash_block_size() > 0)
+ {
+ // GOST-34.11 uses 32 byte block
+ result.test_gte("If hash_block_size is set, it is large", hash->hash_block_size(), 32);
+ }
}
return result;
diff --git a/src/tests/test_kdf.cpp b/src/tests/test_kdf.cpp
index 50034de0e..ec3688fef 100644
--- a/src/tests/test_kdf.cpp
+++ b/src/tests/test_kdf.cpp
@@ -44,6 +44,11 @@ class KDF_KAT_Tests : public Text_Based_Test
result.test_eq("name", kdf->name(), kdf_name);
result.test_eq("derived key", kdf->derive_key(outlen, secret, salt, label), expected);
+ // Test that clone works
+ std::unique_ptr<Botan::KDF> clone(kdf->clone());
+ result.confirm("Clone has different pointer", kdf.get() != clone.get());
+ result.test_eq("Clone has same name", kdf->name(), clone->name());
+
return result;
}
diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp
index 33972fabc..be897143b 100644
--- a/src/tests/test_mac.cpp
+++ b/src/tests/test_mac.cpp
@@ -46,7 +46,7 @@ class Message_Auth_Tests : public Text_Based_Test
if(!mac)
{
- result.note_missing(algo + " from " + provider_ask);
+ result.test_failure("MAC " + algo + " supported by " + provider_ask + " but not found");
continue;
}
@@ -72,6 +72,13 @@ class Message_Auth_Tests : public Text_Based_Test
mac->start(iv);
mac->update(input);
+ // Test that clone works and does not affect parent object
+ std::unique_ptr<Botan::MessageAuthenticationCode> clone(mac->clone());
+ result.confirm("Clone has different pointer", mac.get() != clone.get());
+ result.test_eq("Clone has same name", mac->name(), clone->name());
+ clone->set_key(key);
+ clone->update(Test::rng().random_vec(32));
+
result.test_eq(provider + " correct mac", mac->verify_mac(expected.data(), expected.size()), true);
if(input.size() > 2)
diff --git a/src/tests/test_pbkdf.cpp b/src/tests/test_pbkdf.cpp
index 393a96243..af2cdd498 100644
--- a/src/tests/test_pbkdf.cpp
+++ b/src/tests/test_pbkdf.cpp
@@ -24,6 +24,12 @@ class PBKDF_KAT_Tests : public Text_Based_Test
Test::Result run_one_test(const std::string& pbkdf_name, const VarMap& vars) override
{
+ const size_t outlen = get_req_sz(vars, "OutputLen");
+ const size_t iterations = get_req_sz(vars, "Iterations");
+ const std::vector<uint8_t> salt = get_req_bin(vars, "Salt");
+ const std::string passphrase = get_req_str(vars, "Passphrase");
+ const std::vector<uint8_t> expected = get_req_bin(vars, "Output");
+
Test::Result result(pbkdf_name);
std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create(pbkdf_name));
@@ -33,11 +39,7 @@ class PBKDF_KAT_Tests : public Text_Based_Test
return result;
}
- const size_t outlen = get_req_sz(vars, "OutputLen");
- const size_t iterations = get_req_sz(vars, "Iterations");
- const std::vector<uint8_t> salt = get_req_bin(vars, "Salt");
- const std::string passphrase = get_req_str(vars, "Passphrase");
- const std::vector<uint8_t> expected = get_req_bin(vars, "Output");
+ result.test_eq("Expected name", pbkdf->name(), pbkdf_name);
const Botan::secure_vector<byte> derived =
pbkdf->derive_key(outlen, passphrase, salt.data(), salt.size(), iterations).bits_of();
diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp
index 654021805..c2c1bb256 100644
--- a/src/tests/test_pubkey.cpp
+++ b/src/tests/test_pubkey.cpp
@@ -373,6 +373,9 @@ std::vector<Test::Result> PK_Key_Generation_Test::run()
result.confirm("Key passes self tests", key.check_key(Test::rng(), true));
+ result.test_gte("Key has reasonable estimated strength (lower)", key.estimated_strength(), 64);
+ result.test_lt("Key has reasonable estimated strength (upper)", key.estimated_strength(), 512);
+
// Test PEM public key round trips OK
try
{
diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp
index d53777593..0af0be12c 100644
--- a/src/tests/test_stream.cpp
+++ b/src/tests/test_stream.cpp
@@ -47,7 +47,7 @@ class Stream_Cipher_Tests : public Text_Based_Test
if(!cipher)
{
- result.note_missing(algo + " from " + provider_ask);
+ result.test_failure("Stream " + algo + " supported by " + provider_ask + " but not found");
continue;
}
@@ -58,6 +58,8 @@ class Stream_Cipher_Tests : public Text_Based_Test
if(nonce.size())
{
+ if(!cipher->valid_iv_length(nonce.size()))
+ throw Test_Error("Invalid nonce for " + algo);
cipher->set_iv(nonce.data(), nonce.size());
}
else
@@ -67,12 +69,20 @@ class Stream_Cipher_Tests : public Text_Based_Test
* null/empty nonce. Call set_iv with such a nonce to make sure
* set_iv accepts it.
*/
+ if(!cipher->valid_iv_length(0))
+ throw Test_Error("Stream cipher " + algo + " requires nonce but none provided");
cipher->set_iv(nullptr, 0);
}
if (seek != 0)
cipher->seek(seek);
+ // Test that clone works and does not affect parent object
+ std::unique_ptr<Botan::StreamCipher> clone(cipher->clone());
+ result.confirm("Clone has different pointer", cipher.get() != clone.get());
+ result.test_eq("Clone has same name", cipher->name(), clone->name());
+ clone->set_key(Test::rng().random_vec(cipher->maximum_keylength()));
+
std::vector<uint8_t> buf = input;
cipher->encrypt(buf);
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index 1fe41428e..f922c99a6 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -264,6 +264,16 @@ bool Test::Result::test_gte(const std::string& what, size_t produced, size_t exp
return test_success();
}
+bool Test::Result::test_ne(const std::string& what, const std::string& str1, const std::string& str2)
+ {
+ if(str1 != str2)
+ {
+ return test_success(str1 + " != " + str2);
+ }
+
+ return test_failure(who() + " " + what + " produced matching strings " + str1);
+ }
+
bool Test::Result::test_ne(const std::string& what, size_t produced, size_t expected)
{
if(produced != expected)
@@ -272,7 +282,7 @@ bool Test::Result::test_ne(const std::string& what, size_t produced, size_t expe
}
std::ostringstream err;
- err << who() << " " << what << " produced " << produced << " prohibited value";
+ err << who() << " " << what << " produced " << produced << " unexpected value";
return test_failure(err.str());
}
diff --git a/src/tests/tests.h b/src/tests/tests.h
index 7d168be72..733e948ea 100644
--- a/src/tests/tests.h
+++ b/src/tests/tests.h
@@ -230,6 +230,8 @@ class Test
bool test_ne(const std::string& what, size_t produced, size_t expected);
+ bool test_ne(const std::string& what, const std::string& str1, const std::string& str2);
+
#if defined(BOTAN_HAS_BIGINT)
bool test_eq(const std::string& what, const BigInt& produced, const BigInt& expected);
bool test_ne(const std::string& what, const BigInt& produced, const BigInt& expected);