diff options
author | lloyd <[email protected]> | 2010-03-30 15:24:36 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-03-30 15:24:36 +0000 |
commit | 40d0f36446d5d80dcc1e99c8707e2b84e82c5da0 (patch) | |
tree | f660c5cca710b7098d601c0d77d2a12fd3df2181 /src/ssl/tls_reader.h | |
parent | 9378baca4d4b2eb1f8d36177ada4dfc4015d46e8 (diff) |
Add a class that knows how to decode a (very small subset of) TLS data
formatting. Particularly useful in the ClientHello, but generally helps
centralize the offset handling, which was particularly unreadable in
the hello messages.
Diffstat (limited to 'src/ssl/tls_reader.h')
-rw-r--r-- | src/ssl/tls_reader.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/ssl/tls_reader.h b/src/ssl/tls_reader.h new file mode 100644 index 000000000..d2f21a90f --- /dev/null +++ b/src/ssl/tls_reader.h @@ -0,0 +1,124 @@ +/* +* TLS Data Reader +* (C) 2010 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_READER_H__ +#define BOTAN_TLS_READER_H__ + +#include <botan/secmem.h> +#include <botan/loadstor.h> + +namespace Botan { + +class TLS_Data_Reader + { + public: + TLS_Data_Reader(const MemoryRegion<byte>& buf_in) : + buf(buf_in), offset(0) {} + + u16bit get_u16bit() + { + assert_at_least(2); + u16bit result = make_u16bit(buf[offset], buf[offset+1]); + offset += 2; + return result; + } + + byte get_byte() + { + assert_at_least(1); + byte result = buf[offset]; + offset += 1; + return result; + } + + template<typename T, typename Container> + Container get_elem(u32bit num_elems) + { + assert_at_least(num_elems * sizeof(T)); + + Container result(num_elems); + + for(u32bit i = 0; i != num_elems; ++i) + result[i] = load_be<T>(&buf[offset], i); + + offset += num_elems * sizeof(T); + + return result; + } + + template<typename T> + SecureVector<T> get_range(u32bit len_bytes, + u32bit min_elems, + u32bit max_elems) + { + const u32bit num_elems = + get_num_elems(len_bytes, sizeof(T), min_elems, max_elems); + + return get_elem<T, SecureVector<T> >(num_elems); + } + + template<typename T> + std::vector<T> get_range_vector(u32bit len_bytes, + u32bit min_elems, + u32bit max_elems) + { + const u32bit num_elems = + get_num_elems(len_bytes, sizeof(T), min_elems, max_elems); + + return get_elem<T, std::vector<T> >(num_elems); + } + + template<typename T> + SecureVector<T> get_fixed(u32bit size) + { + return get_elem<T, SecureVector<T> >(size); + } + + private: + u32bit get_length_field(u32bit len_bytes) + { + assert_at_least(len_bytes); + + if(len_bytes == 1) + return get_byte(); + else if(len_bytes == 2) + return get_u16bit(); + + throw Decoding_Error("TLS_Data_Reader: Bad length size"); + } + + u32bit get_num_elems(u32bit len_bytes, + u32bit T_size, + u32bit min_elems, + u32bit max_elems) + { + const u32bit byte_length = get_length_field(len_bytes); + + if(byte_length % T_size != 0) + throw Decoding_Error("TLS_Data_Reader: Size isn't multiple of T"); + + const u32bit num_elems = byte_length / T_size; + + if(num_elems < min_elems || num_elems > max_elems) + throw Decoding_Error("TLS_Data_Reader: Range outside paramaters"); + + return num_elems; + } + + void assert_at_least(u32bit n) + { + if(buf.size() - offset < n) + throw Decoding_Error("TLS_Data_Reader: Corrupt packet"); + } + + const MemoryRegion<byte>& buf; + u32bit offset; + }; + +} + +#endif |