aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/block/blowfish/blowfish.cpp59
-rw-r--r--src/lib/block/blowfish/blowfish.h16
-rw-r--r--src/lib/block/blowfish/info.txt2
-rw-r--r--src/lib/ffi/ffi.h54
-rw-r--r--src/lib/ffi/ffi_block.cpp6
-rw-r--r--src/lib/ffi/ffi_cipher.cpp6
-rw-r--r--src/lib/ffi/ffi_hash.cpp6
-rw-r--r--src/lib/ffi/ffi_mac.cpp6
-rw-r--r--src/lib/ffi/ffi_rng.cpp5
-rw-r--r--src/lib/math/mp/mp_core.cpp22
-rw-r--r--src/lib/modes/aead/ccm/ccm.cpp11
-rw-r--r--src/lib/modes/aead/ccm/ccm.h2
-rw-r--r--src/lib/passhash/bcrypt/bcrypt.cpp18
-rw-r--r--src/lib/rng/rng.h3
-rwxr-xr-xsrc/scripts/ci/setup_travis.sh4
-rw-r--r--src/tests/data/aead/ccm.vec124
-rw-r--r--src/tests/data/salted_blowfish.vec46
-rw-r--r--src/tests/test_blowfish.cpp46
-rw-r--r--src/tests/test_ffi.cpp64
19 files changed, 429 insertions, 71 deletions
diff --git a/src/lib/block/blowfish/blowfish.cpp b/src/lib/block/blowfish/blowfish.cpp
index 0bdc0ed92..9e906c80f 100644
--- a/src/lib/block/blowfish/blowfish.cpp
+++ b/src/lib/block/blowfish/blowfish.cpp
@@ -1,6 +1,6 @@
/*
* Blowfish
-* (C) 1999-2011 Jack Lloyd
+* (C) 1999-2011,2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -319,39 +319,36 @@ void Blowfish::key_schedule(const uint8_t key[], size_t length)
m_S.resize(1024);
copy_mem(m_S.data(), S_INIT, 1024);
- const uint8_t null_salt[16] = { 0 };
-
- key_expansion(key, length, null_salt);
+ key_expansion(key, length, nullptr, 0);
}
void Blowfish::key_expansion(const uint8_t key[],
size_t length,
- const uint8_t salt[16])
+ const uint8_t salt[],
+ size_t salt_length)
{
+ BOTAN_ASSERT_NOMSG(salt_length % 4 == 0);
+
for(size_t i = 0, j = 0; i != 18; ++i, j += 4)
m_P[i] ^= make_uint32(key[(j ) % length], key[(j+1) % length],
key[(j+2) % length], key[(j+3) % length]);
+ const size_t P_salt_offset = (salt_length > 0) ? 18 % (salt_length / 4) : 0;
+
uint32_t L = 0, R = 0;
- generate_sbox(m_P, L, R, salt, 0);
- generate_sbox(m_S, L, R, salt, 2);
+ generate_sbox(m_P, L, R, salt, salt_length, 0);
+ generate_sbox(m_S, L, R, salt, salt_length, P_salt_offset);
}
/*
* Modified key schedule used for bcrypt password hashing
*/
-void Blowfish::eks_key_schedule(const uint8_t key[], size_t length,
- const uint8_t salt[16], size_t workfactor)
+void Blowfish::salted_set_key(const uint8_t key[], size_t length,
+ const uint8_t salt[], size_t salt_length,
+ size_t workfactor)
{
-
- /*
- * On a 4 GHz Skylake, workfactor == 18 takes about 15 seconds to
- * hash a password. This seems like a reasonable upper bound for the
- * time being.
- * Bcrypt allows up to work factor 31 (2^31 iterations)
- */
- BOTAN_ARG_CHECK(workfactor >= 4 && workfactor <= 18,
- "Invalid bcrypt work factor");
+ BOTAN_ARG_CHECK(salt_length > 0 && salt_length % 4 == 0,
+ "Invalid salt length for Blowfish salted key schedule");
if(length > 72)
{
@@ -364,15 +361,17 @@ void Blowfish::eks_key_schedule(const uint8_t key[], size_t length,
m_S.resize(1024);
copy_mem(m_S.data(), S_INIT, 1024);
- key_expansion(key, length, salt);
-
- const uint8_t null_salt[16] = { 0 };
- const size_t rounds = static_cast<size_t>(1) << workfactor;
+ key_expansion(key, length, salt, salt_length);
- for(size_t r = 0; r != rounds; ++r)
+ if(workfactor > 0)
{
- key_expansion(key, length, null_salt);
- key_expansion(salt, 16, null_salt);
+ const size_t rounds = static_cast<size_t>(1) << workfactor;
+
+ for(size_t r = 0; r != rounds; ++r)
+ {
+ key_expansion(key, length, nullptr, 0);
+ key_expansion(salt, salt_length, nullptr, 0);
+ }
}
}
@@ -381,13 +380,17 @@ void Blowfish::eks_key_schedule(const uint8_t key[], size_t length,
*/
void Blowfish::generate_sbox(secure_vector<uint32_t>& box,
uint32_t& L, uint32_t& R,
- const uint8_t salt[16],
+ const uint8_t salt[],
+ size_t salt_length,
size_t salt_off) const
{
for(size_t i = 0; i != box.size(); i += 2)
{
- L ^= load_be<uint32_t>(salt, (i + salt_off) % 4);
- R ^= load_be<uint32_t>(salt, (i + salt_off + 1) % 4);
+ if(salt_length > 0)
+ {
+ L ^= load_be<uint32_t>(salt, (i + salt_off) % (salt_length / 4));
+ R ^= load_be<uint32_t>(salt, (i + salt_off + 1) % (salt_length / 4));
+ }
for(size_t r = 0; r != 16; r += 2)
{
diff --git a/src/lib/block/blowfish/blowfish.h b/src/lib/block/blowfish/blowfish.h
index fa84e2a3d..d5c318752 100644
--- a/src/lib/block/blowfish/blowfish.h
+++ b/src/lib/block/blowfish/blowfish.h
@@ -24,8 +24,16 @@ class BOTAN_PUBLIC_API(2,0) Blowfish final : public Block_Cipher_Fixed_Params<8,
/**
* Modified EKSBlowfish key schedule, used for bcrypt password hashing
*/
+ void salted_set_key(const uint8_t key[], size_t key_length,
+ const uint8_t salt[], size_t salt_length,
+ size_t workfactor);
+
+ BOTAN_DEPRECATED("Use Blowfish::salted_set_key taking salt length")
void eks_key_schedule(const uint8_t key[], size_t key_length,
- const uint8_t salt[16], size_t workfactor);
+ const uint8_t salt[16], size_t workfactor)
+ {
+ salted_set_key(key, key_length, salt, 16, workfactor);
+ }
void clear() override;
std::string name() const override { return "Blowfish"; }
@@ -35,11 +43,13 @@ class BOTAN_PUBLIC_API(2,0) Blowfish final : public Block_Cipher_Fixed_Params<8,
void key_expansion(const uint8_t key[],
size_t key_length,
- const uint8_t salt[16]);
+ const uint8_t salt[],
+ size_t salt_length);
void generate_sbox(secure_vector<uint32_t>& box,
uint32_t& L, uint32_t& R,
- const uint8_t salt[16],
+ const uint8_t salt[],
+ size_t salt_length,
size_t salt_off) const;
secure_vector<uint32_t> m_S, m_P;
diff --git a/src/lib/block/blowfish/info.txt b/src/lib/block/blowfish/info.txt
index e028a5559..cc72634df 100644
--- a/src/lib/block/blowfish/info.txt
+++ b/src/lib/block/blowfish/info.txt
@@ -1,3 +1,3 @@
<defines>
-BLOWFISH -> 20131128
+BLOWFISH -> 20180718
</defines>
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index f62fe17d2..676a451f1 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -214,6 +214,18 @@ BOTAN_PUBLIC_API(2,0) int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t ou
BOTAN_PUBLIC_API(2,0) int botan_rng_reseed(botan_rng_t rng, size_t bits);
/**
+* Add some seed material to a random number generator
+*
+* @param rng rng object
+* @param entropy the data to add
+* @param entropy_len length of entropy buffer
+* @return 0 on success, a negative value on failure
+*/
+BOTAN_PUBLIC_API(2,8) int botan_rng_add_entropy(botan_rng_t rng,
+ const uint8_t* entropy,
+ size_t entropy_len);
+
+/**
* Frees all resources of the random number generator object
* @param rng rng object
* @return always returns 0
@@ -296,9 +308,12 @@ BOTAN_PUBLIC_API(2,0) int botan_hash_clear(botan_hash_t hash);
BOTAN_PUBLIC_API(2,0) int botan_hash_destroy(botan_hash_t hash);
/**
-* TODO has no implementation
+* Get the name of this hash function
+* @param hash the object to read
+* @param name output buffer
+* @param name_len on input, the length of buffer, on success the number of bytes written
*/
-BOTAN_PUBLIC_API(2,0) int botan_hash_name(botan_hash_t hash, char* name, size_t name_len);
+BOTAN_PUBLIC_API(2,8) int botan_hash_name(botan_hash_t hash, char* name, size_t* name_len);
/*
* Message Authentication type
@@ -360,6 +375,14 @@ BOTAN_PUBLIC_API(2,0) int botan_mac_final(botan_mac_t mac, uint8_t out[]);
BOTAN_PUBLIC_API(2,0) int botan_mac_clear(botan_mac_t mac);
/**
+* Get the name of this MAC
+* @param mac the object to read
+* @param name output buffer
+* @param name_len on input, the length of buffer, on success the number of bytes written
+*/
+BOTAN_PUBLIC_API(2,8) int botan_mac_name(botan_mac_t mac, char* name, size_t* name_len);
+
+/**
* Frees all resources of the MAC object
* @param mac mac object
* @return always returns 0
@@ -377,6 +400,8 @@ typedef struct botan_cipher_struct* botan_cipher_t;
BOTAN_PUBLIC_API(2,0) int botan_cipher_init(botan_cipher_t* cipher, const char* name, uint32_t flags);
+BOTAN_PUBLIC_API(2,8) int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len);
+
BOTAN_PUBLIC_API(2,0) int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl);
BOTAN_PUBLIC_API(2,0) int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tag_size);
BOTAN_PUBLIC_API(2,0) int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl);
@@ -493,7 +518,7 @@ typedef struct botan_block_cipher_struct* botan_block_cipher_t;
* Initialize a block cipher object
*/
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_init(botan_block_cipher_t* bc,
- const char* cipher_name);
+ const char* cipher_name);
/**
* Destroy a block cipher object
@@ -510,7 +535,7 @@ BOTAN_PUBLIC_API(2,1) int botan_block_cipher_clear(botan_block_cipher_t bc);
* Set the key for a block cipher instance
*/
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_set_key(botan_block_cipher_t bc,
- const uint8_t key[], size_t len);
+ const uint8_t key[], size_t len);
/**
* Return the positive block size of this block cipher, or negative to
@@ -519,14 +544,23 @@ BOTAN_PUBLIC_API(2,1) int botan_block_cipher_set_key(botan_block_cipher_t bc,
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_block_size(botan_block_cipher_t bc);
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
- const uint8_t in[],
- uint8_t out[],
- size_t blocks);
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks);
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
- const uint8_t in[],
- uint8_t out[],
- size_t blocks);
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks);
+
+/**
+* Get the name of this block cipher
+* @param cipher the object to read
+* @param name output buffer
+* @param name_len on input, the length of buffer, on success the number of bytes written
+*/
+BOTAN_PUBLIC_API(2,8) int botan_block_cipher_name(botan_block_cipher_t cipher,
+ char* name, size_t* name_len);
/*
diff --git a/src/lib/ffi/ffi_block.cpp b/src/lib/ffi/ffi_block.cpp
index f3648430a..fad492fd4 100644
--- a/src/lib/ffi/ffi_block.cpp
+++ b/src/lib/ffi/ffi_block.cpp
@@ -79,4 +79,10 @@ int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.decrypt_n(in, out, blocks); });
}
+int botan_block_cipher_name(botan_block_cipher_t cipher, char* name, size_t* name_len)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, cipher, bc, {
+ return write_str_output(name, name_len, bc.name()); });
+ }
+
}
diff --git a/src/lib/ffi/ffi_cipher.cpp b/src/lib/ffi/ffi_cipher.cpp
index 871cbd31f..094656fd2 100644
--- a/src/lib/ffi/ffi_cipher.cpp
+++ b/src/lib/ffi/ffi_cipher.cpp
@@ -193,4 +193,10 @@ int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tl)
return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });
}
+int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len)
+ {
+ return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {
+ return write_str_output(name, name_len, c.name()); });
+ }
+
}
diff --git a/src/lib/ffi/ffi_hash.cpp b/src/lib/ffi/ffi_hash.cpp
index b5f9451d7..601d97c52 100644
--- a/src/lib/ffi/ffi_hash.cpp
+++ b/src/lib/ffi/ffi_hash.cpp
@@ -67,4 +67,10 @@ int botan_hash_copy_state(botan_hash_t* dest, const botan_hash_t source)
*dest = new botan_hash_struct(src.copy_state().release()); });
}
+int botan_hash_name(botan_hash_t hash, char* name, size_t* name_len)
+ {
+ return BOTAN_FFI_DO(Botan::HashFunction, hash, h, {
+ return write_str_output(name, name_len, h.name()); });
+ }
+
}
diff --git a/src/lib/ffi/ffi_mac.cpp b/src/lib/ffi/ffi_mac.cpp
index 22dbb2513..02ac7900c 100644
--- a/src/lib/ffi/ffi_mac.cpp
+++ b/src/lib/ffi/ffi_mac.cpp
@@ -61,4 +61,10 @@ int botan_mac_final(botan_mac_t mac, uint8_t out[])
return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, m, { m.final(out); });
}
+int botan_mac_name(botan_mac_t mac, char* name, size_t* name_len)
+ {
+ return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, m, {
+ return write_str_output(name, name_len, m.name()); });
+ }
+
}
diff --git a/src/lib/ffi/ffi_rng.cpp b/src/lib/ffi/ffi_rng.cpp
index 6c27b2e7e..8d97a39d8 100644
--- a/src/lib/ffi/ffi_rng.cpp
+++ b/src/lib/ffi/ffi_rng.cpp
@@ -51,4 +51,9 @@ int botan_rng_reseed(botan_rng_t rng, size_t bits)
return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, { r.reseed_from_rng(Botan::system_rng(), bits); });
}
+int botan_rng_add_entropy(botan_rng_t rng, const uint8_t* input, size_t len)
+ {
+ return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, { r.add_entropy(input, len); });
+ }
+
}
diff --git a/src/lib/math/mp/mp_core.cpp b/src/lib/math/mp/mp_core.cpp
index 2ae65e508..5dbf3558a 100644
--- a/src/lib/math/mp/mp_core.cpp
+++ b/src/lib/math/mp/mp_core.cpp
@@ -353,11 +353,33 @@ void bigint_shl1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
}
}
+namespace {
+
+void bigint_shift_right_1(word x[], size_t x_size)
+ {
+ word carry = 0;
+ size_t top = x_size;
+
+ while(top)
+ {
+ word w = x[top-1];
+ x[top-1] = (w >> 1) | carry;
+ carry = (w << (BOTAN_MP_WORD_BITS - 1));
+
+ top--;
+ }
+ }
+
+}
+
/*
* Single Operand Right Shift
*/
void bigint_shr1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
{
+ if(word_shift == 0 && bit_shift == 1)
+ return bigint_shift_right_1(x, x_size);
+
if(x_size < word_shift)
{
clear_mem(x, x_size);
diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp
index 410bd6910..b5a68a72e 100644
--- a/src/lib/modes/aead/ccm/ccm.cpp
+++ b/src/lib/modes/aead/ccm/ccm.cpp
@@ -1,6 +1,6 @@
/*
* CCM Mode Encryption
-* (C) 2013 Jack Lloyd
+* (C) 2013,2018 Jack Lloyd
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -113,16 +113,17 @@ size_t CCM_Mode::process(uint8_t buf[], size_t sz)
return 0; // no output until finished
}
-void CCM_Mode::encode_length(size_t len, uint8_t out[])
+void CCM_Mode::encode_length(uint64_t len, uint8_t out[])
{
const size_t len_bytes = L();
- BOTAN_ASSERT(len_bytes < sizeof(size_t), "Length field fits");
+ BOTAN_ASSERT_NOMSG(len_bytes >= 1 && len_bytes <= 8);
for(size_t i = 0; i != len_bytes; ++i)
- out[len_bytes-1-i] = get_byte(sizeof(size_t)-1-i, len);
+ out[len_bytes-1-i] = get_byte(sizeof(uint64_t)-1-i, len);
- BOTAN_ASSERT((len >> (len_bytes*8)) == 0, "Message length fits in field");
+ if(len_bytes < 8 && (len >> (len_bytes*8)) > 0)
+ throw Encoding_Error("CCM message length too long to encode in L field");
}
void CCM_Mode::inc(secure_vector<uint8_t>& C)
diff --git a/src/lib/modes/aead/ccm/ccm.h b/src/lib/modes/aead/ccm/ccm.h
index 4d4fe73e2..b819ac76e 100644
--- a/src/lib/modes/aead/ccm/ccm.h
+++ b/src/lib/modes/aead/ccm/ccm.h
@@ -48,7 +48,7 @@ class BOTAN_PUBLIC_API(2,0) CCM_Mode : public AEAD_Mode
const BlockCipher& cipher() const { return *m_cipher; }
- void encode_length(size_t len, uint8_t out[]);
+ void encode_length(uint64_t len, uint8_t out[]);
void inc(secure_vector<uint8_t>& C);
diff --git a/src/lib/passhash/bcrypt/bcrypt.cpp b/src/lib/passhash/bcrypt/bcrypt.cpp
index 5688df0e6..29bcc9d1b 100644
--- a/src/lib/passhash/bcrypt/bcrypt.cpp
+++ b/src/lib/passhash/bcrypt/bcrypt.cpp
@@ -92,6 +92,15 @@ std::string make_bcrypt(const std::string& pass,
uint16_t work_factor,
char version)
{
+ /*
+ * On a 4 GHz Skylake, workfactor == 18 takes about 15 seconds to
+ * hash a password. This seems like a reasonable upper bound for the
+ * time being.
+ * Bcrypt allows up to work factor 31 (2^31 iterations)
+ */
+ BOTAN_ARG_CHECK(work_factor >= 4 && work_factor <= 18,
+ "Invalid bcrypt work factor");
+
static const uint8_t BCRYPT_MAGIC[8*3] = {
0x4F, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6E, 0x42,
0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x53,
@@ -101,10 +110,11 @@ std::string make_bcrypt(const std::string& pass,
Blowfish blowfish;
// Include the trailing NULL byte, so we need c_str() not data()
- blowfish.eks_key_schedule(cast_char_ptr_to_uint8(pass.c_str()),
- pass.length() + 1,
- salt.data(),
- work_factor);
+ blowfish.salted_set_key(cast_char_ptr_to_uint8(pass.c_str()),
+ pass.length() + 1,
+ salt.data(),
+ salt.size(),
+ work_factor);
std::vector<uint8_t> ctext(BCRYPT_MAGIC, BCRYPT_MAGIC + 8*3);
diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h
index f6fa80df0..ec8557477 100644
--- a/src/lib/rng/rng.h
+++ b/src/lib/rng/rng.h
@@ -173,8 +173,7 @@ class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator
typedef RandomNumberGenerator RNG;
/**
-* Hardware_RNG has no members but exists to tag hardware RNG types
-* (PKCS11_RNG, TPM_RNG, RDRAND_RNG)
+* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, RDRAND_RNG)
*/
class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator
{
diff --git a/src/scripts/ci/setup_travis.sh b/src/scripts/ci/setup_travis.sh
index 52661494f..9c6c79012 100755
--- a/src/scripts/ci/setup_travis.sh
+++ b/src/scripts/ci/setup_travis.sh
@@ -36,10 +36,10 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
fi
elif [ "$BUILD_MODE" = "lint" ]; then
- pip install --user pylint
+ pip install --user pylint==1.9.2
sudo apt-get install python3-pip
- pip3 install --user pylint
+ pip3 install --user pylint==1.9.2
elif [ "$BUILD_MODE" = "coverage" ]; then
sudo apt-get -qq update
diff --git a/src/tests/data/aead/ccm.vec b/src/tests/data/aead/ccm.vec
index 23a74aec2..83aca12a2 100644
--- a/src/tests/data/aead/ccm.vec
+++ b/src/tests/data/aead/ccm.vec
@@ -48,3 +48,127 @@ Nonce = 0EC3AC452B547B9062AAC8FA
In = B6F345204526439DAF84998F380DCFB4B4167C959C04FF65
AD = 2F1821AA57E5278FFD33C17D46615B77363149DBC98470413F6543A6B749F2CA
Out = 9575E16F35DA3C88A19C26A7B762044F4D7BBBAFEFF05D754829E2A7752FA3A14890972884B511D8
+
+[AES-128/CCM(4,8)]
+# SP 800-38C Example 1
+Key = 404142434445464748494a4b4c4d4e4f
+Nonce = 10111213141516
+AD = 0001020304050607
+In = 20212223
+Out = 7162015b4dac255d
+
+[AES-128/CCM(6,7)]
+# SP 800-38C Example 2
+Key = 404142434445464748494a4b4c4d4e4f
+Nonce = 1011121314151617
+AD = 000102030405060708090a0b0c0d0e0f
+In = 202122232425262728292a2b2c2d2e2f
+Out = d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd
+
+[AES-128/CCM(8,3)]
+# SP 800-38C Example 3
+Key = 404142434445464748494a4b4c4d4e4f
+Nonce = 101112131415161718191a1b
+AD = 000102030405060708090a0b0c0d0e0f10111213
+In = 202122232425262728292a2b2c2d2e2f3031323334353637
+Out = e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951
+
+# From CVMC CAVS data Tue Mar 15 08:09:25 2011
+
+[AES-128/CCM(16,8)]
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+Nonce = 37667f334dce90
+AD = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+In = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+Out = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+[AES-128/CCM(16,7)]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+Nonce = 21fd9011d6d9484a
+AD = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+In = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+Out = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+[AES-128/CCM(16,6)]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+Nonce = b7776aa998f4d1189b
+AD = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+In = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+Out = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+[AES-128/CCM(16,5)]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+Nonce = c4fb7519a19f13d9d1fc
+AD = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+In = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+Out = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+[AES-128/CCM(16,4)]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+Nonce = 74e689eb5af9441dd690a6
+AD = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+In = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+Out = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+[AES-128/CCM(16,3)]
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+Nonce = 0ec3ac452b547b9062aac8fa
+AD = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+In = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+Out = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+[AES-128/CCM(16,2)]
+Key = ac87fef3b76e725d66d905625a387e82
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+AD = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+In = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+Out = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+[AES-128/CCM(4,2)]
+
+Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+Nonce = 9882578e750b9682c6ca7f8f86
+AD = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+In = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+Out = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+[AES-128/CCM(6,2)]
+
+Key = 44e89189b815b4649c4e9b38c4275a5a
+Nonce = 374c83e94384061ac01963f88d
+AD = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e3eaa9f4535718a08
+In = 8db6ae1eb959963931d1c5224f29ef50019d2b0db7f5f76f
+Out = df952dce0f843374d33da94c969eff07b7bc2418ca9ee01e32bc2ffa8600
+
+[AES-128/CCM(8,2)]
+Key = 368f35a1f80eaaacd6bb136609389727
+Nonce = 842a8445847502ea77363a16b6
+AD = 34396dfcfa6f742aea7040976bd596497a7a6fa4fb85ee8e4ca394d02095b7bf
+In = 1cccd55825316a94c5979e049310d1d717cdfb7624289dac
+Out = 1a58094f0e8c6035a5584bfa8d1009c5f78fd2ca487ff222f6d1d897d6051618
+
+[AES-128/CCM(10,2)]
+
+Key = 996a09a652fa6c82eae8be7886d7e75e
+Nonce = a8b3eb68f205a46d8f632c3367
+AD = c71620d0477c8137b77ec5c72ced4df3a1e987fd9af6b5b10853f0526d876cd5
+In = 84cdd7380f47524b86168ed95386faa402831f22045183d0
+Out = a7fbf9dd1b099ed3acf6bcbd0b6f7cae57bee99f9d084f826d86e69c07f053d1a607
+
+[AES-128/CCM(12,2)]
+Key = 3ee186594f110fb788a8bf8aa8be5d4a
+Nonce = 44f705d52acf27b7f17196aa9b
+AD = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+In = d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1
+Out = b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0d6965f5aa6e31302a9cc2b36
+
+[AES-128/CCM(14,2)]
+Key = 7b2d52a5186d912cf6b83ace7740ceda
+Nonce = f47be3a2b019d1beededf5b80c
+AD = 76cf3522aff97a44b4edd0eef3b81e3ab3cd1ccc93a767a133afd508315f05ed
+In = ea384b081f60bb450808e0c20dc2914ae14a320612c3e1e8
+Out = 79070f33114a980dfd48215051e224dfd01471ac293242afddb36e37da1ee8a88a77d7f12cc6
diff --git a/src/tests/data/salted_blowfish.vec b/src/tests/data/salted_blowfish.vec
new file mode 100644
index 000000000..a69c39fe8
--- /dev/null
+++ b/src/tests/data/salted_blowfish.vec
@@ -0,0 +1,46 @@
+
+# From tests in Golang x/crypto
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 20202020
+Out = d1e193f070a6db12
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 20212021
+Out = fc5ebadecbf859ad
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 20212223
+Out = 2ccb7beeac7b7ff8
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 2021222324252627
+Out = 67a1a9750e5bc6b4
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 20212223242526272021222324252627
+Out = 67a1a9750e5bc6b4
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B
+Out = 4bfe43fdbf360447
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B2C2D2E2F
+Out = d9f0fddac023b793
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B2C2D2E2F30313233
+Out = ff98dd0445b46d1f
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B2C2D2E2F3031323334353637
+Out = 6a0aee7c10d919fe
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B2C2D2E2F303132333435363738393A3B
+Out = 978199a4de9e9fb6
+
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Salt = 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
+Out = C560AD4805E16248
diff --git a/src/tests/test_blowfish.cpp b/src/tests/test_blowfish.cpp
new file mode 100644
index 000000000..58b28001e
--- /dev/null
+++ b/src/tests/test_blowfish.cpp
@@ -0,0 +1,46 @@
+/*
+* (C) 2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "tests.h"
+
+#if defined(BOTAN_HAS_BLOWFISH)
+
+#include <botan/blowfish.h>
+
+namespace Botan_Tests {
+
+class Blowfish_Salted_Tests final : public Text_Based_Test
+ {
+ public:
+ Blowfish_Salted_Tests() : Text_Based_Test("salted_blowfish.vec", "Key,Salt,Out") {}
+
+ Test::Result run_one_test(const std::string&, const VarMap& vars) override
+ {
+ Test::Result result("Blowfish salted key schedule");
+
+ const std::vector<uint8_t> key = vars.get_req_bin("Key");
+ const std::vector<uint8_t> salt = vars.get_req_bin("Salt");
+ const std::vector<uint8_t> expected = vars.get_req_bin("Out");
+
+ Botan::Blowfish blowfish;
+
+ blowfish.salted_set_key(key.data(), key.size(),
+ salt.data(), salt.size(), 0);
+
+ std::vector<uint8_t> block(8);
+ blowfish.encrypt(block);
+
+ result.test_eq("Expected output", block, expected);
+
+ return result;
+ }
+ };
+
+BOTAN_REGISTER_TEST("blowfish_salted", Blowfish_Salted_Tests);
+
+}
+
+#endif
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index 916388778..c0afd9ac2 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -56,6 +56,10 @@ class FFI_Unit_Tests final : public Test
{
TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
TEST_FFI_OK(botan_rng_reseed, (rng, 256));
+
+ uint8_t not_really_entropy[32] = { 0 };
+ TEST_FFI_OK(botan_rng_add_entropy, (rng, not_really_entropy, 32));
+
// used for the rest of this function and destroyed at the end
}
else
@@ -167,7 +171,6 @@ class FFI_Unit_Tests final : public Test
std::string outstr;
std::vector<uint8_t> outbuf;
- //char namebuf[32];
outstr.resize(2 * bin.size());
TEST_FFI_OK(botan_hex_encode, (bin.data(), bin.size(), &outstr[0], 0));
@@ -404,6 +407,18 @@ class FFI_Unit_Tests final : public Test
if(TEST_FFI_OK(botan_cipher_init, (&cipher_encrypt, "AES-128/GCM", BOTAN_CIPHER_INIT_FLAG_ENCRYPT)))
{
+ char namebuf[18];
+ size_t name_len = 15;
+ TEST_FFI_FAIL("output buffer too short", botan_cipher_name, (cipher_encrypt, namebuf, &name_len));
+ result.test_eq("name len", name_len, 16);
+
+ name_len = sizeof(namebuf);
+ if(TEST_FFI_OK(botan_cipher_name, (cipher_encrypt, namebuf, &name_len)))
+ {
+ result.test_eq("name len", name_len, 16);
+ result.test_eq("name", std::string(namebuf), "AES-128/GCM(16)");
+ }
+
size_t min_keylen = 0;
size_t max_keylen = 0;
size_t nonce_len = 0;
@@ -632,14 +647,18 @@ class FFI_Unit_Tests final : public Test
if(TEST_FFI_OK(botan_hash_init, (&hash, "SHA-256", 0)))
{
- /*
- TEST_FFI_FAIL("output buffer too short", botan_hash_name, (hash, namebuf, 5));
+ char namebuf[10];
+ size_t name_len = 7;
+ TEST_FFI_FAIL("output buffer too short", botan_hash_name, (hash, namebuf, &name_len));
+ result.test_eq("name len", name_len, 8);
+
+ name_len = sizeof(namebuf);
+ if(TEST_FFI_OK(botan_hash_name, (hash, namebuf, &name_len)))
+ {
+ result.test_eq("name len", name_len, 8);
+ result.test_eq("name", std::string(namebuf), "SHA-256");
+ }
- if(TEST_FFI_OK(botan_hash_name, (hash, namebuf, sizeof(namebuf))))
- {
- result.test_eq("hash name", std::string(namebuf), "SHA-256");
- }
- */
size_t block_size;
if (TEST_FFI_OK(botan_hash_block_size, (hash, &block_size)))
{
@@ -705,14 +724,17 @@ class FFI_Unit_Tests final : public Test
if(TEST_FFI_OK(botan_mac_init, (&mac, "HMAC(SHA-256)", 0)))
{
- /*
- TEST_FFI_FAIL("output buffer too short", botan_mac_name, (mac, namebuf, 5));
+ char namebuf[16];
+ size_t name_len = 13;
+ TEST_FFI_FAIL("output buffer too short", botan_mac_name, (mac, namebuf, &name_len));
+ result.test_eq("name len", name_len, 14);
- if(TEST_FFI_OK(botan_mac_name, (mac, namebuf, 20)))
- {
- result.test_eq("mac name", std::string(namebuf), "HMAC(SHA-256)");
- }
- */
+ name_len = sizeof(namebuf);
+ if(TEST_FFI_OK(botan_mac_name, (mac, namebuf, &name_len)))
+ {
+ result.test_eq("name len", name_len, 14);
+ result.test_eq("name", std::string(namebuf), "HMAC(SHA-256)");
+ }
size_t output_len;
if(TEST_FFI_OK(botan_mac_output_length, (mac, &output_len)))
@@ -819,6 +841,18 @@ class FFI_Unit_Tests final : public Test
if(TEST_FFI_OK(botan_block_cipher_init, (&cipher, "AES-128")))
{
+ char namebuf[10];
+ size_t name_len = 7;
+ TEST_FFI_FAIL("output buffer too short", botan_block_cipher_name, (cipher, namebuf, &name_len));
+ result.test_eq("name len", name_len, 8);
+
+ name_len = sizeof(namebuf);
+ if(TEST_FFI_OK(botan_block_cipher_name, (cipher, namebuf, &name_len)))
+ {
+ result.test_eq("name len", name_len, 8);
+ result.test_eq("name", std::string(namebuf), "AES-128");
+ }
+
const std::vector<uint8_t> zero16(16, 0);
std::vector<uint8_t> block(16, 0);