1 /*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15
16 #include <stdint.h>
17 #include <sys/param.h>
18
19 #include "error/s2n_errno.h"
20
21 #include "tls/s2n_cipher_suites.h"
22 #include "tls/s2n_connection.h"
23 #include "tls/s2n_record.h"
24 #include "tls/s2n_crypto.h"
25
26 #include "stuffer/s2n_stuffer.h"
27
28 #include "crypto/s2n_sequence.h"
29 #include "crypto/s2n_cipher.h"
30 #include "crypto/s2n_hmac.h"
31
32 #include "utils/s2n_safety.h"
33 #include "utils/s2n_random.h"
34 #include "utils/s2n_blob.h"
35
36 extern uint8_t s2n_unknown_protocol_version;
37
38 /* How much overhead does the IV, MAC, TAG and padding bytes introduce ? */
s2n_tls_record_overhead(struct s2n_connection * conn,uint16_t * out)39 static S2N_RESULT s2n_tls_record_overhead(struct s2n_connection *conn, uint16_t *out)
40 {
41 RESULT_ENSURE_REF(conn);
42 RESULT_ENSURE_MUT(out);
43 struct s2n_crypto_parameters *active = conn->server;
44
45 if (conn->mode == S2N_CLIENT) {
46 active = conn->client;
47 }
48
49 uint8_t extra;
50 RESULT_GUARD_POSIX(s2n_hmac_digest_size(active->cipher_suite->record_alg->hmac_alg, &extra));
51
52 if (active->cipher_suite->record_alg->cipher->type == S2N_CBC) {
53 /* Subtract one for the padding length byte */
54 extra += 1;
55
56 if (conn->actual_protocol_version > S2N_TLS10) {
57 extra += active->cipher_suite->record_alg->cipher->io.cbc.record_iv_size;
58 }
59 } else if (active->cipher_suite->record_alg->cipher->type == S2N_AEAD) {
60 extra += active->cipher_suite->record_alg->cipher->io.aead.tag_size;
61 extra += active->cipher_suite->record_alg->cipher->io.aead.record_iv_size;
62 } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE && conn->actual_protocol_version > S2N_TLS10) {
63 extra += active->cipher_suite->record_alg->cipher->io.comp.record_iv_size;
64 }
65
66 *out = extra;
67
68 return S2N_RESULT_OK;
69 }
70
71 /* This function returns maximum size of plaintext data to write for the payload.
72 * Record overheads are not included here.
73 */
s2n_record_max_write_payload_size(struct s2n_connection * conn,uint16_t * max_fragment_size)74 S2N_RESULT s2n_record_max_write_payload_size(struct s2n_connection *conn, uint16_t *max_fragment_size)
75 {
76 RESULT_ENSURE_REF(conn);
77 RESULT_ENSURE_MUT(max_fragment_size);
78 RESULT_ENSURE(conn->max_outgoing_fragment_length > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
79
80 *max_fragment_size = MIN(conn->max_outgoing_fragment_length, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH);
81
82 return S2N_RESULT_OK;
83 }
84
s2n_record_max_write_size(struct s2n_connection * conn,uint16_t max_fragment_size,uint16_t * max_record_size)85 S2N_RESULT s2n_record_max_write_size(struct s2n_connection *conn, uint16_t max_fragment_size, uint16_t *max_record_size)
86 {
87 RESULT_ENSURE_REF(conn);
88 RESULT_ENSURE_MUT(max_record_size);
89
90 if(!IS_NEGOTIATED(conn)) {
91 *max_record_size = S2N_TLS_MAX_RECORD_LEN_FOR(max_fragment_size);
92 } else if (conn->actual_protocol_version < S2N_TLS13) {
93 *max_record_size = S2N_TLS12_MAX_RECORD_LEN_FOR(max_fragment_size);
94 } else {
95 *max_record_size = S2N_TLS13_MAX_RECORD_LEN_FOR(max_fragment_size);
96 }
97 return S2N_RESULT_OK;
98 }
99
100 /* Find the largest size that will fit within an ethernet frame for a "small" payload */
s2n_record_min_write_payload_size(struct s2n_connection * conn,uint16_t * payload_size)101 S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16_t *payload_size)
102 {
103 RESULT_ENSURE_REF(conn);
104 RESULT_ENSURE_MUT(payload_size);
105
106 /* remove ethernet, TCP/IP and TLS header overheads */
107 const uint16_t min_outgoing_fragment_length = ETH_MTU - (conn->ipv6 ? IP_V6_HEADER_LENGTH : IP_V4_HEADER_LENGTH)
108 - TCP_HEADER_LENGTH - TCP_OPTIONS_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH;
109
110 RESULT_ENSURE(min_outgoing_fragment_length <= S2N_TLS_MAXIMUM_FRAGMENT_LENGTH, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
111 uint16_t size = min_outgoing_fragment_length;
112
113 const struct s2n_crypto_parameters *active = conn->mode == S2N_CLIENT ? conn->client : conn->server;
114
115 /* Round the fragment size down to be block aligned */
116 if (active->cipher_suite->record_alg->cipher->type == S2N_CBC) {
117 size -= size % active->cipher_suite->record_alg->cipher->io.cbc.block_size;
118 } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
119 size -= size % active->cipher_suite->record_alg->cipher->io.comp.block_size;
120 /* Composite digest length */
121 size -= active->cipher_suite->record_alg->cipher->io.comp.mac_key_size;
122 /* Padding length byte */
123 size -= 1;
124 }
125
126 /* If TLS1.3, remove content type */
127 if (conn->actual_protocol_version >= S2N_TLS13) {
128 RESULT_ENSURE(size > S2N_TLS_CONTENT_TYPE_LENGTH, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
129 size -= S2N_TLS_CONTENT_TYPE_LENGTH;
130 }
131
132 /* subtract overheads of a TLS record */
133 uint16_t overhead = 0;
134 RESULT_GUARD(s2n_tls_record_overhead(conn, &overhead));
135 RESULT_ENSURE(size > overhead, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
136 size -= overhead;
137
138 RESULT_ENSURE(size > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
139 RESULT_ENSURE(size <= ETH_MTU, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
140
141 *payload_size = size;
142
143 return S2N_RESULT_OK;
144 }
145
s2n_record_write_protocol_version(struct s2n_connection * conn)146 int s2n_record_write_protocol_version(struct s2n_connection *conn)
147 {
148 uint8_t record_protocol_version = conn->actual_protocol_version;
149 if (conn->server_protocol_version == s2n_unknown_protocol_version
150 && conn->early_data_state != S2N_EARLY_DATA_REQUESTED) {
151 /* Some legacy TLS implementations can't handle records with protocol version higher than TLS1.0.
152 * To provide maximum compatibility, send record version as TLS1.0 if server protocol version isn't
153 * established yet, which happens only during ClientHello message. Note, this has no effect on
154 * protocol version in ClientHello, so we're still able to negotiate protocol versions above TLS1.0 */
155 record_protocol_version = MIN(record_protocol_version, S2N_TLS10);
156 }
157
158 /* In accordance to TLS 1.3 spec, https://tools.ietf.org/html/rfc8446#section-5.1
159 * tls record version should never be greater than 33 (legacy TLS 1.2 version).
160 */
161 record_protocol_version = MIN(record_protocol_version, S2N_TLS12);
162
163 uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
164 protocol_version[0] = record_protocol_version / 10;
165 protocol_version[1] = record_protocol_version % 10;
166
167 POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
168
169 return 0;
170 }
171
s2n_record_encrypt(struct s2n_connection * conn,const struct s2n_cipher_suite * cipher_suite,struct s2n_session_key * session_key,struct s2n_blob * iv,struct s2n_blob * aad,struct s2n_blob * en,uint8_t * implicit_iv,uint16_t block_size)172 static inline int s2n_record_encrypt(
173 struct s2n_connection *conn,
174 const struct s2n_cipher_suite *cipher_suite,
175 struct s2n_session_key *session_key,
176 struct s2n_blob *iv,
177 struct s2n_blob *aad,
178 struct s2n_blob *en,
179 uint8_t *implicit_iv, uint16_t block_size)
180 {
181 POSIX_ENSURE_REF(en->data);
182
183 switch (cipher_suite->record_alg->cipher->type) {
184 case S2N_STREAM:
185 POSIX_GUARD(cipher_suite->record_alg->cipher->io.stream.encrypt(session_key, en, en));
186 break;
187 case S2N_CBC:
188 POSIX_GUARD(cipher_suite->record_alg->cipher->io.cbc.encrypt(session_key, iv, en, en));
189
190 /* Copy the last encrypted block to be the next IV */
191 if (conn->actual_protocol_version < S2N_TLS11) {
192 POSIX_ENSURE_GTE(en->size, block_size);
193 POSIX_CHECKED_MEMCPY(implicit_iv, en->data + en->size - block_size, block_size);
194 }
195 break;
196 case S2N_AEAD:
197 POSIX_GUARD(cipher_suite->record_alg->cipher->io.aead.encrypt(session_key, iv, aad, en, en));
198 break;
199 case S2N_COMPOSITE:
200 /* This will: compute mac, append padding, append padding length, and encrypt */
201 POSIX_GUARD(cipher_suite->record_alg->cipher->io.comp.encrypt(session_key, iv, en, en));
202
203 /* Copy the last encrypted block to be the next IV */
204 POSIX_ENSURE_GTE(en->size, block_size);
205 POSIX_CHECKED_MEMCPY(implicit_iv, en->data + en->size - block_size, block_size);
206 break;
207 default:
208 POSIX_BAIL(S2N_ERR_CIPHER_TYPE);
209 break;
210 }
211
212 return 0;
213 }
214
s2n_record_writev(struct s2n_connection * conn,uint8_t content_type,const struct iovec * in,int in_count,size_t offs,size_t to_write)215 int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write)
216 {
217 struct s2n_blob iv = { 0 };
218 uint8_t padding = 0;
219 uint16_t block_size = 0;
220 uint8_t aad_iv[S2N_TLS_MAX_IV_LEN] = { 0 };
221
222 /* In TLS 1.3, handle CCS message as unprotected records */
223 struct s2n_crypto_parameters *current_client_crypto = conn->client;
224 struct s2n_crypto_parameters *current_server_crypto = conn->server;
225 if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) {
226 conn->client = &conn->initial;
227 conn->server = &conn->initial;
228 }
229
230 uint8_t *sequence_number = conn->server->server_sequence_number;
231 struct s2n_hmac_state *mac = &conn->server->server_record_mac;
232 struct s2n_session_key *session_key = &conn->server->server_key;
233 const struct s2n_cipher_suite *cipher_suite = conn->server->cipher_suite;
234 uint8_t *implicit_iv = conn->server->server_implicit_iv;
235
236 if (conn->mode == S2N_CLIENT) {
237 sequence_number = conn->client->client_sequence_number;
238 mac = &conn->client->client_record_mac;
239 session_key = &conn->client->client_key;
240 cipher_suite = conn->client->cipher_suite;
241 implicit_iv = conn->client->client_implicit_iv;
242 }
243
244 /* The NULL stream cipher MUST NEVER be used for ApplicationData.
245 * Writing ApplicationData unencrypted defeats the purpose of TLS. */
246 if (cipher_suite->record_alg->cipher == &s2n_null_cipher) {
247 POSIX_ENSURE(content_type != TLS_APPLICATION_DATA, S2N_ERR_ENCRYPT);
248 }
249
250 const int is_tls13_record = cipher_suite->record_alg->flags & S2N_TLS13_RECORD_AEAD_NONCE;
251 s2n_stack_blob(aad, is_tls13_record ? S2N_TLS13_AAD_LEN : S2N_TLS_MAX_AAD_LEN, S2N_TLS_MAX_AAD_LEN);
252
253 S2N_ERROR_IF(s2n_stuffer_data_available(&conn->out), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
254
255 uint8_t mac_digest_size;
256 POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
257
258 /* Before we do anything, we need to figure out what the length of the
259 * fragment is going to be.
260 */
261 uint16_t max_write_payload_size = 0;
262 POSIX_GUARD_RESULT(s2n_record_max_write_payload_size(conn, &max_write_payload_size));
263 const uint16_t data_bytes_to_take = MIN(to_write, max_write_payload_size);
264
265 uint16_t extra = 0;
266 POSIX_GUARD_RESULT(s2n_tls_record_overhead(conn, &extra));
267
268 /* If we have padding to worry about, figure that out too */
269 if (cipher_suite->record_alg->cipher->type == S2N_CBC) {
270 block_size = cipher_suite->record_alg->cipher->io.cbc.block_size;
271 if (((data_bytes_to_take + extra) % block_size)) {
272 padding = block_size - ((data_bytes_to_take + extra) % block_size);
273 }
274 } else if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
275 block_size = cipher_suite->record_alg->cipher->io.comp.block_size;
276 }
277
278 /* Start the MAC with the sequence number */
279 POSIX_GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
280
281 if (s2n_stuffer_is_freed(&conn->out)) {
282 /* If the output buffer has not been allocated yet, allocate enough memory to hold
283 * a record with the local maximum fragment length. Because this only occurs if the
284 * output buffer has not been allocated, it does NOT resize existing buffers.
285 *
286 * The maximum fragment length is:
287 * 1) The local default configured for new connections
288 * 2) The local value set by the user via s2n_connection_prefer_throughput()
289 * or s2n_connection_prefer_low_latency()
290 * 3) On the server, the minimum of the local value and the value negotiated with the
291 * client via the max_fragment_length extension
292 */
293 uint16_t max_wire_record_size = 0;
294 POSIX_GUARD_RESULT(s2n_record_max_write_size(conn, max_write_payload_size, &max_wire_record_size));
295 POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->out, max_wire_record_size));
296 }
297
298 /* Now that we know the length, start writing the record */
299 POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, is_tls13_record ?
300 /* tls 1.3 opaque type */ TLS_APPLICATION_DATA :
301 /* actual content_type */ content_type ));
302 POSIX_GUARD(s2n_record_write_protocol_version(conn));
303
304 /* First write a header that has the payload length, this is for the MAC */
305 POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, data_bytes_to_take));
306
307 if (conn->actual_protocol_version > S2N_SSLv3) {
308 POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, S2N_TLS_RECORD_HEADER_LENGTH));
309 } else {
310 /* SSLv3 doesn't include the protocol version in the MAC */
311 POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, 1));
312 POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data + 3, 2));
313 }
314
315 /* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers.
316 * Composite "encrypt" will MAC the payload data and fill in padding.
317 */
318 if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
319 /* Only fragment length is needed for MAC, but the EVP ctrl function needs fragment length + eiv len. */
320 uint16_t payload_and_eiv_len = data_bytes_to_take;
321 if (conn->actual_protocol_version > S2N_TLS10) {
322 payload_and_eiv_len += block_size;
323 }
324
325 /* Outputs number of extra bytes required for MAC and padding */
326 int pad_and_mac_len;
327 POSIX_GUARD(cipher_suite->record_alg->cipher->io.comp.initial_hmac(session_key, sequence_number, content_type, conn->actual_protocol_version,
328 payload_and_eiv_len, &pad_and_mac_len));
329 extra += pad_and_mac_len;
330 }
331
332 /* TLS 1.3 protected record occupies one extra byte for content type */
333 if (is_tls13_record) {
334 extra += S2N_TLS_CONTENT_TYPE_LENGTH;
335 }
336
337 /* Rewrite the length to be the actual fragment length */
338 const uint16_t actual_fragment_length = data_bytes_to_take + padding + extra;
339 /* ensure actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH <= max record length */
340 const uint16_t max_record_length = is_tls13_record ? S2N_TLS13_MAXIMUM_RECORD_LENGTH : S2N_TLS_MAXIMUM_RECORD_LENGTH;
341 S2N_ERROR_IF(actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH > max_record_length, S2N_ERR_RECORD_LENGTH_TOO_LARGE);
342 POSIX_GUARD(s2n_stuffer_wipe_n(&conn->out, 2));
343 POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, actual_fragment_length));
344
345 /* If we're AEAD, write the sequence number as an IV, and generate the AAD */
346 if (cipher_suite->record_alg->cipher->type == S2N_AEAD) {
347 struct s2n_stuffer iv_stuffer = {0};
348 s2n_blob_init(&iv, aad_iv, sizeof(aad_iv));
349 POSIX_GUARD(s2n_stuffer_init(&iv_stuffer, &iv));
350
351 if (cipher_suite->record_alg->flags & S2N_TLS12_AES_GCM_AEAD_NONCE) {
352 /* Partially explicit nonce. See RFC 5288 Section 3 */
353 POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
354 POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
355 POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
356 } else if (cipher_suite->record_alg->flags & S2N_TLS12_CHACHA_POLY_AEAD_NONCE || is_tls13_record) {
357 /* Fully implicit nonce. See RFC7905 Section 2 */
358 uint8_t four_zeroes[4] = { 0 };
359 POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
360 POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
361 for(int i = 0; i < cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; i++) {
362 aad_iv[i] = aad_iv[i] ^ implicit_iv[i];
363 }
364 } else {
365 POSIX_BAIL(S2N_ERR_INVALID_NONCE_TYPE);
366 }
367
368 /* Set the IV size to the amount of data written */
369 iv.size = s2n_stuffer_data_available(&iv_stuffer);
370 if (is_tls13_record) {
371 POSIX_GUARD_RESULT(s2n_tls13_aead_aad_init(data_bytes_to_take + S2N_TLS_CONTENT_TYPE_LENGTH, cipher_suite->record_alg->cipher->io.aead.tag_size, &aad));
372 } else {
373 POSIX_GUARD_RESULT(s2n_aead_aad_init(conn, sequence_number, content_type, data_bytes_to_take, &aad));
374 }
375 } else if (cipher_suite->record_alg->cipher->type == S2N_CBC || cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
376 s2n_blob_init(&iv, implicit_iv, block_size);
377
378 /* For TLS1.1/1.2; write the IV with random data */
379 if (conn->actual_protocol_version > S2N_TLS10) {
380 POSIX_GUARD_RESULT(s2n_get_public_random_data(&iv));
381 if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
382 /* Write a separate random block to the record. This will be used along with the previously generated
383 * iv blob to generate the final explicit_iv for this record.
384 *
385 * How? Openssl's AES-CBC stitched encrypt populates the first block of application data with:
386 * AES(Key, XOR(iv, initial_block))
387 *
388 * If we make initial_block a random block unrelated to random_iv, explicit IV for this record
389 * is random value based on the two random blobs we just generated:
390 * AES(Key, XOR(random_iv, explicit_iv_placeholder) == AES(Key, XOR(random_iv, random_iv2))
391 *
392 * NOTE: We can't use the same random IV blob as both the initial block and IV since it will result in:
393 * AES(Key, XOR(random_iv, random_iv)) == AES(Key, 0), which will be shared by all records in this session.
394 */
395 struct s2n_blob explicit_iv_placeholder;
396 uint8_t zero_block[S2N_TLS_MAX_IV_LEN] = { 0 };
397 POSIX_GUARD(s2n_blob_init(&explicit_iv_placeholder, zero_block, block_size));
398 POSIX_GUARD_RESULT(s2n_get_public_random_data(&explicit_iv_placeholder));
399 POSIX_GUARD(s2n_stuffer_write(&conn->out, &explicit_iv_placeholder));
400 } else {
401 /* We can write the explicit IV directly to the record for non composite CBC because
402 * s2n starts AES *after* the explicit IV.
403 */
404 POSIX_GUARD(s2n_stuffer_write(&conn->out, &iv));
405 }
406 }
407 }
408
409 /* We are done with this sequence number, so we can increment it */
410 struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
411 POSIX_GUARD(s2n_increment_sequence_number(&seq));
412
413 /* Write the plaintext data */
414 POSIX_GUARD(s2n_stuffer_writev_bytes(&conn->out, in, in_count, offs, data_bytes_to_take));
415 void *orig_write_ptr = conn->out.blob.data + conn->out.write_cursor - data_bytes_to_take;
416 POSIX_GUARD(s2n_hmac_update(mac, orig_write_ptr, data_bytes_to_take));
417
418 /* Write the digest */
419 uint8_t *digest = s2n_stuffer_raw_write(&conn->out, mac_digest_size);
420 POSIX_ENSURE_REF(digest);
421
422 POSIX_GUARD(s2n_hmac_digest(mac, digest, mac_digest_size));
423 POSIX_GUARD(s2n_hmac_reset(mac));
424
425 /* Write content type for TLS 1.3 record (RFC 8446 Section 5.2) */
426 if (is_tls13_record) {
427 POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, content_type));
428 }
429
430 if (cipher_suite->record_alg->cipher->type == S2N_CBC) {
431 /* Include padding bytes, each with the value 'p', and
432 * include an extra padding length byte, also with the value 'p'.
433 */
434 for (int i = 0; i <= padding; i++) {
435 POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, padding));
436 }
437 }
438
439 /* Rewind to rewrite/encrypt the packet */
440 POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
441
442 /* Skip the header */
443 POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, S2N_TLS_RECORD_HEADER_LENGTH));
444
445 uint16_t encrypted_length = data_bytes_to_take + mac_digest_size;
446 switch (cipher_suite->record_alg->cipher->type) {
447 case S2N_AEAD:
448 POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
449 encrypted_length += cipher_suite->record_alg->cipher->io.aead.tag_size;
450 if (is_tls13_record) {
451 /* one extra byte for content type */
452 encrypted_length += S2N_TLS_CONTENT_TYPE_LENGTH;
453 }
454 break;
455 case S2N_CBC:
456 if (conn->actual_protocol_version > S2N_TLS10) {
457 /* Leave the IV alone and unencrypted */
458 POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, iv.size));
459 }
460 /* Encrypt the padding and the padding length byte too */
461 encrypted_length += padding + 1;
462 break;
463 case S2N_COMPOSITE:
464 /* Composite CBC expects a pointer starting at explicit IV: [Explicit IV | fragment | MAC | padding | padding len ]
465 * extra will account for the explicit IV len(if applicable), MAC digest len, padding len + padding byte.
466 */
467 encrypted_length += extra;
468 break;
469 default:
470 break;
471 }
472
473 /* Check that stuffer have enough space to write encrypted record, because raw_write cannot expand tainted stuffer */
474 S2N_ERROR_IF(s2n_stuffer_space_remaining(&conn->out) < encrypted_length, S2N_ERR_RECORD_STUFFER_SIZE);
475
476 /* Do the encryption */
477 struct s2n_blob en = { .size = encrypted_length, .data = s2n_stuffer_raw_write(&conn->out, encrypted_length) };
478 POSIX_GUARD(s2n_record_encrypt(conn, cipher_suite, session_key, &iv, &aad, &en, implicit_iv, block_size));
479
480 if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) {
481 conn->client = current_client_crypto;
482 conn->server = current_server_crypto;
483 }
484
485 conn->wire_bytes_out += actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH;
486
487 return data_bytes_to_take;
488 }
489
s2n_record_write(struct s2n_connection * conn,uint8_t content_type,struct s2n_blob * in)490 int s2n_record_write(struct s2n_connection *conn, uint8_t content_type, struct s2n_blob *in)
491 {
492 struct iovec iov;
493 iov.iov_base = in->data;
494 iov.iov_len = in->size;
495 return s2n_record_writev(conn, content_type, &iov, 1, 0, in->size);
496 }
497