1 /*
2 * Copyright 1995-2021 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/rand.h>
11 #include <openssl/evp.h>
12 #include "internal/constant_time.h"
13 #include "internal/cryptlib.h"
14
15 /*
16 * This file has no dependencies on the rest of libssl because it is shared
17 * with the providers. It contains functions for low level CBC TLS padding
18 * removal. Responsibility for this lies with the cipher implementations in the
19 * providers. However there are legacy code paths in libssl which also need to
20 * do this. In time those legacy code paths can be removed and this file can be
21 * moved out of libssl.
22 */
23
24 static int ssl3_cbc_copy_mac(size_t *reclen,
25 size_t origreclen,
26 unsigned char *recdata,
27 unsigned char **mac,
28 int *alloced,
29 size_t block_size,
30 size_t mac_size,
31 size_t good,
32 OSSL_LIB_CTX *libctx);
33
34 int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
35 size_t origreclen,
36 unsigned char *recdata,
37 unsigned char **mac,
38 int *alloced,
39 size_t block_size, size_t mac_size,
40 OSSL_LIB_CTX *libctx);
41
42 int tls1_cbc_remove_padding_and_mac(size_t *reclen,
43 size_t origreclen,
44 unsigned char *recdata,
45 unsigned char **mac,
46 int *alloced,
47 size_t block_size, size_t mac_size,
48 int aead,
49 OSSL_LIB_CTX *libctx);
50
51 /*-
52 * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
53 * record in |recdata| by updating |reclen| in constant time. It also extracts
54 * the MAC from the underlying record and places a pointer to it in |mac|. The
55 * MAC data can either be newly allocated memory, or a pointer inside the
56 * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
57 * set to 0.
58 *
59 * origreclen: the original record length before any changes were made
60 * block_size: the block size of the cipher used to encrypt the record.
61 * mac_size: the size of the MAC to be extracted
62 * aead: 1 if an AEAD cipher is in use, or 0 otherwise
63 * returns:
64 * 0: if the record is publicly invalid.
65 * 1: if the record is publicly valid. If the padding removal fails then the
66 * MAC returned is random.
67 */
ssl3_cbc_remove_padding_and_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,OSSL_LIB_CTX * libctx)68 int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
69 size_t origreclen,
70 unsigned char *recdata,
71 unsigned char **mac,
72 int *alloced,
73 size_t block_size, size_t mac_size,
74 OSSL_LIB_CTX *libctx)
75 {
76 size_t padding_length;
77 size_t good;
78 const size_t overhead = 1 /* padding length byte */ + mac_size;
79
80 /*
81 * These lengths are all public so we can test them in non-constant time.
82 */
83 if (overhead > *reclen)
84 return 0;
85
86 padding_length = recdata[*reclen - 1];
87 good = constant_time_ge_s(*reclen, padding_length + overhead);
88 /* SSLv3 requires that the padding is minimal. */
89 good &= constant_time_ge_s(block_size, padding_length + 1);
90 *reclen -= good & (padding_length + 1);
91
92 return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
93 block_size, mac_size, good, libctx);
94 }
95
96 /*-
97 * tls1_cbc_remove_padding_and_mac removes padding from the decrypted, TLS, CBC
98 * record in |recdata| by updating |reclen| in constant time. It also extracts
99 * the MAC from the underlying record and places a pointer to it in |mac|. The
100 * MAC data can either be newly allocated memory, or a pointer inside the
101 * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
102 * set to 0.
103 *
104 * origreclen: the original record length before any changes were made
105 * block_size: the block size of the cipher used to encrypt the record.
106 * mac_size: the size of the MAC to be extracted
107 * aead: 1 if an AEAD cipher is in use, or 0 otherwise
108 * returns:
109 * 0: if the record is publicly invalid.
110 * 1: if the record is publicly valid. If the padding removal fails then the
111 * MAC returned is random.
112 */
tls1_cbc_remove_padding_and_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,int aead,OSSL_LIB_CTX * libctx)113 int tls1_cbc_remove_padding_and_mac(size_t *reclen,
114 size_t origreclen,
115 unsigned char *recdata,
116 unsigned char **mac,
117 int *alloced,
118 size_t block_size, size_t mac_size,
119 int aead,
120 OSSL_LIB_CTX *libctx)
121 {
122 size_t good = -1;
123 size_t padding_length, to_check, i;
124 size_t overhead = ((block_size == 1) ? 0 : 1) /* padding length byte */
125 + mac_size;
126
127 /*
128 * These lengths are all public so we can test them in non-constant
129 * time.
130 */
131 if (overhead > *reclen)
132 return 0;
133
134 if (block_size != 1) {
135
136 padding_length = recdata[*reclen - 1];
137
138 if (aead) {
139 /* padding is already verified and we don't need to check the MAC */
140 *reclen -= padding_length + 1 + mac_size;
141 *mac = NULL;
142 *alloced = 0;
143 return 1;
144 }
145
146 good = constant_time_ge_s(*reclen, overhead + padding_length);
147 /*
148 * The padding consists of a length byte at the end of the record and
149 * then that many bytes of padding, all with the same value as the
150 * length byte. Thus, with the length byte included, there are i+1 bytes
151 * of padding. We can't check just |padding_length+1| bytes because that
152 * leaks decrypted information. Therefore we always have to check the
153 * maximum amount of padding possible. (Again, the length of the record
154 * is public information so we can use it.)
155 */
156 to_check = 256; /* maximum amount of padding, inc length byte. */
157 if (to_check > *reclen)
158 to_check = *reclen;
159
160 for (i = 0; i < to_check; i++) {
161 unsigned char mask = constant_time_ge_8_s(padding_length, i);
162 unsigned char b = recdata[*reclen - 1 - i];
163 /*
164 * The final |padding_length+1| bytes should all have the value
165 * |padding_length|. Therefore the XOR should be zero.
166 */
167 good &= ~(mask & (padding_length ^ b));
168 }
169
170 /*
171 * If any of the final |padding_length+1| bytes had the wrong value, one
172 * or more of the lower eight bits of |good| will be cleared.
173 */
174 good = constant_time_eq_s(0xff, good & 0xff);
175 *reclen -= good & (padding_length + 1);
176 }
177
178 return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
179 block_size, mac_size, good, libctx);
180 }
181
182 /*-
183 * ssl3_cbc_copy_mac copies |md_size| bytes from the end of the record in
184 * |recdata| to |*mac| in constant time (independent of the concrete value of
185 * the record length |reclen|, which may vary within a 256-byte window).
186 *
187 * On entry:
188 * origreclen >= mac_size
189 * mac_size <= EVP_MAX_MD_SIZE
190 *
191 * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
192 * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
193 * a single or pair of cache-lines, then the variable memory accesses don't
194 * actually affect the timing. CPUs with smaller cache-lines [if any] are
195 * not multi-core and are not considered vulnerable to cache-timing attacks.
196 */
197 #define CBC_MAC_ROTATE_IN_PLACE
198
ssl3_cbc_copy_mac(size_t * reclen,size_t origreclen,unsigned char * recdata,unsigned char ** mac,int * alloced,size_t block_size,size_t mac_size,size_t good,OSSL_LIB_CTX * libctx)199 static int ssl3_cbc_copy_mac(size_t *reclen,
200 size_t origreclen,
201 unsigned char *recdata,
202 unsigned char **mac,
203 int *alloced,
204 size_t block_size,
205 size_t mac_size,
206 size_t good,
207 OSSL_LIB_CTX *libctx)
208 {
209 #if defined(CBC_MAC_ROTATE_IN_PLACE)
210 unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
211 unsigned char *rotated_mac;
212 #else
213 unsigned char rotated_mac[EVP_MAX_MD_SIZE];
214 #endif
215 unsigned char randmac[EVP_MAX_MD_SIZE];
216 unsigned char *out;
217
218 /*
219 * mac_end is the index of |recdata| just after the end of the MAC.
220 */
221 size_t mac_end = *reclen;
222 size_t mac_start = mac_end - mac_size;
223 size_t in_mac;
224 /*
225 * scan_start contains the number of bytes that we can ignore because the
226 * MAC's position can only vary by 255 bytes.
227 */
228 size_t scan_start = 0;
229 size_t i, j;
230 size_t rotate_offset;
231
232 if (!ossl_assert(origreclen >= mac_size
233 && mac_size <= EVP_MAX_MD_SIZE))
234 return 0;
235
236 /* If no MAC then nothing to be done */
237 if (mac_size == 0) {
238 /* No MAC so we can do this in non-constant time */
239 if (good == 0)
240 return 0;
241 return 1;
242 }
243
244 *reclen -= mac_size;
245
246 if (block_size == 1) {
247 /* There's no padding so the position of the MAC is fixed */
248 if (mac != NULL)
249 *mac = &recdata[*reclen];
250 if (alloced != NULL)
251 *alloced = 0;
252 return 1;
253 }
254
255 /* Create the random MAC we will emit if padding is bad */
256 if (!RAND_bytes_ex(libctx, randmac, mac_size, 0))
257 return 0;
258
259 if (!ossl_assert(mac != NULL && alloced != NULL))
260 return 0;
261 *mac = out = OPENSSL_malloc(mac_size);
262 if (*mac == NULL)
263 return 0;
264 *alloced = 1;
265
266 #if defined(CBC_MAC_ROTATE_IN_PLACE)
267 rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
268 #endif
269
270 /* This information is public so it's safe to branch based on it. */
271 if (origreclen > mac_size + 255 + 1)
272 scan_start = origreclen - (mac_size + 255 + 1);
273
274 in_mac = 0;
275 rotate_offset = 0;
276 memset(rotated_mac, 0, mac_size);
277 for (i = scan_start, j = 0; i < origreclen; i++) {
278 size_t mac_started = constant_time_eq_s(i, mac_start);
279 size_t mac_ended = constant_time_lt_s(i, mac_end);
280 unsigned char b = recdata[i];
281
282 in_mac |= mac_started;
283 in_mac &= mac_ended;
284 rotate_offset |= j & mac_started;
285 rotated_mac[j++] |= b & in_mac;
286 j &= constant_time_lt_s(j, mac_size);
287 }
288
289 /* Now rotate the MAC */
290 #if defined(CBC_MAC_ROTATE_IN_PLACE)
291 j = 0;
292 for (i = 0; i < mac_size; i++) {
293 /* in case cache-line is 32 bytes, touch second line */
294 ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
295
296 /* If the padding wasn't good we emit a random MAC */
297 out[j++] = constant_time_select_8((unsigned char)(good & 0xff),
298 rotated_mac[rotate_offset++],
299 randmac[i]);
300 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
301 }
302 #else
303 memset(out, 0, mac_size);
304 rotate_offset = mac_size - rotate_offset;
305 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
306 for (i = 0; i < mac_size; i++) {
307 for (j = 0; j < mac_size; j++)
308 out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
309 rotate_offset++;
310 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
311
312 /* If the padding wasn't good we emit a random MAC */
313 out[i] = constant_time_select_8((unsigned char)(good & 0xff), out[i],
314 randmac[i]);
315 }
316 #endif
317
318 return 1;
319 }
320