diff options
author | lloyd <[email protected]> | 2008-09-27 15:46:02 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-27 15:46:02 +0000 |
commit | 4e5e7ed847a2f39a1f059e0c5403488571ef8e96 (patch) | |
tree | 84c9658717113585c9e96839874bd59eea7b2924 /src | |
parent | 224b5e6ed8e3154d185cf07e99bfd1e5556250fe (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.cpp | 2 | ||||
-rw-r--r-- | src/get_enc.cpp | 10 | ||||
-rw-r--r-- | src/ssl3_mac.cpp | 88 | ||||
-rw-r--r-- | src/ssl3_prf.cpp | 71 | ||||
-rw-r--r-- | src/tls_prf.cpp | 63 |
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; + } + +} |