Botan: src/ssl/rec_wri.cpp Source File

Botan 1.10.17

rec_wri.cpp
Go to the documentation of this file.
1 /*
2 * TLS Record Writing
3 * (C) 2004-2010 Jack Lloyd
4 *
5 * Released under the terms of the Botan license
6 */
7
8 #include <botan/tls_record.h>
9 #include <botan/internal/tls_handshake_hash.h>
10 #include <botan/lookup.h>
11 #include <botan/loadstor.h>
12 #include <botan/libstate.h>
13
14 namespace Botan {
15
16 /**
17 * Record_Writer Constructor
18 */
19 Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out) :
20 output_fn(out),
21 buffer(DEFAULT_BUFFERSIZE)
22 {
23 mac = 0;
24 reset();
25 }
26
27 /**
28 * Reset the state
29 */
30 void Record_Writer::reset()
31 {
32 cipher.reset();
33
34 delete mac;
35 mac = 0;
36
37 zeroise(buffer);
38 buf_pos = 0;
39
40 major = minor = buf_type = 0;
41 block_size = 0;
42 mac_size = 0;
43 iv_size = 0;
44
45 seq_no = 0;
46 }
47
48 /**
49 * Set the version to use
50 */
51 void Record_Writer::set_version(Version_Code version)
52 {
53 if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11)
54 throw Invalid_Argument("Record_Writer: Invalid protocol version");
55
56 major = (version >> 8) & 0xFF;
57 minor = (version & 0xFF);
58 }
59
60 /**
61 * Set the keys for writing
62 */
63 void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys,
64 Connection_Side side)
65 {
66 cipher.reset();
67 delete mac;
68 mac = 0;
69 seq_no = 0;
70
71 SymmetricKey mac_key, cipher_key;
72 InitializationVector iv;
73
74 if(side == CLIENT)
75 {
76 cipher_key = keys.client_cipher_key();
77 iv = keys.client_iv();
78 mac_key = keys.client_mac_key();
79 }
80 else
81 {
82 cipher_key = keys.server_cipher_key();
83 iv = keys.server_iv();
84 mac_key = keys.server_mac_key();
85 }
86
87 const std::string cipher_algo = suite.cipher_algo();
88 const std::string mac_algo = suite.mac_algo();
89
90 if(have_block_cipher(cipher_algo))
91 {
92 cipher.append(get_cipher(
93 cipher_algo + "/CBC/NoPadding",
94 cipher_key, iv, ENCRYPTION)
95 );
96 block_size = block_size_of(cipher_algo);
97
98 if(major > 3 || (major == 3 && minor >= 2))
99 iv_size = block_size;
100 else
101 iv_size = 0;
102 }
103 else if(have_stream_cipher(cipher_algo))
104 {
105 cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION));
106 block_size = 0;
107 iv_size = 0;
108 }
109 else
110 throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo);
111
112 if(have_hash(mac_algo))
113 {
114 Algorithm_Factory& af = global_state().algorithm_factory();
115
116 if(major == 3 && minor == 0)
117 mac = af.make_mac("SSL3-MAC(" + mac_algo + ")");
118 else
119 mac = af.make_mac("HMAC(" + mac_algo + ")");
120
121 mac->set_key(mac_key);
122 mac_size = mac->output_length();
123 }
124 else
125 throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo);
126 }
127
128 /**
129 * Send one or more records to the other side
130 */
131 void Record_Writer::send(byte type, const byte input[], size_t length)
132 {
133 if(type != buf_type)
134 flush();
135
136 const size_t BUFFER_SIZE = buffer.size();
137 buf_type = type;
138
139 // FIXME: compression right here
140
141 buffer.copy(buf_pos, input, length);
142 if(buf_pos + length >= BUFFER_SIZE)
143 {
144 send_record(buf_type, &buffer[0], length);
145 input += (BUFFER_SIZE - buf_pos);
146 length -= (BUFFER_SIZE - buf_pos);
147 while(length >= BUFFER_SIZE)
148 {
149 send_record(buf_type, input, BUFFER_SIZE);
150 input += BUFFER_SIZE;
151 length -= BUFFER_SIZE;
152 }
153 buffer.copy(input, length);
154 buf_pos = 0;
155 }
156 buf_pos += length;
157 }
158
159 /**
160 * Split buffer into records, and send them all
161 */
162 void Record_Writer::flush()
163 {
164 const byte* buf_ptr = &buffer[0];
165 size_t offset = 0;
166
167 while(offset != buf_pos)
168 {
169 size_t record_size = buf_pos - offset;
170 if(record_size > MAX_PLAINTEXT_SIZE)
171 record_size = MAX_PLAINTEXT_SIZE;
172
173 send_record(buf_type, buf_ptr + offset, record_size);
174 offset += record_size;
175 }
176 buf_type = 0;
177 buf_pos = 0;
178 }
179
180 /**
181 * Encrypt and send the record
182 */
183 void Record_Writer::send_record(byte type, const byte buf[], size_t length)
184 {
185 if(length >= MAX_COMPRESSED_SIZE)
186 throw TLS_Exception(INTERNAL_ERROR,
187 "Record_Writer: Compressed packet is too big");
188
189 if(mac_size == 0)
190 send_record(type, major, minor, buf, length);
191 else
192 {
193 mac->update_be(seq_no);
194 mac->update(type);
195
196 if(major > 3 || (major == 3 && minor != 0))
197 {
198 mac->update(major);
199 mac->update(minor);
200 }
201
202 mac->update(get_byte<u16bit>(0, length));
203 mac->update(get_byte<u16bit>(1, length));
204 mac->update(buf, length);
205
206 SecureVector<byte> buf_mac = mac->final();
207
208 // TODO: This could all use a single buffer
209 cipher.start_msg();
210
211 if(iv_size)
212 {
213 RandomNumberGenerator& rng = global_state().global_rng();
214
215 SecureVector<byte> random_iv(iv_size);
216
217 rng.randomize(&random_iv[0], random_iv.size());
218
219 cipher.write(random_iv);
220 }
221
222 cipher.write(buf, length);
223 cipher.write(buf_mac);
224
225 if(block_size)
226 {
227 size_t pad_val =
228 (block_size - (1 + length + buf_mac.size())) % block_size;
229
230 for(size_t i = 0; i != pad_val + 1; ++i)
231 cipher.write(pad_val);
232 }
233 cipher.end_msg();
234
235 SecureVector<byte> output = cipher.read_all(Pipe::LAST_MESSAGE);
236
237 send_record(type, major, minor, &output[0], output.size());
238
239 seq_no++;
240 }
241 }
242
243 /**
244 * Send a final record packet
245 */
246 void Record_Writer::send_record(byte type, byte major, byte minor,
247 const byte out[], size_t length)
248 {
249 if(length >= MAX_CIPHERTEXT_SIZE)
250 throw TLS_Exception(INTERNAL_ERROR,
251 "Record_Writer: Record is too big");
252
253 byte header[5] = { type, major, minor, 0 };
254 for(size_t i = 0; i != 2; ++i)
255 header[i+3] = get_byte<u16bit>(i, length);
256
257 output_fn(header, 5);
258 output_fn(out, length);
259 }
260
261 /**
262 * Send an alert
263 */
264 void Record_Writer::alert(Alert_Level level, Alert_Type type)
265 {
266 byte alert[2] = { level, type };
267 send(ALERT, alert, sizeof(alert));
268 flush();
269 }
270
271 }
Botan::SessionKeys::server_mac_key
SymmetricKey server_mac_key() const
Definition: tls_session_key.cpp:42
Botan::Pipe::start_msg
void start_msg()
Definition: pipe.cpp:152
Botan::Record_Writer::Record_Writer
Record_Writer(std::tr1::function< void(const byte[], size_t)> output_fn)
Definition: rec_wri.cpp:19
Botan::Pipe::append
void append(Filter *filt)
Definition: pipe.cpp:215
Botan::SessionKeys::client_mac_key
SymmetricKey client_mac_key() const
Definition: tls_session_key.cpp:34
Botan::Library_State::global_rng
RandomNumberGenerator & global_rng()
Definition: libstate.cpp:183
Botan::Algorithm_Factory
Definition: algo_factory.h:34
Botan::ALERT
Definition: tls_magic.h:35
Botan::OctetString
Definition: symkey.h:19
Botan::Library_State::algorithm_factory
Algorithm_Factory & algorithm_factory() const
Definition: libstate.cpp:173
Botan::ENCRYPTION
Definition: sym_algo.h:87
Botan::Pipe::write
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
Botan::CipherSuite::mac_algo
std::string mac_algo() const
Definition: tls_suites.h:26
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::Record_Writer::set_version
void set_version(Version_Code)
Definition: rec_wri.cpp:51
Botan::TLS_Exception
Definition: tls_exceptn.h:19
Botan::TLS_V10
Definition: tls_magic.h:25
Botan::Record_Writer::set_keys
void set_keys(const CipherSuite &, const SessionKeys &, Connection_Side)
Definition: rec_wri.cpp:63
Botan::Pipe::reset
void reset()
Definition: pipe.cpp:76
Botan::MemoryRegion::copy
void copy(const T in[], size_t n)
Definition: secmem.h:126
Botan::Algorithm_Factory::make_mac
MessageAuthenticationCode * make_mac(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:286
Botan::SessionKeys::client_iv
InitializationVector client_iv() const
Definition: tls_session_key.cpp:50
Botan::SessionKeys::server_cipher_key
SymmetricKey server_cipher_key() const
Definition: tls_session_key.cpp:26
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::Alert_Level
Alert_Level
Definition: tls_magic.h:57
Botan::Connection_Side
Connection_Side
Definition: tls_magic.h:29
Botan::MAX_PLAINTEXT_SIZE
Definition: tls_magic.h:17
Botan::Pipe::end_msg
void end_msg()
Definition: pipe.cpp:166
Botan::SessionKeys::client_cipher_key
SymmetricKey client_cipher_key() const
Definition: tls_session_key.cpp:18
Botan::Pipe::read_all
SecureVector< byte > read_all(message_id msg=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:105
Botan::MAX_COMPRESSED_SIZE
Definition: tls_magic.h:18
Botan::SymmetricAlgorithm::set_key
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:60
Botan::Pipe::LAST_MESSAGE
static const message_id LAST_MESSAGE
Definition: pipe.h:52
Botan::Global_State_Management::global_state
Library_State & global_state()
Definition: global_state.cpp:32
Botan::Buffered_Computation::update
void update(const byte in[], size_t length)
Definition: buf_comp.h:33
Botan::block_size_of
size_t block_size_of(const std::string &name)
Definition: lookup.cpp:35
Botan::SessionKeys
Definition: tls_session_key.h:20
Botan::Version_Code
Version_Code
Definition: tls_magic.h:22
Botan
Definition: algo_base.h:14
Botan::SSL_V3
Definition: tls_magic.h:24
Botan::Buffered_Computation::final
void final(byte out[])
Definition: buf_comp.h:80
Botan::Record_Writer::flush
void flush()
Definition: rec_wri.cpp:162
Botan::Alert_Type
Alert_Type
Definition: tls_magic.h:62
Botan::have_stream_cipher
bool have_stream_cipher(const std::string &algo_spec)
Definition: lookup.h:248
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::SessionKeys::server_iv
InitializationVector server_iv() const
Definition: tls_session_key.cpp:58
Botan::have_hash
bool have_hash(const std::string &algo_spec)
Definition: lookup.h:261
Botan::CipherSuite::cipher_algo
std::string cipher_algo() const
Definition: tls_suites.h:25
Botan::have_block_cipher
bool have_block_cipher(const std::string &algo_spec)
Definition: lookup.h:235
Botan::CipherSuite
Definition: tls_suites.h:20
Botan::INTERNAL_ERROR
Definition: tls_magic.h:83
Botan::TLS_V11
Definition: tls_magic.h:26
Botan::Record_Writer::alert
void alert(Alert_Level, Alert_Type)
Definition: rec_wri.cpp:264
Botan::Buffered_Computation::update_be
void update_be(const T in)
Definition: buf_comp.h:48
Botan::get_cipher
Keyed_Filter * get_cipher(const std::string &algo_spec, Cipher_Dir direction)
Definition: lookup.cpp:124
Botan::zeroise
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:428
Botan::Buffered_Computation::output_length
virtual size_t output_length() const =0
Botan::Record_Writer::reset
void reset()
Definition: rec_wri.cpp:30
Botan::CLIENT
Definition: tls_magic.h:29
Botan::MAX_CIPHERTEXT_SIZE
Definition: tls_magic.h:19
Botan::Record_Writer::send
void send(byte type, const byte input[], size_t length)
Definition: rec_wri.cpp:131