Botan 3.6.1
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/fmt.h>
14#include <botan/internal/loadstor.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() { return std::vector<uint8_t>(m_buf.begin() + m_offset, m_buf.end()); }
42
43 std::vector<uint8_t> get_data_read_so_far() {
44 return std::vector<uint8_t>(m_buf.begin(), m_buf.begin() + m_offset);
45 }
46
47 void discard_next(size_t bytes) {
48 assert_at_least(bytes);
49 m_offset += bytes;
50 }
51
52 uint32_t get_uint32_t() {
53 assert_at_least(4);
54 uint32_t result = make_uint32(m_buf[m_offset], m_buf[m_offset + 1], m_buf[m_offset + 2], m_buf[m_offset + 3]);
55 m_offset += 4;
56 return result;
57 }
58
59 uint32_t get_uint24_t() {
60 assert_at_least(3);
61 uint32_t result = make_uint32(0, m_buf[m_offset], m_buf[m_offset + 1], m_buf[m_offset + 2]);
62 m_offset += 3;
63 return result;
64 }
65
66 uint16_t get_uint16_t() {
67 assert_at_least(2);
68 uint16_t result = make_uint16(m_buf[m_offset], m_buf[m_offset + 1]);
69 m_offset += 2;
70 return result;
71 }
72
73 uint16_t peek_uint16_t() const {
74 assert_at_least(2);
75 return make_uint16(m_buf[m_offset], m_buf[m_offset + 1]);
76 }
77
78 uint8_t get_byte() {
79 assert_at_least(1);
80 uint8_t result = m_buf[m_offset];
81 m_offset += 1;
82 return result;
83 }
84
85 template <typename T, typename Container>
86 Container get_elem(size_t num_elems) {
87 assert_at_least(num_elems * sizeof(T));
88
89 Container result(num_elems);
90
91 for(size_t i = 0; i != num_elems; ++i) {
92 result[i] = load_be<T>(&m_buf[m_offset], i);
93 }
94
95 m_offset += num_elems * sizeof(T);
96
97 return result;
98 }
99
100 std::vector<uint8_t> get_tls_length_value(size_t len_bytes) {
101 return get_fixed<uint8_t>(get_length_field(len_bytes));
102 }
103
104 template <typename T>
105 std::vector<T> get_range(size_t len_bytes, size_t min_elems, size_t max_elems) {
106 const size_t num_elems = get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
107
108 return get_elem<T, std::vector<T>>(num_elems);
109 }
110
111 template <typename T>
112 std::vector<T> get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems) {
113 const size_t num_elems = get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
114
115 return get_elem<T, std::vector<T>>(num_elems);
116 }
117
118 std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes) {
119 std::vector<uint8_t> v = get_range_vector<uint8_t>(len_bytes, min_bytes, max_bytes);
120
121 return std::string(cast_uint8_ptr_to_char(v.data()), v.size());
122 }
123
124 template <typename T>
125 std::vector<T> get_fixed(size_t size) {
126 return get_elem<T, std::vector<T>>(size);
127 }
128
129 private:
130 size_t get_length_field(size_t len_bytes) {
131 assert_at_least(len_bytes);
132
133 if(len_bytes == 1) {
134 return get_byte();
135 } else if(len_bytes == 2) {
136 return get_uint16_t();
137 } else if(len_bytes == 3) {
138 return get_uint24_t();
139 }
140
141 throw_decode_error("Bad length size");
142 }
143
144 size_t get_num_elems(size_t len_bytes, size_t T_size, size_t min_elems, size_t max_elems) {
145 const size_t byte_length = get_length_field(len_bytes);
146
147 if(byte_length % T_size != 0) {
148 throw_decode_error("Size isn't multiple of T");
149 }
150
151 const size_t num_elems = byte_length / T_size;
152
153 if(num_elems < min_elems || num_elems > max_elems) {
154 throw_decode_error("Length field outside parameters");
155 }
156
157 return num_elems;
158 }
159
160 void assert_at_least(size_t n) const {
161 if(m_buf.size() - m_offset < n) {
162 throw_decode_error("Expected " + std::to_string(n) + " bytes remaining, only " +
163 std::to_string(m_buf.size() - m_offset) + " left");
164 }
165 }
166
167 [[noreturn]] void throw_decode_error(std::string_view why) const {
168 throw Decoding_Error(fmt("Invalid {}: {}", m_typename, why));
169 }
170
171 const char* m_typename;
172 std::span<const uint8_t> m_buf;
173 size_t m_offset;
174};
175
176/**
177* Helper function for encoding length-tagged vectors
178*/
179template <typename T, typename Alloc>
180void append_tls_length_value(std::vector<uint8_t, Alloc>& buf, const T* vals, size_t vals_size, size_t tag_size) {
181 const size_t T_size = sizeof(T);
182 const size_t val_bytes = T_size * vals_size;
183
184 if(tag_size != 1 && tag_size != 2 && tag_size != 3) {
185 throw Invalid_Argument("append_tls_length_value: invalid tag size");
186 }
187
188 if((tag_size == 1 && val_bytes > 255) || (tag_size == 2 && val_bytes > 65535) ||
189 (tag_size == 3 && val_bytes > 16777215)) {
190 throw Invalid_Argument("append_tls_length_value: value too large");
191 }
192
193 for(size_t i = 0; i != tag_size; ++i) {
194 buf.push_back(get_byte_var(sizeof(val_bytes) - tag_size + i, val_bytes));
195 }
196
197 for(size_t i = 0; i != vals_size; ++i) {
198 for(size_t j = 0; j != T_size; ++j) {
199 buf.push_back(get_byte_var(j, vals[i]));
200 }
201 }
202}
203
204template <typename T, typename Alloc, typename Alloc2>
205void append_tls_length_value(std::vector<uint8_t, Alloc>& buf, const std::vector<T, Alloc2>& vals, size_t tag_size) {
206 append_tls_length_value(buf, vals.data(), vals.size(), tag_size);
207}
208
209template <typename Alloc>
210void append_tls_length_value(std::vector<uint8_t, Alloc>& buf, std::string_view str, size_t tag_size) {
211 append_tls_length_value(buf, cast_char_ptr_to_uint8(str.data()), str.size(), tag_size);
212}
213
214} // namespace Botan::TLS
215
216#endif
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition tls_reader.h:118
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:47
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:86
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:105
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:100
std::vector< T > get_fixed(size_t size)
Definition tls_reader.h:125
std::vector< uint8_t > get_data_read_so_far()
Definition tls_reader.h:43
uint16_t peek_uint16_t() const
Definition tls_reader.h:73
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:112
int(* final)(unsigned char *, CTX *)
FE_25519 T
Definition ge.cpp:34
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:180
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition loadstor.h:100
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition mem_ops.h:277
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition loadstor.h:65
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:530
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition mem_ops.h:273
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition loadstor.h:88