diff options
author | lloyd <[email protected]> | 2012-01-28 02:57:30 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-28 02:57:30 +0000 |
commit | 6e1544d590826b48aaf44273373a3fe58fa3df7d (patch) | |
tree | 8580b977bc53a19c3ef961f32a4566e48506f861 | |
parent | 467d07f38e31d5df6d12ae85ef68ba4317b10b68 (diff) |
Support alternate PRF hashes in TLS 1.2. Add support for the SHA-384
ciphersuites.
-rw-r--r-- | src/tls/finished.cpp | 18 | ||||
-rw-r--r-- | src/tls/tls_ciphersuite.cpp | 17 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.cpp | 72 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.h | 4 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 22 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 4 | ||||
-rw-r--r-- | src/tls/tls_magic.h | 7 | ||||
-rw-r--r-- | src/tls/tls_session_key.cpp | 20 |
8 files changed, 90 insertions, 74 deletions
diff --git a/src/tls/finished.cpp b/src/tls/finished.cpp index 140a3cb59..18cc51b96 100644 --- a/src/tls/finished.cpp +++ b/src/tls/finished.cpp @@ -6,9 +6,6 @@ */ #include <botan/internal/tls_messages.h> -#include <botan/prf_tls.h> -#include <botan/hmac.h> -#include <botan/sha2_32.h> #include <memory> namespace Botan { @@ -17,17 +14,6 @@ namespace TLS { namespace { -KDF* choose_tls_prf(Protocol_Version version) - { - if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11) - return new TLS_PRF; - else if(version == Protocol_Version::TLS_V12) - return new TLS_12_PRF(new HMAC(new SHA_256)); // might depend on ciphersuite - else - throw TLS_Exception(Alert::PROTOCOL_VERSION, - "Unknown version for PRF"); - } - /* * Compute the verify_data */ @@ -60,7 +46,7 @@ MemoryVector<byte> finished_compute_verify(Handshake_State* state, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69, 0x73, 0x68, 0x65, 0x64 }; - std::auto_ptr<KDF> prf(choose_tls_prf(state->version)); + std::auto_ptr<KDF> prf(state->protocol_specific_prf()); MemoryVector<byte> input; if(side == CLIENT) @@ -68,7 +54,7 @@ MemoryVector<byte> finished_compute_verify(Handshake_State* state, else input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); - input += state->hash.final(state->version); + input += state->hash.final(state->version, state->suite.mac_algo()); return prf->derive_key(12, state->keys.master_secret(), input); } diff --git a/src/tls/tls_ciphersuite.cpp b/src/tls/tls_ciphersuite.cpp index 15a8d5e12..b924ad8c7 100644 --- a/src/tls/tls_ciphersuite.cpp +++ b/src/tls/tls_ciphersuite.cpp @@ -106,6 +106,9 @@ Ciphersuite Ciphersuite::lookup_ciphersuite(u16bit suite) case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return Ciphersuite("RSA", "ECDH", "SHA-256", "AES-128", 16); + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return Ciphersuite("RSA", "ECDH", "SHA-384", "AES-256", 32); + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return Ciphersuite("RSA", "ECDH", "SHA-1", "3DES", 24); @@ -123,6 +126,9 @@ Ciphersuite Ciphersuite::lookup_ciphersuite(u16bit suite) case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return Ciphersuite("ECDSA", "ECDH", "SHA-256", "AES-128", 16); + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return Ciphersuite("ECDSA", "ECDH", "SHA-384", "AES-256", 32); + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return Ciphersuite("ECDSA", "ECDH", "SHA-1", "ARC4", 16); @@ -141,11 +147,14 @@ Ciphersuite Ciphersuite::lookup_ciphersuite(u16bit suite) return Ciphersuite("", "PSK", "SHA-1", "AES-128", 16); case TLS_PSK_WITH_AES_128_CBC_SHA256: - return Ciphersuite("", "PSK", "SHA-1", "AES-256", 16); + return Ciphersuite("", "PSK", "SHA-256", "AES-128", 16); case TLS_PSK_WITH_AES_256_CBC_SHA: return Ciphersuite("", "PSK", "SHA-1", "AES-256", 32); + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return Ciphersuite("", "PSK", "SHA-384", "AES-256", 32); + // PSK+DH ciphersuites case TLS_DHE_PSK_WITH_RC4_128_SHA: @@ -163,6 +172,9 @@ Ciphersuite Ciphersuite::lookup_ciphersuite(u16bit suite) case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: return Ciphersuite("", "DHE_PSK", "SHA-1", "AES-256", 32); + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return Ciphersuite("", "DHE_PSK", "SHA-384", "AES-256", 32); + // PSK+ECDH ciphersuites case TLS_ECDHE_PSK_WITH_RC4_128_SHA: @@ -180,6 +192,9 @@ Ciphersuite Ciphersuite::lookup_ciphersuite(u16bit suite) case TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: return Ciphersuite("", "ECDHE_PSK", "SHA-1", "AES-256", 32); + case TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + return Ciphersuite("", "ECDHE_PSK", "SHA-384", "AES-256", 32); + // SRP/RSA ciphersuites case TLS_SRP_SHA_RSA_WITH_AES_128_SHA: diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp index 1e5bd63a3..61295a95c 100644 --- a/src/tls/tls_handshake_hash.cpp +++ b/src/tls/tls_handshake_hash.cpp @@ -7,9 +7,8 @@ #include <botan/internal/tls_handshake_hash.h> #include <botan/tls_exceptn.h> -#include <botan/md5.h> -#include <botan/sha160.h> -#include <botan/sha2_32.h> +#include <botan/libstate.h> +#include <botan/hash.h> #include <memory> namespace Botan { @@ -17,7 +16,7 @@ namespace Botan { namespace TLS { void Handshake_Hash::update(Handshake_Type handshake_type, - const MemoryRegion<byte>& handshake_msg) + const MemoryRegion<byte>& handshake_msg) { update(static_cast<byte>(handshake_type)); @@ -31,33 +30,30 @@ void Handshake_Hash::update(Handshake_Type handshake_type, /** * Return a TLS Handshake Hash */ -SecureVector<byte> Handshake_Hash::final(Protocol_Version version) +SecureVector<byte> Handshake_Hash::final(Protocol_Version version, + const std::string& mac_algo) { - SecureVector<byte> output; + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::auto_ptr<HashFunction> hash; if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11) { - MD5 md5; - SHA_160 sha1; - - md5.update(data); - sha1.update(data); - - output += md5.final(); - output += sha1.final(); + hash.reset(af.make_hash_function("TLS.Digest.0")); } else if(version == Protocol_Version::TLS_V12) { - // This might depend on the ciphersuite - SHA_256 sha256; - sha256.update(data); - output += sha256.final(); + if(mac_algo == "SHA-1" || mac_algo == "SHA-256") + hash.reset(af.make_hash_function("SHA-256")); + else + hash.reset(af.make_hash_function(mac_algo)); } else throw TLS_Exception(Alert::PROTOCOL_VERSION, "Unknown version for handshake hashes"); - return output; + hash->update(data); + return hash->final(); } /** @@ -67,34 +63,38 @@ SecureVector<byte> Handshake_Hash::final_ssl3(const MemoryRegion<byte>& secret) { const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C; - MD5 md5; - SHA_160 sha1; + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::auto_ptr<HashFunction> md5(af.make_hash_function("MD5")); + std::auto_ptr<HashFunction> sha1(af.make_hash_function("SHA-1")); - md5.update(data); - sha1.update(data); + md5->update(data); + sha1->update(data); - md5.update(secret); - sha1.update(secret); + md5->update(secret); + sha1->update(secret); for(size_t i = 0; i != 48; ++i) - md5.update(PAD_INNER); + md5->update(PAD_INNER); for(size_t i = 0; i != 40; ++i) - sha1.update(PAD_INNER); + sha1->update(PAD_INNER); - SecureVector<byte> inner_md5 = md5.final(), inner_sha1 = sha1.final(); + SecureVector<byte> inner_md5 = md5->final(), inner_sha1 = sha1->final(); + + md5->update(secret); + sha1->update(secret); - md5.update(secret); - sha1.update(secret); for(size_t i = 0; i != 48; ++i) - md5.update(PAD_OUTER); + md5->update(PAD_OUTER); for(size_t i = 0; i != 40; ++i) - sha1.update(PAD_OUTER); - md5.update(inner_md5); - sha1.update(inner_sha1); + sha1->update(PAD_OUTER); + + md5->update(inner_md5); + sha1->update(inner_sha1); SecureVector<byte> output; - output += md5.final(); - output += sha1.final(); + output += md5->final(); + output += sha1->final(); return output; } diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h index 20f3c51fc..c13f97aa8 100644 --- a/src/tls/tls_handshake_hash.h +++ b/src/tls/tls_handshake_hash.h @@ -36,7 +36,9 @@ class Handshake_Hash void update(Handshake_Type handshake_type, const MemoryRegion<byte>& handshake_msg); - SecureVector<byte> final(Protocol_Version version); + SecureVector<byte> final(Protocol_Version version, + const std::string& mac_algo); + SecureVector<byte> final_ssl3(const MemoryRegion<byte>& master_secret); const SecureVector<byte>& get_contents() const diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp index 6e3d80ac2..9087031b6 100644 --- a/src/tls/tls_handshake_state.cpp +++ b/src/tls/tls_handshake_state.cpp @@ -8,6 +8,7 @@ #include <botan/internal/tls_handshake_state.h> #include <botan/internal/tls_messages.h> #include <botan/internal/assert.h> +#include <botan/lookup.h> namespace Botan { @@ -131,6 +132,27 @@ bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const return (hand_received_mask & mask); } +KDF* Handshake_State::protocol_specific_prf() + { + if(version == Protocol_Version::SSL_V3) + { + return get_kdf("SSL3-PRF"); + } + else if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11) + { + return get_kdf("TLS-PRF"); + } + else if(version == Protocol_Version::TLS_V12) + { + if(suite.mac_algo() == "SHA-1" || suite.mac_algo() == "SHA-256") + return get_kdf("TLS-12-PRF(SHA-256)"); + + return get_kdf("TLS-12-PRF(" + suite.mac_algo() + ")"); + } + + throw Internal_Error("Unknown version code " + version.to_string()); + } + std::pair<std::string, Signature_Format> Handshake_State::choose_sig_format(const Private_Key* key, std::string& hash_algo_out, diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h index 93846da52..5be5c3620 100644 --- a/src/tls/tls_handshake_state.h +++ b/src/tls/tls_handshake_state.h @@ -32,6 +32,8 @@ namespace Botan { +class KDF; + namespace TLS { /** @@ -60,6 +62,8 @@ class Handshake_State std::string& sig_algo, bool for_client_auth); + KDF* protocol_specific_prf(); + Protocol_Version version; class Client_Hello* client_hello; diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h index 9793b1ae2..946b13a04 100644 --- a/src/tls/tls_magic.h +++ b/src/tls/tls_magic.h @@ -87,30 +87,35 @@ enum Ciphersuite_Code { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024, TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028, TLS_PSK_WITH_RC4_128_SHA = 0x008A, TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B, TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D, - TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00B0, + TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE, + TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF, TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F, TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090, TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091, TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3, TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033, TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037, + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038, TLS_SRP_SHA_DSS_WITH_3DES_EDE_SHA = 0xC01C, TLS_SRP_SHA_DSS_WITH_AES_128_SHA = 0xC01F, diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp index 541f0b2d9..83ac7540b 100644 --- a/src/tls/tls_session_key.cpp +++ b/src/tls/tls_session_key.cpp @@ -15,22 +15,6 @@ namespace Botan { namespace TLS { -namespace { - -std::string lookup_prf_name(Protocol_Version version) - { - if(version == Protocol_Version::SSL_V3) - return "SSL3-PRF"; - else if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11) - return "TLS-PRF"; - else if(version == Protocol_Version::TLS_V12) - return "TLS-12-PRF(SHA-256)"; - else - throw Invalid_Argument("Session_Keys: Unknown version code"); - } - -} - /** * Session_Keys Constructor */ @@ -38,8 +22,6 @@ Session_Keys::Session_Keys(Handshake_State* state, const MemoryRegion<byte>& pre_master_secret, bool resuming) { - const std::string prf_name = lookup_prf_name(state->version); - const size_t mac_keylen = output_length_of(state->suite.mac_algo()); const size_t cipher_keylen = state->suite.cipher_keylen(); @@ -55,7 +37,7 @@ Session_Keys::Session_Keys(Handshake_State* state, const byte KEY_GEN_MAGIC[] = { 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E }; - std::auto_ptr<KDF> prf(get_kdf(prf_name)); + std::auto_ptr<KDF> prf(state->protocol_specific_prf()); if(resuming) { |