aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/block/blowfish
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-07-18 13:50:20 -0400
committerJack Lloyd <[email protected]>2018-07-18 13:58:30 -0400
commita45cc661948b88b0ebe2e80347d16389f7556224 (patch)
treeae9cb06c2d976aefc8b84ba67e9ae87b3dfca690 /src/lib/block/blowfish
parentf2b7c668882eef8dae36a6757c44dde5339e0686 (diff)
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.
Diffstat (limited to 'src/lib/block/blowfish')
-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
3 files changed, 45 insertions, 32 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>