aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/base/info.txt1
-rw-r--r--src/lib/ffi/ffi.cpp68
-rw-r--r--src/lib/kdf/kdf.h47
-rw-r--r--src/lib/kdf/kdf1/kdf1.cpp24
-rw-r--r--src/lib/kdf/kdf1/kdf1.h15
-rw-r--r--src/lib/kdf/kdf2/kdf2.cpp35
-rw-r--r--src/lib/kdf/kdf2/kdf2.h14
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.cpp78
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.h24
-rw-r--r--src/lib/kdf/prf_x942/prf_x942.cpp37
-rw-r--r--src/lib/kdf/prf_x942/prf_x942.h12
-rw-r--r--src/lib/passhash/bcrypt/bcrypt.cpp6
-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
-rw-r--r--src/lib/pubkey/dlies/dlies.cpp16
-rw-r--r--src/tests/data/kdf/kdf1.vec10
20 files changed, 349 insertions, 344 deletions
diff --git a/src/lib/base/info.txt b/src/lib/base/info.txt
index 581c40fe0..e09351596 100644
--- a/src/lib/base/info.txt
+++ b/src/lib/base/info.txt
@@ -23,6 +23,7 @@ hash
hex
mac
modes
+pbkdf
rng
stream
utils
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 94fc546fe..cb2efceda 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -128,6 +128,11 @@ int write_str_output(uint8_t out[], size_t* out_len, const std::string& str)
str.size() + 1);
}
+int write_str_output(char out[], size_t* out_len, const std::string& str)
+ {
+ return write_str_output(reinterpret_cast<uint8_t*>(out), out_len, str);
+ }
+
#define BOTAN_FFI_DO(T, obj, block) apply_fn(obj, BOTAN_CURRENT_FUNCTION, [=](T& obj) { do { block } while(0); return 0; })
}
@@ -582,15 +587,7 @@ int botan_pbkdf(const char* pbkdf_algo, uint8_t out[], size_t out_len,
try
{
std::unique_ptr<Botan::PBKDF> pbkdf(Botan::get_pbkdf(pbkdf_algo));
-
- auto r = pbkdf->derive_key(out_len, pass, salt, salt_len, iterations).bits_of();
-
- if(r.size() != out_len)
- throw std::runtime_error(std::string(pbkdf_algo) + " produced " +
- std::to_string(r.size()) + " asked for " +
- std::to_string(out_len));
-
- Botan::copy_mem(out, &r[0], out_len);
+ pbkdf->pbkdf_iterations(out, out_len, pass, salt, salt_len, iterations);
}
catch(std::exception& e)
{
@@ -610,17 +607,9 @@ int botan_pbkdf_timed(const char* pbkdf_algo,
try
{
std::unique_ptr<Botan::PBKDF> pbkdf(Botan::get_pbkdf(pbkdf_algo));
-
- auto r = pbkdf->derive_key(out_len, password, salt, salt_len,
- std::chrono::milliseconds(ms_to_run),
- *iterations_used).bits_of();
-
- if(r.size() != out_len)
- throw std::runtime_error(std::string(pbkdf_algo) + " produced " +
- std::to_string(r.size()) + " asked for " +
- std::to_string(out_len));
-
- Botan::copy_mem(out, &r[0], out_len);
+ pbkdf->pbkdf_timed(out, out_len, password, salt, salt_len,
+ std::chrono::milliseconds(ms_to_run),
+ *iterations_used);
}
catch(std::exception& e)
{
@@ -638,12 +627,7 @@ int botan_kdf(const char* kdf_algo,
try
{
std::unique_ptr<Botan::KDF> kdf(Botan::get_kdf(kdf_algo));
- auto r = kdf->derive_key(out_len, secret, secret_len, salt, salt_len);
- if(r.size() != out_len)
- throw std::runtime_error(std::string(kdf_algo) + " produced " +
- std::to_string(r.size()) + " asked for " +
- std::to_string(out_len));
- Botan::copy_mem(out, &r[0], out_len);
+ kdf->kdf(out, out_len, secret, secret_len, salt, salt_len);
}
catch(std::exception& e)
{
@@ -860,20 +844,7 @@ int botan_privkey_export_pubkey(botan_pubkey_t* pubout, botan_privkey_t key_obj)
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
{
- return apply_fn(key, BOTAN_CURRENT_FUNCTION,
- [out,out_len](Botan::Public_Key& k)
- {
- const std::string name = k.algo_name();
- const size_t avail = *out_len;
- *out_len = name.size() + 1;
- if(avail > 1 + name.size())
- {
- Botan::copy_mem(out, name.data(), name.size());
- out[name.size()] = 0;
- return 0;
- }
- return -1;
- });
+ return BOTAN_FFI_DO(Botan::Public_Key, key, { return write_str_output(out, out_len, key.algo_name()); });
}
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
@@ -1147,20 +1118,9 @@ int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
uint8_t out[], size_t* out_len)
{
return BOTAN_FFI_DO(Botan::Private_Key, key, {
- auto kak = dynamic_cast<const Botan::PK_Key_Agreement_Key*>(&key);
- if(!kak)
- return -2;
- const std::vector<uint8_t> pv = kak->public_value();
- const size_t avail = *out_len;
- *out_len = pv.size();
-
- if(pv.size() <= avail)
- {
- Botan::copy_mem(out, &pv[0], pv.size());
- return 0;
- }
-
- return -1;
+ if(auto kak = dynamic_cast<const Botan::PK_Key_Agreement_Key*>(&key))
+ return write_vec_output(out, out_len, kak->public_value());
+ return -2;
});
}
diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h
index 9d8ca57fc..dc23a82bd 100644
--- a/src/lib/kdf/kdf.h
+++ b/src/lib/kdf/kdf.h
@@ -25,6 +25,30 @@ class BOTAN_DLL KDF
virtual std::string name() const = 0;
+ virtual size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const = 0;
+
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param secret_len size of secret in bytes
+ * @param salt a diversifier
+ * @param salt_len size of salt in bytes
+ */
+ secure_vector<byte> derive_key(size_t key_len,
+ const byte secret[],
+ size_t secret_len,
+ const byte salt[],
+ size_t salt_len) const
+ {
+ secure_vector<byte> key(key_len);
+ key.resize(kdf(&key[0], key.size(), secret, secret_len, salt, salt_len));
+ return key;
+ }
+
/**
* Derive a key
* @param key_len the desired output length in bytes
@@ -90,31 +114,10 @@ class BOTAN_DLL KDF
salt.length());
}
- /**
- * Derive a key
- * @param key_len the desired output length in bytes
- * @param secret the secret input
- * @param secret_len size of secret in bytes
- * @param salt a diversifier
- * @param salt_len size of salt in bytes
- */
- secure_vector<byte> derive_key(size_t key_len,
- const byte secret[],
- size_t secret_len,
- const byte salt[],
- size_t salt_len) const
- {
- return derive(key_len, secret, secret_len, salt, salt_len);
- }
-
virtual KDF* clone() const = 0;
typedef SCAN_Name Spec;
- private:
- virtual secure_vector<byte>
- derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte salt[], size_t salt_len) const = 0;
+
};
/**
diff --git a/src/lib/kdf/kdf1/kdf1.cpp b/src/lib/kdf/kdf1/kdf1.cpp
index df84a1a00..c2a74027b 100644
--- a/src/lib/kdf/kdf1/kdf1.cpp
+++ b/src/lib/kdf/kdf1/kdf1.cpp
@@ -12,16 +12,22 @@ namespace Botan {
BOTAN_REGISTER_KDF_1HASH(KDF1, "KDF1");
-/*
-* KDF1 Key Derivation Mechanism
-*/
-secure_vector<byte> KDF1::derive(size_t,
- const byte secret[], size_t secret_len,
- const byte P[], size_t P_len) const
+size_t KDF1::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
{
- hash->update(secret, secret_len);
- hash->update(P, P_len);
- return hash->final();
+ m_hash->update(secret, secret_len);
+ m_hash->update(salt, salt_len);
+
+ if(key_len < m_hash->output_length())
+ {
+ secure_vector<byte> v = m_hash->final();
+ copy_mem(key, &v[0], key_len);
+ return key_len;
+ }
+
+ m_hash->final(key);
+ return m_hash->output_length();
}
}
diff --git a/src/lib/kdf/kdf1/kdf1.h b/src/lib/kdf/kdf1/kdf1.h
index 9f617878b..a22d19d97 100644
--- a/src/lib/kdf/kdf1/kdf1.h
+++ b/src/lib/kdf/kdf1/kdf1.h
@@ -19,16 +19,17 @@ namespace Botan {
class BOTAN_DLL KDF1 : public KDF
{
public:
- secure_vector<byte> derive(size_t,
- const byte secret[], size_t secret_len,
- const byte P[], size_t P_len) const;
+ std::string name() const override { return "KDF1(" + m_hash->name() + ")"; }
- std::string name() const { return "KDF1(" + hash->name() + ")"; }
- KDF* clone() const { return new KDF1(hash->clone()); }
+ KDF* clone() const override { return new KDF1(m_hash->clone()); }
- KDF1(HashFunction* h) : hash(h) {}
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
+
+ KDF1(HashFunction* h) : m_hash(h) {}
private:
- std::unique_ptr<HashFunction> hash;
+ std::unique_ptr<HashFunction> m_hash;
};
}
diff --git a/src/lib/kdf/kdf2/kdf2.cpp b/src/lib/kdf/kdf2/kdf2.cpp
index c7b355580..f1a702887 100644
--- a/src/lib/kdf/kdf2/kdf2.cpp
+++ b/src/lib/kdf/kdf2/kdf2.cpp
@@ -12,32 +12,27 @@ namespace Botan {
BOTAN_REGISTER_KDF_1HASH(KDF2, "KDF2");
-/*
-* KDF2 Key Derivation Mechanism
-*/
-secure_vector<byte> KDF2::derive(size_t out_len,
- const byte secret[], size_t secret_len,
- const byte P[], size_t P_len) const
+size_t KDF2::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
{
- secure_vector<byte> output;
u32bit counter = 1;
+ secure_vector<byte> h;
- while(out_len && counter)
+ size_t offset = 0;
+ while(offset != key_len && counter != 0)
{
- hash->update(secret, secret_len);
- hash->update_be(counter);
- hash->update(P, P_len);
-
- secure_vector<byte> hash_result = hash->final();
-
- size_t added = std::min(hash_result.size(), out_len);
- output += std::make_pair(&hash_result[0], added);
- out_len -= added;
-
- ++counter;
+ m_hash->update(secret, secret_len);
+ m_hash->update_be(counter++);
+ m_hash->update(salt, salt_len);
+ m_hash->final(h);
+
+ const size_t added = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], &h[0], added);
+ offset += added;
}
- return output;
+ return offset;
}
}
diff --git a/src/lib/kdf/kdf2/kdf2.h b/src/lib/kdf/kdf2/kdf2.h
index c574336b6..e8a8be1fa 100644
--- a/src/lib/kdf/kdf2/kdf2.h
+++ b/src/lib/kdf/kdf2/kdf2.h
@@ -19,15 +19,17 @@ namespace Botan {
class BOTAN_DLL KDF2 : public KDF
{
public:
- secure_vector<byte> derive(size_t, const byte[], size_t,
- const byte[], size_t) const;
+ std::string name() const override { return "KDF2(" + m_hash->name() + ")"; }
- std::string name() const { return "KDF2(" + hash->name() + ")"; }
- KDF* clone() const { return new KDF2(hash->clone()); }
+ KDF* clone() const override { return new KDF2(m_hash->clone()); }
- KDF2(HashFunction* h) : hash(h) {}
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
+
+ KDF2(HashFunction* h) : m_hash(h) {}
private:
- std::unique_ptr<HashFunction> hash;
+ std::unique_ptr<HashFunction> m_hash;
};
}
diff --git a/src/lib/kdf/prf_tls/prf_tls.cpp b/src/lib/kdf/prf_tls/prf_tls.cpp
index f1061fd10..9161dc71e 100644
--- a/src/lib/kdf/prf_tls/prf_tls.cpp
+++ b/src/lib/kdf/prf_tls/prf_tls.cpp
@@ -23,15 +23,21 @@ TLS_12_PRF* TLS_12_PRF::make(const Spec& spec)
BOTAN_REGISTER_NAMED_T(KDF, "TLS-12-PRF", TLS_12_PRF, TLS_12_PRF::make);
BOTAN_REGISTER_KDF_NOARGS(TLS_PRF, "TLS-PRF");
+TLS_PRF::TLS_PRF()
+ {
+ m_hmac_md5.reset(make_a<MessageAuthenticationCode>("HMAC(MD5)"));
+ m_hmac_sha1.reset(make_a<MessageAuthenticationCode>("HMAC(SHA-1)"));
+ }
+
namespace {
/*
* TLS PRF P_hash function
*/
-void P_hash(secure_vector<byte>& output,
+void P_hash(byte out[], size_t out_len,
MessageAuthenticationCode& mac,
const byte secret[], size_t secret_len,
- const byte seed[], size_t seed_len)
+ const byte salt[], size_t salt_len)
{
try
{
@@ -44,73 +50,47 @@ void P_hash(secure_vector<byte>& output,
" bytes is too long for the PRF");
}
- secure_vector<byte> A(seed, seed + seed_len);
+ secure_vector<byte> A(salt, salt + salt_len);
+ secure_vector<byte> h;
size_t offset = 0;
- while(offset != output.size())
+ while(offset != out_len)
{
- const size_t this_block_len =
- std::min<size_t>(mac.output_length(), output.size() - offset);
-
A = mac.process(A);
mac.update(A);
- mac.update(seed, seed_len);
- secure_vector<byte> block = mac.final();
+ mac.update(salt, salt_len);
+ mac.final(h);
- xor_buf(&output[offset], &block[0], this_block_len);
- offset += this_block_len;
+ const size_t writing = std::min(h.size(), out_len - offset);
+ xor_buf(&out[offset], &h[0], writing);
+ offset += writing;
}
}
}
-/*
-* TLS PRF Constructor and Destructor
-*/
-TLS_PRF::TLS_PRF()
- {
- hmac_md5.reset(make_a<MessageAuthenticationCode>("HMAC(MD5)"));
- hmac_sha1.reset(make_a<MessageAuthenticationCode>("HMAC(SHA-1)"));
- }
-
-/*
-* TLS PRF
-*/
-secure_vector<byte> TLS_PRF::derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte seed[], size_t seed_len) const
+size_t TLS_PRF::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
{
- secure_vector<byte> output(key_len);
-
- size_t S1_len = (secret_len + 1) / 2,
- S2_len = (secret_len + 1) / 2;
+ const size_t S1_len = (secret_len + 1) / 2,
+ S2_len = (secret_len + 1) / 2;
const byte* S1 = secret;
const byte* S2 = secret + (secret_len - S2_len);
- P_hash(output, *hmac_md5, S1, S1_len, seed, seed_len);
- P_hash(output, *hmac_sha1, S2, S2_len, seed, seed_len);
-
- return output;
+ P_hash(key, key_len, *m_hmac_md5, S1, S1_len, salt, salt_len);
+ P_hash(key, key_len, *m_hmac_sha1, S2, S2_len, salt, salt_len);
+ return key_len;
}
-/*
-* TLS v1.2 PRF Constructor and Destructor
-*/
-TLS_12_PRF::TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac)
+size_t TLS_12_PRF::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
{
- }
-
-secure_vector<byte> TLS_12_PRF::derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte seed[], size_t seed_len) const
- {
- secure_vector<byte> output(key_len);
-
- P_hash(output, *m_mac, secret, secret_len, seed, seed_len);
-
- return output;
+ P_hash(key, key_len, *m_mac, secret, secret_len, salt, salt_len);
+ return key_len;
}
}
diff --git a/src/lib/kdf/prf_tls/prf_tls.h b/src/lib/kdf/prf_tls/prf_tls.h
index c3adc6caf..e2289a6e8 100644
--- a/src/lib/kdf/prf_tls/prf_tls.h
+++ b/src/lib/kdf/prf_tls/prf_tls.h
@@ -19,17 +19,18 @@ namespace Botan {
class BOTAN_DLL TLS_PRF : public KDF
{
public:
- secure_vector<byte> derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte seed[], size_t seed_len) const;
-
std::string name() const { return "TLS-PRF"; }
+
KDF* clone() const { return new TLS_PRF; }
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
+
TLS_PRF();
private:
- std::unique_ptr<MessageAuthenticationCode> hmac_md5;
- std::unique_ptr<MessageAuthenticationCode> hmac_sha1;
+ std::unique_ptr<MessageAuthenticationCode> m_hmac_md5;
+ std::unique_ptr<MessageAuthenticationCode> m_hmac_sha1;
};
/**
@@ -38,14 +39,15 @@ class BOTAN_DLL TLS_PRF : public KDF
class BOTAN_DLL TLS_12_PRF : public KDF
{
public:
- secure_vector<byte> derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte seed[], size_t seed_len) const;
-
std::string name() const { return "TLS-12-PRF(" + m_mac->name() + ")"; }
+
KDF* clone() const { return new TLS_12_PRF(m_mac->clone()); }
- TLS_12_PRF(MessageAuthenticationCode* mac);
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
+
+ TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {}
static TLS_12_PRF* make(const Spec& spec);
private:
diff --git a/src/lib/kdf/prf_x942/prf_x942.cpp b/src/lib/kdf/prf_x942/prf_x942.cpp
index 30bf737a9..5ca0f01ff 100644
--- a/src/lib/kdf/prf_x942/prf_x942.cpp
+++ b/src/lib/kdf/prf_x942/prf_x942.cpp
@@ -9,7 +9,7 @@
#include <botan/prf_x942.h>
#include <botan/der_enc.h>
#include <botan/oids.h>
-#include <botan/sha160.h>
+#include <botan/hash.h>
#include <botan/loadstor.h>
#include <algorithm>
@@ -31,24 +31,22 @@ std::vector<byte> encode_x942_int(u32bit n)
}
-/*
-* X9.42 PRF
-*/
-secure_vector<byte> X942_PRF::derive(size_t key_len,
- const byte secret[], size_t secret_len,
- const byte salt[], size_t salt_len) const
+size_t X942_PRF::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
{
- SHA_160 hash;
- const OID kek_algo(key_wrap_oid);
+ std::unique_ptr<HashFunction> hash(make_a<HashFunction>("SHA-160"));
+ const OID kek_algo(m_key_wrap_oid);
- secure_vector<byte> key;
+ secure_vector<byte> h;
+ size_t offset = 0;
u32bit counter = 1;
- while(key.size() != key_len && counter)
+ while(offset != key_len && counter)
{
- hash.update(secret, secret_len);
+ hash->update(secret, secret_len);
- hash.update(
+ hash->update(
DER_Encoder().start_cons(SEQUENCE)
.start_cons(SEQUENCE)
@@ -70,14 +68,15 @@ secure_vector<byte> X942_PRF::derive(size_t key_len,
.end_cons().get_contents()
);
- secure_vector<byte> digest = hash.final();
- const size_t needed = std::min(digest.size(), key_len - key.size());
- key += std::make_pair(&digest[0], needed);
+ hash->final(h);
+ const size_t copied = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], &h[0], copied);
+ offset += copied;
++counter;
}
- return key;
+ return offset;
}
/*
@@ -86,9 +85,9 @@ secure_vector<byte> X942_PRF::derive(size_t key_len,
X942_PRF::X942_PRF(const std::string& oid)
{
if(OIDS::have_oid(oid))
- key_wrap_oid = OIDS::lookup(oid).as_string();
+ m_key_wrap_oid = OIDS::lookup(oid).as_string();
else
- key_wrap_oid = oid;
+ m_key_wrap_oid = oid;
}
}
diff --git a/src/lib/kdf/prf_x942/prf_x942.h b/src/lib/kdf/prf_x942/prf_x942.h
index d2678c127..242a83150 100644
--- a/src/lib/kdf/prf_x942/prf_x942.h
+++ b/src/lib/kdf/prf_x942/prf_x942.h
@@ -18,15 +18,17 @@ namespace Botan {
class BOTAN_DLL X942_PRF : public KDF
{
public:
- secure_vector<byte> derive(size_t, const byte[], size_t,
- const byte[], size_t) const;
+ std::string name() const { return "X942_PRF(" + m_key_wrap_oid + ")"; }
- std::string name() const { return "X942_PRF(" + key_wrap_oid + ")"; }
- KDF* clone() const { return new X942_PRF(key_wrap_oid); }
+ KDF* clone() const { return new X942_PRF(m_key_wrap_oid); }
+
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
X942_PRF(const std::string& oid);
private:
- std::string key_wrap_oid;
+ std::string m_key_wrap_oid;
};
}
diff --git a/src/lib/passhash/bcrypt/bcrypt.cpp b/src/lib/passhash/bcrypt/bcrypt.cpp
index 6766dc0d1..218404110 100644
--- a/src/lib/passhash/bcrypt/bcrypt.cpp
+++ b/src/lib/passhash/bcrypt/bcrypt.cpp
@@ -140,11 +140,13 @@ bool check_bcrypt(const std::string& pass, const std::string& hash)
const u16bit workfactor = to_u32bit(hash.substr(4, 2));
- std::vector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
+ const std::vector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
+ if(salt.size() != 16)
+ return false;
const std::string compare = make_bcrypt(pass, salt, workfactor);
- return (hash == compare);
+ return same_mem(hash.data(), compare.data(), compare.size());
}
}
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
diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp
index 42ecfb561..899ee98aa 100644
--- a/src/lib/pubkey/dlies/dlies.cpp
+++ b/src/lib/pubkey/dlies/dlies.cpp
@@ -44,14 +44,14 @@ std::vector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
vz += ka.derive_key(0, other_key).bits_of();
const size_t K_LENGTH = length + mac_keylen;
- OctetString K = kdf->derive_key(K_LENGTH, vz);
+ secure_vector<byte> K = kdf->derive_key(K_LENGTH, vz);
- if(K.length() != K_LENGTH)
+ if(K.size() != K_LENGTH)
throw Encoding_Error("DLIES: KDF did not provide sufficient output");
byte* C = &out[my_key.size()];
- xor_buf(C, K.begin() + mac_keylen, length);
- mac->set_key(K.begin(), mac_keylen);
+ mac->set_key(&K[0], mac_keylen);
+ xor_buf(C, &K[mac_keylen], length);
mac->update(C, length);
for(size_t j = 0; j != 8; ++j)
@@ -114,11 +114,11 @@ secure_vector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
vz += ka.derive_key(0, v).bits_of();
const size_t K_LENGTH = C.size() + mac_keylen;
- OctetString K = kdf->derive_key(K_LENGTH, vz);
- if(K.length() != K_LENGTH)
+ secure_vector<byte> K = kdf->derive_key(K_LENGTH, vz);
+ if(K.size() != K_LENGTH)
throw Encoding_Error("DLIES: KDF did not provide sufficient output");
- mac->set_key(K.begin(), mac_keylen);
+ mac->set_key(&K[0], mac_keylen);
mac->update(C);
for(size_t j = 0; j != 8; ++j)
mac->update(0);
@@ -126,7 +126,7 @@ secure_vector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
if(T != T2)
throw Decoding_Error("DLIES: message authentication failed");
- xor_buf(C, K.begin() + mac_keylen, C.size());
+ xor_buf(C, &K[0] + mac_keylen, C.size());
return C;
}
diff --git a/src/tests/data/kdf/kdf1.vec b/src/tests/data/kdf/kdf1.vec
index 14f605e5d..990fcf970 100644
--- a/src/tests/data/kdf/kdf1.vec
+++ b/src/tests/data/kdf/kdf1.vec
@@ -1,26 +1,26 @@
[KDF1(SHA-1)]
Secret = 61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A736F6964676A736F6964676A736F696A
Salt =
-OutputLen = 0
+OutputLen = 20
Output = A0D760447F105CE64DB99FF2FC92F961F24E7D9C
Secret = 61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A73
Salt = 6F6964676A736F6964676A736F696A
-OutputLen = 0
+OutputLen = 20
Output = A0D760447F105CE64DB99FF2FC92F961F24E7D9C
Secret = 61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A
Salt = 736F6964676A736F6964676A736F696A
-OutputLen = 0
+OutputLen = 20
Output = A0D760447F105CE64DB99FF2FC92F961F24E7D9C
Secret = 617361736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A736F6964676A736F6964676A736F696A0A
Salt =
-OutputLen = 0
+OutputLen = 20
Output = DBFEFA0EA12D352C4AE5B0AF17D061E0E2C469A8
Secret = 617361736F67696A6F7367696A736F69676A736F6964676A6F696A6F73646769
Salt = 6A736F6964676A736F6964676A736F696A0A
-OutputLen = 0
+OutputLen = 20
Output = DBFEFA0EA12D352C4AE5B0AF17D061E0E2C469A8