aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/kdf
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-10 03:41:59 +0000
committerlloyd <[email protected]>2014-01-10 03:41:59 +0000
commit6894dca64c04936d07048c0e8cbf7e25858548c3 (patch)
tree5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/kdf
parent9efa3be92442afb3d0b69890a36c7f122df18eda (diff)
Move lib into src
Diffstat (limited to 'src/lib/kdf')
-rw-r--r--src/lib/kdf/info.txt5
-rw-r--r--src/lib/kdf/kdf.cpp81
-rw-r--r--src/lib/kdf/kdf.h136
-rw-r--r--src/lib/kdf/kdf1/info.txt5
-rw-r--r--src/lib/kdf/kdf1/kdf1.cpp24
-rw-r--r--src/lib/kdf/kdf1/kdf1.h39
-rw-r--r--src/lib/kdf/kdf2/info.txt5
-rw-r--r--src/lib/kdf/kdf2/kdf2.cpp40
-rw-r--r--src/lib/kdf/kdf2/kdf2.h37
-rw-r--r--src/lib/kdf/mgf1/info.txt5
-rw-r--r--src/lib/kdf/mgf1/mgf1.cpp56
-rw-r--r--src/lib/kdf/mgf1/mgf1.h36
-rw-r--r--src/lib/kdf/prf_ssl3/info.txt7
-rw-r--r--src/lib/kdf/prf_ssl3/prf_ssl3.cpp76
-rw-r--r--src/lib/kdf/prf_ssl3/prf_ssl3.h30
-rw-r--r--src/lib/kdf/prf_tls/info.txt8
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.cpp117
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.h58
-rw-r--r--src/lib/kdf/prf_x942/info.txt7
-rw-r--r--src/lib/kdf/prf_x942/prf_x942.cpp92
-rw-r--r--src/lib/kdf/prf_x942/prf_x942.h34
21 files changed, 898 insertions, 0 deletions
diff --git a/src/lib/kdf/info.txt b/src/lib/kdf/info.txt
new file mode 100644
index 000000000..e9cbdeb1a
--- /dev/null
+++ b/src/lib/kdf/info.txt
@@ -0,0 +1,5 @@
+define KDF_BASE 20131128
+
+<requires>
+alloc
+</requires>
diff --git a/src/lib/kdf/kdf.cpp b/src/lib/kdf/kdf.cpp
new file mode 100644
index 000000000..84a0cdd15
--- /dev/null
+++ b/src/lib/kdf/kdf.cpp
@@ -0,0 +1,81 @@
+/*
+* KDF Retrieval
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_KDF1)
+ #include <botan/kdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ #include <botan/kdf2.h>
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ #include <botan/prf_x942.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ #include <botan/prf_ssl3.h>
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ #include <botan/prf_tls.h>
+#endif
+
+namespace Botan {
+
+KDF* get_kdf(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(request.algo_name() == "Raw")
+ return nullptr; // No KDF
+
+#if defined(BOTAN_HAS_KDF1)
+ if(request.algo_name() == "KDF1" && request.arg_count() == 1)
+ return new KDF1(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ if(request.algo_name() == "KDF2" && request.arg_count() == 1)
+ return new KDF2(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ if(request.algo_name() == "X9.42-PRF" && request.arg_count() == 1)
+ return new X942_PRF(request.arg(0)); // OID
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0)
+ return new SSL3_PRF;
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0)
+ return new TLS_PRF;
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0)
+ return new TLS_PRF;
+#endif
+
+#if defined(BOTAN_HAS_TLS_V12_PRF)
+ if(request.algo_name() == "TLS-12-PRF" && request.arg_count() == 1)
+ return new TLS_12_PRF(af.make_mac("HMAC(" + request.arg(0) + ")"));
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+}
diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h
new file mode 100644
index 000000000..b0f6e1dc3
--- /dev/null
+++ b/src/lib/kdf/kdf.h
@@ -0,0 +1,136 @@
+/*
+* KDF/MGF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF_BASE_H__
+#define BOTAN_KDF_BASE_H__
+
+#include <botan/algo_base.h>
+#include <botan/secmem.h>
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Key Derivation Function
+*/
+class BOTAN_DLL KDF : public Algorithm
+ {
+ public:
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ */
+ secure_vector<byte> derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
+ const std::string& salt = "") const
+ {
+ return derive_key(key_len, &secret[0], secret.size(),
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ */
+ template<typename Alloc, typename Alloc2>
+ secure_vector<byte> derive_key(size_t key_len,
+ const std::vector<byte, Alloc>& secret,
+ const std::vector<byte, Alloc2>& salt) const
+ {
+ return derive_key(key_len,
+ &secret[0], secret.size(),
+ &salt[0], salt.size());
+ }
+
+ /**
+ * Derive a key
+ * @param key_len the desired output length in bytes
+ * @param secret the secret input
+ * @param salt a diversifier
+ * @param salt_len size of salt in bytes
+ */
+ secure_vector<byte> derive_key(size_t key_len,
+ const secure_vector<byte>& secret,
+ const byte salt[],
+ size_t salt_len) const
+ {
+ return derive_key(key_len,
+ &secret[0], secret.size(),
+ salt, salt_len);
+ }
+
+ /**
+ * 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
+ */
+ secure_vector<byte> derive_key(size_t key_len,
+ const byte secret[],
+ size_t secret_len,
+ const std::string& salt = "") const
+ {
+ return derive_key(key_len, secret, secret_len,
+ reinterpret_cast<const byte*>(salt.data()),
+ 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);
+ }
+
+ void clear() {}
+
+ virtual KDF* clone() const = 0;
+ 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;
+ };
+
+/**
+* Mask Generation Function
+*/
+class BOTAN_DLL MGF
+ {
+ public:
+ virtual void mask(const byte in[], size_t in_len,
+ byte out[], size_t out_len) const = 0;
+
+ virtual ~MGF() {}
+ };
+
+/**
+* Factory method for KDF (key derivation function)
+* @param algo_spec the name of the KDF to create
+* @return pointer to newly allocated object of that type
+*/
+BOTAN_DLL KDF* get_kdf(const std::string& algo_spec);
+
+}
+
+#endif
diff --git a/src/lib/kdf/kdf1/info.txt b/src/lib/kdf/kdf1/info.txt
new file mode 100644
index 000000000..08192fa95
--- /dev/null
+++ b/src/lib/kdf/kdf1/info.txt
@@ -0,0 +1,5 @@
+define KDF1 20131128
+
+<requires>
+hash
+</requires>
diff --git a/src/lib/kdf/kdf1/kdf1.cpp b/src/lib/kdf/kdf1/kdf1.cpp
new file mode 100644
index 000000000..f00f71010
--- /dev/null
+++ b/src/lib/kdf/kdf1/kdf1.cpp
@@ -0,0 +1,24 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kdf1.h>
+
+namespace Botan {
+
+/*
+* 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
+ {
+ hash->update(secret, secret_len);
+ hash->update(P, P_len);
+ return hash->final();
+ }
+
+}
diff --git a/src/lib/kdf/kdf1/kdf1.h b/src/lib/kdf/kdf1/kdf1.h
new file mode 100644
index 000000000..6a14d2995
--- /dev/null
+++ b/src/lib/kdf/kdf1/kdf1.h
@@ -0,0 +1,39 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF1_H__
+#define BOTAN_KDF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* KDF1, from IEEE 1363
+*/
+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 { return "KDF1(" + hash->name() + ")"; }
+ KDF* clone() const { return new KDF1(hash->clone()); }
+
+ KDF1(HashFunction* h) : hash(h) {}
+ KDF1(const KDF1& other) : KDF(), hash(other.hash->clone()) {}
+
+ ~KDF1() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/src/lib/kdf/kdf2/info.txt b/src/lib/kdf/kdf2/info.txt
new file mode 100644
index 000000000..3481ff04f
--- /dev/null
+++ b/src/lib/kdf/kdf2/info.txt
@@ -0,0 +1,5 @@
+define KDF2 20131128
+
+<requires>
+hash
+</requires>
diff --git a/src/lib/kdf/kdf2/kdf2.cpp b/src/lib/kdf/kdf2/kdf2.cpp
new file mode 100644
index 000000000..39a929b58
--- /dev/null
+++ b/src/lib/kdf/kdf2/kdf2.cpp
@@ -0,0 +1,40 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kdf2.h>
+
+namespace Botan {
+
+/*
+* 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
+ {
+ secure_vector<byte> output;
+ u32bit counter = 1;
+
+ while(out_len && counter)
+ {
+ 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;
+ }
+
+ return output;
+ }
+
+}
diff --git a/src/lib/kdf/kdf2/kdf2.h b/src/lib/kdf/kdf2/kdf2.h
new file mode 100644
index 000000000..e33939df9
--- /dev/null
+++ b/src/lib/kdf/kdf2/kdf2.h
@@ -0,0 +1,37 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF2_H__
+#define BOTAN_KDF2_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* KDF2, from IEEE 1363
+*/
+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 { return "KDF2(" + hash->name() + ")"; }
+ KDF* clone() const { return new KDF2(hash->clone()); }
+
+ KDF2(HashFunction* h) : hash(h) {}
+ KDF2(const KDF2& other) : KDF(), hash(other.hash->clone()) {}
+ ~KDF2() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/src/lib/kdf/mgf1/info.txt b/src/lib/kdf/mgf1/info.txt
new file mode 100644
index 000000000..c6254b8a0
--- /dev/null
+++ b/src/lib/kdf/mgf1/info.txt
@@ -0,0 +1,5 @@
+define MGF1 20131128
+
+<requires>
+hash
+</requires>
diff --git a/src/lib/kdf/mgf1/mgf1.cpp b/src/lib/kdf/mgf1/mgf1.cpp
new file mode 100644
index 000000000..e0433a02f
--- /dev/null
+++ b/src/lib/kdf/mgf1/mgf1.cpp
@@ -0,0 +1,56 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mgf1.h>
+#include <botan/exceptn.h>
+#include <botan/internal/xor_buf.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*
+* MGF1 Mask Generation Function
+*/
+void MGF1::mask(const byte in[], size_t in_len, byte out[],
+ size_t out_len) const
+ {
+ u32bit counter = 0;
+
+ while(out_len)
+ {
+ hash->update(in, in_len);
+ hash->update_be(counter);
+ secure_vector<byte> buffer = hash->final();
+
+ size_t xored = std::min<size_t>(buffer.size(), out_len);
+ xor_buf(out, &buffer[0], xored);
+ out += xored;
+ out_len -= xored;
+
+ ++counter;
+ }
+ }
+
+/*
+* MGF1 Constructor
+*/
+MGF1::MGF1(HashFunction* h) : hash(h)
+ {
+ if(!hash)
+ throw Invalid_Argument("MGF1 given null hash object");
+ }
+
+/*
+* MGF1 Destructor
+*/
+MGF1::~MGF1()
+ {
+ delete hash;
+ }
+
+}
diff --git a/src/lib/kdf/mgf1/mgf1.h b/src/lib/kdf/mgf1/mgf1.h
new file mode 100644
index 000000000..95a2a2bc5
--- /dev/null
+++ b/src/lib/kdf/mgf1/mgf1.h
@@ -0,0 +1,36 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MGF1_H__
+#define BOTAN_MGF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* MGF1 from PKCS #1 v2.0
+*/
+class BOTAN_DLL MGF1 : public MGF
+ {
+ public:
+ void mask(const byte[], size_t, byte[], size_t) const;
+
+ /**
+ MGF1 constructor: takes ownership of hash
+ */
+ MGF1(HashFunction* hash);
+
+ ~MGF1();
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/src/lib/kdf/prf_ssl3/info.txt b/src/lib/kdf/prf_ssl3/info.txt
new file mode 100644
index 000000000..c4e830bac
--- /dev/null
+++ b/src/lib/kdf/prf_ssl3/info.txt
@@ -0,0 +1,7 @@
+define SSL_V3_PRF 20131128
+
+<requires>
+md5
+sha1
+algo_base
+</requires>
diff --git a/src/lib/kdf/prf_ssl3/prf_ssl3.cpp b/src/lib/kdf/prf_ssl3/prf_ssl3.cpp
new file mode 100644
index 000000000..93901416f
--- /dev/null
+++ b/src/lib/kdf/prf_ssl3/prf_ssl3.cpp
@@ -0,0 +1,76 @@
+/*
+* SSLv3 PRF
+* (C) 2004-2006 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_ssl3.h>
+#include <botan/symkey.h>
+#include <botan/exceptn.h>
+#include <botan/sha160.h>
+#include <botan/md5.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Return the next inner hash
+*/
+OctetString next_hash(size_t where, size_t want,
+ HashFunction& md5, HashFunction& sha1,
+ const byte secret[], size_t secret_len,
+ const byte seed[], size_t seed_len)
+ {
+ BOTAN_ASSERT(want <= md5.output_length(),
+ "Output size producable by MD5");
+
+ const byte ASCII_A_CHAR = 0x41;
+
+ for(size_t j = 0; j != where + 1; j++)
+ sha1.update(static_cast<byte>(ASCII_A_CHAR + where));
+ sha1.update(secret, secret_len);
+ sha1.update(seed, seed_len);
+ secure_vector<byte> sha1_hash = sha1.final();
+
+ md5.update(secret, secret_len);
+ md5.update(sha1_hash);
+ secure_vector<byte> md5_hash = md5.final();
+
+ return OctetString(&md5_hash[0], want);
+ }
+
+}
+
+/*
+* SSL3 PRF
+*/
+secure_vector<byte> SSL3_PRF::derive(size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte seed[], size_t seed_len) const
+ {
+ if(key_len > 416)
+ throw Invalid_Argument("SSL3_PRF: Requested key length is too large");
+
+ MD5 md5;
+ SHA_160 sha1;
+
+ OctetString output;
+
+ int counter = 0;
+ while(key_len)
+ {
+ const size_t produce = std::min<size_t>(key_len, md5.output_length());
+
+ output = output + next_hash(counter++, produce, md5, sha1,
+ secret, secret_len, seed, seed_len);
+
+ key_len -= produce;
+ }
+
+ return output.bits_of();
+ }
+
+}
diff --git a/src/lib/kdf/prf_ssl3/prf_ssl3.h b/src/lib/kdf/prf_ssl3/prf_ssl3.h
new file mode 100644
index 000000000..bae8badb8
--- /dev/null
+++ b/src/lib/kdf/prf_ssl3/prf_ssl3.h
@@ -0,0 +1,30 @@
+/*
+* SSLv3 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSLV3_PRF_H__
+#define BOTAN_SSLV3_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* PRF used in SSLv3
+*/
+class BOTAN_DLL SSL3_PRF : public KDF
+ {
+ public:
+ secure_vector<byte> derive(size_t, const byte[], size_t,
+ const byte[], size_t) const;
+
+ std::string name() const { return "SSL3-PRF"; }
+ KDF* clone() const { return new SSL3_PRF; }
+ };
+
+}
+
+#endif
diff --git a/src/lib/kdf/prf_tls/info.txt b/src/lib/kdf/prf_tls/info.txt
new file mode 100644
index 000000000..505e1ff1e
--- /dev/null
+++ b/src/lib/kdf/prf_tls/info.txt
@@ -0,0 +1,8 @@
+define TLS_V10_PRF 20131128
+define TLS_V12_PRF 20131128
+
+<requires>
+hmac
+md5
+sha1
+</requires>
diff --git a/src/lib/kdf/prf_tls/prf_tls.cpp b/src/lib/kdf/prf_tls/prf_tls.cpp
new file mode 100644
index 000000000..006b418c9
--- /dev/null
+++ b/src/lib/kdf/prf_tls/prf_tls.cpp
@@ -0,0 +1,117 @@
+/*
+* TLS v1.0 and v1.2 PRFs
+* (C) 2004-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_tls.h>
+#include <botan/internal/xor_buf.h>
+#include <botan/hmac.h>
+#include <botan/md5.h>
+#include <botan/sha160.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* TLS PRF P_hash function
+*/
+void P_hash(secure_vector<byte>& output,
+ MessageAuthenticationCode* mac,
+ const byte secret[], size_t secret_len,
+ const byte seed[], size_t seed_len)
+ {
+ try
+ {
+ mac->set_key(secret, secret_len);
+ }
+ catch(Invalid_Key_Length)
+ {
+ throw Internal_Error("The premaster secret of " +
+ std::to_string(secret_len) +
+ " bytes is too long for the PRF");
+ }
+
+ secure_vector<byte> A(seed, seed + seed_len);
+
+ size_t offset = 0;
+
+ while(offset != output.size())
+ {
+ 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();
+
+ xor_buf(&output[offset], &block[0], this_block_len);
+ offset += this_block_len;
+ }
+ }
+
+}
+
+/*
+* TLS PRF Constructor and Destructor
+*/
+TLS_PRF::TLS_PRF()
+ {
+ hmac_md5 = new HMAC(new MD5);
+ hmac_sha1 = new HMAC(new SHA_160);
+ }
+
+TLS_PRF::~TLS_PRF()
+ {
+ delete hmac_md5;
+ delete hmac_sha1;
+ }
+
+/*
+* 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
+ {
+ secure_vector<byte> output(key_len);
+
+ 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;
+ }
+
+/*
+* TLS v1.2 PRF Constructor and Destructor
+*/
+TLS_12_PRF::TLS_12_PRF(MessageAuthenticationCode* mac) : hmac(mac)
+ {
+ }
+
+TLS_12_PRF::~TLS_12_PRF()
+ {
+ delete hmac;
+ }
+
+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, hmac, secret, secret_len, seed, seed_len);
+
+ return output;
+ }
+
+}
diff --git a/src/lib/kdf/prf_tls/prf_tls.h b/src/lib/kdf/prf_tls/prf_tls.h
new file mode 100644
index 000000000..fce11eae0
--- /dev/null
+++ b/src/lib/kdf/prf_tls/prf_tls.h
@@ -0,0 +1,58 @@
+/*
+* TLS v1.0 and v1.2 PRFs
+* (C) 2004-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_PRF_H__
+#define BOTAN_TLS_PRF_H__
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* PRF used in TLS 1.0/1.1
+*/
+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; }
+
+ TLS_PRF();
+ ~TLS_PRF();
+ private:
+ MessageAuthenticationCode* hmac_md5;
+ MessageAuthenticationCode* hmac_sha1;
+ };
+
+/**
+* PRF used in TLS 1.2
+*/
+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 "TLSv12-PRF(" + hmac->name() + ")"; }
+ KDF* clone() const { return new TLS_12_PRF(hmac->clone()); }
+
+ TLS_12_PRF(MessageAuthenticationCode* hmac);
+ ~TLS_12_PRF();
+ private:
+ MessageAuthenticationCode* hmac;
+ };
+
+}
+
+#endif
diff --git a/src/lib/kdf/prf_x942/info.txt b/src/lib/kdf/prf_x942/info.txt
new file mode 100644
index 000000000..ff4a6f160
--- /dev/null
+++ b/src/lib/kdf/prf_x942/info.txt
@@ -0,0 +1,7 @@
+define X942_PRF 20131128
+
+<requires>
+asn1
+oid_lookup
+sha1
+</requires>
diff --git a/src/lib/kdf/prf_x942/prf_x942.cpp b/src/lib/kdf/prf_x942/prf_x942.cpp
new file mode 100644
index 000000000..149be163f
--- /dev/null
+++ b/src/lib/kdf/prf_x942/prf_x942.cpp
@@ -0,0 +1,92 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_x942.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/sha160.h>
+#include <botan/loadstor.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Encode an integer as an OCTET STRING
+*/
+std::vector<byte> encode_x942_int(u32bit n)
+ {
+ byte n_buf[4] = { 0 };
+ store_be(n, n_buf);
+ return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents_unlocked();
+ }
+
+}
+
+/*
+* 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
+ {
+ SHA_160 hash;
+ const OID kek_algo(key_wrap_oid);
+
+ secure_vector<byte> key;
+ u32bit counter = 1;
+
+ while(key.size() != key_len && counter)
+ {
+ hash.update(secret, secret_len);
+
+ hash.update(
+ DER_Encoder().start_cons(SEQUENCE)
+
+ .start_cons(SEQUENCE)
+ .encode(kek_algo)
+ .raw_bytes(encode_x942_int(counter))
+ .end_cons()
+
+ .encode_if(salt_len != 0,
+ DER_Encoder()
+ .start_explicit(0)
+ .encode(salt, salt_len, OCTET_STRING)
+ .end_explicit()
+ )
+
+ .start_explicit(2)
+ .raw_bytes(encode_x942_int(static_cast<u32bit>(8 * key_len)))
+ .end_explicit()
+
+ .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);
+
+ ++counter;
+ }
+
+ return key;
+ }
+
+/*
+* X9.42 Constructor
+*/
+X942_PRF::X942_PRF(const std::string& oid)
+ {
+ if(OIDS::have_oid(oid))
+ key_wrap_oid = OIDS::lookup(oid).as_string();
+ else
+ key_wrap_oid = oid;
+ }
+
+}
diff --git a/src/lib/kdf/prf_x942/prf_x942.h b/src/lib/kdf/prf_x942/prf_x942.h
new file mode 100644
index 000000000..f86b1bdd5
--- /dev/null
+++ b/src/lib/kdf/prf_x942/prf_x942.h
@@ -0,0 +1,34 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X942_PRF_H__
+#define BOTAN_ANSI_X942_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* PRF from ANSI X9.42
+*/
+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(" + key_wrap_oid + ")"; }
+ KDF* clone() const { return new X942_PRF(key_wrap_oid); }
+
+ X942_PRF(const std::string& oid);
+ private:
+ std::string key_wrap_oid;
+ };
+
+}
+
+#endif