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