]>
Commit | Line | Data |
---|---|---|
50023e9b | 1 | /* |
b6461792 | 2 | * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. |
50023e9b MC |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <openssl/evp.h> | |
11 | #include <openssl/core_names.h> | |
12 | #include "../../ssl_local.h" | |
13 | #include "../record_local.h" | |
14 | #include "recmethod_local.h" | |
15 | ||
16 | static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, | |
17 | unsigned char *key, size_t keylen, | |
18 | unsigned char *iv, size_t ivlen, | |
19 | unsigned char *mackey, size_t mackeylen, | |
20 | const EVP_CIPHER *ciph, | |
21 | size_t taglen, | |
50023e9b MC |
22 | int mactype, |
23 | const EVP_MD *md, | |
1e76110b | 24 | COMP_METHOD *comp) |
50023e9b MC |
25 | { |
26 | EVP_CIPHER_CTX *ciph_ctx; | |
27 | int mode; | |
2c50d7fb | 28 | int enc = (rl->direction == OSSL_RECORD_DIRECTION_WRITE) ? 1 : 0; |
50023e9b MC |
29 | |
30 | if (ivlen > sizeof(rl->iv)) { | |
7c293999 MC |
31 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
32 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
33 | } |
34 | memcpy(rl->iv, iv, ivlen); | |
35 | ||
6366bdd9 | 36 | ciph_ctx = rl->enc_ctx = EVP_CIPHER_CTX_new(); |
50023e9b | 37 | if (ciph_ctx == NULL) { |
7c293999 MC |
38 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
39 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
40 | } |
41 | ||
50023e9b MC |
42 | mode = EVP_CIPHER_get_mode(ciph); |
43 | ||
2c50d7fb | 44 | if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, enc) <= 0 |
1704961c MC |
45 | || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, |
46 | NULL) <= 0 | |
50023e9b | 47 | || (mode == EVP_CIPH_CCM_MODE |
1704961c MC |
48 | && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, |
49 | NULL) <= 0) | |
2c50d7fb | 50 | || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, enc) <= 0) { |
7c293999 MC |
51 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
52 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
53 | } |
54 | ||
7c293999 | 55 | return OSSL_RECORD_RETURN_SUCCESS; |
50023e9b MC |
56 | } |
57 | ||
22094d11 MC |
58 | static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs, |
59 | size_t n_recs, int sending, SSL_MAC_BUF *mac, | |
60 | size_t macsize) | |
50023e9b MC |
61 | { |
62 | EVP_CIPHER_CTX *ctx; | |
63 | unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; | |
64 | size_t ivlen, offset, loop, hdrlen; | |
65 | unsigned char *staticiv; | |
0755722c | 66 | unsigned char *seq = rl->sequence; |
50023e9b | 67 | int lenu, lenf; |
22094d11 | 68 | TLS_RL_RECORD *rec = &recs[0]; |
50023e9b MC |
69 | WPACKET wpkt; |
70 | const EVP_CIPHER *cipher; | |
71 | int mode; | |
72 | ||
73 | if (n_recs != 1) { | |
74 | /* Should not happen */ | |
75 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
76 | return 0; | |
77 | } | |
78 | ||
6366bdd9 MC |
79 | ctx = rl->enc_ctx; |
80 | staticiv = rl->iv; | |
50023e9b MC |
81 | |
82 | cipher = EVP_CIPHER_CTX_get0_cipher(ctx); | |
83 | if (cipher == NULL) { | |
84 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
85 | return 0; | |
86 | } | |
87 | mode = EVP_CIPHER_get_mode(cipher); | |
88 | ||
89 | /* | |
90 | * If we're sending an alert and ctx != NULL then we must be forcing | |
91 | * plaintext alerts. If we're reading and ctx != NULL then we allow | |
92 | * plaintext alerts at certain points in the handshake. If we've got this | |
93 | * far then we have already validated that a plaintext alert is ok here. | |
94 | */ | |
95 | if (ctx == NULL || rec->type == SSL3_RT_ALERT) { | |
96 | memmove(rec->data, rec->input, rec->length); | |
97 | rec->input = rec->data; | |
98 | return 1; | |
99 | } | |
100 | ||
101 | ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); | |
102 | ||
103 | if (!sending) { | |
104 | /* | |
105 | * Take off tag. There must be at least one byte of content type as | |
106 | * well as the tag | |
107 | */ | |
108 | if (rec->length < rl->taglen + 1) | |
109 | return 0; | |
110 | rec->length -= rl->taglen; | |
111 | } | |
112 | ||
113 | /* Set up IV */ | |
114 | if (ivlen < SEQ_NUM_SIZE) { | |
115 | /* Should not happen */ | |
116 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
117 | return 0; | |
118 | } | |
119 | offset = ivlen - SEQ_NUM_SIZE; | |
120 | memcpy(iv, staticiv, offset); | |
121 | for (loop = 0; loop < SEQ_NUM_SIZE; loop++) | |
122 | iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; | |
123 | ||
bed07b18 MC |
124 | if (!tls_increment_sequence_ctr(rl)) { |
125 | /* RLAYERfatal already called */ | |
50023e9b MC |
126 | return 0; |
127 | } | |
128 | ||
129 | if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 | |
130 | || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, | |
131 | rl->taglen, | |
132 | rec->data + rec->length) <= 0)) { | |
133 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
134 | return 0; | |
135 | } | |
136 | ||
137 | /* Set up the AAD */ | |
138 | if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) | |
139 | || !WPACKET_put_bytes_u8(&wpkt, rec->type) | |
140 | || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) | |
141 | || !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen) | |
142 | || !WPACKET_get_total_written(&wpkt, &hdrlen) | |
143 | || hdrlen != SSL3_RT_HEADER_LENGTH | |
144 | || !WPACKET_finish(&wpkt)) { | |
145 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
146 | WPACKET_cleanup(&wpkt); | |
147 | return 0; | |
148 | } | |
149 | ||
150 | /* | |
151 | * For CCM we must explicitly set the total plaintext length before we add | |
152 | * any AAD. | |
153 | */ | |
154 | if ((mode == EVP_CIPH_CCM_MODE | |
155 | && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, | |
156 | (unsigned int)rec->length) <= 0) | |
157 | || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, | |
158 | sizeof(recheader)) <= 0 | |
159 | || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, | |
160 | (unsigned int)rec->length) <= 0 | |
161 | || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 | |
162 | || (size_t)(lenu + lenf) != rec->length) { | |
163 | return 0; | |
164 | } | |
165 | if (sending) { | |
166 | /* Add the tag */ | |
167 | if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen, | |
168 | rec->data + rec->length) <= 0) { | |
169 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
170 | return 0; | |
171 | } | |
172 | rec->length += rl->taglen; | |
173 | } | |
174 | ||
175 | return 1; | |
176 | } | |
177 | ||
22094d11 MC |
178 | static int tls13_validate_record_header(OSSL_RECORD_LAYER *rl, |
179 | TLS_RL_RECORD *rec) | |
1853d20a MC |
180 | { |
181 | if (rec->type != SSL3_RT_APPLICATION_DATA | |
182 | && (rec->type != SSL3_RT_CHANGE_CIPHER_SPEC | |
183 | || !rl->is_first_handshake) | |
184 | && (rec->type != SSL3_RT_ALERT || !rl->allow_plain_alerts)) { | |
185 | RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE); | |
186 | return 0; | |
187 | } | |
188 | ||
189 | if (rec->rec_version != TLS1_2_VERSION) { | |
190 | RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_WRONG_VERSION_NUMBER); | |
191 | return 0; | |
192 | } | |
193 | ||
194 | if (rec->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) { | |
195 | RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, | |
196 | SSL_R_ENCRYPTED_LENGTH_TOO_LONG); | |
197 | return 0; | |
198 | } | |
199 | return 1; | |
200 | } | |
201 | ||
22094d11 | 202 | static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec) |
1853d20a MC |
203 | { |
204 | /* Skip this if we've received a plaintext alert */ | |
205 | if (rec->type != SSL3_RT_ALERT) { | |
206 | size_t end; | |
207 | ||
208 | if (rec->length == 0 | |
209 | || rec->type != SSL3_RT_APPLICATION_DATA) { | |
210 | RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, | |
211 | SSL_R_BAD_RECORD_TYPE); | |
212 | return 0; | |
213 | } | |
214 | ||
215 | /* Strip trailing padding */ | |
1704961c | 216 | for (end = rec->length - 1; end > 0 && rec->data[end] == 0; end--) |
1853d20a MC |
217 | continue; |
218 | ||
219 | rec->length = end; | |
220 | rec->type = rec->data[end]; | |
221 | } | |
222 | ||
223 | if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) { | |
224 | RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); | |
225 | return 0; | |
226 | } | |
227 | ||
8124ab56 | 228 | if (!tls13_common_post_process_record(rl, rec)) { |
1853d20a MC |
229 | /* RLAYERfatal already called */ |
230 | return 0; | |
231 | } | |
232 | ||
233 | return 1; | |
234 | } | |
235 | ||
eb1eaa9a TM |
236 | static uint8_t tls13_get_record_type(OSSL_RECORD_LAYER *rl, |
237 | OSSL_RECORD_TEMPLATE *template) | |
7ca61d63 MC |
238 | { |
239 | if (rl->allow_plain_alerts && template->type == SSL3_RT_ALERT) | |
eb1eaa9a | 240 | return SSL3_RT_ALERT; |
7ca61d63 MC |
241 | |
242 | /* | |
243 | * Aside from the above case we always use the application data record type | |
244 | * when encrypting in TLSv1.3. The "inner" record type encodes the "real" | |
245 | * record type from the template. | |
246 | */ | |
247 | return SSL3_RT_APPLICATION_DATA; | |
248 | } | |
249 | ||
2582de25 MC |
250 | static int tls13_add_record_padding(OSSL_RECORD_LAYER *rl, |
251 | OSSL_RECORD_TEMPLATE *thistempl, | |
252 | WPACKET *thispkt, | |
22094d11 | 253 | TLS_RL_RECORD *thiswr) |
2582de25 MC |
254 | { |
255 | size_t rlen; | |
256 | ||
257 | /* Nothing to be done in the case of a plaintext alert */ | |
258 | if (rl->allow_plain_alerts && thistempl->type != SSL3_RT_ALERT) | |
259 | return 1; | |
260 | ||
261 | if (!WPACKET_put_bytes_u8(thispkt, thistempl->type)) { | |
262 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
263 | return 0; | |
264 | } | |
22094d11 | 265 | TLS_RL_RECORD_add_length(thiswr, 1); |
2582de25 MC |
266 | |
267 | /* Add TLS1.3 padding */ | |
22094d11 | 268 | rlen = TLS_RL_RECORD_get_length(thiswr); |
2582de25 MC |
269 | if (rlen < rl->max_frag_len) { |
270 | size_t padding = 0; | |
271 | size_t max_padding = rl->max_frag_len - rlen; | |
272 | ||
273 | if (rl->padding != NULL) { | |
274 | padding = rl->padding(rl->cbarg, thistempl->type, rlen); | |
275 | } else if (rl->block_padding > 0) { | |
276 | size_t mask = rl->block_padding - 1; | |
277 | size_t remainder; | |
278 | ||
279 | /* optimize for power of 2 */ | |
280 | if ((rl->block_padding & mask) == 0) | |
281 | remainder = rlen & mask; | |
282 | else | |
283 | remainder = rlen % rl->block_padding; | |
284 | /* don't want to add a block of padding if we don't have to */ | |
285 | if (remainder == 0) | |
286 | padding = 0; | |
287 | else | |
288 | padding = rl->block_padding - remainder; | |
289 | } | |
290 | if (padding > 0) { | |
291 | /* do not allow the record to exceed max plaintext length */ | |
292 | if (padding > max_padding) | |
293 | padding = max_padding; | |
294 | if (!WPACKET_memset(thispkt, 0, padding)) { | |
295 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, | |
296 | ERR_R_INTERNAL_ERROR); | |
297 | return 0; | |
298 | } | |
22094d11 | 299 | TLS_RL_RECORD_add_length(thiswr, padding); |
2582de25 MC |
300 | } |
301 | } | |
302 | ||
303 | return 1; | |
304 | } | |
305 | ||
89dd87e1 | 306 | const struct record_functions_st tls_1_3_funcs = { |
50023e9b MC |
307 | tls13_set_crypto_state, |
308 | tls13_cipher, | |
1853d20a MC |
309 | NULL, |
310 | tls_default_set_protocol_version, | |
bafe524b MC |
311 | tls_default_read_n, |
312 | tls_get_more_records, | |
1853d20a | 313 | tls13_validate_record_header, |
bafe524b MC |
314 | tls13_post_process_record, |
315 | tls_get_max_records_default, | |
91fe8ff0 MC |
316 | tls_write_records_default, |
317 | tls_allocate_write_buffers_default, | |
7ca61d63 | 318 | tls_initialise_write_packets_default, |
aca70ca8 | 319 | tls13_get_record_type, |
2582de25 | 320 | tls_prepare_record_header_default, |
757ef3ba | 321 | tls13_add_record_padding, |
2a354d54 | 322 | tls_prepare_for_encryption_default, |
ace38195 MC |
323 | tls_post_encryption_processing_default, |
324 | NULL | |
50023e9b | 325 | }; |