diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/block/blowfish/blowfish.cpp | 59 | ||||
-rw-r--r-- | src/lib/block/blowfish/blowfish.h | 16 | ||||
-rw-r--r-- | src/lib/block/blowfish/info.txt | 2 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 54 | ||||
-rw-r--r-- | src/lib/ffi/ffi_block.cpp | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi_cipher.cpp | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi_hash.cpp | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi_mac.cpp | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi_rng.cpp | 5 | ||||
-rw-r--r-- | src/lib/math/mp/mp_core.cpp | 22 | ||||
-rw-r--r-- | src/lib/modes/aead/ccm/ccm.cpp | 11 | ||||
-rw-r--r-- | src/lib/modes/aead/ccm/ccm.h | 2 | ||||
-rw-r--r-- | src/lib/passhash/bcrypt/bcrypt.cpp | 18 | ||||
-rw-r--r-- | src/lib/rng/rng.h | 3 | ||||
-rwxr-xr-x | src/scripts/ci/setup_travis.sh | 4 | ||||
-rw-r--r-- | src/tests/data/aead/ccm.vec | 124 | ||||
-rw-r--r-- | src/tests/data/salted_blowfish.vec | 46 | ||||
-rw-r--r-- | src/tests/test_blowfish.cpp | 46 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 64 |
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); |