Botan 3.11.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/assert.h>
12#include <botan/secmem.h>
13#include <botan/internal/loadstor.h>
14#include <botan/internal/mem_utils.h>
15#include <span>
16#include <string>
17#include <vector>
18
19namespace Botan::TLS {
20
21/**
22* Helper class for decoding TLS protocol messages
23*/
25 public:
26 TLS_Data_Reader(const char* type, std::span<const uint8_t> buf_in) :
27 m_typename(type), m_buf(buf_in), m_offset(0) {}
28
29 void assert_done() const {
30 if(has_remaining()) {
31 throw_decode_error("Extra bytes at end of message");
32 }
33 }
34
35 size_t read_so_far() const { return m_offset; }
36
37 size_t remaining_bytes() const { return m_buf.size() - m_offset; }
38
39 bool has_remaining() const { return (remaining_bytes() > 0); }
40
41 std::vector<uint8_t> get_remaining() {
42 const std::span rest = m_buf.subspan(m_offset);
43 return std::vector<uint8_t>(rest.begin(), rest.end());
44 }
45
46 std::vector<uint8_t> get_data_read_so_far() {
47 const std::span first = m_buf.first(m_offset);
48 return std::vector<uint8_t>(first.begin(), first.end());
49 }
50
51 void discard_next(size_t bytes) {
52 assert_at_least(bytes);
53 m_offset += bytes;
54 }
55
56 uint32_t get_uint32_t() {
57 assert_at_least(4);
58 const uint32_t result =
59 make_uint32(m_buf[m_offset], m_buf[m_offset + 1], m_buf[m_offset + 2], m_buf[m_offset + 3]);
60 m_offset += 4;
61 return result;
62 }
63
64 uint32_t get_uint24_t() {
65 assert_at_least(3);
66 const uint32_t result = make_uint32(0, m_buf[m_offset], m_buf[m_offset + 1], m_buf[m_offset + 2]);
67 m_offset += 3;
68 return result;
69 }
70
71 uint16_t get_uint16_t() {
72 assert_at_least(2);
73 const uint16_t result = make_uint16(m_buf[m_offset], m_buf[m_offset + 1]);
74 m_offset += 2;
75 return result;
76 }
77
78 uint16_t peek_uint16_t() const {
79 assert_at_least(2);
80 return make_uint16(m_buf[m_offset], m_buf[m_offset + 1]);
81 }
82
83 uint8_t get_byte() {
84 assert_at_least(1);
85 const uint8_t result = m_buf[m_offset];
86 m_offset += 1;
87 return result;
88 }
89
90 template <typename T, typename Container>
91 Container get_elem(size_t num_elems) {
92 assert_at_least(num_elems * sizeof(T));
93
94 Container result(num_elems);
95
96 for(size_t i = 0; i != num_elems; ++i) {
97 result[i] = load_be<T>(&m_buf[m_offset], i);
98 }
99
100 m_offset += num_elems * sizeof(T);
101
102 return result;
103 }
104
105 std::vector<uint8_t> get_tls_length_value(size_t len_bytes) {
106 return get_fixed<uint8_t>(get_length_field(len_bytes));
107 }
108
109 template <typename T>
110 std::vector<T> get_range(size_t len_bytes, size_t min_elems, size_t max_elems) {
111 const size_t num_elems = get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
112
113 return get_elem<T, std::vector<T>>(num_elems);
114 }
115
116 template <typename T>
117 std::vector<T> get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems) {
118 const size_t num_elems = get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
119
120 return get_elem<T, std::vector<T>>(num_elems);
121 }
122
123 std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes) {
124 std::vector<uint8_t> v = get_range_vector<uint8_t>(len_bytes, min_bytes, max_bytes);
125 return bytes_to_string(v);
126 }
127
128 template <typename T>
129 std::vector<T> get_fixed(size_t size) {
130 return get_elem<T, std::vector<T>>(size);
131 }
132
133 private:
134 size_t get_length_field(size_t len_bytes) {
135 assert_at_least(len_bytes);
136
137 if(len_bytes == 1) {
138 return get_byte();
139 } else if(len_bytes == 2) {
140 return get_uint16_t();
141 } else if(len_bytes == 3) {
142 return get_uint24_t();
143 }
144
145 throw_decode_error("Bad length size");
146 }
147
148 size_t get_num_elems(size_t len_bytes, size_t T_size, size_t min_elems, size_t max_elems) {
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
155 const size_t num_elems = byte_length / T_size;
156
157 if(num_elems < min_elems || num_elems > max_elems) {
158 throw_decode_error("Length field outside parameters");
159 }
160
161 return num_elems;
162 }
163
164 void assert_at_least(size_t n) const;
165
166 [[noreturn]] void throw_decode_error(std::string_view why) const;
167
168 const char* m_typename;
169 std::span<const uint8_t> m_buf;
170 size_t m_offset;
171};
172
173/**
174* Helper function for encoding length-tagged vectors
175*/
176template <typename T, typename Alloc>
177inline void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
178 const T* vals,
179 size_t vals_size,
180 size_t tag_size) {
181 const size_t T_size = sizeof(T);
182 const size_t val_bytes = T_size * vals_size;
183
184 BOTAN_ARG_CHECK(tag_size == 1 || tag_size == 2 || tag_size == 3, "Invalid TLS tag size");
185
186 const size_t max_possible_size = (1 << (8 * tag_size)) - 1;
187
188 BOTAN_ARG_CHECK(val_bytes <= max_possible_size, "Value too large to encode");
189
190 for(size_t i = 0; i != tag_size; ++i) {
191 buf.push_back(get_byte_var(sizeof(val_bytes) - tag_size + i, val_bytes));
192 }
193
194 for(size_t i = 0; i != vals_size; ++i) {
195 for(size_t j = 0; j != T_size; ++j) {
196 buf.push_back(get_byte_var(j, vals[i]));
197 }
198 }
199}
200
201template <typename T, typename Alloc>
202inline void append_tls_length_value(std::vector<uint8_t, Alloc>& buf, std::span<const T> vals, size_t tag_size) {
203 append_tls_length_value(buf, vals.data(), vals.size(), tag_size);
204}
205
206template <typename T, typename Alloc, typename Alloc2>
207inline void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
208 const std::vector<T, Alloc2>& vals,
209 size_t tag_size) {
210 append_tls_length_value(buf, std::span{vals}, tag_size);
211}
212
213template <typename Alloc>
214inline void append_tls_length_value(std::vector<uint8_t, Alloc>& buf, std::string_view str, size_t tag_size) {
215 append_tls_length_value(buf, as_span_of_bytes(str), tag_size);
216}
217
218} // namespace Botan::TLS
219
220#endif
#define BOTAN_TEST_API
Definition api.h:41
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition tls_reader.h:123
std::vector< uint8_t > get_remaining()
Definition tls_reader.h:41
size_t read_so_far() const
Definition tls_reader.h:35
void discard_next(size_t bytes)
Definition tls_reader.h:51
TLS_Data_Reader(const char *type, std::span< const uint8_t > buf_in)
Definition tls_reader.h:26
Container get_elem(size_t num_elems)
Definition tls_reader.h:91
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:110
size_t remaining_bytes() const
Definition tls_reader.h:37
std::vector< uint8_t > get_tls_length_value(size_t len_bytes)
Definition tls_reader.h:105
std::vector< T > get_fixed(size_t size)
Definition tls_reader.h:129
std::vector< uint8_t > get_data_read_so_far()
Definition tls_reader.h:46
uint16_t peek_uint16_t() const
Definition tls_reader.h:78
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:117
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:177
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:59
std::string bytes_to_string(std::span< const uint8_t > bytes)
Definition mem_utils.h:76
constexpr uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition loadstor.h:104
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition loadstor.h:69
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition loadstor.h:92