From b500ef1a58f977f5ce5869e7160615f7b44876e7 Mon Sep 17 00:00:00 2001 From: lloyd Date: Thu, 29 Dec 2011 17:18:56 +0000 Subject: Add support for sending server name indicator in client hello Add support for sending and reading the SRP identifier extension. Add some helper classes for managing TLS extensions Add ciphersuite codes for SRP key exchange. --- src/tls/tls_extensions.cpp | 150 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/tls/tls_extensions.cpp (limited to 'src/tls/tls_extensions.cpp') diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp new file mode 100644 index 000000000..b9881ea3a --- /dev/null +++ b/src/tls/tls_extensions.cpp @@ -0,0 +1,150 @@ +/* +* TLS Extensions +* (C) 2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include +#include + +#include + +namespace Botan { + +TLS_Extensions::TLS_Extensions(class TLS_Data_Reader& reader) + { + if(reader.has_remaining()) + { + const u16bit all_extn_size = reader.get_u16bit(); + + if(reader.remaining_bytes() != all_extn_size) + throw Decoding_Error("Bad extension size"); + + while(reader.has_remaining()) + { + const u16bit extension_code = reader.get_u16bit(); + const u16bit extension_size = reader.get_u16bit(); + + if(extension_code == TLSEXT_SERVER_NAME_INDICATION) + extensions.push_back(new Server_Name_Indicator(reader)); + else if(extension_code == TLSEXT_SRP_IDENTIFIER) + extensions.push_back(new SRP_Identifier(reader)); + else // unknown/unhandled extension + { + printf("Unknown extension code %d\n", extension_code); + reader.discard_next(extension_size); + } + } + } + } + +MemoryVector TLS_Extensions::serialize() const + { + MemoryVector buf(2); // allocate length + + for(size_t i = 0; i != extensions.size(); ++i) + { + if(extensions[i]->empty()) + continue; + + const u16bit extn_code = extensions[i]->type(); + + MemoryVector extn_val = extensions[i]->serialize(); + + printf("serializing extn %d of %d bytes\n", extn_code, extn_val.size()); + + buf.push_back(get_byte(0, extn_code)); + buf.push_back(get_byte(1, extn_code)); + + buf.push_back(get_byte(0, extn_val.size())); + buf.push_back(get_byte(1, extn_val.size())); + + buf += extn_val; + } + + const u16bit extn_size = buf.size() - 2; + + buf[0] = get_byte(0, extn_size); + buf[1] = get_byte(1, extn_size); + + printf("%d bytes of extensions\n", buf.size()); + + // avoid sending an empty extensions block + if(buf.size() == 2) + return MemoryVector(); + + return buf; + } + +TLS_Extensions::~TLS_Extensions() + { + for(size_t i = 0; i != extensions.size(); ++i) + delete extensions[i]; + extensions.clear(); + } + +Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader) + { + u16bit name_bytes = reader.get_u16bit(); + + while(name_bytes) + { + byte name_type = reader.get_byte(); + name_bytes--; + + if(name_type == 0) // DNS + { + sni_host_name = reader.get_string(2, 1, 65535); + name_bytes -= (2 + sni_host_name.size()); + } + else // some other unknown name type + { + reader.discard_next(name_bytes); + name_bytes = 0; + } + } + } + +MemoryVector Server_Name_Indicator::serialize() const + { + MemoryVector buf; + + size_t name_len = sni_host_name.size(); + + buf.push_back(get_byte(0, name_len+3)); + buf.push_back(get_byte(1, name_len+3)); + buf.push_back(0); // DNS + + buf.push_back(get_byte(0, name_len)); + buf.push_back(get_byte(1, name_len)); + + + buf += std::make_pair( + reinterpret_cast(sni_host_name.data()), + sni_host_name.size()); + + printf("serializing %d bytes %s\n", buf.size(), + sni_host_name.c_str()); + return buf; + } + +SRP_Identifier::SRP_Identifier(TLS_Data_Reader& reader) + { + srp_identifier = reader.get_string(1, 1, 255); + } + +MemoryVector SRP_Identifier::serialize() const + { + MemoryVector buf; + + const byte* srp_bytes = + reinterpret_cast(srp_identifier.data()); + + append_tls_length_value(buf, srp_bytes, srp_identifier.size(), 1); + + return buf; + } + + +} -- cgit v1.2.3