1 /* 2 * Copyright 2019-2023 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 <assert.h> 11 /* For SSL3_VERSION, TLS1_VERSION etc */ 12 #include <openssl/prov_ssl.h> 13 #include <openssl/rand.h> 14 #include <openssl/proverr.h> 15 #include "internal/constant_time.h" 16 #include "internal/ssl3_cbc.h" 17 #include "ciphercommon_local.h" 18 19 /* 20 * Fills a single block of buffered data from the input, and returns the amount 21 * of data remaining in the input that is a multiple of the blocksize. The buffer 22 * is only filled if it already has some data in it, isn't full already or we 23 * don't have at least one block in the input. 24 * 25 * buf: a buffer of blocksize bytes 26 * buflen: contains the amount of data already in buf on entry. Updated with the 27 * amount of data in buf at the end. On entry *buflen must always be 28 * less than the blocksize 29 * blocksize: size of a block. Must be greater than 0 and a power of 2 30 * in: pointer to a pointer containing the input data 31 * inlen: amount of input data available 32 * 33 * On return buf is filled with as much data as possible up to a full block, 34 * *buflen is updated containing the amount of data in buf. *in is updated to 35 * the new location where input data should be read from, *inlen is updated with 36 * the remaining amount of data in *in. Returns the largest value <= *inlen 37 * which is a multiple of the blocksize. 38 */ 39 size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen, 40 size_t blocksize, 41 const unsigned char **in, size_t *inlen) 42 { 43 size_t blockmask = ~(blocksize - 1); 44 size_t bufremain = blocksize - *buflen; 45 46 assert(*buflen <= blocksize); 47 assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0); 48 49 if (*inlen < bufremain) 50 bufremain = *inlen; 51 memcpy(buf + *buflen, *in, bufremain); 52 *in += bufremain; 53 *inlen -= bufremain; 54 *buflen += bufremain; 55 56 return *inlen & blockmask; 57 } 58 59 /* 60 * Fills the buffer with trailing data from an encryption/decryption that didn't 61 * fit into a full block. 62 */ 63 int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, 64 const unsigned char **in, size_t *inlen) 65 { 66 if (*inlen == 0) 67 return 1; 68 69 if (*buflen + *inlen > blocksize) { 70 ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); 71 return 0; 72 } 73 74 memcpy(buf + *buflen, *in, *inlen); 75 *buflen += *inlen; 76 *inlen = 0; 77 78 return 1; 79 } 80 81 /* Pad the final block for encryption */ 82 void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize) 83 { 84 size_t i; 85 unsigned char pad = (unsigned char)(blocksize - *buflen); 86 87 for (i = *buflen; i < blocksize; i++) 88 buf[i] = pad; 89 } 90 91 int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize) 92 { 93 size_t pad, i; 94 size_t len = *buflen; 95 96 if (len != blocksize) { 97 ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); 98 return 0; 99 } 100 101 /* 102 * The following assumes that the ciphertext has been authenticated. 103 * Otherwise it provides a padding oracle. 104 */ 105 pad = buf[blocksize - 1]; 106 if (pad == 0 || pad > blocksize) { 107 ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); 108 return 0; 109 } 110 for (i = 0; i < pad; i++) { 111 if (buf[--len] != pad) { 112 ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); 113 return 0; 114 } 115 } 116 *buflen = len; 117 return 1; 118 } 119 120 /*- 121 * ossl_cipher_tlsunpadblock removes the CBC padding from the decrypted, TLS, CBC 122 * record in constant time. Also removes the MAC from the record in constant 123 * time. 124 * 125 * libctx: Our library context 126 * tlsversion: The TLS version in use, e.g. SSL3_VERSION, TLS1_VERSION, etc 127 * buf: The decrypted TLS record data 128 * buflen: The length of the decrypted TLS record data. Updated with the new 129 * length after the padding is removed 130 * block_size: the block size of the cipher used to encrypt the record. 131 * mac: Location to store the pointer to the MAC 132 * alloced: Whether the MAC is stored in a newly allocated buffer, or whether 133 * *mac points into *buf 134 * macsize: the size of the MAC inside the record (or 0 if there isn't one) 135 * aead: whether this is an aead cipher 136 * returns: 137 * 0: (in non-constant time) if the record is publicly invalid. 138 * 1: (in constant time) Record is publicly valid. If padding is invalid then 139 * the mac is random 140 */ 141 int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion, 142 unsigned char *buf, size_t *buflen, 143 size_t blocksize, 144 unsigned char **mac, int *alloced, size_t macsize, 145 int aead) 146 { 147 int ret; 148 149 switch (tlsversion) { 150 case SSL3_VERSION: 151 return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac, 152 alloced, blocksize, macsize, 153 libctx); 154 155 case TLS1_2_VERSION: 156 case DTLS1_2_VERSION: 157 case TLS1_1_VERSION: 158 case DTLS1_VERSION: 159 case DTLS1_BAD_VER: 160 /* Remove the explicit IV */ 161 buf += blocksize; 162 *buflen -= blocksize; 163 /* Fall through */ 164 case TLS1_VERSION: 165 ret = tls1_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac, 166 alloced, blocksize, macsize, 167 aead, libctx); 168 return ret; 169 170 default: 171 return 0; 172 } 173 } 174