1 /* 2 * Copyright 1995-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/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 */ 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 */ 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 return 1; 142 } 143 144 good = constant_time_ge_s(*reclen, overhead + padding_length); 145 /* 146 * The padding consists of a length byte at the end of the record and 147 * then that many bytes of padding, all with the same value as the 148 * length byte. Thus, with the length byte included, there are i+1 bytes 149 * of padding. We can't check just |padding_length+1| bytes because that 150 * leaks decrypted information. Therefore we always have to check the 151 * maximum amount of padding possible. (Again, the length of the record 152 * is public information so we can use it.) 153 */ 154 to_check = 256; /* maximum amount of padding, inc length byte. */ 155 if (to_check > *reclen) 156 to_check = *reclen; 157 158 for (i = 0; i < to_check; i++) { 159 unsigned char mask = constant_time_ge_8_s(padding_length, i); 160 unsigned char b = recdata[*reclen - 1 - i]; 161 /* 162 * The final |padding_length+1| bytes should all have the value 163 * |padding_length|. Therefore the XOR should be zero. 164 */ 165 good &= ~(mask & (padding_length ^ b)); 166 } 167 168 /* 169 * If any of the final |padding_length+1| bytes had the wrong value, one 170 * or more of the lower eight bits of |good| will be cleared. 171 */ 172 good = constant_time_eq_s(0xff, good & 0xff); 173 *reclen -= good & (padding_length + 1); 174 } 175 176 return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced, 177 block_size, mac_size, good, libctx); 178 } 179 180 /*- 181 * ssl3_cbc_copy_mac copies |md_size| bytes from the end of the record in 182 * |recdata| to |*mac| in constant time (independent of the concrete value of 183 * the record length |reclen|, which may vary within a 256-byte window). 184 * 185 * On entry: 186 * origreclen >= mac_size 187 * mac_size <= EVP_MAX_MD_SIZE 188 * 189 * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with 190 * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into 191 * a single or pair of cache-lines, then the variable memory accesses don't 192 * actually affect the timing. CPUs with smaller cache-lines [if any] are 193 * not multi-core and are not considered vulnerable to cache-timing attacks. 194 */ 195 #define CBC_MAC_ROTATE_IN_PLACE 196 197 static int ssl3_cbc_copy_mac(size_t *reclen, 198 size_t origreclen, 199 unsigned char *recdata, 200 unsigned char **mac, 201 int *alloced, 202 size_t block_size, 203 size_t mac_size, 204 size_t good, 205 OSSL_LIB_CTX *libctx) 206 { 207 #if defined(CBC_MAC_ROTATE_IN_PLACE) 208 unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE]; 209 unsigned char *rotated_mac; 210 char aux1, aux2, aux3, mask; 211 #else 212 unsigned char rotated_mac[EVP_MAX_MD_SIZE]; 213 #endif 214 unsigned char randmac[EVP_MAX_MD_SIZE]; 215 unsigned char *out; 216 217 /* 218 * mac_end is the index of |recdata| just after the end of the MAC. 219 */ 220 size_t mac_end = *reclen; 221 size_t mac_start = mac_end - mac_size; 222 size_t in_mac; 223 /* 224 * scan_start contains the number of bytes that we can ignore because the 225 * MAC's position can only vary by 255 bytes. 226 */ 227 size_t scan_start = 0; 228 size_t i, j; 229 size_t rotate_offset; 230 231 if (!ossl_assert(origreclen >= mac_size 232 && mac_size <= EVP_MAX_MD_SIZE)) 233 return 0; 234 235 /* If no MAC then nothing to be done */ 236 if (mac_size == 0) { 237 /* No MAC so we can do this in non-constant time */ 238 if (good == 0) 239 return 0; 240 return 1; 241 } 242 243 *reclen -= mac_size; 244 245 if (block_size == 1) { 246 /* There's no padding so the position of the MAC is fixed */ 247 if (mac != NULL) 248 *mac = &recdata[*reclen]; 249 if (alloced != NULL) 250 *alloced = 0; 251 return 1; 252 } 253 254 /* Create the random MAC we will emit if padding is bad */ 255 if (RAND_bytes_ex(libctx, randmac, mac_size, 0) <= 0) 256 return 0; 257 258 if (!ossl_assert(mac != NULL && alloced != NULL)) 259 return 0; 260 *mac = out = OPENSSL_malloc(mac_size); 261 if (*mac == NULL) 262 return 0; 263 *alloced = 1; 264 265 #if defined(CBC_MAC_ROTATE_IN_PLACE) 266 rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63); 267 #endif 268 269 /* This information is public so it's safe to branch based on it. */ 270 if (origreclen > mac_size + 255 + 1) 271 scan_start = origreclen - (mac_size + 255 + 1); 272 273 in_mac = 0; 274 rotate_offset = 0; 275 memset(rotated_mac, 0, mac_size); 276 for (i = scan_start, j = 0; i < origreclen; i++) { 277 size_t mac_started = constant_time_eq_s(i, mac_start); 278 size_t mac_ended = constant_time_lt_s(i, mac_end); 279 unsigned char b = recdata[i]; 280 281 in_mac |= mac_started; 282 in_mac &= mac_ended; 283 rotate_offset |= j & mac_started; 284 rotated_mac[j++] |= b & in_mac; 285 j &= constant_time_lt_s(j, mac_size); 286 } 287 288 /* Now rotate the MAC */ 289 #if defined(CBC_MAC_ROTATE_IN_PLACE) 290 j = 0; 291 for (i = 0; i < mac_size; i++) { 292 /* 293 * in case cache-line is 32 bytes, 294 * load from both lines and select appropriately 295 */ 296 aux1 = rotated_mac[rotate_offset & ~32]; 297 aux2 = rotated_mac[rotate_offset | 32]; 298 mask = constant_time_eq_8(rotate_offset & ~32, rotate_offset); 299 aux3 = constant_time_select_8(mask, aux1, aux2); 300 rotate_offset++; 301 302 /* If the padding wasn't good we emit a random MAC */ 303 out[j++] = constant_time_select_8((unsigned char)(good & 0xff), 304 aux3, 305 randmac[i]); 306 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size); 307 } 308 #else 309 memset(out, 0, mac_size); 310 rotate_offset = mac_size - rotate_offset; 311 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size); 312 for (i = 0; i < mac_size; i++) { 313 for (j = 0; j < mac_size; j++) 314 out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset); 315 rotate_offset++; 316 rotate_offset &= constant_time_lt_s(rotate_offset, mac_size); 317 318 /* If the padding wasn't good we emit a random MAC */ 319 out[i] = constant_time_select_8((unsigned char)(good & 0xff), out[i], 320 randmac[i]); 321 } 322 #endif 323 324 return 1; 325 } 326