Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/crypto/openssl/ossl_aes.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 Stormshield.
5
* Copyright (c) 2021 Semihalf.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/malloc.h>
30
31
#include <opencrypto/cryptodev.h>
32
#include <opencrypto/gmac.h>
33
34
#include <crypto/openssl/ossl.h>
35
#include <crypto/openssl/ossl_aes_gcm.h>
36
#include <crypto/openssl/ossl_cipher.h>
37
38
#if defined(__amd64__) || defined(__i386__)
39
#include <crypto/openssl/ossl_x86.h>
40
#elif defined (__aarch64__)
41
#include <crypto/openssl/ossl_aarch64.h>
42
#elif defined (__arm__)
43
#include <crypto/openssl/ossl_arm.h>
44
#elif defined (__powerpc64__)
45
#include <crypto/openssl/ossl_ppc.h>
46
#else
47
#error "Unsupported architecture!"
48
#endif
49
50
static ossl_cipher_process_t ossl_aes_cbc;
51
static ossl_cipher_process_t ossl_aes_gcm;
52
53
struct ossl_cipher ossl_cipher_aes_cbc = {
54
.type = CRYPTO_AES_CBC,
55
.blocksize = AES_BLOCK_LEN,
56
.ivsize = AES_BLOCK_LEN,
57
58
/* Filled during initialization based on CPU caps. */
59
.set_encrypt_key = NULL,
60
.set_decrypt_key = NULL,
61
.process = ossl_aes_cbc
62
};
63
64
struct ossl_cipher ossl_cipher_aes_gcm = {
65
.type = CRYPTO_AES_NIST_GCM_16,
66
.blocksize = 1,
67
.ivsize = AES_GCM_IV_LEN,
68
69
/* Filled during initialization based on CPU caps. */
70
.set_encrypt_key = NULL,
71
.set_decrypt_key = NULL,
72
.process = ossl_aes_gcm,
73
};
74
75
static int
76
ossl_aes_cbc(struct ossl_session_cipher *s, struct cryptop *crp,
77
const struct crypto_session_params *csp)
78
{
79
struct crypto_buffer_cursor cc_in, cc_out;
80
unsigned char block[EALG_MAX_BLOCK_LEN];
81
unsigned char iv[EALG_MAX_BLOCK_LEN];
82
const unsigned char *in, *inseg;
83
unsigned char *out, *outseg;
84
size_t plen, seglen, inlen, outlen;
85
struct ossl_cipher_context key;
86
struct ossl_cipher *cipher;
87
int blocklen, error;
88
bool encrypt;
89
90
cipher = s->cipher;
91
encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
92
plen = crp->crp_payload_length;
93
blocklen = cipher->blocksize;
94
95
if (plen % blocklen)
96
return (EINVAL);
97
98
if (crp->crp_cipher_key != NULL) {
99
if (encrypt)
100
error = cipher->set_encrypt_key(crp->crp_cipher_key,
101
8 * csp->csp_cipher_klen, &key);
102
else
103
error = cipher->set_decrypt_key(crp->crp_cipher_key,
104
8 * csp->csp_cipher_klen, &key);
105
if (error)
106
return (error);
107
} else {
108
if (encrypt)
109
key = s->enc_ctx;
110
else
111
key = s->dec_ctx;
112
}
113
114
crypto_read_iv(crp, iv);
115
116
/* Derived from ossl_chacha20.c */
117
crypto_cursor_init(&cc_in, &crp->crp_buf);
118
crypto_cursor_advance(&cc_in, crp->crp_payload_start);
119
inseg = crypto_cursor_segment(&cc_in, &inlen);
120
if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
121
crypto_cursor_init(&cc_out, &crp->crp_obuf);
122
crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
123
} else {
124
cc_out = cc_in;
125
}
126
outseg = crypto_cursor_segment(&cc_out, &outlen);
127
128
while (plen >= blocklen) {
129
if (inlen < blocklen) {
130
crypto_cursor_copydata(&cc_in, blocklen, block);
131
in = block;
132
inlen = blocklen;
133
} else {
134
in = inseg;
135
}
136
if (outlen < blocklen) {
137
out = block;
138
outlen = blocklen;
139
} else {
140
out = outseg;
141
}
142
143
/* Figure out how many blocks we can encrypt/decrypt at once. */
144
seglen = rounddown(MIN(plen, MIN(inlen, outlen)), blocklen);
145
146
AES_CBC_ENCRYPT(in, out, seglen, &key, iv, encrypt);
147
148
if (out == block) {
149
crypto_cursor_copyback(&cc_out, blocklen, block);
150
outseg = crypto_cursor_segment(&cc_out, &outlen);
151
} else {
152
crypto_cursor_advance(&cc_out, seglen);
153
outseg += seglen;
154
outlen -= seglen;
155
}
156
if (in == block) {
157
inseg = crypto_cursor_segment(&cc_in, &inlen);
158
} else {
159
crypto_cursor_advance(&cc_in, seglen);
160
inseg += seglen;
161
inlen -= seglen;
162
}
163
plen -= seglen;
164
}
165
166
explicit_bzero(block, sizeof(block));
167
explicit_bzero(iv, sizeof(iv));
168
explicit_bzero(&key, sizeof(key));
169
return (0);
170
}
171
172
static int
173
ossl_aes_gcm(struct ossl_session_cipher *s, struct cryptop *crp,
174
const struct crypto_session_params *csp)
175
{
176
struct ossl_gcm_context ctx;
177
struct crypto_buffer_cursor cc_in, cc_out;
178
unsigned char iv[AES_BLOCK_LEN], tag[AES_BLOCK_LEN];
179
const unsigned char *inseg;
180
unsigned char *outseg;
181
size_t inlen, outlen, seglen;
182
int error;
183
bool encrypt;
184
185
encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
186
187
if (crp->crp_cipher_key != NULL) {
188
if (encrypt)
189
error = s->cipher->set_encrypt_key(crp->crp_cipher_key,
190
8 * csp->csp_cipher_klen,
191
(struct ossl_cipher_context *)&ctx);
192
else
193
error = s->cipher->set_decrypt_key(crp->crp_cipher_key,
194
8 * csp->csp_cipher_klen,
195
(struct ossl_cipher_context *)&ctx);
196
if (error)
197
return (error);
198
} else if (encrypt) {
199
memcpy(&ctx, &s->enc_ctx, sizeof(struct ossl_gcm_context));
200
} else {
201
memcpy(&ctx, &s->dec_ctx, sizeof(struct ossl_gcm_context));
202
}
203
204
crypto_read_iv(crp, iv);
205
ctx.ops->setiv(&ctx, iv, csp->csp_ivlen);
206
207
if (crp->crp_aad != NULL) {
208
if (ctx.ops->aad(&ctx, crp->crp_aad, crp->crp_aad_length) != 0)
209
return (EINVAL);
210
} else {
211
crypto_cursor_init(&cc_in, &crp->crp_buf);
212
crypto_cursor_advance(&cc_in, crp->crp_aad_start);
213
for (size_t alen = crp->crp_aad_length; alen > 0;
214
alen -= seglen) {
215
inseg = crypto_cursor_segment(&cc_in, &inlen);
216
seglen = MIN(alen, inlen);
217
if (ctx.ops->aad(&ctx, inseg, seglen) != 0)
218
return (EINVAL);
219
crypto_cursor_advance(&cc_in, seglen);
220
}
221
}
222
223
crypto_cursor_init(&cc_in, &crp->crp_buf);
224
crypto_cursor_advance(&cc_in, crp->crp_payload_start);
225
if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
226
crypto_cursor_init(&cc_out, &crp->crp_obuf);
227
crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
228
} else {
229
cc_out = cc_in;
230
}
231
232
for (size_t plen = crp->crp_payload_length; plen > 0; plen -= seglen) {
233
inseg = crypto_cursor_segment(&cc_in, &inlen);
234
outseg = crypto_cursor_segment(&cc_out, &outlen);
235
seglen = MIN(plen, MIN(inlen, outlen));
236
237
if (encrypt) {
238
if (ctx.ops->encrypt(&ctx, inseg, outseg, seglen) != 0)
239
return (EINVAL);
240
} else {
241
if (ctx.ops->decrypt(&ctx, inseg, outseg, seglen) != 0)
242
return (EINVAL);
243
}
244
245
crypto_cursor_advance(&cc_in, seglen);
246
crypto_cursor_advance(&cc_out, seglen);
247
}
248
249
error = 0;
250
if (encrypt) {
251
ctx.ops->tag(&ctx, tag, GMAC_DIGEST_LEN);
252
crypto_copyback(crp, crp->crp_digest_start, GMAC_DIGEST_LEN,
253
tag);
254
} else {
255
crypto_copydata(crp, crp->crp_digest_start, GMAC_DIGEST_LEN,
256
tag);
257
if (ctx.ops->finish(&ctx, tag, GMAC_DIGEST_LEN) != 0)
258
error = EBADMSG;
259
}
260
261
explicit_bzero(iv, sizeof(iv));
262
explicit_bzero(tag, sizeof(tag));
263
explicit_bzero(&ctx, sizeof(ctx));
264
265
return (error);
266
}
267
268