1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*
* TLS Record Reading
* (C) 2004-2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/
#include <botan/tls_record.h>
#include <botan/tls_exceptn.h>
#include <botan/internal/rounding.h>
namespace Botan {
namespace TLS {
Record_Reader::Record_Reader() :
m_readbuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE)
{
reset();
set_maximum_fragment_size(0);
}
/*
* Reset the state
*/
void Record_Reader::reset()
{
set_maximum_fragment_size(0);
m_macbuf.clear();
zeroise(m_readbuf);
m_readbuf_pos = 0;
m_read_cipherstate.reset();
m_version = Protocol_Version();
m_read_seq_no = 0;
}
void Record_Reader::set_maximum_fragment_size(size_t max_fragment)
{
if(max_fragment == 0)
m_max_fragment = MAX_PLAINTEXT_SIZE;
else
m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE);
}
/*
* Set the version to use
*/
void Record_Reader::set_version(Protocol_Version version)
{
m_version = version;
}
Protocol_Version Record_Reader::get_version() const
{
return m_version;
}
/*
* Set the keys for reading
*/
void Record_Reader::change_cipher_spec(Connection_Side side,
const Ciphersuite& suite,
const Session_Keys& keys,
byte compression_method)
{
if(compression_method != NO_COMPRESSION)
throw Internal_Error("Negotiated unknown compression algorithm");
m_read_seq_no = 0;
// flip side as we are reading
side = (side == CLIENT) ? SERVER : CLIENT;
m_read_cipherstate.reset(
new Connection_Cipher_State(m_version, side, suite, keys)
);
m_macbuf.resize(m_read_cipherstate->mac_size());
}
/*
* Retrieve the next record
*/
size_t Record_Reader::add_input(const byte input_array[], size_t input_sz,
size_t& consumed,
byte& msg_type,
std::vector<byte>& msg,
u64bit& msg_sequence)
{
const size_t needed = read_record(m_readbuf,
m_readbuf_pos,
input_array,
input_sz,
consumed,
msg_type,
msg,
m_read_seq_no,
m_version,
m_read_cipherstate.get());
if(needed)
return needed;
// full message decoded
if(msg.size() > m_max_fragment)
throw TLS_Exception(Alert::RECORD_OVERFLOW, "Plaintext record is too large");
msg_sequence = m_read_seq_no;
m_read_seq_no += 1;
return 0;
}
}
}
|