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