/src/hostap/src/crypto/crypto_openssl.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Wrapper functions for OpenSSL libcrypto |
3 | | * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | #include <openssl/opensslv.h> |
11 | | #include <openssl/err.h> |
12 | | #include <openssl/des.h> |
13 | | #include <openssl/aes.h> |
14 | | #include <openssl/bn.h> |
15 | | #include <openssl/evp.h> |
16 | | #include <openssl/dh.h> |
17 | | #include <openssl/hmac.h> |
18 | | #include <openssl/rand.h> |
19 | | #include <openssl/rsa.h> |
20 | | #include <openssl/pem.h> |
21 | | #ifdef CONFIG_ECC |
22 | | #include <openssl/ec.h> |
23 | | #include <openssl/x509.h> |
24 | | #endif /* CONFIG_ECC */ |
25 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
26 | | #include <openssl/provider.h> |
27 | | #include <openssl/core_names.h> |
28 | | #include <openssl/param_build.h> |
29 | | #include <openssl/encoder.h> |
30 | | #include <openssl/decoder.h> |
31 | | #else /* OpenSSL version >= 3.0 */ |
32 | | #include <openssl/cmac.h> |
33 | | #endif /* OpenSSL version >= 3.0 */ |
34 | | #ifdef CONFIG_DPP3 |
35 | | #if OPENSSL_VERSION_NUMBER >= 0x30200000L |
36 | | #include <openssl/hpke.h> |
37 | | #endif |
38 | | #endif /* CONFIG_DPP3 */ |
39 | | |
40 | | #include "common.h" |
41 | | #include "utils/const_time.h" |
42 | | #include "wpabuf.h" |
43 | | #include "dh_group5.h" |
44 | | #include "sha1.h" |
45 | | #include "sha256.h" |
46 | | #include "sha384.h" |
47 | | #include "sha512.h" |
48 | | #include "md5.h" |
49 | | #include "aes_wrap.h" |
50 | | #include "crypto.h" |
51 | | |
52 | | #if OPENSSL_VERSION_NUMBER < 0x10100000L |
53 | | /* Compatibility wrappers for older versions. */ |
54 | | |
55 | | static HMAC_CTX * HMAC_CTX_new(void) |
56 | | { |
57 | | HMAC_CTX *ctx; |
58 | | |
59 | | ctx = os_zalloc(sizeof(*ctx)); |
60 | | if (ctx) |
61 | | HMAC_CTX_init(ctx); |
62 | | return ctx; |
63 | | } |
64 | | |
65 | | |
66 | | static void HMAC_CTX_free(HMAC_CTX *ctx) |
67 | | { |
68 | | if (!ctx) |
69 | | return; |
70 | | HMAC_CTX_cleanup(ctx); |
71 | | bin_clear_free(ctx, sizeof(*ctx)); |
72 | | } |
73 | | |
74 | | |
75 | | static EVP_MD_CTX * EVP_MD_CTX_new(void) |
76 | | { |
77 | | EVP_MD_CTX *ctx; |
78 | | |
79 | | ctx = os_zalloc(sizeof(*ctx)); |
80 | | if (ctx) |
81 | | EVP_MD_CTX_init(ctx); |
82 | | return ctx; |
83 | | } |
84 | | |
85 | | |
86 | | static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) |
87 | | { |
88 | | if (!ctx) |
89 | | return; |
90 | | EVP_MD_CTX_cleanup(ctx); |
91 | | bin_clear_free(ctx, sizeof(*ctx)); |
92 | | } |
93 | | |
94 | | |
95 | | #ifdef CONFIG_ECC |
96 | | |
97 | | static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) |
98 | | { |
99 | | if (pkey->type != EVP_PKEY_EC) |
100 | | return NULL; |
101 | | return pkey->pkey.ec; |
102 | | } |
103 | | |
104 | | |
105 | | static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) |
106 | | { |
107 | | sig->r = r; |
108 | | sig->s = s; |
109 | | return 1; |
110 | | } |
111 | | |
112 | | |
113 | | static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, |
114 | | const BIGNUM **ps) |
115 | | { |
116 | | if (pr) |
117 | | *pr = sig->r; |
118 | | if (ps) |
119 | | *ps = sig->s; |
120 | | } |
121 | | |
122 | | #endif /* CONFIG_ECC */ |
123 | | |
124 | | static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x) |
125 | | { |
126 | | return ASN1_STRING_data((ASN1_STRING *) x); |
127 | | } |
128 | | |
129 | | |
130 | | static const ASN1_TIME * X509_get0_notBefore(const X509 *x) |
131 | | { |
132 | | return X509_get_notBefore(x); |
133 | | } |
134 | | |
135 | | |
136 | | static const ASN1_TIME * X509_get0_notAfter(const X509 *x) |
137 | | { |
138 | | return X509_get_notAfter(x); |
139 | | } |
140 | | |
141 | | #endif /* OpenSSL version < 1.1.0 */ |
142 | | |
143 | | |
144 | | #if OPENSSL_VERSION_NUMBER < 0x10101000L || \ |
145 | | (defined(LIBRESSL_VERSION_NUMBER) && \ |
146 | | LIBRESSL_VERSION_NUMBER < 0x30400000L) |
147 | | |
148 | | static int EC_POINT_get_affine_coordinates(const EC_GROUP *group, |
149 | | const EC_POINT *point, BIGNUM *x, |
150 | | BIGNUM *y, BN_CTX *ctx) |
151 | | { |
152 | | return EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx); |
153 | | } |
154 | | |
155 | | |
156 | | static int EC_POINT_set_affine_coordinates(const EC_GROUP *group, |
157 | | EC_POINT *point, const BIGNUM *x, |
158 | | const BIGNUM *y, BN_CTX *ctx) |
159 | | { |
160 | | return EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx); |
161 | | } |
162 | | |
163 | | #endif /* OpenSSL version < 1.1.1 */ |
164 | | |
165 | | |
166 | | #if OPENSSL_VERSION_NUMBER < 0x10101000L || \ |
167 | | defined(OPENSSL_IS_BORINGSSL) || \ |
168 | | (defined(LIBRESSL_VERSION_NUMBER) && \ |
169 | | LIBRESSL_VERSION_NUMBER < 0x30400000L) |
170 | | |
171 | | static int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, |
172 | | EC_POINT *point, const BIGNUM *x, |
173 | | int y_bit, BN_CTX *ctx) |
174 | | { |
175 | | return EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, |
176 | | ctx); |
177 | | } |
178 | | |
179 | | |
180 | | static int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, |
181 | | BIGNUM *b, BN_CTX *ctx) |
182 | | { |
183 | | return EC_GROUP_get_curve_GFp(group, p, a, b, ctx); |
184 | | } |
185 | | |
186 | | #endif /* OpenSSL version < 1.1.1 */ |
187 | | |
188 | | |
189 | | static void openssl_disable_fips(void) |
190 | 0 | { |
191 | 0 | #ifndef CONFIG_FIPS |
192 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
193 | | static bool done = false; |
194 | | |
195 | | if (done) |
196 | | return; |
197 | | done = true; |
198 | | |
199 | | if (!EVP_default_properties_is_fips_enabled(NULL)) |
200 | | return; /* FIPS mode is not enabled */ |
201 | | |
202 | | if (!EVP_default_properties_enable_fips(NULL, 0)) |
203 | | wpa_printf(MSG_INFO, |
204 | | "OpenSSL: Failed to disable FIPS mode"); |
205 | | else |
206 | | wpa_printf(MSG_DEBUG, |
207 | | "OpenSSL: Disabled FIPS mode to enable non-FIPS-compliant algorithms and parameters"); |
208 | | #endif /* OpenSSL version >= 3.0 */ |
209 | 0 | #endif /* !CONFIG_FIPS */ |
210 | 0 | } |
211 | | |
212 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
213 | | static OSSL_PROVIDER *openssl_legacy_provider = NULL; |
214 | | static OSSL_PROVIDER *openssl_default_provider = NULL; |
215 | | #endif /* OpenSSL version >= 3.0 */ |
216 | | |
217 | | void openssl_load_legacy_provider(void) |
218 | 0 | { |
219 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
220 | | if (openssl_legacy_provider) |
221 | | return; |
222 | | |
223 | | openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "legacy", 1); |
224 | | #endif /* OpenSSL version >= 3.0 */ |
225 | 0 | } |
226 | | |
227 | | |
228 | | static void openssl_unload_legacy_provider(void) |
229 | 0 | { |
230 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
231 | | if (openssl_legacy_provider) { |
232 | | OSSL_PROVIDER_unload(openssl_legacy_provider); |
233 | | openssl_legacy_provider = NULL; |
234 | | } |
235 | | #endif /* OpenSSL version >= 3.0 */ |
236 | 0 | } |
237 | | |
238 | | |
239 | | static void openssl_load_default_provider_if_fips(void) |
240 | 0 | { |
241 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
242 | | if (openssl_default_provider) |
243 | | return; |
244 | | |
245 | | if (!OSSL_PROVIDER_available(NULL, "fips")) |
246 | | return; |
247 | | |
248 | | wpa_printf(MSG_DEBUG, |
249 | | "OpenSSL: Load default provider to replace fips provider when needed"); |
250 | | openssl_default_provider = OSSL_PROVIDER_try_load(NULL, "default", 1); |
251 | | if (!openssl_default_provider) |
252 | | wpa_printf(MSG_DEBUG, |
253 | | "OpenSSL: Failed to load default provider"); |
254 | | #endif /* OpenSSL version >= 3.0 */ |
255 | 0 | } |
256 | | |
257 | | |
258 | | static void openssl_unload_default_provider(void) |
259 | 0 | { |
260 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
261 | | if (openssl_default_provider) { |
262 | | OSSL_PROVIDER_unload(openssl_default_provider); |
263 | | openssl_default_provider = NULL; |
264 | | } |
265 | | #endif /* OpenSSL version >= 3.0 */ |
266 | 0 | } |
267 | | |
268 | | |
269 | | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
270 | | |
271 | | static BIGNUM * get_group5_prime(void) |
272 | 0 | { |
273 | 0 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L |
274 | 0 | return BN_get_rfc3526_prime_1536(NULL); |
275 | | #elif !defined(OPENSSL_IS_BORINGSSL) |
276 | | return get_rfc3526_prime_1536(NULL); |
277 | | #else |
278 | | static const unsigned char RFC3526_PRIME_1536[] = { |
279 | | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, |
280 | | 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, |
281 | | 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, |
282 | | 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, |
283 | | 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, |
284 | | 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, |
285 | | 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, |
286 | | 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, |
287 | | 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, |
288 | | 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, |
289 | | 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, |
290 | | 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, |
291 | | 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, |
292 | | 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, |
293 | | 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, |
294 | | 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
295 | | }; |
296 | | return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); |
297 | | #endif |
298 | 0 | } |
299 | | |
300 | | |
301 | | static BIGNUM * get_group5_order(void) |
302 | 0 | { |
303 | 0 | static const unsigned char RFC3526_ORDER_1536[] = { |
304 | 0 | 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51, |
305 | 0 | 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68, |
306 | 0 | 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53, |
307 | 0 | 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E, |
308 | 0 | 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36, |
309 | 0 | 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22, |
310 | 0 | 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74, |
311 | 0 | 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6, |
312 | 0 | 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08, |
313 | 0 | 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E, |
314 | 0 | 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B, |
315 | 0 | 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF, |
316 | 0 | 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB, |
317 | 0 | 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36, |
318 | 0 | 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04, |
319 | 0 | 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF |
320 | 0 | }; |
321 | 0 | return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL); |
322 | 0 | } |
323 | | |
324 | | #endif /* OpenSSL version < 3.0 */ |
325 | | |
326 | | |
327 | | #ifdef OPENSSL_NO_SHA256 |
328 | | #define NO_SHA256_WRAPPER |
329 | | #endif |
330 | | #ifdef OPENSSL_NO_SHA512 |
331 | | #define NO_SHA384_WRAPPER |
332 | | #endif |
333 | | |
334 | | static int openssl_digest_vector(const EVP_MD *type, size_t num_elem, |
335 | | const u8 *addr[], const size_t *len, u8 *mac) |
336 | 336 | { |
337 | 336 | EVP_MD_CTX *ctx; |
338 | 336 | size_t i; |
339 | 336 | unsigned int mac_len; |
340 | | |
341 | 336 | if (TEST_FAIL()) |
342 | 0 | return -1; |
343 | | |
344 | 336 | ctx = EVP_MD_CTX_new(); |
345 | 336 | if (!ctx) |
346 | 0 | return -1; |
347 | 336 | if (!EVP_DigestInit_ex(ctx, type, NULL)) { |
348 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", |
349 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
350 | 0 | EVP_MD_CTX_free(ctx); |
351 | 0 | return -1; |
352 | 0 | } |
353 | 840 | for (i = 0; i < num_elem; i++) { |
354 | 504 | if (!EVP_DigestUpdate(ctx, addr[i], len[i])) { |
355 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " |
356 | 0 | "failed: %s", |
357 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
358 | 0 | EVP_MD_CTX_free(ctx); |
359 | 0 | return -1; |
360 | 0 | } |
361 | 504 | } |
362 | 336 | if (!EVP_DigestFinal(ctx, mac, &mac_len)) { |
363 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", |
364 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
365 | 0 | EVP_MD_CTX_free(ctx); |
366 | 0 | return -1; |
367 | 0 | } |
368 | 336 | EVP_MD_CTX_free(ctx); |
369 | | |
370 | 336 | return 0; |
371 | 336 | } |
372 | | |
373 | | |
374 | | #ifndef CONFIG_FIPS |
375 | | |
376 | | static void openssl_need_md5(void) |
377 | 0 | { |
378 | 0 | openssl_disable_fips(); |
379 | 0 | openssl_load_default_provider_if_fips(); |
380 | 0 | } |
381 | | |
382 | | |
383 | | int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
384 | 0 | { |
385 | 0 | openssl_disable_fips(); |
386 | 0 | openssl_load_legacy_provider(); |
387 | 0 | return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac); |
388 | 0 | } |
389 | | |
390 | | |
391 | | int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) |
392 | 0 | { |
393 | 0 | u8 pkey[8], next, tmp; |
394 | 0 | int i, plen, ret = -1; |
395 | 0 | EVP_CIPHER_CTX *ctx; |
396 | |
|
397 | 0 | openssl_load_legacy_provider(); |
398 | | |
399 | | /* Add parity bits to the key */ |
400 | 0 | next = 0; |
401 | 0 | for (i = 0; i < 7; i++) { |
402 | 0 | tmp = key[i]; |
403 | 0 | pkey[i] = (tmp >> i) | next | 1; |
404 | 0 | next = tmp << (7 - i); |
405 | 0 | } |
406 | 0 | pkey[i] = next | 1; |
407 | |
|
408 | 0 | ctx = EVP_CIPHER_CTX_new(); |
409 | 0 | if (ctx && |
410 | 0 | EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, pkey, NULL) == 1 && |
411 | 0 | EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && |
412 | 0 | EVP_EncryptUpdate(ctx, cypher, &plen, clear, 8) == 1 && |
413 | 0 | EVP_EncryptFinal_ex(ctx, &cypher[plen], &plen) == 1) |
414 | 0 | ret = 0; |
415 | 0 | else |
416 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: DES encrypt failed"); |
417 | |
|
418 | 0 | if (ctx) |
419 | 0 | EVP_CIPHER_CTX_free(ctx); |
420 | 0 | return ret; |
421 | 0 | } |
422 | | |
423 | | |
424 | | #ifndef CONFIG_NO_RC4 |
425 | | int rc4_skip(const u8 *key, size_t keylen, size_t skip, |
426 | | u8 *data, size_t data_len) |
427 | 0 | { |
428 | | #ifdef OPENSSL_NO_RC4 |
429 | | return -1; |
430 | | #else /* OPENSSL_NO_RC4 */ |
431 | 0 | EVP_CIPHER_CTX *ctx; |
432 | 0 | int outl; |
433 | 0 | int res = -1; |
434 | 0 | unsigned char skip_buf[16]; |
435 | |
|
436 | 0 | openssl_load_legacy_provider(); |
437 | |
|
438 | 0 | ctx = EVP_CIPHER_CTX_new(); |
439 | 0 | if (!ctx || |
440 | 0 | !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) || |
441 | 0 | !EVP_CIPHER_CTX_set_padding(ctx, 0) || |
442 | 0 | !EVP_CIPHER_CTX_set_key_length(ctx, keylen) || |
443 | 0 | !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1)) |
444 | 0 | goto out; |
445 | | |
446 | 0 | while (skip >= sizeof(skip_buf)) { |
447 | 0 | size_t len = skip; |
448 | 0 | if (len > sizeof(skip_buf)) |
449 | 0 | len = sizeof(skip_buf); |
450 | 0 | if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len)) |
451 | 0 | goto out; |
452 | 0 | skip -= len; |
453 | 0 | } |
454 | | |
455 | 0 | if (EVP_CipherUpdate(ctx, data, &outl, data, data_len)) |
456 | 0 | res = 0; |
457 | |
|
458 | 0 | out: |
459 | 0 | if (ctx) |
460 | 0 | EVP_CIPHER_CTX_free(ctx); |
461 | 0 | return res; |
462 | 0 | #endif /* OPENSSL_NO_RC4 */ |
463 | 0 | } |
464 | | #endif /* CONFIG_NO_RC4 */ |
465 | | |
466 | | |
467 | | int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
468 | 0 | { |
469 | 0 | openssl_need_md5(); |
470 | 0 | return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac); |
471 | 0 | } |
472 | | |
473 | | #endif /* CONFIG_FIPS */ |
474 | | |
475 | | |
476 | | int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
477 | 0 | { |
478 | 0 | return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac); |
479 | 0 | } |
480 | | |
481 | | |
482 | | #ifndef NO_SHA256_WRAPPER |
483 | | int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, |
484 | | u8 *mac) |
485 | 336 | { |
486 | 336 | return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac); |
487 | 336 | } |
488 | | #endif /* NO_SHA256_WRAPPER */ |
489 | | |
490 | | |
491 | | #ifndef NO_SHA384_WRAPPER |
492 | | int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, |
493 | | u8 *mac) |
494 | 0 | { |
495 | 0 | return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac); |
496 | 0 | } |
497 | | #endif /* NO_SHA384_WRAPPER */ |
498 | | |
499 | | |
500 | | #ifndef NO_SHA512_WRAPPER |
501 | | int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, |
502 | | u8 *mac) |
503 | 0 | { |
504 | 0 | return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac); |
505 | 0 | } |
506 | | #endif /* NO_SHA512_WRAPPER */ |
507 | | |
508 | | |
509 | | static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen) |
510 | 0 | { |
511 | 0 | switch (keylen) { |
512 | 0 | case 16: |
513 | 0 | return EVP_aes_128_ecb(); |
514 | 0 | case 24: |
515 | 0 | return EVP_aes_192_ecb(); |
516 | 0 | case 32: |
517 | 0 | return EVP_aes_256_ecb(); |
518 | 0 | default: |
519 | 0 | return NULL; |
520 | 0 | } |
521 | 0 | } |
522 | | |
523 | | |
524 | | void * aes_encrypt_init(const u8 *key, size_t len) |
525 | 0 | { |
526 | 0 | EVP_CIPHER_CTX *ctx; |
527 | 0 | const EVP_CIPHER *type; |
528 | |
|
529 | 0 | if (TEST_FAIL()) |
530 | 0 | return NULL; |
531 | | |
532 | 0 | type = aes_get_evp_cipher(len); |
533 | 0 | if (!type) { |
534 | 0 | wpa_printf(MSG_INFO, "%s: Unsupported len=%u", |
535 | 0 | __func__, (unsigned int) len); |
536 | 0 | return NULL; |
537 | 0 | } |
538 | | |
539 | 0 | ctx = EVP_CIPHER_CTX_new(); |
540 | 0 | if (ctx == NULL) |
541 | 0 | return NULL; |
542 | 0 | if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1 || |
543 | 0 | EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) { |
544 | 0 | EVP_CIPHER_CTX_free(ctx); |
545 | 0 | return NULL; |
546 | 0 | } |
547 | 0 | return ctx; |
548 | 0 | } |
549 | | |
550 | | |
551 | | int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) |
552 | 0 | { |
553 | 0 | EVP_CIPHER_CTX *c = ctx; |
554 | 0 | int clen = 16; |
555 | 0 | if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) { |
556 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s", |
557 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
558 | 0 | return -1; |
559 | 0 | } |
560 | 0 | return 0; |
561 | 0 | } |
562 | | |
563 | | |
564 | | void aes_encrypt_deinit(void *ctx) |
565 | 0 | { |
566 | 0 | EVP_CIPHER_CTX *c = ctx; |
567 | 0 | u8 buf[16]; |
568 | 0 | int len = sizeof(buf); |
569 | 0 | if (EVP_EncryptFinal_ex(c, buf, &len) != 1) { |
570 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: " |
571 | 0 | "%s", ERR_error_string(ERR_get_error(), NULL)); |
572 | 0 | } |
573 | 0 | if (len != 0) { |
574 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " |
575 | 0 | "in AES encrypt", len); |
576 | 0 | } |
577 | 0 | EVP_CIPHER_CTX_free(c); |
578 | 0 | } |
579 | | |
580 | | |
581 | | void * aes_decrypt_init(const u8 *key, size_t len) |
582 | 0 | { |
583 | 0 | EVP_CIPHER_CTX *ctx; |
584 | 0 | const EVP_CIPHER *type; |
585 | |
|
586 | 0 | if (TEST_FAIL()) |
587 | 0 | return NULL; |
588 | | |
589 | 0 | type = aes_get_evp_cipher(len); |
590 | 0 | if (!type) { |
591 | 0 | wpa_printf(MSG_INFO, "%s: Unsupported len=%u", |
592 | 0 | __func__, (unsigned int) len); |
593 | 0 | return NULL; |
594 | 0 | } |
595 | | |
596 | 0 | ctx = EVP_CIPHER_CTX_new(); |
597 | 0 | if (ctx == NULL) |
598 | 0 | return NULL; |
599 | 0 | if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1 || |
600 | 0 | EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) { |
601 | 0 | EVP_CIPHER_CTX_free(ctx); |
602 | 0 | return NULL; |
603 | 0 | } |
604 | 0 | return ctx; |
605 | 0 | } |
606 | | |
607 | | |
608 | | int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) |
609 | 0 | { |
610 | 0 | EVP_CIPHER_CTX *c = ctx; |
611 | 0 | int plen = 16; |
612 | 0 | if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) { |
613 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s", |
614 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
615 | 0 | return -1; |
616 | 0 | } |
617 | 0 | return 0; |
618 | 0 | } |
619 | | |
620 | | |
621 | | void aes_decrypt_deinit(void *ctx) |
622 | 0 | { |
623 | 0 | EVP_CIPHER_CTX *c = ctx; |
624 | 0 | u8 buf[16]; |
625 | 0 | int len = sizeof(buf); |
626 | 0 | if (EVP_DecryptFinal_ex(c, buf, &len) != 1) { |
627 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: " |
628 | 0 | "%s", ERR_error_string(ERR_get_error(), NULL)); |
629 | 0 | } |
630 | 0 | if (len != 0) { |
631 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " |
632 | 0 | "in AES decrypt", len); |
633 | 0 | } |
634 | 0 | EVP_CIPHER_CTX_free(c); |
635 | 0 | } |
636 | | |
637 | | |
638 | | #ifndef CONFIG_FIPS |
639 | | #ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP |
640 | | |
641 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
642 | | static const EVP_CIPHER * aes_get_evp_wrap_cipher(size_t keylen) |
643 | | { |
644 | | switch (keylen) { |
645 | | case 16: |
646 | | return EVP_aes_128_wrap(); |
647 | | case 24: |
648 | | return EVP_aes_192_wrap(); |
649 | | case 32: |
650 | | return EVP_aes_256_wrap(); |
651 | | default: |
652 | | return NULL; |
653 | | } |
654 | | } |
655 | | #endif /* OpenSSL version >= 3.0 */ |
656 | | |
657 | | |
658 | | int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) |
659 | 0 | { |
660 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
661 | | EVP_CIPHER_CTX *ctx; |
662 | | const EVP_CIPHER *type; |
663 | | int ret = -1, len; |
664 | | u8 buf[16]; |
665 | | |
666 | | if (TEST_FAIL()) |
667 | | return -1; |
668 | | |
669 | | type = aes_get_evp_wrap_cipher(kek_len); |
670 | | if (!type) |
671 | | return -1; |
672 | | |
673 | | ctx = EVP_CIPHER_CTX_new(); |
674 | | if (!ctx) |
675 | | return -1; |
676 | | |
677 | | if (EVP_EncryptInit_ex(ctx, type, NULL, kek, NULL) == 1 && |
678 | | EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && |
679 | | EVP_EncryptUpdate(ctx, cipher, &len, plain, n * 8) == 1 && |
680 | | len == (n + 1) * 8 && |
681 | | EVP_EncryptFinal_ex(ctx, buf, &len) == 1) |
682 | | ret = 0; |
683 | | |
684 | | EVP_CIPHER_CTX_free(ctx); |
685 | | return ret; |
686 | | #else /* OpenSSL version >= 3.0 */ |
687 | 0 | AES_KEY actx; |
688 | 0 | int res; |
689 | |
|
690 | 0 | if (TEST_FAIL()) |
691 | 0 | return -1; |
692 | 0 | if (AES_set_encrypt_key(kek, kek_len << 3, &actx)) |
693 | 0 | return -1; |
694 | 0 | res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8); |
695 | 0 | OPENSSL_cleanse(&actx, sizeof(actx)); |
696 | 0 | return res <= 0 ? -1 : 0; |
697 | 0 | #endif /* OpenSSL version >= 3.0 */ |
698 | 0 | } |
699 | | |
700 | | |
701 | | int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, |
702 | | u8 *plain) |
703 | 0 | { |
704 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
705 | | EVP_CIPHER_CTX *ctx; |
706 | | const EVP_CIPHER *type; |
707 | | int ret = -1, len; |
708 | | u8 buf[16]; |
709 | | |
710 | | if (TEST_FAIL()) |
711 | | return -1; |
712 | | |
713 | | type = aes_get_evp_wrap_cipher(kek_len); |
714 | | if (!type) |
715 | | return -1; |
716 | | |
717 | | ctx = EVP_CIPHER_CTX_new(); |
718 | | if (!ctx) |
719 | | return -1; |
720 | | |
721 | | if (EVP_DecryptInit_ex(ctx, type, NULL, kek, NULL) == 1 && |
722 | | EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && |
723 | | EVP_DecryptUpdate(ctx, plain, &len, cipher, (n + 1) * 8) == 1 && |
724 | | len == n * 8 && |
725 | | EVP_DecryptFinal_ex(ctx, buf, &len) == 1) |
726 | | ret = 0; |
727 | | |
728 | | EVP_CIPHER_CTX_free(ctx); |
729 | | return ret; |
730 | | #else /* OpenSSL version >= 3.0 */ |
731 | 0 | AES_KEY actx; |
732 | 0 | int res; |
733 | |
|
734 | 0 | if (TEST_FAIL()) |
735 | 0 | return -1; |
736 | 0 | if (AES_set_decrypt_key(kek, kek_len << 3, &actx)) |
737 | 0 | return -1; |
738 | 0 | res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8); |
739 | 0 | OPENSSL_cleanse(&actx, sizeof(actx)); |
740 | 0 | return res <= 0 ? -1 : 0; |
741 | 0 | #endif /* OpenSSL version >= 3.0 */ |
742 | 0 | } |
743 | | |
744 | | #endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */ |
745 | | #endif /* CONFIG_FIPS */ |
746 | | |
747 | | |
748 | | int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) |
749 | 0 | { |
750 | 0 | EVP_CIPHER_CTX *ctx; |
751 | 0 | int clen, len; |
752 | 0 | u8 buf[16]; |
753 | 0 | int res = -1; |
754 | |
|
755 | 0 | if (TEST_FAIL()) |
756 | 0 | return -1; |
757 | | |
758 | 0 | ctx = EVP_CIPHER_CTX_new(); |
759 | 0 | if (!ctx) |
760 | 0 | return -1; |
761 | 0 | clen = data_len; |
762 | 0 | len = sizeof(buf); |
763 | 0 | if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && |
764 | 0 | EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && |
765 | 0 | EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 && |
766 | 0 | clen == (int) data_len && |
767 | 0 | EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0) |
768 | 0 | res = 0; |
769 | 0 | EVP_CIPHER_CTX_free(ctx); |
770 | |
|
771 | 0 | return res; |
772 | 0 | } |
773 | | |
774 | | |
775 | | int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) |
776 | 0 | { |
777 | 0 | EVP_CIPHER_CTX *ctx; |
778 | 0 | int plen, len; |
779 | 0 | u8 buf[16]; |
780 | 0 | int res = -1; |
781 | |
|
782 | 0 | if (TEST_FAIL()) |
783 | 0 | return -1; |
784 | | |
785 | 0 | ctx = EVP_CIPHER_CTX_new(); |
786 | 0 | if (!ctx) |
787 | 0 | return -1; |
788 | 0 | plen = data_len; |
789 | 0 | len = sizeof(buf); |
790 | 0 | if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && |
791 | 0 | EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && |
792 | 0 | EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 && |
793 | 0 | plen == (int) data_len && |
794 | 0 | EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0) |
795 | 0 | res = 0; |
796 | 0 | EVP_CIPHER_CTX_free(ctx); |
797 | |
|
798 | 0 | return res; |
799 | |
|
800 | 0 | } |
801 | | |
802 | | |
803 | | int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, |
804 | | u8 *pubkey) |
805 | 0 | { |
806 | 0 | size_t pubkey_len, pad; |
807 | |
|
808 | 0 | if (os_get_random(privkey, prime_len) < 0) |
809 | 0 | return -1; |
810 | 0 | if (os_memcmp(privkey, prime, prime_len) > 0) { |
811 | | /* Make sure private value is smaller than prime */ |
812 | 0 | privkey[0] = 0; |
813 | 0 | } |
814 | |
|
815 | 0 | pubkey_len = prime_len; |
816 | 0 | if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, |
817 | 0 | pubkey, &pubkey_len) < 0) |
818 | 0 | return -1; |
819 | 0 | if (pubkey_len < prime_len) { |
820 | 0 | pad = prime_len - pubkey_len; |
821 | 0 | os_memmove(pubkey + pad, pubkey, pubkey_len); |
822 | 0 | os_memset(pubkey, 0, pad); |
823 | 0 | } |
824 | |
|
825 | 0 | return 0; |
826 | 0 | } |
827 | | |
828 | | |
829 | | int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, |
830 | | const u8 *order, size_t order_len, |
831 | | const u8 *privkey, size_t privkey_len, |
832 | | const u8 *pubkey, size_t pubkey_len, |
833 | | u8 *secret, size_t *len) |
834 | 0 | { |
835 | 0 | BIGNUM *pub, *p; |
836 | 0 | int res = -1; |
837 | |
|
838 | 0 | pub = BN_bin2bn(pubkey, pubkey_len, NULL); |
839 | 0 | p = BN_bin2bn(prime, prime_len, NULL); |
840 | 0 | if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) || |
841 | 0 | BN_cmp(pub, p) >= 0) |
842 | 0 | goto fail; |
843 | | |
844 | 0 | if (order) { |
845 | 0 | BN_CTX *ctx; |
846 | 0 | BIGNUM *q, *tmp; |
847 | 0 | int failed; |
848 | | |
849 | | /* verify: pubkey^q == 1 mod p */ |
850 | 0 | q = BN_bin2bn(order, order_len, NULL); |
851 | 0 | ctx = BN_CTX_new(); |
852 | 0 | tmp = BN_new(); |
853 | 0 | failed = !q || !ctx || !tmp || |
854 | 0 | !BN_mod_exp(tmp, pub, q, p, ctx) || |
855 | 0 | !BN_is_one(tmp); |
856 | 0 | BN_clear_free(q); |
857 | 0 | BN_clear_free(tmp); |
858 | 0 | BN_CTX_free(ctx); |
859 | 0 | if (failed) |
860 | 0 | goto fail; |
861 | 0 | } |
862 | | |
863 | 0 | res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, |
864 | 0 | prime, prime_len, secret, len); |
865 | 0 | fail: |
866 | 0 | BN_clear_free(pub); |
867 | 0 | BN_clear_free(p); |
868 | 0 | return res; |
869 | 0 | } |
870 | | |
871 | | |
872 | | int crypto_mod_exp(const u8 *base, size_t base_len, |
873 | | const u8 *power, size_t power_len, |
874 | | const u8 *modulus, size_t modulus_len, |
875 | | u8 *result, size_t *result_len) |
876 | 0 | { |
877 | 0 | BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; |
878 | 0 | int ret = -1; |
879 | 0 | BN_CTX *ctx; |
880 | |
|
881 | 0 | ctx = BN_CTX_new(); |
882 | 0 | if (ctx == NULL) |
883 | 0 | return -1; |
884 | | |
885 | 0 | bn_base = BN_bin2bn(base, base_len, NULL); |
886 | 0 | bn_exp = BN_bin2bn(power, power_len, NULL); |
887 | 0 | bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); |
888 | 0 | bn_result = BN_new(); |
889 | |
|
890 | 0 | if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || |
891 | 0 | bn_result == NULL) |
892 | 0 | goto error; |
893 | | |
894 | 0 | if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus, |
895 | 0 | ctx, NULL) != 1) |
896 | 0 | goto error; |
897 | | |
898 | 0 | *result_len = BN_bn2bin(bn_result, result); |
899 | 0 | ret = 0; |
900 | |
|
901 | 0 | error: |
902 | 0 | BN_clear_free(bn_base); |
903 | 0 | BN_clear_free(bn_exp); |
904 | 0 | BN_clear_free(bn_modulus); |
905 | 0 | BN_clear_free(bn_result); |
906 | 0 | BN_CTX_free(ctx); |
907 | 0 | return ret; |
908 | 0 | } |
909 | | |
910 | | |
911 | | struct crypto_cipher { |
912 | | EVP_CIPHER_CTX *enc; |
913 | | EVP_CIPHER_CTX *dec; |
914 | | }; |
915 | | |
916 | | |
917 | | struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, |
918 | | const u8 *iv, const u8 *key, |
919 | | size_t key_len) |
920 | 0 | { |
921 | 0 | struct crypto_cipher *ctx; |
922 | 0 | const EVP_CIPHER *cipher; |
923 | |
|
924 | 0 | ctx = os_zalloc(sizeof(*ctx)); |
925 | 0 | if (ctx == NULL) |
926 | 0 | return NULL; |
927 | | |
928 | 0 | switch (alg) { |
929 | 0 | #ifndef CONFIG_NO_RC4 |
930 | 0 | #ifndef OPENSSL_NO_RC4 |
931 | 0 | case CRYPTO_CIPHER_ALG_RC4: |
932 | 0 | cipher = EVP_rc4(); |
933 | 0 | break; |
934 | 0 | #endif /* OPENSSL_NO_RC4 */ |
935 | 0 | #endif /* CONFIG_NO_RC4 */ |
936 | 0 | #ifndef OPENSSL_NO_AES |
937 | 0 | case CRYPTO_CIPHER_ALG_AES: |
938 | 0 | switch (key_len) { |
939 | 0 | case 16: |
940 | 0 | cipher = EVP_aes_128_cbc(); |
941 | 0 | break; |
942 | 0 | #ifndef OPENSSL_IS_BORINGSSL |
943 | 0 | case 24: |
944 | 0 | cipher = EVP_aes_192_cbc(); |
945 | 0 | break; |
946 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
947 | 0 | case 32: |
948 | 0 | cipher = EVP_aes_256_cbc(); |
949 | 0 | break; |
950 | 0 | default: |
951 | 0 | os_free(ctx); |
952 | 0 | return NULL; |
953 | 0 | } |
954 | 0 | break; |
955 | 0 | #endif /* OPENSSL_NO_AES */ |
956 | 0 | #ifndef OPENSSL_NO_DES |
957 | 0 | case CRYPTO_CIPHER_ALG_3DES: |
958 | 0 | cipher = EVP_des_ede3_cbc(); |
959 | 0 | break; |
960 | 0 | case CRYPTO_CIPHER_ALG_DES: |
961 | 0 | cipher = EVP_des_cbc(); |
962 | 0 | break; |
963 | 0 | #endif /* OPENSSL_NO_DES */ |
964 | 0 | #ifndef OPENSSL_NO_RC2 |
965 | 0 | case CRYPTO_CIPHER_ALG_RC2: |
966 | 0 | cipher = EVP_rc2_ecb(); |
967 | 0 | break; |
968 | 0 | #endif /* OPENSSL_NO_RC2 */ |
969 | 0 | default: |
970 | 0 | os_free(ctx); |
971 | 0 | return NULL; |
972 | 0 | } |
973 | | |
974 | 0 | if (!(ctx->enc = EVP_CIPHER_CTX_new()) || |
975 | 0 | !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) || |
976 | 0 | !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) || |
977 | 0 | !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) || |
978 | 0 | !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) { |
979 | 0 | if (ctx->enc) |
980 | 0 | EVP_CIPHER_CTX_free(ctx->enc); |
981 | 0 | os_free(ctx); |
982 | 0 | return NULL; |
983 | 0 | } |
984 | | |
985 | 0 | if (!(ctx->dec = EVP_CIPHER_CTX_new()) || |
986 | 0 | !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) || |
987 | 0 | !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) || |
988 | 0 | !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) || |
989 | 0 | !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) { |
990 | 0 | EVP_CIPHER_CTX_free(ctx->enc); |
991 | 0 | if (ctx->dec) |
992 | 0 | EVP_CIPHER_CTX_free(ctx->dec); |
993 | 0 | os_free(ctx); |
994 | 0 | return NULL; |
995 | 0 | } |
996 | | |
997 | 0 | return ctx; |
998 | 0 | } |
999 | | |
1000 | | |
1001 | | int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, |
1002 | | u8 *crypt, size_t len) |
1003 | 0 | { |
1004 | 0 | int outl; |
1005 | 0 | if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len)) |
1006 | 0 | return -1; |
1007 | 0 | return 0; |
1008 | 0 | } |
1009 | | |
1010 | | |
1011 | | int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, |
1012 | | u8 *plain, size_t len) |
1013 | 0 | { |
1014 | 0 | int outl; |
1015 | 0 | outl = len; |
1016 | 0 | if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len)) |
1017 | 0 | return -1; |
1018 | 0 | return 0; |
1019 | 0 | } |
1020 | | |
1021 | | |
1022 | | void crypto_cipher_deinit(struct crypto_cipher *ctx) |
1023 | 0 | { |
1024 | 0 | EVP_CIPHER_CTX_free(ctx->enc); |
1025 | 0 | EVP_CIPHER_CTX_free(ctx->dec); |
1026 | 0 | os_free(ctx); |
1027 | 0 | } |
1028 | | |
1029 | | |
1030 | | void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) |
1031 | 0 | { |
1032 | | #if OPENSSL_VERSION_NUMBER < 0x10100000L |
1033 | | DH *dh; |
1034 | | struct wpabuf *pubkey = NULL, *privkey = NULL; |
1035 | | size_t publen, privlen; |
1036 | | |
1037 | | *priv = NULL; |
1038 | | wpabuf_free(*publ); |
1039 | | *publ = NULL; |
1040 | | |
1041 | | dh = DH_new(); |
1042 | | if (dh == NULL) |
1043 | | return NULL; |
1044 | | |
1045 | | dh->g = BN_new(); |
1046 | | if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) |
1047 | | goto err; |
1048 | | |
1049 | | dh->p = get_group5_prime(); |
1050 | | if (dh->p == NULL) |
1051 | | goto err; |
1052 | | |
1053 | | dh->q = get_group5_order(); |
1054 | | if (!dh->q) |
1055 | | goto err; |
1056 | | |
1057 | | if (DH_generate_key(dh) != 1) |
1058 | | goto err; |
1059 | | |
1060 | | publen = BN_num_bytes(dh->pub_key); |
1061 | | pubkey = wpabuf_alloc(publen); |
1062 | | if (pubkey == NULL) |
1063 | | goto err; |
1064 | | privlen = BN_num_bytes(dh->priv_key); |
1065 | | privkey = wpabuf_alloc(privlen); |
1066 | | if (privkey == NULL) |
1067 | | goto err; |
1068 | | |
1069 | | BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); |
1070 | | BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); |
1071 | | |
1072 | | *priv = privkey; |
1073 | | *publ = pubkey; |
1074 | | return dh; |
1075 | | |
1076 | | err: |
1077 | | wpabuf_clear_free(pubkey); |
1078 | | wpabuf_clear_free(privkey); |
1079 | | DH_free(dh); |
1080 | | return NULL; |
1081 | | #elif OPENSSL_VERSION_NUMBER >= 0x30000000L |
1082 | | EVP_PKEY *pkey = NULL; |
1083 | | OSSL_PARAM params[2]; |
1084 | | size_t pub_len = OSSL_PARAM_UNMODIFIED; |
1085 | | size_t priv_len; |
1086 | | struct wpabuf *pubkey = NULL, *privkey = NULL; |
1087 | | BIGNUM *priv_bn = NULL; |
1088 | | EVP_PKEY_CTX *gctx; |
1089 | | const char *propquery = NULL; |
1090 | | |
1091 | | *priv = NULL; |
1092 | | wpabuf_free(*publ); |
1093 | | *publ = NULL; |
1094 | | |
1095 | | if (OSSL_PROVIDER_available(NULL, "fips")) { |
1096 | | openssl_disable_fips(); |
1097 | | openssl_load_default_provider_if_fips(); |
1098 | | propquery = "provider!=fips"; |
1099 | | } |
1100 | | |
1101 | | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, |
1102 | | "modp_1536", 0); |
1103 | | params[1] = OSSL_PARAM_construct_end(); |
1104 | | |
1105 | | gctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", propquery); |
1106 | | if (!gctx || |
1107 | | EVP_PKEY_keygen_init(gctx) != 1 || |
1108 | | EVP_PKEY_CTX_set_params(gctx, params) != 1 || |
1109 | | EVP_PKEY_generate(gctx, &pkey) != 1 || |
1110 | | EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, |
1111 | | &priv_bn) != 1 || |
1112 | | EVP_PKEY_get_octet_string_param(pkey, |
1113 | | OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, |
1114 | | NULL, 0, &pub_len) < 0 || |
1115 | | pub_len == OSSL_PARAM_UNMODIFIED || |
1116 | | (priv_len = BN_num_bytes(priv_bn)) == 0 || |
1117 | | !(pubkey = wpabuf_alloc(pub_len)) || |
1118 | | !(privkey = wpabuf_alloc(priv_len)) || |
1119 | | EVP_PKEY_get_octet_string_param(pkey, |
1120 | | OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, |
1121 | | wpabuf_put(pubkey, pub_len), |
1122 | | pub_len, NULL) != 1) { |
1123 | | wpa_printf(MSG_INFO, "OpenSSL: failed: %s", |
1124 | | ERR_error_string(ERR_get_error(), NULL)); |
1125 | | wpabuf_free(pubkey); |
1126 | | wpabuf_clear_free(privkey); |
1127 | | EVP_PKEY_free(pkey); |
1128 | | pkey = NULL; |
1129 | | } else { |
1130 | | BN_bn2bin(priv_bn, wpabuf_put(privkey, priv_len)); |
1131 | | |
1132 | | *priv = privkey; |
1133 | | *publ = pubkey; |
1134 | | } |
1135 | | |
1136 | | BN_clear_free(priv_bn); |
1137 | | EVP_PKEY_CTX_free(gctx); |
1138 | | return pkey; |
1139 | | #else |
1140 | 0 | DH *dh; |
1141 | 0 | struct wpabuf *pubkey = NULL, *privkey = NULL; |
1142 | 0 | size_t publen, privlen; |
1143 | 0 | BIGNUM *p, *g, *q; |
1144 | 0 | const BIGNUM *priv_key = NULL, *pub_key = NULL; |
1145 | |
|
1146 | 0 | *priv = NULL; |
1147 | 0 | wpabuf_free(*publ); |
1148 | 0 | *publ = NULL; |
1149 | |
|
1150 | 0 | dh = DH_new(); |
1151 | 0 | if (dh == NULL) |
1152 | 0 | return NULL; |
1153 | | |
1154 | 0 | g = BN_new(); |
1155 | 0 | p = get_group5_prime(); |
1156 | 0 | q = get_group5_order(); |
1157 | 0 | if (!g || BN_set_word(g, 2) != 1 || !p || !q || |
1158 | 0 | DH_set0_pqg(dh, p, q, g) != 1) |
1159 | 0 | goto err; |
1160 | 0 | p = NULL; |
1161 | 0 | q = NULL; |
1162 | 0 | g = NULL; |
1163 | |
|
1164 | 0 | if (DH_generate_key(dh) != 1) |
1165 | 0 | goto err; |
1166 | | |
1167 | 0 | DH_get0_key(dh, &pub_key, &priv_key); |
1168 | 0 | publen = BN_num_bytes(pub_key); |
1169 | 0 | pubkey = wpabuf_alloc(publen); |
1170 | 0 | if (!pubkey) |
1171 | 0 | goto err; |
1172 | 0 | privlen = BN_num_bytes(priv_key); |
1173 | 0 | privkey = wpabuf_alloc(privlen); |
1174 | 0 | if (!privkey) |
1175 | 0 | goto err; |
1176 | | |
1177 | 0 | BN_bn2bin(pub_key, wpabuf_put(pubkey, publen)); |
1178 | 0 | BN_bn2bin(priv_key, wpabuf_put(privkey, privlen)); |
1179 | |
|
1180 | 0 | *priv = privkey; |
1181 | 0 | *publ = pubkey; |
1182 | 0 | return dh; |
1183 | | |
1184 | 0 | err: |
1185 | 0 | BN_free(p); |
1186 | 0 | BN_free(q); |
1187 | 0 | BN_free(g); |
1188 | 0 | wpabuf_clear_free(pubkey); |
1189 | 0 | wpabuf_clear_free(privkey); |
1190 | 0 | DH_free(dh); |
1191 | 0 | return NULL; |
1192 | 0 | #endif |
1193 | 0 | } |
1194 | | |
1195 | | |
1196 | | void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) |
1197 | 0 | { |
1198 | | #if OPENSSL_VERSION_NUMBER < 0x10100000L |
1199 | | DH *dh; |
1200 | | |
1201 | | dh = DH_new(); |
1202 | | if (dh == NULL) |
1203 | | return NULL; |
1204 | | |
1205 | | dh->g = BN_new(); |
1206 | | if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) |
1207 | | goto err; |
1208 | | |
1209 | | dh->p = get_group5_prime(); |
1210 | | if (dh->p == NULL) |
1211 | | goto err; |
1212 | | |
1213 | | dh->priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); |
1214 | | if (dh->priv_key == NULL) |
1215 | | goto err; |
1216 | | |
1217 | | dh->pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); |
1218 | | if (dh->pub_key == NULL) |
1219 | | goto err; |
1220 | | |
1221 | | if (DH_generate_key(dh) != 1) |
1222 | | goto err; |
1223 | | |
1224 | | return dh; |
1225 | | |
1226 | | err: |
1227 | | DH_free(dh); |
1228 | | return NULL; |
1229 | | #elif OPENSSL_VERSION_NUMBER >= 0x30000000L |
1230 | | EVP_PKEY *pkey = NULL; |
1231 | | OSSL_PARAM_BLD *bld; |
1232 | | OSSL_PARAM *params = NULL; |
1233 | | BIGNUM *priv_key, *pub_key; |
1234 | | EVP_PKEY_CTX *fctx; |
1235 | | |
1236 | | fctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL); |
1237 | | priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); |
1238 | | pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); |
1239 | | bld = OSSL_PARAM_BLD_new(); |
1240 | | if (!fctx || !priv_key || !pub_key || !bld || |
1241 | | OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, |
1242 | | "modp_1536", 0) != 1 || |
1243 | | OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, |
1244 | | priv_key) != 1 || |
1245 | | OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, |
1246 | | pub_key) != 1 || |
1247 | | !(params = OSSL_PARAM_BLD_to_param(bld)) || |
1248 | | EVP_PKEY_fromdata_init(fctx) != 1 || |
1249 | | EVP_PKEY_fromdata(fctx, &pkey, EVP_PKEY_KEYPAIR, params) != 1) { |
1250 | | wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_fromdata failed: %s", |
1251 | | ERR_error_string(ERR_get_error(), NULL)); |
1252 | | EVP_PKEY_free(pkey); |
1253 | | pkey = NULL; |
1254 | | } |
1255 | | |
1256 | | BN_clear_free(priv_key); |
1257 | | BN_free(pub_key); |
1258 | | EVP_PKEY_CTX_free(fctx); |
1259 | | OSSL_PARAM_BLD_free(bld); |
1260 | | OSSL_PARAM_free(params); |
1261 | | return pkey; |
1262 | | #else |
1263 | 0 | DH *dh; |
1264 | 0 | BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL; |
1265 | |
|
1266 | 0 | dh = DH_new(); |
1267 | 0 | if (dh == NULL) |
1268 | 0 | return NULL; |
1269 | | |
1270 | 0 | g = BN_new(); |
1271 | 0 | p = get_group5_prime(); |
1272 | 0 | if (!g || BN_set_word(g, 2) != 1 || !p || |
1273 | 0 | DH_set0_pqg(dh, p, NULL, g) != 1) |
1274 | 0 | goto err; |
1275 | 0 | p = NULL; |
1276 | 0 | g = NULL; |
1277 | |
|
1278 | 0 | priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); |
1279 | 0 | pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); |
1280 | 0 | if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1) |
1281 | 0 | goto err; |
1282 | 0 | pub_key = NULL; |
1283 | 0 | priv_key = NULL; |
1284 | |
|
1285 | 0 | if (DH_generate_key(dh) != 1) |
1286 | 0 | goto err; |
1287 | | |
1288 | 0 | return dh; |
1289 | | |
1290 | 0 | err: |
1291 | 0 | BN_free(p); |
1292 | 0 | BN_free(g); |
1293 | 0 | BN_free(pub_key); |
1294 | 0 | BN_clear_free(priv_key); |
1295 | 0 | DH_free(dh); |
1296 | 0 | return NULL; |
1297 | 0 | #endif |
1298 | 0 | } |
1299 | | |
1300 | | |
1301 | | struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, |
1302 | | const struct wpabuf *own_private) |
1303 | 0 | { |
1304 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1305 | | EVP_PKEY *pkey = ctx; |
1306 | | EVP_PKEY *peer_pub; |
1307 | | size_t len; |
1308 | | struct wpabuf *res = NULL; |
1309 | | EVP_PKEY_CTX *dctx = NULL; |
1310 | | |
1311 | | peer_pub = EVP_PKEY_new(); |
1312 | | if (!pkey || !peer_pub || |
1313 | | EVP_PKEY_copy_parameters(peer_pub, pkey) != 1 || |
1314 | | EVP_PKEY_set1_encoded_public_key(peer_pub, wpabuf_head(peer_public), |
1315 | | wpabuf_len(peer_public)) != 1 || |
1316 | | !(dctx = EVP_PKEY_CTX_new(pkey, NULL)) || |
1317 | | EVP_PKEY_derive_init(dctx) != 1 || |
1318 | | EVP_PKEY_derive_set_peer(dctx, peer_pub) != 1 || |
1319 | | EVP_PKEY_derive(dctx, NULL, &len) != 1 || |
1320 | | !(res = wpabuf_alloc(len)) || |
1321 | | EVP_PKEY_derive(dctx, wpabuf_mhead(res), &len) != 1) { |
1322 | | wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_derive failed: %s", |
1323 | | ERR_error_string(ERR_get_error(), NULL)); |
1324 | | wpabuf_free(res); |
1325 | | res = NULL; |
1326 | | } else { |
1327 | | wpabuf_put(res, len); |
1328 | | } |
1329 | | |
1330 | | EVP_PKEY_free(peer_pub); |
1331 | | EVP_PKEY_CTX_free(dctx); |
1332 | | return res; |
1333 | | #else /* OpenSSL version >= 3.0 */ |
1334 | 0 | BIGNUM *pub_key; |
1335 | 0 | struct wpabuf *res = NULL; |
1336 | 0 | size_t rlen; |
1337 | 0 | DH *dh = ctx; |
1338 | 0 | int keylen; |
1339 | |
|
1340 | 0 | if (ctx == NULL) |
1341 | 0 | return NULL; |
1342 | | |
1343 | 0 | pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), |
1344 | 0 | NULL); |
1345 | 0 | if (pub_key == NULL) |
1346 | 0 | return NULL; |
1347 | | |
1348 | 0 | rlen = DH_size(dh); |
1349 | 0 | res = wpabuf_alloc(rlen); |
1350 | 0 | if (res == NULL) |
1351 | 0 | goto err; |
1352 | | |
1353 | 0 | keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); |
1354 | 0 | if (keylen < 0) |
1355 | 0 | goto err; |
1356 | 0 | wpabuf_put(res, keylen); |
1357 | 0 | BN_clear_free(pub_key); |
1358 | |
|
1359 | 0 | return res; |
1360 | | |
1361 | 0 | err: |
1362 | 0 | BN_clear_free(pub_key); |
1363 | 0 | wpabuf_clear_free(res); |
1364 | 0 | return NULL; |
1365 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1366 | 0 | } |
1367 | | |
1368 | | |
1369 | | void dh5_free(void *ctx) |
1370 | 0 | { |
1371 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1372 | | EVP_PKEY *pkey = ctx; |
1373 | | |
1374 | | EVP_PKEY_free(pkey); |
1375 | | #else /* OpenSSL version >= 3.0 */ |
1376 | 0 | DH *dh; |
1377 | 0 | if (ctx == NULL) |
1378 | 0 | return; |
1379 | 0 | dh = ctx; |
1380 | 0 | DH_free(dh); |
1381 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1382 | 0 | } |
1383 | | |
1384 | | |
1385 | | struct crypto_hash { |
1386 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1387 | | EVP_MAC_CTX *ctx; |
1388 | | #else /* OpenSSL version >= 3.0 */ |
1389 | | HMAC_CTX *ctx; |
1390 | | #endif /* OpenSSL version >= 3.0 */ |
1391 | | bool failed; |
1392 | | }; |
1393 | | |
1394 | | |
1395 | | struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, |
1396 | | size_t key_len) |
1397 | 0 | { |
1398 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1399 | | struct crypto_hash *ctx; |
1400 | | EVP_MAC *mac; |
1401 | | OSSL_PARAM params[2]; |
1402 | | char *a = NULL; |
1403 | | |
1404 | | switch (alg) { |
1405 | | #ifndef OPENSSL_NO_MD5 |
1406 | | case CRYPTO_HASH_ALG_HMAC_MD5: |
1407 | | a = "MD5"; |
1408 | | break; |
1409 | | #endif /* OPENSSL_NO_MD5 */ |
1410 | | #ifndef OPENSSL_NO_SHA |
1411 | | case CRYPTO_HASH_ALG_HMAC_SHA1: |
1412 | | a = "SHA1"; |
1413 | | break; |
1414 | | #endif /* OPENSSL_NO_SHA */ |
1415 | | #ifndef OPENSSL_NO_SHA256 |
1416 | | #ifdef CONFIG_SHA256 |
1417 | | case CRYPTO_HASH_ALG_HMAC_SHA256: |
1418 | | a = "SHA256"; |
1419 | | break; |
1420 | | #endif /* CONFIG_SHA256 */ |
1421 | | #endif /* OPENSSL_NO_SHA256 */ |
1422 | | default: |
1423 | | return NULL; |
1424 | | } |
1425 | | |
1426 | | mac = EVP_MAC_fetch(NULL, "HMAC", NULL); |
1427 | | if (!mac) |
1428 | | return NULL; |
1429 | | |
1430 | | params[0] = OSSL_PARAM_construct_utf8_string("digest", a, 0); |
1431 | | params[1] = OSSL_PARAM_construct_end(); |
1432 | | |
1433 | | ctx = os_zalloc(sizeof(*ctx)); |
1434 | | if (!ctx) |
1435 | | goto fail; |
1436 | | ctx->ctx = EVP_MAC_CTX_new(mac); |
1437 | | if (!ctx->ctx) { |
1438 | | os_free(ctx); |
1439 | | ctx = NULL; |
1440 | | goto fail; |
1441 | | } |
1442 | | |
1443 | | if (EVP_MAC_init(ctx->ctx, key, key_len, params) != 1) { |
1444 | | wpa_printf(MSG_INFO, |
1445 | | "OpenSSL: EVP_MAC_init(hmac,digest=%s) failed: %s", |
1446 | | a, ERR_error_string(ERR_get_error(), NULL)); |
1447 | | EVP_MAC_CTX_free(ctx->ctx); |
1448 | | bin_clear_free(ctx, sizeof(*ctx)); |
1449 | | ctx = NULL; |
1450 | | goto fail; |
1451 | | } |
1452 | | |
1453 | | fail: |
1454 | | EVP_MAC_free(mac); |
1455 | | return ctx; |
1456 | | #else /* OpenSSL version >= 3.0 */ |
1457 | 0 | struct crypto_hash *ctx; |
1458 | 0 | const EVP_MD *md; |
1459 | |
|
1460 | 0 | switch (alg) { |
1461 | 0 | #ifndef OPENSSL_NO_MD5 |
1462 | 0 | case CRYPTO_HASH_ALG_HMAC_MD5: |
1463 | 0 | md = EVP_md5(); |
1464 | 0 | break; |
1465 | 0 | #endif /* OPENSSL_NO_MD5 */ |
1466 | 0 | #ifndef OPENSSL_NO_SHA |
1467 | 0 | case CRYPTO_HASH_ALG_HMAC_SHA1: |
1468 | 0 | md = EVP_sha1(); |
1469 | 0 | break; |
1470 | 0 | #endif /* OPENSSL_NO_SHA */ |
1471 | 0 | #ifndef OPENSSL_NO_SHA256 |
1472 | 0 | #ifdef CONFIG_SHA256 |
1473 | 0 | case CRYPTO_HASH_ALG_HMAC_SHA256: |
1474 | 0 | md = EVP_sha256(); |
1475 | 0 | break; |
1476 | 0 | #endif /* CONFIG_SHA256 */ |
1477 | 0 | #endif /* OPENSSL_NO_SHA256 */ |
1478 | 0 | default: |
1479 | 0 | return NULL; |
1480 | 0 | } |
1481 | | |
1482 | 0 | ctx = os_zalloc(sizeof(*ctx)); |
1483 | 0 | if (ctx == NULL) |
1484 | 0 | return NULL; |
1485 | 0 | ctx->ctx = HMAC_CTX_new(); |
1486 | 0 | if (!ctx->ctx) { |
1487 | 0 | os_free(ctx); |
1488 | 0 | return NULL; |
1489 | 0 | } |
1490 | | |
1491 | 0 | if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) { |
1492 | 0 | HMAC_CTX_free(ctx->ctx); |
1493 | 0 | bin_clear_free(ctx, sizeof(*ctx)); |
1494 | 0 | return NULL; |
1495 | 0 | } |
1496 | | |
1497 | 0 | return ctx; |
1498 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1499 | 0 | } |
1500 | | |
1501 | | |
1502 | | void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) |
1503 | 0 | { |
1504 | 0 | if (ctx == NULL) |
1505 | 0 | return; |
1506 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1507 | | if (!EVP_MAC_update(ctx->ctx, data, len)) |
1508 | | ctx->failed = true; |
1509 | | #else /* OpenSSL version >= 3.0 */ |
1510 | 0 | if (!HMAC_Update(ctx->ctx, data, len)) |
1511 | 0 | ctx->failed = true; |
1512 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1513 | 0 | } |
1514 | | |
1515 | | |
1516 | | int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) |
1517 | 0 | { |
1518 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1519 | | size_t mdlen; |
1520 | | int res; |
1521 | | bool failed; |
1522 | | |
1523 | | if (!ctx) |
1524 | | return -2; |
1525 | | |
1526 | | if (!mac || !len) { |
1527 | | EVP_MAC_CTX_free(ctx->ctx); |
1528 | | bin_clear_free(ctx, sizeof(*ctx)); |
1529 | | return 0; |
1530 | | } |
1531 | | |
1532 | | res = EVP_MAC_final(ctx->ctx, NULL, &mdlen, 0); |
1533 | | if (res != 1) { |
1534 | | EVP_MAC_CTX_free(ctx->ctx); |
1535 | | bin_clear_free(ctx, sizeof(*ctx)); |
1536 | | return -1; |
1537 | | } |
1538 | | res = EVP_MAC_final(ctx->ctx, mac, &mdlen, mdlen); |
1539 | | EVP_MAC_CTX_free(ctx->ctx); |
1540 | | failed = ctx->failed; |
1541 | | bin_clear_free(ctx, sizeof(*ctx)); |
1542 | | |
1543 | | if (TEST_FAIL()) |
1544 | | return -1; |
1545 | | |
1546 | | if (failed) |
1547 | | return -2; |
1548 | | |
1549 | | if (res == 1) { |
1550 | | *len = mdlen; |
1551 | | return 0; |
1552 | | } |
1553 | | |
1554 | | return -1; |
1555 | | #else /* OpenSSL version >= 3.0 */ |
1556 | 0 | unsigned int mdlen; |
1557 | 0 | int res; |
1558 | 0 | bool failed; |
1559 | |
|
1560 | 0 | if (ctx == NULL) |
1561 | 0 | return -2; |
1562 | | |
1563 | 0 | if (mac == NULL || len == NULL) { |
1564 | 0 | HMAC_CTX_free(ctx->ctx); |
1565 | 0 | bin_clear_free(ctx, sizeof(*ctx)); |
1566 | 0 | return 0; |
1567 | 0 | } |
1568 | | |
1569 | 0 | mdlen = *len; |
1570 | 0 | res = HMAC_Final(ctx->ctx, mac, &mdlen); |
1571 | 0 | HMAC_CTX_free(ctx->ctx); |
1572 | 0 | failed = ctx->failed; |
1573 | 0 | bin_clear_free(ctx, sizeof(*ctx)); |
1574 | |
|
1575 | 0 | if (TEST_FAIL()) |
1576 | 0 | return -1; |
1577 | | |
1578 | 0 | if (failed) |
1579 | 0 | return -2; |
1580 | | |
1581 | 0 | if (res == 1) { |
1582 | 0 | *len = mdlen; |
1583 | 0 | return 0; |
1584 | 0 | } |
1585 | | |
1586 | 0 | return -1; |
1587 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1588 | 0 | } |
1589 | | |
1590 | | |
1591 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1592 | | |
1593 | | static int openssl_hmac_vector(char *digest, const u8 *key, |
1594 | | size_t key_len, size_t num_elem, |
1595 | | const u8 *addr[], const size_t *len, u8 *mac, |
1596 | | unsigned int mdlen) |
1597 | | { |
1598 | | EVP_MAC *hmac; |
1599 | | OSSL_PARAM params[2]; |
1600 | | EVP_MAC_CTX *ctx; |
1601 | | size_t i, mlen; |
1602 | | int res; |
1603 | | const char *property_query = NULL; |
1604 | | |
1605 | | if (TEST_FAIL()) |
1606 | | return -1; |
1607 | | |
1608 | | #ifndef CONFIG_FIPS |
1609 | | if (os_strcmp(digest, "MD5") == 0) { |
1610 | | openssl_need_md5(); |
1611 | | property_query = "provider!=fips"; |
1612 | | } else if (key_len < 14 && OSSL_PROVIDER_available(NULL, "fips")) { |
1613 | | /* Need to use non-FIPS provider in OpenSSL to handle cases |
1614 | | * where HMAC is used with salt that is less than 112 bits |
1615 | | * instead of the HMAC uses with an actual key. */ |
1616 | | openssl_disable_fips(); |
1617 | | openssl_load_default_provider_if_fips(); |
1618 | | property_query = "provider!=fips"; |
1619 | | } |
1620 | | #endif /* CONFIG_FIPS */ |
1621 | | hmac = EVP_MAC_fetch(NULL, "HMAC", property_query); |
1622 | | if (!hmac) { |
1623 | | wpa_printf(MSG_INFO, "OpenSSL: EVP_MAC_fetch(HMAC) failed: %s", |
1624 | | ERR_error_string(ERR_get_error(), NULL)); |
1625 | | return -1; |
1626 | | } |
1627 | | |
1628 | | params[0] = OSSL_PARAM_construct_utf8_string("digest", digest, 0); |
1629 | | params[1] = OSSL_PARAM_construct_end(); |
1630 | | |
1631 | | ctx = EVP_MAC_CTX_new(hmac); |
1632 | | EVP_MAC_free(hmac); |
1633 | | if (!ctx) |
1634 | | return -1; |
1635 | | |
1636 | | if (EVP_MAC_init(ctx, key, key_len, params) != 1) { |
1637 | | wpa_printf(MSG_INFO, |
1638 | | "OpenSSL: EVP_MAC_init(hmac,digest=%s,key_len=%zu) failed: %s", |
1639 | | digest, key_len, |
1640 | | ERR_error_string(ERR_get_error(), NULL)); |
1641 | | goto fail; |
1642 | | } |
1643 | | |
1644 | | for (i = 0; i < num_elem; i++) { |
1645 | | if (EVP_MAC_update(ctx, addr[i], len[i]) != 1) |
1646 | | goto fail; |
1647 | | } |
1648 | | |
1649 | | res = EVP_MAC_final(ctx, mac, &mlen, mdlen); |
1650 | | EVP_MAC_CTX_free(ctx); |
1651 | | |
1652 | | return res == 1 ? 0 : -1; |
1653 | | fail: |
1654 | | EVP_MAC_CTX_free(ctx); |
1655 | | return -1; |
1656 | | } |
1657 | | |
1658 | | |
1659 | | #ifndef CONFIG_FIPS |
1660 | | |
1661 | | int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, |
1662 | | const u8 *addr[], const size_t *len, u8 *mac) |
1663 | | { |
1664 | | return openssl_hmac_vector("MD5", key ,key_len, num_elem, addr, len, |
1665 | | mac, 16); |
1666 | | } |
1667 | | |
1668 | | |
1669 | | int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
1670 | | u8 *mac) |
1671 | | { |
1672 | | return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); |
1673 | | } |
1674 | | |
1675 | | #endif /* CONFIG_FIPS */ |
1676 | | |
1677 | | |
1678 | | int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, |
1679 | | const u8 *addr[], const size_t *len, u8 *mac) |
1680 | | { |
1681 | | return openssl_hmac_vector("SHA1", key, key_len, num_elem, addr, |
1682 | | len, mac, 20); |
1683 | | } |
1684 | | |
1685 | | |
1686 | | int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
1687 | | u8 *mac) |
1688 | | { |
1689 | | return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); |
1690 | | } |
1691 | | |
1692 | | |
1693 | | #ifdef CONFIG_SHA256 |
1694 | | |
1695 | | int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, |
1696 | | const u8 *addr[], const size_t *len, u8 *mac) |
1697 | | { |
1698 | | return openssl_hmac_vector("SHA256", key, key_len, num_elem, addr, |
1699 | | len, mac, 32); |
1700 | | } |
1701 | | |
1702 | | |
1703 | | int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, |
1704 | | size_t data_len, u8 *mac) |
1705 | | { |
1706 | | return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); |
1707 | | } |
1708 | | |
1709 | | #endif /* CONFIG_SHA256 */ |
1710 | | |
1711 | | |
1712 | | #ifdef CONFIG_SHA384 |
1713 | | |
1714 | | int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, |
1715 | | const u8 *addr[], const size_t *len, u8 *mac) |
1716 | | { |
1717 | | return openssl_hmac_vector("SHA384", key, key_len, num_elem, addr, |
1718 | | len, mac, 48); |
1719 | | } |
1720 | | |
1721 | | |
1722 | | int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, |
1723 | | size_t data_len, u8 *mac) |
1724 | | { |
1725 | | return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); |
1726 | | } |
1727 | | |
1728 | | #endif /* CONFIG_SHA384 */ |
1729 | | |
1730 | | |
1731 | | #ifdef CONFIG_SHA512 |
1732 | | |
1733 | | int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, |
1734 | | const u8 *addr[], const size_t *len, u8 *mac) |
1735 | | { |
1736 | | return openssl_hmac_vector("SHA512", key, key_len, num_elem, addr, |
1737 | | len, mac, 64); |
1738 | | } |
1739 | | |
1740 | | |
1741 | | int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, |
1742 | | size_t data_len, u8 *mac) |
1743 | | { |
1744 | | return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); |
1745 | | } |
1746 | | |
1747 | | #endif /* CONFIG_SHA512 */ |
1748 | | |
1749 | | #else /* OpenSSL version >= 3.0 */ |
1750 | | |
1751 | | static int openssl_hmac_vector(const EVP_MD *type, const u8 *key, |
1752 | | size_t key_len, size_t num_elem, |
1753 | | const u8 *addr[], const size_t *len, u8 *mac, |
1754 | | unsigned int mdlen) |
1755 | 0 | { |
1756 | 0 | HMAC_CTX *ctx; |
1757 | 0 | size_t i; |
1758 | 0 | int res; |
1759 | |
|
1760 | 0 | if (TEST_FAIL()) |
1761 | 0 | return -1; |
1762 | | |
1763 | 0 | ctx = HMAC_CTX_new(); |
1764 | 0 | if (!ctx) |
1765 | 0 | return -1; |
1766 | 0 | res = HMAC_Init_ex(ctx, key, key_len, type, NULL); |
1767 | 0 | if (res != 1) |
1768 | 0 | goto done; |
1769 | | |
1770 | 0 | for (i = 0; i < num_elem; i++) |
1771 | 0 | HMAC_Update(ctx, addr[i], len[i]); |
1772 | |
|
1773 | 0 | res = HMAC_Final(ctx, mac, &mdlen); |
1774 | 0 | done: |
1775 | 0 | HMAC_CTX_free(ctx); |
1776 | |
|
1777 | 0 | return res == 1 ? 0 : -1; |
1778 | 0 | } |
1779 | | |
1780 | | |
1781 | | #ifndef CONFIG_FIPS |
1782 | | |
1783 | | int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, |
1784 | | const u8 *addr[], const size_t *len, u8 *mac) |
1785 | 0 | { |
1786 | 0 | return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len, |
1787 | 0 | mac, 16); |
1788 | 0 | } |
1789 | | |
1790 | | |
1791 | | int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
1792 | | u8 *mac) |
1793 | 0 | { |
1794 | 0 | return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); |
1795 | 0 | } |
1796 | | |
1797 | | #endif /* CONFIG_FIPS */ |
1798 | | |
1799 | | |
1800 | | int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, |
1801 | | const u8 *addr[], const size_t *len, u8 *mac) |
1802 | 0 | { |
1803 | 0 | return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr, |
1804 | 0 | len, mac, 20); |
1805 | 0 | } |
1806 | | |
1807 | | |
1808 | | int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
1809 | | u8 *mac) |
1810 | 0 | { |
1811 | 0 | return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); |
1812 | 0 | } |
1813 | | |
1814 | | |
1815 | | #ifdef CONFIG_SHA256 |
1816 | | |
1817 | | int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, |
1818 | | const u8 *addr[], const size_t *len, u8 *mac) |
1819 | 0 | { |
1820 | 0 | return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr, |
1821 | 0 | len, mac, 32); |
1822 | 0 | } |
1823 | | |
1824 | | |
1825 | | int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, |
1826 | | size_t data_len, u8 *mac) |
1827 | 0 | { |
1828 | 0 | return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); |
1829 | 0 | } |
1830 | | |
1831 | | #endif /* CONFIG_SHA256 */ |
1832 | | |
1833 | | |
1834 | | #ifdef CONFIG_SHA384 |
1835 | | |
1836 | | int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, |
1837 | | const u8 *addr[], const size_t *len, u8 *mac) |
1838 | 0 | { |
1839 | 0 | return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr, |
1840 | 0 | len, mac, 48); |
1841 | 0 | } |
1842 | | |
1843 | | |
1844 | | int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, |
1845 | | size_t data_len, u8 *mac) |
1846 | 0 | { |
1847 | 0 | return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); |
1848 | 0 | } |
1849 | | |
1850 | | #endif /* CONFIG_SHA384 */ |
1851 | | |
1852 | | |
1853 | | #ifdef CONFIG_SHA512 |
1854 | | |
1855 | | int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, |
1856 | | const u8 *addr[], const size_t *len, u8 *mac) |
1857 | 0 | { |
1858 | 0 | return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr, |
1859 | 0 | len, mac, 64); |
1860 | 0 | } |
1861 | | |
1862 | | |
1863 | | int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, |
1864 | | size_t data_len, u8 *mac) |
1865 | 0 | { |
1866 | 0 | return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); |
1867 | 0 | } |
1868 | | |
1869 | | #endif /* CONFIG_SHA512 */ |
1870 | | |
1871 | | #endif /* OpenSSL version >= 3.0 */ |
1872 | | |
1873 | | |
1874 | | int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, |
1875 | | int iterations, u8 *buf, size_t buflen) |
1876 | 0 | { |
1877 | 0 | if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid, |
1878 | 0 | ssid_len, iterations, buflen, buf) != 1) |
1879 | 0 | return -1; |
1880 | 0 | return 0; |
1881 | 0 | } |
1882 | | |
1883 | | |
1884 | | int crypto_get_random(void *buf, size_t len) |
1885 | 0 | { |
1886 | 0 | if (RAND_bytes(buf, len) != 1) |
1887 | 0 | return -1; |
1888 | 0 | return 0; |
1889 | 0 | } |
1890 | | |
1891 | | |
1892 | | int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, |
1893 | | const u8 *addr[], const size_t *len, u8 *mac) |
1894 | 0 | { |
1895 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
1896 | | EVP_MAC_CTX *ctx = NULL; |
1897 | | EVP_MAC *emac; |
1898 | | int ret = -1; |
1899 | | size_t outlen, i; |
1900 | | OSSL_PARAM params[2]; |
1901 | | char *cipher = NULL; |
1902 | | |
1903 | | if (TEST_FAIL()) |
1904 | | return -1; |
1905 | | |
1906 | | emac = EVP_MAC_fetch(NULL, "CMAC", NULL); |
1907 | | |
1908 | | if (key_len == 32) |
1909 | | cipher = "aes-256-cbc"; |
1910 | | else if (key_len == 24) |
1911 | | cipher = "aes-192-cbc"; |
1912 | | else if (key_len == 16) |
1913 | | cipher = "aes-128-cbc"; |
1914 | | |
1915 | | params[0] = OSSL_PARAM_construct_utf8_string("cipher", cipher, 0); |
1916 | | params[1] = OSSL_PARAM_construct_end(); |
1917 | | |
1918 | | if (!emac || !cipher || |
1919 | | !(ctx = EVP_MAC_CTX_new(emac)) || |
1920 | | EVP_MAC_init(ctx, key, key_len, params) != 1) { |
1921 | | wpa_printf(MSG_INFO, |
1922 | | "OpenSSL: EVP_MAC_init(cmac,cipher=%s) failed: %s", |
1923 | | cipher, ERR_error_string(ERR_get_error(), NULL)); |
1924 | | goto fail; |
1925 | | } |
1926 | | |
1927 | | for (i = 0; i < num_elem; i++) { |
1928 | | if (!EVP_MAC_update(ctx, addr[i], len[i])) |
1929 | | goto fail; |
1930 | | } |
1931 | | if (EVP_MAC_final(ctx, mac, &outlen, 16) != 1 || outlen != 16) |
1932 | | goto fail; |
1933 | | |
1934 | | ret = 0; |
1935 | | fail: |
1936 | | EVP_MAC_CTX_free(ctx); |
1937 | | EVP_MAC_free(emac); |
1938 | | return ret; |
1939 | | #else /* OpenSSL version >= 3.0 */ |
1940 | 0 | CMAC_CTX *ctx; |
1941 | 0 | int ret = -1; |
1942 | 0 | size_t outlen, i; |
1943 | |
|
1944 | 0 | if (TEST_FAIL()) |
1945 | 0 | return -1; |
1946 | | |
1947 | 0 | ctx = CMAC_CTX_new(); |
1948 | 0 | if (ctx == NULL) |
1949 | 0 | return -1; |
1950 | | |
1951 | 0 | if (key_len == 32) { |
1952 | 0 | if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL)) |
1953 | 0 | goto fail; |
1954 | 0 | } else if (key_len == 24) { |
1955 | 0 | if (!CMAC_Init(ctx, key, 24, EVP_aes_192_cbc(), NULL)) |
1956 | 0 | goto fail; |
1957 | 0 | } else if (key_len == 16) { |
1958 | 0 | if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL)) |
1959 | 0 | goto fail; |
1960 | 0 | } else { |
1961 | 0 | goto fail; |
1962 | 0 | } |
1963 | 0 | for (i = 0; i < num_elem; i++) { |
1964 | 0 | if (!CMAC_Update(ctx, addr[i], len[i])) |
1965 | 0 | goto fail; |
1966 | 0 | } |
1967 | 0 | if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16) |
1968 | 0 | goto fail; |
1969 | | |
1970 | 0 | ret = 0; |
1971 | 0 | fail: |
1972 | 0 | CMAC_CTX_free(ctx); |
1973 | 0 | return ret; |
1974 | 0 | #endif /* OpenSSL version >= 3.0 */ |
1975 | 0 | } |
1976 | | |
1977 | | |
1978 | | int omac1_aes_128_vector(const u8 *key, size_t num_elem, |
1979 | | const u8 *addr[], const size_t *len, u8 *mac) |
1980 | 0 | { |
1981 | 0 | return omac1_aes_vector(key, 16, num_elem, addr, len, mac); |
1982 | 0 | } |
1983 | | |
1984 | | |
1985 | | int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
1986 | 0 | { |
1987 | 0 | return omac1_aes_128_vector(key, 1, &data, &data_len, mac); |
1988 | 0 | } |
1989 | | |
1990 | | |
1991 | | int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
1992 | 0 | { |
1993 | 0 | return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); |
1994 | 0 | } |
1995 | | |
1996 | | |
1997 | | struct crypto_bignum * crypto_bignum_init(void) |
1998 | 0 | { |
1999 | 0 | if (TEST_FAIL()) |
2000 | 0 | return NULL; |
2001 | 0 | return (struct crypto_bignum *) BN_new(); |
2002 | 0 | } |
2003 | | |
2004 | | |
2005 | | struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) |
2006 | 0 | { |
2007 | 0 | BIGNUM *bn; |
2008 | |
|
2009 | 0 | if (TEST_FAIL()) |
2010 | 0 | return NULL; |
2011 | | |
2012 | 0 | bn = BN_bin2bn(buf, len, NULL); |
2013 | 0 | return (struct crypto_bignum *) bn; |
2014 | 0 | } |
2015 | | |
2016 | | |
2017 | | struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) |
2018 | 0 | { |
2019 | 0 | BIGNUM *bn; |
2020 | |
|
2021 | 0 | if (TEST_FAIL()) |
2022 | 0 | return NULL; |
2023 | | |
2024 | 0 | bn = BN_new(); |
2025 | 0 | if (!bn) |
2026 | 0 | return NULL; |
2027 | 0 | if (BN_set_word(bn, val) != 1) { |
2028 | 0 | BN_free(bn); |
2029 | 0 | return NULL; |
2030 | 0 | } |
2031 | 0 | return (struct crypto_bignum *) bn; |
2032 | 0 | } |
2033 | | |
2034 | | |
2035 | | void crypto_bignum_deinit(struct crypto_bignum *n, int clear) |
2036 | 0 | { |
2037 | 0 | if (clear) |
2038 | 0 | BN_clear_free((BIGNUM *) n); |
2039 | 0 | else |
2040 | 0 | BN_free((BIGNUM *) n); |
2041 | 0 | } |
2042 | | |
2043 | | |
2044 | | int crypto_bignum_to_bin(const struct crypto_bignum *a, |
2045 | | u8 *buf, size_t buflen, size_t padlen) |
2046 | 0 | { |
2047 | 0 | int num_bytes, offset; |
2048 | |
|
2049 | 0 | if (TEST_FAIL()) |
2050 | 0 | return -1; |
2051 | | |
2052 | 0 | if (padlen > buflen) |
2053 | 0 | return -1; |
2054 | | |
2055 | 0 | if (padlen) { |
2056 | | #ifdef OPENSSL_IS_BORINGSSL |
2057 | | if (BN_bn2bin_padded(buf, padlen, (const BIGNUM *) a) == 0) |
2058 | | return -1; |
2059 | | return padlen; |
2060 | | #else /* OPENSSL_IS_BORINGSSL */ |
2061 | 0 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) |
2062 | 0 | return BN_bn2binpad((const BIGNUM *) a, buf, padlen); |
2063 | 0 | #endif |
2064 | 0 | #endif |
2065 | 0 | } |
2066 | | |
2067 | 0 | num_bytes = BN_num_bytes((const BIGNUM *) a); |
2068 | 0 | if ((size_t) num_bytes > buflen) |
2069 | 0 | return -1; |
2070 | 0 | if (padlen > (size_t) num_bytes) |
2071 | 0 | offset = padlen - num_bytes; |
2072 | 0 | else |
2073 | 0 | offset = 0; |
2074 | |
|
2075 | 0 | os_memset(buf, 0, offset); |
2076 | 0 | BN_bn2bin((const BIGNUM *) a, buf + offset); |
2077 | |
|
2078 | 0 | return num_bytes + offset; |
2079 | 0 | } |
2080 | | |
2081 | | |
2082 | | int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) |
2083 | 0 | { |
2084 | 0 | if (TEST_FAIL()) |
2085 | 0 | return -1; |
2086 | 0 | return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1; |
2087 | 0 | } |
2088 | | |
2089 | | |
2090 | | int crypto_bignum_add(const struct crypto_bignum *a, |
2091 | | const struct crypto_bignum *b, |
2092 | | struct crypto_bignum *c) |
2093 | 0 | { |
2094 | 0 | return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ? |
2095 | 0 | 0 : -1; |
2096 | 0 | } |
2097 | | |
2098 | | |
2099 | | int crypto_bignum_mod(const struct crypto_bignum *a, |
2100 | | const struct crypto_bignum *b, |
2101 | | struct crypto_bignum *c) |
2102 | 0 | { |
2103 | 0 | int res; |
2104 | 0 | BN_CTX *bnctx; |
2105 | |
|
2106 | 0 | bnctx = BN_CTX_new(); |
2107 | 0 | if (bnctx == NULL) |
2108 | 0 | return -1; |
2109 | 0 | res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, |
2110 | 0 | bnctx); |
2111 | 0 | BN_CTX_free(bnctx); |
2112 | |
|
2113 | 0 | return res ? 0 : -1; |
2114 | 0 | } |
2115 | | |
2116 | | |
2117 | | int crypto_bignum_exptmod(const struct crypto_bignum *a, |
2118 | | const struct crypto_bignum *b, |
2119 | | const struct crypto_bignum *c, |
2120 | | struct crypto_bignum *d) |
2121 | 0 | { |
2122 | 0 | int res; |
2123 | 0 | BN_CTX *bnctx; |
2124 | |
|
2125 | 0 | if (TEST_FAIL()) |
2126 | 0 | return -1; |
2127 | | |
2128 | 0 | bnctx = BN_CTX_new(); |
2129 | 0 | if (bnctx == NULL) |
2130 | 0 | return -1; |
2131 | 0 | res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a, |
2132 | 0 | (const BIGNUM *) b, (const BIGNUM *) c, |
2133 | 0 | bnctx, NULL); |
2134 | 0 | BN_CTX_free(bnctx); |
2135 | |
|
2136 | 0 | return res ? 0 : -1; |
2137 | 0 | } |
2138 | | |
2139 | | |
2140 | | int crypto_bignum_inverse(const struct crypto_bignum *a, |
2141 | | const struct crypto_bignum *b, |
2142 | | struct crypto_bignum *c) |
2143 | 0 | { |
2144 | 0 | BIGNUM *res; |
2145 | 0 | BN_CTX *bnctx; |
2146 | |
|
2147 | 0 | if (TEST_FAIL()) |
2148 | 0 | return -1; |
2149 | 0 | bnctx = BN_CTX_new(); |
2150 | 0 | if (bnctx == NULL) |
2151 | 0 | return -1; |
2152 | | #ifdef OPENSSL_IS_BORINGSSL |
2153 | | /* TODO: use BN_mod_inverse_blinded() ? */ |
2154 | | #else /* OPENSSL_IS_BORINGSSL */ |
2155 | 0 | BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); |
2156 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
2157 | 0 | res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a, |
2158 | 0 | (const BIGNUM *) b, bnctx); |
2159 | 0 | BN_CTX_free(bnctx); |
2160 | |
|
2161 | 0 | return res ? 0 : -1; |
2162 | 0 | } |
2163 | | |
2164 | | |
2165 | | int crypto_bignum_sub(const struct crypto_bignum *a, |
2166 | | const struct crypto_bignum *b, |
2167 | | struct crypto_bignum *c) |
2168 | 0 | { |
2169 | 0 | if (TEST_FAIL()) |
2170 | 0 | return -1; |
2171 | 0 | return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ? |
2172 | 0 | 0 : -1; |
2173 | 0 | } |
2174 | | |
2175 | | |
2176 | | int crypto_bignum_div(const struct crypto_bignum *a, |
2177 | | const struct crypto_bignum *b, |
2178 | | struct crypto_bignum *c) |
2179 | 0 | { |
2180 | 0 | int res; |
2181 | |
|
2182 | 0 | BN_CTX *bnctx; |
2183 | |
|
2184 | 0 | if (TEST_FAIL()) |
2185 | 0 | return -1; |
2186 | | |
2187 | 0 | bnctx = BN_CTX_new(); |
2188 | 0 | if (bnctx == NULL) |
2189 | 0 | return -1; |
2190 | 0 | #ifndef OPENSSL_IS_BORINGSSL |
2191 | 0 | BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); |
2192 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
2193 | 0 | res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a, |
2194 | 0 | (const BIGNUM *) b, bnctx); |
2195 | 0 | BN_CTX_free(bnctx); |
2196 | |
|
2197 | 0 | return res ? 0 : -1; |
2198 | 0 | } |
2199 | | |
2200 | | |
2201 | | int crypto_bignum_addmod(const struct crypto_bignum *a, |
2202 | | const struct crypto_bignum *b, |
2203 | | const struct crypto_bignum *c, |
2204 | | struct crypto_bignum *d) |
2205 | 0 | { |
2206 | 0 | int res; |
2207 | 0 | BN_CTX *bnctx; |
2208 | |
|
2209 | 0 | if (TEST_FAIL()) |
2210 | 0 | return -1; |
2211 | | |
2212 | 0 | bnctx = BN_CTX_new(); |
2213 | 0 | if (!bnctx) |
2214 | 0 | return -1; |
2215 | 0 | res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, |
2216 | 0 | (const BIGNUM *) c, bnctx); |
2217 | 0 | BN_CTX_free(bnctx); |
2218 | |
|
2219 | 0 | return res ? 0 : -1; |
2220 | 0 | } |
2221 | | |
2222 | | |
2223 | | int crypto_bignum_mulmod(const struct crypto_bignum *a, |
2224 | | const struct crypto_bignum *b, |
2225 | | const struct crypto_bignum *c, |
2226 | | struct crypto_bignum *d) |
2227 | 0 | { |
2228 | 0 | int res; |
2229 | |
|
2230 | 0 | BN_CTX *bnctx; |
2231 | |
|
2232 | 0 | if (TEST_FAIL()) |
2233 | 0 | return -1; |
2234 | | |
2235 | 0 | bnctx = BN_CTX_new(); |
2236 | 0 | if (bnctx == NULL) |
2237 | 0 | return -1; |
2238 | 0 | res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, |
2239 | 0 | (const BIGNUM *) c, bnctx); |
2240 | 0 | BN_CTX_free(bnctx); |
2241 | |
|
2242 | 0 | return res ? 0 : -1; |
2243 | 0 | } |
2244 | | |
2245 | | |
2246 | | int crypto_bignum_sqrmod(const struct crypto_bignum *a, |
2247 | | const struct crypto_bignum *b, |
2248 | | struct crypto_bignum *c) |
2249 | 0 | { |
2250 | 0 | int res; |
2251 | 0 | BN_CTX *bnctx; |
2252 | |
|
2253 | 0 | if (TEST_FAIL()) |
2254 | 0 | return -1; |
2255 | | |
2256 | 0 | bnctx = BN_CTX_new(); |
2257 | 0 | if (!bnctx) |
2258 | 0 | return -1; |
2259 | 0 | res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, |
2260 | 0 | bnctx); |
2261 | 0 | BN_CTX_free(bnctx); |
2262 | |
|
2263 | 0 | return res ? 0 : -1; |
2264 | 0 | } |
2265 | | |
2266 | | |
2267 | | int crypto_bignum_rshift(const struct crypto_bignum *a, int n, |
2268 | | struct crypto_bignum *r) |
2269 | 0 | { |
2270 | 0 | return BN_rshift((BIGNUM *) r, (const BIGNUM *) a, n) == 1 ? 0 : -1; |
2271 | 0 | } |
2272 | | |
2273 | | |
2274 | | int crypto_bignum_cmp(const struct crypto_bignum *a, |
2275 | | const struct crypto_bignum *b) |
2276 | 0 | { |
2277 | 0 | return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b); |
2278 | 0 | } |
2279 | | |
2280 | | |
2281 | | int crypto_bignum_is_zero(const struct crypto_bignum *a) |
2282 | 0 | { |
2283 | 0 | return BN_is_zero((const BIGNUM *) a); |
2284 | 0 | } |
2285 | | |
2286 | | |
2287 | | int crypto_bignum_is_one(const struct crypto_bignum *a) |
2288 | 0 | { |
2289 | 0 | return BN_is_one((const BIGNUM *) a); |
2290 | 0 | } |
2291 | | |
2292 | | |
2293 | | int crypto_bignum_is_odd(const struct crypto_bignum *a) |
2294 | 0 | { |
2295 | 0 | return BN_is_odd((const BIGNUM *) a); |
2296 | 0 | } |
2297 | | |
2298 | | |
2299 | | int crypto_bignum_legendre(const struct crypto_bignum *a, |
2300 | | const struct crypto_bignum *p) |
2301 | 0 | { |
2302 | 0 | BN_CTX *bnctx; |
2303 | 0 | BIGNUM *exp = NULL, *tmp = NULL; |
2304 | 0 | int res = -2; |
2305 | 0 | unsigned int mask; |
2306 | |
|
2307 | 0 | if (TEST_FAIL()) |
2308 | 0 | return -2; |
2309 | | |
2310 | 0 | bnctx = BN_CTX_new(); |
2311 | 0 | if (bnctx == NULL) |
2312 | 0 | return -2; |
2313 | | |
2314 | 0 | exp = BN_new(); |
2315 | 0 | tmp = BN_new(); |
2316 | 0 | if (!exp || !tmp || |
2317 | | /* exp = (p-1) / 2 */ |
2318 | 0 | !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) || |
2319 | 0 | !BN_rshift1(exp, exp) || |
2320 | 0 | !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp, |
2321 | 0 | (const BIGNUM *) p, bnctx, NULL)) |
2322 | 0 | goto fail; |
2323 | | |
2324 | | /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use |
2325 | | * constant time selection to avoid branches here. */ |
2326 | 0 | res = -1; |
2327 | 0 | mask = const_time_eq(BN_is_word(tmp, 1), 1); |
2328 | 0 | res = const_time_select_int(mask, 1, res); |
2329 | 0 | mask = const_time_eq(BN_is_zero(tmp), 1); |
2330 | 0 | res = const_time_select_int(mask, 0, res); |
2331 | |
|
2332 | 0 | fail: |
2333 | 0 | BN_clear_free(tmp); |
2334 | 0 | BN_clear_free(exp); |
2335 | 0 | BN_CTX_free(bnctx); |
2336 | 0 | return res; |
2337 | 0 | } |
2338 | | |
2339 | | |
2340 | | #ifdef CONFIG_ECC |
2341 | | |
2342 | | struct crypto_ec { |
2343 | | EC_GROUP *group; |
2344 | | int nid; |
2345 | | int iana_group; |
2346 | | BN_CTX *bnctx; |
2347 | | BIGNUM *prime; |
2348 | | BIGNUM *order; |
2349 | | BIGNUM *a; |
2350 | | BIGNUM *b; |
2351 | | }; |
2352 | | |
2353 | | |
2354 | | static int crypto_ec_group_2_nid(int group) |
2355 | 0 | { |
2356 | | /* Map from IANA registry for IKE D-H groups to OpenSSL NID */ |
2357 | 0 | switch (group) { |
2358 | 0 | case 19: |
2359 | 0 | return NID_X9_62_prime256v1; |
2360 | 0 | case 20: |
2361 | 0 | return NID_secp384r1; |
2362 | 0 | case 21: |
2363 | 0 | return NID_secp521r1; |
2364 | 0 | case 25: |
2365 | 0 | return NID_X9_62_prime192v1; |
2366 | 0 | case 26: |
2367 | 0 | return NID_secp224r1; |
2368 | 0 | #ifdef NID_brainpoolP224r1 |
2369 | 0 | case 27: |
2370 | 0 | return NID_brainpoolP224r1; |
2371 | 0 | #endif /* NID_brainpoolP224r1 */ |
2372 | 0 | #ifdef NID_brainpoolP256r1 |
2373 | 0 | case 28: |
2374 | 0 | return NID_brainpoolP256r1; |
2375 | 0 | #endif /* NID_brainpoolP256r1 */ |
2376 | 0 | #ifdef NID_brainpoolP384r1 |
2377 | 0 | case 29: |
2378 | 0 | return NID_brainpoolP384r1; |
2379 | 0 | #endif /* NID_brainpoolP384r1 */ |
2380 | 0 | #ifdef NID_brainpoolP512r1 |
2381 | 0 | case 30: |
2382 | 0 | return NID_brainpoolP512r1; |
2383 | 0 | #endif /* NID_brainpoolP512r1 */ |
2384 | 0 | default: |
2385 | 0 | return -1; |
2386 | 0 | } |
2387 | 0 | } |
2388 | | |
2389 | | |
2390 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
2391 | | static const char * crypto_ec_group_2_name(int group) |
2392 | | { |
2393 | | /* Map from IANA registry for IKE D-H groups to OpenSSL group name */ |
2394 | | switch (group) { |
2395 | | case 19: |
2396 | | return "prime256v1"; |
2397 | | case 20: |
2398 | | return "secp384r1"; |
2399 | | case 21: |
2400 | | return "secp521r1"; |
2401 | | case 25: |
2402 | | return "prime192v1"; |
2403 | | case 26: |
2404 | | return "secp224r1"; |
2405 | | #ifdef NID_brainpoolP224r1 |
2406 | | case 27: |
2407 | | return "brainpoolP224r1"; |
2408 | | #endif /* NID_brainpoolP224r1 */ |
2409 | | #ifdef NID_brainpoolP256r1 |
2410 | | case 28: |
2411 | | return "brainpoolP256r1"; |
2412 | | #endif /* NID_brainpoolP256r1 */ |
2413 | | #ifdef NID_brainpoolP384r1 |
2414 | | case 29: |
2415 | | return "brainpoolP384r1"; |
2416 | | #endif /* NID_brainpoolP384r1 */ |
2417 | | #ifdef NID_brainpoolP512r1 |
2418 | | case 30: |
2419 | | return "brainpoolP512r1"; |
2420 | | #endif /* NID_brainpoolP512r1 */ |
2421 | | default: |
2422 | | return NULL; |
2423 | | } |
2424 | | } |
2425 | | #endif /* OpenSSL version >= 3.0 */ |
2426 | | |
2427 | | |
2428 | | struct crypto_ec * crypto_ec_init(int group) |
2429 | 0 | { |
2430 | 0 | struct crypto_ec *e; |
2431 | 0 | int nid; |
2432 | |
|
2433 | 0 | nid = crypto_ec_group_2_nid(group); |
2434 | 0 | if (nid < 0) |
2435 | 0 | return NULL; |
2436 | | |
2437 | 0 | e = os_zalloc(sizeof(*e)); |
2438 | 0 | if (e == NULL) |
2439 | 0 | return NULL; |
2440 | | |
2441 | 0 | e->nid = nid; |
2442 | 0 | e->iana_group = group; |
2443 | 0 | e->bnctx = BN_CTX_new(); |
2444 | 0 | e->group = EC_GROUP_new_by_curve_name(nid); |
2445 | 0 | e->prime = BN_new(); |
2446 | 0 | e->order = BN_new(); |
2447 | 0 | e->a = BN_new(); |
2448 | 0 | e->b = BN_new(); |
2449 | 0 | if (e->group == NULL || e->bnctx == NULL || e->prime == NULL || |
2450 | 0 | e->order == NULL || e->a == NULL || e->b == NULL || |
2451 | 0 | !EC_GROUP_get_curve(e->group, e->prime, e->a, e->b, e->bnctx) || |
2452 | 0 | !EC_GROUP_get_order(e->group, e->order, e->bnctx)) { |
2453 | 0 | crypto_ec_deinit(e); |
2454 | 0 | e = NULL; |
2455 | 0 | } |
2456 | |
|
2457 | 0 | return e; |
2458 | 0 | } |
2459 | | |
2460 | | |
2461 | | void crypto_ec_deinit(struct crypto_ec *e) |
2462 | 0 | { |
2463 | 0 | if (e == NULL) |
2464 | 0 | return; |
2465 | 0 | BN_clear_free(e->b); |
2466 | 0 | BN_clear_free(e->a); |
2467 | 0 | BN_clear_free(e->order); |
2468 | 0 | BN_clear_free(e->prime); |
2469 | 0 | EC_GROUP_free(e->group); |
2470 | 0 | BN_CTX_free(e->bnctx); |
2471 | 0 | os_free(e); |
2472 | 0 | } |
2473 | | |
2474 | | |
2475 | | struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e) |
2476 | 0 | { |
2477 | 0 | if (TEST_FAIL()) |
2478 | 0 | return NULL; |
2479 | 0 | if (e == NULL) |
2480 | 0 | return NULL; |
2481 | 0 | return (struct crypto_ec_point *) EC_POINT_new(e->group); |
2482 | 0 | } |
2483 | | |
2484 | | |
2485 | | size_t crypto_ec_prime_len(struct crypto_ec *e) |
2486 | 0 | { |
2487 | 0 | return BN_num_bytes(e->prime); |
2488 | 0 | } |
2489 | | |
2490 | | |
2491 | | size_t crypto_ec_prime_len_bits(struct crypto_ec *e) |
2492 | 0 | { |
2493 | 0 | return BN_num_bits(e->prime); |
2494 | 0 | } |
2495 | | |
2496 | | |
2497 | | size_t crypto_ec_order_len(struct crypto_ec *e) |
2498 | 0 | { |
2499 | 0 | return BN_num_bytes(e->order); |
2500 | 0 | } |
2501 | | |
2502 | | |
2503 | | const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e) |
2504 | 0 | { |
2505 | 0 | return (const struct crypto_bignum *) e->prime; |
2506 | 0 | } |
2507 | | |
2508 | | |
2509 | | const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) |
2510 | 0 | { |
2511 | 0 | return (const struct crypto_bignum *) e->order; |
2512 | 0 | } |
2513 | | |
2514 | | |
2515 | | const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) |
2516 | 0 | { |
2517 | 0 | return (const struct crypto_bignum *) e->a; |
2518 | 0 | } |
2519 | | |
2520 | | |
2521 | | const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) |
2522 | 0 | { |
2523 | 0 | return (const struct crypto_bignum *) e->b; |
2524 | 0 | } |
2525 | | |
2526 | | |
2527 | | const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e) |
2528 | 0 | { |
2529 | 0 | return (const struct crypto_ec_point *) |
2530 | 0 | EC_GROUP_get0_generator(e->group); |
2531 | 0 | } |
2532 | | |
2533 | | |
2534 | | void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) |
2535 | 0 | { |
2536 | 0 | if (clear) |
2537 | 0 | EC_POINT_clear_free((EC_POINT *) p); |
2538 | 0 | else |
2539 | 0 | EC_POINT_free((EC_POINT *) p); |
2540 | 0 | } |
2541 | | |
2542 | | |
2543 | | int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, |
2544 | | struct crypto_bignum *x) |
2545 | 0 | { |
2546 | 0 | return EC_POINT_get_affine_coordinates(e->group, |
2547 | 0 | (const EC_POINT *) p, |
2548 | 0 | (BIGNUM *) x, NULL, |
2549 | 0 | e->bnctx) == 1 ? 0 : -1; |
2550 | 0 | } |
2551 | | |
2552 | | |
2553 | | int crypto_ec_point_to_bin(struct crypto_ec *e, |
2554 | | const struct crypto_ec_point *point, u8 *x, u8 *y) |
2555 | 0 | { |
2556 | 0 | BIGNUM *x_bn, *y_bn; |
2557 | 0 | int ret = -1; |
2558 | 0 | int len = BN_num_bytes(e->prime); |
2559 | |
|
2560 | 0 | if (TEST_FAIL()) |
2561 | 0 | return -1; |
2562 | | |
2563 | 0 | x_bn = BN_new(); |
2564 | 0 | y_bn = BN_new(); |
2565 | |
|
2566 | 0 | if (x_bn && y_bn && |
2567 | 0 | EC_POINT_get_affine_coordinates(e->group, (EC_POINT *) point, |
2568 | 0 | x_bn, y_bn, e->bnctx)) { |
2569 | 0 | if (x) { |
2570 | 0 | ret = crypto_bignum_to_bin( |
2571 | 0 | (struct crypto_bignum *) x_bn, x, len, len); |
2572 | 0 | } |
2573 | 0 | if (ret >= 0 && y) { |
2574 | 0 | ret = crypto_bignum_to_bin( |
2575 | 0 | (struct crypto_bignum *) y_bn, y, len, len); |
2576 | 0 | } |
2577 | |
|
2578 | 0 | if (ret > 0) |
2579 | 0 | ret = 0; |
2580 | 0 | } |
2581 | |
|
2582 | 0 | BN_clear_free(x_bn); |
2583 | 0 | BN_clear_free(y_bn); |
2584 | 0 | return ret; |
2585 | 0 | } |
2586 | | |
2587 | | |
2588 | | struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, |
2589 | | const u8 *val) |
2590 | 0 | { |
2591 | 0 | BIGNUM *x, *y; |
2592 | 0 | EC_POINT *elem; |
2593 | 0 | int len = BN_num_bytes(e->prime); |
2594 | |
|
2595 | 0 | if (TEST_FAIL()) |
2596 | 0 | return NULL; |
2597 | | |
2598 | 0 | x = BN_bin2bn(val, len, NULL); |
2599 | 0 | y = BN_bin2bn(val + len, len, NULL); |
2600 | 0 | elem = EC_POINT_new(e->group); |
2601 | 0 | if (x == NULL || y == NULL || elem == NULL) { |
2602 | 0 | BN_clear_free(x); |
2603 | 0 | BN_clear_free(y); |
2604 | 0 | EC_POINT_clear_free(elem); |
2605 | 0 | return NULL; |
2606 | 0 | } |
2607 | | |
2608 | 0 | if (!EC_POINT_set_affine_coordinates(e->group, elem, x, y, e->bnctx)) { |
2609 | 0 | EC_POINT_clear_free(elem); |
2610 | 0 | elem = NULL; |
2611 | 0 | } |
2612 | |
|
2613 | 0 | BN_clear_free(x); |
2614 | 0 | BN_clear_free(y); |
2615 | |
|
2616 | 0 | return (struct crypto_ec_point *) elem; |
2617 | 0 | } |
2618 | | |
2619 | | |
2620 | | int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, |
2621 | | const struct crypto_ec_point *b, |
2622 | | struct crypto_ec_point *c) |
2623 | 0 | { |
2624 | 0 | if (TEST_FAIL()) |
2625 | 0 | return -1; |
2626 | 0 | return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a, |
2627 | 0 | (const EC_POINT *) b, e->bnctx) ? 0 : -1; |
2628 | 0 | } |
2629 | | |
2630 | | |
2631 | | int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, |
2632 | | const struct crypto_bignum *b, |
2633 | | struct crypto_ec_point *res) |
2634 | 0 | { |
2635 | 0 | if (TEST_FAIL()) |
2636 | 0 | return -1; |
2637 | 0 | return EC_POINT_mul(e->group, (EC_POINT *) res, NULL, |
2638 | 0 | (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx) |
2639 | 0 | ? 0 : -1; |
2640 | 0 | } |
2641 | | |
2642 | | |
2643 | | int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) |
2644 | 0 | { |
2645 | 0 | if (TEST_FAIL()) |
2646 | 0 | return -1; |
2647 | 0 | return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1; |
2648 | 0 | } |
2649 | | |
2650 | | |
2651 | | struct crypto_bignum * |
2652 | | crypto_ec_point_compute_y_sqr(struct crypto_ec *e, |
2653 | | const struct crypto_bignum *x) |
2654 | 0 | { |
2655 | 0 | BIGNUM *tmp; |
2656 | |
|
2657 | 0 | if (TEST_FAIL()) |
2658 | 0 | return NULL; |
2659 | | |
2660 | 0 | tmp = BN_new(); |
2661 | | |
2662 | | /* y^2 = x^3 + ax + b = (x^2 + a)x + b */ |
2663 | 0 | if (tmp && |
2664 | 0 | BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) && |
2665 | 0 | BN_mod_add_quick(tmp, e->a, tmp, e->prime) && |
2666 | 0 | BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) && |
2667 | 0 | BN_mod_add_quick(tmp, tmp, e->b, e->prime)) |
2668 | 0 | return (struct crypto_bignum *) tmp; |
2669 | | |
2670 | 0 | BN_clear_free(tmp); |
2671 | 0 | return NULL; |
2672 | 0 | } |
2673 | | |
2674 | | |
2675 | | int crypto_ec_point_is_at_infinity(struct crypto_ec *e, |
2676 | | const struct crypto_ec_point *p) |
2677 | 0 | { |
2678 | 0 | return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p); |
2679 | 0 | } |
2680 | | |
2681 | | |
2682 | | int crypto_ec_point_is_on_curve(struct crypto_ec *e, |
2683 | | const struct crypto_ec_point *p) |
2684 | 0 | { |
2685 | 0 | return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, |
2686 | 0 | e->bnctx) == 1; |
2687 | 0 | } |
2688 | | |
2689 | | |
2690 | | int crypto_ec_point_cmp(const struct crypto_ec *e, |
2691 | | const struct crypto_ec_point *a, |
2692 | | const struct crypto_ec_point *b) |
2693 | 0 | { |
2694 | 0 | return EC_POINT_cmp(e->group, (const EC_POINT *) a, |
2695 | 0 | (const EC_POINT *) b, e->bnctx); |
2696 | 0 | } |
2697 | | |
2698 | | |
2699 | | void crypto_ec_point_debug_print(const struct crypto_ec *e, |
2700 | | const struct crypto_ec_point *p, |
2701 | | const char *title) |
2702 | 0 | { |
2703 | 0 | BIGNUM *x, *y; |
2704 | 0 | char *x_str = NULL, *y_str = NULL; |
2705 | |
|
2706 | 0 | x = BN_new(); |
2707 | 0 | y = BN_new(); |
2708 | 0 | if (!x || !y || |
2709 | 0 | EC_POINT_get_affine_coordinates(e->group, (const EC_POINT *) p, |
2710 | 0 | x, y, e->bnctx) != 1) |
2711 | 0 | goto fail; |
2712 | | |
2713 | 0 | x_str = BN_bn2hex(x); |
2714 | 0 | y_str = BN_bn2hex(y); |
2715 | 0 | if (!x_str || !y_str) |
2716 | 0 | goto fail; |
2717 | | |
2718 | 0 | wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); |
2719 | |
|
2720 | 0 | fail: |
2721 | 0 | OPENSSL_free(x_str); |
2722 | 0 | OPENSSL_free(y_str); |
2723 | 0 | BN_free(x); |
2724 | 0 | BN_free(y); |
2725 | 0 | } |
2726 | | |
2727 | | |
2728 | | struct crypto_ecdh { |
2729 | | struct crypto_ec *ec; |
2730 | | EVP_PKEY *pkey; |
2731 | | }; |
2732 | | |
2733 | | struct crypto_ecdh * crypto_ecdh_init(int group) |
2734 | 0 | { |
2735 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
2736 | | struct crypto_ecdh *ecdh; |
2737 | | const char *name; |
2738 | | |
2739 | | ecdh = os_zalloc(sizeof(*ecdh)); |
2740 | | if (!ecdh) |
2741 | | goto fail; |
2742 | | |
2743 | | ecdh->ec = crypto_ec_init(group); |
2744 | | if (!ecdh->ec) |
2745 | | goto fail; |
2746 | | |
2747 | | name = OSSL_EC_curve_nid2name(ecdh->ec->nid); |
2748 | | if (!name) |
2749 | | goto fail; |
2750 | | |
2751 | | ecdh->pkey = EVP_EC_gen(name); |
2752 | | if (!ecdh->pkey) { |
2753 | | wpa_printf(MSG_INFO, |
2754 | | "OpenSSL: EVP_EC_gen(group=%d) failed: %s", |
2755 | | group, ERR_error_string(ERR_get_error(), NULL)); |
2756 | | goto fail; |
2757 | | } |
2758 | | |
2759 | | done: |
2760 | | return ecdh; |
2761 | | fail: |
2762 | | crypto_ecdh_deinit(ecdh); |
2763 | | ecdh = NULL; |
2764 | | goto done; |
2765 | | #else /* OpenSSL version >= 3.0 */ |
2766 | 0 | struct crypto_ecdh *ecdh; |
2767 | 0 | EVP_PKEY *params = NULL; |
2768 | 0 | EC_KEY *ec_params = NULL; |
2769 | 0 | EVP_PKEY_CTX *kctx = NULL; |
2770 | |
|
2771 | 0 | ecdh = os_zalloc(sizeof(*ecdh)); |
2772 | 0 | if (!ecdh) |
2773 | 0 | goto fail; |
2774 | | |
2775 | 0 | ecdh->ec = crypto_ec_init(group); |
2776 | 0 | if (!ecdh->ec) |
2777 | 0 | goto fail; |
2778 | | |
2779 | 0 | ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid); |
2780 | 0 | if (!ec_params) { |
2781 | 0 | wpa_printf(MSG_ERROR, |
2782 | 0 | "OpenSSL: Failed to generate EC_KEY parameters"); |
2783 | 0 | goto fail; |
2784 | 0 | } |
2785 | 0 | EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); |
2786 | 0 | params = EVP_PKEY_new(); |
2787 | 0 | if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { |
2788 | 0 | wpa_printf(MSG_ERROR, |
2789 | 0 | "OpenSSL: Failed to generate EVP_PKEY parameters"); |
2790 | 0 | goto fail; |
2791 | 0 | } |
2792 | | |
2793 | 0 | kctx = EVP_PKEY_CTX_new(params, NULL); |
2794 | 0 | if (!kctx) |
2795 | 0 | goto fail; |
2796 | | |
2797 | 0 | if (EVP_PKEY_keygen_init(kctx) != 1) { |
2798 | 0 | wpa_printf(MSG_ERROR, |
2799 | 0 | "OpenSSL: EVP_PKEY_keygen_init failed: %s", |
2800 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
2801 | 0 | goto fail; |
2802 | 0 | } |
2803 | | |
2804 | 0 | if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) { |
2805 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s", |
2806 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
2807 | 0 | goto fail; |
2808 | 0 | } |
2809 | | |
2810 | 0 | done: |
2811 | 0 | EC_KEY_free(ec_params); |
2812 | 0 | EVP_PKEY_free(params); |
2813 | 0 | EVP_PKEY_CTX_free(kctx); |
2814 | |
|
2815 | 0 | return ecdh; |
2816 | 0 | fail: |
2817 | 0 | crypto_ecdh_deinit(ecdh); |
2818 | 0 | ecdh = NULL; |
2819 | 0 | goto done; |
2820 | 0 | #endif /* OpenSSL version >= 3.0 */ |
2821 | 0 | } |
2822 | | |
2823 | | |
2824 | | struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key) |
2825 | 0 | { |
2826 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
2827 | | struct crypto_ecdh *ecdh; |
2828 | | |
2829 | | ecdh = os_zalloc(sizeof(*ecdh)); |
2830 | | if (!ecdh) |
2831 | | goto fail; |
2832 | | |
2833 | | ecdh->ec = crypto_ec_init(group); |
2834 | | if (!ecdh->ec) |
2835 | | goto fail; |
2836 | | |
2837 | | ecdh->pkey = EVP_PKEY_dup((EVP_PKEY *) own_key); |
2838 | | if (!ecdh->pkey) |
2839 | | goto fail; |
2840 | | |
2841 | | return ecdh; |
2842 | | fail: |
2843 | | crypto_ecdh_deinit(ecdh); |
2844 | | return NULL; |
2845 | | #else /* OpenSSL version >= 3.0 */ |
2846 | 0 | struct crypto_ecdh *ecdh; |
2847 | |
|
2848 | 0 | ecdh = os_zalloc(sizeof(*ecdh)); |
2849 | 0 | if (!ecdh) |
2850 | 0 | goto fail; |
2851 | | |
2852 | 0 | ecdh->ec = crypto_ec_init(group); |
2853 | 0 | if (!ecdh->ec) |
2854 | 0 | goto fail; |
2855 | | |
2856 | 0 | ecdh->pkey = EVP_PKEY_new(); |
2857 | 0 | if (!ecdh->pkey || |
2858 | 0 | EVP_PKEY_assign_EC_KEY(ecdh->pkey, |
2859 | 0 | EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key)) |
2860 | 0 | != 1) |
2861 | 0 | goto fail; |
2862 | | |
2863 | 0 | return ecdh; |
2864 | 0 | fail: |
2865 | 0 | crypto_ecdh_deinit(ecdh); |
2866 | 0 | return NULL; |
2867 | 0 | #endif /* OpenSSL version >= 3.0 */ |
2868 | 0 | } |
2869 | | |
2870 | | |
2871 | | struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) |
2872 | 0 | { |
2873 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
2874 | | struct wpabuf *buf = NULL; |
2875 | | unsigned char *pub; |
2876 | | size_t len, exp_len; |
2877 | | |
2878 | | len = EVP_PKEY_get1_encoded_public_key(ecdh->pkey, &pub); |
2879 | | if (len == 0) |
2880 | | return NULL; |
2881 | | |
2882 | | /* Encoded using SECG SEC 1, Sec. 2.3.4 format */ |
2883 | | exp_len = 1 + 2 * crypto_ec_prime_len(ecdh->ec); |
2884 | | if (len != exp_len) { |
2885 | | wpa_printf(MSG_ERROR, |
2886 | | "OpenSSL:%s: Unexpected encoded public key length %zu (expected %zu)", |
2887 | | __func__, len, exp_len); |
2888 | | goto fail; |
2889 | | } |
2890 | | buf = wpabuf_alloc_copy(pub + 1, inc_y ? len - 1 : len / 2); |
2891 | | fail: |
2892 | | OPENSSL_free(pub); |
2893 | | return buf; |
2894 | | #else /* OpenSSL version >= 3.0 */ |
2895 | 0 | struct wpabuf *buf = NULL; |
2896 | 0 | EC_KEY *eckey; |
2897 | 0 | const EC_POINT *pubkey; |
2898 | 0 | BIGNUM *x, *y = NULL; |
2899 | 0 | int len = BN_num_bytes(ecdh->ec->prime); |
2900 | 0 | int res; |
2901 | |
|
2902 | 0 | eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey); |
2903 | 0 | if (!eckey) |
2904 | 0 | return NULL; |
2905 | | |
2906 | 0 | pubkey = EC_KEY_get0_public_key(eckey); |
2907 | 0 | if (!pubkey) |
2908 | 0 | return NULL; |
2909 | | |
2910 | 0 | x = BN_new(); |
2911 | 0 | if (inc_y) { |
2912 | 0 | y = BN_new(); |
2913 | 0 | if (!y) |
2914 | 0 | goto fail; |
2915 | 0 | } |
2916 | 0 | buf = wpabuf_alloc(inc_y ? 2 * len : len); |
2917 | 0 | if (!x || !buf) |
2918 | 0 | goto fail; |
2919 | | |
2920 | 0 | if (EC_POINT_get_affine_coordinates(ecdh->ec->group, pubkey, |
2921 | 0 | x, y, ecdh->ec->bnctx) != 1) { |
2922 | 0 | wpa_printf(MSG_ERROR, |
2923 | 0 | "OpenSSL: EC_POINT_get_affine_coordinates failed: %s", |
2924 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
2925 | 0 | goto fail; |
2926 | 0 | } |
2927 | | |
2928 | 0 | res = crypto_bignum_to_bin((struct crypto_bignum *) x, |
2929 | 0 | wpabuf_put(buf, len), len, len); |
2930 | 0 | if (res < 0) |
2931 | 0 | goto fail; |
2932 | | |
2933 | 0 | if (inc_y) { |
2934 | 0 | res = crypto_bignum_to_bin((struct crypto_bignum *) y, |
2935 | 0 | wpabuf_put(buf, len), len, len); |
2936 | 0 | if (res < 0) |
2937 | 0 | goto fail; |
2938 | 0 | } |
2939 | | |
2940 | 0 | done: |
2941 | 0 | BN_clear_free(x); |
2942 | 0 | BN_clear_free(y); |
2943 | 0 | EC_KEY_free(eckey); |
2944 | |
|
2945 | 0 | return buf; |
2946 | 0 | fail: |
2947 | 0 | wpabuf_free(buf); |
2948 | 0 | buf = NULL; |
2949 | 0 | goto done; |
2950 | 0 | #endif /* OpenSSL version >= 3.0 */ |
2951 | 0 | } |
2952 | | |
2953 | | |
2954 | | struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, |
2955 | | const u8 *key, size_t len) |
2956 | 0 | { |
2957 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
2958 | | EVP_PKEY *peerkey = EVP_PKEY_new(); |
2959 | | EVP_PKEY_CTX *ctx; |
2960 | | size_t res_len; |
2961 | | struct wpabuf *res = NULL; |
2962 | | u8 *peer; |
2963 | | |
2964 | | /* Encode using SECG SEC 1, Sec. 2.3.4 format */ |
2965 | | peer = os_malloc(1 + len); |
2966 | | if (!peer) { |
2967 | | EVP_PKEY_free(peerkey); |
2968 | | return NULL; |
2969 | | } |
2970 | | peer[0] = inc_y ? 0x04 : 0x02; |
2971 | | os_memcpy(peer + 1, key, len); |
2972 | | |
2973 | | if (!peerkey || |
2974 | | EVP_PKEY_copy_parameters(peerkey, ecdh->pkey) != 1 || |
2975 | | EVP_PKEY_set1_encoded_public_key(peerkey, peer, 1 + len) != 1) { |
2976 | | wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_set1_encoded_public_key failed: %s", |
2977 | | ERR_error_string(ERR_get_error(), NULL)); |
2978 | | EVP_PKEY_free(peerkey); |
2979 | | os_free(peer); |
2980 | | return NULL; |
2981 | | } |
2982 | | os_free(peer); |
2983 | | |
2984 | | ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL); |
2985 | | if (!ctx || |
2986 | | EVP_PKEY_derive_init(ctx) != 1 || |
2987 | | EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 || |
2988 | | EVP_PKEY_derive(ctx, NULL, &res_len) != 1 || |
2989 | | !(res = wpabuf_alloc(res_len)) || |
2990 | | EVP_PKEY_derive(ctx, wpabuf_mhead(res), &res_len) != 1) { |
2991 | | wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_derive failed: %s", |
2992 | | ERR_error_string(ERR_get_error(), NULL)); |
2993 | | wpabuf_free(res); |
2994 | | res = NULL; |
2995 | | } else { |
2996 | | wpabuf_put(res, res_len); |
2997 | | } |
2998 | | |
2999 | | EVP_PKEY_free(peerkey); |
3000 | | EVP_PKEY_CTX_free(ctx); |
3001 | | return res; |
3002 | | #else /* OpenSSL version >= 3.0 */ |
3003 | 0 | BIGNUM *x, *y = NULL; |
3004 | 0 | EVP_PKEY_CTX *ctx = NULL; |
3005 | 0 | EVP_PKEY *peerkey = NULL; |
3006 | 0 | struct wpabuf *secret = NULL; |
3007 | 0 | size_t secret_len; |
3008 | 0 | EC_POINT *pub; |
3009 | 0 | EC_KEY *eckey = NULL; |
3010 | |
|
3011 | 0 | x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL); |
3012 | 0 | pub = EC_POINT_new(ecdh->ec->group); |
3013 | 0 | if (!x || !pub) |
3014 | 0 | goto fail; |
3015 | | |
3016 | 0 | if (inc_y) { |
3017 | 0 | y = BN_bin2bn(key + len / 2, len / 2, NULL); |
3018 | 0 | if (!y) |
3019 | 0 | goto fail; |
3020 | 0 | if (!EC_POINT_set_affine_coordinates(ecdh->ec->group, pub, |
3021 | 0 | x, y, ecdh->ec->bnctx)) { |
3022 | 0 | wpa_printf(MSG_ERROR, |
3023 | 0 | "OpenSSL: EC_POINT_set_affine_coordinates failed: %s", |
3024 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3025 | 0 | goto fail; |
3026 | 0 | } |
3027 | 0 | } else if (!EC_POINT_set_compressed_coordinates(ecdh->ec->group, |
3028 | 0 | pub, x, 0, |
3029 | 0 | ecdh->ec->bnctx)) { |
3030 | 0 | wpa_printf(MSG_ERROR, |
3031 | 0 | "OpenSSL: EC_POINT_set_compressed_coordinates failed: %s", |
3032 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3033 | 0 | goto fail; |
3034 | 0 | } |
3035 | | |
3036 | 0 | if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) { |
3037 | 0 | wpa_printf(MSG_ERROR, |
3038 | 0 | "OpenSSL: ECDH peer public key is not on curve"); |
3039 | 0 | goto fail; |
3040 | 0 | } |
3041 | | |
3042 | 0 | eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid); |
3043 | 0 | if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) { |
3044 | 0 | wpa_printf(MSG_ERROR, |
3045 | 0 | "OpenSSL: EC_KEY_set_public_key failed: %s", |
3046 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3047 | 0 | goto fail; |
3048 | 0 | } |
3049 | | |
3050 | 0 | peerkey = EVP_PKEY_new(); |
3051 | 0 | if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1) |
3052 | 0 | goto fail; |
3053 | | |
3054 | 0 | ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL); |
3055 | 0 | if (!ctx || EVP_PKEY_derive_init(ctx) != 1 || |
3056 | 0 | EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 || |
3057 | 0 | EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) { |
3058 | 0 | wpa_printf(MSG_ERROR, |
3059 | 0 | "OpenSSL: EVP_PKEY_derive(1) failed: %s", |
3060 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3061 | 0 | goto fail; |
3062 | 0 | } |
3063 | | |
3064 | 0 | secret = wpabuf_alloc(secret_len); |
3065 | 0 | if (!secret) |
3066 | 0 | goto fail; |
3067 | 0 | if (EVP_PKEY_derive(ctx, wpabuf_put(secret, 0), &secret_len) != 1) { |
3068 | 0 | wpa_printf(MSG_ERROR, |
3069 | 0 | "OpenSSL: EVP_PKEY_derive(2) failed: %s", |
3070 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3071 | 0 | goto fail; |
3072 | 0 | } |
3073 | 0 | if (secret->size != secret_len) |
3074 | 0 | wpa_printf(MSG_DEBUG, |
3075 | 0 | "OpenSSL: EVP_PKEY_derive(2) changed secret_len %d -> %d", |
3076 | 0 | (int) secret->size, (int) secret_len); |
3077 | 0 | wpabuf_put(secret, secret_len); |
3078 | |
|
3079 | 0 | done: |
3080 | 0 | BN_free(x); |
3081 | 0 | BN_free(y); |
3082 | 0 | EC_KEY_free(eckey); |
3083 | 0 | EC_POINT_free(pub); |
3084 | 0 | EVP_PKEY_CTX_free(ctx); |
3085 | 0 | EVP_PKEY_free(peerkey); |
3086 | 0 | return secret; |
3087 | 0 | fail: |
3088 | 0 | wpabuf_free(secret); |
3089 | 0 | secret = NULL; |
3090 | 0 | goto done; |
3091 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3092 | 0 | } |
3093 | | |
3094 | | |
3095 | | void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) |
3096 | 0 | { |
3097 | 0 | if (ecdh) { |
3098 | 0 | crypto_ec_deinit(ecdh->ec); |
3099 | 0 | EVP_PKEY_free(ecdh->pkey); |
3100 | 0 | os_free(ecdh); |
3101 | 0 | } |
3102 | 0 | } |
3103 | | |
3104 | | |
3105 | | size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) |
3106 | 0 | { |
3107 | 0 | return crypto_ec_prime_len(ecdh->ec); |
3108 | 0 | } |
3109 | | |
3110 | | |
3111 | | struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) |
3112 | 0 | { |
3113 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3114 | | EVP_PKEY *pkey = NULL; |
3115 | | OSSL_DECODER_CTX *ctx; |
3116 | | |
3117 | | ctx = OSSL_DECODER_CTX_new_for_pkey( |
3118 | | &pkey, "DER", NULL, "EC", |
3119 | | OSSL_KEYMGMT_SELECT_KEYPAIR | |
3120 | | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, |
3121 | | NULL, NULL); |
3122 | | if (!ctx || |
3123 | | OSSL_DECODER_from_data(ctx, &der, &der_len) != 1) { |
3124 | | wpa_printf(MSG_INFO, |
3125 | | "OpenSSL: Decoding EC private key (DER) failed: %s", |
3126 | | ERR_error_string(ERR_get_error(), NULL)); |
3127 | | if (ctx) |
3128 | | OSSL_DECODER_CTX_free(ctx); |
3129 | | goto fail; |
3130 | | } |
3131 | | |
3132 | | OSSL_DECODER_CTX_free(ctx); |
3133 | | return (struct crypto_ec_key *) pkey; |
3134 | | fail: |
3135 | | crypto_ec_key_deinit((struct crypto_ec_key *) pkey); |
3136 | | return NULL; |
3137 | | #else /* OpenSSL version >= 3.0 */ |
3138 | 0 | EVP_PKEY *pkey = NULL; |
3139 | 0 | EC_KEY *eckey; |
3140 | |
|
3141 | 0 | eckey = d2i_ECPrivateKey(NULL, &der, der_len); |
3142 | 0 | if (!eckey) { |
3143 | 0 | wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s", |
3144 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3145 | 0 | goto fail; |
3146 | 0 | } |
3147 | 0 | EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); |
3148 | |
|
3149 | 0 | pkey = EVP_PKEY_new(); |
3150 | 0 | if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { |
3151 | 0 | EC_KEY_free(eckey); |
3152 | 0 | goto fail; |
3153 | 0 | } |
3154 | | |
3155 | 0 | return (struct crypto_ec_key *) pkey; |
3156 | 0 | fail: |
3157 | 0 | crypto_ec_key_deinit((struct crypto_ec_key *) pkey); |
3158 | 0 | return NULL; |
3159 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3160 | 0 | } |
3161 | | |
3162 | | |
3163 | | struct crypto_ec_key * crypto_ec_key_set_priv(int group, |
3164 | | const u8 *raw, size_t raw_len) |
3165 | 0 | { |
3166 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3167 | | const char *group_name; |
3168 | | OSSL_PARAM params[4]; |
3169 | | EVP_PKEY_CTX *ctx = NULL; |
3170 | | EVP_PKEY *pkey = NULL; |
3171 | | BIGNUM *priv; |
3172 | | EC_POINT *pub = NULL; |
3173 | | EC_GROUP *ec_group = NULL; |
3174 | | size_t len; |
3175 | | u8 *pub_bin = NULL; |
3176 | | u8 *priv_bin = NULL; |
3177 | | int priv_bin_len; |
3178 | | |
3179 | | group_name = crypto_ec_group_2_name(group); |
3180 | | if (!group_name) |
3181 | | return NULL; |
3182 | | |
3183 | | priv = BN_bin2bn(raw, raw_len, NULL); |
3184 | | if (!priv) |
3185 | | return NULL; |
3186 | | priv_bin = os_malloc(raw_len); |
3187 | | if (!priv_bin) |
3188 | | goto fail; |
3189 | | priv_bin_len = BN_bn2lebinpad(priv, priv_bin, raw_len); |
3190 | | if (priv_bin_len < 0) |
3191 | | goto fail; |
3192 | | |
3193 | | ec_group = EC_GROUP_new_by_curve_name(crypto_ec_group_2_nid(group)); |
3194 | | if (!ec_group) |
3195 | | goto fail; |
3196 | | pub = EC_POINT_new(ec_group); |
3197 | | if (!pub || |
3198 | | EC_POINT_mul(ec_group, pub, priv, NULL, NULL, NULL) != 1) |
3199 | | goto fail; |
3200 | | len = EC_POINT_point2oct(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, |
3201 | | NULL, 0, NULL); |
3202 | | if (len == 0) |
3203 | | goto fail; |
3204 | | pub_bin = os_malloc(len); |
3205 | | if (!pub_bin) |
3206 | | goto fail; |
3207 | | len = EC_POINT_point2oct(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, |
3208 | | pub_bin, len, NULL); |
3209 | | if (len == 0) |
3210 | | goto fail; |
3211 | | |
3212 | | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, |
3213 | | (char *) group_name, 0); |
3214 | | params[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, |
3215 | | priv_bin, priv_bin_len); |
3216 | | params[2] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, |
3217 | | pub_bin, len); |
3218 | | params[3] = OSSL_PARAM_construct_end(); |
3219 | | |
3220 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); |
3221 | | if (!ctx || |
3222 | | EVP_PKEY_fromdata_init(ctx) <= 0 || |
3223 | | EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) |
3224 | | goto fail; |
3225 | | |
3226 | | out: |
3227 | | bin_clear_free(priv_bin, raw_len); |
3228 | | os_free(pub_bin); |
3229 | | BN_clear_free(priv); |
3230 | | EVP_PKEY_CTX_free(ctx); |
3231 | | EC_POINT_free(pub); |
3232 | | EC_GROUP_free(ec_group); |
3233 | | return (struct crypto_ec_key *) pkey; |
3234 | | |
3235 | | fail: |
3236 | | EVP_PKEY_free(pkey); |
3237 | | pkey = NULL; |
3238 | | goto out; |
3239 | | #else /* OpenSSL version >= 3.0 */ |
3240 | 0 | EC_KEY *eckey = NULL; |
3241 | 0 | EVP_PKEY *pkey = NULL; |
3242 | 0 | BIGNUM *priv = NULL; |
3243 | 0 | int nid; |
3244 | 0 | const EC_GROUP *ec_group; |
3245 | 0 | EC_POINT *pub = NULL; |
3246 | |
|
3247 | 0 | nid = crypto_ec_group_2_nid(group); |
3248 | 0 | if (nid < 0) { |
3249 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); |
3250 | 0 | return NULL; |
3251 | 0 | } |
3252 | | |
3253 | 0 | eckey = EC_KEY_new_by_curve_name(nid); |
3254 | 0 | priv = BN_bin2bn(raw, raw_len, NULL); |
3255 | 0 | if (!eckey || !priv || |
3256 | 0 | EC_KEY_set_private_key(eckey, priv) != 1) { |
3257 | 0 | wpa_printf(MSG_ERROR, |
3258 | 0 | "OpenSSL: Failed to set EC_KEY: %s", |
3259 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3260 | 0 | goto fail; |
3261 | 0 | } |
3262 | | |
3263 | 0 | ec_group = EC_KEY_get0_group(eckey); |
3264 | 0 | if (!ec_group) |
3265 | 0 | goto fail; |
3266 | 0 | pub = EC_POINT_new(ec_group); |
3267 | 0 | if (!pub || |
3268 | 0 | EC_POINT_mul(ec_group, pub, priv, NULL, NULL, NULL) != 1 || |
3269 | 0 | EC_KEY_set_public_key(eckey, pub) != 1) { |
3270 | 0 | wpa_printf(MSG_ERROR, |
3271 | 0 | "OpenSSL: Failed to set EC_KEY(pub): %s", |
3272 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3273 | 0 | goto fail; |
3274 | 0 | } |
3275 | | |
3276 | 0 | EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); |
3277 | |
|
3278 | 0 | pkey = EVP_PKEY_new(); |
3279 | 0 | if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { |
3280 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); |
3281 | 0 | goto fail; |
3282 | 0 | } |
3283 | | |
3284 | 0 | out: |
3285 | 0 | BN_clear_free(priv); |
3286 | 0 | EC_POINT_free(pub); |
3287 | 0 | return (struct crypto_ec_key *) pkey; |
3288 | | |
3289 | 0 | fail: |
3290 | 0 | EC_KEY_free(eckey); |
3291 | 0 | EVP_PKEY_free(pkey); |
3292 | 0 | pkey = NULL; |
3293 | 0 | goto out; |
3294 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3295 | 0 | } |
3296 | | |
3297 | | |
3298 | | struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) |
3299 | 168 | { |
3300 | 168 | EVP_PKEY *pkey; |
3301 | | |
3302 | 168 | pkey = d2i_PUBKEY(NULL, &der, der_len); |
3303 | 168 | if (!pkey) { |
3304 | 117 | wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s", |
3305 | 117 | ERR_error_string(ERR_get_error(), NULL)); |
3306 | 117 | goto fail; |
3307 | 117 | } |
3308 | | |
3309 | | /* Ensure this is an EC key */ |
3310 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3311 | | if (!EVP_PKEY_is_a(pkey, "EC")) |
3312 | | goto fail; |
3313 | | #else /* OpenSSL version >= 3.0 */ |
3314 | 51 | if (!EVP_PKEY_get0_EC_KEY(pkey)) |
3315 | 0 | goto fail; |
3316 | 51 | #endif /* OpenSSL version >= 3.0 */ |
3317 | 51 | return (struct crypto_ec_key *) pkey; |
3318 | 117 | fail: |
3319 | 117 | crypto_ec_key_deinit((struct crypto_ec_key *) pkey); |
3320 | 117 | return NULL; |
3321 | 51 | } |
3322 | | |
3323 | | |
3324 | | struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x, |
3325 | | const u8 *buf_y, size_t len) |
3326 | 0 | { |
3327 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3328 | | const char *group_name; |
3329 | | OSSL_PARAM params[3]; |
3330 | | u8 *pub; |
3331 | | EVP_PKEY_CTX *ctx; |
3332 | | EVP_PKEY *pkey = NULL; |
3333 | | |
3334 | | group_name = crypto_ec_group_2_name(group); |
3335 | | if (!group_name) |
3336 | | return NULL; |
3337 | | |
3338 | | pub = os_malloc(1 + len * 2); |
3339 | | if (!pub) |
3340 | | return NULL; |
3341 | | pub[0] = 0x04; /* uncompressed */ |
3342 | | os_memcpy(pub + 1, buf_x, len); |
3343 | | os_memcpy(pub + 1 + len, buf_y, len); |
3344 | | |
3345 | | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, |
3346 | | (char *) group_name, 0); |
3347 | | params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, |
3348 | | pub, 1 + len * 2); |
3349 | | params[2] = OSSL_PARAM_construct_end(); |
3350 | | |
3351 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); |
3352 | | if (!ctx) { |
3353 | | os_free(pub); |
3354 | | return NULL; |
3355 | | } |
3356 | | if (EVP_PKEY_fromdata_init(ctx) <= 0 || |
3357 | | EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { |
3358 | | os_free(pub); |
3359 | | EVP_PKEY_CTX_free(ctx); |
3360 | | return NULL; |
3361 | | } |
3362 | | |
3363 | | os_free(pub); |
3364 | | EVP_PKEY_CTX_free(ctx); |
3365 | | |
3366 | | return (struct crypto_ec_key *) pkey; |
3367 | | #else /* OpenSSL version >= 3.0 */ |
3368 | 0 | EC_KEY *eckey = NULL; |
3369 | 0 | EVP_PKEY *pkey = NULL; |
3370 | 0 | EC_GROUP *ec_group = NULL; |
3371 | 0 | BN_CTX *ctx; |
3372 | 0 | EC_POINT *point = NULL; |
3373 | 0 | BIGNUM *x = NULL, *y = NULL; |
3374 | 0 | int nid; |
3375 | |
|
3376 | 0 | if (!buf_x || !buf_y) |
3377 | 0 | return NULL; |
3378 | | |
3379 | 0 | nid = crypto_ec_group_2_nid(group); |
3380 | 0 | if (nid < 0) { |
3381 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); |
3382 | 0 | return NULL; |
3383 | 0 | } |
3384 | | |
3385 | 0 | ctx = BN_CTX_new(); |
3386 | 0 | if (!ctx) |
3387 | 0 | goto fail; |
3388 | | |
3389 | 0 | ec_group = EC_GROUP_new_by_curve_name(nid); |
3390 | 0 | if (!ec_group) |
3391 | 0 | goto fail; |
3392 | | |
3393 | 0 | x = BN_bin2bn(buf_x, len, NULL); |
3394 | 0 | y = BN_bin2bn(buf_y, len, NULL); |
3395 | 0 | point = EC_POINT_new(ec_group); |
3396 | 0 | if (!x || !y || !point) |
3397 | 0 | goto fail; |
3398 | | |
3399 | 0 | if (!EC_POINT_set_affine_coordinates(ec_group, point, x, y, ctx)) { |
3400 | 0 | wpa_printf(MSG_ERROR, |
3401 | 0 | "OpenSSL: EC_POINT_set_affine_coordinates failed: %s", |
3402 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3403 | 0 | goto fail; |
3404 | 0 | } |
3405 | | |
3406 | 0 | if (!EC_POINT_is_on_curve(ec_group, point, ctx) || |
3407 | 0 | EC_POINT_is_at_infinity(ec_group, point)) { |
3408 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Invalid point"); |
3409 | 0 | goto fail; |
3410 | 0 | } |
3411 | | |
3412 | 0 | eckey = EC_KEY_new(); |
3413 | 0 | if (!eckey || |
3414 | 0 | EC_KEY_set_group(eckey, ec_group) != 1 || |
3415 | 0 | EC_KEY_set_public_key(eckey, point) != 1) { |
3416 | 0 | wpa_printf(MSG_ERROR, |
3417 | 0 | "OpenSSL: Failed to set EC_KEY: %s", |
3418 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3419 | 0 | goto fail; |
3420 | 0 | } |
3421 | 0 | EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); |
3422 | |
|
3423 | 0 | pkey = EVP_PKEY_new(); |
3424 | 0 | if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { |
3425 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); |
3426 | 0 | goto fail; |
3427 | 0 | } |
3428 | | |
3429 | 0 | out: |
3430 | 0 | EC_GROUP_free(ec_group); |
3431 | 0 | BN_free(x); |
3432 | 0 | BN_free(y); |
3433 | 0 | EC_POINT_free(point); |
3434 | 0 | BN_CTX_free(ctx); |
3435 | 0 | return (struct crypto_ec_key *) pkey; |
3436 | | |
3437 | 0 | fail: |
3438 | 0 | EC_KEY_free(eckey); |
3439 | 0 | EVP_PKEY_free(pkey); |
3440 | 0 | pkey = NULL; |
3441 | 0 | goto out; |
3442 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3443 | 0 | } |
3444 | | |
3445 | | |
3446 | | struct crypto_ec_key * |
3447 | | crypto_ec_key_set_pub_point(struct crypto_ec *ec, |
3448 | | const struct crypto_ec_point *pub) |
3449 | 0 | { |
3450 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3451 | | int len = BN_num_bytes(ec->prime); |
3452 | | struct crypto_ec_key *key; |
3453 | | u8 *buf; |
3454 | | |
3455 | | buf = os_malloc(2 * len); |
3456 | | if (!buf) |
3457 | | return NULL; |
3458 | | if (crypto_ec_point_to_bin(ec, pub, buf, buf + len) < 0) { |
3459 | | os_free(buf); |
3460 | | return NULL; |
3461 | | } |
3462 | | |
3463 | | key = crypto_ec_key_set_pub(ec->iana_group, buf, buf + len, len); |
3464 | | os_free(buf); |
3465 | | |
3466 | | return key; |
3467 | | #else /* OpenSSL version >= 3.0 */ |
3468 | 0 | EC_KEY *eckey; |
3469 | 0 | EVP_PKEY *pkey = NULL; |
3470 | |
|
3471 | 0 | eckey = EC_KEY_new(); |
3472 | 0 | if (!eckey || |
3473 | 0 | EC_KEY_set_group(eckey, ec->group) != 1 || |
3474 | 0 | EC_KEY_set_public_key(eckey, (const EC_POINT *) pub) != 1) { |
3475 | 0 | wpa_printf(MSG_ERROR, |
3476 | 0 | "OpenSSL: Failed to set EC_KEY: %s", |
3477 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3478 | 0 | goto fail; |
3479 | 0 | } |
3480 | 0 | EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); |
3481 | |
|
3482 | 0 | pkey = EVP_PKEY_new(); |
3483 | 0 | if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { |
3484 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); |
3485 | 0 | goto fail; |
3486 | 0 | } |
3487 | | |
3488 | 0 | out: |
3489 | 0 | return (struct crypto_ec_key *) pkey; |
3490 | | |
3491 | 0 | fail: |
3492 | 0 | EVP_PKEY_free(pkey); |
3493 | 0 | EC_KEY_free(eckey); |
3494 | 0 | pkey = NULL; |
3495 | 0 | goto out; |
3496 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3497 | 0 | } |
3498 | | |
3499 | | |
3500 | | struct crypto_ec_key * crypto_ec_key_gen(int group) |
3501 | 0 | { |
3502 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3503 | | EVP_PKEY_CTX *ctx; |
3504 | | OSSL_PARAM params[2]; |
3505 | | const char *group_name; |
3506 | | EVP_PKEY *pkey = NULL; |
3507 | | |
3508 | | group_name = crypto_ec_group_2_name(group); |
3509 | | if (!group_name) |
3510 | | return NULL; |
3511 | | |
3512 | | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, |
3513 | | (char *) group_name, 0); |
3514 | | params[1] = OSSL_PARAM_construct_end(); |
3515 | | |
3516 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); |
3517 | | if (!ctx || |
3518 | | EVP_PKEY_keygen_init(ctx) != 1 || |
3519 | | EVP_PKEY_CTX_set_params(ctx, params) != 1 || |
3520 | | EVP_PKEY_generate(ctx, &pkey) != 1) { |
3521 | | wpa_printf(MSG_INFO, |
3522 | | "OpenSSL: Failed to generate EC keypair (group=%d): %s", |
3523 | | group, ERR_error_string(ERR_get_error(), NULL)); |
3524 | | pkey = NULL; |
3525 | | } |
3526 | | |
3527 | | EVP_PKEY_CTX_free(ctx); |
3528 | | |
3529 | | return (struct crypto_ec_key *) pkey; |
3530 | | #else /* OpenSSL version >= 3.0 */ |
3531 | 0 | EVP_PKEY_CTX *kctx = NULL; |
3532 | 0 | EC_KEY *ec_params = NULL, *eckey; |
3533 | 0 | EVP_PKEY *params = NULL, *key = NULL; |
3534 | 0 | int nid; |
3535 | |
|
3536 | 0 | nid = crypto_ec_group_2_nid(group); |
3537 | 0 | if (nid < 0) { |
3538 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); |
3539 | 0 | return NULL; |
3540 | 0 | } |
3541 | | |
3542 | 0 | ec_params = EC_KEY_new_by_curve_name(nid); |
3543 | 0 | if (!ec_params) { |
3544 | 0 | wpa_printf(MSG_ERROR, |
3545 | 0 | "OpenSSL: Failed to generate EC_KEY parameters"); |
3546 | 0 | goto fail; |
3547 | 0 | } |
3548 | 0 | EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); |
3549 | 0 | params = EVP_PKEY_new(); |
3550 | 0 | if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { |
3551 | 0 | wpa_printf(MSG_ERROR, |
3552 | 0 | "OpenSSL: Failed to generate EVP_PKEY parameters"); |
3553 | 0 | goto fail; |
3554 | 0 | } |
3555 | | |
3556 | 0 | kctx = EVP_PKEY_CTX_new(params, NULL); |
3557 | 0 | if (!kctx || |
3558 | 0 | EVP_PKEY_keygen_init(kctx) != 1 || |
3559 | 0 | EVP_PKEY_keygen(kctx, &key) != 1) { |
3560 | 0 | wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC key"); |
3561 | 0 | key = NULL; |
3562 | 0 | goto fail; |
3563 | 0 | } |
3564 | | |
3565 | 0 | eckey = EVP_PKEY_get1_EC_KEY(key); |
3566 | 0 | if (!eckey) { |
3567 | 0 | key = NULL; |
3568 | 0 | goto fail; |
3569 | 0 | } |
3570 | 0 | EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); |
3571 | 0 | EC_KEY_free(eckey); |
3572 | |
|
3573 | 0 | fail: |
3574 | 0 | EC_KEY_free(ec_params); |
3575 | 0 | EVP_PKEY_free(params); |
3576 | 0 | EVP_PKEY_CTX_free(kctx); |
3577 | 0 | return (struct crypto_ec_key *) key; |
3578 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3579 | 0 | } |
3580 | | |
3581 | | |
3582 | | void crypto_ec_key_deinit(struct crypto_ec_key *key) |
3583 | 1.57k | { |
3584 | 1.57k | EVP_PKEY_free((EVP_PKEY *) key); |
3585 | 1.57k | } |
3586 | | |
3587 | | |
3588 | | #ifdef OPENSSL_IS_BORINGSSL |
3589 | | |
3590 | | /* BoringSSL version of i2d_PUBKEY() always outputs public EC key using |
3591 | | * uncompressed form so define a custom function to export EC pubkey using |
3592 | | * the compressed format that is explicitly required for some protocols. */ |
3593 | | |
3594 | | #include <openssl/asn1.h> |
3595 | | #include <openssl/asn1t.h> |
3596 | | |
3597 | | typedef struct { |
3598 | | /* AlgorithmIdentifier ecPublicKey with optional parameters present |
3599 | | * as an OID identifying the curve */ |
3600 | | X509_ALGOR *alg; |
3601 | | /* Compressed format public key per ANSI X9.63 */ |
3602 | | ASN1_BIT_STRING *pub_key; |
3603 | | } EC_COMP_PUBKEY; |
3604 | | |
3605 | | ASN1_SEQUENCE(EC_COMP_PUBKEY) = { |
3606 | | ASN1_SIMPLE(EC_COMP_PUBKEY, alg, X509_ALGOR), |
3607 | | ASN1_SIMPLE(EC_COMP_PUBKEY, pub_key, ASN1_BIT_STRING) |
3608 | | } ASN1_SEQUENCE_END(EC_COMP_PUBKEY); |
3609 | | |
3610 | | IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY); |
3611 | | |
3612 | | #endif /* OPENSSL_IS_BORINGSSL */ |
3613 | | |
3614 | | |
3615 | | struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) |
3616 | 0 | { |
3617 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
3618 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3619 | | OSSL_ENCODER_CTX *ctx; |
3620 | | int selection; |
3621 | | unsigned char *pdata = NULL; |
3622 | | size_t pdata_len = 0; |
3623 | | EVP_PKEY *copy = NULL; |
3624 | | struct wpabuf *buf = NULL; |
3625 | | |
3626 | | if (EVP_PKEY_get_ec_point_conv_form(pkey) != |
3627 | | POINT_CONVERSION_COMPRESSED) { |
3628 | | copy = EVP_PKEY_dup(pkey); |
3629 | | if (!copy) |
3630 | | return NULL; |
3631 | | if (EVP_PKEY_set_utf8_string_param( |
3632 | | copy, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, |
3633 | | OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED) != |
3634 | | 1) { |
3635 | | wpa_printf(MSG_INFO, |
3636 | | "OpenSSL: Failed to set compressed format"); |
3637 | | EVP_PKEY_free(copy); |
3638 | | return NULL; |
3639 | | } |
3640 | | pkey = copy; |
3641 | | } |
3642 | | |
3643 | | selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS | |
3644 | | OSSL_KEYMGMT_SELECT_PUBLIC_KEY; |
3645 | | |
3646 | | ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER", |
3647 | | "SubjectPublicKeyInfo", |
3648 | | NULL); |
3649 | | if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) { |
3650 | | wpa_printf(MSG_INFO, |
3651 | | "OpenSSL: Failed to encode SubjectPublicKeyInfo: %s", |
3652 | | ERR_error_string(ERR_get_error(), NULL)); |
3653 | | pdata = NULL; |
3654 | | } |
3655 | | OSSL_ENCODER_CTX_free(ctx); |
3656 | | if (pdata) { |
3657 | | buf = wpabuf_alloc_copy(pdata, pdata_len); |
3658 | | OPENSSL_free(pdata); |
3659 | | } |
3660 | | |
3661 | | EVP_PKEY_free(copy); |
3662 | | |
3663 | | return buf; |
3664 | | #else /* OpenSSL version >= 3.0 */ |
3665 | | #ifdef OPENSSL_IS_BORINGSSL |
3666 | | unsigned char *der = NULL; |
3667 | | int der_len; |
3668 | | const EC_KEY *eckey; |
3669 | | struct wpabuf *ret = NULL; |
3670 | | size_t len; |
3671 | | const EC_GROUP *group; |
3672 | | const EC_POINT *point; |
3673 | | BN_CTX *ctx; |
3674 | | EC_COMP_PUBKEY *pubkey = NULL; |
3675 | | int nid; |
3676 | | |
3677 | | ctx = BN_CTX_new(); |
3678 | | eckey = EVP_PKEY_get0_EC_KEY(pkey); |
3679 | | if (!ctx || !eckey) |
3680 | | goto fail; |
3681 | | |
3682 | | group = EC_KEY_get0_group(eckey); |
3683 | | point = EC_KEY_get0_public_key(eckey); |
3684 | | if (!group || !point) |
3685 | | goto fail; |
3686 | | nid = EC_GROUP_get_curve_name(group); |
3687 | | |
3688 | | pubkey = EC_COMP_PUBKEY_new(); |
3689 | | if (!pubkey || |
3690 | | X509_ALGOR_set0(pubkey->alg, OBJ_nid2obj(EVP_PKEY_EC), |
3691 | | V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) |
3692 | | goto fail; |
3693 | | |
3694 | | len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, |
3695 | | NULL, 0, ctx); |
3696 | | if (len == 0) |
3697 | | goto fail; |
3698 | | |
3699 | | der = OPENSSL_malloc(len); |
3700 | | if (!der) |
3701 | | goto fail; |
3702 | | len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, |
3703 | | der, len, ctx); |
3704 | | |
3705 | | OPENSSL_free(pubkey->pub_key->data); |
3706 | | pubkey->pub_key->data = der; |
3707 | | der = NULL; |
3708 | | pubkey->pub_key->length = len; |
3709 | | /* No unused bits */ |
3710 | | pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); |
3711 | | pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; |
3712 | | |
3713 | | der_len = i2d_EC_COMP_PUBKEY(pubkey, &der); |
3714 | | if (der_len <= 0) { |
3715 | | wpa_printf(MSG_ERROR, |
3716 | | "BoringSSL: Failed to build DER encoded public key"); |
3717 | | goto fail; |
3718 | | } |
3719 | | |
3720 | | ret = wpabuf_alloc_copy(der, der_len); |
3721 | | fail: |
3722 | | EC_COMP_PUBKEY_free(pubkey); |
3723 | | OPENSSL_free(der); |
3724 | | BN_CTX_free(ctx); |
3725 | | return ret; |
3726 | | #else /* OPENSSL_IS_BORINGSSL */ |
3727 | 0 | unsigned char *der = NULL; |
3728 | 0 | int der_len; |
3729 | 0 | struct wpabuf *buf; |
3730 | 0 | EC_KEY *eckey; |
3731 | |
|
3732 | 0 | eckey = EVP_PKEY_get1_EC_KEY(pkey); |
3733 | 0 | if (!eckey) |
3734 | 0 | return NULL; |
3735 | | |
3736 | | /* For now, all users expect COMPRESSED form */ |
3737 | 0 | EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); |
3738 | |
|
3739 | 0 | der_len = i2d_PUBKEY((EVP_PKEY *) key, &der); |
3740 | 0 | EC_KEY_free(eckey); |
3741 | 0 | if (der_len <= 0) { |
3742 | 0 | wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s", |
3743 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
3744 | 0 | return NULL; |
3745 | 0 | } |
3746 | | |
3747 | 0 | buf = wpabuf_alloc_copy(der, der_len); |
3748 | 0 | OPENSSL_free(der); |
3749 | 0 | return buf; |
3750 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
3751 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3752 | 0 | } |
3753 | | |
3754 | | |
3755 | | struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, |
3756 | | bool include_pub) |
3757 | 0 | { |
3758 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
3759 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3760 | | OSSL_ENCODER_CTX *ctx; |
3761 | | int selection; |
3762 | | unsigned char *pdata = NULL; |
3763 | | size_t pdata_len = 0; |
3764 | | struct wpabuf *buf; |
3765 | | EVP_PKEY *copy = NULL; |
3766 | | |
3767 | | selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS | |
3768 | | OSSL_KEYMGMT_SELECT_PRIVATE_KEY; |
3769 | | if (include_pub) { |
3770 | | selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; |
3771 | | } else { |
3772 | | /* Not including OSSL_KEYMGMT_SELECT_PUBLIC_KEY does not seem |
3773 | | * to really be sufficient, so clone the key and explicitly |
3774 | | * mark it not to include the public key. */ |
3775 | | copy = EVP_PKEY_dup(pkey); |
3776 | | if (!copy) |
3777 | | return NULL; |
3778 | | EVP_PKEY_set_int_param(copy, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, |
3779 | | 0); |
3780 | | pkey = copy; |
3781 | | } |
3782 | | |
3783 | | ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER", |
3784 | | "type-specific", NULL); |
3785 | | if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) { |
3786 | | wpa_printf(MSG_INFO, "OpenSSL: OSSL_ENCODER failed: %s", |
3787 | | ERR_error_string(ERR_get_error(), NULL)); |
3788 | | OSSL_ENCODER_CTX_free(ctx); |
3789 | | EVP_PKEY_free(copy); |
3790 | | return NULL; |
3791 | | } |
3792 | | OSSL_ENCODER_CTX_free(ctx); |
3793 | | buf = wpabuf_alloc_copy(pdata, pdata_len); |
3794 | | OPENSSL_free(pdata); |
3795 | | EVP_PKEY_free(copy); |
3796 | | return buf; |
3797 | | #else /* OpenSSL version >= 3.0 */ |
3798 | 0 | EC_KEY *eckey; |
3799 | 0 | unsigned char *der = NULL; |
3800 | 0 | int der_len; |
3801 | 0 | struct wpabuf *buf; |
3802 | 0 | unsigned int key_flags; |
3803 | |
|
3804 | 0 | eckey = EVP_PKEY_get1_EC_KEY(pkey); |
3805 | 0 | if (!eckey) |
3806 | 0 | return NULL; |
3807 | | |
3808 | 0 | key_flags = EC_KEY_get_enc_flags(eckey); |
3809 | 0 | if (include_pub) |
3810 | 0 | key_flags &= ~EC_PKEY_NO_PUBKEY; |
3811 | 0 | else |
3812 | 0 | key_flags |= EC_PKEY_NO_PUBKEY; |
3813 | 0 | EC_KEY_set_enc_flags(eckey, key_flags); |
3814 | |
|
3815 | 0 | EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); |
3816 | |
|
3817 | 0 | der_len = i2d_ECPrivateKey(eckey, &der); |
3818 | 0 | EC_KEY_free(eckey); |
3819 | 0 | if (der_len <= 0) |
3820 | 0 | return NULL; |
3821 | 0 | buf = wpabuf_alloc_copy(der, der_len); |
3822 | 0 | OPENSSL_free(der); |
3823 | |
|
3824 | 0 | return buf; |
3825 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3826 | 0 | } |
3827 | | |
3828 | | |
3829 | | struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, |
3830 | | int prefix) |
3831 | 0 | { |
3832 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
3833 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3834 | | struct wpabuf *buf; |
3835 | | unsigned char *pos; |
3836 | | size_t pub_len = OSSL_PARAM_UNMODIFIED; |
3837 | | |
3838 | | buf = NULL; |
3839 | | if (!EVP_PKEY_is_a(pkey, "EC") || |
3840 | | EVP_PKEY_get_octet_string_param(pkey, |
3841 | | OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, |
3842 | | NULL, 0, &pub_len) < 0 || |
3843 | | pub_len == OSSL_PARAM_UNMODIFIED || |
3844 | | !(buf = wpabuf_alloc(pub_len)) || |
3845 | | EVP_PKEY_get_octet_string_param(pkey, |
3846 | | OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, |
3847 | | wpabuf_put(buf, pub_len), |
3848 | | pub_len, NULL) != 1 || |
3849 | | wpabuf_head_u8(buf)[0] != 0x04) { |
3850 | | wpa_printf(MSG_INFO, |
3851 | | "OpenSSL: Failed to get encoded public key: %s", |
3852 | | ERR_error_string(ERR_get_error(), NULL)); |
3853 | | wpabuf_free(buf); |
3854 | | return NULL; |
3855 | | } |
3856 | | |
3857 | | if (!prefix) { |
3858 | | /* Remove 0x04 prefix if requested */ |
3859 | | pos = wpabuf_mhead(buf); |
3860 | | os_memmove(pos, pos + 1, pub_len - 1); |
3861 | | buf->used--; |
3862 | | } |
3863 | | |
3864 | | return buf; |
3865 | | #else /* OpenSSL version >= 3.0 */ |
3866 | 0 | int len, res; |
3867 | 0 | EC_KEY *eckey; |
3868 | 0 | struct wpabuf *buf; |
3869 | 0 | unsigned char *pos; |
3870 | |
|
3871 | 0 | eckey = EVP_PKEY_get1_EC_KEY(pkey); |
3872 | 0 | if (!eckey) |
3873 | 0 | return NULL; |
3874 | 0 | EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); |
3875 | 0 | len = i2o_ECPublicKey(eckey, NULL); |
3876 | 0 | if (len <= 0) { |
3877 | 0 | wpa_printf(MSG_ERROR, |
3878 | 0 | "OpenSSL: Failed to determine public key encoding length"); |
3879 | 0 | EC_KEY_free(eckey); |
3880 | 0 | return NULL; |
3881 | 0 | } |
3882 | | |
3883 | 0 | buf = wpabuf_alloc(len); |
3884 | 0 | if (!buf) { |
3885 | 0 | EC_KEY_free(eckey); |
3886 | 0 | return NULL; |
3887 | 0 | } |
3888 | | |
3889 | 0 | pos = wpabuf_put(buf, len); |
3890 | 0 | res = i2o_ECPublicKey(eckey, &pos); |
3891 | 0 | EC_KEY_free(eckey); |
3892 | 0 | if (res != len) { |
3893 | 0 | wpa_printf(MSG_ERROR, |
3894 | 0 | "OpenSSL: Failed to encode public key (res=%d/%d)", |
3895 | 0 | res, len); |
3896 | 0 | wpabuf_free(buf); |
3897 | 0 | return NULL; |
3898 | 0 | } |
3899 | | |
3900 | 0 | if (!prefix) { |
3901 | | /* Remove 0x04 prefix if requested */ |
3902 | 0 | pos = wpabuf_mhead(buf); |
3903 | 0 | os_memmove(pos, pos + 1, len - 1); |
3904 | 0 | buf->used--; |
3905 | 0 | } |
3906 | |
|
3907 | 0 | return buf; |
3908 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3909 | 0 | } |
3910 | | |
3911 | | |
3912 | | struct crypto_ec_point * |
3913 | | crypto_ec_key_get_public_key(struct crypto_ec_key *key) |
3914 | 0 | { |
3915 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
3916 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3917 | | char group[64]; |
3918 | | unsigned char pub[256]; |
3919 | | size_t len; |
3920 | | EC_POINT *point = NULL; |
3921 | | EC_GROUP *grp; |
3922 | | int res = 0; |
3923 | | OSSL_PARAM params[2]; |
3924 | | |
3925 | | if (!EVP_PKEY_is_a(pkey, "EC") || |
3926 | | EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, |
3927 | | group, sizeof(group), &len) != 1 || |
3928 | | EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, |
3929 | | pub, sizeof(pub), &len) != 1) |
3930 | | return NULL; |
3931 | | |
3932 | | params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, |
3933 | | group, 0); |
3934 | | params[1] = OSSL_PARAM_construct_end(); |
3935 | | grp = EC_GROUP_new_from_params(params, NULL, NULL); |
3936 | | if (!grp) |
3937 | | goto fail; |
3938 | | point = EC_POINT_new(grp); |
3939 | | if (!point) |
3940 | | goto fail; |
3941 | | res = EC_POINT_oct2point(grp, point, pub, len, NULL); |
3942 | | |
3943 | | fail: |
3944 | | if (res != 1) { |
3945 | | EC_POINT_free(point); |
3946 | | point = NULL; |
3947 | | } |
3948 | | |
3949 | | EC_GROUP_free(grp); |
3950 | | |
3951 | | return (struct crypto_ec_point *) point; |
3952 | | #else /* OpenSSL version >= 3.0 */ |
3953 | 0 | const EC_KEY *eckey; |
3954 | 0 | const EC_POINT *point; |
3955 | 0 | const EC_GROUP *group; |
3956 | |
|
3957 | 0 | eckey = EVP_PKEY_get0_EC_KEY(pkey); |
3958 | 0 | if (!eckey) |
3959 | 0 | return NULL; |
3960 | 0 | group = EC_KEY_get0_group(eckey); |
3961 | 0 | if (!group) |
3962 | 0 | return NULL; |
3963 | 0 | point = EC_KEY_get0_public_key(eckey); |
3964 | 0 | if (!point) |
3965 | 0 | return NULL; |
3966 | 0 | return (struct crypto_ec_point *) EC_POINT_dup(point, group); |
3967 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3968 | 0 | } |
3969 | | |
3970 | | |
3971 | | struct crypto_bignum * |
3972 | | crypto_ec_key_get_private_key(struct crypto_ec_key *key) |
3973 | 0 | { |
3974 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
3975 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
3976 | | BIGNUM *bn = NULL; |
3977 | | |
3978 | | if (!EVP_PKEY_is_a(pkey, "EC") || |
3979 | | EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &bn) != 1) |
3980 | | return NULL; |
3981 | | return (struct crypto_bignum *) bn; |
3982 | | #else /* OpenSSL version >= 3.0 */ |
3983 | 0 | const EC_KEY *eckey; |
3984 | 0 | const BIGNUM *bn; |
3985 | |
|
3986 | 0 | eckey = EVP_PKEY_get0_EC_KEY(pkey); |
3987 | 0 | if (!eckey) |
3988 | 0 | return NULL; |
3989 | 0 | bn = EC_KEY_get0_private_key(eckey); |
3990 | 0 | if (!bn) |
3991 | 0 | return NULL; |
3992 | 0 | return (struct crypto_bignum *) BN_dup(bn); |
3993 | 0 | #endif /* OpenSSL version >= 3.0 */ |
3994 | 0 | } |
3995 | | |
3996 | | |
3997 | | struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, |
3998 | | size_t len) |
3999 | 0 | { |
4000 | 0 | EVP_PKEY_CTX *pkctx; |
4001 | 0 | struct wpabuf *sig_der; |
4002 | 0 | size_t sig_len; |
4003 | |
|
4004 | 0 | sig_len = EVP_PKEY_size((EVP_PKEY *) key); |
4005 | 0 | sig_der = wpabuf_alloc(sig_len); |
4006 | 0 | if (!sig_der) |
4007 | 0 | return NULL; |
4008 | | |
4009 | 0 | pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL); |
4010 | 0 | if (!pkctx || |
4011 | 0 | EVP_PKEY_sign_init(pkctx) <= 0 || |
4012 | 0 | EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len, |
4013 | 0 | data, len) <= 0) { |
4014 | 0 | wpabuf_free(sig_der); |
4015 | 0 | sig_der = NULL; |
4016 | 0 | } else { |
4017 | 0 | wpabuf_put(sig_der, sig_len); |
4018 | 0 | } |
4019 | |
|
4020 | 0 | EVP_PKEY_CTX_free(pkctx); |
4021 | 0 | return sig_der; |
4022 | 0 | } |
4023 | | |
4024 | | |
4025 | | static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key) |
4026 | 0 | { |
4027 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4028 | | char gname[50]; |
4029 | | int nid; |
4030 | | EC_GROUP *group; |
4031 | | BIGNUM *prime = NULL; |
4032 | | int prime_len = -1; |
4033 | | |
4034 | | if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname), |
4035 | | NULL) != 1) |
4036 | | return -1; |
4037 | | nid = OBJ_txt2nid(gname); |
4038 | | group = EC_GROUP_new_by_curve_name(nid); |
4039 | | prime = BN_new(); |
4040 | | if (!group || !prime) |
4041 | | goto fail; |
4042 | | if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1) |
4043 | | prime_len = BN_num_bytes(prime); |
4044 | | fail: |
4045 | | EC_GROUP_free(group); |
4046 | | BN_free(prime); |
4047 | | return prime_len; |
4048 | | #else |
4049 | 0 | const EC_GROUP *group; |
4050 | 0 | const EC_KEY *eckey; |
4051 | 0 | BIGNUM *prime = NULL; |
4052 | 0 | int prime_len = -1; |
4053 | |
|
4054 | 0 | eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); |
4055 | 0 | if (!eckey) |
4056 | 0 | goto fail; |
4057 | 0 | group = EC_KEY_get0_group(eckey); |
4058 | 0 | prime = BN_new(); |
4059 | 0 | if (!prime || !group || |
4060 | 0 | !EC_GROUP_get_curve(group, prime, NULL, NULL, NULL)) |
4061 | 0 | goto fail; |
4062 | 0 | prime_len = BN_num_bytes(prime); |
4063 | 0 | fail: |
4064 | 0 | BN_free(prime); |
4065 | 0 | return prime_len; |
4066 | 0 | #endif |
4067 | 0 | } |
4068 | | |
4069 | | |
4070 | | struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, |
4071 | | const u8 *data, size_t len) |
4072 | 0 | { |
4073 | 0 | ECDSA_SIG *sig = NULL; |
4074 | 0 | const BIGNUM *r, *s; |
4075 | 0 | u8 *r_buf, *s_buf; |
4076 | 0 | struct wpabuf *buf; |
4077 | 0 | const unsigned char *p; |
4078 | 0 | int prime_len; |
4079 | |
|
4080 | 0 | prime_len = openssl_evp_pkey_ec_prime_len(key); |
4081 | 0 | if (prime_len < 0) |
4082 | 0 | return NULL; |
4083 | | |
4084 | 0 | buf = crypto_ec_key_sign(key, data, len); |
4085 | 0 | if (!buf) |
4086 | 0 | return NULL; |
4087 | | |
4088 | | /* Extract (r,s) from Ecdsa-Sig-Value */ |
4089 | | |
4090 | 0 | p = wpabuf_head(buf); |
4091 | 0 | sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf)); |
4092 | 0 | if (!sig) |
4093 | 0 | goto fail; |
4094 | 0 | ECDSA_SIG_get0(sig, &r, &s); |
4095 | | |
4096 | | /* Re-use wpabuf returned by crypto_ec_key_sign() */ |
4097 | 0 | buf->used = 0; |
4098 | 0 | r_buf = wpabuf_put(buf, prime_len); |
4099 | 0 | s_buf = wpabuf_put(buf, prime_len); |
4100 | 0 | if (crypto_bignum_to_bin((const struct crypto_bignum *) r, r_buf, |
4101 | 0 | prime_len, prime_len) < 0 || |
4102 | 0 | crypto_bignum_to_bin((const struct crypto_bignum *) s, s_buf, |
4103 | 0 | prime_len, prime_len) < 0) |
4104 | 0 | goto fail; |
4105 | | |
4106 | 0 | out: |
4107 | 0 | ECDSA_SIG_free(sig); |
4108 | 0 | return buf; |
4109 | 0 | fail: |
4110 | 0 | wpabuf_clear_free(buf); |
4111 | 0 | buf = NULL; |
4112 | 0 | goto out; |
4113 | 0 | } |
4114 | | |
4115 | | |
4116 | | int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, |
4117 | | size_t len, const u8 *sig, size_t sig_len) |
4118 | 0 | { |
4119 | 0 | EVP_PKEY_CTX *pkctx; |
4120 | 0 | int ret; |
4121 | |
|
4122 | 0 | pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL); |
4123 | 0 | if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) { |
4124 | 0 | EVP_PKEY_CTX_free(pkctx); |
4125 | 0 | return -1; |
4126 | 0 | } |
4127 | | |
4128 | 0 | ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len); |
4129 | 0 | EVP_PKEY_CTX_free(pkctx); |
4130 | 0 | if (ret == 1) |
4131 | 0 | return 1; /* signature ok */ |
4132 | 0 | if (ret == 0) |
4133 | 0 | return 0; /* incorrect signature */ |
4134 | 0 | return -1; |
4135 | 0 | } |
4136 | | |
4137 | | |
4138 | | int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, |
4139 | | const u8 *data, size_t len, |
4140 | | const u8 *r, size_t r_len, |
4141 | | const u8 *s, size_t s_len) |
4142 | 0 | { |
4143 | 0 | ECDSA_SIG *sig; |
4144 | 0 | BIGNUM *r_bn, *s_bn; |
4145 | 0 | unsigned char *der = NULL; |
4146 | 0 | int der_len; |
4147 | 0 | int ret = -1; |
4148 | |
|
4149 | 0 | r_bn = BN_bin2bn(r, r_len, NULL); |
4150 | 0 | s_bn = BN_bin2bn(s, s_len, NULL); |
4151 | 0 | sig = ECDSA_SIG_new(); |
4152 | 0 | if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1) |
4153 | 0 | goto fail; |
4154 | 0 | r_bn = NULL; |
4155 | 0 | s_bn = NULL; |
4156 | |
|
4157 | 0 | der_len = i2d_ECDSA_SIG(sig, &der); |
4158 | 0 | if (der_len <= 0) { |
4159 | 0 | wpa_printf(MSG_DEBUG, |
4160 | 0 | "OpenSSL: Could not DER encode signature"); |
4161 | 0 | goto fail; |
4162 | 0 | } |
4163 | | |
4164 | 0 | ret = crypto_ec_key_verify_signature(key, data, len, der, der_len); |
4165 | |
|
4166 | 0 | fail: |
4167 | 0 | OPENSSL_free(der); |
4168 | 0 | BN_free(r_bn); |
4169 | 0 | BN_free(s_bn); |
4170 | 0 | ECDSA_SIG_free(sig); |
4171 | 0 | return ret; |
4172 | 0 | } |
4173 | | |
4174 | | |
4175 | | int crypto_ec_key_group(struct crypto_ec_key *key) |
4176 | 59 | { |
4177 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4178 | | char gname[50]; |
4179 | | int nid; |
4180 | | |
4181 | | if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname), |
4182 | | NULL) != 1) |
4183 | | return -1; |
4184 | | nid = OBJ_txt2nid(gname); |
4185 | | #else |
4186 | 59 | const EC_KEY *eckey; |
4187 | 59 | const EC_GROUP *group; |
4188 | 59 | int nid; |
4189 | | |
4190 | 59 | eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); |
4191 | 59 | if (!eckey) |
4192 | 0 | return -1; |
4193 | 59 | group = EC_KEY_get0_group(eckey); |
4194 | 59 | if (!group) |
4195 | 0 | return -1; |
4196 | 59 | nid = EC_GROUP_get_curve_name(group); |
4197 | 59 | #endif |
4198 | 59 | switch (nid) { |
4199 | 43 | case NID_X9_62_prime256v1: |
4200 | 43 | return 19; |
4201 | 0 | case NID_secp384r1: |
4202 | 0 | return 20; |
4203 | 0 | case NID_secp521r1: |
4204 | 0 | return 21; |
4205 | 0 | #ifdef NID_brainpoolP256r1 |
4206 | 0 | case NID_brainpoolP256r1: |
4207 | 0 | return 28; |
4208 | 0 | #endif /* NID_brainpoolP256r1 */ |
4209 | 0 | #ifdef NID_brainpoolP384r1 |
4210 | 0 | case NID_brainpoolP384r1: |
4211 | 0 | return 29; |
4212 | 0 | #endif /* NID_brainpoolP384r1 */ |
4213 | 0 | #ifdef NID_brainpoolP512r1 |
4214 | 0 | case NID_brainpoolP512r1: |
4215 | 0 | return 30; |
4216 | 0 | #endif /* NID_brainpoolP512r1 */ |
4217 | 16 | default: |
4218 | 16 | wpa_printf(MSG_ERROR, |
4219 | 16 | "OpenSSL: Unsupported curve (nid=%d) in EC key", |
4220 | 16 | nid); |
4221 | 16 | return -1; |
4222 | 59 | } |
4223 | 59 | } |
4224 | | |
4225 | | |
4226 | | int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2) |
4227 | 0 | { |
4228 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4229 | | if (EVP_PKEY_eq((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1) |
4230 | | return -1; |
4231 | | #else |
4232 | 0 | if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1) |
4233 | 0 | return -1; |
4234 | 0 | #endif |
4235 | 0 | return 0; |
4236 | 0 | } |
4237 | | |
4238 | | |
4239 | | void crypto_ec_key_debug_print(const struct crypto_ec_key *key, |
4240 | | const char *title) |
4241 | 0 | { |
4242 | 0 | BIO *out; |
4243 | 0 | size_t rlen; |
4244 | 0 | char *txt; |
4245 | 0 | int res; |
4246 | |
|
4247 | 0 | out = BIO_new(BIO_s_mem()); |
4248 | 0 | if (!out) |
4249 | 0 | return; |
4250 | | |
4251 | 0 | EVP_PKEY_print_private(out, (EVP_PKEY *) key, 0, NULL); |
4252 | 0 | rlen = BIO_ctrl_pending(out); |
4253 | 0 | txt = os_malloc(rlen + 1); |
4254 | 0 | if (txt) { |
4255 | 0 | res = BIO_read(out, txt, rlen); |
4256 | 0 | if (res > 0) { |
4257 | 0 | txt[res] = '\0'; |
4258 | 0 | wpa_printf(MSG_DEBUG, "%s: %s", title, txt); |
4259 | 0 | } |
4260 | 0 | os_free(txt); |
4261 | 0 | } |
4262 | 0 | BIO_free(out); |
4263 | 0 | } |
4264 | | |
4265 | | |
4266 | | struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7) |
4267 | 0 | { |
4268 | | #ifdef OPENSSL_IS_BORINGSSL |
4269 | | CBS pkcs7_cbs; |
4270 | | #else /* OPENSSL_IS_BORINGSSL */ |
4271 | 0 | PKCS7 *p7 = NULL; |
4272 | 0 | const unsigned char *p = wpabuf_head(pkcs7); |
4273 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
4274 | 0 | STACK_OF(X509) *certs; |
4275 | 0 | int i, num; |
4276 | 0 | BIO *out = NULL; |
4277 | 0 | size_t rlen; |
4278 | 0 | struct wpabuf *pem = NULL; |
4279 | 0 | int res; |
4280 | |
|
4281 | | #ifdef OPENSSL_IS_BORINGSSL |
4282 | | certs = sk_X509_new_null(); |
4283 | | if (!certs) |
4284 | | goto fail; |
4285 | | CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7)); |
4286 | | if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { |
4287 | | wpa_printf(MSG_INFO, |
4288 | | "OpenSSL: Could not parse PKCS#7 object: %s", |
4289 | | ERR_error_string(ERR_get_error(), NULL)); |
4290 | | goto fail; |
4291 | | } |
4292 | | #else /* OPENSSL_IS_BORINGSSL */ |
4293 | 0 | p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7)); |
4294 | 0 | if (!p7) { |
4295 | 0 | wpa_printf(MSG_INFO, |
4296 | 0 | "OpenSSL: Could not parse PKCS#7 object: %s", |
4297 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
4298 | 0 | goto fail; |
4299 | 0 | } |
4300 | | |
4301 | 0 | switch (OBJ_obj2nid(p7->type)) { |
4302 | 0 | case NID_pkcs7_signed: |
4303 | 0 | certs = p7->d.sign->cert; |
4304 | 0 | break; |
4305 | 0 | case NID_pkcs7_signedAndEnveloped: |
4306 | 0 | certs = p7->d.signed_and_enveloped->cert; |
4307 | 0 | break; |
4308 | 0 | default: |
4309 | 0 | certs = NULL; |
4310 | 0 | break; |
4311 | 0 | } |
4312 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
4313 | | |
4314 | 0 | if (!certs || ((num = sk_X509_num(certs)) == 0)) { |
4315 | 0 | wpa_printf(MSG_INFO, |
4316 | 0 | "OpenSSL: No certificates found in PKCS#7 object"); |
4317 | 0 | goto fail; |
4318 | 0 | } |
4319 | | |
4320 | 0 | out = BIO_new(BIO_s_mem()); |
4321 | 0 | if (!out) |
4322 | 0 | goto fail; |
4323 | | |
4324 | 0 | for (i = 0; i < num; i++) { |
4325 | 0 | X509 *cert = sk_X509_value(certs, i); |
4326 | |
|
4327 | 0 | PEM_write_bio_X509(out, cert); |
4328 | 0 | } |
4329 | |
|
4330 | 0 | rlen = BIO_ctrl_pending(out); |
4331 | 0 | pem = wpabuf_alloc(rlen); |
4332 | 0 | if (!pem) |
4333 | 0 | goto fail; |
4334 | 0 | res = BIO_read(out, wpabuf_put(pem, 0), rlen); |
4335 | 0 | if (res <= 0) { |
4336 | 0 | wpabuf_free(pem); |
4337 | 0 | pem = NULL; |
4338 | 0 | goto fail; |
4339 | 0 | } |
4340 | 0 | wpabuf_put(pem, res); |
4341 | |
|
4342 | 0 | fail: |
4343 | | #ifdef OPENSSL_IS_BORINGSSL |
4344 | | if (certs) |
4345 | | sk_X509_pop_free(certs, X509_free); |
4346 | | #else /* OPENSSL_IS_BORINGSSL */ |
4347 | 0 | PKCS7_free(p7); |
4348 | 0 | #endif /* OPENSSL_IS_BORINGSSL */ |
4349 | 0 | if (out) |
4350 | 0 | BIO_free_all(out); |
4351 | |
|
4352 | 0 | return pem; |
4353 | 0 | } |
4354 | | |
4355 | | |
4356 | | struct crypto_csr * crypto_csr_init(void) |
4357 | 0 | { |
4358 | 0 | return (struct crypto_csr *)X509_REQ_new(); |
4359 | 0 | } |
4360 | | |
4361 | | |
4362 | | struct crypto_csr * crypto_csr_verify(const struct wpabuf *req) |
4363 | 0 | { |
4364 | 0 | X509_REQ *csr; |
4365 | 0 | EVP_PKEY *pkey = NULL; |
4366 | 0 | const u8 *der = wpabuf_head(req); |
4367 | |
|
4368 | 0 | csr = d2i_X509_REQ(NULL, &der, wpabuf_len(req)); |
4369 | 0 | if (!csr) |
4370 | 0 | return NULL; |
4371 | | |
4372 | 0 | pkey = X509_REQ_get_pubkey((X509_REQ *)csr); |
4373 | 0 | if (!pkey) |
4374 | 0 | goto fail; |
4375 | | |
4376 | 0 | if (X509_REQ_verify((X509_REQ *)csr, pkey) != 1) |
4377 | 0 | goto fail; |
4378 | | |
4379 | 0 | return (struct crypto_csr *)csr; |
4380 | 0 | fail: |
4381 | 0 | X509_REQ_free(csr); |
4382 | 0 | return NULL; |
4383 | 0 | } |
4384 | | |
4385 | | |
4386 | | void crypto_csr_deinit(struct crypto_csr *csr) |
4387 | 0 | { |
4388 | 0 | X509_REQ_free((X509_REQ *)csr); |
4389 | 0 | } |
4390 | | |
4391 | | |
4392 | | int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key) |
4393 | 0 | { |
4394 | 0 | if (!X509_REQ_set_pubkey((X509_REQ *)csr, (EVP_PKEY *)key)) |
4395 | 0 | return -1; |
4396 | | |
4397 | 0 | return 0; |
4398 | 0 | } |
4399 | | |
4400 | | |
4401 | | int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type, |
4402 | | const char *name) |
4403 | 0 | { |
4404 | 0 | X509_NAME *n; |
4405 | 0 | int nid; |
4406 | |
|
4407 | 0 | switch (type) { |
4408 | 0 | case CSR_NAME_CN: |
4409 | 0 | nid = NID_commonName; |
4410 | 0 | break; |
4411 | 0 | case CSR_NAME_SN: |
4412 | 0 | nid = NID_surname; |
4413 | 0 | break; |
4414 | 0 | case CSR_NAME_C: |
4415 | 0 | nid = NID_countryName; |
4416 | 0 | break; |
4417 | 0 | case CSR_NAME_O: |
4418 | 0 | nid = NID_organizationName; |
4419 | 0 | break; |
4420 | 0 | case CSR_NAME_OU: |
4421 | 0 | nid = NID_organizationalUnitName; |
4422 | 0 | break; |
4423 | 0 | default: |
4424 | 0 | return -1; |
4425 | 0 | } |
4426 | | |
4427 | 0 | n = X509_REQ_get_subject_name((X509_REQ *) csr); |
4428 | 0 | if (!n) |
4429 | 0 | return -1; |
4430 | | |
4431 | | #if OPENSSL_VERSION_NUMBER < 0x10100000L |
4432 | | if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8, |
4433 | | (unsigned char *) name, |
4434 | | os_strlen(name), -1, 0)) |
4435 | | return -1; |
4436 | | #else |
4437 | 0 | if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8, |
4438 | 0 | (const unsigned char *) name, |
4439 | 0 | os_strlen(name), -1, 0)) |
4440 | 0 | return -1; |
4441 | 0 | #endif |
4442 | | |
4443 | 0 | return 0; |
4444 | 0 | } |
4445 | | |
4446 | | |
4447 | | int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, |
4448 | | int attr_type, const u8 *value, size_t len) |
4449 | 0 | { |
4450 | 0 | int nid; |
4451 | |
|
4452 | 0 | switch (attr) { |
4453 | 0 | case CSR_ATTR_CHALLENGE_PASSWORD: |
4454 | 0 | nid = NID_pkcs9_challengePassword; |
4455 | 0 | break; |
4456 | 0 | default: |
4457 | 0 | return -1; |
4458 | 0 | } |
4459 | | |
4460 | 0 | if (!X509_REQ_add1_attr_by_NID((X509_REQ *) csr, nid, attr_type, value, |
4461 | 0 | len)) |
4462 | 0 | return -1; |
4463 | | |
4464 | 0 | return 0; |
4465 | 0 | } |
4466 | | |
4467 | | |
4468 | | const u8 * crypto_csr_get_attribute(struct crypto_csr *csr, |
4469 | | enum crypto_csr_attr attr, |
4470 | | size_t *len, int *type) |
4471 | 0 | { |
4472 | 0 | X509_ATTRIBUTE *attrib; |
4473 | 0 | ASN1_TYPE *attrib_type; |
4474 | 0 | ASN1_STRING *data; |
4475 | 0 | int loc; |
4476 | 0 | int nid; |
4477 | |
|
4478 | 0 | switch (attr) { |
4479 | 0 | case CSR_ATTR_CHALLENGE_PASSWORD: |
4480 | 0 | nid = NID_pkcs9_challengePassword; |
4481 | 0 | break; |
4482 | 0 | default: |
4483 | 0 | return NULL; |
4484 | 0 | } |
4485 | | |
4486 | 0 | loc = X509_REQ_get_attr_by_NID((X509_REQ *) csr, nid, -1); |
4487 | 0 | if (loc < 0) |
4488 | 0 | return NULL; |
4489 | | |
4490 | 0 | attrib = X509_REQ_get_attr((X509_REQ *) csr, loc); |
4491 | 0 | if (!attrib) |
4492 | 0 | return NULL; |
4493 | | |
4494 | 0 | attrib_type = X509_ATTRIBUTE_get0_type(attrib, 0); |
4495 | 0 | if (!attrib_type) |
4496 | 0 | return NULL; |
4497 | 0 | *type = ASN1_TYPE_get(attrib_type); |
4498 | 0 | data = X509_ATTRIBUTE_get0_data(attrib, 0, *type, NULL); |
4499 | 0 | if (!data) |
4500 | 0 | return NULL; |
4501 | 0 | *len = ASN1_STRING_length(data); |
4502 | 0 | return ASN1_STRING_get0_data(data); |
4503 | 0 | } |
4504 | | |
4505 | | |
4506 | | struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, |
4507 | | struct crypto_ec_key *key, |
4508 | | enum crypto_hash_alg algo) |
4509 | 0 | { |
4510 | 0 | const EVP_MD *sign_md; |
4511 | 0 | struct wpabuf *buf; |
4512 | 0 | unsigned char *der = NULL; |
4513 | 0 | int der_len; |
4514 | |
|
4515 | 0 | switch (algo) { |
4516 | 0 | case CRYPTO_HASH_ALG_SHA256: |
4517 | 0 | sign_md = EVP_sha256(); |
4518 | 0 | break; |
4519 | 0 | case CRYPTO_HASH_ALG_SHA384: |
4520 | 0 | sign_md = EVP_sha384(); |
4521 | 0 | break; |
4522 | 0 | case CRYPTO_HASH_ALG_SHA512: |
4523 | 0 | sign_md = EVP_sha512(); |
4524 | 0 | break; |
4525 | 0 | default: |
4526 | 0 | return NULL; |
4527 | 0 | } |
4528 | | |
4529 | 0 | if (!X509_REQ_sign((X509_REQ *) csr, (EVP_PKEY *) key, sign_md)) |
4530 | 0 | return NULL; |
4531 | | |
4532 | 0 | der_len = i2d_X509_REQ((X509_REQ *) csr, &der); |
4533 | 0 | if (der_len < 0) |
4534 | 0 | return NULL; |
4535 | | |
4536 | 0 | buf = wpabuf_alloc_copy(der, der_len); |
4537 | 0 | OPENSSL_free(der); |
4538 | |
|
4539 | 0 | return buf; |
4540 | 0 | } |
4541 | | |
4542 | | #endif /* CONFIG_ECC */ |
4543 | | |
4544 | | |
4545 | | static EVP_PKEY * crypto_rsa_key_read_public(FILE *f) |
4546 | 0 | { |
4547 | 0 | EVP_PKEY *pkey; |
4548 | 0 | X509 *x509; |
4549 | 0 | const ASN1_TIME *not_before, *not_after; |
4550 | 0 | int res_before, res_after; |
4551 | |
|
4552 | 0 | pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL); |
4553 | 0 | if (pkey) |
4554 | 0 | return pkey; |
4555 | | |
4556 | 0 | rewind(f); |
4557 | 0 | x509 = PEM_read_X509(f, NULL, NULL, NULL); |
4558 | 0 | if (!x509) |
4559 | 0 | return NULL; |
4560 | | |
4561 | 0 | not_before = X509_get0_notBefore(x509); |
4562 | 0 | not_after = X509_get0_notAfter(x509); |
4563 | 0 | if (!not_before || !not_after) |
4564 | 0 | goto fail; |
4565 | 0 | res_before = X509_cmp_current_time(not_before); |
4566 | 0 | res_after = X509_cmp_current_time(not_after); |
4567 | 0 | if (!res_before || !res_after) |
4568 | 0 | goto fail; |
4569 | 0 | if (res_before > 0 || res_after < 0) { |
4570 | 0 | wpa_printf(MSG_INFO, |
4571 | 0 | "OpenSSL: Certificate for RSA public key is not valid at this time (%d %d)", |
4572 | 0 | res_before, res_after); |
4573 | 0 | goto fail; |
4574 | 0 | } |
4575 | | |
4576 | 0 | pkey = X509_get_pubkey(x509); |
4577 | 0 | X509_free(x509); |
4578 | |
|
4579 | 0 | if (!pkey) |
4580 | 0 | return NULL; |
4581 | 0 | if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { |
4582 | 0 | wpa_printf(MSG_INFO, "OpenSSL: No RSA public key found"); |
4583 | 0 | EVP_PKEY_free(pkey); |
4584 | 0 | return NULL; |
4585 | 0 | } |
4586 | | |
4587 | 0 | return pkey; |
4588 | 0 | fail: |
4589 | 0 | X509_free(x509); |
4590 | 0 | return NULL; |
4591 | 0 | } |
4592 | | |
4593 | | |
4594 | | struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key) |
4595 | 0 | { |
4596 | 0 | FILE *f; |
4597 | 0 | EVP_PKEY *pkey; |
4598 | |
|
4599 | 0 | f = fopen(file, "r"); |
4600 | 0 | if (!f) |
4601 | 0 | return NULL; |
4602 | 0 | if (private_key) |
4603 | 0 | pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); |
4604 | 0 | else |
4605 | 0 | pkey = crypto_rsa_key_read_public(f); |
4606 | 0 | fclose(f); |
4607 | 0 | return (struct crypto_rsa_key *) pkey; |
4608 | 0 | } |
4609 | | |
4610 | | |
4611 | | #ifndef OPENSSL_NO_SHA256 |
4612 | | |
4613 | | struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, |
4614 | | const struct wpabuf *in) |
4615 | 0 | { |
4616 | 0 | #if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L |
4617 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
4618 | 0 | EVP_PKEY_CTX *pkctx; |
4619 | 0 | struct wpabuf *res = NULL; |
4620 | 0 | size_t outlen; |
4621 | |
|
4622 | 0 | pkctx = EVP_PKEY_CTX_new(pkey, NULL); |
4623 | 0 | if (!pkctx) |
4624 | 0 | goto fail; |
4625 | | |
4626 | 0 | if (EVP_PKEY_encrypt_init(pkctx) != 1 || |
4627 | 0 | EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 || |
4628 | 0 | EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 || |
4629 | 0 | EVP_PKEY_encrypt(pkctx, NULL, &outlen, wpabuf_head(in), |
4630 | 0 | wpabuf_len(in)) != 1 || |
4631 | 0 | !(res = wpabuf_alloc(outlen)) || |
4632 | 0 | EVP_PKEY_encrypt(pkctx, wpabuf_put(res, 0), &outlen, |
4633 | 0 | wpabuf_head(in), wpabuf_len(in)) != 1) { |
4634 | 0 | wpabuf_free(res); |
4635 | 0 | res = NULL; |
4636 | 0 | goto fail; |
4637 | 0 | } |
4638 | 0 | wpabuf_put(res, outlen); |
4639 | |
|
4640 | 0 | fail: |
4641 | 0 | EVP_PKEY_CTX_free(pkctx); |
4642 | 0 | return res; |
4643 | | #else |
4644 | | wpa_printf(MSG_ERROR, "%s() not supported", __func__); |
4645 | | return NULL; |
4646 | | #endif |
4647 | 0 | } |
4648 | | |
4649 | | |
4650 | | struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, |
4651 | | const struct wpabuf *in) |
4652 | 0 | { |
4653 | 0 | #if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L |
4654 | 0 | EVP_PKEY *pkey = (EVP_PKEY *) key; |
4655 | 0 | EVP_PKEY_CTX *pkctx; |
4656 | 0 | struct wpabuf *res = NULL; |
4657 | 0 | size_t outlen; |
4658 | |
|
4659 | 0 | pkctx = EVP_PKEY_CTX_new(pkey, NULL); |
4660 | 0 | if (!pkctx) |
4661 | 0 | goto fail; |
4662 | | |
4663 | 0 | if (EVP_PKEY_decrypt_init(pkctx) != 1 || |
4664 | 0 | EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 || |
4665 | 0 | EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 || |
4666 | 0 | EVP_PKEY_decrypt(pkctx, NULL, &outlen, wpabuf_head(in), |
4667 | 0 | wpabuf_len(in)) != 1 || |
4668 | 0 | !(res = wpabuf_alloc(outlen)) || |
4669 | 0 | EVP_PKEY_decrypt(pkctx, wpabuf_put(res, 0), &outlen, |
4670 | 0 | wpabuf_head(in), wpabuf_len(in)) != 1) { |
4671 | 0 | wpabuf_free(res); |
4672 | 0 | res = NULL; |
4673 | 0 | goto fail; |
4674 | 0 | } |
4675 | 0 | wpabuf_put(res, outlen); |
4676 | |
|
4677 | 0 | fail: |
4678 | 0 | EVP_PKEY_CTX_free(pkctx); |
4679 | 0 | return res; |
4680 | | #else |
4681 | | wpa_printf(MSG_ERROR, "%s() not supported", __func__); |
4682 | | return NULL; |
4683 | | #endif |
4684 | 0 | } |
4685 | | |
4686 | | #endif /* OPENSSL_NO_SHA256 */ |
4687 | | |
4688 | | |
4689 | | void crypto_rsa_key_free(struct crypto_rsa_key *key) |
4690 | 0 | { |
4691 | 0 | EVP_PKEY_free((EVP_PKEY *) key); |
4692 | 0 | } |
4693 | | |
4694 | | |
4695 | | #ifdef CONFIG_DPP3 |
4696 | | |
4697 | | #define HPKE_MAX_SHARED_SECRET_LEN 66 |
4698 | | #define HPKE_MAX_HASH_LEN 64 |
4699 | | #define HPKE_MAX_KEY_LEN 32 |
4700 | | #define HPKE_MAX_NONCE_LEN 12 |
4701 | | #define HPKE_MAX_PUB_LEN (1 + 2 * 66) |
4702 | | |
4703 | | struct hpke_context { |
4704 | | /* KEM */ |
4705 | | enum hpke_kem_id kem_id; |
4706 | | int kem_nid; |
4707 | | int iana_group; |
4708 | | size_t n_pk; |
4709 | | size_t n_secret; |
4710 | | const EVP_MD *kem_h; |
4711 | | size_t kem_n_h; |
4712 | | |
4713 | | /* KDF */ |
4714 | | enum hpke_kdf_id kdf_id; |
4715 | | const EVP_MD *kdf_h; |
4716 | | size_t n_h; |
4717 | | |
4718 | | /* AEAD */ |
4719 | | enum hpke_aead_id aead_id; |
4720 | | const EVP_CIPHER *cipher; |
4721 | | size_t n_k; |
4722 | | size_t n_n; |
4723 | | size_t n_t; |
4724 | | u8 key[HPKE_MAX_KEY_LEN]; |
4725 | | u8 base_nonce[HPKE_MAX_NONCE_LEN]; |
4726 | | }; |
4727 | | |
4728 | | |
4729 | | static void hpke_free_context(struct hpke_context *ctx) |
4730 | | { |
4731 | | bin_clear_free(ctx, sizeof(*ctx)); |
4732 | | } |
4733 | | |
4734 | | |
4735 | | static struct hpke_context * hpke_get_context(enum hpke_kem_id kem_id, |
4736 | | enum hpke_kdf_id kdf_id, |
4737 | | enum hpke_aead_id aead_id, |
4738 | | struct crypto_ec_key *key) |
4739 | | { |
4740 | | struct hpke_context *ctx; |
4741 | | int group; |
4742 | | |
4743 | | ctx = os_zalloc(sizeof(*ctx)); |
4744 | | if (!ctx) |
4745 | | return NULL; |
4746 | | |
4747 | | ctx->kem_id = kem_id; |
4748 | | switch (kem_id) { |
4749 | | case HPKE_DHKEM_P256_HKDF_SHA256: |
4750 | | ctx->kem_nid = NID_X9_62_prime256v1; |
4751 | | ctx->iana_group = 19; |
4752 | | ctx->n_pk = 65; |
4753 | | ctx->n_secret = 32; |
4754 | | ctx->kem_h = EVP_sha256(); |
4755 | | ctx->kem_n_h = 32; |
4756 | | break; |
4757 | | case HPKE_DHKEM_P384_HKDF_SHA384: |
4758 | | ctx->kem_nid = NID_secp384r1; |
4759 | | ctx->iana_group = 20; |
4760 | | ctx->n_pk = 97; |
4761 | | ctx->n_secret = 48; |
4762 | | ctx->kem_h = EVP_sha384(); |
4763 | | ctx->kem_n_h = 48; |
4764 | | break; |
4765 | | case HPKE_DHKEM_P521_HKDF_SHA512: |
4766 | | ctx->kem_nid = NID_secp521r1; |
4767 | | ctx->iana_group = 21; |
4768 | | ctx->n_pk = 133; |
4769 | | ctx->n_secret = 64; |
4770 | | ctx->kem_h = EVP_sha512(); |
4771 | | ctx->kem_n_h = 64; |
4772 | | break; |
4773 | | default: |
4774 | | goto fail; |
4775 | | } |
4776 | | |
4777 | | ctx->kdf_id = kdf_id; |
4778 | | switch (kdf_id) { |
4779 | | case HPKE_KDF_HKDF_SHA256: |
4780 | | ctx->kdf_h = EVP_sha256(); |
4781 | | ctx->n_h = 32; |
4782 | | break; |
4783 | | case HPKE_KDF_HKDF_SHA384: |
4784 | | ctx->kdf_h = EVP_sha384(); |
4785 | | ctx->n_h = 48; |
4786 | | break; |
4787 | | case HPKE_KDF_HKDF_SHA512: |
4788 | | ctx->kdf_h = EVP_sha512(); |
4789 | | ctx->n_h = 64; |
4790 | | break; |
4791 | | default: |
4792 | | goto fail; |
4793 | | } |
4794 | | |
4795 | | ctx->aead_id = aead_id; |
4796 | | switch (aead_id) { |
4797 | | case HPKE_AEAD_AES_128_GCM: |
4798 | | ctx->cipher = EVP_aes_128_gcm(); |
4799 | | ctx->n_k = 16; |
4800 | | ctx->n_n = 12; |
4801 | | ctx->n_t = 16; |
4802 | | break; |
4803 | | case HPKE_AEAD_AES_256_GCM: |
4804 | | ctx->cipher = EVP_aes_256_gcm(); |
4805 | | ctx->n_k = 32; |
4806 | | ctx->n_n = 12; |
4807 | | ctx->n_t = 16; |
4808 | | break; |
4809 | | default: |
4810 | | goto fail; |
4811 | | } |
4812 | | |
4813 | | /* Convert BP-256/384/512 to P-256/384/521 for DPP */ |
4814 | | group = crypto_ec_key_group(key); |
4815 | | if (group == 28 && ctx->iana_group == 19) { |
4816 | | ctx->iana_group = 28; |
4817 | | } else if (group == 29 && ctx->iana_group == 20) { |
4818 | | ctx->iana_group = 29; |
4819 | | } else if (group == 30 && ctx->iana_group == 21) { |
4820 | | ctx->iana_group = 30; |
4821 | | ctx->n_pk = 129; |
4822 | | } |
4823 | | if (group != ctx->iana_group) { |
4824 | | wpa_printf(MSG_INFO, "OpenSSL:%s:group mismatch (%d != %d)", |
4825 | | __func__, group, ctx->iana_group); |
4826 | | goto fail; |
4827 | | } |
4828 | | |
4829 | | return ctx; |
4830 | | fail: |
4831 | | hpke_free_context(ctx); |
4832 | | return NULL; |
4833 | | } |
4834 | | |
4835 | | |
4836 | | static size_t hpke_suite_id(struct hpke_context *ctx, bool kem, u8 *suite_id) |
4837 | | { |
4838 | | size_t suite_id_len; |
4839 | | |
4840 | | if (kem) { |
4841 | | os_memcpy(suite_id, "KEM", 3); |
4842 | | WPA_PUT_BE16(&suite_id[3], ctx->kem_id); |
4843 | | suite_id_len = 5; |
4844 | | } else { |
4845 | | os_memcpy(suite_id, "HPKE", 4); |
4846 | | WPA_PUT_BE16(&suite_id[4], ctx->kem_id); |
4847 | | WPA_PUT_BE16(&suite_id[6], ctx->kdf_id); |
4848 | | WPA_PUT_BE16(&suite_id[8], ctx->aead_id); |
4849 | | suite_id_len = 10; |
4850 | | } |
4851 | | return suite_id_len; |
4852 | | } |
4853 | | |
4854 | | |
4855 | | static int hpke_labeled_extract(struct hpke_context *ctx, bool kem, |
4856 | | const u8 *salt, size_t salt_len, |
4857 | | const char *label, |
4858 | | const u8 *ikm, size_t ikm_len, u8 *prk) |
4859 | | { |
4860 | | u8 zero[HPKE_MAX_HASH_LEN]; |
4861 | | u8 suite_id[10]; |
4862 | | size_t suite_id_len; |
4863 | | unsigned int mdlen = kem ? ctx->kem_n_h : ctx->n_h; |
4864 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4865 | | EVP_MAC *hmac; |
4866 | | OSSL_PARAM params[2]; |
4867 | | EVP_MAC_CTX *hctx; |
4868 | | size_t mlen; |
4869 | | int res; |
4870 | | #else /* OpenSSL version >= 3.0 */ |
4871 | | HMAC_CTX *hctx; |
4872 | | int res; |
4873 | | #endif /* OpenSSL version >= 3.0 */ |
4874 | | |
4875 | | if (!salt || !salt_len) { |
4876 | | salt_len = mdlen; |
4877 | | os_memset(zero, 0, salt_len); |
4878 | | salt = zero; |
4879 | | } |
4880 | | |
4881 | | suite_id_len = hpke_suite_id(ctx, kem, suite_id); |
4882 | | |
4883 | | /* labeled_ikm = concat("HPKE-v1", suite_id, label, ikm) |
4884 | | * return Extract(salt, labeled_ikm) */ |
4885 | | |
4886 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4887 | | hmac = EVP_MAC_fetch(NULL, "HMAC", NULL); |
4888 | | if (!hmac) |
4889 | | return -1; |
4890 | | |
4891 | | params[0] = OSSL_PARAM_construct_utf8_string( |
4892 | | "digest", |
4893 | | (char *) EVP_MD_get0_name(kem ? ctx->kem_h : ctx->kdf_h), 0); |
4894 | | params[1] = OSSL_PARAM_construct_end(); |
4895 | | |
4896 | | hctx = EVP_MAC_CTX_new(hmac); |
4897 | | EVP_MAC_free(hmac); |
4898 | | if (!hctx) |
4899 | | return -1; |
4900 | | |
4901 | | if (EVP_MAC_init(hctx, salt, salt_len, params) != 1) { |
4902 | | wpa_printf(MSG_INFO, |
4903 | | "OpenSSL: EVP_MAC_init(hmac,digest/HPKE) failed: %s", |
4904 | | ERR_error_string(ERR_get_error(), NULL)); |
4905 | | goto fail; |
4906 | | } |
4907 | | |
4908 | | if (EVP_MAC_update(hctx, (const unsigned char *) "HPKE-v1", 7) != 1 || |
4909 | | EVP_MAC_update(hctx, suite_id, suite_id_len) != 1 || |
4910 | | EVP_MAC_update(hctx, (const unsigned char *) label, |
4911 | | os_strlen(label)) != 1 || |
4912 | | EVP_MAC_update(hctx, ikm, ikm_len) != 1) |
4913 | | goto fail; |
4914 | | |
4915 | | res = EVP_MAC_final(hctx, prk, &mlen, mdlen); |
4916 | | EVP_MAC_CTX_free(hctx); |
4917 | | |
4918 | | return res == 1 ? 0 : -1; |
4919 | | fail: |
4920 | | EVP_MAC_CTX_free(hctx); |
4921 | | return -1; |
4922 | | #else /* OpenSSL version >= 3.0 */ |
4923 | | hctx = HMAC_CTX_new(); |
4924 | | if (!hctx) |
4925 | | return -1; |
4926 | | res = HMAC_Init_ex(hctx, salt, salt_len, kem ? ctx->kem_h : ctx->kdf_h, |
4927 | | NULL); |
4928 | | if (res != 1) |
4929 | | goto done; |
4930 | | |
4931 | | HMAC_Update(hctx, (const unsigned char *) "HPKE-v1", 7); |
4932 | | HMAC_Update(hctx, suite_id, suite_id_len); |
4933 | | HMAC_Update(hctx, (const unsigned char *) label, os_strlen(label)); |
4934 | | HMAC_Update(hctx, ikm, ikm_len); |
4935 | | |
4936 | | res = HMAC_Final(hctx, prk, &mdlen); |
4937 | | done: |
4938 | | HMAC_CTX_free(hctx); |
4939 | | |
4940 | | return res == 1 ? 0 : -1; |
4941 | | #endif /* OpenSSL version >= 3.0 */ |
4942 | | } |
4943 | | |
4944 | | |
4945 | | static int |
4946 | | hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk, |
4947 | | const char *label, const u8 *info, size_t info_len, |
4948 | | u8 *out, size_t out_len) |
4949 | | { |
4950 | | u8 suite_id[10]; |
4951 | | size_t suite_id_len; |
4952 | | u8 hash[HPKE_MAX_HASH_LEN]; |
4953 | | u8 iter = 0; |
4954 | | size_t label_len = os_strlen(label); |
4955 | | u8 *pos; |
4956 | | size_t left = out_len, clen; |
4957 | | int res = -1; |
4958 | | u8 *labeled_info; |
4959 | | size_t labeled_info_len; |
4960 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4961 | | EVP_MAC *hmac; |
4962 | | OSSL_PARAM params[2]; |
4963 | | EVP_MAC_CTX *hctx = NULL; |
4964 | | size_t mdlen; |
4965 | | #else /* OpenSSL version >= 3.0 */ |
4966 | | HMAC_CTX *hctx; |
4967 | | unsigned int mdlen; |
4968 | | #endif /* OpenSSL version >= 3.0 */ |
4969 | | |
4970 | | /* labeled_info = concat(I2OSP(L, 2), "HPKE-v1", suite_id, |
4971 | | * label, info) |
4972 | | * return Expand(prk, labeled_info, L) */ |
4973 | | suite_id_len = hpke_suite_id(ctx, kem, suite_id); |
4974 | | labeled_info_len = 2 + 7 + suite_id_len + label_len + info_len; |
4975 | | labeled_info = os_malloc(labeled_info_len); |
4976 | | if (!labeled_info) |
4977 | | return -1; |
4978 | | pos = labeled_info; |
4979 | | WPA_PUT_BE16(pos, out_len); |
4980 | | pos += 2; |
4981 | | os_memcpy(pos, "HPKE-v1", 7); |
4982 | | pos += 7; |
4983 | | os_memcpy(pos, suite_id, suite_id_len); |
4984 | | pos += suite_id_len; |
4985 | | os_memcpy(pos, label, label_len); |
4986 | | pos += label_len; |
4987 | | if (info && info_len) |
4988 | | os_memcpy(pos, info, info_len); |
4989 | | |
4990 | | pos = out; |
4991 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4992 | | hmac = EVP_MAC_fetch(NULL, "HMAC", NULL); |
4993 | | if (!hmac) |
4994 | | goto fail; |
4995 | | |
4996 | | params[0] = OSSL_PARAM_construct_utf8_string( |
4997 | | "digest", |
4998 | | (char *) EVP_MD_get0_name(kem ? ctx->kem_h : ctx->kdf_h), 0); |
4999 | | params[1] = OSSL_PARAM_construct_end(); |
5000 | | #else /* OpenSSL version >= 3.0 */ |
5001 | | hctx = HMAC_CTX_new(); |
5002 | | if (!hctx) |
5003 | | goto fail; |
5004 | | #endif /* OpenSSL version >= 3.0 */ |
5005 | | |
5006 | | while (left > 0) { |
5007 | | mdlen = kem ? ctx->kem_n_h : ctx->n_h; |
5008 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
5009 | | EVP_MAC_CTX_free(hctx); |
5010 | | hctx = EVP_MAC_CTX_new(hmac); |
5011 | | if (!hctx) |
5012 | | goto fail; |
5013 | | |
5014 | | if (EVP_MAC_init(hctx, prk, mdlen, params) != 1) { |
5015 | | wpa_printf(MSG_INFO, |
5016 | | "OpenSSL: EVP_MAC_init(hmac,digest/HPKE) failed: %s", |
5017 | | ERR_error_string(ERR_get_error(), NULL)); |
5018 | | goto fail; |
5019 | | } |
5020 | | |
5021 | | if (iter > 0 && EVP_MAC_update(hctx, hash, mdlen) != 1) |
5022 | | goto fail; |
5023 | | if (iter == 255) |
5024 | | goto fail; |
5025 | | iter++; |
5026 | | |
5027 | | if (EVP_MAC_update(hctx, labeled_info, labeled_info_len) != 1 || |
5028 | | EVP_MAC_update(hctx, &iter, sizeof(iter)) != 1) |
5029 | | goto fail; |
5030 | | |
5031 | | if (EVP_MAC_final(hctx, hash, &mdlen, mdlen) != 1) |
5032 | | goto fail; |
5033 | | #else /* OpenSSL version >= 3.0 */ |
5034 | | if (HMAC_Init_ex(hctx, prk, mdlen, |
5035 | | kem ? ctx->kem_h : ctx->kdf_h, |
5036 | | NULL) != 1) |
5037 | | goto fail; |
5038 | | |
5039 | | if (iter > 0) |
5040 | | HMAC_Update(hctx, hash, mdlen); |
5041 | | if (iter == 255) |
5042 | | goto fail; |
5043 | | iter++; |
5044 | | HMAC_Update(hctx, labeled_info, labeled_info_len); |
5045 | | HMAC_Update(hctx, &iter, sizeof(iter)); |
5046 | | |
5047 | | if (HMAC_Final(hctx, hash, &mdlen) != 1) |
5048 | | goto fail; |
5049 | | HMAC_CTX_reset(hctx); |
5050 | | #endif /* OpenSSL version >= 3.0 */ |
5051 | | |
5052 | | clen = left > mdlen ? mdlen : left; |
5053 | | os_memcpy(pos, hash, clen); |
5054 | | pos += clen; |
5055 | | left -= clen; |
5056 | | } |
5057 | | res = 0; |
5058 | | fail: |
5059 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
5060 | | EVP_MAC_free(hmac); |
5061 | | EVP_MAC_CTX_free(hctx); |
5062 | | #else /* OpenSSL version >= 3.0 */ |
5063 | | HMAC_CTX_free(hctx); |
5064 | | #endif /* OpenSSL version >= 3.0 */ |
5065 | | os_free(labeled_info); |
5066 | | |
5067 | | return res; |
5068 | | } |
5069 | | |
5070 | | |
5071 | | static int hpke_extract_and_expand(struct hpke_context *ctx, |
5072 | | const u8 *dhss, size_t dhss_len, |
5073 | | const u8 *enc, size_t enc_len, |
5074 | | const u8 *pk_rm, size_t pk_rm_len, |
5075 | | u8 *shared_secret) |
5076 | | { |
5077 | | u8 kem_context[2 * HPKE_MAX_PUB_LEN]; |
5078 | | u8 eae_prk[HPKE_MAX_HASH_LEN]; |
5079 | | |
5080 | | /* eae_prk = LabeledExtract("", "eae_prk", dh) */ |
5081 | | if (hpke_labeled_extract(ctx, true, NULL, 0, "eae_prk", dhss, dhss_len, |
5082 | | eae_prk) < 0) |
5083 | | return -1; |
5084 | | |
5085 | | if (enc_len > HPKE_MAX_PUB_LEN || pk_rm_len > HPKE_MAX_PUB_LEN) |
5086 | | return -1; |
5087 | | /* kem_context = concat(enc, pkRm) */ |
5088 | | os_memcpy(kem_context, enc, enc_len); |
5089 | | os_memcpy(&kem_context[enc_len], pk_rm, pk_rm_len); |
5090 | | |
5091 | | /* shared_secret = LabeledExpand(eae_prk, "shared_secret", |
5092 | | * kem_context, Nsecret) */ |
5093 | | if (hpke_labeled_expand(ctx, true, eae_prk, "shared_secret", |
5094 | | kem_context, enc_len + pk_rm_len, |
5095 | | shared_secret, ctx->n_secret) < 0) |
5096 | | return -1; |
5097 | | |
5098 | | forced_memzero(eae_prk, sizeof(eae_prk)); |
5099 | | return 0; |
5100 | | } |
5101 | | |
5102 | | |
5103 | | static int hpke_key_schedule(struct hpke_context *ctx, const u8 *shared_secret, |
5104 | | const u8 *info, size_t info_len) |
5105 | | { |
5106 | | u8 key_schedule_context[1 + 2 * HPKE_MAX_HASH_LEN]; |
5107 | | u8 secret[HPKE_MAX_HASH_LEN]; |
5108 | | int res = -1; |
5109 | | |
5110 | | /* key_schedule_context = concat(mode, psk_id_hash, info_hash) */ |
5111 | | key_schedule_context[0] = HPKE_MODE_BASE; |
5112 | | |
5113 | | /* psk_id_hash = LabeledExtract("", "psk_id_hash", psk_id) */ |
5114 | | if (hpke_labeled_extract(ctx, false, NULL, 0, "psk_id_hash", |
5115 | | NULL, 0, &key_schedule_context[1]) < 0) |
5116 | | goto fail; |
5117 | | |
5118 | | /* info_hash = LabeledExtract("", "info_hash", info) */ |
5119 | | if (hpke_labeled_extract(ctx, false, NULL, 0, "info_hash", |
5120 | | info, info_len, |
5121 | | &key_schedule_context[1 + ctx->n_h]) < 0) |
5122 | | goto fail; |
5123 | | |
5124 | | /* secret = LabeledExtract(shared_secret, "secret", psk) */ |
5125 | | if (hpke_labeled_extract(ctx, false, shared_secret, ctx->n_secret, |
5126 | | "secret", NULL, 0, secret) < 0) |
5127 | | goto fail; |
5128 | | |
5129 | | /* key = LabeledExpand(secret, "key", key_schedule_context, Nk) */ |
5130 | | if (hpke_labeled_expand(ctx, false, secret, "key", |
5131 | | key_schedule_context, 1 + 2 * ctx->n_h, |
5132 | | ctx->key, ctx->n_k) < 0) |
5133 | | goto fail; |
5134 | | |
5135 | | /* base_nonce = LabeledExpand(secret, "base_nonce", |
5136 | | * key_schedule_context, Nn) */ |
5137 | | if (hpke_labeled_expand(ctx, false, secret, "base_nonce", |
5138 | | key_schedule_context, 1 + 2 * ctx->n_h, |
5139 | | ctx->base_nonce, ctx->n_n) < 0) |
5140 | | goto fail; |
5141 | | res = 0; |
5142 | | fail: |
5143 | | forced_memzero(key_schedule_context, sizeof(key_schedule_context)); |
5144 | | forced_memzero(secret, sizeof(secret)); |
5145 | | return res; |
5146 | | } |
5147 | | |
5148 | | |
5149 | | static int hpke_encap(struct hpke_context *ctx, struct crypto_ec_key *pk_r, |
5150 | | u8 *shared_secret, u8 *enc) |
5151 | | { |
5152 | | EVP_PKEY_CTX *pctx = NULL; |
5153 | | struct crypto_ec_key *sk_e; |
5154 | | int res = -1; |
5155 | | u8 *dhss = NULL; |
5156 | | size_t dhss_len = 0; |
5157 | | struct wpabuf *enc_buf = NULL, *pk_rm = NULL; |
5158 | | |
5159 | | /* skE, pkE = GenerateKeyPair() */ |
5160 | | sk_e = crypto_ec_key_gen(ctx->iana_group); |
5161 | | if (!sk_e) { |
5162 | | wpa_printf(MSG_INFO, "OpenSSL:%s:Could not generate key pair", |
5163 | | __func__); |
5164 | | goto fail; |
5165 | | } |
5166 | | |
5167 | | /* dh = DH(skE, pkR) */ |
5168 | | dhss_len = sizeof(dhss); |
5169 | | pctx = EVP_PKEY_CTX_new((EVP_PKEY *) sk_e, NULL); |
5170 | | if (!pctx || |
5171 | | EVP_PKEY_derive_init(pctx) != 1 || |
5172 | | EVP_PKEY_derive_set_peer(pctx, (EVP_PKEY *) pk_r) != 1 || |
5173 | | EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 || |
5174 | | !(dhss = os_malloc(dhss_len)) || |
5175 | | EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 || |
5176 | | dhss_len > HPKE_MAX_SHARED_SECRET_LEN) { |
5177 | | wpa_printf(MSG_INFO, |
5178 | | "OpenSSL: hpke_encap: EVP_PKEY_derive failed (dhss_len=%zu): %s", |
5179 | | dhss_len, ERR_error_string(ERR_get_error(), NULL)); |
5180 | | goto fail; |
5181 | | } |
5182 | | |
5183 | | /* enc = SerializePublicKey(pkE) */ |
5184 | | enc_buf = crypto_ec_key_get_pubkey_point(sk_e, 1); |
5185 | | if (!enc_buf) |
5186 | | goto fail; |
5187 | | os_memcpy(enc, wpabuf_head(enc_buf), wpabuf_len(enc_buf)); |
5188 | | |
5189 | | /* pkRm = SerializePublicKey(pkR) */ |
5190 | | pk_rm = crypto_ec_key_get_pubkey_point(pk_r, 1); |
5191 | | if (!pk_rm) |
5192 | | goto fail; |
5193 | | |
5194 | | /* kem_context = concat(enc, pkRm) */ |
5195 | | /* shared_secret = ExtractAndExpand(dh, kem_context) */ |
5196 | | /* return shared_secret, enc */ |
5197 | | res = hpke_extract_and_expand(ctx, dhss, dhss_len, enc, ctx->n_pk, |
5198 | | wpabuf_head(pk_rm), |
5199 | | wpabuf_len(pk_rm), shared_secret); |
5200 | | fail: |
5201 | | bin_clear_free(dhss, dhss_len); |
5202 | | crypto_ec_key_deinit(sk_e); |
5203 | | EVP_PKEY_CTX_free(pctx); |
5204 | | wpabuf_free(enc_buf); |
5205 | | wpabuf_free(pk_rm); |
5206 | | return res; |
5207 | | } |
5208 | | |
5209 | | |
5210 | | static struct wpabuf * |
5211 | | hpke_aead_seal(struct hpke_context *ctx, const u8 *aad, size_t aad_len, |
5212 | | const u8 *pt, size_t pt_len) |
5213 | | { |
5214 | | EVP_CIPHER_CTX *cctx; |
5215 | | int len = 0; |
5216 | | struct wpabuf *ct = NULL; |
5217 | | |
5218 | | /* No need to xor in sequence number since we support only the |
5219 | | * single-shot API, i.e., base_nonce can be used as-is. */ |
5220 | | |
5221 | | cctx = EVP_CIPHER_CTX_new(); |
5222 | | if (!cctx || |
5223 | | EVP_EncryptInit_ex(cctx, ctx->cipher, NULL, ctx->key, |
5224 | | ctx->base_nonce) != 1) { |
5225 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptInit_ex failed", |
5226 | | __func__); |
5227 | | goto fail; |
5228 | | } |
5229 | | if (aad && aad_len && |
5230 | | EVP_EncryptUpdate(cctx, NULL, &len, aad, aad_len) != 1) { |
5231 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_EncryptUpdate(AAD) failed", |
5232 | | __func__); |
5233 | | goto fail; |
5234 | | } |
5235 | | ct = wpabuf_alloc(pt_len + AES_BLOCK_SIZE + ctx->n_t); |
5236 | | if (!ct) |
5237 | | goto fail; |
5238 | | if (EVP_EncryptUpdate(cctx, wpabuf_put(ct, 0), &len, pt, pt_len) != 1) { |
5239 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_EncryptUpdate failed", |
5240 | | __func__); |
5241 | | goto fail; |
5242 | | } |
5243 | | wpabuf_put(ct, len); |
5244 | | |
5245 | | if (EVP_EncryptFinal(cctx, wpabuf_put(ct, 0), &len) != 1) { |
5246 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptFinal failed", |
5247 | | __func__); |
5248 | | wpabuf_free(ct); |
5249 | | ct = NULL; |
5250 | | goto fail; |
5251 | | } |
5252 | | |
5253 | | if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG, ctx->n_t, |
5254 | | wpabuf_put(ct, ctx->n_t)) != 1) { |
5255 | | wpa_printf(MSG_INFO, "OpenSSL:%s:Could not get tag", |
5256 | | __func__); |
5257 | | wpabuf_free(ct); |
5258 | | ct = NULL; |
5259 | | goto fail; |
5260 | | } |
5261 | | fail: |
5262 | | EVP_CIPHER_CTX_free(cctx); |
5263 | | return ct; |
5264 | | } |
5265 | | |
5266 | | |
5267 | | static struct wpabuf * hpke_base_seal_int(enum hpke_kem_id kem_id, |
5268 | | enum hpke_kdf_id kdf_id, |
5269 | | enum hpke_aead_id aead_id, |
5270 | | struct crypto_ec_key *peer_pub, |
5271 | | const u8 *info, size_t info_len, |
5272 | | const u8 *aad, size_t aad_len, |
5273 | | const u8 *pt, size_t pt_len) |
5274 | | { |
5275 | | struct hpke_context *ctx; |
5276 | | u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN]; |
5277 | | u8 enc[1 + 2 * HPKE_MAX_PUB_LEN]; |
5278 | | struct wpabuf *ct = NULL, *enc_ct = NULL; |
5279 | | |
5280 | | ctx = hpke_get_context(kem_id, kdf_id, aead_id, peer_pub); |
5281 | | if (!ctx) |
5282 | | return NULL; |
5283 | | |
5284 | | /* shared_secret, enc = Encap(pkR) */ |
5285 | | if (hpke_encap(ctx, peer_pub, shared_secret, enc) < 0) |
5286 | | goto fail; |
5287 | | |
5288 | | /* KeyScheduleS(mode_base, shared_secret, info, |
5289 | | * default_psk, default_psk_id) */ |
5290 | | if (hpke_key_schedule(ctx, shared_secret, info, info_len) < 0) |
5291 | | goto fail; |
5292 | | |
5293 | | /* ct = ctx.Seal(aad, pt) */ |
5294 | | ct = hpke_aead_seal(ctx, aad, aad_len, pt, pt_len); |
5295 | | if (!ct) |
5296 | | goto fail; |
5297 | | |
5298 | | /* return enc, ct */ |
5299 | | enc_ct = wpabuf_alloc(ctx->n_pk + wpabuf_len(ct)); |
5300 | | if (!enc_ct) |
5301 | | goto fail; |
5302 | | wpabuf_put_data(enc_ct, enc, ctx->n_pk); |
5303 | | wpabuf_put_buf(enc_ct, ct); |
5304 | | |
5305 | | fail: |
5306 | | forced_memzero(shared_secret, sizeof(shared_secret)); |
5307 | | hpke_free_context(ctx); |
5308 | | wpabuf_free(ct); |
5309 | | return enc_ct; |
5310 | | } |
5311 | | |
5312 | | |
5313 | | static int hpke_decap(struct hpke_context *ctx, const u8 *enc, |
5314 | | size_t enc_ct_len, struct crypto_ec_key *sk_r, |
5315 | | u8 *shared_secret) |
5316 | | { |
5317 | | EVP_PKEY_CTX *pctx = NULL; |
5318 | | struct wpabuf *pk_rm = NULL; |
5319 | | size_t len; |
5320 | | int res = -1; |
5321 | | struct crypto_ec_key *pk_e = NULL; |
5322 | | u8 *dhss = NULL; |
5323 | | size_t dhss_len = 0; |
5324 | | |
5325 | | /* pkE = DeserializePublicKey(enc) */ |
5326 | | if (enc_ct_len < ctx->n_pk) |
5327 | | return -1; /* not enough room for enc */ |
5328 | | if (enc[0] != 0x04) |
5329 | | return -1; /* not in uncompressed form */ |
5330 | | len = (ctx->n_pk - 1) / 2; |
5331 | | pk_e = crypto_ec_key_set_pub(ctx->iana_group, &enc[1], |
5332 | | &enc[1 + len], len); |
5333 | | if (!pk_e) |
5334 | | return -1; /* invalid public key point */ |
5335 | | /* dh = DH(skR, pkE) */ |
5336 | | pctx = EVP_PKEY_CTX_new((EVP_PKEY *) sk_r, NULL); |
5337 | | if (!pctx || |
5338 | | EVP_PKEY_derive_init(pctx) != 1 || |
5339 | | EVP_PKEY_derive_set_peer(pctx, (EVP_PKEY *) pk_e) != 1 || |
5340 | | EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 || |
5341 | | !(dhss = os_malloc(dhss_len)) || |
5342 | | EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 || |
5343 | | dhss_len > HPKE_MAX_SHARED_SECRET_LEN) { |
5344 | | wpa_printf(MSG_INFO, |
5345 | | "OpenSSL: hpke_decap: EVP_PKEY_derive failed (dhss_len=%zu): %s", |
5346 | | dhss_len, ERR_error_string(ERR_get_error(), NULL)); |
5347 | | goto fail; |
5348 | | } |
5349 | | |
5350 | | /* pkRm = SerializePublicKey(pk(skR)) */ |
5351 | | pk_rm = crypto_ec_key_get_pubkey_point(sk_r, 1); |
5352 | | if (!pk_rm) |
5353 | | goto fail; |
5354 | | |
5355 | | /* kem_context = concat(enc, pkRm) */ |
5356 | | /* shared_secret = ExtractAndExpand(dh, kem_context) */ |
5357 | | res = hpke_extract_and_expand(ctx, dhss, dhss_len, enc, ctx->n_pk, |
5358 | | wpabuf_head(pk_rm), |
5359 | | wpabuf_len(pk_rm), shared_secret); |
5360 | | fail: |
5361 | | bin_clear_free(dhss, dhss_len); |
5362 | | crypto_ec_key_deinit(pk_e); |
5363 | | EVP_PKEY_CTX_free(pctx); |
5364 | | wpabuf_free(pk_rm); |
5365 | | return res; |
5366 | | } |
5367 | | |
5368 | | |
5369 | | static struct wpabuf * |
5370 | | hpke_aead_open(struct hpke_context *ctx, const u8 *aad, size_t aad_len, |
5371 | | const u8 *ct, size_t ct_len) |
5372 | | { |
5373 | | EVP_CIPHER_CTX *cctx; |
5374 | | int len = 0; |
5375 | | const u8 *tag; |
5376 | | struct wpabuf *pt = NULL; |
5377 | | |
5378 | | if (ct_len < ctx->n_t) |
5379 | | return NULL; |
5380 | | tag = ct + ct_len - ctx->n_t; |
5381 | | ct_len -= ctx->n_t; |
5382 | | |
5383 | | /* No need to xor in sequence number since we support only the |
5384 | | * single-shot API, i.e., base_nonce can be used as-is. */ |
5385 | | |
5386 | | cctx = EVP_CIPHER_CTX_new(); |
5387 | | if (!cctx || |
5388 | | EVP_DecryptInit_ex(cctx, ctx->cipher, NULL, ctx->key, |
5389 | | ctx->base_nonce) != 1) { |
5390 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptInit_ex failed", |
5391 | | __func__); |
5392 | | goto fail; |
5393 | | } |
5394 | | if (aad && aad_len && |
5395 | | EVP_DecryptUpdate(cctx, NULL, &len, aad, aad_len) != 1) { |
5396 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptUpdate(AAD) failed", |
5397 | | __func__); |
5398 | | goto fail; |
5399 | | } |
5400 | | pt = wpabuf_alloc(ct_len + AES_BLOCK_SIZE); |
5401 | | if (!pt) |
5402 | | goto fail; |
5403 | | if (EVP_DecryptUpdate(cctx, wpabuf_put(pt, 0), &len, ct, ct_len) != 1) { |
5404 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptUpdate failed", |
5405 | | __func__); |
5406 | | goto fail; |
5407 | | } |
5408 | | wpabuf_put(pt, len); |
5409 | | |
5410 | | if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_SET_TAG, ctx->n_t, |
5411 | | (void *) tag) != 1) { |
5412 | | wpa_printf(MSG_INFO, "OpenSSL:%s:Could not set tag", |
5413 | | __func__); |
5414 | | wpabuf_free(pt); |
5415 | | pt = NULL; |
5416 | | goto fail; |
5417 | | } |
5418 | | |
5419 | | if (EVP_DecryptFinal(cctx, wpabuf_put(pt, 0), &len) != 1) { |
5420 | | wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptFinal failed", |
5421 | | __func__); |
5422 | | wpabuf_free(pt); |
5423 | | pt = NULL; |
5424 | | } |
5425 | | fail: |
5426 | | EVP_CIPHER_CTX_free(cctx); |
5427 | | return pt; |
5428 | | } |
5429 | | |
5430 | | |
5431 | | static struct wpabuf * hpke_base_open_int(enum hpke_kem_id kem_id, |
5432 | | enum hpke_kdf_id kdf_id, |
5433 | | enum hpke_aead_id aead_id, |
5434 | | struct crypto_ec_key *own_priv, |
5435 | | const u8 *info, size_t info_len, |
5436 | | const u8 *aad, size_t aad_len, |
5437 | | const u8 *enc_ct, size_t enc_ct_len) |
5438 | | { |
5439 | | struct hpke_context *ctx; |
5440 | | u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN]; |
5441 | | struct wpabuf *pt = NULL; |
5442 | | |
5443 | | ctx = hpke_get_context(kem_id, kdf_id, aead_id, own_priv); |
5444 | | if (!ctx) |
5445 | | return NULL; |
5446 | | |
5447 | | /* shared_secret = Decap(enc, skR) */ |
5448 | | if (hpke_decap(ctx, enc_ct, enc_ct_len, own_priv, shared_secret) < 0) |
5449 | | goto fail; |
5450 | | |
5451 | | /* KeyScheduleR(mode_base, shared_secret, info, |
5452 | | * default_psk, default_psk_id) */ |
5453 | | if (hpke_key_schedule(ctx, shared_secret, info, info_len) < 0) |
5454 | | goto fail; |
5455 | | |
5456 | | /* return ctx.Open(aad, ct) */ |
5457 | | pt = hpke_aead_open(ctx, aad, aad_len, |
5458 | | &enc_ct[ctx->n_pk], enc_ct_len - ctx->n_pk); |
5459 | | |
5460 | | fail: |
5461 | | forced_memzero(shared_secret, sizeof(shared_secret)); |
5462 | | hpke_free_context(ctx); |
5463 | | return pt; |
5464 | | } |
5465 | | |
5466 | | |
5467 | | #if OPENSSL_VERSION_NUMBER >= 0x30200000L |
5468 | | |
5469 | | static bool hpke_set_suite(OSSL_HPKE_SUITE *suite, |
5470 | | enum hpke_kem_id kem_id, |
5471 | | enum hpke_kdf_id kdf_id, |
5472 | | enum hpke_aead_id aead_id) |
5473 | | { |
5474 | | os_memset(suite, 0, sizeof(*suite)); |
5475 | | |
5476 | | switch (kem_id) { |
5477 | | case HPKE_DHKEM_P256_HKDF_SHA256: |
5478 | | suite->kem_id = OSSL_HPKE_KEM_ID_P256; |
5479 | | break; |
5480 | | case HPKE_DHKEM_P384_HKDF_SHA384: |
5481 | | suite->kem_id = OSSL_HPKE_KEM_ID_P384; |
5482 | | break; |
5483 | | case HPKE_DHKEM_P521_HKDF_SHA512: |
5484 | | suite->kem_id = OSSL_HPKE_KEM_ID_P521; |
5485 | | break; |
5486 | | default: |
5487 | | return false; |
5488 | | } |
5489 | | |
5490 | | switch (kdf_id) { |
5491 | | case HPKE_KDF_HKDF_SHA256: |
5492 | | suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA256; |
5493 | | break; |
5494 | | case HPKE_KDF_HKDF_SHA384: |
5495 | | suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA384; |
5496 | | break; |
5497 | | case HPKE_KDF_HKDF_SHA512: |
5498 | | suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA512; |
5499 | | break; |
5500 | | default: |
5501 | | return false; |
5502 | | } |
5503 | | |
5504 | | switch (aead_id) { |
5505 | | case HPKE_AEAD_AES_128_GCM: |
5506 | | suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128; |
5507 | | break; |
5508 | | case HPKE_AEAD_AES_256_GCM: |
5509 | | suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_256; |
5510 | | break; |
5511 | | default: |
5512 | | return false; |
5513 | | } |
5514 | | |
5515 | | if (!OSSL_HPKE_suite_check(*suite)) { |
5516 | | wpa_printf(MSG_INFO, |
5517 | | "OpenSSL: HPKE suite kem_id=%d kdf_id=%d aead_id=%d not supported", |
5518 | | kem_id, kdf_id, aead_id); |
5519 | | return false; |
5520 | | } |
5521 | | |
5522 | | return true; |
5523 | | } |
5524 | | |
5525 | | |
5526 | | struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id, |
5527 | | enum hpke_kdf_id kdf_id, |
5528 | | enum hpke_aead_id aead_id, |
5529 | | struct crypto_ec_key *peer_pub, |
5530 | | const u8 *info, size_t info_len, |
5531 | | const u8 *aad, size_t aad_len, |
5532 | | const u8 *pt, size_t pt_len) |
5533 | | { |
5534 | | OSSL_HPKE_SUITE suite; |
5535 | | OSSL_HPKE_CTX *ctx = NULL; |
5536 | | struct wpabuf *res = NULL, *buf, *pub = NULL; |
5537 | | size_t enc_len, ct_len; |
5538 | | int group; |
5539 | | |
5540 | | group = crypto_ec_key_group(peer_pub); |
5541 | | if (group == 28 || group == 29 || group == 30) { |
5542 | | /* Use the internal routines for the special DPP use case with |
5543 | | * brainpool curves, */ |
5544 | | return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub, |
5545 | | info, info_len, aad, aad_len, |
5546 | | pt, pt_len); |
5547 | | } |
5548 | | |
5549 | | |
5550 | | if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id)) |
5551 | | return NULL; |
5552 | | |
5553 | | enc_len = OSSL_HPKE_get_public_encap_size(suite); |
5554 | | ct_len = OSSL_HPKE_get_ciphertext_size(suite, pt_len); |
5555 | | buf = wpabuf_alloc(enc_len + ct_len); |
5556 | | if (!buf) |
5557 | | goto out; |
5558 | | |
5559 | | pub = crypto_ec_key_get_pubkey_point(peer_pub, 1); |
5560 | | if (!pub) |
5561 | | goto out; |
5562 | | |
5563 | | ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite, |
5564 | | OSSL_HPKE_ROLE_SENDER, NULL, NULL); |
5565 | | if (!ctx) |
5566 | | goto out; |
5567 | | |
5568 | | if (OSSL_HPKE_encap(ctx, wpabuf_put(buf, 0), &enc_len, |
5569 | | wpabuf_head(pub), wpabuf_len(pub), |
5570 | | info, info_len) != 1) { |
5571 | | wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_encap failed: %s", |
5572 | | ERR_error_string(ERR_get_error(), NULL)); |
5573 | | goto out; |
5574 | | } |
5575 | | wpabuf_put(buf, enc_len); |
5576 | | |
5577 | | if (OSSL_HPKE_seal(ctx, wpabuf_put(buf, 0), &ct_len, aad, aad_len, |
5578 | | pt, pt_len) != 1) { |
5579 | | wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_seal failed: %s", |
5580 | | ERR_error_string(ERR_get_error(), NULL)); |
5581 | | goto out; |
5582 | | } |
5583 | | wpabuf_put(buf, ct_len); |
5584 | | res = buf; |
5585 | | buf = NULL; |
5586 | | |
5587 | | out: |
5588 | | OSSL_HPKE_CTX_free(ctx); |
5589 | | wpabuf_free(buf); |
5590 | | wpabuf_free(pub); |
5591 | | return res; |
5592 | | } |
5593 | | |
5594 | | |
5595 | | struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id, |
5596 | | enum hpke_kdf_id kdf_id, |
5597 | | enum hpke_aead_id aead_id, |
5598 | | struct crypto_ec_key *own_priv, |
5599 | | const u8 *info, size_t info_len, |
5600 | | const u8 *aad, size_t aad_len, |
5601 | | const u8 *enc_ct, size_t enc_ct_len) |
5602 | | { |
5603 | | OSSL_HPKE_SUITE suite; |
5604 | | OSSL_HPKE_CTX *ctx; |
5605 | | struct wpabuf *buf = NULL, *res = NULL; |
5606 | | size_t len, enc_len; |
5607 | | int group; |
5608 | | |
5609 | | group = crypto_ec_key_group(own_priv); |
5610 | | if (group == 28 || group == 29 || group == 30) { |
5611 | | /* Use the internal routines for the special DPP use case with |
5612 | | * brainpool curves, */ |
5613 | | return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv, |
5614 | | info, info_len, aad, aad_len, |
5615 | | enc_ct, enc_ct_len); |
5616 | | } |
5617 | | |
5618 | | if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id)) |
5619 | | return NULL; |
5620 | | |
5621 | | enc_len = OSSL_HPKE_get_public_encap_size(suite); |
5622 | | if (enc_ct_len < enc_len) { |
5623 | | wpa_printf(MSG_DEBUG, "OpenSSL: Too short HPKE enc_ct data"); |
5624 | | return NULL; |
5625 | | } |
5626 | | |
5627 | | ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite, |
5628 | | OSSL_HPKE_ROLE_RECEIVER, NULL, NULL); |
5629 | | if (!ctx) |
5630 | | goto out; |
5631 | | |
5632 | | if (OSSL_HPKE_decap(ctx, enc_ct, enc_len, (EVP_PKEY *) own_priv, |
5633 | | info, info_len) != 1) { |
5634 | | wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_decap failed: %s", |
5635 | | ERR_error_string(ERR_get_error(), NULL)); |
5636 | | goto out; |
5637 | | } |
5638 | | |
5639 | | len = enc_ct_len; |
5640 | | buf = wpabuf_alloc(len); |
5641 | | if (!buf) |
5642 | | goto out; |
5643 | | |
5644 | | if (OSSL_HPKE_open(ctx, wpabuf_put(buf, 0), &len, aad, aad_len, |
5645 | | enc_ct + enc_len, enc_ct_len - enc_len) != 1) { |
5646 | | wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_open failed: %s", |
5647 | | ERR_error_string(ERR_get_error(), NULL)); |
5648 | | goto out; |
5649 | | } |
5650 | | |
5651 | | wpabuf_put(buf, len); |
5652 | | res = buf; |
5653 | | buf = NULL; |
5654 | | |
5655 | | out: |
5656 | | OSSL_HPKE_CTX_free(ctx); |
5657 | | wpabuf_free(buf); |
5658 | | return res; |
5659 | | } |
5660 | | |
5661 | | #else /* OpenSSL < 3.2 */ |
5662 | | |
5663 | | struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id, |
5664 | | enum hpke_kdf_id kdf_id, |
5665 | | enum hpke_aead_id aead_id, |
5666 | | struct crypto_ec_key *peer_pub, |
5667 | | const u8 *info, size_t info_len, |
5668 | | const u8 *aad, size_t aad_len, |
5669 | | const u8 *pt, size_t pt_len) |
5670 | | { |
5671 | | return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub, |
5672 | | info, info_len, aad, aad_len, pt, pt_len); |
5673 | | } |
5674 | | |
5675 | | |
5676 | | struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id, |
5677 | | enum hpke_kdf_id kdf_id, |
5678 | | enum hpke_aead_id aead_id, |
5679 | | struct crypto_ec_key *own_priv, |
5680 | | const u8 *info, size_t info_len, |
5681 | | const u8 *aad, size_t aad_len, |
5682 | | const u8 *enc_ct, size_t enc_ct_len) |
5683 | | { |
5684 | | return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv, |
5685 | | info, info_len, aad, aad_len, |
5686 | | enc_ct, enc_ct_len); |
5687 | | } |
5688 | | |
5689 | | #endif /* OpenSSL < 3.2 */ |
5690 | | |
5691 | | #endif /* CONFIG_DPP3 */ |
5692 | | |
5693 | | |
5694 | | void crypto_unload(void) |
5695 | 0 | { |
5696 | 0 | openssl_unload_legacy_provider(); |
5697 | 0 | openssl_unload_default_provider(); |
5698 | 0 | } |