aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pbkdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pbkdf')
-rw-r--r--src/lib/pbkdf/pbkdf.cpp55
-rw-r--r--src/lib/pbkdf/pbkdf.h97
-rw-r--r--src/lib/pbkdf/pbkdf1/pbkdf1.cpp30
-rw-r--r--src/lib/pbkdf/pbkdf1/pbkdf1.h21
-rw-r--r--src/lib/pbkdf/pbkdf2/pbkdf2.cpp84
-rw-r--r--src/lib/pbkdf/pbkdf2/pbkdf2.h19
6 files changed, 179 insertions, 127 deletions
diff --git a/src/lib/pbkdf/pbkdf.cpp b/src/lib/pbkdf/pbkdf.cpp
index 973805f65..6fbf8ba37 100644
--- a/src/lib/pbkdf/pbkdf.cpp
+++ b/src/lib/pbkdf/pbkdf.cpp
@@ -10,35 +10,48 @@
namespace Botan {
-OctetString PBKDF::derive_key(size_t output_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations) const
+void PBKDF::pbkdf_timed(byte out[], size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ std::chrono::milliseconds msec,
+ size_t& iterations) const
+ {
+ iterations = pbkdf(out, out_len, passphrase, salt, salt_len, 0, msec);
+ }
+
+void PBKDF::pbkdf_iterations(byte out[], size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations) const
{
if(iterations == 0)
throw std::invalid_argument(name() + ": Invalid iteration count");
- auto derived = key_derivation(output_len, passphrase,
- salt, salt_len, iterations,
- std::chrono::milliseconds(0));
-
- BOTAN_ASSERT(derived.first == iterations,
- "PBKDF used the correct number of iterations");
-
- return derived.second;
+ const size_t iterations_run = pbkdf(out, out_len, passphrase,
+ salt, salt_len, iterations,
+ std::chrono::milliseconds(0));
+ BOTAN_ASSERT_EQUAL(iterations, iterations_run, "Expected PBKDF iterations");
}
-OctetString PBKDF::derive_key(size_t output_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- std::chrono::milliseconds ms,
- size_t& iterations) const
+secure_vector<byte> PBKDF::pbkdf_iterations(size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations) const
{
- auto derived = key_derivation(output_len, passphrase, salt, salt_len, 0, ms);
-
- iterations = derived.first;
+ secure_vector<byte> out(out_len);
+ pbkdf_iterations(&out[0], out_len, passphrase, salt, salt_len, iterations);
+ return out;
+ }
- return derived.second;
+secure_vector<byte> PBKDF::pbkdf_timed(size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ std::chrono::milliseconds msec,
+ size_t& iterations) const
+ {
+ secure_vector<byte> out(out_len);
+ pbkdf_timed(&out[0], out_len, passphrase, salt, salt_len, msec, iterations);
+ return out;
}
}
diff --git a/src/lib/pbkdf/pbkdf.h b/src/lib/pbkdf/pbkdf.h
index ad5346e36..3eaa293a1 100644
--- a/src/lib/pbkdf/pbkdf.h
+++ b/src/lib/pbkdf/pbkdf.h
@@ -1,6 +1,6 @@
/*
* PBKDF
-* (C) 1999-2007,2012 Jack Lloyd
+* (C) 1999-2007,2012,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -35,87 +35,116 @@ class BOTAN_DLL PBKDF
virtual std::string name() const = 0;
/**
+ * Derive a key from a passphrase for a number of iterations
+ * specified by either iterations or if iterations == 0 then
+ * running until seconds time has elapsed.
+ *
+ * @param out_len the desired length of the key to produce
+ * @param passphrase the password to derive the key from
+ * @param salt a randomly chosen salt
+ * @param salt_len length of salt in bytes
+ * @param iterations the number of iterations to use (use 10K or more)
+ * @param msec if iterations is zero, then instead the PBKDF is
+ * run until msec milliseconds has passed.
+ * @return the number of iterations performed
+ */
+ virtual size_t pbkdf(byte out[], size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec) const = 0;
+
+ void pbkdf_iterations(byte out[], size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations) const;
+
+ void pbkdf_timed(byte out[], size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ std::chrono::milliseconds msec,
+ size_t& iterations) const;
+
+ secure_vector<byte> pbkdf_iterations(size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations) const;
+
+ secure_vector<byte> pbkdf_timed(size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ std::chrono::milliseconds msec,
+ size_t& iterations) const;
+
+ // Following kept for compat with 1.10:
+
+ /**
* Derive a key from a passphrase
- * @param output_len the desired length of the key to produce
+ * @param out_len the desired length of the key to produce
* @param passphrase the password to derive the key from
* @param salt a randomly chosen salt
* @param salt_len length of salt in bytes
* @param iterations the number of iterations to use (use 10K or more)
*/
- OctetString derive_key(size_t output_len,
+ OctetString derive_key(size_t out_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
- size_t iterations) const;
+ size_t iterations) const
+ {
+ return pbkdf_iterations(out_len, passphrase, salt, salt_len, iterations);
+ }
/**
* Derive a key from a passphrase
- * @param output_len the desired length of the key to produce
+ * @param out_len the desired length of the key to produce
* @param passphrase the password to derive the key from
* @param salt a randomly chosen salt
* @param iterations the number of iterations to use (use 10K or more)
*/
template<typename Alloc>
- OctetString derive_key(size_t output_len,
+ OctetString derive_key(size_t out_len,
const std::string& passphrase,
const std::vector<byte, Alloc>& salt,
size_t iterations) const
{
- return derive_key(output_len, passphrase, &salt[0], salt.size(), iterations);
+ return pbkdf_iterations(out_len, passphrase, &salt[0], salt.size(), iterations);
}
/**
* Derive a key from a passphrase
- * @param output_len the desired length of the key to produce
+ * @param out_len the desired length of the key to produce
* @param passphrase the password to derive the key from
* @param salt a randomly chosen salt
* @param salt_len length of salt in bytes
* @param msec is how long to run the PBKDF
* @param iterations is set to the number of iterations used
*/
- OctetString derive_key(size_t output_len,
+ OctetString derive_key(size_t out_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
std::chrono::milliseconds msec,
- size_t& iterations) const;
+ size_t& iterations) const
+ {
+ return pbkdf_timed(out_len, passphrase, salt, salt_len, msec, iterations);
+ }
/**
* Derive a key from a passphrase using a certain amount of time
- * @param output_len the desired length of the key to produce
+ * @param out_len the desired length of the key to produce
* @param passphrase the password to derive the key from
* @param salt a randomly chosen salt
* @param msec is how long to run the PBKDF
* @param iterations is set to the number of iterations used
*/
template<typename Alloc>
- OctetString derive_key(size_t output_len,
+ OctetString derive_key(size_t out_len,
const std::string& passphrase,
const std::vector<byte, Alloc>& salt,
std::chrono::milliseconds msec,
size_t& iterations) const
{
- return derive_key(output_len, passphrase, &salt[0], salt.size(), msec, iterations);
+ return pbkdf_timed(out_len, passphrase, &salt[0], salt.size(), msec, iterations);
}
-
- /**
- * Derive a key from a passphrase for a number of iterations
- * specified by either iterations or if iterations == 0 then
- * running until seconds time has elapsed.
- *
- * @param output_len the desired length of the key to produce
- * @param passphrase the password to derive the key from
- * @param salt a randomly chosen salt
- * @param salt_len length of salt in bytes
- * @param iterations the number of iterations to use (use 10K or more)
- * @param msec if iterations is zero, then instead the PBKDF is
- * run until msec milliseconds has passed.
- * @return the number of iterations performed and the derived key
- */
- virtual std::pair<size_t, OctetString>
- key_derivation(size_t output_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations,
- std::chrono::milliseconds msec) const = 0;
};
}
diff --git a/src/lib/pbkdf/pbkdf1/pbkdf1.cpp b/src/lib/pbkdf/pbkdf1/pbkdf1.cpp
index e5dda579f..8134b39c4 100644
--- a/src/lib/pbkdf/pbkdf1/pbkdf1.cpp
+++ b/src/lib/pbkdf/pbkdf1/pbkdf1.cpp
@@ -13,22 +13,18 @@ namespace Botan {
BOTAN_REGISTER_PBKDF_1HASH(PKCS5_PBKDF1, "PBKDF1")
-/*
-* Return a PKCS#5 PBKDF1 derived key
-*/
-std::pair<size_t, OctetString>
-PKCS5_PBKDF1::key_derivation(size_t key_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations,
- std::chrono::milliseconds msec) const
+size_t PKCS5_PBKDF1::pbkdf(byte output_buf[], size_t output_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec) const
{
- if(key_len > hash->output_length())
+ if(output_len > m_hash->output_length())
throw Invalid_Argument("PKCS5_PBKDF1: Requested output length too long");
- hash->update(passphrase);
- hash->update(salt, salt_len);
- secure_vector<byte> key = hash->final();
+ m_hash->update(passphrase);
+ m_hash->update(salt, salt_len);
+ secure_vector<byte> key = m_hash->final();
const auto start = std::chrono::high_resolution_clock::now();
size_t iterations_performed = 1;
@@ -48,14 +44,14 @@ PKCS5_PBKDF1::key_derivation(size_t key_len,
else if(iterations_performed == iterations)
break;
- hash->update(key);
- hash->final(&key[0]);
+ m_hash->update(key);
+ m_hash->final(&key[0]);
++iterations_performed;
}
- return std::make_pair(iterations_performed,
- OctetString(&key[0], std::min(key_len, key.size())));
+ copy_mem(output_buf, &key[0], output_len);
+ return iterations_performed;
}
}
diff --git a/src/lib/pbkdf/pbkdf1/pbkdf1.h b/src/lib/pbkdf/pbkdf1/pbkdf1.h
index 4c2f3888c..c93dbe503 100644
--- a/src/lib/pbkdf/pbkdf1/pbkdf1.h
+++ b/src/lib/pbkdf/pbkdf1/pbkdf1.h
@@ -23,28 +23,27 @@ class BOTAN_DLL PKCS5_PBKDF1 : public PBKDF
public:
/**
* Create a PKCS #5 instance using the specified hash function.
- * @param hash_in pointer to a hash function object to use
+ * @param hash pointer to a hash function object to use
*/
- PKCS5_PBKDF1(HashFunction* hash_in) : hash(hash_in) {}
+ PKCS5_PBKDF1(HashFunction* hash) : m_hash(hash) {}
std::string name() const
{
- return "PBKDF1(" + hash->name() + ")";
+ return "PBKDF1(" + m_hash->name() + ")";
}
PBKDF* clone() const
{
- return new PKCS5_PBKDF1(hash->clone());
+ return new PKCS5_PBKDF1(m_hash->clone());
}
- std::pair<size_t, OctetString>
- key_derivation(size_t output_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations,
- std::chrono::milliseconds msec) const override;
+ size_t pbkdf(byte output_buf[], size_t output_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec) const override;
private:
- std::unique_ptr<HashFunction> hash;
+ std::unique_ptr<HashFunction> m_hash;
};
}
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
index 146dd15b0..0ff412bc5 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
@@ -27,51 +27,49 @@ PKCS5_PBKDF2* PKCS5_PBKDF2::make(const Spec& spec)
return nullptr;
}
-/*
-* Return a PKCS #5 PBKDF2 derived key
-*/
-std::pair<size_t, OctetString>
-PKCS5_PBKDF2::key_derivation(size_t key_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations,
- std::chrono::milliseconds msec) const
+size_t
+pbkdf2(MessageAuthenticationCode& prf,
+ byte out[],
+ size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec)
{
- if(key_len == 0)
- return std::make_pair(iterations, OctetString());
+ clear_mem(out, out_len);
+
+ if(out_len == 0)
+ return 0;
try
{
- mac->set_key(reinterpret_cast<const byte*>(passphrase.data()),
- passphrase.length());
+ prf.set_key(reinterpret_cast<const byte*>(passphrase.data()), passphrase.size());
}
catch(Invalid_Key_Length)
{
- throw Exception(name() + " cannot accept passphrases of length " +
- std::to_string(passphrase.length()));
+ throw std::runtime_error("PBKDF2 with " + prf.name() +
+ " cannot accept passphrases of length " +
+ std::to_string(passphrase.size()));
}
- secure_vector<byte> key(key_len);
-
- byte* T = &key[0];
-
- secure_vector<byte> U(mac->output_length());
+ const size_t prf_sz = prf.output_length();
+ secure_vector<byte> U(prf_sz);
- const size_t blocks_needed = round_up(key_len, mac->output_length()) / mac->output_length();
+ const size_t blocks_needed = round_up(out_len, prf_sz) / prf_sz;
std::chrono::microseconds usec_per_block =
std::chrono::duration_cast<std::chrono::microseconds>(msec) / blocks_needed;
u32bit counter = 1;
- while(key_len)
+ while(out_len)
{
- size_t T_size = std::min<size_t>(mac->output_length(), key_len);
+ const size_t prf_output = std::min<size_t>(prf_sz, out_len);
- mac->update(salt, salt_len);
- mac->update_be(counter);
- mac->final(&U[0]);
+ prf.update(salt, salt_len);
+ prf.update_be(counter++);
+ prf.final(&U[0]);
- xor_buf(T, &U[0], T_size);
+ xor_buf(out, &U[0], prf_output);
if(iterations == 0)
{
@@ -86,9 +84,9 @@ PKCS5_PBKDF2::key_derivation(size_t key_len,
while(true)
{
- mac->update(U);
- mac->final(&U[0]);
- xor_buf(T, &U[0], T_size);
+ prf.update(U);
+ prf.final(&U[0]);
+ xor_buf(out, &U[0], prf_output);
iterations++;
/*
@@ -96,7 +94,7 @@ PKCS5_PBKDF2::key_derivation(size_t key_len,
avoids confusion, and likely some broken implementations
break on getting completely randomly distributed values
*/
- if(iterations % 1000 == 0)
+ if(iterations % 10000 == 0)
{
auto time_taken = std::chrono::high_resolution_clock::now() - start;
auto usec_taken = std::chrono::duration_cast<std::chrono::microseconds>(time_taken);
@@ -109,18 +107,28 @@ PKCS5_PBKDF2::key_derivation(size_t key_len,
{
for(size_t i = 1; i != iterations; ++i)
{
- mac->update(U);
- mac->final(&U[0]);
- xor_buf(T, &U[0], T_size);
+ prf.update(U);
+ prf.final(&U[0]);
+ xor_buf(out, &U[0], prf_output);
}
}
- key_len -= T_size;
- T += T_size;
- ++counter;
+ out_len -= prf_output;
+ out += prf_output;
}
- return std::make_pair(iterations, key);
+ return iterations;
}
+size_t
+PKCS5_PBKDF2::pbkdf(byte key[], size_t key_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec) const
+ {
+ return pbkdf2(*mac.get(), key, key_len, passphrase, salt, salt_len, iterations, msec);
+ }
+
+
}
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.h b/src/lib/pbkdf/pbkdf2/pbkdf2.h
index 3d1a14fab..d74410b89 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.h
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.h
@@ -14,6 +14,14 @@
namespace Botan {
+BOTAN_DLL size_t pbkdf2(MessageAuthenticationCode& prf,
+ byte out[],
+ size_t out_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec);
+
/**
* PKCS #5 PBKDF2
*/
@@ -30,12 +38,11 @@ class BOTAN_DLL PKCS5_PBKDF2 : public PBKDF
return new PKCS5_PBKDF2(mac->clone());
}
- std::pair<size_t, OctetString>
- key_derivation(size_t output_len,
- const std::string& passphrase,
- const byte salt[], size_t salt_len,
- size_t iterations,
- std::chrono::milliseconds msec) const override;
+ size_t pbkdf(byte output_buf[], size_t output_len,
+ const std::string& passphrase,
+ const byte salt[], size_t salt_len,
+ size_t iterations,
+ std::chrono::milliseconds msec) const override;
/**
* Create a PKCS #5 instance using the specified message auth code