aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-28 02:57:30 +0000
committerlloyd <[email protected]>2012-01-28 02:57:30 +0000
commit6e1544d590826b48aaf44273373a3fe58fa3df7d (patch)
tree8580b977bc53a19c3ef961f32a4566e48506f861
parent467d07f38e31d5df6d12ae85ef68ba4317b10b68 (diff)
Support alternate PRF hashes in TLS 1.2. Add support for the SHA-384
ciphersuites.
-rw-r--r--src/tls/finished.cpp18
-rw-r--r--src/tls/tls_ciphersuite.cpp17
-rw-r--r--src/tls/tls_handshake_hash.cpp72
-rw-r--r--src/tls/tls_handshake_hash.h4
-rw-r--r--src/tls/tls_handshake_state.cpp22
-rw-r--r--src/tls/tls_handshake_state.h4
-rw-r--r--src/tls/tls_magic.h7
-rw-r--r--src/tls/tls_session_key.cpp20
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)
{