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