2 * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
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
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"
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.
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
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.
39 size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen,
41 const unsigned char **in, size_t *inlen)
43 size_t blockmask = ~(blocksize - 1);
44 size_t bufremain = blocksize - *buflen;
46 assert(*buflen <= blocksize);
47 assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
49 if (*inlen < bufremain)
51 memcpy(buf + *buflen, *in, bufremain);
56 return *inlen & blockmask;
60 * Fills the buffer with trailing data from an encryption/decryption that didn't
61 * fit into a full block.
63 int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
64 const unsigned char **in, size_t *inlen)
69 if (*buflen + *inlen > blocksize) {
70 ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
74 memcpy(buf + *buflen, *in, *inlen);
81 /* Pad the final block for encryption */
82 void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
85 unsigned char pad = (unsigned char)(blocksize - *buflen);
87 for (i = *buflen; i < blocksize; i++)
91 int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
96 if (len != blocksize) {
97 ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
102 * The following assumes that the ciphertext has been authenticated.
103 * Otherwise it provides a padding oracle.
105 pad = buf[blocksize - 1];
106 if (pad == 0 || pad > blocksize) {
107 ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
110 for (i = 0; i < pad; i++) {
111 if (buf[--len] != pad) {
112 ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
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
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
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
141 int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion,
142 unsigned char *buf, size_t *buflen,
144 unsigned char **mac, int *alloced, size_t macsize,
149 switch (tlsversion) {
151 return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
152 alloced, blocksize, macsize,
156 case DTLS1_2_VERSION:
160 /* Remove the explicit IV */
162 *buflen -= blocksize;
165 ret = tls1_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
166 alloced, blocksize, macsize,