diff options
Diffstat (limited to 'src/tls/tls_extensions.cpp')
-rw-r--r-- | src/tls/tls_extensions.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
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 <botan/internal/tls_extensions.h> +#include <botan/internal/tls_reader.h> + +#include <stdio.h> + +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<byte> TLS_Extensions::serialize() const + { + MemoryVector<byte> 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<byte> 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<u16bit>(0, extn_val.size())); + buf.push_back(get_byte<u16bit>(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<byte>(); + + 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<byte> Server_Name_Indicator::serialize() const + { + MemoryVector<byte> buf; + + size_t name_len = sni_host_name.size(); + + buf.push_back(get_byte<u16bit>(0, name_len+3)); + buf.push_back(get_byte<u16bit>(1, name_len+3)); + buf.push_back(0); // DNS + + buf.push_back(get_byte<u16bit>(0, name_len)); + buf.push_back(get_byte<u16bit>(1, name_len)); + + + buf += std::make_pair( + reinterpret_cast<const byte*>(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<byte> SRP_Identifier::serialize() const + { + MemoryVector<byte> buf; + + const byte* srp_bytes = + reinterpret_cast<const byte*>(srp_identifier.data()); + + append_tls_length_value(buf, srp_bytes, srp_identifier.size(), 1); + + return buf; + } + + +} |