Botan  2.4.0
Crypto and TLS for C++11
tls_reader.h
Go to the documentation of this file.
1 /*
2 * TLS Data Reader
3 * (C) 2010-2011,2014 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #ifndef BOTAN_TLS_READER_H_
9 #define BOTAN_TLS_READER_H_
10 
11 #include <botan/exceptn.h>
12 #include <botan/secmem.h>
13 #include <botan/loadstor.h>
14 #include <string>
15 #include <vector>
16 
17 namespace Botan {
18 
19 namespace TLS {
20 
21 /**
22 * Helper class for decoding TLS protocol messages
23 */
24 class TLS_Data_Reader final
25  {
26  public:
27  TLS_Data_Reader(const char* type, const std::vector<uint8_t>& buf_in) :
28  m_typename(type), m_buf(buf_in), m_offset(0) {}
29 
30  void assert_done() const
31  {
32  if(has_remaining())
33  throw decode_error("Extra bytes at end of message");
34  }
35 
36  size_t read_so_far() const { return m_offset; }
37 
38  size_t remaining_bytes() const { return m_buf.size() - m_offset; }
39 
40  bool has_remaining() const { return (remaining_bytes() > 0); }
41 
42  std::vector<uint8_t> get_remaining()
43  {
44  return std::vector<uint8_t>(m_buf.begin() + m_offset, m_buf.end());
45  }
46 
47  void discard_next(size_t bytes)
48  {
49  assert_at_least(bytes);
50  m_offset += bytes;
51  }
52 
53  uint32_t get_uint32_t()
54  {
55  assert_at_least(4);
56  uint32_t result = make_uint32(m_buf[m_offset ], m_buf[m_offset+1],
57  m_buf[m_offset+2], m_buf[m_offset+3]);
58  m_offset += 4;
59  return result;
60  }
61 
62  uint16_t get_uint16_t()
63  {
64  assert_at_least(2);
65  uint16_t result = make_uint16(m_buf[m_offset], m_buf[m_offset+1]);
66  m_offset += 2;
67  return result;
68  }
69 
70  uint8_t get_byte()
71  {
72  assert_at_least(1);
73  uint8_t result = m_buf[m_offset];
74  m_offset += 1;
75  return result;
76  }
77 
78  template<typename T, typename Container>
79  Container get_elem(size_t num_elems)
80  {
81  assert_at_least(num_elems * sizeof(T));
82 
83  Container result(num_elems);
84 
85  for(size_t i = 0; i != num_elems; ++i)
86  result[i] = load_be<T>(&m_buf[m_offset], i);
87 
88  m_offset += num_elems * sizeof(T);
89 
90  return result;
91  }
92 
93  template<typename T>
94  std::vector<T> get_range(size_t len_bytes,
95  size_t min_elems,
96  size_t max_elems)
97  {
98  const size_t num_elems =
99  get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
100 
101  return get_elem<T, std::vector<T> >(num_elems);
102  }
103 
104  template<typename T>
105  std::vector<T> get_range_vector(size_t len_bytes,
106  size_t min_elems,
107  size_t max_elems)
108  {
109  const size_t num_elems =
110  get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
111 
112  return get_elem<T, std::vector<T> >(num_elems);
113  }
114 
115  std::string get_string(size_t len_bytes,
116  size_t min_bytes,
117  size_t max_bytes)
118  {
119  std::vector<uint8_t> v =
120  get_range_vector<uint8_t>(len_bytes, min_bytes, max_bytes);
121 
122  return std::string(cast_uint8_ptr_to_char(v.data()), v.size());
123  }
124 
125  template<typename T>
126  std::vector<T> get_fixed(size_t size)
127  {
128  return get_elem<T, std::vector<T> >(size);
129  }
130 
131  private:
132  size_t get_length_field(size_t len_bytes)
133  {
134  assert_at_least(len_bytes);
135 
136  if(len_bytes == 1)
137  return get_byte();
138  else if(len_bytes == 2)
139  return get_uint16_t();
140 
141  throw decode_error("Bad length size");
142  }
143 
144  size_t get_num_elems(size_t len_bytes,
145  size_t T_size,
146  size_t min_elems,
147  size_t max_elems)
148  {
149  const size_t byte_length = get_length_field(len_bytes);
150 
151  if(byte_length % T_size != 0)
152  throw decode_error("Size isn't multiple of T");
153 
154  const size_t num_elems = byte_length / T_size;
155 
156  if(num_elems < min_elems || num_elems > max_elems)
157  throw decode_error("Length field outside parameters");
158 
159  return num_elems;
160  }
161 
162  void assert_at_least(size_t n) const
163  {
164  if(m_buf.size() - m_offset < n)
165  throw decode_error("Expected " + std::to_string(n) +
166  " bytes remaining, only " +
167  std::to_string(m_buf.size()-m_offset) +
168  " left");
169  }
170 
171  Decoding_Error decode_error(const std::string& why) const
172  {
173  return Decoding_Error("Invalid " + std::string(m_typename) + ": " + why);
174  }
175 
176  const char* m_typename;
177  const std::vector<uint8_t>& m_buf;
178  size_t m_offset;
179  };
180 
181 /**
182 * Helper function for encoding length-tagged vectors
183 */
184 template<typename T, typename Alloc>
185 void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
186  const T* vals,
187  size_t vals_size,
188  size_t tag_size)
189  {
190  const size_t T_size = sizeof(T);
191  const size_t val_bytes = T_size * vals_size;
192 
193  if(tag_size != 1 && tag_size != 2)
194  throw Invalid_Argument("append_tls_length_value: invalid tag size");
195 
196  if((tag_size == 1 && val_bytes > 255) ||
197  (tag_size == 2 && val_bytes > 65535))
198  throw Invalid_Argument("append_tls_length_value: value too large");
199 
200  for(size_t i = 0; i != tag_size; ++i)
201  buf.push_back(get_byte(sizeof(val_bytes)-tag_size+i, val_bytes));
202 
203  for(size_t i = 0; i != vals_size; ++i)
204  for(size_t j = 0; j != T_size; ++j)
205  buf.push_back(get_byte(j, vals[i]));
206  }
207 
208 template<typename T, typename Alloc, typename Alloc2>
209 void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
210  const std::vector<T, Alloc2>& vals,
211  size_t tag_size)
212  {
213  append_tls_length_value(buf, vals.data(), vals.size(), tag_size);
214  }
215 
216 template<typename Alloc>
217 void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
218  const std::string& str,
219  size_t tag_size)
220  {
222  cast_char_ptr_to_uint8(str.data()),
223  str.size(),
224  tag_size);
225  }
226 
227 }
228 
229 }
230 
231 #endif
std::vector< T > get_fixed(size_t size)
Definition: tls_reader.h:126
size_t read_so_far() const
Definition: tls_reader.h:36
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:120
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:108
MechanismType type
std::vector< uint8_t > get_remaining()
Definition: tls_reader.h:42
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition: tls_reader.h:115
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:105
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
Definition: alg_id.cpp:13
Container get_elem(size_t num_elems)
Definition: tls_reader.h:79
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:125
uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:52
void discard_next(size_t bytes)
Definition: tls_reader.h:47
TLS_Data_Reader(const char *type, const std::vector< uint8_t > &buf_in)
Definition: tls_reader.h:27
fe T
Definition: ge.cpp:37
size_t remaining_bytes() const
Definition: tls_reader.h:38
uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition: loadstor.h:65
bool has_remaining() const
Definition: tls_reader.h:40
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition: tls_reader.h:185