Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/src/aes256.c
39478 views
1
/*
2
* Copyright (c) 2021 Yubico AB. All rights reserved.
3
* Use of this source code is governed by a BSD-style
4
* license that can be found in the LICENSE file.
5
* SPDX-License-Identifier: BSD-2-Clause
6
*/
7
8
#include "fido.h"
9
10
static int
11
aes256_cbc(const fido_blob_t *key, const u_char *iv, const fido_blob_t *in,
12
fido_blob_t *out, int encrypt)
13
{
14
EVP_CIPHER_CTX *ctx = NULL;
15
const EVP_CIPHER *cipher;
16
int ok = -1;
17
18
memset(out, 0, sizeof(*out));
19
20
if (key->len != 32) {
21
fido_log_debug("%s: invalid key len %zu", __func__, key->len);
22
goto fail;
23
}
24
if (in->len > UINT_MAX || in->len % 16 || in->len == 0) {
25
fido_log_debug("%s: invalid input len %zu", __func__, in->len);
26
goto fail;
27
}
28
out->len = in->len;
29
if ((out->ptr = calloc(1, out->len)) == NULL) {
30
fido_log_debug("%s: calloc", __func__);
31
goto fail;
32
}
33
if ((ctx = EVP_CIPHER_CTX_new()) == NULL ||
34
(cipher = EVP_aes_256_cbc()) == NULL) {
35
fido_log_debug("%s: EVP_CIPHER_CTX_new", __func__);
36
goto fail;
37
}
38
if (EVP_CipherInit(ctx, cipher, key->ptr, iv, encrypt) == 0 ||
39
EVP_Cipher(ctx, out->ptr, in->ptr, (u_int)out->len) < 0) {
40
fido_log_debug("%s: EVP_Cipher", __func__);
41
goto fail;
42
}
43
44
ok = 0;
45
fail:
46
if (ctx != NULL)
47
EVP_CIPHER_CTX_free(ctx);
48
if (ok < 0)
49
fido_blob_reset(out);
50
51
return ok;
52
}
53
54
static int
55
aes256_cbc_proto1(const fido_blob_t *key, const fido_blob_t *in,
56
fido_blob_t *out, int encrypt)
57
{
58
u_char iv[16];
59
60
memset(&iv, 0, sizeof(iv));
61
62
return aes256_cbc(key, iv, in, out, encrypt);
63
}
64
65
static int
66
aes256_cbc_fips(const fido_blob_t *secret, const fido_blob_t *in,
67
fido_blob_t *out, int encrypt)
68
{
69
fido_blob_t key, cin, cout;
70
u_char iv[16];
71
72
memset(out, 0, sizeof(*out));
73
74
if (secret->len != 64) {
75
fido_log_debug("%s: invalid secret len %zu", __func__,
76
secret->len);
77
return -1;
78
}
79
if (in->len < sizeof(iv)) {
80
fido_log_debug("%s: invalid input len %zu", __func__, in->len);
81
return -1;
82
}
83
if (encrypt) {
84
if (fido_get_random(iv, sizeof(iv)) < 0) {
85
fido_log_debug("%s: fido_get_random", __func__);
86
return -1;
87
}
88
cin = *in;
89
} else {
90
memcpy(iv, in->ptr, sizeof(iv));
91
cin.ptr = in->ptr + sizeof(iv);
92
cin.len = in->len - sizeof(iv);
93
}
94
key.ptr = secret->ptr + 32;
95
key.len = secret->len - 32;
96
if (aes256_cbc(&key, iv, &cin, &cout, encrypt) < 0)
97
return -1;
98
if (encrypt) {
99
if (cout.len > SIZE_MAX - sizeof(iv) ||
100
(out->ptr = calloc(1, sizeof(iv) + cout.len)) == NULL) {
101
fido_blob_reset(&cout);
102
return -1;
103
}
104
out->len = sizeof(iv) + cout.len;
105
memcpy(out->ptr, iv, sizeof(iv));
106
memcpy(out->ptr + sizeof(iv), cout.ptr, cout.len);
107
fido_blob_reset(&cout);
108
} else
109
*out = cout;
110
111
return 0;
112
}
113
114
static int
115
aes256_gcm(const fido_blob_t *key, const fido_blob_t *nonce,
116
const fido_blob_t *aad, const fido_blob_t *in, fido_blob_t *out,
117
int encrypt)
118
{
119
EVP_CIPHER_CTX *ctx = NULL;
120
const EVP_CIPHER *cipher;
121
size_t textlen;
122
int ok = -1;
123
124
memset(out, 0, sizeof(*out));
125
126
if (nonce->len != 12 || key->len != 32 || aad->len > UINT_MAX) {
127
fido_log_debug("%s: invalid params %zu, %zu, %zu", __func__,
128
nonce->len, key->len, aad->len);
129
goto fail;
130
}
131
if (in->len > UINT_MAX || in->len > SIZE_MAX - 16 || in->len < 16) {
132
fido_log_debug("%s: invalid input len %zu", __func__, in->len);
133
goto fail;
134
}
135
/* add tag to (on encrypt) or trim tag from the output (on decrypt) */
136
out->len = encrypt ? in->len + 16 : in->len - 16;
137
if ((out->ptr = calloc(1, out->len)) == NULL) {
138
fido_log_debug("%s: calloc", __func__);
139
goto fail;
140
}
141
if ((ctx = EVP_CIPHER_CTX_new()) == NULL ||
142
(cipher = EVP_aes_256_gcm()) == NULL) {
143
fido_log_debug("%s: EVP_CIPHER_CTX_new", __func__);
144
goto fail;
145
}
146
if (EVP_CipherInit(ctx, cipher, key->ptr, nonce->ptr, encrypt) == 0) {
147
fido_log_debug("%s: EVP_CipherInit", __func__);
148
goto fail;
149
}
150
151
if (encrypt)
152
textlen = in->len;
153
else {
154
textlen = in->len - 16;
155
/* point openssl at the mac tag */
156
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16,
157
in->ptr + in->len - 16) == 0) {
158
fido_log_debug("%s: EVP_CIPHER_CTX_ctrl", __func__);
159
goto fail;
160
}
161
}
162
/* the last EVP_Cipher() will either compute or verify the mac tag */
163
if (EVP_Cipher(ctx, NULL, aad->ptr, (u_int)aad->len) < 0 ||
164
EVP_Cipher(ctx, out->ptr, in->ptr, (u_int)textlen) < 0 ||
165
EVP_Cipher(ctx, NULL, NULL, 0) < 0) {
166
fido_log_debug("%s: EVP_Cipher", __func__);
167
goto fail;
168
}
169
if (encrypt) {
170
/* append the mac tag */
171
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16,
172
out->ptr + out->len - 16) == 0) {
173
fido_log_debug("%s: EVP_CIPHER_CTX_ctrl", __func__);
174
goto fail;
175
}
176
}
177
178
ok = 0;
179
fail:
180
if (ctx != NULL)
181
EVP_CIPHER_CTX_free(ctx);
182
if (ok < 0)
183
fido_blob_reset(out);
184
185
return ok;
186
}
187
188
int
189
aes256_cbc_enc(const fido_dev_t *dev, const fido_blob_t *secret,
190
const fido_blob_t *in, fido_blob_t *out)
191
{
192
return fido_dev_get_pin_protocol(dev) == 2 ? aes256_cbc_fips(secret,
193
in, out, 1) : aes256_cbc_proto1(secret, in, out, 1);
194
}
195
196
int
197
aes256_cbc_dec(const fido_dev_t *dev, const fido_blob_t *secret,
198
const fido_blob_t *in, fido_blob_t *out)
199
{
200
return fido_dev_get_pin_protocol(dev) == 2 ? aes256_cbc_fips(secret,
201
in, out, 0) : aes256_cbc_proto1(secret, in, out, 0);
202
}
203
204
int
205
aes256_gcm_enc(const fido_blob_t *key, const fido_blob_t *nonce,
206
const fido_blob_t *aad, const fido_blob_t *in, fido_blob_t *out)
207
{
208
return aes256_gcm(key, nonce, aad, in, out, 1);
209
}
210
211
int
212
aes256_gcm_dec(const fido_blob_t *key, const fido_blob_t *nonce,
213
const fido_blob_t *aad, const fido_blob_t *in, fido_blob_t *out)
214
{
215
return aes256_gcm(key, nonce, aad, in, out, 0);
216
}
217
218