Fix migration guide mappings for i2o/o2i_ECPublicKey
[openssl.git] / providers / implementations / ciphers / ciphercommon_block.c
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 }