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