]>
Commit | Line | Data |
---|---|---|
50023e9b MC |
1 | /* |
2 | * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. | |
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 | /* TODO(RECLAYER): Handle OPENSSL_NO_COMP */ | |
17 | static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, | |
18 | unsigned char *key, size_t keylen, | |
19 | unsigned char *iv, size_t ivlen, | |
20 | unsigned char *mackey, size_t mackeylen, | |
21 | const EVP_CIPHER *ciph, | |
22 | size_t taglen, | |
23 | /* TODO(RECLAYER): This probably should not be an int */ | |
24 | int mactype, | |
25 | const EVP_MD *md, | |
26 | const SSL_COMP *comp, | |
27 | /* TODO(RECLAYER): Remove me */ | |
28 | SSL_CONNECTION *s) | |
29 | { | |
30 | EVP_CIPHER_CTX *ciph_ctx; | |
31 | ||
32 | if (md == NULL) { | |
7c293999 MC |
33 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
34 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
35 | } |
36 | ||
37 | if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { | |
7c293999 MC |
38 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
39 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
40 | } |
41 | ciph_ctx = rl->enc_read_ctx; | |
42 | ||
43 | rl->read_hash = EVP_MD_CTX_new(); | |
44 | if (rl->read_hash == NULL) { | |
7c293999 MC |
45 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
46 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
47 | } |
48 | #ifndef OPENSSL_NO_COMP | |
49 | if (comp != NULL) { | |
50 | rl->expand = COMP_CTX_new(comp->method); | |
51 | if (rl->expand == NULL) { | |
7c293999 MC |
52 | ERR_raise(ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR); |
53 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
54 | } |
55 | } | |
56 | #endif | |
57 | ||
58 | if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) { | |
7c293999 MC |
59 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
60 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
61 | } |
62 | ||
63 | if (EVP_CIPHER_get0_provider(ciph) != NULL | |
7f2f0ac7 | 64 | && !ossl_set_tls_provider_parameters(rl, ciph_ctx, ciph, md)) { |
7c293999 | 65 | return OSSL_RECORD_RETURN_FATAL; |
50023e9b MC |
66 | } |
67 | ||
68 | if (mackeylen > sizeof(rl->mac_secret)) { | |
7c293999 MC |
69 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
70 | return OSSL_RECORD_RETURN_FATAL; | |
50023e9b MC |
71 | } |
72 | memcpy(rl->mac_secret, mackey, mackeylen); | |
73 | ||
7c293999 | 74 | return OSSL_RECORD_RETURN_SUCCESS; |
50023e9b MC |
75 | } |
76 | ||
77 | /* | |
78 | * ssl3_cipher encrypts/decrypts |n_recs| records in |inrecs|. Calls RLAYERfatal | |
79 | * on internal error, but not otherwise. It is the responsibility of the caller | |
80 | * to report a bad_record_mac | |
81 | * | |
82 | * Returns: | |
83 | * 0: if the record is publicly invalid, or an internal error | |
84 | * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised) | |
85 | */ | |
86 | static int ssl3_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs, | |
87 | int sending, SSL_MAC_BUF *mac, size_t macsize, | |
88 | /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) | |
89 | { | |
90 | SSL3_RECORD *rec; | |
91 | EVP_CIPHER_CTX *ds; | |
92 | size_t l, i; | |
93 | size_t bs; | |
94 | const EVP_CIPHER *enc; | |
95 | int provided; | |
96 | ||
97 | rec = inrecs; | |
98 | /* | |
99 | * We shouldn't ever be called with more than one record in the SSLv3 case | |
100 | */ | |
101 | if (n_recs != 1) | |
102 | return 0; | |
103 | if (sending) { | |
104 | ds = s->enc_write_ctx; | |
105 | if (s->enc_write_ctx == NULL) | |
106 | enc = NULL; | |
107 | else | |
108 | enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx); | |
109 | } else { | |
110 | ds = rl->enc_read_ctx; | |
111 | if (rl->enc_read_ctx == NULL) | |
112 | enc = NULL; | |
113 | else | |
114 | enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx); | |
115 | } | |
116 | ||
117 | provided = (EVP_CIPHER_get0_provider(enc) != NULL); | |
118 | ||
119 | l = rec->length; | |
120 | bs = EVP_CIPHER_CTX_get_block_size(ds); | |
121 | ||
122 | /* COMPRESS */ | |
123 | ||
124 | if ((bs != 1) && sending && !provided) { | |
125 | /* | |
126 | * We only do this for legacy ciphers. Provided ciphers add the | |
127 | * padding on the provider side. | |
128 | */ | |
129 | i = bs - (l % bs); | |
130 | ||
131 | /* we need to add 'i-1' padding bytes */ | |
132 | l += i; | |
133 | /* | |
134 | * the last of these zero bytes will be overwritten with the | |
135 | * padding length. | |
136 | */ | |
137 | memset(&rec->input[rec->length], 0, i); | |
138 | rec->length += i; | |
139 | rec->input[l - 1] = (unsigned char)(i - 1); | |
140 | } | |
141 | ||
142 | if (!sending) { | |
143 | if (l == 0 || l % bs != 0) { | |
144 | /* Publicly invalid */ | |
145 | return 0; | |
146 | } | |
147 | /* otherwise, rec->length >= bs */ | |
148 | } | |
149 | ||
150 | if (provided) { | |
151 | int outlen; | |
152 | ||
153 | if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input, | |
154 | (unsigned int)l)) | |
155 | return 0; | |
156 | rec->length = outlen; | |
157 | ||
158 | if (!sending && mac != NULL) { | |
159 | /* Now get a pointer to the MAC */ | |
160 | OSSL_PARAM params[2], *p = params; | |
161 | ||
162 | /* Get the MAC */ | |
163 | mac->alloced = 0; | |
164 | ||
165 | *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC, | |
166 | (void **)&mac->mac, | |
167 | macsize); | |
168 | *p = OSSL_PARAM_construct_end(); | |
169 | ||
170 | if (!EVP_CIPHER_CTX_get_params(ds, params)) { | |
171 | /* Shouldn't normally happen */ | |
172 | RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); | |
173 | return 0; | |
174 | } | |
175 | } | |
176 | } else { | |
177 | if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) { | |
178 | /* Shouldn't happen */ | |
179 | RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR); | |
180 | return 0; | |
181 | } | |
182 | ||
183 | if (!sending) | |
184 | return ssl3_cbc_remove_padding_and_mac(&rec->length, | |
185 | rec->orig_len, | |
186 | rec->data, | |
187 | (mac != NULL) ? &mac->mac : NULL, | |
188 | (mac != NULL) ? &mac->alloced : NULL, | |
189 | bs, | |
190 | macsize, | |
191 | rl->libctx); | |
192 | } | |
193 | ||
194 | return 1; | |
195 | } | |
196 | ||
197 | static const unsigned char ssl3_pad_1[48] = { | |
198 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
199 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
200 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
201 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
202 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
203 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 | |
204 | }; | |
205 | ||
206 | static const unsigned char ssl3_pad_2[48] = { | |
207 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |
208 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |
209 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |
210 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |
211 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |
212 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c | |
213 | }; | |
214 | ||
215 | static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, | |
216 | int sending, SSL_CONNECTION *ssl) | |
217 | { | |
0755722c | 218 | unsigned char *mac_sec, *seq = rl->sequence; |
50023e9b MC |
219 | const EVP_MD_CTX *hash; |
220 | unsigned char *p, rec_char; | |
221 | size_t md_size; | |
222 | size_t npad; | |
223 | int t; | |
224 | ||
225 | if (sending) { | |
226 | mac_sec = &(ssl->s3.write_mac_secret[0]); | |
50023e9b MC |
227 | hash = ssl->write_hash; |
228 | } else { | |
229 | mac_sec = &(rl->mac_secret[0]); | |
50023e9b MC |
230 | hash = rl->read_hash; |
231 | } | |
232 | ||
233 | t = EVP_MD_CTX_get_size(hash); | |
234 | if (t < 0) | |
235 | return 0; | |
236 | md_size = t; | |
237 | npad = (48 / md_size) * md_size; | |
238 | ||
239 | if (!sending | |
240 | && EVP_CIPHER_CTX_get_mode(rl->enc_read_ctx) == EVP_CIPH_CBC_MODE | |
241 | && ssl3_cbc_record_digest_supported(hash)) { | |
242 | #ifdef OPENSSL_NO_DEPRECATED_3_0 | |
243 | return 0; | |
244 | #else | |
245 | /* | |
246 | * This is a CBC-encrypted record. We must avoid leaking any | |
247 | * timing-side channel information about how many blocks of data we | |
248 | * are hashing because that gives an attacker a timing-oracle. | |
249 | */ | |
250 | ||
251 | /*- | |
252 | * npad is, at most, 48 bytes and that's with MD5: | |
253 | * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. | |
254 | * | |
255 | * With SHA-1 (the largest hash speced for SSLv3) the hash size | |
256 | * goes up 4, but npad goes down by 8, resulting in a smaller | |
257 | * total size. | |
258 | */ | |
259 | unsigned char header[75]; | |
260 | size_t j = 0; | |
261 | memcpy(header + j, mac_sec, md_size); | |
262 | j += md_size; | |
263 | memcpy(header + j, ssl3_pad_1, npad); | |
264 | j += npad; | |
265 | memcpy(header + j, seq, 8); | |
266 | j += 8; | |
267 | header[j++] = rec->type; | |
268 | header[j++] = (unsigned char)(rec->length >> 8); | |
269 | header[j++] = (unsigned char)(rec->length & 0xff); | |
270 | ||
271 | /* Final param == is SSLv3 */ | |
272 | if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash), | |
273 | md, &md_size, | |
274 | header, rec->input, | |
275 | rec->length, rec->orig_len, | |
276 | mac_sec, md_size, 1) <= 0) | |
277 | return 0; | |
278 | #endif | |
279 | } else { | |
280 | unsigned int md_size_u; | |
281 | /* Chop the digest off the end :-) */ | |
282 | EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); | |
283 | ||
284 | if (md_ctx == NULL) | |
285 | return 0; | |
286 | ||
287 | rec_char = rec->type; | |
288 | p = md; | |
289 | s2n(rec->length, p); | |
290 | if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 | |
291 | || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 | |
292 | || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0 | |
293 | || EVP_DigestUpdate(md_ctx, seq, 8) <= 0 | |
294 | || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0 | |
295 | || EVP_DigestUpdate(md_ctx, md, 2) <= 0 | |
296 | || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0 | |
297 | || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0 | |
298 | || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 | |
299 | || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 | |
300 | || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0 | |
301 | || EVP_DigestUpdate(md_ctx, md, md_size) <= 0 | |
302 | || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) { | |
303 | EVP_MD_CTX_free(md_ctx); | |
304 | return 0; | |
305 | } | |
306 | ||
307 | EVP_MD_CTX_free(md_ctx); | |
308 | } | |
309 | ||
310 | ssl3_record_sequence_update(seq); | |
311 | return 1; | |
312 | } | |
313 | ||
314 | struct record_functions_st ssl_3_0_funcs = { | |
315 | ssl3_set_crypto_state, | |
1853d20a | 316 | tls_default_read_n, |
50023e9b | 317 | ssl3_cipher, |
1853d20a MC |
318 | ssl3_mac, |
319 | tls_default_set_protocol_version, | |
320 | tls_default_validate_record_header, | |
321 | tls_default_post_process_record | |
50023e9b | 322 | }; |