blob: c84ccb466f50da3b767b7778654f723dec5d0c51 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002 * Wrapper functions for OpenSSL libcrypto
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003 * Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
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>
Dmitry Shmidt04949592012-07-19 12:16:46 -070017#include <openssl/hmac.h>
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070018#include <openssl/rand.h>
Sunil Ravi89eba102022-09-13 21:04:37 -070019#include <openssl/rsa.h>
Sunil Ravia04bd252022-05-02 22:54:18 -070020#include <openssl/pem.h>
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080021#ifdef CONFIG_ECC
22#include <openssl/ec.h>
Hai Shalom899fcc72020-10-19 14:38:18 -070023#include <openssl/x509.h>
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080024#endif /* CONFIG_ECC */
Hai Shaloma20dcd72022-02-04 13:43:00 -080025#if OPENSSL_VERSION_NUMBER >= 0x30000000L
26#include <openssl/provider.h>
Sunil Ravia04bd252022-05-02 22:54:18 -070027#include <openssl/core_names.h>
28#include <openssl/param_build.h>
Sunil8cd6f4d2022-06-28 18:40:46 +000029#include <openssl/encoder.h>
30#include <openssl/decoder.h>
Sunil Ravia04bd252022-05-02 22:54:18 -070031#else /* OpenSSL version >= 3.0 */
32#include <openssl/cmac.h>
Hai Shaloma20dcd72022-02-04 13:43:00 -080033#endif /* OpenSSL version >= 3.0 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +000034#ifdef CONFIG_DPP3
35#if OPENSSL_VERSION_NUMBER >= 0x30200000L
36#include <openssl/hpke.h>
37#endif
38#endif /* CONFIG_DPP3 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039
40#include "common.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070041#include "utils/const_time.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042#include "wpabuf.h"
43#include "dh_group5.h"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080044#include "sha1.h"
45#include "sha256.h"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080046#include "sha384.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080047#include "sha512.h"
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -070048#include "md5.h"
49#include "aes_wrap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070050#include "crypto.h"
51
Sunil Ravia04bd252022-05-02 22:54:18 -070052#if OPENSSL_VERSION_NUMBER < 0x10100000L
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -080053/* Compatibility wrappers for older versions. */
54
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -080055static 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
66static void HMAC_CTX_free(HMAC_CTX *ctx)
67{
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070068 if (!ctx)
69 return;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080070 HMAC_CTX_cleanup(ctx);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -080071 bin_clear_free(ctx, sizeof(*ctx));
72}
73
74
75static 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
86static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
87{
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070088 if (!ctx)
89 return;
90 EVP_MD_CTX_cleanup(ctx);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -080091 bin_clear_free(ctx, sizeof(*ctx));
92}
93
Hai Shalom899fcc72020-10-19 14:38:18 -070094
Hai Shaloma20dcd72022-02-04 13:43:00 -080095#ifdef CONFIG_ECC
96
Hai Shalom899fcc72020-10-19 14:38:18 -070097static 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
Hai Shaloma20dcd72022-02-04 13:43:00 -0800104
105static 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
113static 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
124static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
125{
126 return ASN1_STRING_data((ASN1_STRING *) x);
127}
Sunil8cd6f4d2022-06-28 18:40:46 +0000128
129
130static const ASN1_TIME * X509_get0_notBefore(const X509 *x)
131{
132 return X509_get_notBefore(x);
133}
134
135
136static const ASN1_TIME * X509_get0_notAfter(const X509 *x)
137{
138 return X509_get_notAfter(x);
139}
140
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800141#endif /* OpenSSL version < 1.1.0 */
142
Hai Shaloma20dcd72022-02-04 13:43:00 -0800143
Sunil Ravia04bd252022-05-02 22:54:18 -0700144#if OPENSSL_VERSION_NUMBER < 0x10101000L || \
145 (defined(LIBRESSL_VERSION_NUMBER) && \
146 LIBRESSL_VERSION_NUMBER < 0x30400000L)
147
148static 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
156static 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
171static 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
180static 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
Sunil Ravi876a49b2025-02-03 19:18:32 +0000189static void openssl_disable_fips(void)
190{
191#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#endif /* !CONFIG_FIPS */
210}
211
Sunil Ravia04bd252022-05-02 22:54:18 -0700212#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravia04bd252022-05-02 22:54:18 -0700213static OSSL_PROVIDER *openssl_legacy_provider = NULL;
Sunil Ravi876a49b2025-02-03 19:18:32 +0000214static OSSL_PROVIDER *openssl_default_provider = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -0700215#endif /* OpenSSL version >= 3.0 */
216
Hai Shaloma20dcd72022-02-04 13:43:00 -0800217void openssl_load_legacy_provider(void)
218{
219#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravia04bd252022-05-02 22:54:18 -0700220 if (openssl_legacy_provider)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800221 return;
222
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000223 openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "legacy", 1);
Sunil Ravia04bd252022-05-02 22:54:18 -0700224#endif /* OpenSSL version >= 3.0 */
225}
Hai Shaloma20dcd72022-02-04 13:43:00 -0800226
Sunil Ravia04bd252022-05-02 22:54:18 -0700227
228static void openssl_unload_legacy_provider(void)
229{
230#if OPENSSL_VERSION_NUMBER >= 0x30000000L
231 if (openssl_legacy_provider) {
232 OSSL_PROVIDER_unload(openssl_legacy_provider);
233 openssl_legacy_provider = NULL;
234 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800235#endif /* OpenSSL version >= 3.0 */
236}
237
238
Sunil Ravi876a49b2025-02-03 19:18:32 +0000239static void openssl_load_default_provider_if_fips(void)
240{
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}
256
257
258static void openssl_unload_default_provider(void)
259{
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}
267
268
Sunil Ravia04bd252022-05-02 22:54:18 -0700269#if OPENSSL_VERSION_NUMBER < 0x30000000L
270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271static BIGNUM * get_group5_prime(void)
272{
Sunil Ravia04bd252022-05-02 22:54:18 -0700273#if OPENSSL_VERSION_NUMBER >= 0x10100000L
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700274 return BN_get_rfc3526_prime_1536(NULL);
275#elif !defined(OPENSSL_IS_BORINGSSL)
276 return get_rfc3526_prime_1536(NULL);
277#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700278 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);
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700297#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298}
299
Hai Shalom021b0b52019-04-10 11:17:58 -0700300
301static BIGNUM * get_group5_order(void)
302{
303 static const unsigned char RFC3526_ORDER_1536[] = {
304 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51,
305 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68,
306 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53,
307 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E,
308 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36,
309 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22,
310 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74,
311 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6,
312 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08,
313 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E,
314 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B,
315 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF,
316 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB,
317 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36,
318 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04,
319 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
320 };
321 return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL);
322}
323
Sunil Ravia04bd252022-05-02 22:54:18 -0700324#endif /* OpenSSL version < 3.0 */
325
Hai Shalom021b0b52019-04-10 11:17:58 -0700326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327#ifdef OPENSSL_NO_SHA256
328#define NO_SHA256_WRAPPER
329#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800330#ifdef OPENSSL_NO_SHA512
331#define NO_SHA384_WRAPPER
332#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700334static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
335 const u8 *addr[], const size_t *len, u8 *mac)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -0800337 EVP_MD_CTX *ctx;
338 size_t i;
339 unsigned int mac_len;
340
341 if (TEST_FAIL())
342 return -1;
343
344 ctx = EVP_MD_CTX_new();
345 if (!ctx)
346 return -1;
347 if (!EVP_DigestInit_ex(ctx, type, NULL)) {
348 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
349 ERR_error_string(ERR_get_error(), NULL));
350 EVP_MD_CTX_free(ctx);
351 return -1;
352 }
353 for (i = 0; i < num_elem; i++) {
354 if (!EVP_DigestUpdate(ctx, addr[i], len[i])) {
355 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
356 "failed: %s",
357 ERR_error_string(ERR_get_error(), NULL));
358 EVP_MD_CTX_free(ctx);
359 return -1;
360 }
361 }
362 if (!EVP_DigestFinal(ctx, mac, &mac_len)) {
363 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
364 ERR_error_string(ERR_get_error(), NULL));
365 EVP_MD_CTX_free(ctx);
366 return -1;
367 }
368 EVP_MD_CTX_free(ctx);
369
370 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371}
372
373
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800374#ifndef CONFIG_FIPS
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000375
Sunil Ravi876a49b2025-02-03 19:18:32 +0000376static void openssl_need_md5(void)
377{
378 openssl_disable_fips();
379 openssl_load_default_provider_if_fips();
380}
381
382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
384{
Sunil Ravi876a49b2025-02-03 19:18:32 +0000385 openssl_disable_fips();
Hai Shaloma20dcd72022-02-04 13:43:00 -0800386 openssl_load_legacy_provider();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700387 return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700391int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392{
393 u8 pkey[8], next, tmp;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800394 int i, plen, ret = -1;
395 EVP_CIPHER_CTX *ctx;
396
397 openssl_load_legacy_provider();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700398
399 /* Add parity bits to the key */
400 next = 0;
401 for (i = 0; i < 7; i++) {
402 tmp = key[i];
403 pkey[i] = (tmp >> i) | next | 1;
404 next = tmp << (7 - i);
405 }
406 pkey[i] = next | 1;
407
Hai Shaloma20dcd72022-02-04 13:43:00 -0800408 ctx = EVP_CIPHER_CTX_new();
409 if (ctx &&
410 EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, pkey, NULL) == 1 &&
411 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
412 EVP_EncryptUpdate(ctx, cypher, &plen, clear, 8) == 1 &&
413 EVP_EncryptFinal_ex(ctx, &cypher[plen], &plen) == 1)
414 ret = 0;
415 else
416 wpa_printf(MSG_ERROR, "OpenSSL: DES encrypt failed");
417
418 if (ctx)
419 EVP_CIPHER_CTX_free(ctx);
420 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700421}
422
423
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800424#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425int rc4_skip(const u8 *key, size_t keylen, size_t skip,
426 u8 *data, size_t data_len)
427{
428#ifdef OPENSSL_NO_RC4
429 return -1;
430#else /* OPENSSL_NO_RC4 */
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800431 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 int outl;
433 int res = -1;
434 unsigned char skip_buf[16];
435
Hai Shaloma20dcd72022-02-04 13:43:00 -0800436 openssl_load_legacy_provider();
437
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800438 ctx = EVP_CIPHER_CTX_new();
439 if (!ctx ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800440 !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800441 !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800442 !EVP_CIPHER_CTX_set_key_length(ctx, keylen) ||
443 !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 goto out;
445
446 while (skip >= sizeof(skip_buf)) {
447 size_t len = skip;
448 if (len > sizeof(skip_buf))
449 len = sizeof(skip_buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800450 if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 goto out;
452 skip -= len;
453 }
454
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800455 if (EVP_CipherUpdate(ctx, data, &outl, data, data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456 res = 0;
457
458out:
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800459 if (ctx)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800460 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461 return res;
462#endif /* OPENSSL_NO_RC4 */
463}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800464#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700465
466
467int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
468{
Sunil Ravi876a49b2025-02-03 19:18:32 +0000469 openssl_need_md5();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700470 return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700471}
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000472
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800473#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474
475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
477{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700478 return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700479}
480
481
482#ifndef NO_SHA256_WRAPPER
483int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
484 u8 *mac)
485{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700486 return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487}
488#endif /* NO_SHA256_WRAPPER */
489
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700490
Paul Stewart092955c2017-02-06 09:13:09 -0800491#ifndef NO_SHA384_WRAPPER
492int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
493 u8 *mac)
494{
495 return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac);
496}
497#endif /* NO_SHA384_WRAPPER */
498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700500#ifndef NO_SHA512_WRAPPER
501int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
502 u8 *mac)
503{
504 return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac);
505}
506#endif /* NO_SHA512_WRAPPER */
507
508
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700509static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
510{
511 switch (keylen) {
512 case 16:
513 return EVP_aes_128_ecb();
514 case 24:
515 return EVP_aes_192_ecb();
516 case 32:
517 return EVP_aes_256_ecb();
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000518 default:
519 return NULL;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700520 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700521}
522
523
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700524void * aes_encrypt_init(const u8 *key, size_t len)
525{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700526 EVP_CIPHER_CTX *ctx;
527 const EVP_CIPHER *type;
528
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800529 if (TEST_FAIL())
530 return NULL;
531
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700532 type = aes_get_evp_cipher(len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700533 if (!type) {
534 wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
535 __func__, (unsigned int) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700536 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700537 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700538
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800539 ctx = EVP_CIPHER_CTX_new();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700540 if (ctx == NULL)
541 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000542 if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
543 EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
Sunil Ravia04bd252022-05-02 22:54:18 -0700544 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700545 return NULL;
546 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700547 return ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548}
549
550
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700551int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700552{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700553 EVP_CIPHER_CTX *c = ctx;
554 int clen = 16;
555 if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) {
556 wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s",
557 ERR_error_string(ERR_get_error(), NULL));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700558 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700559 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700560 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561}
562
563
564void aes_encrypt_deinit(void *ctx)
565{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700566 EVP_CIPHER_CTX *c = ctx;
567 u8 buf[16];
568 int len = sizeof(buf);
569 if (EVP_EncryptFinal_ex(c, buf, &len) != 1) {
570 wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: "
571 "%s", ERR_error_string(ERR_get_error(), NULL));
572 }
573 if (len != 0) {
574 wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
575 "in AES encrypt", len);
576 }
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800577 EVP_CIPHER_CTX_free(c);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578}
579
580
581void * aes_decrypt_init(const u8 *key, size_t len)
582{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700583 EVP_CIPHER_CTX *ctx;
584 const EVP_CIPHER *type;
585
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800586 if (TEST_FAIL())
587 return NULL;
588
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700589 type = aes_get_evp_cipher(len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700590 if (!type) {
591 wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
592 __func__, (unsigned int) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700594 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700595
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800596 ctx = EVP_CIPHER_CTX_new();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700597 if (ctx == NULL)
598 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000599 if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
600 EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800601 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 return NULL;
603 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700604 return ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605}
606
607
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700608int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700610 EVP_CIPHER_CTX *c = ctx;
611 int plen = 16;
612 if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) {
613 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s",
614 ERR_error_string(ERR_get_error(), NULL));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700615 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700616 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700617 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618}
619
620
621void aes_decrypt_deinit(void *ctx)
622{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700623 EVP_CIPHER_CTX *c = ctx;
624 u8 buf[16];
625 int len = sizeof(buf);
626 if (EVP_DecryptFinal_ex(c, buf, &len) != 1) {
627 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: "
628 "%s", ERR_error_string(ERR_get_error(), NULL));
629 }
630 if (len != 0) {
631 wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
632 "in AES decrypt", len);
633 }
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800634 EVP_CIPHER_CTX_free(c);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700635}
636
637
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800638#ifndef CONFIG_FIPS
639#ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP
640
Sunil Ravia04bd252022-05-02 22:54:18 -0700641#if OPENSSL_VERSION_NUMBER >= 0x30000000L
642static 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
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800658int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
659{
Sunil Ravia04bd252022-05-02 22:54:18 -0700660#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 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800687 AES_KEY actx;
688 int res;
689
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800690 if (TEST_FAIL())
691 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800692 if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
693 return -1;
694 res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
695 OPENSSL_cleanse(&actx, sizeof(actx));
696 return res <= 0 ? -1 : 0;
Sunil Ravia04bd252022-05-02 22:54:18 -0700697#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800698}
699
700
701int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
702 u8 *plain)
703{
Sunil Ravia04bd252022-05-02 22:54:18 -0700704#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 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800731 AES_KEY actx;
732 int res;
733
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800734 if (TEST_FAIL())
735 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800736 if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
737 return -1;
738 res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
739 OPENSSL_cleanse(&actx, sizeof(actx));
740 return res <= 0 ? -1 : 0;
Sunil Ravia04bd252022-05-02 22:54:18 -0700741#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800742}
743
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800744#endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */
745#endif /* CONFIG_FIPS */
746
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800747
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700748int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
749{
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800750 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700751 int clen, len;
752 u8 buf[16];
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800753 int res = -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700754
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800755 if (TEST_FAIL())
756 return -1;
757
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800758 ctx = EVP_CIPHER_CTX_new();
759 if (!ctx)
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700760 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700761 clen = data_len;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700762 len = sizeof(buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800763 if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
764 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
765 EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 &&
766 clen == (int) data_len &&
767 EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
768 res = 0;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800769 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700770
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800771 return res;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700772}
773
774
775int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
776{
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800777 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700778 int plen, len;
779 u8 buf[16];
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800780 int res = -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700781
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800782 if (TEST_FAIL())
783 return -1;
784
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800785 ctx = EVP_CIPHER_CTX_new();
786 if (!ctx)
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700787 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700788 plen = data_len;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700789 len = sizeof(buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800790 if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
791 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
792 EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 &&
793 plen == (int) data_len &&
794 EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
795 res = 0;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800796 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700797
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800798 return res;
799
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700800}
801
802
Roshan Pius3a1667e2018-07-03 15:17:14 -0700803int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
804 u8 *pubkey)
805{
806 size_t pubkey_len, pad;
807
808 if (os_get_random(privkey, prime_len) < 0)
809 return -1;
810 if (os_memcmp(privkey, prime, prime_len) > 0) {
811 /* Make sure private value is smaller than prime */
812 privkey[0] = 0;
813 }
814
815 pubkey_len = prime_len;
816 if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
817 pubkey, &pubkey_len) < 0)
818 return -1;
819 if (pubkey_len < prime_len) {
820 pad = prime_len - pubkey_len;
821 os_memmove(pubkey + pad, pubkey, pubkey_len);
822 os_memset(pubkey, 0, pad);
823 }
824
825 return 0;
826}
827
828
829int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
Hai Shalom021b0b52019-04-10 11:17:58 -0700830 const u8 *order, size_t order_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700831 const u8 *privkey, size_t privkey_len,
832 const u8 *pubkey, size_t pubkey_len,
833 u8 *secret, size_t *len)
834{
Hai Shalom021b0b52019-04-10 11:17:58 -0700835 BIGNUM *pub, *p;
836 int res = -1;
837
838 pub = BN_bin2bn(pubkey, pubkey_len, NULL);
839 p = BN_bin2bn(prime, prime_len, NULL);
840 if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) ||
841 BN_cmp(pub, p) >= 0)
842 goto fail;
843
844 if (order) {
845 BN_CTX *ctx;
846 BIGNUM *q, *tmp;
847 int failed;
848
849 /* verify: pubkey^q == 1 mod p */
850 q = BN_bin2bn(order, order_len, NULL);
851 ctx = BN_CTX_new();
852 tmp = BN_new();
853 failed = !q || !ctx || !tmp ||
854 !BN_mod_exp(tmp, pub, q, p, ctx) ||
855 !BN_is_one(tmp);
Hai Shalom81f62d82019-07-22 12:10:00 -0700856 BN_clear_free(q);
857 BN_clear_free(tmp);
Hai Shalom021b0b52019-04-10 11:17:58 -0700858 BN_CTX_free(ctx);
859 if (failed)
860 goto fail;
861 }
862
863 res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
864 prime, prime_len, secret, len);
865fail:
Hai Shalom81f62d82019-07-22 12:10:00 -0700866 BN_clear_free(pub);
867 BN_clear_free(p);
Hai Shalom021b0b52019-04-10 11:17:58 -0700868 return res;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700869}
870
871
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872int 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{
877 BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
878 int ret = -1;
879 BN_CTX *ctx;
880
881 ctx = BN_CTX_new();
882 if (ctx == NULL)
883 return -1;
884
885 bn_base = BN_bin2bn(base, base_len, NULL);
886 bn_exp = BN_bin2bn(power, power_len, NULL);
887 bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
888 bn_result = BN_new();
889
890 if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
891 bn_result == NULL)
892 goto error;
893
Hai Shalom021b0b52019-04-10 11:17:58 -0700894 if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
895 ctx, NULL) != 1)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700896 goto error;
897
898 *result_len = BN_bn2bin(bn_result, result);
899 ret = 0;
900
901error:
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -0700902 BN_clear_free(bn_base);
903 BN_clear_free(bn_exp);
904 BN_clear_free(bn_modulus);
905 BN_clear_free(bn_result);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906 BN_CTX_free(ctx);
907 return ret;
908}
909
910
911struct crypto_cipher {
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800912 EVP_CIPHER_CTX *enc;
913 EVP_CIPHER_CTX *dec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914};
915
916
917struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
918 const u8 *iv, const u8 *key,
919 size_t key_len)
920{
921 struct crypto_cipher *ctx;
922 const EVP_CIPHER *cipher;
923
924 ctx = os_zalloc(sizeof(*ctx));
925 if (ctx == NULL)
926 return NULL;
927
928 switch (alg) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800929#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930#ifndef OPENSSL_NO_RC4
931 case CRYPTO_CIPHER_ALG_RC4:
932 cipher = EVP_rc4();
933 break;
934#endif /* OPENSSL_NO_RC4 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800935#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936#ifndef OPENSSL_NO_AES
937 case CRYPTO_CIPHER_ALG_AES:
938 switch (key_len) {
939 case 16:
940 cipher = EVP_aes_128_cbc();
941 break;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700942#ifndef OPENSSL_IS_BORINGSSL
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700943 case 24:
944 cipher = EVP_aes_192_cbc();
945 break;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700946#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 case 32:
948 cipher = EVP_aes_256_cbc();
949 break;
950 default:
951 os_free(ctx);
952 return NULL;
953 }
954 break;
955#endif /* OPENSSL_NO_AES */
956#ifndef OPENSSL_NO_DES
957 case CRYPTO_CIPHER_ALG_3DES:
958 cipher = EVP_des_ede3_cbc();
959 break;
960 case CRYPTO_CIPHER_ALG_DES:
961 cipher = EVP_des_cbc();
962 break;
963#endif /* OPENSSL_NO_DES */
964#ifndef OPENSSL_NO_RC2
965 case CRYPTO_CIPHER_ALG_RC2:
966 cipher = EVP_rc2_ecb();
967 break;
968#endif /* OPENSSL_NO_RC2 */
969 default:
970 os_free(ctx);
971 return NULL;
972 }
973
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800974 if (!(ctx->enc = EVP_CIPHER_CTX_new()) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800975 !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800976 !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800977 !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) ||
978 !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) {
979 if (ctx->enc)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800980 EVP_CIPHER_CTX_free(ctx->enc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981 os_free(ctx);
982 return NULL;
983 }
984
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800985 if (!(ctx->dec = EVP_CIPHER_CTX_new()) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800986 !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800987 !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800988 !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) ||
989 !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800990 EVP_CIPHER_CTX_free(ctx->enc);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800991 if (ctx->dec)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800992 EVP_CIPHER_CTX_free(ctx->dec);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 os_free(ctx);
994 return NULL;
995 }
996
997 return ctx;
998}
999
1000
1001int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
1002 u8 *crypt, size_t len)
1003{
1004 int outl;
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -08001005 if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 return -1;
1007 return 0;
1008}
1009
1010
1011int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
1012 u8 *plain, size_t len)
1013{
1014 int outl;
1015 outl = len;
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -08001016 if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017 return -1;
1018 return 0;
1019}
1020
1021
1022void crypto_cipher_deinit(struct crypto_cipher *ctx)
1023{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001024 EVP_CIPHER_CTX_free(ctx->enc);
1025 EVP_CIPHER_CTX_free(ctx->dec);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 os_free(ctx);
1027}
1028
1029
1030void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
1031{
Sunil Ravia04bd252022-05-02 22:54:18 -07001032#if OPENSSL_VERSION_NUMBER < 0x10100000L
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033 DH *dh;
1034 struct wpabuf *pubkey = NULL, *privkey = NULL;
1035 size_t publen, privlen;
1036
1037 *priv = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001038 wpabuf_free(*publ);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 *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
Hai Shalom021b0b52019-04-10 11:17:58 -07001053 dh->q = get_group5_order();
1054 if (!dh->q)
1055 goto err;
1056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 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
1076err:
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001077 wpabuf_clear_free(pubkey);
1078 wpabuf_clear_free(privkey);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079 DH_free(dh);
1080 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001081#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;
Sunil Ravi876a49b2025-02-03 19:18:32 +00001089 const char *propquery = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001090
1091 *priv = NULL;
1092 wpabuf_free(*publ);
1093 *publ = NULL;
1094
Sunil Ravi876a49b2025-02-03 19:18:32 +00001095 if (OSSL_PROVIDER_available(NULL, "fips")) {
1096 openssl_disable_fips();
1097 openssl_load_default_provider_if_fips();
1098 propquery = "provider!=fips";
1099 }
1100
Sunil Ravia04bd252022-05-02 22:54:18 -07001101 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
1102 "modp_1536", 0);
1103 params[1] = OSSL_PARAM_construct_end();
1104
Sunil Ravi876a49b2025-02-03 19:18:32 +00001105 gctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", propquery);
Sunil Ravia04bd252022-05-02 22:54:18 -07001106 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;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001139#else
1140 DH *dh;
1141 struct wpabuf *pubkey = NULL, *privkey = NULL;
1142 size_t publen, privlen;
Hai Shalom021b0b52019-04-10 11:17:58 -07001143 BIGNUM *p, *g, *q;
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07001144 const BIGNUM *priv_key = NULL, *pub_key = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001145
1146 *priv = NULL;
1147 wpabuf_free(*publ);
1148 *publ = NULL;
1149
1150 dh = DH_new();
1151 if (dh == NULL)
1152 return NULL;
1153
1154 g = BN_new();
1155 p = get_group5_prime();
Hai Shalom021b0b52019-04-10 11:17:58 -07001156 q = get_group5_order();
1157 if (!g || BN_set_word(g, 2) != 1 || !p || !q ||
1158 DH_set0_pqg(dh, p, q, g) != 1)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001159 goto err;
1160 p = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07001161 q = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001162 g = NULL;
1163
1164 if (DH_generate_key(dh) != 1)
1165 goto err;
1166
1167 DH_get0_key(dh, &pub_key, &priv_key);
1168 publen = BN_num_bytes(pub_key);
1169 pubkey = wpabuf_alloc(publen);
1170 if (!pubkey)
1171 goto err;
1172 privlen = BN_num_bytes(priv_key);
1173 privkey = wpabuf_alloc(privlen);
1174 if (!privkey)
1175 goto err;
1176
1177 BN_bn2bin(pub_key, wpabuf_put(pubkey, publen));
1178 BN_bn2bin(priv_key, wpabuf_put(privkey, privlen));
1179
1180 *priv = privkey;
1181 *publ = pubkey;
1182 return dh;
1183
1184err:
1185 BN_free(p);
Hai Shalom021b0b52019-04-10 11:17:58 -07001186 BN_free(q);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001187 BN_free(g);
1188 wpabuf_clear_free(pubkey);
1189 wpabuf_clear_free(privkey);
1190 DH_free(dh);
1191 return NULL;
1192#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193}
1194
1195
Dmitry Shmidt04949592012-07-19 12:16:46 -07001196void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
1197{
Sunil Ravia04bd252022-05-02 22:54:18 -07001198#if OPENSSL_VERSION_NUMBER < 0x10100000L
Dmitry Shmidt04949592012-07-19 12:16:46 -07001199 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
1226err:
1227 DH_free(dh);
1228 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001229#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;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001262#else
1263 DH *dh;
1264 BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL;
1265
1266 dh = DH_new();
1267 if (dh == NULL)
1268 return NULL;
1269
1270 g = BN_new();
1271 p = get_group5_prime();
1272 if (!g || BN_set_word(g, 2) != 1 || !p ||
1273 DH_set0_pqg(dh, p, NULL, g) != 1)
1274 goto err;
1275 p = NULL;
1276 g = NULL;
1277
1278 priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
1279 pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001280 if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001281 goto err;
1282 pub_key = NULL;
1283 priv_key = NULL;
1284
1285 if (DH_generate_key(dh) != 1)
1286 goto err;
1287
1288 return dh;
1289
1290err:
1291 BN_free(p);
1292 BN_free(g);
1293 BN_free(pub_key);
1294 BN_clear_free(priv_key);
1295 DH_free(dh);
1296 return NULL;
1297#endif
Dmitry Shmidt04949592012-07-19 12:16:46 -07001298}
1299
1300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
1302 const struct wpabuf *own_private)
1303{
Sunil Ravia04bd252022-05-02 22:54:18 -07001304#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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 BIGNUM *pub_key;
1335 struct wpabuf *res = NULL;
1336 size_t rlen;
1337 DH *dh = ctx;
1338 int keylen;
1339
1340 if (ctx == NULL)
1341 return NULL;
1342
1343 pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
1344 NULL);
1345 if (pub_key == NULL)
1346 return NULL;
1347
1348 rlen = DH_size(dh);
1349 res = wpabuf_alloc(rlen);
1350 if (res == NULL)
1351 goto err;
1352
1353 keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
1354 if (keylen < 0)
1355 goto err;
1356 wpabuf_put(res, keylen);
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001357 BN_clear_free(pub_key);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001358
1359 return res;
1360
1361err:
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001362 BN_clear_free(pub_key);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001363 wpabuf_clear_free(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001364 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001365#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366}
1367
1368
1369void dh5_free(void *ctx)
1370{
Sunil Ravia04bd252022-05-02 22:54:18 -07001371#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1372 EVP_PKEY *pkey = ctx;
1373
1374 EVP_PKEY_free(pkey);
1375#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376 DH *dh;
1377 if (ctx == NULL)
1378 return;
1379 dh = ctx;
1380 DH_free(dh);
Sunil Ravia04bd252022-05-02 22:54:18 -07001381#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001382}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001383
1384
1385struct crypto_hash {
Sunil Ravia04bd252022-05-02 22:54:18 -07001386#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1387 EVP_MAC_CTX *ctx;
1388#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001389 HMAC_CTX *ctx;
Sunil Ravia04bd252022-05-02 22:54:18 -07001390#endif /* OpenSSL version >= 3.0 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001391 bool failed;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001392};
1393
1394
1395struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
1396 size_t key_len)
1397{
Sunil Ravia04bd252022-05-02 22:54:18 -07001398#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)
Sunil8cd6f4d2022-06-28 18:40:46 +00001435 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001436 ctx->ctx = EVP_MAC_CTX_new(mac);
1437 if (!ctx->ctx) {
Sunil Ravia04bd252022-05-02 22:54:18 -07001438 os_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00001439 ctx = NULL;
1440 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001441 }
1442
1443 if (EVP_MAC_init(ctx->ctx, key, key_len, params) != 1) {
Sunil Ravi876a49b2025-02-03 19:18:32 +00001444 wpa_printf(MSG_INFO,
1445 "OpenSSL: EVP_MAC_init(hmac,digest=%s) failed: %s",
1446 a, ERR_error_string(ERR_get_error(), NULL));
Sunil Ravia04bd252022-05-02 22:54:18 -07001447 EVP_MAC_CTX_free(ctx->ctx);
1448 bin_clear_free(ctx, sizeof(*ctx));
Sunil8cd6f4d2022-06-28 18:40:46 +00001449 ctx = NULL;
1450 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001451 }
1452
Sunil8cd6f4d2022-06-28 18:40:46 +00001453fail:
Sunil Ravia04bd252022-05-02 22:54:18 -07001454 EVP_MAC_free(mac);
1455 return ctx;
1456#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001457 struct crypto_hash *ctx;
1458 const EVP_MD *md;
1459
1460 switch (alg) {
1461#ifndef OPENSSL_NO_MD5
1462 case CRYPTO_HASH_ALG_HMAC_MD5:
1463 md = EVP_md5();
1464 break;
1465#endif /* OPENSSL_NO_MD5 */
1466#ifndef OPENSSL_NO_SHA
1467 case CRYPTO_HASH_ALG_HMAC_SHA1:
1468 md = EVP_sha1();
1469 break;
1470#endif /* OPENSSL_NO_SHA */
1471#ifndef OPENSSL_NO_SHA256
1472#ifdef CONFIG_SHA256
1473 case CRYPTO_HASH_ALG_HMAC_SHA256:
1474 md = EVP_sha256();
1475 break;
1476#endif /* CONFIG_SHA256 */
1477#endif /* OPENSSL_NO_SHA256 */
1478 default:
1479 return NULL;
1480 }
1481
1482 ctx = os_zalloc(sizeof(*ctx));
1483 if (ctx == NULL)
1484 return NULL;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001485 ctx->ctx = HMAC_CTX_new();
1486 if (!ctx->ctx) {
1487 os_free(ctx);
1488 return NULL;
1489 }
1490
1491 if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) {
1492 HMAC_CTX_free(ctx->ctx);
1493 bin_clear_free(ctx, sizeof(*ctx));
1494 return NULL;
1495 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001496
1497 return ctx;
Sunil Ravia04bd252022-05-02 22:54:18 -07001498#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001499}
1500
1501
1502void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
1503{
1504 if (ctx == NULL)
1505 return;
Sunil Ravia04bd252022-05-02 22:54:18 -07001506#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001507 if (!EVP_MAC_update(ctx->ctx, data, len))
1508 ctx->failed = true;
Sunil Ravia04bd252022-05-02 22:54:18 -07001509#else /* OpenSSL version >= 3.0 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001510 if (!HMAC_Update(ctx->ctx, data, len))
1511 ctx->failed = true;
Sunil Ravia04bd252022-05-02 22:54:18 -07001512#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001513}
1514
1515
1516int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
1517{
Sunil Ravia04bd252022-05-02 22:54:18 -07001518#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1519 size_t mdlen;
1520 int res;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001521 bool failed;
Sunil Ravia04bd252022-05-02 22:54:18 -07001522
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);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001540 failed = ctx->failed;
Sunil Ravia04bd252022-05-02 22:54:18 -07001541 bin_clear_free(ctx, sizeof(*ctx));
1542
1543 if (TEST_FAIL())
1544 return -1;
1545
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001546 if (failed)
1547 return -2;
1548
Sunil Ravia04bd252022-05-02 22:54:18 -07001549 if (res == 1) {
1550 *len = mdlen;
1551 return 0;
1552 }
1553
1554 return -1;
1555#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001556 unsigned int mdlen;
1557 int res;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001558 bool failed;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001559
1560 if (ctx == NULL)
1561 return -2;
1562
1563 if (mac == NULL || len == NULL) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001564 HMAC_CTX_free(ctx->ctx);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001565 bin_clear_free(ctx, sizeof(*ctx));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001566 return 0;
1567 }
1568
1569 mdlen = *len;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001570 res = HMAC_Final(ctx->ctx, mac, &mdlen);
1571 HMAC_CTX_free(ctx->ctx);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001572 failed = ctx->failed;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001573 bin_clear_free(ctx, sizeof(*ctx));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001574
Hai Shalom5f92bc92019-04-18 11:54:11 -07001575 if (TEST_FAIL())
1576 return -1;
1577
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001578 if (failed)
1579 return -2;
1580
Dmitry Shmidt04949592012-07-19 12:16:46 -07001581 if (res == 1) {
1582 *len = mdlen;
1583 return 0;
1584 }
1585
1586 return -1;
Sunil Ravia04bd252022-05-02 22:54:18 -07001587#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001588}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001589
1590
Sunil Ravia04bd252022-05-02 22:54:18 -07001591#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1592
1593static 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;
Sunil Ravi876a49b2025-02-03 19:18:32 +00001603 const char *property_query = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001604
1605 if (TEST_FAIL())
1606 return -1;
1607
Sunil Ravi876a49b2025-02-03 19:18:32 +00001608#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));
Sunil Ravia04bd252022-05-02 22:54:18 -07001625 return -1;
Sunil Ravi876a49b2025-02-03 19:18:32 +00001626 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001627
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
Sunil Ravi876a49b2025-02-03 19:18:32 +00001636 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));
Sunil Ravia04bd252022-05-02 22:54:18 -07001641 goto fail;
Sunil Ravi876a49b2025-02-03 19:18:32 +00001642 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001643
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;
1653fail:
1654 EVP_MAC_CTX_free(ctx);
1655 return -1;
1656}
1657
1658
1659#ifndef CONFIG_FIPS
1660
1661int 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
1669int 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
1678int 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
1686int 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
1695int 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
1703int 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
1714int 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
1722int 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
1733int 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
1741int 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
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001751static 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)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001755{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001756 HMAC_CTX *ctx;
1757 size_t i;
1758 int res;
1759
1760 if (TEST_FAIL())
1761 return -1;
1762
1763 ctx = HMAC_CTX_new();
1764 if (!ctx)
1765 return -1;
1766 res = HMAC_Init_ex(ctx, key, key_len, type, NULL);
1767 if (res != 1)
1768 goto done;
1769
1770 for (i = 0; i < num_elem; i++)
1771 HMAC_Update(ctx, addr[i], len[i]);
1772
1773 res = HMAC_Final(ctx, mac, &mdlen);
1774done:
1775 HMAC_CTX_free(ctx);
1776
1777 return res == 1 ? 0 : -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001778}
1779
1780
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001781#ifndef CONFIG_FIPS
1782
1783int 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{
1786 return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
1787 mac, 16);
1788}
1789
1790
1791int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1792 u8 *mac)
1793{
1794 return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
1795}
1796
1797#endif /* CONFIG_FIPS */
1798
1799
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001800int 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{
1803 return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr,
1804 len, mac, 20);
1805}
1806
1807
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1809 u8 *mac)
1810{
1811 return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
1812}
1813
1814
1815#ifdef CONFIG_SHA256
1816
1817int 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{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001820 return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr,
1821 len, mac, 32);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001822}
1823
1824
1825int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
1826 size_t data_len, u8 *mac)
1827{
1828 return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
1829}
1830
1831#endif /* CONFIG_SHA256 */
1832
1833
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001834#ifdef CONFIG_SHA384
1835
1836int 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{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001839 return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001840 len, mac, 48);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001841}
1842
1843
1844int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
1845 size_t data_len, u8 *mac)
1846{
1847 return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
1848}
1849
1850#endif /* CONFIG_SHA384 */
1851
1852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001853#ifdef CONFIG_SHA512
1854
1855int 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{
1858 return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr,
1859 len, mac, 64);
1860}
1861
1862
1863int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
1864 size_t data_len, u8 *mac)
1865{
1866 return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
1867}
1868
1869#endif /* CONFIG_SHA512 */
1870
Sunil Ravia04bd252022-05-02 22:54:18 -07001871#endif /* OpenSSL version >= 3.0 */
1872
1873
1874int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
1875 int iterations, u8 *buf, size_t buflen)
1876{
1877 if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
1878 ssid_len, iterations, buflen, buf) != 1)
1879 return -1;
1880 return 0;
1881}
1882
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001883
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001884int crypto_get_random(void *buf, size_t len)
1885{
1886 if (RAND_bytes(buf, len) != 1)
1887 return -1;
1888 return 0;
1889}
1890
1891
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001892int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
1893 const u8 *addr[], const size_t *len, u8 *mac)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001894{
Sunil Ravia04bd252022-05-02 22:54:18 -07001895#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)) ||
Sunil Ravi876a49b2025-02-03 19:18:32 +00001920 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));
Sunil Ravia04bd252022-05-02 22:54:18 -07001924 goto fail;
Sunil Ravi876a49b2025-02-03 19:18:32 +00001925 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001926
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;
1935fail:
1936 EVP_MAC_CTX_free(ctx);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001937 EVP_MAC_free(emac);
Sunil Ravia04bd252022-05-02 22:54:18 -07001938 return ret;
1939#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001940 CMAC_CTX *ctx;
1941 int ret = -1;
1942 size_t outlen, i;
1943
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001944 if (TEST_FAIL())
1945 return -1;
1946
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001947 ctx = CMAC_CTX_new();
1948 if (ctx == NULL)
1949 return -1;
1950
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001951 if (key_len == 32) {
1952 if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL))
1953 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001954 } else if (key_len == 24) {
1955 if (!CMAC_Init(ctx, key, 24, EVP_aes_192_cbc(), NULL))
1956 goto fail;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001957 } else if (key_len == 16) {
1958 if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
1959 goto fail;
1960 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001961 goto fail;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001962 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001963 for (i = 0; i < num_elem; i++) {
1964 if (!CMAC_Update(ctx, addr[i], len[i]))
1965 goto fail;
1966 }
1967 if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16)
1968 goto fail;
1969
1970 ret = 0;
1971fail:
1972 CMAC_CTX_free(ctx);
1973 return ret;
Sunil Ravia04bd252022-05-02 22:54:18 -07001974#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001975}
1976
1977
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001978int omac1_aes_128_vector(const u8 *key, size_t num_elem,
1979 const u8 *addr[], const size_t *len, u8 *mac)
1980{
1981 return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
1982}
1983
1984
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001985int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1986{
1987 return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
1988}
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001989
1990
1991int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1992{
1993 return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
1994}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001995
1996
1997struct crypto_bignum * crypto_bignum_init(void)
1998{
Dmitry Shmidte4663042016-04-04 10:07:49 -07001999 if (TEST_FAIL())
2000 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002001 return (struct crypto_bignum *) BN_new();
2002}
2003
2004
2005struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
2006{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002007 BIGNUM *bn;
2008
2009 if (TEST_FAIL())
2010 return NULL;
2011
2012 bn = BN_bin2bn(buf, len, NULL);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002013 return (struct crypto_bignum *) bn;
2014}
2015
2016
Hai Shalomc3565922019-10-28 11:58:20 -07002017struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
2018{
2019 BIGNUM *bn;
2020
2021 if (TEST_FAIL())
2022 return NULL;
2023
2024 bn = BN_new();
2025 if (!bn)
2026 return NULL;
2027 if (BN_set_word(bn, val) != 1) {
2028 BN_free(bn);
2029 return NULL;
2030 }
2031 return (struct crypto_bignum *) bn;
2032}
2033
2034
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002035void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
2036{
2037 if (clear)
2038 BN_clear_free((BIGNUM *) n);
2039 else
2040 BN_free((BIGNUM *) n);
2041}
2042
2043
2044int crypto_bignum_to_bin(const struct crypto_bignum *a,
2045 u8 *buf, size_t buflen, size_t padlen)
2046{
2047 int num_bytes, offset;
2048
Dmitry Shmidte4663042016-04-04 10:07:49 -07002049 if (TEST_FAIL())
2050 return -1;
2051
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002052 if (padlen > buflen)
2053 return -1;
2054
Hai Shalomc3565922019-10-28 11:58:20 -07002055 if (padlen) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002056#ifdef OPENSSL_IS_BORINGSSL
Hai Shalomc3565922019-10-28 11:58:20 -07002057 if (BN_bn2bin_padded(buf, padlen, (const BIGNUM *) a) == 0)
2058 return -1;
2059 return padlen;
Hai Shalom81f62d82019-07-22 12:10:00 -07002060#else /* OPENSSL_IS_BORINGSSL */
2061#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
Hai Shalomc3565922019-10-28 11:58:20 -07002062 return BN_bn2binpad((const BIGNUM *) a, buf, padlen);
2063#endif
2064#endif
2065 }
2066
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002067 num_bytes = BN_num_bytes((const BIGNUM *) a);
2068 if ((size_t) num_bytes > buflen)
2069 return -1;
2070 if (padlen > (size_t) num_bytes)
2071 offset = padlen - num_bytes;
2072 else
2073 offset = 0;
2074
2075 os_memset(buf, 0, offset);
2076 BN_bn2bin((const BIGNUM *) a, buf + offset);
2077
2078 return num_bytes + offset;
2079}
2080
2081
Roshan Pius3a1667e2018-07-03 15:17:14 -07002082int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
2083{
Hai Shalom5f92bc92019-04-18 11:54:11 -07002084 if (TEST_FAIL())
2085 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002086 return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
2087}
2088
2089
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002090int crypto_bignum_add(const struct crypto_bignum *a,
2091 const struct crypto_bignum *b,
2092 struct crypto_bignum *c)
2093{
2094 return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
2095 0 : -1;
2096}
2097
2098
2099int crypto_bignum_mod(const struct crypto_bignum *a,
2100 const struct crypto_bignum *b,
2101 struct crypto_bignum *c)
2102{
2103 int res;
2104 BN_CTX *bnctx;
2105
2106 bnctx = BN_CTX_new();
2107 if (bnctx == NULL)
2108 return -1;
2109 res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
2110 bnctx);
2111 BN_CTX_free(bnctx);
2112
2113 return res ? 0 : -1;
2114}
2115
2116
2117int 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{
2122 int res;
2123 BN_CTX *bnctx;
2124
Dmitry Shmidte4663042016-04-04 10:07:49 -07002125 if (TEST_FAIL())
2126 return -1;
2127
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002128 bnctx = BN_CTX_new();
2129 if (bnctx == NULL)
2130 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002131 res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
2132 (const BIGNUM *) b, (const BIGNUM *) c,
2133 bnctx, NULL);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002134 BN_CTX_free(bnctx);
2135
2136 return res ? 0 : -1;
2137}
2138
2139
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002140int crypto_bignum_inverse(const struct crypto_bignum *a,
2141 const struct crypto_bignum *b,
2142 struct crypto_bignum *c)
2143{
2144 BIGNUM *res;
2145 BN_CTX *bnctx;
2146
Dmitry Shmidte4663042016-04-04 10:07:49 -07002147 if (TEST_FAIL())
2148 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002149 bnctx = BN_CTX_new();
2150 if (bnctx == NULL)
2151 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002152#ifdef OPENSSL_IS_BORINGSSL
2153 /* TODO: use BN_mod_inverse_blinded() ? */
2154#else /* OPENSSL_IS_BORINGSSL */
2155 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
2156#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002157 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
2158 (const BIGNUM *) b, bnctx);
2159 BN_CTX_free(bnctx);
2160
2161 return res ? 0 : -1;
2162}
2163
2164
2165int crypto_bignum_sub(const struct crypto_bignum *a,
2166 const struct crypto_bignum *b,
2167 struct crypto_bignum *c)
2168{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002169 if (TEST_FAIL())
2170 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002171 return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
2172 0 : -1;
2173}
2174
2175
2176int crypto_bignum_div(const struct crypto_bignum *a,
2177 const struct crypto_bignum *b,
2178 struct crypto_bignum *c)
2179{
2180 int res;
2181
2182 BN_CTX *bnctx;
2183
Dmitry Shmidte4663042016-04-04 10:07:49 -07002184 if (TEST_FAIL())
2185 return -1;
2186
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002187 bnctx = BN_CTX_new();
2188 if (bnctx == NULL)
2189 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002190#ifndef OPENSSL_IS_BORINGSSL
2191 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
2192#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002193 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
2194 (const BIGNUM *) b, bnctx);
2195 BN_CTX_free(bnctx);
2196
2197 return res ? 0 : -1;
2198}
2199
2200
Hai Shalomc3565922019-10-28 11:58:20 -07002201int 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{
2206 int res;
2207 BN_CTX *bnctx;
2208
2209 if (TEST_FAIL())
2210 return -1;
2211
2212 bnctx = BN_CTX_new();
2213 if (!bnctx)
2214 return -1;
2215 res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
2216 (const BIGNUM *) c, bnctx);
2217 BN_CTX_free(bnctx);
2218
2219 return res ? 0 : -1;
2220}
2221
2222
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002223int 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{
2228 int res;
2229
2230 BN_CTX *bnctx;
2231
Dmitry Shmidte4663042016-04-04 10:07:49 -07002232 if (TEST_FAIL())
2233 return -1;
2234
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002235 bnctx = BN_CTX_new();
2236 if (bnctx == NULL)
2237 return -1;
2238 res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
2239 (const BIGNUM *) c, bnctx);
2240 BN_CTX_free(bnctx);
2241
2242 return res ? 0 : -1;
2243}
2244
2245
Hai Shalomc3565922019-10-28 11:58:20 -07002246int crypto_bignum_sqrmod(const struct crypto_bignum *a,
2247 const struct crypto_bignum *b,
2248 struct crypto_bignum *c)
2249{
2250 int res;
2251 BN_CTX *bnctx;
2252
2253 if (TEST_FAIL())
2254 return -1;
2255
2256 bnctx = BN_CTX_new();
2257 if (!bnctx)
2258 return -1;
2259 res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
2260 bnctx);
2261 BN_CTX_free(bnctx);
2262
2263 return res ? 0 : -1;
2264}
2265
2266
Roshan Pius3a1667e2018-07-03 15:17:14 -07002267int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
2268 struct crypto_bignum *r)
2269{
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002270 return BN_rshift((BIGNUM *) r, (const BIGNUM *) a, n) == 1 ? 0 : -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002271}
2272
2273
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002274int crypto_bignum_cmp(const struct crypto_bignum *a,
2275 const struct crypto_bignum *b)
2276{
2277 return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b);
2278}
2279
2280
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002281int crypto_bignum_is_zero(const struct crypto_bignum *a)
2282{
2283 return BN_is_zero((const BIGNUM *) a);
2284}
2285
2286
2287int crypto_bignum_is_one(const struct crypto_bignum *a)
2288{
2289 return BN_is_one((const BIGNUM *) a);
2290}
2291
2292
Roshan Pius3a1667e2018-07-03 15:17:14 -07002293int crypto_bignum_is_odd(const struct crypto_bignum *a)
2294{
2295 return BN_is_odd((const BIGNUM *) a);
2296}
2297
2298
Dmitry Shmidt41712582015-06-29 11:02:15 -07002299int crypto_bignum_legendre(const struct crypto_bignum *a,
2300 const struct crypto_bignum *p)
2301{
2302 BN_CTX *bnctx;
2303 BIGNUM *exp = NULL, *tmp = NULL;
2304 int res = -2;
Hai Shalom021b0b52019-04-10 11:17:58 -07002305 unsigned int mask;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002306
Dmitry Shmidte4663042016-04-04 10:07:49 -07002307 if (TEST_FAIL())
2308 return -2;
2309
Dmitry Shmidt41712582015-06-29 11:02:15 -07002310 bnctx = BN_CTX_new();
2311 if (bnctx == NULL)
2312 return -2;
2313
2314 exp = BN_new();
2315 tmp = BN_new();
2316 if (!exp || !tmp ||
2317 /* exp = (p-1) / 2 */
2318 !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
2319 !BN_rshift1(exp, exp) ||
Hai Shalom021b0b52019-04-10 11:17:58 -07002320 !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
2321 (const BIGNUM *) p, bnctx, NULL))
Dmitry Shmidt41712582015-06-29 11:02:15 -07002322 goto fail;
2323
Hai Shalom021b0b52019-04-10 11:17:58 -07002324 /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
2325 * constant time selection to avoid branches here. */
2326 res = -1;
2327 mask = const_time_eq(BN_is_word(tmp, 1), 1);
2328 res = const_time_select_int(mask, 1, res);
2329 mask = const_time_eq(BN_is_zero(tmp), 1);
2330 res = const_time_select_int(mask, 0, res);
Dmitry Shmidt41712582015-06-29 11:02:15 -07002331
2332fail:
2333 BN_clear_free(tmp);
2334 BN_clear_free(exp);
2335 BN_CTX_free(bnctx);
2336 return res;
2337}
2338
2339
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002340#ifdef CONFIG_ECC
2341
2342struct crypto_ec {
2343 EC_GROUP *group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002344 int nid;
Sunil8cd6f4d2022-06-28 18:40:46 +00002345 int iana_group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002346 BN_CTX *bnctx;
2347 BIGNUM *prime;
2348 BIGNUM *order;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002349 BIGNUM *a;
2350 BIGNUM *b;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002351};
2352
Hai Shaloma20dcd72022-02-04 13:43:00 -08002353
2354static int crypto_ec_group_2_nid(int group)
2355{
2356 /* Map from IANA registry for IKE D-H groups to OpenSSL NID */
2357 switch (group) {
2358 case 19:
2359 return NID_X9_62_prime256v1;
2360 case 20:
2361 return NID_secp384r1;
2362 case 21:
2363 return NID_secp521r1;
2364 case 25:
2365 return NID_X9_62_prime192v1;
2366 case 26:
2367 return NID_secp224r1;
2368#ifdef NID_brainpoolP224r1
2369 case 27:
2370 return NID_brainpoolP224r1;
2371#endif /* NID_brainpoolP224r1 */
2372#ifdef NID_brainpoolP256r1
2373 case 28:
2374 return NID_brainpoolP256r1;
2375#endif /* NID_brainpoolP256r1 */
2376#ifdef NID_brainpoolP384r1
2377 case 29:
2378 return NID_brainpoolP384r1;
2379#endif /* NID_brainpoolP384r1 */
2380#ifdef NID_brainpoolP512r1
2381 case 30:
2382 return NID_brainpoolP512r1;
2383#endif /* NID_brainpoolP512r1 */
2384 default:
2385 return -1;
2386 }
2387}
2388
2389
Sunil8cd6f4d2022-06-28 18:40:46 +00002390#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2391static 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
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002428struct crypto_ec * crypto_ec_init(int group)
2429{
2430 struct crypto_ec *e;
2431 int nid;
2432
Hai Shaloma20dcd72022-02-04 13:43:00 -08002433 nid = crypto_ec_group_2_nid(group);
2434 if (nid < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002435 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002436
2437 e = os_zalloc(sizeof(*e));
2438 if (e == NULL)
2439 return NULL;
2440
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002441 e->nid = nid;
Sunil8cd6f4d2022-06-28 18:40:46 +00002442 e->iana_group = group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002443 e->bnctx = BN_CTX_new();
2444 e->group = EC_GROUP_new_by_curve_name(nid);
2445 e->prime = BN_new();
2446 e->order = BN_new();
Dmitry Shmidt41712582015-06-29 11:02:15 -07002447 e->a = BN_new();
2448 e->b = BN_new();
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002449 if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
Dmitry Shmidt41712582015-06-29 11:02:15 -07002450 e->order == NULL || e->a == NULL || e->b == NULL ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002451 !EC_GROUP_get_curve(e->group, e->prime, e->a, e->b, e->bnctx) ||
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002452 !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
2453 crypto_ec_deinit(e);
2454 e = NULL;
2455 }
2456
2457 return e;
2458}
2459
2460
2461void crypto_ec_deinit(struct crypto_ec *e)
2462{
2463 if (e == NULL)
2464 return;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002465 BN_clear_free(e->b);
2466 BN_clear_free(e->a);
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002467 BN_clear_free(e->order);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002468 BN_clear_free(e->prime);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002469 EC_GROUP_free(e->group);
2470 BN_CTX_free(e->bnctx);
2471 os_free(e);
2472}
2473
2474
2475struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
2476{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002477 if (TEST_FAIL())
2478 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002479 if (e == NULL)
2480 return NULL;
2481 return (struct crypto_ec_point *) EC_POINT_new(e->group);
2482}
2483
2484
2485size_t crypto_ec_prime_len(struct crypto_ec *e)
2486{
2487 return BN_num_bytes(e->prime);
2488}
2489
2490
2491size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
2492{
2493 return BN_num_bits(e->prime);
2494}
2495
2496
Roshan Pius3a1667e2018-07-03 15:17:14 -07002497size_t crypto_ec_order_len(struct crypto_ec *e)
2498{
2499 return BN_num_bytes(e->order);
2500}
2501
2502
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002503const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
2504{
2505 return (const struct crypto_bignum *) e->prime;
2506}
2507
2508
2509const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
2510{
2511 return (const struct crypto_bignum *) e->order;
2512}
2513
2514
Hai Shalomc3565922019-10-28 11:58:20 -07002515const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e)
2516{
2517 return (const struct crypto_bignum *) e->a;
2518}
2519
2520
2521const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
2522{
2523 return (const struct crypto_bignum *) e->b;
2524}
2525
2526
Hai Shaloma20dcd72022-02-04 13:43:00 -08002527const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
2528{
2529 return (const struct crypto_ec_point *)
2530 EC_GROUP_get0_generator(e->group);
2531}
2532
2533
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002534void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
2535{
2536 if (clear)
2537 EC_POINT_clear_free((EC_POINT *) p);
2538 else
2539 EC_POINT_free((EC_POINT *) p);
2540}
2541
2542
Roshan Pius3a1667e2018-07-03 15:17:14 -07002543int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
2544 struct crypto_bignum *x)
2545{
Sunil Ravia04bd252022-05-02 22:54:18 -07002546 return EC_POINT_get_affine_coordinates(e->group,
2547 (const EC_POINT *) p,
2548 (BIGNUM *) x, NULL,
2549 e->bnctx) == 1 ? 0 : -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002550}
2551
2552
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002553int crypto_ec_point_to_bin(struct crypto_ec *e,
2554 const struct crypto_ec_point *point, u8 *x, u8 *y)
2555{
2556 BIGNUM *x_bn, *y_bn;
2557 int ret = -1;
2558 int len = BN_num_bytes(e->prime);
2559
Dmitry Shmidte4663042016-04-04 10:07:49 -07002560 if (TEST_FAIL())
2561 return -1;
2562
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002563 x_bn = BN_new();
2564 y_bn = BN_new();
2565
2566 if (x_bn && y_bn &&
Sunil Ravia04bd252022-05-02 22:54:18 -07002567 EC_POINT_get_affine_coordinates(e->group, (EC_POINT *) point,
2568 x_bn, y_bn, e->bnctx)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002569 if (x) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002570 ret = crypto_bignum_to_bin(
2571 (struct crypto_bignum *) x_bn, x, len, len);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002572 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002573 if (ret >= 0 && y) {
2574 ret = crypto_bignum_to_bin(
2575 (struct crypto_bignum *) y_bn, y, len, len);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002576 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002577
2578 if (ret > 0)
2579 ret = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002580 }
2581
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002582 BN_clear_free(x_bn);
2583 BN_clear_free(y_bn);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002584 return ret;
2585}
2586
2587
2588struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
2589 const u8 *val)
2590{
2591 BIGNUM *x, *y;
2592 EC_POINT *elem;
2593 int len = BN_num_bytes(e->prime);
2594
Dmitry Shmidte4663042016-04-04 10:07:49 -07002595 if (TEST_FAIL())
2596 return NULL;
2597
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002598 x = BN_bin2bn(val, len, NULL);
2599 y = BN_bin2bn(val + len, len, NULL);
2600 elem = EC_POINT_new(e->group);
2601 if (x == NULL || y == NULL || elem == NULL) {
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002602 BN_clear_free(x);
2603 BN_clear_free(y);
2604 EC_POINT_clear_free(elem);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002605 return NULL;
2606 }
2607
Sunil Ravia04bd252022-05-02 22:54:18 -07002608 if (!EC_POINT_set_affine_coordinates(e->group, elem, x, y, e->bnctx)) {
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002609 EC_POINT_clear_free(elem);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002610 elem = NULL;
2611 }
2612
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002613 BN_clear_free(x);
2614 BN_clear_free(y);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002615
2616 return (struct crypto_ec_point *) elem;
2617}
2618
2619
2620int 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{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002624 if (TEST_FAIL())
2625 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002626 return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
2627 (const EC_POINT *) b, e->bnctx) ? 0 : -1;
2628}
2629
2630
2631int 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{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002635 if (TEST_FAIL())
2636 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002637 return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
2638 (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
2639 ? 0 : -1;
2640}
2641
2642
2643int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
2644{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002645 if (TEST_FAIL())
2646 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002647 return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
2648}
2649
2650
Dmitry Shmidt41712582015-06-29 11:02:15 -07002651struct crypto_bignum *
2652crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
2653 const struct crypto_bignum *x)
2654{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002655 BIGNUM *tmp;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002656
Dmitry Shmidte4663042016-04-04 10:07:49 -07002657 if (TEST_FAIL())
2658 return NULL;
2659
Dmitry Shmidt41712582015-06-29 11:02:15 -07002660 tmp = BN_new();
Dmitry Shmidt41712582015-06-29 11:02:15 -07002661
Hai Shaloma20dcd72022-02-04 13:43:00 -08002662 /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
2663 if (tmp &&
Dmitry Shmidt41712582015-06-29 11:02:15 -07002664 BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002665 BN_mod_add_quick(tmp, e->a, tmp, e->prime) &&
Dmitry Shmidt41712582015-06-29 11:02:15 -07002666 BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002667 BN_mod_add_quick(tmp, tmp, e->b, e->prime))
2668 return (struct crypto_bignum *) tmp;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002669
2670 BN_clear_free(tmp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002671 return NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002672}
2673
2674
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002675int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
2676 const struct crypto_ec_point *p)
2677{
2678 return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p);
2679}
2680
2681
2682int crypto_ec_point_is_on_curve(struct crypto_ec *e,
2683 const struct crypto_ec_point *p)
2684{
Dmitry Shmidt41712582015-06-29 11:02:15 -07002685 return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p,
2686 e->bnctx) == 1;
2687}
2688
2689
2690int crypto_ec_point_cmp(const struct crypto_ec *e,
2691 const struct crypto_ec_point *a,
2692 const struct crypto_ec_point *b)
2693{
2694 return EC_POINT_cmp(e->group, (const EC_POINT *) a,
2695 (const EC_POINT *) b, e->bnctx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002696}
2697
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002698
Hai Shaloma20dcd72022-02-04 13:43:00 -08002699void crypto_ec_point_debug_print(const struct crypto_ec *e,
2700 const struct crypto_ec_point *p,
2701 const char *title)
2702{
2703 BIGNUM *x, *y;
2704 char *x_str = NULL, *y_str = NULL;
2705
2706 x = BN_new();
2707 y = BN_new();
2708 if (!x || !y ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002709 EC_POINT_get_affine_coordinates(e->group, (const EC_POINT *) p,
2710 x, y, e->bnctx) != 1)
Hai Shaloma20dcd72022-02-04 13:43:00 -08002711 goto fail;
2712
2713 x_str = BN_bn2hex(x);
2714 y_str = BN_bn2hex(y);
2715 if (!x_str || !y_str)
2716 goto fail;
2717
2718 wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
2719
2720fail:
2721 OPENSSL_free(x_str);
2722 OPENSSL_free(y_str);
2723 BN_free(x);
2724 BN_free(y);
2725}
2726
2727
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002728struct crypto_ecdh {
2729 struct crypto_ec *ec;
2730 EVP_PKEY *pkey;
2731};
2732
2733struct crypto_ecdh * crypto_ecdh_init(int group)
2734{
Sunil Ravia04bd252022-05-02 22:54:18 -07002735#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);
Sunil Ravi876a49b2025-02-03 19:18:32 +00002752 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));
Sunil Ravia04bd252022-05-02 22:54:18 -07002756 goto fail;
Sunil Ravi876a49b2025-02-03 19:18:32 +00002757 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002758
2759done:
2760 return ecdh;
2761fail:
2762 crypto_ecdh_deinit(ecdh);
2763 ecdh = NULL;
2764 goto done;
2765#else /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002766 struct crypto_ecdh *ecdh;
2767 EVP_PKEY *params = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002768 EC_KEY *ec_params = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002769 EVP_PKEY_CTX *kctx = NULL;
2770
2771 ecdh = os_zalloc(sizeof(*ecdh));
2772 if (!ecdh)
2773 goto fail;
2774
2775 ecdh->ec = crypto_ec_init(group);
2776 if (!ecdh->ec)
2777 goto fail;
2778
Roshan Pius3a1667e2018-07-03 15:17:14 -07002779 ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid);
2780 if (!ec_params) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002781 wpa_printf(MSG_ERROR,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002782 "OpenSSL: Failed to generate EC_KEY parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002783 goto fail;
2784 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002785 EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
2786 params = EVP_PKEY_new();
2787 if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002788 wpa_printf(MSG_ERROR,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002789 "OpenSSL: Failed to generate EVP_PKEY parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002790 goto fail;
2791 }
2792
2793 kctx = EVP_PKEY_CTX_new(params, NULL);
2794 if (!kctx)
2795 goto fail;
2796
2797 if (EVP_PKEY_keygen_init(kctx) != 1) {
2798 wpa_printf(MSG_ERROR,
2799 "OpenSSL: EVP_PKEY_keygen_init failed: %s",
2800 ERR_error_string(ERR_get_error(), NULL));
2801 goto fail;
2802 }
2803
2804 if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) {
2805 wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s",
2806 ERR_error_string(ERR_get_error(), NULL));
2807 goto fail;
2808 }
2809
2810done:
Hai Shalom81f62d82019-07-22 12:10:00 -07002811 EC_KEY_free(ec_params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002812 EVP_PKEY_free(params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002813 EVP_PKEY_CTX_free(kctx);
2814
2815 return ecdh;
2816fail:
2817 crypto_ecdh_deinit(ecdh);
2818 ecdh = NULL;
2819 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07002820#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002821}
2822
2823
Hai Shaloma20dcd72022-02-04 13:43:00 -08002824struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
2825{
Sunil Ravia04bd252022-05-02 22:54:18 -07002826#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;
2842fail:
2843 crypto_ecdh_deinit(ecdh);
2844 return NULL;
2845#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002846 struct crypto_ecdh *ecdh;
2847
2848 ecdh = os_zalloc(sizeof(*ecdh));
2849 if (!ecdh)
2850 goto fail;
2851
2852 ecdh->ec = crypto_ec_init(group);
2853 if (!ecdh->ec)
2854 goto fail;
2855
2856 ecdh->pkey = EVP_PKEY_new();
2857 if (!ecdh->pkey ||
2858 EVP_PKEY_assign_EC_KEY(ecdh->pkey,
2859 EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key))
2860 != 1)
2861 goto fail;
2862
2863 return ecdh;
2864fail:
2865 crypto_ecdh_deinit(ecdh);
2866 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07002867#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002868}
2869
2870
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002871struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
2872{
Sunil Ravia04bd252022-05-02 22:54:18 -07002873#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);
2891fail:
2892 OPENSSL_free(pub);
2893 return buf;
2894#else /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002895 struct wpabuf *buf = NULL;
2896 EC_KEY *eckey;
2897 const EC_POINT *pubkey;
2898 BIGNUM *x, *y = NULL;
2899 int len = BN_num_bytes(ecdh->ec->prime);
2900 int res;
2901
2902 eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey);
2903 if (!eckey)
2904 return NULL;
2905
2906 pubkey = EC_KEY_get0_public_key(eckey);
2907 if (!pubkey)
2908 return NULL;
2909
2910 x = BN_new();
2911 if (inc_y) {
2912 y = BN_new();
2913 if (!y)
2914 goto fail;
2915 }
2916 buf = wpabuf_alloc(inc_y ? 2 * len : len);
2917 if (!x || !buf)
2918 goto fail;
2919
Sunil Ravia04bd252022-05-02 22:54:18 -07002920 if (EC_POINT_get_affine_coordinates(ecdh->ec->group, pubkey,
2921 x, y, ecdh->ec->bnctx) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07002923 "OpenSSL: EC_POINT_get_affine_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002924 ERR_error_string(ERR_get_error(), NULL));
2925 goto fail;
2926 }
2927
2928 res = crypto_bignum_to_bin((struct crypto_bignum *) x,
2929 wpabuf_put(buf, len), len, len);
2930 if (res < 0)
2931 goto fail;
2932
2933 if (inc_y) {
2934 res = crypto_bignum_to_bin((struct crypto_bignum *) y,
2935 wpabuf_put(buf, len), len, len);
2936 if (res < 0)
2937 goto fail;
2938 }
2939
2940done:
2941 BN_clear_free(x);
2942 BN_clear_free(y);
2943 EC_KEY_free(eckey);
2944
2945 return buf;
2946fail:
2947 wpabuf_free(buf);
2948 buf = NULL;
2949 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07002950#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002951}
2952
2953
2954struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
2955 const u8 *key, size_t len)
2956{
Sunil Ravia04bd252022-05-02 22:54:18 -07002957#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);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002966 if (!peer) {
2967 EVP_PKEY_free(peerkey);
Sunil Ravia04bd252022-05-02 22:54:18 -07002968 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002969 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002970 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 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003003 BIGNUM *x, *y = NULL;
3004 EVP_PKEY_CTX *ctx = NULL;
3005 EVP_PKEY *peerkey = NULL;
3006 struct wpabuf *secret = NULL;
3007 size_t secret_len;
3008 EC_POINT *pub;
3009 EC_KEY *eckey = NULL;
3010
3011 x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL);
3012 pub = EC_POINT_new(ecdh->ec->group);
3013 if (!x || !pub)
3014 goto fail;
3015
3016 if (inc_y) {
3017 y = BN_bin2bn(key + len / 2, len / 2, NULL);
3018 if (!y)
3019 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07003020 if (!EC_POINT_set_affine_coordinates(ecdh->ec->group, pub,
3021 x, y, ecdh->ec->bnctx)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003022 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07003023 "OpenSSL: EC_POINT_set_affine_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003024 ERR_error_string(ERR_get_error(), NULL));
3025 goto fail;
3026 }
Sunil Ravia04bd252022-05-02 22:54:18 -07003027 } else if (!EC_POINT_set_compressed_coordinates(ecdh->ec->group,
3028 pub, x, 0,
3029 ecdh->ec->bnctx)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003030 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07003031 "OpenSSL: EC_POINT_set_compressed_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003032 ERR_error_string(ERR_get_error(), NULL));
3033 goto fail;
3034 }
3035
3036 if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) {
3037 wpa_printf(MSG_ERROR,
3038 "OpenSSL: ECDH peer public key is not on curve");
3039 goto fail;
3040 }
3041
3042 eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid);
3043 if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) {
3044 wpa_printf(MSG_ERROR,
3045 "OpenSSL: EC_KEY_set_public_key failed: %s",
3046 ERR_error_string(ERR_get_error(), NULL));
3047 goto fail;
3048 }
3049
3050 peerkey = EVP_PKEY_new();
3051 if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1)
3052 goto fail;
3053
3054 ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL);
3055 if (!ctx || EVP_PKEY_derive_init(ctx) != 1 ||
3056 EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 ||
3057 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) {
3058 wpa_printf(MSG_ERROR,
3059 "OpenSSL: EVP_PKEY_derive(1) failed: %s",
3060 ERR_error_string(ERR_get_error(), NULL));
3061 goto fail;
3062 }
3063
3064 secret = wpabuf_alloc(secret_len);
3065 if (!secret)
3066 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07003067 if (EVP_PKEY_derive(ctx, wpabuf_put(secret, 0), &secret_len) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003068 wpa_printf(MSG_ERROR,
3069 "OpenSSL: EVP_PKEY_derive(2) failed: %s",
3070 ERR_error_string(ERR_get_error(), NULL));
3071 goto fail;
3072 }
Hai Shalomc3565922019-10-28 11:58:20 -07003073 if (secret->size != secret_len)
3074 wpa_printf(MSG_DEBUG,
3075 "OpenSSL: EVP_PKEY_derive(2) changed secret_len %d -> %d",
3076 (int) secret->size, (int) secret_len);
3077 wpabuf_put(secret, secret_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003078
3079done:
3080 BN_free(x);
3081 BN_free(y);
3082 EC_KEY_free(eckey);
3083 EC_POINT_free(pub);
3084 EVP_PKEY_CTX_free(ctx);
3085 EVP_PKEY_free(peerkey);
3086 return secret;
3087fail:
3088 wpabuf_free(secret);
3089 secret = NULL;
3090 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07003091#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003092}
3093
3094
3095void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
3096{
3097 if (ecdh) {
3098 crypto_ec_deinit(ecdh->ec);
3099 EVP_PKEY_free(ecdh->pkey);
3100 os_free(ecdh);
3101 }
3102}
3103
Hai Shalomfdcde762020-04-02 11:19:20 -07003104
3105size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
3106{
3107 return crypto_ec_prime_len(ecdh->ec);
3108}
3109
Hai Shalom899fcc72020-10-19 14:38:18 -07003110
Hai Shalom899fcc72020-10-19 14:38:18 -07003111struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
3112{
Sunil8cd6f4d2022-06-28 18:40:46 +00003113#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) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003124 wpa_printf(MSG_INFO,
3125 "OpenSSL: Decoding EC private key (DER) failed: %s",
Sunil8cd6f4d2022-06-28 18:40:46 +00003126 ERR_error_string(ERR_get_error(), NULL));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003127 if (ctx)
3128 OSSL_DECODER_CTX_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003129 goto fail;
3130 }
3131
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003132 OSSL_DECODER_CTX_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003133 return (struct crypto_ec_key *) pkey;
3134fail:
3135 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
3136 return NULL;
3137#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003138 EVP_PKEY *pkey = NULL;
3139 EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003140
Hai Shaloma20dcd72022-02-04 13:43:00 -08003141 eckey = d2i_ECPrivateKey(NULL, &der, der_len);
3142 if (!eckey) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003143 wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s",
3144 ERR_error_string(ERR_get_error(), NULL));
3145 goto fail;
3146 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003147 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
Hai Shalom899fcc72020-10-19 14:38:18 -07003148
Hai Shaloma20dcd72022-02-04 13:43:00 -08003149 pkey = EVP_PKEY_new();
3150 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3151 EC_KEY_free(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003152 goto fail;
3153 }
3154
Hai Shaloma20dcd72022-02-04 13:43:00 -08003155 return (struct crypto_ec_key *) pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003156fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003157 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003158 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003159#endif /* OpenSSL version >= 3.0 */
Hai Shalom899fcc72020-10-19 14:38:18 -07003160}
3161
3162
Sunil Ravi89eba102022-09-13 21:04:37 -07003163struct crypto_ec_key * crypto_ec_key_set_priv(int group,
3164 const u8 *raw, size_t raw_len)
3165{
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
3226out:
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
3235fail:
3236 EVP_PKEY_free(pkey);
3237 pkey = NULL;
3238 goto out;
3239#else /* OpenSSL version >= 3.0 */
3240 EC_KEY *eckey = NULL;
3241 EVP_PKEY *pkey = NULL;
3242 BIGNUM *priv = NULL;
3243 int nid;
3244 const EC_GROUP *ec_group;
3245 EC_POINT *pub = NULL;
3246
3247 nid = crypto_ec_group_2_nid(group);
3248 if (nid < 0) {
3249 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3250 return NULL;
3251 }
3252
3253 eckey = EC_KEY_new_by_curve_name(nid);
3254 priv = BN_bin2bn(raw, raw_len, NULL);
3255 if (!eckey || !priv ||
3256 EC_KEY_set_private_key(eckey, priv) != 1) {
3257 wpa_printf(MSG_ERROR,
3258 "OpenSSL: Failed to set EC_KEY: %s",
3259 ERR_error_string(ERR_get_error(), NULL));
3260 goto fail;
3261 }
3262
3263 ec_group = EC_KEY_get0_group(eckey);
3264 if (!ec_group)
3265 goto fail;
3266 pub = EC_POINT_new(ec_group);
3267 if (!pub ||
3268 EC_POINT_mul(ec_group, pub, priv, NULL, NULL, NULL) != 1 ||
3269 EC_KEY_set_public_key(eckey, pub) != 1) {
3270 wpa_printf(MSG_ERROR,
3271 "OpenSSL: Failed to set EC_KEY(pub): %s",
3272 ERR_error_string(ERR_get_error(), NULL));
3273 goto fail;
3274 }
3275
3276 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3277
3278 pkey = EVP_PKEY_new();
3279 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3280 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3281 goto fail;
3282 }
3283
3284out:
3285 BN_clear_free(priv);
3286 EC_POINT_free(pub);
3287 return (struct crypto_ec_key *) pkey;
3288
3289fail:
3290 EC_KEY_free(eckey);
3291 EVP_PKEY_free(pkey);
3292 pkey = NULL;
3293 goto out;
3294#endif /* OpenSSL version >= 3.0 */
3295}
3296
3297
Hai Shalom899fcc72020-10-19 14:38:18 -07003298struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
3299{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003300 EVP_PKEY *pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003301
Hai Shaloma20dcd72022-02-04 13:43:00 -08003302 pkey = d2i_PUBKEY(NULL, &der, der_len);
3303 if (!pkey) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003304 wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s",
3305 ERR_error_string(ERR_get_error(), NULL));
3306 goto fail;
3307 }
3308
Hai Shaloma20dcd72022-02-04 13:43:00 -08003309 /* Ensure this is an EC key */
Sunil8cd6f4d2022-06-28 18:40:46 +00003310#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3311 if (!EVP_PKEY_is_a(pkey, "EC"))
3312 goto fail;
3313#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003314 if (!EVP_PKEY_get0_EC_KEY(pkey))
Hai Shalom899fcc72020-10-19 14:38:18 -07003315 goto fail;
Sunil8cd6f4d2022-06-28 18:40:46 +00003316#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003317 return (struct crypto_ec_key *) pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003318fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003319 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003320 return NULL;
3321}
3322
3323
Hai Shaloma20dcd72022-02-04 13:43:00 -08003324struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x,
3325 const u8 *buf_y, size_t len)
3326{
Sunil8cd6f4d2022-06-28 18:40:46 +00003327#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 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003368 EC_KEY *eckey = NULL;
3369 EVP_PKEY *pkey = NULL;
3370 EC_GROUP *ec_group = NULL;
3371 BN_CTX *ctx;
3372 EC_POINT *point = NULL;
3373 BIGNUM *x = NULL, *y = NULL;
3374 int nid;
3375
3376 if (!buf_x || !buf_y)
3377 return NULL;
3378
3379 nid = crypto_ec_group_2_nid(group);
3380 if (nid < 0) {
3381 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3382 return NULL;
3383 }
3384
3385 ctx = BN_CTX_new();
3386 if (!ctx)
3387 goto fail;
3388
3389 ec_group = EC_GROUP_new_by_curve_name(nid);
3390 if (!ec_group)
3391 goto fail;
3392
3393 x = BN_bin2bn(buf_x, len, NULL);
3394 y = BN_bin2bn(buf_y, len, NULL);
3395 point = EC_POINT_new(ec_group);
3396 if (!x || !y || !point)
3397 goto fail;
3398
Sunil Ravia04bd252022-05-02 22:54:18 -07003399 if (!EC_POINT_set_affine_coordinates(ec_group, point, x, y, ctx)) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003400 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07003401 "OpenSSL: EC_POINT_set_affine_coordinates failed: %s",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003402 ERR_error_string(ERR_get_error(), NULL));
3403 goto fail;
3404 }
3405
3406 if (!EC_POINT_is_on_curve(ec_group, point, ctx) ||
3407 EC_POINT_is_at_infinity(ec_group, point)) {
3408 wpa_printf(MSG_ERROR, "OpenSSL: Invalid point");
3409 goto fail;
3410 }
3411
3412 eckey = EC_KEY_new();
3413 if (!eckey ||
3414 EC_KEY_set_group(eckey, ec_group) != 1 ||
3415 EC_KEY_set_public_key(eckey, point) != 1) {
3416 wpa_printf(MSG_ERROR,
3417 "OpenSSL: Failed to set EC_KEY: %s",
3418 ERR_error_string(ERR_get_error(), NULL));
3419 goto fail;
3420 }
3421 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3422
3423 pkey = EVP_PKEY_new();
3424 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3425 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3426 goto fail;
3427 }
3428
3429out:
3430 EC_GROUP_free(ec_group);
3431 BN_free(x);
3432 BN_free(y);
3433 EC_POINT_free(point);
3434 BN_CTX_free(ctx);
3435 return (struct crypto_ec_key *) pkey;
3436
3437fail:
3438 EC_KEY_free(eckey);
3439 EVP_PKEY_free(pkey);
3440 pkey = NULL;
3441 goto out;
Sunil8cd6f4d2022-06-28 18:40:46 +00003442#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003443}
3444
3445
3446struct crypto_ec_key *
3447crypto_ec_key_set_pub_point(struct crypto_ec *ec,
3448 const struct crypto_ec_point *pub)
3449{
Sunil8cd6f4d2022-06-28 18:40:46 +00003450#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 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003468 EC_KEY *eckey;
3469 EVP_PKEY *pkey = NULL;
3470
3471 eckey = EC_KEY_new();
3472 if (!eckey ||
3473 EC_KEY_set_group(eckey, ec->group) != 1 ||
3474 EC_KEY_set_public_key(eckey, (const EC_POINT *) pub) != 1) {
3475 wpa_printf(MSG_ERROR,
3476 "OpenSSL: Failed to set EC_KEY: %s",
3477 ERR_error_string(ERR_get_error(), NULL));
3478 goto fail;
3479 }
3480 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3481
3482 pkey = EVP_PKEY_new();
3483 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3484 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3485 goto fail;
3486 }
3487
3488out:
3489 return (struct crypto_ec_key *) pkey;
3490
3491fail:
3492 EVP_PKEY_free(pkey);
3493 EC_KEY_free(eckey);
3494 pkey = NULL;
3495 goto out;
Sunil8cd6f4d2022-06-28 18:40:46 +00003496#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003497}
3498
3499
3500struct crypto_ec_key * crypto_ec_key_gen(int group)
3501{
Sunil8cd6f4d2022-06-28 18:40:46 +00003502#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,
Sunil Ravi876a49b2025-02-03 19:18:32 +00003522 "OpenSSL: Failed to generate EC keypair (group=%d): %s",
3523 group, ERR_error_string(ERR_get_error(), NULL));
Sunil8cd6f4d2022-06-28 18:40:46 +00003524 pkey = NULL;
3525 }
3526
3527 EVP_PKEY_CTX_free(ctx);
3528
3529 return (struct crypto_ec_key *) pkey;
3530#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003531 EVP_PKEY_CTX *kctx = NULL;
3532 EC_KEY *ec_params = NULL, *eckey;
3533 EVP_PKEY *params = NULL, *key = NULL;
3534 int nid;
3535
3536 nid = crypto_ec_group_2_nid(group);
3537 if (nid < 0) {
3538 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3539 return NULL;
3540 }
3541
3542 ec_params = EC_KEY_new_by_curve_name(nid);
3543 if (!ec_params) {
3544 wpa_printf(MSG_ERROR,
3545 "OpenSSL: Failed to generate EC_KEY parameters");
3546 goto fail;
3547 }
3548 EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
3549 params = EVP_PKEY_new();
3550 if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
3551 wpa_printf(MSG_ERROR,
3552 "OpenSSL: Failed to generate EVP_PKEY parameters");
3553 goto fail;
3554 }
3555
3556 kctx = EVP_PKEY_CTX_new(params, NULL);
3557 if (!kctx ||
3558 EVP_PKEY_keygen_init(kctx) != 1 ||
3559 EVP_PKEY_keygen(kctx, &key) != 1) {
3560 wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC key");
3561 key = NULL;
3562 goto fail;
3563 }
3564
3565 eckey = EVP_PKEY_get1_EC_KEY(key);
3566 if (!eckey) {
3567 key = NULL;
3568 goto fail;
3569 }
3570 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
3571 EC_KEY_free(eckey);
3572
3573fail:
3574 EC_KEY_free(ec_params);
3575 EVP_PKEY_free(params);
3576 EVP_PKEY_CTX_free(kctx);
3577 return (struct crypto_ec_key *) key;
Sunil8cd6f4d2022-06-28 18:40:46 +00003578#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003579}
3580
3581
Hai Shalom899fcc72020-10-19 14:38:18 -07003582void crypto_ec_key_deinit(struct crypto_ec_key *key)
3583{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003584 EVP_PKEY_free((EVP_PKEY *) key);
Hai Shalom899fcc72020-10-19 14:38:18 -07003585}
3586
3587
Hai Shaloma20dcd72022-02-04 13:43:00 -08003588#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
3597typedef 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
3605ASN1_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
3610IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY);
3611
3612#endif /* OPENSSL_IS_BORINGSSL */
3613
3614
Hai Shalom899fcc72020-10-19 14:38:18 -07003615struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
3616{
Sunil8cd6f4d2022-06-28 18:40:46 +00003617 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 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003665#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();
Sunil8cd6f4d2022-06-28 18:40:46 +00003678 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003679 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);
3721fail:
3722 EC_COMP_PUBKEY_free(pubkey);
3723 OPENSSL_free(der);
3724 BN_CTX_free(ctx);
3725 return ret;
3726#else /* OPENSSL_IS_BORINGSSL */
Hai Shalom899fcc72020-10-19 14:38:18 -07003727 unsigned char *der = NULL;
3728 int der_len;
3729 struct wpabuf *buf;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003730 EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003731
Sunil8cd6f4d2022-06-28 18:40:46 +00003732 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003733 if (!eckey)
3734 return NULL;
3735
3736 /* For now, all users expect COMPRESSED form */
3737 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
3738
Hai Shaloma20dcd72022-02-04 13:43:00 -08003739 der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
3740 EC_KEY_free(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003741 if (der_len <= 0) {
3742 wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
3743 ERR_error_string(ERR_get_error(), NULL));
3744 return NULL;
3745 }
3746
3747 buf = wpabuf_alloc_copy(der, der_len);
3748 OPENSSL_free(der);
3749 return buf;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003750#endif /* OPENSSL_IS_BORINGSSL */
Sunil8cd6f4d2022-06-28 18:40:46 +00003751#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003752}
3753
3754
3755struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
3756 bool include_pub)
3757{
Sunil8cd6f4d2022-06-28 18:40:46 +00003758 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) {
Sunil Ravi876a49b2025-02-03 19:18:32 +00003786 wpa_printf(MSG_INFO, "OpenSSL: OSSL_ENCODER failed: %s",
3787 ERR_error_string(ERR_get_error(), NULL));
Sunil8cd6f4d2022-06-28 18:40:46 +00003788 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 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003798 EC_KEY *eckey;
3799 unsigned char *der = NULL;
3800 int der_len;
3801 struct wpabuf *buf;
3802 unsigned int key_flags;
3803
Sunil8cd6f4d2022-06-28 18:40:46 +00003804 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003805 if (!eckey)
3806 return NULL;
3807
3808 key_flags = EC_KEY_get_enc_flags(eckey);
3809 if (include_pub)
3810 key_flags &= ~EC_PKEY_NO_PUBKEY;
3811 else
3812 key_flags |= EC_PKEY_NO_PUBKEY;
3813 EC_KEY_set_enc_flags(eckey, key_flags);
3814
3815 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
3816
3817 der_len = i2d_ECPrivateKey(eckey, &der);
3818 EC_KEY_free(eckey);
3819 if (der_len <= 0)
3820 return NULL;
3821 buf = wpabuf_alloc_copy(der, der_len);
3822 OPENSSL_free(der);
3823
3824 return buf;
Sunil8cd6f4d2022-06-28 18:40:46 +00003825#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003826}
3827
3828
3829struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
3830 int prefix)
3831{
Sunil8cd6f4d2022-06-28 18:40:46 +00003832 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 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003866 int len, res;
3867 EC_KEY *eckey;
3868 struct wpabuf *buf;
3869 unsigned char *pos;
3870
Sunil8cd6f4d2022-06-28 18:40:46 +00003871 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003872 if (!eckey)
3873 return NULL;
3874 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
3875 len = i2o_ECPublicKey(eckey, NULL);
3876 if (len <= 0) {
3877 wpa_printf(MSG_ERROR,
3878 "OpenSSL: Failed to determine public key encoding length");
3879 EC_KEY_free(eckey);
3880 return NULL;
3881 }
3882
3883 buf = wpabuf_alloc(len);
3884 if (!buf) {
3885 EC_KEY_free(eckey);
3886 return NULL;
3887 }
3888
3889 pos = wpabuf_put(buf, len);
3890 res = i2o_ECPublicKey(eckey, &pos);
3891 EC_KEY_free(eckey);
3892 if (res != len) {
3893 wpa_printf(MSG_ERROR,
3894 "OpenSSL: Failed to encode public key (res=%d/%d)",
3895 res, len);
3896 wpabuf_free(buf);
3897 return NULL;
3898 }
3899
3900 if (!prefix) {
3901 /* Remove 0x04 prefix if requested */
3902 pos = wpabuf_mhead(buf);
3903 os_memmove(pos, pos + 1, len - 1);
3904 buf->used--;
3905 }
3906
3907 return buf;
Sunil8cd6f4d2022-06-28 18:40:46 +00003908#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003909}
3910
3911
Sunil8cd6f4d2022-06-28 18:40:46 +00003912struct crypto_ec_point *
Hai Shaloma20dcd72022-02-04 13:43:00 -08003913crypto_ec_key_get_public_key(struct crypto_ec_key *key)
3914{
Sunil8cd6f4d2022-06-28 18:40:46 +00003915 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];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003924
Sunil8cd6f4d2022-06-28 18:40:46 +00003925 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
3943fail:
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 const EC_KEY *eckey;
3954 const EC_POINT *point;
3955 const EC_GROUP *group;
3956
3957 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003958 if (!eckey)
3959 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003960 group = EC_KEY_get0_group(eckey);
3961 if (!group)
3962 return NULL;
3963 point = EC_KEY_get0_public_key(eckey);
3964 if (!point)
3965 return NULL;
3966 return (struct crypto_ec_point *) EC_POINT_dup(point, group);
3967#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003968}
3969
3970
Sunil8cd6f4d2022-06-28 18:40:46 +00003971struct crypto_bignum *
Hai Shaloma20dcd72022-02-04 13:43:00 -08003972crypto_ec_key_get_private_key(struct crypto_ec_key *key)
3973{
Sunil8cd6f4d2022-06-28 18:40:46 +00003974 EVP_PKEY *pkey = (EVP_PKEY *) key;
3975#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3976 BIGNUM *bn = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003977
Sunil8cd6f4d2022-06-28 18:40:46 +00003978 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 const EC_KEY *eckey;
3984 const BIGNUM *bn;
3985
3986 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003987 if (!eckey)
3988 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003989 bn = EC_KEY_get0_private_key(eckey);
3990 if (!bn)
3991 return NULL;
3992 return (struct crypto_bignum *) BN_dup(bn);
3993#endif /* OpenSSL version >= 3.0 */
Hai Shalom899fcc72020-10-19 14:38:18 -07003994}
3995
3996
3997struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
3998 size_t len)
3999{
4000 EVP_PKEY_CTX *pkctx;
4001 struct wpabuf *sig_der;
4002 size_t sig_len;
4003
Hai Shaloma20dcd72022-02-04 13:43:00 -08004004 sig_len = EVP_PKEY_size((EVP_PKEY *) key);
Hai Shalom899fcc72020-10-19 14:38:18 -07004005 sig_der = wpabuf_alloc(sig_len);
4006 if (!sig_der)
4007 return NULL;
4008
Hai Shaloma20dcd72022-02-04 13:43:00 -08004009 pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004010 if (!pkctx ||
4011 EVP_PKEY_sign_init(pkctx) <= 0 ||
4012 EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len,
4013 data, len) <= 0) {
4014 wpabuf_free(sig_der);
4015 sig_der = NULL;
4016 } else {
4017 wpabuf_put(sig_der, sig_len);
4018 }
4019
4020 EVP_PKEY_CTX_free(pkctx);
4021 return sig_der;
4022}
4023
4024
Sunil Ravia04bd252022-05-02 22:54:18 -07004025static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key)
Hai Shaloma20dcd72022-02-04 13:43:00 -08004026{
Sunil Ravia04bd252022-05-02 22:54:18 -07004027#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)
Sunil Ravi99c035e2024-07-12 01:42:03 +00004041 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07004042 if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1)
4043 prime_len = BN_num_bytes(prime);
Sunil Ravi99c035e2024-07-12 01:42:03 +00004044fail:
Sunil Ravia04bd252022-05-02 22:54:18 -07004045 EC_GROUP_free(group);
4046 BN_free(prime);
4047 return prime_len;
4048#else
Hai Shaloma20dcd72022-02-04 13:43:00 -08004049 const EC_GROUP *group;
4050 const EC_KEY *eckey;
4051 BIGNUM *prime = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004052 int prime_len = -1;
4053
4054 eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
4055 if (!eckey)
4056 goto fail;
4057 group = EC_KEY_get0_group(eckey);
4058 prime = BN_new();
4059 if (!prime || !group ||
4060 !EC_GROUP_get_curve(group, prime, NULL, NULL, NULL))
4061 goto fail;
4062 prime_len = BN_num_bytes(prime);
4063fail:
4064 BN_free(prime);
4065 return prime_len;
4066#endif
4067}
4068
4069
4070struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
4071 const u8 *data, size_t len)
4072{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004073 ECDSA_SIG *sig = NULL;
4074 const BIGNUM *r, *s;
4075 u8 *r_buf, *s_buf;
4076 struct wpabuf *buf;
4077 const unsigned char *p;
4078 int prime_len;
4079
Sunil Ravia04bd252022-05-02 22:54:18 -07004080 prime_len = openssl_evp_pkey_ec_prime_len(key);
4081 if (prime_len < 0)
4082 return NULL;
4083
Hai Shaloma20dcd72022-02-04 13:43:00 -08004084 buf = crypto_ec_key_sign(key, data, len);
4085 if (!buf)
4086 return NULL;
4087
4088 /* Extract (r,s) from Ecdsa-Sig-Value */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004089
4090 p = wpabuf_head(buf);
4091 sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf));
4092 if (!sig)
4093 goto fail;
4094 ECDSA_SIG_get0(sig, &r, &s);
4095
4096 /* Re-use wpabuf returned by crypto_ec_key_sign() */
4097 buf->used = 0;
4098 r_buf = wpabuf_put(buf, prime_len);
4099 s_buf = wpabuf_put(buf, prime_len);
4100 if (crypto_bignum_to_bin((const struct crypto_bignum *) r, r_buf,
4101 prime_len, prime_len) < 0 ||
4102 crypto_bignum_to_bin((const struct crypto_bignum *) s, s_buf,
4103 prime_len, prime_len) < 0)
4104 goto fail;
4105
4106out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004107 ECDSA_SIG_free(sig);
4108 return buf;
4109fail:
4110 wpabuf_clear_free(buf);
4111 buf = NULL;
4112 goto out;
4113}
4114
4115
Hai Shalom899fcc72020-10-19 14:38:18 -07004116int 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{
4119 EVP_PKEY_CTX *pkctx;
4120 int ret;
4121
Hai Shaloma20dcd72022-02-04 13:43:00 -08004122 pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004123 if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) {
4124 EVP_PKEY_CTX_free(pkctx);
4125 return -1;
4126 }
4127
4128 ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len);
4129 EVP_PKEY_CTX_free(pkctx);
4130 if (ret == 1)
4131 return 1; /* signature ok */
4132 if (ret == 0)
4133 return 0; /* incorrect signature */
4134 return -1;
4135}
4136
4137
Hai Shaloma20dcd72022-02-04 13:43:00 -08004138int 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{
4143 ECDSA_SIG *sig;
4144 BIGNUM *r_bn, *s_bn;
4145 unsigned char *der = NULL;
4146 int der_len;
4147 int ret = -1;
4148
4149 r_bn = BN_bin2bn(r, r_len, NULL);
4150 s_bn = BN_bin2bn(s, s_len, NULL);
4151 sig = ECDSA_SIG_new();
4152 if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1)
4153 goto fail;
4154 r_bn = NULL;
4155 s_bn = NULL;
4156
4157 der_len = i2d_ECDSA_SIG(sig, &der);
4158 if (der_len <= 0) {
4159 wpa_printf(MSG_DEBUG,
4160 "OpenSSL: Could not DER encode signature");
4161 goto fail;
4162 }
4163
4164 ret = crypto_ec_key_verify_signature(key, data, len, der, der_len);
4165
4166fail:
4167 OPENSSL_free(der);
4168 BN_free(r_bn);
4169 BN_free(s_bn);
4170 ECDSA_SIG_free(sig);
4171 return ret;
4172}
4173
4174
Hai Shalom899fcc72020-10-19 14:38:18 -07004175int crypto_ec_key_group(struct crypto_ec_key *key)
4176{
Sunil Ravia04bd252022-05-02 22:54:18 -07004177#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
Hai Shaloma20dcd72022-02-04 13:43:00 -08004186 const EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07004187 const EC_GROUP *group;
4188 int nid;
4189
Hai Shaloma20dcd72022-02-04 13:43:00 -08004190 eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
4191 if (!eckey)
4192 return -1;
4193 group = EC_KEY_get0_group(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07004194 if (!group)
4195 return -1;
4196 nid = EC_GROUP_get_curve_name(group);
Sunil Ravia04bd252022-05-02 22:54:18 -07004197#endif
Hai Shalom899fcc72020-10-19 14:38:18 -07004198 switch (nid) {
4199 case NID_X9_62_prime256v1:
4200 return 19;
4201 case NID_secp384r1:
4202 return 20;
4203 case NID_secp521r1:
4204 return 21;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004205#ifdef NID_brainpoolP256r1
4206 case NID_brainpoolP256r1:
4207 return 28;
4208#endif /* NID_brainpoolP256r1 */
4209#ifdef NID_brainpoolP384r1
4210 case NID_brainpoolP384r1:
4211 return 29;
4212#endif /* NID_brainpoolP384r1 */
4213#ifdef NID_brainpoolP512r1
4214 case NID_brainpoolP512r1:
4215 return 30;
4216#endif /* NID_brainpoolP512r1 */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004217 default:
4218 wpa_printf(MSG_ERROR,
4219 "OpenSSL: Unsupported curve (nid=%d) in EC key",
4220 nid);
4221 return -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07004222 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004223}
4224
Hai Shaloma20dcd72022-02-04 13:43:00 -08004225
4226int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
4227{
Sunil Ravia04bd252022-05-02 22:54:18 -07004228#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4229 if (EVP_PKEY_eq((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1)
4230 return -1;
4231#else
Hai Shaloma20dcd72022-02-04 13:43:00 -08004232 if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1)
4233 return -1;
Sunil Ravia04bd252022-05-02 22:54:18 -07004234#endif
Hai Shaloma20dcd72022-02-04 13:43:00 -08004235 return 0;
4236}
4237
4238
4239void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
4240 const char *title)
4241{
4242 BIO *out;
4243 size_t rlen;
4244 char *txt;
4245 int res;
4246
4247 out = BIO_new(BIO_s_mem());
4248 if (!out)
4249 return;
4250
4251 EVP_PKEY_print_private(out, (EVP_PKEY *) key, 0, NULL);
4252 rlen = BIO_ctrl_pending(out);
4253 txt = os_malloc(rlen + 1);
4254 if (txt) {
4255 res = BIO_read(out, txt, rlen);
4256 if (res > 0) {
4257 txt[res] = '\0';
4258 wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
4259 }
4260 os_free(txt);
4261 }
4262 BIO_free(out);
4263}
4264
4265
4266struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
4267{
4268#ifdef OPENSSL_IS_BORINGSSL
4269 CBS pkcs7_cbs;
4270#else /* OPENSSL_IS_BORINGSSL */
4271 PKCS7 *p7 = NULL;
4272 const unsigned char *p = wpabuf_head(pkcs7);
4273#endif /* OPENSSL_IS_BORINGSSL */
4274 STACK_OF(X509) *certs;
4275 int i, num;
4276 BIO *out = NULL;
4277 size_t rlen;
4278 struct wpabuf *pem = NULL;
4279 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 p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
4294 if (!p7) {
4295 wpa_printf(MSG_INFO,
4296 "OpenSSL: Could not parse PKCS#7 object: %s",
4297 ERR_error_string(ERR_get_error(), NULL));
4298 goto fail;
4299 }
4300
4301 switch (OBJ_obj2nid(p7->type)) {
4302 case NID_pkcs7_signed:
4303 certs = p7->d.sign->cert;
4304 break;
4305 case NID_pkcs7_signedAndEnveloped:
4306 certs = p7->d.signed_and_enveloped->cert;
4307 break;
4308 default:
4309 certs = NULL;
4310 break;
4311 }
4312#endif /* OPENSSL_IS_BORINGSSL */
4313
4314 if (!certs || ((num = sk_X509_num(certs)) == 0)) {
4315 wpa_printf(MSG_INFO,
4316 "OpenSSL: No certificates found in PKCS#7 object");
4317 goto fail;
4318 }
4319
4320 out = BIO_new(BIO_s_mem());
4321 if (!out)
4322 goto fail;
4323
4324 for (i = 0; i < num; i++) {
4325 X509 *cert = sk_X509_value(certs, i);
4326
4327 PEM_write_bio_X509(out, cert);
4328 }
4329
4330 rlen = BIO_ctrl_pending(out);
4331 pem = wpabuf_alloc(rlen);
4332 if (!pem)
4333 goto fail;
4334 res = BIO_read(out, wpabuf_put(pem, 0), rlen);
4335 if (res <= 0) {
4336 wpabuf_free(pem);
4337 pem = NULL;
4338 goto fail;
4339 }
4340 wpabuf_put(pem, res);
4341
4342fail:
4343#ifdef OPENSSL_IS_BORINGSSL
4344 if (certs)
4345 sk_X509_pop_free(certs, X509_free);
4346#else /* OPENSSL_IS_BORINGSSL */
4347 PKCS7_free(p7);
4348#endif /* OPENSSL_IS_BORINGSSL */
4349 if (out)
4350 BIO_free_all(out);
4351
4352 return pem;
4353}
4354
4355
Sunil Ravi876a49b2025-02-03 19:18:32 +00004356struct crypto_csr * crypto_csr_init(void)
Hai Shaloma20dcd72022-02-04 13:43:00 -08004357{
4358 return (struct crypto_csr *)X509_REQ_new();
4359}
4360
4361
4362struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
4363{
4364 X509_REQ *csr;
4365 EVP_PKEY *pkey = NULL;
4366 const u8 *der = wpabuf_head(req);
4367
4368 csr = d2i_X509_REQ(NULL, &der, wpabuf_len(req));
4369 if (!csr)
4370 return NULL;
4371
4372 pkey = X509_REQ_get_pubkey((X509_REQ *)csr);
4373 if (!pkey)
4374 goto fail;
4375
4376 if (X509_REQ_verify((X509_REQ *)csr, pkey) != 1)
4377 goto fail;
4378
4379 return (struct crypto_csr *)csr;
4380fail:
4381 X509_REQ_free(csr);
4382 return NULL;
4383}
4384
4385
4386void crypto_csr_deinit(struct crypto_csr *csr)
4387{
4388 X509_REQ_free((X509_REQ *)csr);
4389}
4390
4391
4392int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key)
4393{
4394 if (!X509_REQ_set_pubkey((X509_REQ *)csr, (EVP_PKEY *)key))
4395 return -1;
4396
4397 return 0;
4398}
4399
4400
4401int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
4402 const char *name)
4403{
4404 X509_NAME *n;
4405 int nid;
4406
4407 switch (type) {
4408 case CSR_NAME_CN:
4409 nid = NID_commonName;
4410 break;
4411 case CSR_NAME_SN:
4412 nid = NID_surname;
4413 break;
4414 case CSR_NAME_C:
4415 nid = NID_countryName;
4416 break;
4417 case CSR_NAME_O:
4418 nid = NID_organizationName;
4419 break;
4420 case CSR_NAME_OU:
4421 nid = NID_organizationalUnitName;
4422 break;
4423 default:
4424 return -1;
4425 }
4426
4427 n = X509_REQ_get_subject_name((X509_REQ *) csr);
4428 if (!n)
4429 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 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8,
4438 (const unsigned char *) name,
4439 os_strlen(name), -1, 0))
4440 return -1;
4441#endif
4442
4443 return 0;
4444}
4445
4446
4447int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
4448 int attr_type, const u8 *value, size_t len)
4449{
4450 int nid;
4451
4452 switch (attr) {
4453 case CSR_ATTR_CHALLENGE_PASSWORD:
4454 nid = NID_pkcs9_challengePassword;
4455 break;
4456 default:
4457 return -1;
4458 }
4459
4460 if (!X509_REQ_add1_attr_by_NID((X509_REQ *) csr, nid, attr_type, value,
4461 len))
4462 return -1;
4463
4464 return 0;
4465}
4466
4467
4468const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
4469 enum crypto_csr_attr attr,
4470 size_t *len, int *type)
4471{
4472 X509_ATTRIBUTE *attrib;
4473 ASN1_TYPE *attrib_type;
4474 ASN1_STRING *data;
4475 int loc;
4476 int nid;
4477
4478 switch (attr) {
4479 case CSR_ATTR_CHALLENGE_PASSWORD:
4480 nid = NID_pkcs9_challengePassword;
4481 break;
4482 default:
4483 return NULL;
4484 }
4485
4486 loc = X509_REQ_get_attr_by_NID((X509_REQ *) csr, nid, -1);
4487 if (loc < 0)
4488 return NULL;
4489
4490 attrib = X509_REQ_get_attr((X509_REQ *) csr, loc);
4491 if (!attrib)
4492 return NULL;
4493
4494 attrib_type = X509_ATTRIBUTE_get0_type(attrib, 0);
4495 if (!attrib_type)
4496 return NULL;
4497 *type = ASN1_TYPE_get(attrib_type);
4498 data = X509_ATTRIBUTE_get0_data(attrib, 0, *type, NULL);
4499 if (!data)
4500 return NULL;
4501 *len = ASN1_STRING_length(data);
4502 return ASN1_STRING_get0_data(data);
4503}
4504
4505
4506struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
4507 struct crypto_ec_key *key,
4508 enum crypto_hash_alg algo)
4509{
4510 const EVP_MD *sign_md;
4511 struct wpabuf *buf;
4512 unsigned char *der = NULL;
4513 int der_len;
4514
4515 switch (algo) {
4516 case CRYPTO_HASH_ALG_SHA256:
4517 sign_md = EVP_sha256();
4518 break;
4519 case CRYPTO_HASH_ALG_SHA384:
4520 sign_md = EVP_sha384();
4521 break;
4522 case CRYPTO_HASH_ALG_SHA512:
4523 sign_md = EVP_sha512();
4524 break;
4525 default:
4526 return NULL;
4527 }
4528
4529 if (!X509_REQ_sign((X509_REQ *) csr, (EVP_PKEY *) key, sign_md))
4530 return NULL;
4531
4532 der_len = i2d_X509_REQ((X509_REQ *) csr, &der);
4533 if (der_len < 0)
4534 return NULL;
4535
4536 buf = wpabuf_alloc_copy(der, der_len);
4537 OPENSSL_free(der);
4538
4539 return buf;
4540}
4541
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004542#endif /* CONFIG_ECC */
Sunil Ravia04bd252022-05-02 22:54:18 -07004543
4544
4545static EVP_PKEY * crypto_rsa_key_read_public(FILE *f)
4546{
4547 EVP_PKEY *pkey;
4548 X509 *x509;
Sunil8cd6f4d2022-06-28 18:40:46 +00004549 const ASN1_TIME *not_before, *not_after;
4550 int res_before, res_after;
Sunil Ravia04bd252022-05-02 22:54:18 -07004551
4552 pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
4553 if (pkey)
4554 return pkey;
4555
4556 rewind(f);
4557 x509 = PEM_read_X509(f, NULL, NULL, NULL);
4558 if (!x509)
4559 return NULL;
4560
Sunil8cd6f4d2022-06-28 18:40:46 +00004561 not_before = X509_get0_notBefore(x509);
4562 not_after = X509_get0_notAfter(x509);
4563 if (!not_before || !not_after)
4564 goto fail;
4565 res_before = X509_cmp_current_time(not_before);
4566 res_after = X509_cmp_current_time(not_after);
4567 if (!res_before || !res_after)
4568 goto fail;
4569 if (res_before > 0 || res_after < 0) {
4570 wpa_printf(MSG_INFO,
4571 "OpenSSL: Certificate for RSA public key is not valid at this time (%d %d)",
4572 res_before, res_after);
4573 goto fail;
4574 }
4575
Sunil Ravia04bd252022-05-02 22:54:18 -07004576 pkey = X509_get_pubkey(x509);
4577 X509_free(x509);
4578
4579 if (!pkey)
4580 return NULL;
4581 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
Sunil8cd6f4d2022-06-28 18:40:46 +00004582 wpa_printf(MSG_INFO, "OpenSSL: No RSA public key found");
Sunil Ravia04bd252022-05-02 22:54:18 -07004583 EVP_PKEY_free(pkey);
4584 return NULL;
4585 }
4586
4587 return pkey;
Sunil8cd6f4d2022-06-28 18:40:46 +00004588fail:
4589 X509_free(x509);
4590 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004591}
4592
4593
4594struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key)
4595{
4596 FILE *f;
4597 EVP_PKEY *pkey;
4598
4599 f = fopen(file, "r");
4600 if (!f)
4601 return NULL;
4602 if (private_key)
4603 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
4604 else
4605 pkey = crypto_rsa_key_read_public(f);
4606 fclose(f);
4607 return (struct crypto_rsa_key *) pkey;
4608}
4609
4610
4611#ifndef OPENSSL_NO_SHA256
4612
4613struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key,
4614 const struct wpabuf *in)
4615{
4616#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L
4617 EVP_PKEY *pkey = (EVP_PKEY *) key;
4618 EVP_PKEY_CTX *pkctx;
4619 struct wpabuf *res = NULL;
4620 size_t outlen;
4621
4622 pkctx = EVP_PKEY_CTX_new(pkey, NULL);
4623 if (!pkctx)
4624 goto fail;
4625
4626 if (EVP_PKEY_encrypt_init(pkctx) != 1 ||
4627 EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
4628 EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 ||
4629 EVP_PKEY_encrypt(pkctx, NULL, &outlen, wpabuf_head(in),
4630 wpabuf_len(in)) != 1 ||
4631 !(res = wpabuf_alloc(outlen)) ||
4632 EVP_PKEY_encrypt(pkctx, wpabuf_put(res, 0), &outlen,
4633 wpabuf_head(in), wpabuf_len(in)) != 1) {
4634 wpabuf_free(res);
4635 res = NULL;
4636 goto fail;
4637 }
4638 wpabuf_put(res, outlen);
4639
4640fail:
4641 EVP_PKEY_CTX_free(pkctx);
4642 return res;
4643#else
4644 wpa_printf(MSG_ERROR, "%s() not supported", __func__);
4645 return NULL;
4646#endif
4647}
4648
4649
4650struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key,
4651 const struct wpabuf *in)
4652{
4653#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L
4654 EVP_PKEY *pkey = (EVP_PKEY *) key;
4655 EVP_PKEY_CTX *pkctx;
4656 struct wpabuf *res = NULL;
4657 size_t outlen;
4658
4659 pkctx = EVP_PKEY_CTX_new(pkey, NULL);
4660 if (!pkctx)
4661 goto fail;
4662
4663 if (EVP_PKEY_decrypt_init(pkctx) != 1 ||
4664 EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
4665 EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 ||
4666 EVP_PKEY_decrypt(pkctx, NULL, &outlen, wpabuf_head(in),
4667 wpabuf_len(in)) != 1 ||
4668 !(res = wpabuf_alloc(outlen)) ||
4669 EVP_PKEY_decrypt(pkctx, wpabuf_put(res, 0), &outlen,
4670 wpabuf_head(in), wpabuf_len(in)) != 1) {
4671 wpabuf_free(res);
4672 res = NULL;
4673 goto fail;
4674 }
4675 wpabuf_put(res, outlen);
4676
4677fail:
4678 EVP_PKEY_CTX_free(pkctx);
4679 return res;
4680#else
4681 wpa_printf(MSG_ERROR, "%s() not supported", __func__);
4682 return NULL;
4683#endif
4684}
4685
4686#endif /* OPENSSL_NO_SHA256 */
4687
4688
4689void crypto_rsa_key_free(struct crypto_rsa_key *key)
4690{
4691 EVP_PKEY_free((EVP_PKEY *) key);
4692}
4693
4694
Sunil Ravi89eba102022-09-13 21:04:37 -07004695#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
4703struct 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
4729static void hpke_free_context(struct hpke_context *ctx)
4730{
4731 bin_clear_free(ctx, sizeof(*ctx));
4732}
4733
4734
4735static 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;
4830fail:
4831 hpke_free_context(ctx);
4832 return NULL;
4833}
4834
4835
4836static 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
4855static 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
Sunil Ravi876a49b2025-02-03 19:18:32 +00004901 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));
Sunil Ravi89eba102022-09-13 21:04:37 -07004905 goto fail;
Sunil Ravi876a49b2025-02-03 19:18:32 +00004906 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004907
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;
4919fail:
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);
4937done:
4938 HMAC_CTX_free(hctx);
4939
4940 return res == 1 ? 0 : -1;
4941#endif /* OpenSSL version >= 3.0 */
4942}
4943
4944
4945static int
4946hpke_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;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004987 if (info && info_len)
Sunil Ravi89eba102022-09-13 21:04:37 -07004988 os_memcpy(pos, info, info_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07004989
4990 pos = out;
4991#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4992 hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
4993 if (!hmac)
Sunil Ravi99c035e2024-07-12 01:42:03 +00004994 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07004995
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)
Sunil Ravi99c035e2024-07-12 01:42:03 +00005003 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07005004#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)
Sunil Ravi99c035e2024-07-12 01:42:03 +00005012 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07005013
Sunil Ravi876a49b2025-02-03 19:18:32 +00005014 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));
Sunil Ravi89eba102022-09-13 21:04:37 -07005018 goto fail;
Sunil Ravi876a49b2025-02-03 19:18:32 +00005019 }
Sunil Ravi89eba102022-09-13 21:04:37 -07005020
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;
5058fail:
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
5071static 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
5103static 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;
5142fail:
5143 forced_memzero(key_schedule_context, sizeof(key_schedule_context));
5144 forced_memzero(secret, sizeof(secret));
5145 return res;
5146}
5147
5148
5149static 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;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005155 u8 *dhss = NULL;
5156 size_t dhss_len = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07005157 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 ||
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005173 EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 ||
5174 !(dhss = os_malloc(dhss_len)) ||
Sunil Ravi89eba102022-09-13 21:04:37 -07005175 EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 ||
5176 dhss_len > HPKE_MAX_SHARED_SECRET_LEN) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005177 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));
Sunil Ravi89eba102022-09-13 21:04:37 -07005180 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);
5200fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005201 bin_clear_free(dhss, dhss_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07005202 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
5210static struct wpabuf *
5211hpke_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 }
5261fail:
5262 EVP_CIPHER_CTX_free(cctx);
5263 return ct;
5264}
5265
5266
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005267static 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)
Sunil Ravi89eba102022-09-13 21:04:37 -07005274{
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
5305fail:
5306 forced_memzero(shared_secret, sizeof(shared_secret));
5307 hpke_free_context(ctx);
5308 wpabuf_free(ct);
5309 return enc_ct;
5310}
5311
5312
5313static 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;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005322 u8 *dhss = NULL;
5323 size_t dhss_len = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07005324
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) */
Sunil Ravi89eba102022-09-13 21:04:37 -07005336 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 ||
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005340 EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 ||
5341 !(dhss = os_malloc(dhss_len)) ||
Sunil Ravi89eba102022-09-13 21:04:37 -07005342 EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 ||
5343 dhss_len > HPKE_MAX_SHARED_SECRET_LEN) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005344 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));
Sunil Ravi89eba102022-09-13 21:04:37 -07005347 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);
5360fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005361 bin_clear_free(dhss, dhss_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07005362 crypto_ec_key_deinit(pk_e);
5363 EVP_PKEY_CTX_free(pctx);
5364 wpabuf_free(pk_rm);
5365 return res;
5366}
5367
5368
5369static struct wpabuf *
5370hpke_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 }
5425fail:
5426 EVP_CIPHER_CTX_free(cctx);
5427 return pt;
5428}
5429
5430
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005431static 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)
Sunil Ravi89eba102022-09-13 21:04:37 -07005438{
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
5460fail:
5461 forced_memzero(shared_secret, sizeof(shared_secret));
5462 hpke_free_context(ctx);
5463 return pt;
5464}
5465
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005466
5467#if OPENSSL_VERSION_NUMBER >= 0x30200000L
5468
5469static 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
5526struct 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
5587out:
5588 OSSL_HPKE_CTX_free(ctx);
5589 wpabuf_free(buf);
5590 wpabuf_free(pub);
5591 return res;
5592}
5593
5594
5595struct 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
5655out:
5656 OSSL_HPKE_CTX_free(ctx);
5657 wpabuf_free(buf);
5658 return res;
5659}
5660
5661#else /* OpenSSL < 3.2 */
5662
5663struct 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
5676struct 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
Sunil Ravi89eba102022-09-13 21:04:37 -07005691#endif /* CONFIG_DPP3 */
5692
5693
Sunil Ravia04bd252022-05-02 22:54:18 -07005694void crypto_unload(void)
5695{
5696 openssl_unload_legacy_provider();
Sunil Ravi876a49b2025-02-03 19:18:32 +00005697 openssl_unload_default_provider();
Sunil Ravia04bd252022-05-02 22:54:18 -07005698}