aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-09-27 15:46:02 +0000
committerlloyd <[email protected]>2008-09-27 15:46:02 +0000
commit4e5e7ed847a2f39a1f059e0c5403488571ef8e96 (patch)
tree84c9658717113585c9e96839874bd59eea7b2924 /src
parent224b5e6ed8e3154d185cf07e99bfd1e5556250fe (diff)
Add back from Ajisai 0.5.0 the implementations of the SSLv3 MAC and PRF
and the TLS v1.0 PRF. These were removed from Botan in v1.4.5. Initially I had felt that since these protocols were specific to SSL/TLS they should be placed in Ajisai (an SSL/TLS library based on Botan). However upon further reflection I have realized it is quite possible that other alternate implementations of SSL/TLS based on Botan would be quite desirable, and so to make that (a very slightly bit) easier I am adding back the SSL/TLS functions to Botan, so other SSL/TLS libs can use them directly.
Diffstat (limited to 'src')
-rw-r--r--src/def_alg.cpp2
-rw-r--r--src/get_enc.cpp10
-rw-r--r--src/ssl3_mac.cpp88
-rw-r--r--src/ssl3_prf.cpp71
-rw-r--r--src/tls_prf.cpp63
5 files changed, 234 insertions, 0 deletions
diff --git a/src/def_alg.cpp b/src/def_alg.cpp
index 29e99d6a0..bba904b11 100644
--- a/src/def_alg.cpp
+++ b/src/def_alg.cpp
@@ -57,6 +57,7 @@
#include <botan/cbc_mac.h>
#include <botan/cmac.h>
#include <botan/hmac.h>
+#include <botan/ssl3_mac.h>
#include <botan/x919_mac.h>
#include <botan/mode_pad.h>
@@ -233,6 +234,7 @@ Default_Engine::find_mac(const std::string& algo_spec) const
HANDLE_TYPE_ONE_STRING("CBC-MAC", CBC_MAC);
HANDLE_TYPE_ONE_STRING("CMAC", CMAC);
HANDLE_TYPE_ONE_STRING("HMAC", HMAC);
+ HANDLE_TYPE_ONE_STRING("SSL3-MAC", SSL3_MAC);
HANDLE_TYPE_NO_ARGS("X9.19-MAC", ANSI_X919_MAC);
return 0;
diff --git a/src/get_enc.cpp b/src/get_enc.cpp
index 29a166b2c..31c1e06aa 100644
--- a/src/get_enc.cpp
+++ b/src/get_enc.cpp
@@ -106,6 +106,16 @@ KDF* get_kdf(const std::string& algo_spec)
if(name.size() == 2)
return new X942_PRF(name[1]);
}
+ if(kdf_name == "TLS-PRF")
+ {
+ if(name.size() == 1)
+ return new TLS_PRF;
+ }
+ else if(kdf_name == "SSL3-PRF")
+ {
+ if(name.size() == 1)
+ return new SSL3_PRF;
+ }
else
throw Algorithm_Not_Found(algo_spec);
diff --git a/src/ssl3_mac.cpp b/src/ssl3_mac.cpp
new file mode 100644
index 000000000..ceb04bf44
--- /dev/null
+++ b/src/ssl3_mac.cpp
@@ -0,0 +1,88 @@
+/*************************************************
+* SSL3-MAC Source File *
+* (C) 1999-2004 Jack Lloyd *
+*************************************************/
+
+#include <botan/ssl3_mac.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+/*************************************************
+* Update a SSL3-MAC Calculation *
+*************************************************/
+void SSL3_MAC::add_data(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*************************************************
+* Finalize a SSL3-MAC Calculation *
+*************************************************/
+void SSL3_MAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, OUTPUT_LENGTH);
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*************************************************
+* SSL3-MAC Key Schedule *
+*************************************************/
+void SSL3_MAC::key(const byte key[], u32bit length)
+ {
+ hash->clear();
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ i_key.copy(key, length);
+ o_key.copy(key, length);
+ hash->update(i_key);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void SSL3_MAC::clear() throw()
+ {
+ hash->clear();
+ i_key.clear();
+ o_key.clear();
+ }
+
+/*************************************************
+* Return the name of this type *
+*************************************************/
+std::string SSL3_MAC::name() const
+ {
+ return "SSL3-MAC(" + hash->name() + ")";
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+MessageAuthenticationCode* SSL3_MAC::clone() const
+ {
+ return new SSL3_MAC(hash->name());
+ }
+
+/*************************************************
+* SSL3-MAC Constructor *
+*************************************************/
+SSL3_MAC::SSL3_MAC(const std::string& hash_name) :
+ MessageAuthenticationCode(output_length_of(hash_name),
+ output_length_of(hash_name)),
+ hash(get_hash(hash_name))
+ {
+ if(hash->name() != "MD5" && hash->name() != "SHA-160")
+ throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
+
+ const u32bit INNER_HASH_LENGTH = (hash->name() == "MD5") ? 64 : 60;
+
+ i_key.create(INNER_HASH_LENGTH);
+ o_key.create(INNER_HASH_LENGTH);
+ }
+
+}
diff --git a/src/ssl3_prf.cpp b/src/ssl3_prf.cpp
new file mode 100644
index 000000000..a86ed8ff7
--- /dev/null
+++ b/src/ssl3_prf.cpp
@@ -0,0 +1,71 @@
+/*************************************************
+* SSL3 PRF Source File *
+* (C) 2004-2006 Jack Lloyd *
+*************************************************/
+
+#include <botan/kdf.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Return the next inner hash *
+*************************************************/
+OctetString next_hash(u32bit where, u32bit want,
+ HashFunction* md5, HashFunction* sha1,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len)
+ {
+ if(want > md5->OUTPUT_LENGTH)
+ throw Internal_Error("SSL3_PRF:next_hash: want is too big");
+
+ const byte ASCII_A_CHAR = 0x41;
+
+ for(u32bit j = 0; j != where + 1; j++)
+ sha1->update(ASCII_A_CHAR + where);
+ sha1->update(secret, secret_len);
+ sha1->update(seed, seed_len);
+ SecureVector<byte> sha1_hash = sha1->final();
+
+ md5->update(secret, secret_len);
+ md5->update(sha1_hash);
+ SecureVector<byte> md5_hash = md5->final();
+
+ return OctetString(md5_hash, want);
+ }
+
+}
+
+/*************************************************
+* SSL3 PRF *
+*************************************************/
+SecureVector<byte> SSL3_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ if(key_len > 416)
+ throw Internal_Error("SSL3_PRF: Requested key length is too large");
+
+ std::auto_ptr<HashFunction> md5(get_hash("MD5"));
+ std::auto_ptr<HashFunction> sha1(get_hash("SHA-1"));
+
+ OctetString output;
+
+ int counter = 0;
+ while(key_len)
+ {
+ const u32bit produce = std::min(key_len, md5->OUTPUT_LENGTH);
+
+ output = output + next_hash(counter++, produce, md5.get(), sha1.get(),
+ secret, secret_len, seed, seed_len);
+
+ key_len -= produce;
+ }
+
+ return output.bits_of();
+ }
+
+}
diff --git a/src/tls_prf.cpp b/src/tls_prf.cpp
new file mode 100644
index 000000000..2222e3baa
--- /dev/null
+++ b/src/tls_prf.cpp
@@ -0,0 +1,63 @@
+/*************************************************
+* TLS PRF Source File *
+* (C) 2004-2006 Jack Lloyd *
+*************************************************/
+
+#include <botan/kdf.h>
+#include <botan/lookup.h>
+#include <botan/xor_buf.h>
+#include <botan/hmac.h>
+
+namespace Botan {
+
+/*************************************************
+* TLS PRF *
+*************************************************/
+SecureVector<byte> TLS_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ u32bit S1_len = (secret_len + 1) / 2,
+ S2_len = (secret_len + 1) / 2;
+ const byte* S1 = secret;
+ const byte* S2 = secret + (secret_len - S2_len);
+
+ SecureVector<byte> key1, key2;
+ key1 = P_hash("MD5", key_len, S1, S1_len, seed, seed_len);
+ key2 = P_hash("SHA-1", key_len, S2, S2_len, seed, seed_len);
+
+ xor_buf(key1.begin(), key2.begin(), key2.size());
+
+ return key1;
+ }
+
+/*************************************************
+* TLS PRF P_hash function *
+*************************************************/
+SecureVector<byte> TLS_PRF::P_hash(const std::string& hash, u32bit len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ SecureVector<byte> out;
+
+ HMAC hmac(hash);
+ hmac.set_key(secret, secret_len);
+
+ SecureVector<byte> A(seed, seed_len);
+ while(len)
+ {
+ const u32bit this_block_len = std::min(hmac.OUTPUT_LENGTH, len);
+
+ A = hmac.process(A);
+
+ hmac.update(A);
+ hmac.update(seed, seed_len);
+ SecureVector<byte> block = hmac.final();
+
+ out.append(block, this_block_len);
+ len -= this_block_len;
+ }
+ return out;
+ }
+
+}