Botan: Botan::Record_Reader Class Reference

Botan 1.10.16

Public Member Functions | List of all members
Botan::Record_Reader Class Reference

`#include <tls_record.h>`

## Public Member Functions
void | add_input (const byte input[], size_t input_size)
size_t | get_record (byte &msg_type, MemoryRegion< byte > &buffer)
SecureVector< byte > | get_record (byte &msg_type)
| Record_Reader ()
void | reset ()
void | set_keys (const CipherSuite &suite, const SessionKeys &keys, Connection_Side side)
void | set_version (Version_Code version)
| ~Record_Reader ()

## Detailed Description

TLS Record Reader

Definition at line 79 of file tls_record.h.

## Constructor & Destructor Documentation

## ◆ Record_Reader()

Botan::Record_Reader::Record_Reader | ( |  | ) |
| inline

Definition at line 102 of file tls_record.h.

102 { mac = 0; reset(); }
Botan::Record_Reader::reset
void reset()
Definition: rec_read.cpp:17

## ◆ ~Record_Reader()

Botan::Record_Reader::~Record_Reader | ( |  | ) |
| inline

Definition at line 104 of file tls_record.h.

104 { delete mac; }

## Member Function Documentation

## ◆ add_input()

void Botan::Record_Reader::add_input | ( | const byte | input[],
|  | size_t | input_size
| ) |  |

Definition at line 111 of file rec_read.cpp.

References Botan::SecureQueue::write().

Referenced by Botan::TLS_Server::close(), and Botan::TLS_Client::is_closed().

112 {
113 input_queue.write(input, input_size);
114 }
Botan::SecureQueue::write
void write(const byte[], size_t)
Definition: secqueue.cpp:117

## ◆ get_record() [1/2]

size_t Botan::Record_Reader::get_record | ( | byte & | msg_type,
|  | MemoryRegion< byte > & | buffer
| ) |  |

Parameters

  msg_type | (output variable)
  buffer | (output variable)

Returns
  Number of bytes still needed (minimum), or 0 if success

Definition at line 119 of file rec_read.cpp.

References Botan::ALERT, Botan::APPLICATION_DATA, Botan::BAD_RECORD_MAC, Botan::CHANGE_CIPHER_SPEC, Botan::CLIENT_HELLO_SSLV2, Botan::copy_mem(), Botan::Buffered_Computation::final(), Botan::get_byte(), Botan::HANDSHAKE, Botan::Pipe::LAST_MESSAGE, Botan::make_u16bit(), Botan::SecureQueue::peek(), Botan::Pipe::process_msg(), Botan::PROTOCOL_VERSION, Botan::SecureQueue::read(), Botan::Pipe::read_all(), Botan::MemoryRegion< T >::resize(), Botan::MemoryRegion< T >::size(), Botan::SecureQueue::size(), Botan::SSL_V3, Botan::UNEXPECTED_MESSAGE, Botan::Buffered_Computation::update(), and Botan::Buffered_Computation::update_be().

Referenced by Botan::TLS_Server::close(), and Botan::TLS_Client::is_closed().

121 {
122 byte header[5] = { 0 };
123
124 const size_t have_in_queue = input_queue.size();
125
126 if(have_in_queue < sizeof(header))
127 return (sizeof(header) - have_in_queue);
128
129 /*
130 * We peek first to make sure we have the full record
131 */
132 input_queue.peek(header, sizeof(header));
133
134 // SSLv2-format client hello?
135 if(header[0] & 0x80 && header[2] == 1 && header[3] == 3)
136 {
137 size_t record_len = make_u16bit(header[0], header[1]) & 0x7FFF;
138
139 if(have_in_queue < record_len + 2)
140 return (record_len + 2 - have_in_queue);
141
142 msg_type = HANDSHAKE;
143 output.resize(record_len + 4);
144
145 input_queue.read(&output[2], record_len + 2);
146 output[0] = CLIENT_HELLO_SSLV2;
147 output[1] = 0;
148 output[2] = header[0] & 0x7F;
149 output[3] = header[1];
150
151 return 0;
152 }
153
154 if(header[0] != CHANGE_CIPHER_SPEC &&
155 header[0] != ALERT &&
156 header[0] != HANDSHAKE &&
157 header[0] != APPLICATION_DATA)
158 {
159 throw TLS_Exception(UNEXPECTED_MESSAGE,
160 "Record_Reader: Unknown record type");
161 }
162
163 const u16bit version = make_u16bit(header[1], header[2]);
164 const u16bit record_len = make_u16bit(header[3], header[4]);
165
166 if(major && (header[1] != major || header[2] != minor))
167 throw TLS_Exception(PROTOCOL_VERSION,
168 "Record_Reader: Got unexpected version");
169
170 // If insufficient data, return without doing anything
171 if(have_in_queue < (sizeof(header) + record_len))
172 return (sizeof(header) + record_len - have_in_queue);
173
174 SecureVector<byte> buffer(record_len);
175
176 input_queue.read(header, sizeof(header)); // pull off the header
177 input_queue.read(&buffer[0], buffer.size());
178
179 /*
180 * We are handshaking, no crypto to do so return as-is
181 * TODO: Check msg_type to confirm a handshake?
182 */
183 if(mac_size == 0)
184 {
185 msg_type = header[0];
186 output = buffer;
187 return 0; // got a full record
188 }
189
190 // Otherwise, decrypt, check MAC, return plaintext
191
192 cipher.process_msg(buffer);
193 SecureVector<byte> plaintext = cipher.read_all(Pipe::LAST_MESSAGE);
194
195 size_t pad_size = 0;
196
197 if(block_size)
198 {
199 byte pad_value = plaintext[plaintext.size()-1];
200 pad_size = pad_value + 1;
201
202 /*
203 * Check the padding; if it is wrong, then say we have 0 bytes of
204 * padding, which should ensure that the MAC check below does not
205 * suceed. This hides a timing channel.
206 *
207 * This particular countermeasure is recommended in the TLS 1.2
208 * spec (RFC 5246) in section 6.2.3.2
209 */
210 if(version == SSL_V3)
211 {
212 if(pad_value > block_size)
213 pad_size = 0;
214 }
215 else
216 {
217 bool padding_good = true;
218
219 for(size_t i = 0; i != pad_size; ++i)
220 if(plaintext[plaintext.size()-i-1] != pad_value)
221 padding_good = false;
222
223 if(!padding_good)
224 pad_size = 0;
225 }
226 }
227
228 if(plaintext.size() < mac_size + pad_size + iv_size)
229 throw Decoding_Error("Record_Reader: Record truncated");
230
231 const size_t mac_offset = plaintext.size() - (mac_size + pad_size);
232 SecureVector<byte> received_mac(&plaintext[mac_offset],
233 mac_size);
234
235 const u16bit plain_length = plaintext.size() - (mac_size + pad_size + iv_size);
236
237 mac->update_be(seq_no);
238 mac->update(header[0]); // msg_type
239
240 if(version != SSL_V3)
241 for(size_t i = 0; i != 2; ++i)
242 mac->update(get_byte(i, version));
243
244 mac->update_be(plain_length);
245 mac->update(&plaintext[iv_size], plain_length);
246
247 ++seq_no;
248
249 SecureVector<byte> computed_mac = mac->final();
250
251 if(received_mac != computed_mac)
252 throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure");
253
254 msg_type = header[0];
255
256 output.resize(plain_length);
257 copy_mem(&output[0], &plaintext[iv_size], plain_length);
258 return 0;
259 }
Botan::SecureQueue::size
size_t size() const
Definition: secqueue.cpp:190
Botan::ALERT
Definition: tls_magic.h:35
Botan::SecureQueue::read
size_t read(byte[], size_t)
Definition: secqueue.cpp:137
Botan::UNEXPECTED_MESSAGE
Definition: tls_magic.h:64
Botan::HANDSHAKE
Definition: tls_magic.h:36
Botan::get_byte
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
Botan::CLIENT_HELLO_SSLV2
Definition: tls_magic.h:43
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::BAD_RECORD_MAC
Definition: tls_magic.h:65
Botan::Pipe::read_all
SecureVector< byte > read_all(message_id msg=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:105
Botan::Pipe::LAST_MESSAGE
static const message_id LAST_MESSAGE
Definition: pipe.h:52
Botan::Buffered_Computation::update
void update(const byte in[], size_t length)
Definition: buf_comp.h:33
Botan::u16bit
unsigned short u16bit
Definition: types.h:27
Botan::PROTOCOL_VERSION
Definition: tls_magic.h:81
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
Botan::SSL_V3
Definition: tls_magic.h:24
Botan::Buffered_Computation::final
void final(byte out[])
Definition: buf_comp.h:80
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::make_u16bit
u16bit make_u16bit(byte i0, byte i1)
Definition: loadstor.h:47
Botan::SecureQueue::peek
size_t peek(byte[], size_t, size_t=0) const
Definition: secqueue.cpp:159
Botan::APPLICATION_DATA
Definition: tls_magic.h:37
Botan::Buffered_Computation::update_be
void update_be(const T in)
Definition: buf_comp.h:48
Botan::CHANGE_CIPHER_SPEC
Definition: tls_magic.h:34
Botan::Pipe::process_msg
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:116

## ◆ get_record() [2/2]

SecureVector<byte> Botan::Record_Reader::get_record | ( | byte & | msg_type | ) |

## ◆ reset()

void Botan::Record_Reader::reset | ( |  | ) |

Definition at line 17 of file rec_read.cpp.

References Botan::Pipe::reset().

Referenced by Botan::TLS_Server::close(), Botan::TLS_Client::is_closed(), and Botan::TLS_Client::~TLS_Client().

18 {
19 cipher.reset();
20
21 delete mac;
22 mac = 0;
23
24 mac_size = 0;
25 block_size = 0;
26 iv_size = 0;
27 major = minor = 0;
28 seq_no = 0;
29 }
Botan::Pipe::reset
void reset()
Definition: pipe.cpp:76

## ◆ set_keys()

void Botan::Record_Reader::set_keys | ( | const CipherSuite & | suite,
|  | const SessionKeys & | keys,
|  | Connection_Side | side
| ) |  |

Definition at line 46 of file rec_read.cpp.

References Botan::Library_State::algorithm_factory(), Botan::Pipe::append(), Botan::block_size_of(), Botan::CipherSuite::cipher_algo(), Botan::CLIENT, Botan::SessionKeys::client_cipher_key(), Botan::SessionKeys::client_iv(), Botan::SessionKeys::client_mac_key(), Botan::DECRYPTION, Botan::get_cipher(), Botan::Global_State_Management::global_state(), Botan::have_block_cipher(), Botan::have_hash(), Botan::have_stream_cipher(), Botan::CipherSuite::mac_algo(), Botan::Algorithm_Factory::make_mac(), Botan::Buffered_Computation::output_length(), Botan::Pipe::reset(), Botan::SessionKeys::server_cipher_key(), Botan::SessionKeys::server_iv(), Botan::SessionKeys::server_mac_key(), and Botan::SymmetricAlgorithm::set_key().

Referenced by Botan::TLS_Server::close(), and Botan::TLS_Client::is_closed().

48 {
49 cipher.reset();
50 delete mac;
51 mac = 0;
52 seq_no = 0;
53
54 SymmetricKey mac_key, cipher_key;
55 InitializationVector iv;
56
57 if(side == CLIENT)
58 {
59 cipher_key = keys.server_cipher_key();
60 iv = keys.server_iv();
61 mac_key = keys.server_mac_key();
62 }
63 else
64 {
65 cipher_key = keys.client_cipher_key();
66 iv = keys.client_iv();
67 mac_key = keys.client_mac_key();
68 }
69
70 const std::string cipher_algo = suite.cipher_algo();
71 const std::string mac_algo = suite.mac_algo();
72
73 if(have_block_cipher(cipher_algo))
74 {
75 cipher.append(get_cipher(
76 cipher_algo + "/CBC/NoPadding",
77 cipher_key, iv, DECRYPTION)
78 );
79 block_size = block_size_of(cipher_algo);
80
81 if(major > 3 || (major == 3 && minor >= 2))
82 iv_size = block_size;
83 else
84 iv_size = 0;
85 }
86 else if(have_stream_cipher(cipher_algo))
87 {
88 cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION));
89 block_size = 0;
90 iv_size = 0;
91 }
92 else
93 throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo);
94
95 if(have_hash(mac_algo))
96 {
97 Algorithm_Factory& af = global_state().algorithm_factory();
98
99 if(major == 3 && minor == 0)
100 mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
101 else
102 mac = af.make_mac("HMAC(" + mac_algo + ")");
103
104 mac->set_key(mac_key);
105 mac_size = mac->output_length();
106 }
107 else
108 throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo);
109 }
Botan::Pipe::append
void append(Filter *filt)
Definition: pipe.cpp:215
Botan::Library_State::algorithm_factory
Algorithm_Factory & algorithm_factory() const
Definition: libstate.cpp:173
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::Pipe::reset
void reset()
Definition: pipe.cpp:76
Botan::DECRYPTION
Definition: sym_algo.h:87
Botan::SymmetricKey
OctetString SymmetricKey
Definition: symkey.h:147
Botan::SymmetricAlgorithm::set_key
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:60
Botan::Global_State_Management::global_state
Library_State & global_state()
Definition: global_state.cpp:32
Botan::block_size_of
size_t block_size_of(const std::string &name)
Definition: lookup.cpp:35
Botan::have_stream_cipher
bool have_stream_cipher(const std::string &algo_spec)
Definition: lookup.h:248
Botan::have_hash
bool have_hash(const std::string &algo_spec)
Definition: lookup.h:261
Botan::have_block_cipher
bool have_block_cipher(const std::string &algo_spec)
Definition: lookup.h:235
Botan::get_cipher
Keyed_Filter * get_cipher(const std::string &algo_spec, Cipher_Dir direction)
Definition: lookup.cpp:124
Botan::Buffered_Computation::output_length
virtual size_t output_length() const =0
Botan::CLIENT
Definition: tls_magic.h:29
Botan::InitializationVector
OctetString InitializationVector
Definition: symkey.h:152

## ◆ set_version()

void Botan::Record_Reader::set_version | ( | Version_Code | version | ) |

Definition at line 34 of file rec_read.cpp.

References Botan::SSL_V3, Botan::TLS_V10, and Botan::TLS_V11.

Referenced by Botan::TLS_Server::close(), and Botan::TLS_Client::is_closed().

35 {
36 if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11)
37 throw Invalid_Argument("Record_Reader: Invalid protocol version");
38
39 major = (version >> 8) & 0xFF;
40 minor = (version & 0xFF);
41 }
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::TLS_V10
Definition: tls_magic.h:25
Botan::SSL_V3
Definition: tls_magic.h:24
Botan::TLS_V11
Definition: tls_magic.h:26

The documentation for this class was generated from the following files:

- src/ssl/tls_record.h
- src/ssl/rec_read.cpp