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