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 | }
|
---|