From a45cc661948b88b0ebe2e80347d16389f7556224 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 18 Jul 2018 13:50:20 -0400 Subject: Support salts other than exactly 16 bytes for Blowfish key setup Bcrypt only needs 16 byte salts but unfortunately Bcrypt-PBKDF is defined to use 64 byte salts instead. So extend support to handle any salt that is a multiple of 4 bytes. --- src/lib/block/blowfish/blowfish.cpp | 59 +++++++++++++++++++------------------ src/lib/block/blowfish/blowfish.h | 16 ++++++++-- src/lib/block/blowfish/info.txt | 2 +- 3 files changed, 45 insertions(+), 32 deletions(-) (limited to 'src/lib/block/blowfish') 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(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(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& 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(salt, (i + salt_off) % 4); - R ^= load_be(salt, (i + salt_off + 1) % 4); + if(salt_length > 0) + { + L ^= load_be(salt, (i + salt_off) % (salt_length / 4)); + R ^= load_be(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& 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 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 @@ -BLOWFISH -> 20131128 +BLOWFISH -> 20180718 -- cgit v1.2.3