blob: 427677d34a60d74f0fc66b69a7b2565b8dec5ab8 [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
189#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravia04bd252022-05-02 22:54:18 -0700190static OSSL_PROVIDER *openssl_legacy_provider = NULL;
191#endif /* OpenSSL version >= 3.0 */
192
Hai Shaloma20dcd72022-02-04 13:43:00 -0800193void openssl_load_legacy_provider(void)
194{
195#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravia04bd252022-05-02 22:54:18 -0700196 if (openssl_legacy_provider)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800197 return;
198
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000199 openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "legacy", 1);
Sunil Ravia04bd252022-05-02 22:54:18 -0700200#endif /* OpenSSL version >= 3.0 */
201}
Hai Shaloma20dcd72022-02-04 13:43:00 -0800202
Sunil Ravia04bd252022-05-02 22:54:18 -0700203
204static void openssl_unload_legacy_provider(void)
205{
206#if OPENSSL_VERSION_NUMBER >= 0x30000000L
207 if (openssl_legacy_provider) {
208 OSSL_PROVIDER_unload(openssl_legacy_provider);
209 openssl_legacy_provider = NULL;
210 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800211#endif /* OpenSSL version >= 3.0 */
212}
213
214
Sunil Ravia04bd252022-05-02 22:54:18 -0700215#if OPENSSL_VERSION_NUMBER < 0x30000000L
216
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217static BIGNUM * get_group5_prime(void)
218{
Sunil Ravia04bd252022-05-02 22:54:18 -0700219#if OPENSSL_VERSION_NUMBER >= 0x10100000L
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700220 return BN_get_rfc3526_prime_1536(NULL);
221#elif !defined(OPENSSL_IS_BORINGSSL)
222 return get_rfc3526_prime_1536(NULL);
223#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224 static const unsigned char RFC3526_PRIME_1536[] = {
225 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
226 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
227 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
228 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
229 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
230 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
231 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
232 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
233 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
234 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
235 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
236 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
237 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
238 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
239 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
240 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
241 };
242 return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700243#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244}
245
Hai Shalom021b0b52019-04-10 11:17:58 -0700246
247static BIGNUM * get_group5_order(void)
248{
249 static const unsigned char RFC3526_ORDER_1536[] = {
250 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51,
251 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68,
252 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53,
253 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E,
254 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36,
255 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22,
256 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74,
257 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6,
258 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08,
259 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E,
260 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B,
261 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF,
262 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB,
263 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36,
264 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04,
265 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
266 };
267 return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL);
268}
269
Sunil Ravia04bd252022-05-02 22:54:18 -0700270#endif /* OpenSSL version < 3.0 */
271
Hai Shalom021b0b52019-04-10 11:17:58 -0700272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273#ifdef OPENSSL_NO_SHA256
274#define NO_SHA256_WRAPPER
275#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800276#ifdef OPENSSL_NO_SHA512
277#define NO_SHA384_WRAPPER
278#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700280static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
281 const u8 *addr[], const size_t *len, u8 *mac)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -0800283 EVP_MD_CTX *ctx;
284 size_t i;
285 unsigned int mac_len;
286
287 if (TEST_FAIL())
288 return -1;
289
290 ctx = EVP_MD_CTX_new();
291 if (!ctx)
292 return -1;
293 if (!EVP_DigestInit_ex(ctx, type, NULL)) {
294 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
295 ERR_error_string(ERR_get_error(), NULL));
296 EVP_MD_CTX_free(ctx);
297 return -1;
298 }
299 for (i = 0; i < num_elem; i++) {
300 if (!EVP_DigestUpdate(ctx, addr[i], len[i])) {
301 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
302 "failed: %s",
303 ERR_error_string(ERR_get_error(), NULL));
304 EVP_MD_CTX_free(ctx);
305 return -1;
306 }
307 }
308 if (!EVP_DigestFinal(ctx, mac, &mac_len)) {
309 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
310 ERR_error_string(ERR_get_error(), NULL));
311 EVP_MD_CTX_free(ctx);
312 return -1;
313 }
314 EVP_MD_CTX_free(ctx);
315
316 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317}
318
319
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800320#ifndef CONFIG_FIPS
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
323{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800324 openssl_load_legacy_provider();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700325 return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326}
327
328
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700329int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330{
331 u8 pkey[8], next, tmp;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800332 int i, plen, ret = -1;
333 EVP_CIPHER_CTX *ctx;
334
335 openssl_load_legacy_provider();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336
337 /* Add parity bits to the key */
338 next = 0;
339 for (i = 0; i < 7; i++) {
340 tmp = key[i];
341 pkey[i] = (tmp >> i) | next | 1;
342 next = tmp << (7 - i);
343 }
344 pkey[i] = next | 1;
345
Hai Shaloma20dcd72022-02-04 13:43:00 -0800346 ctx = EVP_CIPHER_CTX_new();
347 if (ctx &&
348 EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, pkey, NULL) == 1 &&
349 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
350 EVP_EncryptUpdate(ctx, cypher, &plen, clear, 8) == 1 &&
351 EVP_EncryptFinal_ex(ctx, &cypher[plen], &plen) == 1)
352 ret = 0;
353 else
354 wpa_printf(MSG_ERROR, "OpenSSL: DES encrypt failed");
355
356 if (ctx)
357 EVP_CIPHER_CTX_free(ctx);
358 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359}
360
361
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800362#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700363int rc4_skip(const u8 *key, size_t keylen, size_t skip,
364 u8 *data, size_t data_len)
365{
366#ifdef OPENSSL_NO_RC4
367 return -1;
368#else /* OPENSSL_NO_RC4 */
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800369 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700370 int outl;
371 int res = -1;
372 unsigned char skip_buf[16];
373
Hai Shaloma20dcd72022-02-04 13:43:00 -0800374 openssl_load_legacy_provider();
375
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800376 ctx = EVP_CIPHER_CTX_new();
377 if (!ctx ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800378 !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800379 !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800380 !EVP_CIPHER_CTX_set_key_length(ctx, keylen) ||
381 !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700382 goto out;
383
384 while (skip >= sizeof(skip_buf)) {
385 size_t len = skip;
386 if (len > sizeof(skip_buf))
387 len = sizeof(skip_buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800388 if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389 goto out;
390 skip -= len;
391 }
392
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800393 if (EVP_CipherUpdate(ctx, data, &outl, data, data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394 res = 0;
395
396out:
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800397 if (ctx)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800398 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399 return res;
400#endif /* OPENSSL_NO_RC4 */
401}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800402#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403
404
405int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
406{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700407 return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408}
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000409
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800410#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700411
412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
414{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700415 return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416}
417
418
419#ifndef NO_SHA256_WRAPPER
420int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
421 u8 *mac)
422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700423 return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424}
425#endif /* NO_SHA256_WRAPPER */
426
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700427
Paul Stewart092955c2017-02-06 09:13:09 -0800428#ifndef NO_SHA384_WRAPPER
429int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
430 u8 *mac)
431{
432 return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac);
433}
434#endif /* NO_SHA384_WRAPPER */
435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700436
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700437#ifndef NO_SHA512_WRAPPER
438int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
439 u8 *mac)
440{
441 return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac);
442}
443#endif /* NO_SHA512_WRAPPER */
444
445
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700446static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
447{
448 switch (keylen) {
449 case 16:
450 return EVP_aes_128_ecb();
451 case 24:
452 return EVP_aes_192_ecb();
453 case 32:
454 return EVP_aes_256_ecb();
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000455 default:
456 return NULL;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700457 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700458}
459
460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461void * aes_encrypt_init(const u8 *key, size_t len)
462{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700463 EVP_CIPHER_CTX *ctx;
464 const EVP_CIPHER *type;
465
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800466 if (TEST_FAIL())
467 return NULL;
468
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700469 type = aes_get_evp_cipher(len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700470 if (!type) {
471 wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
472 __func__, (unsigned int) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700473 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700474 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800476 ctx = EVP_CIPHER_CTX_new();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700477 if (ctx == NULL)
478 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000479 if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
480 EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
Sunil Ravia04bd252022-05-02 22:54:18 -0700481 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482 return NULL;
483 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700484 return ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485}
486
487
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700488int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700489{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700490 EVP_CIPHER_CTX *c = ctx;
491 int clen = 16;
492 if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) {
493 wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s",
494 ERR_error_string(ERR_get_error(), NULL));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700495 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700496 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700497 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700498}
499
500
501void aes_encrypt_deinit(void *ctx)
502{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700503 EVP_CIPHER_CTX *c = ctx;
504 u8 buf[16];
505 int len = sizeof(buf);
506 if (EVP_EncryptFinal_ex(c, buf, &len) != 1) {
507 wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: "
508 "%s", ERR_error_string(ERR_get_error(), NULL));
509 }
510 if (len != 0) {
511 wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
512 "in AES encrypt", len);
513 }
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800514 EVP_CIPHER_CTX_free(c);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515}
516
517
518void * aes_decrypt_init(const u8 *key, size_t len)
519{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700520 EVP_CIPHER_CTX *ctx;
521 const EVP_CIPHER *type;
522
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800523 if (TEST_FAIL())
524 return NULL;
525
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700526 type = aes_get_evp_cipher(len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700527 if (!type) {
528 wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
529 __func__, (unsigned int) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700530 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700531 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700532
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800533 ctx = EVP_CIPHER_CTX_new();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700534 if (ctx == NULL)
535 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000536 if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1 ||
537 EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800538 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539 return NULL;
540 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700541 return ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700542}
543
544
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700545int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700547 EVP_CIPHER_CTX *c = ctx;
548 int plen = 16;
549 if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) {
550 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s",
551 ERR_error_string(ERR_get_error(), NULL));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700552 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700553 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700554 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555}
556
557
558void aes_decrypt_deinit(void *ctx)
559{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700560 EVP_CIPHER_CTX *c = ctx;
561 u8 buf[16];
562 int len = sizeof(buf);
563 if (EVP_DecryptFinal_ex(c, buf, &len) != 1) {
564 wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: "
565 "%s", ERR_error_string(ERR_get_error(), NULL));
566 }
567 if (len != 0) {
568 wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
569 "in AES decrypt", len);
570 }
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800571 EVP_CIPHER_CTX_free(c);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572}
573
574
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800575#ifndef CONFIG_FIPS
576#ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP
577
Sunil Ravia04bd252022-05-02 22:54:18 -0700578#if OPENSSL_VERSION_NUMBER >= 0x30000000L
579static const EVP_CIPHER * aes_get_evp_wrap_cipher(size_t keylen)
580{
581 switch (keylen) {
582 case 16:
583 return EVP_aes_128_wrap();
584 case 24:
585 return EVP_aes_192_wrap();
586 case 32:
587 return EVP_aes_256_wrap();
588 default:
589 return NULL;
590 }
591}
592#endif /* OpenSSL version >= 3.0 */
593
594
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800595int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
596{
Sunil Ravia04bd252022-05-02 22:54:18 -0700597#if OPENSSL_VERSION_NUMBER >= 0x30000000L
598 EVP_CIPHER_CTX *ctx;
599 const EVP_CIPHER *type;
600 int ret = -1, len;
601 u8 buf[16];
602
603 if (TEST_FAIL())
604 return -1;
605
606 type = aes_get_evp_wrap_cipher(kek_len);
607 if (!type)
608 return -1;
609
610 ctx = EVP_CIPHER_CTX_new();
611 if (!ctx)
612 return -1;
613
614 if (EVP_EncryptInit_ex(ctx, type, NULL, kek, NULL) == 1 &&
615 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
616 EVP_EncryptUpdate(ctx, cipher, &len, plain, n * 8) == 1 &&
617 len == (n + 1) * 8 &&
618 EVP_EncryptFinal_ex(ctx, buf, &len) == 1)
619 ret = 0;
620
621 EVP_CIPHER_CTX_free(ctx);
622 return ret;
623#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800624 AES_KEY actx;
625 int res;
626
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800627 if (TEST_FAIL())
628 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800629 if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
630 return -1;
631 res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
632 OPENSSL_cleanse(&actx, sizeof(actx));
633 return res <= 0 ? -1 : 0;
Sunil Ravia04bd252022-05-02 22:54:18 -0700634#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800635}
636
637
638int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
639 u8 *plain)
640{
Sunil Ravia04bd252022-05-02 22:54:18 -0700641#if OPENSSL_VERSION_NUMBER >= 0x30000000L
642 EVP_CIPHER_CTX *ctx;
643 const EVP_CIPHER *type;
644 int ret = -1, len;
645 u8 buf[16];
646
647 if (TEST_FAIL())
648 return -1;
649
650 type = aes_get_evp_wrap_cipher(kek_len);
651 if (!type)
652 return -1;
653
654 ctx = EVP_CIPHER_CTX_new();
655 if (!ctx)
656 return -1;
657
658 if (EVP_DecryptInit_ex(ctx, type, NULL, kek, NULL) == 1 &&
659 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
660 EVP_DecryptUpdate(ctx, plain, &len, cipher, (n + 1) * 8) == 1 &&
661 len == n * 8 &&
662 EVP_DecryptFinal_ex(ctx, buf, &len) == 1)
663 ret = 0;
664
665 EVP_CIPHER_CTX_free(ctx);
666 return ret;
667#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800668 AES_KEY actx;
669 int res;
670
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800671 if (TEST_FAIL())
672 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800673 if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
674 return -1;
675 res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
676 OPENSSL_cleanse(&actx, sizeof(actx));
677 return res <= 0 ? -1 : 0;
Sunil Ravia04bd252022-05-02 22:54:18 -0700678#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800679}
680
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800681#endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */
682#endif /* CONFIG_FIPS */
683
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800684
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700685int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
686{
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800687 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700688 int clen, len;
689 u8 buf[16];
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800690 int res = -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700691
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800692 if (TEST_FAIL())
693 return -1;
694
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800695 ctx = EVP_CIPHER_CTX_new();
696 if (!ctx)
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700697 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700698 clen = data_len;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700699 len = sizeof(buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800700 if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
701 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
702 EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 &&
703 clen == (int) data_len &&
704 EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
705 res = 0;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800706 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700707
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800708 return res;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700709}
710
711
712int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
713{
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800714 EVP_CIPHER_CTX *ctx;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700715 int plen, len;
716 u8 buf[16];
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800717 int res = -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700718
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800719 if (TEST_FAIL())
720 return -1;
721
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800722 ctx = EVP_CIPHER_CTX_new();
723 if (!ctx)
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700724 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700725 plen = data_len;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700726 len = sizeof(buf);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800727 if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
728 EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
729 EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 &&
730 plen == (int) data_len &&
731 EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
732 res = 0;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800733 EVP_CIPHER_CTX_free(ctx);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700734
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800735 return res;
736
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700737}
738
739
Roshan Pius3a1667e2018-07-03 15:17:14 -0700740int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
741 u8 *pubkey)
742{
743 size_t pubkey_len, pad;
744
745 if (os_get_random(privkey, prime_len) < 0)
746 return -1;
747 if (os_memcmp(privkey, prime, prime_len) > 0) {
748 /* Make sure private value is smaller than prime */
749 privkey[0] = 0;
750 }
751
752 pubkey_len = prime_len;
753 if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
754 pubkey, &pubkey_len) < 0)
755 return -1;
756 if (pubkey_len < prime_len) {
757 pad = prime_len - pubkey_len;
758 os_memmove(pubkey + pad, pubkey, pubkey_len);
759 os_memset(pubkey, 0, pad);
760 }
761
762 return 0;
763}
764
765
766int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
Hai Shalom021b0b52019-04-10 11:17:58 -0700767 const u8 *order, size_t order_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700768 const u8 *privkey, size_t privkey_len,
769 const u8 *pubkey, size_t pubkey_len,
770 u8 *secret, size_t *len)
771{
Hai Shalom021b0b52019-04-10 11:17:58 -0700772 BIGNUM *pub, *p;
773 int res = -1;
774
775 pub = BN_bin2bn(pubkey, pubkey_len, NULL);
776 p = BN_bin2bn(prime, prime_len, NULL);
777 if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) ||
778 BN_cmp(pub, p) >= 0)
779 goto fail;
780
781 if (order) {
782 BN_CTX *ctx;
783 BIGNUM *q, *tmp;
784 int failed;
785
786 /* verify: pubkey^q == 1 mod p */
787 q = BN_bin2bn(order, order_len, NULL);
788 ctx = BN_CTX_new();
789 tmp = BN_new();
790 failed = !q || !ctx || !tmp ||
791 !BN_mod_exp(tmp, pub, q, p, ctx) ||
792 !BN_is_one(tmp);
Hai Shalom81f62d82019-07-22 12:10:00 -0700793 BN_clear_free(q);
794 BN_clear_free(tmp);
Hai Shalom021b0b52019-04-10 11:17:58 -0700795 BN_CTX_free(ctx);
796 if (failed)
797 goto fail;
798 }
799
800 res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
801 prime, prime_len, secret, len);
802fail:
Hai Shalom81f62d82019-07-22 12:10:00 -0700803 BN_clear_free(pub);
804 BN_clear_free(p);
Hai Shalom021b0b52019-04-10 11:17:58 -0700805 return res;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700806}
807
808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700809int crypto_mod_exp(const u8 *base, size_t base_len,
810 const u8 *power, size_t power_len,
811 const u8 *modulus, size_t modulus_len,
812 u8 *result, size_t *result_len)
813{
814 BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
815 int ret = -1;
816 BN_CTX *ctx;
817
818 ctx = BN_CTX_new();
819 if (ctx == NULL)
820 return -1;
821
822 bn_base = BN_bin2bn(base, base_len, NULL);
823 bn_exp = BN_bin2bn(power, power_len, NULL);
824 bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
825 bn_result = BN_new();
826
827 if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
828 bn_result == NULL)
829 goto error;
830
Hai Shalom021b0b52019-04-10 11:17:58 -0700831 if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
832 ctx, NULL) != 1)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 goto error;
834
835 *result_len = BN_bn2bin(bn_result, result);
836 ret = 0;
837
838error:
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -0700839 BN_clear_free(bn_base);
840 BN_clear_free(bn_exp);
841 BN_clear_free(bn_modulus);
842 BN_clear_free(bn_result);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843 BN_CTX_free(ctx);
844 return ret;
845}
846
847
848struct crypto_cipher {
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800849 EVP_CIPHER_CTX *enc;
850 EVP_CIPHER_CTX *dec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851};
852
853
854struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
855 const u8 *iv, const u8 *key,
856 size_t key_len)
857{
858 struct crypto_cipher *ctx;
859 const EVP_CIPHER *cipher;
860
861 ctx = os_zalloc(sizeof(*ctx));
862 if (ctx == NULL)
863 return NULL;
864
865 switch (alg) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800866#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700867#ifndef OPENSSL_NO_RC4
868 case CRYPTO_CIPHER_ALG_RC4:
869 cipher = EVP_rc4();
870 break;
871#endif /* OPENSSL_NO_RC4 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800872#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873#ifndef OPENSSL_NO_AES
874 case CRYPTO_CIPHER_ALG_AES:
875 switch (key_len) {
876 case 16:
877 cipher = EVP_aes_128_cbc();
878 break;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700879#ifndef OPENSSL_IS_BORINGSSL
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 case 24:
881 cipher = EVP_aes_192_cbc();
882 break;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700883#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 case 32:
885 cipher = EVP_aes_256_cbc();
886 break;
887 default:
888 os_free(ctx);
889 return NULL;
890 }
891 break;
892#endif /* OPENSSL_NO_AES */
893#ifndef OPENSSL_NO_DES
894 case CRYPTO_CIPHER_ALG_3DES:
895 cipher = EVP_des_ede3_cbc();
896 break;
897 case CRYPTO_CIPHER_ALG_DES:
898 cipher = EVP_des_cbc();
899 break;
900#endif /* OPENSSL_NO_DES */
901#ifndef OPENSSL_NO_RC2
902 case CRYPTO_CIPHER_ALG_RC2:
903 cipher = EVP_rc2_ecb();
904 break;
905#endif /* OPENSSL_NO_RC2 */
906 default:
907 os_free(ctx);
908 return NULL;
909 }
910
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800911 if (!(ctx->enc = EVP_CIPHER_CTX_new()) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800912 !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800913 !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800914 !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) ||
915 !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) {
916 if (ctx->enc)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800917 EVP_CIPHER_CTX_free(ctx->enc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700918 os_free(ctx);
919 return NULL;
920 }
921
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800922 if (!(ctx->dec = EVP_CIPHER_CTX_new()) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800923 !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800924 !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800925 !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) ||
926 !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800927 EVP_CIPHER_CTX_free(ctx->enc);
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800928 if (ctx->dec)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800929 EVP_CIPHER_CTX_free(ctx->dec);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 os_free(ctx);
931 return NULL;
932 }
933
934 return ctx;
935}
936
937
938int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
939 u8 *crypt, size_t len)
940{
941 int outl;
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800942 if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700943 return -1;
944 return 0;
945}
946
947
948int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
949 u8 *plain, size_t len)
950{
951 int outl;
952 outl = len;
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -0800953 if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700954 return -1;
955 return 0;
956}
957
958
959void crypto_cipher_deinit(struct crypto_cipher *ctx)
960{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800961 EVP_CIPHER_CTX_free(ctx->enc);
962 EVP_CIPHER_CTX_free(ctx->dec);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963 os_free(ctx);
964}
965
966
967void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
968{
Sunil Ravia04bd252022-05-02 22:54:18 -0700969#if OPENSSL_VERSION_NUMBER < 0x10100000L
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970 DH *dh;
971 struct wpabuf *pubkey = NULL, *privkey = NULL;
972 size_t publen, privlen;
973
974 *priv = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700975 wpabuf_free(*publ);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976 *publ = NULL;
977
978 dh = DH_new();
979 if (dh == NULL)
980 return NULL;
981
982 dh->g = BN_new();
983 if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
984 goto err;
985
986 dh->p = get_group5_prime();
987 if (dh->p == NULL)
988 goto err;
989
Hai Shalom021b0b52019-04-10 11:17:58 -0700990 dh->q = get_group5_order();
991 if (!dh->q)
992 goto err;
993
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 if (DH_generate_key(dh) != 1)
995 goto err;
996
997 publen = BN_num_bytes(dh->pub_key);
998 pubkey = wpabuf_alloc(publen);
999 if (pubkey == NULL)
1000 goto err;
1001 privlen = BN_num_bytes(dh->priv_key);
1002 privkey = wpabuf_alloc(privlen);
1003 if (privkey == NULL)
1004 goto err;
1005
1006 BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen));
1007 BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen));
1008
1009 *priv = privkey;
1010 *publ = pubkey;
1011 return dh;
1012
1013err:
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001014 wpabuf_clear_free(pubkey);
1015 wpabuf_clear_free(privkey);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 DH_free(dh);
1017 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001018#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
1019 EVP_PKEY *pkey = NULL;
1020 OSSL_PARAM params[2];
1021 size_t pub_len = OSSL_PARAM_UNMODIFIED;
1022 size_t priv_len;
1023 struct wpabuf *pubkey = NULL, *privkey = NULL;
1024 BIGNUM *priv_bn = NULL;
1025 EVP_PKEY_CTX *gctx;
1026
1027 *priv = NULL;
1028 wpabuf_free(*publ);
1029 *publ = NULL;
1030
1031 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
1032 "modp_1536", 0);
1033 params[1] = OSSL_PARAM_construct_end();
1034
1035 gctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
1036 if (!gctx ||
1037 EVP_PKEY_keygen_init(gctx) != 1 ||
1038 EVP_PKEY_CTX_set_params(gctx, params) != 1 ||
1039 EVP_PKEY_generate(gctx, &pkey) != 1 ||
1040 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
1041 &priv_bn) != 1 ||
1042 EVP_PKEY_get_octet_string_param(pkey,
1043 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
1044 NULL, 0, &pub_len) < 0 ||
1045 pub_len == OSSL_PARAM_UNMODIFIED ||
1046 (priv_len = BN_num_bytes(priv_bn)) == 0 ||
1047 !(pubkey = wpabuf_alloc(pub_len)) ||
1048 !(privkey = wpabuf_alloc(priv_len)) ||
1049 EVP_PKEY_get_octet_string_param(pkey,
1050 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
1051 wpabuf_put(pubkey, pub_len),
1052 pub_len, NULL) != 1) {
1053 wpa_printf(MSG_INFO, "OpenSSL: failed: %s",
1054 ERR_error_string(ERR_get_error(), NULL));
1055 wpabuf_free(pubkey);
1056 wpabuf_clear_free(privkey);
1057 EVP_PKEY_free(pkey);
1058 pkey = NULL;
1059 } else {
1060 BN_bn2bin(priv_bn, wpabuf_put(privkey, priv_len));
1061
1062 *priv = privkey;
1063 *publ = pubkey;
1064 }
1065
1066 BN_clear_free(priv_bn);
1067 EVP_PKEY_CTX_free(gctx);
1068 return pkey;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001069#else
1070 DH *dh;
1071 struct wpabuf *pubkey = NULL, *privkey = NULL;
1072 size_t publen, privlen;
Hai Shalom021b0b52019-04-10 11:17:58 -07001073 BIGNUM *p, *g, *q;
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07001074 const BIGNUM *priv_key = NULL, *pub_key = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001075
1076 *priv = NULL;
1077 wpabuf_free(*publ);
1078 *publ = NULL;
1079
1080 dh = DH_new();
1081 if (dh == NULL)
1082 return NULL;
1083
1084 g = BN_new();
1085 p = get_group5_prime();
Hai Shalom021b0b52019-04-10 11:17:58 -07001086 q = get_group5_order();
1087 if (!g || BN_set_word(g, 2) != 1 || !p || !q ||
1088 DH_set0_pqg(dh, p, q, g) != 1)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001089 goto err;
1090 p = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07001091 q = NULL;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001092 g = NULL;
1093
1094 if (DH_generate_key(dh) != 1)
1095 goto err;
1096
1097 DH_get0_key(dh, &pub_key, &priv_key);
1098 publen = BN_num_bytes(pub_key);
1099 pubkey = wpabuf_alloc(publen);
1100 if (!pubkey)
1101 goto err;
1102 privlen = BN_num_bytes(priv_key);
1103 privkey = wpabuf_alloc(privlen);
1104 if (!privkey)
1105 goto err;
1106
1107 BN_bn2bin(pub_key, wpabuf_put(pubkey, publen));
1108 BN_bn2bin(priv_key, wpabuf_put(privkey, privlen));
1109
1110 *priv = privkey;
1111 *publ = pubkey;
1112 return dh;
1113
1114err:
1115 BN_free(p);
Hai Shalom021b0b52019-04-10 11:17:58 -07001116 BN_free(q);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001117 BN_free(g);
1118 wpabuf_clear_free(pubkey);
1119 wpabuf_clear_free(privkey);
1120 DH_free(dh);
1121 return NULL;
1122#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123}
1124
1125
Dmitry Shmidt04949592012-07-19 12:16:46 -07001126void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
1127{
Sunil Ravia04bd252022-05-02 22:54:18 -07001128#if OPENSSL_VERSION_NUMBER < 0x10100000L
Dmitry Shmidt04949592012-07-19 12:16:46 -07001129 DH *dh;
1130
1131 dh = DH_new();
1132 if (dh == NULL)
1133 return NULL;
1134
1135 dh->g = BN_new();
1136 if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
1137 goto err;
1138
1139 dh->p = get_group5_prime();
1140 if (dh->p == NULL)
1141 goto err;
1142
1143 dh->priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
1144 if (dh->priv_key == NULL)
1145 goto err;
1146
1147 dh->pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
1148 if (dh->pub_key == NULL)
1149 goto err;
1150
1151 if (DH_generate_key(dh) != 1)
1152 goto err;
1153
1154 return dh;
1155
1156err:
1157 DH_free(dh);
1158 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001159#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
1160 EVP_PKEY *pkey = NULL;
1161 OSSL_PARAM_BLD *bld;
1162 OSSL_PARAM *params = NULL;
1163 BIGNUM *priv_key, *pub_key;
1164 EVP_PKEY_CTX *fctx;
1165
1166 fctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
1167 priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
1168 pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
1169 bld = OSSL_PARAM_BLD_new();
1170 if (!fctx || !priv_key || !pub_key || !bld ||
1171 OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
1172 "modp_1536", 0) != 1 ||
1173 OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
1174 priv_key) != 1 ||
1175 OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY,
1176 pub_key) != 1 ||
1177 !(params = OSSL_PARAM_BLD_to_param(bld)) ||
1178 EVP_PKEY_fromdata_init(fctx) != 1 ||
1179 EVP_PKEY_fromdata(fctx, &pkey, EVP_PKEY_KEYPAIR, params) != 1) {
1180 wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_fromdata failed: %s",
1181 ERR_error_string(ERR_get_error(), NULL));
1182 EVP_PKEY_free(pkey);
1183 pkey = NULL;
1184 }
1185
1186 BN_clear_free(priv_key);
1187 BN_free(pub_key);
1188 EVP_PKEY_CTX_free(fctx);
1189 OSSL_PARAM_BLD_free(bld);
1190 OSSL_PARAM_free(params);
1191 return pkey;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001192#else
1193 DH *dh;
1194 BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL;
1195
1196 dh = DH_new();
1197 if (dh == NULL)
1198 return NULL;
1199
1200 g = BN_new();
1201 p = get_group5_prime();
1202 if (!g || BN_set_word(g, 2) != 1 || !p ||
1203 DH_set0_pqg(dh, p, NULL, g) != 1)
1204 goto err;
1205 p = NULL;
1206 g = NULL;
1207
1208 priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
1209 pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001210 if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001211 goto err;
1212 pub_key = NULL;
1213 priv_key = NULL;
1214
1215 if (DH_generate_key(dh) != 1)
1216 goto err;
1217
1218 return dh;
1219
1220err:
1221 BN_free(p);
1222 BN_free(g);
1223 BN_free(pub_key);
1224 BN_clear_free(priv_key);
1225 DH_free(dh);
1226 return NULL;
1227#endif
Dmitry Shmidt04949592012-07-19 12:16:46 -07001228}
1229
1230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
1232 const struct wpabuf *own_private)
1233{
Sunil Ravia04bd252022-05-02 22:54:18 -07001234#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1235 EVP_PKEY *pkey = ctx;
1236 EVP_PKEY *peer_pub;
1237 size_t len;
1238 struct wpabuf *res = NULL;
1239 EVP_PKEY_CTX *dctx = NULL;
1240
1241 peer_pub = EVP_PKEY_new();
1242 if (!pkey || !peer_pub ||
1243 EVP_PKEY_copy_parameters(peer_pub, pkey) != 1 ||
1244 EVP_PKEY_set1_encoded_public_key(peer_pub, wpabuf_head(peer_public),
1245 wpabuf_len(peer_public)) != 1 ||
1246 !(dctx = EVP_PKEY_CTX_new(pkey, NULL)) ||
1247 EVP_PKEY_derive_init(dctx) != 1 ||
1248 EVP_PKEY_derive_set_peer(dctx, peer_pub) != 1 ||
1249 EVP_PKEY_derive(dctx, NULL, &len) != 1 ||
1250 !(res = wpabuf_alloc(len)) ||
1251 EVP_PKEY_derive(dctx, wpabuf_mhead(res), &len) != 1) {
1252 wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_derive failed: %s",
1253 ERR_error_string(ERR_get_error(), NULL));
1254 wpabuf_free(res);
1255 res = NULL;
1256 } else {
1257 wpabuf_put(res, len);
1258 }
1259
1260 EVP_PKEY_free(peer_pub);
1261 EVP_PKEY_CTX_free(dctx);
1262 return res;
1263#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001264 BIGNUM *pub_key;
1265 struct wpabuf *res = NULL;
1266 size_t rlen;
1267 DH *dh = ctx;
1268 int keylen;
1269
1270 if (ctx == NULL)
1271 return NULL;
1272
1273 pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
1274 NULL);
1275 if (pub_key == NULL)
1276 return NULL;
1277
1278 rlen = DH_size(dh);
1279 res = wpabuf_alloc(rlen);
1280 if (res == NULL)
1281 goto err;
1282
1283 keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
1284 if (keylen < 0)
1285 goto err;
1286 wpabuf_put(res, keylen);
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001287 BN_clear_free(pub_key);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288
1289 return res;
1290
1291err:
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001292 BN_clear_free(pub_key);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001293 wpabuf_clear_free(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07001295#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296}
1297
1298
1299void dh5_free(void *ctx)
1300{
Sunil Ravia04bd252022-05-02 22:54:18 -07001301#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1302 EVP_PKEY *pkey = ctx;
1303
1304 EVP_PKEY_free(pkey);
1305#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001306 DH *dh;
1307 if (ctx == NULL)
1308 return;
1309 dh = ctx;
1310 DH_free(dh);
Sunil Ravia04bd252022-05-02 22:54:18 -07001311#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001313
1314
1315struct crypto_hash {
Sunil Ravia04bd252022-05-02 22:54:18 -07001316#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1317 EVP_MAC_CTX *ctx;
1318#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001319 HMAC_CTX *ctx;
Sunil Ravia04bd252022-05-02 22:54:18 -07001320#endif /* OpenSSL version >= 3.0 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001321 bool failed;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001322};
1323
1324
1325struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
1326 size_t key_len)
1327{
Sunil Ravia04bd252022-05-02 22:54:18 -07001328#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1329 struct crypto_hash *ctx;
1330 EVP_MAC *mac;
1331 OSSL_PARAM params[2];
1332 char *a = NULL;
1333
1334 switch (alg) {
1335#ifndef OPENSSL_NO_MD5
1336 case CRYPTO_HASH_ALG_HMAC_MD5:
1337 a = "MD5";
1338 break;
1339#endif /* OPENSSL_NO_MD5 */
1340#ifndef OPENSSL_NO_SHA
1341 case CRYPTO_HASH_ALG_HMAC_SHA1:
1342 a = "SHA1";
1343 break;
1344#endif /* OPENSSL_NO_SHA */
1345#ifndef OPENSSL_NO_SHA256
1346#ifdef CONFIG_SHA256
1347 case CRYPTO_HASH_ALG_HMAC_SHA256:
1348 a = "SHA256";
1349 break;
1350#endif /* CONFIG_SHA256 */
1351#endif /* OPENSSL_NO_SHA256 */
1352 default:
1353 return NULL;
1354 }
1355
1356 mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
1357 if (!mac)
1358 return NULL;
1359
1360 params[0] = OSSL_PARAM_construct_utf8_string("digest", a, 0);
1361 params[1] = OSSL_PARAM_construct_end();
1362
1363 ctx = os_zalloc(sizeof(*ctx));
1364 if (!ctx)
Sunil8cd6f4d2022-06-28 18:40:46 +00001365 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001366 ctx->ctx = EVP_MAC_CTX_new(mac);
1367 if (!ctx->ctx) {
Sunil Ravia04bd252022-05-02 22:54:18 -07001368 os_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00001369 ctx = NULL;
1370 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001371 }
1372
1373 if (EVP_MAC_init(ctx->ctx, key, key_len, params) != 1) {
1374 EVP_MAC_CTX_free(ctx->ctx);
1375 bin_clear_free(ctx, sizeof(*ctx));
Sunil8cd6f4d2022-06-28 18:40:46 +00001376 ctx = NULL;
1377 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001378 }
1379
Sunil8cd6f4d2022-06-28 18:40:46 +00001380fail:
Sunil Ravia04bd252022-05-02 22:54:18 -07001381 EVP_MAC_free(mac);
1382 return ctx;
1383#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001384 struct crypto_hash *ctx;
1385 const EVP_MD *md;
1386
1387 switch (alg) {
1388#ifndef OPENSSL_NO_MD5
1389 case CRYPTO_HASH_ALG_HMAC_MD5:
1390 md = EVP_md5();
1391 break;
1392#endif /* OPENSSL_NO_MD5 */
1393#ifndef OPENSSL_NO_SHA
1394 case CRYPTO_HASH_ALG_HMAC_SHA1:
1395 md = EVP_sha1();
1396 break;
1397#endif /* OPENSSL_NO_SHA */
1398#ifndef OPENSSL_NO_SHA256
1399#ifdef CONFIG_SHA256
1400 case CRYPTO_HASH_ALG_HMAC_SHA256:
1401 md = EVP_sha256();
1402 break;
1403#endif /* CONFIG_SHA256 */
1404#endif /* OPENSSL_NO_SHA256 */
1405 default:
1406 return NULL;
1407 }
1408
1409 ctx = os_zalloc(sizeof(*ctx));
1410 if (ctx == NULL)
1411 return NULL;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001412 ctx->ctx = HMAC_CTX_new();
1413 if (!ctx->ctx) {
1414 os_free(ctx);
1415 return NULL;
1416 }
1417
1418 if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) {
1419 HMAC_CTX_free(ctx->ctx);
1420 bin_clear_free(ctx, sizeof(*ctx));
1421 return NULL;
1422 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001423
1424 return ctx;
Sunil Ravia04bd252022-05-02 22:54:18 -07001425#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001426}
1427
1428
1429void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
1430{
1431 if (ctx == NULL)
1432 return;
Sunil Ravia04bd252022-05-02 22:54:18 -07001433#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001434 if (!EVP_MAC_update(ctx->ctx, data, len))
1435 ctx->failed = true;
Sunil Ravia04bd252022-05-02 22:54:18 -07001436#else /* OpenSSL version >= 3.0 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001437 if (!HMAC_Update(ctx->ctx, data, len))
1438 ctx->failed = true;
Sunil Ravia04bd252022-05-02 22:54:18 -07001439#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001440}
1441
1442
1443int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
1444{
Sunil Ravia04bd252022-05-02 22:54:18 -07001445#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1446 size_t mdlen;
1447 int res;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001448 bool failed;
Sunil Ravia04bd252022-05-02 22:54:18 -07001449
1450 if (!ctx)
1451 return -2;
1452
1453 if (!mac || !len) {
1454 EVP_MAC_CTX_free(ctx->ctx);
1455 bin_clear_free(ctx, sizeof(*ctx));
1456 return 0;
1457 }
1458
1459 res = EVP_MAC_final(ctx->ctx, NULL, &mdlen, 0);
1460 if (res != 1) {
1461 EVP_MAC_CTX_free(ctx->ctx);
1462 bin_clear_free(ctx, sizeof(*ctx));
1463 return -1;
1464 }
1465 res = EVP_MAC_final(ctx->ctx, mac, &mdlen, mdlen);
1466 EVP_MAC_CTX_free(ctx->ctx);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001467 failed = ctx->failed;
Sunil Ravia04bd252022-05-02 22:54:18 -07001468 bin_clear_free(ctx, sizeof(*ctx));
1469
1470 if (TEST_FAIL())
1471 return -1;
1472
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001473 if (failed)
1474 return -2;
1475
Sunil Ravia04bd252022-05-02 22:54:18 -07001476 if (res == 1) {
1477 *len = mdlen;
1478 return 0;
1479 }
1480
1481 return -1;
1482#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001483 unsigned int mdlen;
1484 int res;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001485 bool failed;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001486
1487 if (ctx == NULL)
1488 return -2;
1489
1490 if (mac == NULL || len == NULL) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001491 HMAC_CTX_free(ctx->ctx);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001492 bin_clear_free(ctx, sizeof(*ctx));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001493 return 0;
1494 }
1495
1496 mdlen = *len;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001497 res = HMAC_Final(ctx->ctx, mac, &mdlen);
1498 HMAC_CTX_free(ctx->ctx);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001499 failed = ctx->failed;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001500 bin_clear_free(ctx, sizeof(*ctx));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001501
Hai Shalom5f92bc92019-04-18 11:54:11 -07001502 if (TEST_FAIL())
1503 return -1;
1504
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001505 if (failed)
1506 return -2;
1507
Dmitry Shmidt04949592012-07-19 12:16:46 -07001508 if (res == 1) {
1509 *len = mdlen;
1510 return 0;
1511 }
1512
1513 return -1;
Sunil Ravia04bd252022-05-02 22:54:18 -07001514#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001515}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001516
1517
Sunil Ravia04bd252022-05-02 22:54:18 -07001518#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1519
1520static int openssl_hmac_vector(char *digest, const u8 *key,
1521 size_t key_len, size_t num_elem,
1522 const u8 *addr[], const size_t *len, u8 *mac,
1523 unsigned int mdlen)
1524{
1525 EVP_MAC *hmac;
1526 OSSL_PARAM params[2];
1527 EVP_MAC_CTX *ctx;
1528 size_t i, mlen;
1529 int res;
1530
1531 if (TEST_FAIL())
1532 return -1;
1533
1534 hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
1535 if (!hmac)
1536 return -1;
1537
1538 params[0] = OSSL_PARAM_construct_utf8_string("digest", digest, 0);
1539 params[1] = OSSL_PARAM_construct_end();
1540
1541 ctx = EVP_MAC_CTX_new(hmac);
1542 EVP_MAC_free(hmac);
1543 if (!ctx)
1544 return -1;
1545
1546 if (EVP_MAC_init(ctx, key, key_len, params) != 1)
1547 goto fail;
1548
1549 for (i = 0; i < num_elem; i++) {
1550 if (EVP_MAC_update(ctx, addr[i], len[i]) != 1)
1551 goto fail;
1552 }
1553
1554 res = EVP_MAC_final(ctx, mac, &mlen, mdlen);
1555 EVP_MAC_CTX_free(ctx);
1556
1557 return res == 1 ? 0 : -1;
1558fail:
1559 EVP_MAC_CTX_free(ctx);
1560 return -1;
1561}
1562
1563
1564#ifndef CONFIG_FIPS
1565
1566int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
1567 const u8 *addr[], const size_t *len, u8 *mac)
1568{
1569 return openssl_hmac_vector("MD5", key ,key_len, num_elem, addr, len,
1570 mac, 16);
1571}
1572
1573
1574int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1575 u8 *mac)
1576{
1577 return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
1578}
1579
1580#endif /* CONFIG_FIPS */
1581
1582
1583int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
1584 const u8 *addr[], const size_t *len, u8 *mac)
1585{
1586 return openssl_hmac_vector("SHA1", key, key_len, num_elem, addr,
1587 len, mac, 20);
1588}
1589
1590
1591int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1592 u8 *mac)
1593{
1594 return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
1595}
1596
1597
1598#ifdef CONFIG_SHA256
1599
1600int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
1601 const u8 *addr[], const size_t *len, u8 *mac)
1602{
1603 return openssl_hmac_vector("SHA256", key, key_len, num_elem, addr,
1604 len, mac, 32);
1605}
1606
1607
1608int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
1609 size_t data_len, u8 *mac)
1610{
1611 return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
1612}
1613
1614#endif /* CONFIG_SHA256 */
1615
1616
1617#ifdef CONFIG_SHA384
1618
1619int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
1620 const u8 *addr[], const size_t *len, u8 *mac)
1621{
1622 return openssl_hmac_vector("SHA384", key, key_len, num_elem, addr,
1623 len, mac, 48);
1624}
1625
1626
1627int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
1628 size_t data_len, u8 *mac)
1629{
1630 return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
1631}
1632
1633#endif /* CONFIG_SHA384 */
1634
1635
1636#ifdef CONFIG_SHA512
1637
1638int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
1639 const u8 *addr[], const size_t *len, u8 *mac)
1640{
1641 return openssl_hmac_vector("SHA512", key, key_len, num_elem, addr,
1642 len, mac, 64);
1643}
1644
1645
1646int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
1647 size_t data_len, u8 *mac)
1648{
1649 return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
1650}
1651
1652#endif /* CONFIG_SHA512 */
1653
1654#else /* OpenSSL version >= 3.0 */
1655
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001656static int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
1657 size_t key_len, size_t num_elem,
1658 const u8 *addr[], const size_t *len, u8 *mac,
1659 unsigned int mdlen)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001660{
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08001661 HMAC_CTX *ctx;
1662 size_t i;
1663 int res;
1664
1665 if (TEST_FAIL())
1666 return -1;
1667
1668 ctx = HMAC_CTX_new();
1669 if (!ctx)
1670 return -1;
1671 res = HMAC_Init_ex(ctx, key, key_len, type, NULL);
1672 if (res != 1)
1673 goto done;
1674
1675 for (i = 0; i < num_elem; i++)
1676 HMAC_Update(ctx, addr[i], len[i]);
1677
1678 res = HMAC_Final(ctx, mac, &mdlen);
1679done:
1680 HMAC_CTX_free(ctx);
1681
1682 return res == 1 ? 0 : -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001683}
1684
1685
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001686#ifndef CONFIG_FIPS
1687
1688int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
1689 const u8 *addr[], const size_t *len, u8 *mac)
1690{
1691 return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
1692 mac, 16);
1693}
1694
1695
1696int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1697 u8 *mac)
1698{
1699 return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
1700}
1701
1702#endif /* CONFIG_FIPS */
1703
1704
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001705int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
1706 const u8 *addr[], const size_t *len, u8 *mac)
1707{
1708 return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr,
1709 len, mac, 20);
1710}
1711
1712
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001713int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
1714 u8 *mac)
1715{
1716 return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
1717}
1718
1719
1720#ifdef CONFIG_SHA256
1721
1722int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
1723 const u8 *addr[], const size_t *len, u8 *mac)
1724{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001725 return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr,
1726 len, mac, 32);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001727}
1728
1729
1730int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
1731 size_t data_len, u8 *mac)
1732{
1733 return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
1734}
1735
1736#endif /* CONFIG_SHA256 */
1737
1738
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001739#ifdef CONFIG_SHA384
1740
1741int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
1742 const u8 *addr[], const size_t *len, u8 *mac)
1743{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001744 return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001745 len, mac, 48);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001746}
1747
1748
1749int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
1750 size_t data_len, u8 *mac)
1751{
1752 return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
1753}
1754
1755#endif /* CONFIG_SHA384 */
1756
1757
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001758#ifdef CONFIG_SHA512
1759
1760int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
1761 const u8 *addr[], const size_t *len, u8 *mac)
1762{
1763 return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr,
1764 len, mac, 64);
1765}
1766
1767
1768int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
1769 size_t data_len, u8 *mac)
1770{
1771 return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
1772}
1773
1774#endif /* CONFIG_SHA512 */
1775
Sunil Ravia04bd252022-05-02 22:54:18 -07001776#endif /* OpenSSL version >= 3.0 */
1777
1778
1779int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
1780 int iterations, u8 *buf, size_t buflen)
1781{
1782 if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
1783 ssid_len, iterations, buflen, buf) != 1)
1784 return -1;
1785 return 0;
1786}
1787
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001788
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001789int crypto_get_random(void *buf, size_t len)
1790{
1791 if (RAND_bytes(buf, len) != 1)
1792 return -1;
1793 return 0;
1794}
1795
1796
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001797int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
1798 const u8 *addr[], const size_t *len, u8 *mac)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001799{
Sunil Ravia04bd252022-05-02 22:54:18 -07001800#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1801 EVP_MAC_CTX *ctx = NULL;
1802 EVP_MAC *emac;
1803 int ret = -1;
1804 size_t outlen, i;
1805 OSSL_PARAM params[2];
1806 char *cipher = NULL;
1807
1808 if (TEST_FAIL())
1809 return -1;
1810
1811 emac = EVP_MAC_fetch(NULL, "CMAC", NULL);
1812
1813 if (key_len == 32)
1814 cipher = "aes-256-cbc";
1815 else if (key_len == 24)
1816 cipher = "aes-192-cbc";
1817 else if (key_len == 16)
1818 cipher = "aes-128-cbc";
1819
1820 params[0] = OSSL_PARAM_construct_utf8_string("cipher", cipher, 0);
1821 params[1] = OSSL_PARAM_construct_end();
1822
1823 if (!emac || !cipher ||
1824 !(ctx = EVP_MAC_CTX_new(emac)) ||
1825 EVP_MAC_init(ctx, key, key_len, params) != 1)
1826 goto fail;
1827
1828 for (i = 0; i < num_elem; i++) {
1829 if (!EVP_MAC_update(ctx, addr[i], len[i]))
1830 goto fail;
1831 }
1832 if (EVP_MAC_final(ctx, mac, &outlen, 16) != 1 || outlen != 16)
1833 goto fail;
1834
1835 ret = 0;
1836fail:
1837 EVP_MAC_CTX_free(ctx);
1838 return ret;
1839#else /* OpenSSL version >= 3.0 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001840 CMAC_CTX *ctx;
1841 int ret = -1;
1842 size_t outlen, i;
1843
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001844 if (TEST_FAIL())
1845 return -1;
1846
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001847 ctx = CMAC_CTX_new();
1848 if (ctx == NULL)
1849 return -1;
1850
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001851 if (key_len == 32) {
1852 if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL))
1853 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07001854 } else if (key_len == 24) {
1855 if (!CMAC_Init(ctx, key, 24, EVP_aes_192_cbc(), NULL))
1856 goto fail;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001857 } else if (key_len == 16) {
1858 if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
1859 goto fail;
1860 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001861 goto fail;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001862 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001863 for (i = 0; i < num_elem; i++) {
1864 if (!CMAC_Update(ctx, addr[i], len[i]))
1865 goto fail;
1866 }
1867 if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16)
1868 goto fail;
1869
1870 ret = 0;
1871fail:
1872 CMAC_CTX_free(ctx);
1873 return ret;
Sunil Ravia04bd252022-05-02 22:54:18 -07001874#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001875}
1876
1877
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001878int omac1_aes_128_vector(const u8 *key, size_t num_elem,
1879 const u8 *addr[], const size_t *len, u8 *mac)
1880{
1881 return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
1882}
1883
1884
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001885int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1886{
1887 return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
1888}
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001889
1890
1891int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1892{
1893 return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
1894}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001895
1896
1897struct crypto_bignum * crypto_bignum_init(void)
1898{
Dmitry Shmidte4663042016-04-04 10:07:49 -07001899 if (TEST_FAIL())
1900 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001901 return (struct crypto_bignum *) BN_new();
1902}
1903
1904
1905struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
1906{
Dmitry Shmidte4663042016-04-04 10:07:49 -07001907 BIGNUM *bn;
1908
1909 if (TEST_FAIL())
1910 return NULL;
1911
1912 bn = BN_bin2bn(buf, len, NULL);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001913 return (struct crypto_bignum *) bn;
1914}
1915
1916
Hai Shalomc3565922019-10-28 11:58:20 -07001917struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
1918{
1919 BIGNUM *bn;
1920
1921 if (TEST_FAIL())
1922 return NULL;
1923
1924 bn = BN_new();
1925 if (!bn)
1926 return NULL;
1927 if (BN_set_word(bn, val) != 1) {
1928 BN_free(bn);
1929 return NULL;
1930 }
1931 return (struct crypto_bignum *) bn;
1932}
1933
1934
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001935void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
1936{
1937 if (clear)
1938 BN_clear_free((BIGNUM *) n);
1939 else
1940 BN_free((BIGNUM *) n);
1941}
1942
1943
1944int crypto_bignum_to_bin(const struct crypto_bignum *a,
1945 u8 *buf, size_t buflen, size_t padlen)
1946{
1947 int num_bytes, offset;
1948
Dmitry Shmidte4663042016-04-04 10:07:49 -07001949 if (TEST_FAIL())
1950 return -1;
1951
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001952 if (padlen > buflen)
1953 return -1;
1954
Hai Shalomc3565922019-10-28 11:58:20 -07001955 if (padlen) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001956#ifdef OPENSSL_IS_BORINGSSL
Hai Shalomc3565922019-10-28 11:58:20 -07001957 if (BN_bn2bin_padded(buf, padlen, (const BIGNUM *) a) == 0)
1958 return -1;
1959 return padlen;
Hai Shalom81f62d82019-07-22 12:10:00 -07001960#else /* OPENSSL_IS_BORINGSSL */
1961#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
Hai Shalomc3565922019-10-28 11:58:20 -07001962 return BN_bn2binpad((const BIGNUM *) a, buf, padlen);
1963#endif
1964#endif
1965 }
1966
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001967 num_bytes = BN_num_bytes((const BIGNUM *) a);
1968 if ((size_t) num_bytes > buflen)
1969 return -1;
1970 if (padlen > (size_t) num_bytes)
1971 offset = padlen - num_bytes;
1972 else
1973 offset = 0;
1974
1975 os_memset(buf, 0, offset);
1976 BN_bn2bin((const BIGNUM *) a, buf + offset);
1977
1978 return num_bytes + offset;
1979}
1980
1981
Roshan Pius3a1667e2018-07-03 15:17:14 -07001982int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
1983{
Hai Shalom5f92bc92019-04-18 11:54:11 -07001984 if (TEST_FAIL())
1985 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001986 return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
1987}
1988
1989
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001990int crypto_bignum_add(const struct crypto_bignum *a,
1991 const struct crypto_bignum *b,
1992 struct crypto_bignum *c)
1993{
1994 return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
1995 0 : -1;
1996}
1997
1998
1999int crypto_bignum_mod(const struct crypto_bignum *a,
2000 const struct crypto_bignum *b,
2001 struct crypto_bignum *c)
2002{
2003 int res;
2004 BN_CTX *bnctx;
2005
2006 bnctx = BN_CTX_new();
2007 if (bnctx == NULL)
2008 return -1;
2009 res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
2010 bnctx);
2011 BN_CTX_free(bnctx);
2012
2013 return res ? 0 : -1;
2014}
2015
2016
2017int crypto_bignum_exptmod(const struct crypto_bignum *a,
2018 const struct crypto_bignum *b,
2019 const struct crypto_bignum *c,
2020 struct crypto_bignum *d)
2021{
2022 int res;
2023 BN_CTX *bnctx;
2024
Dmitry Shmidte4663042016-04-04 10:07:49 -07002025 if (TEST_FAIL())
2026 return -1;
2027
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002028 bnctx = BN_CTX_new();
2029 if (bnctx == NULL)
2030 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002031 res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
2032 (const BIGNUM *) b, (const BIGNUM *) c,
2033 bnctx, NULL);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002034 BN_CTX_free(bnctx);
2035
2036 return res ? 0 : -1;
2037}
2038
2039
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002040int crypto_bignum_inverse(const struct crypto_bignum *a,
2041 const struct crypto_bignum *b,
2042 struct crypto_bignum *c)
2043{
2044 BIGNUM *res;
2045 BN_CTX *bnctx;
2046
Dmitry Shmidte4663042016-04-04 10:07:49 -07002047 if (TEST_FAIL())
2048 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002049 bnctx = BN_CTX_new();
2050 if (bnctx == NULL)
2051 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002052#ifdef OPENSSL_IS_BORINGSSL
2053 /* TODO: use BN_mod_inverse_blinded() ? */
2054#else /* OPENSSL_IS_BORINGSSL */
2055 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
2056#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002057 res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
2058 (const BIGNUM *) b, bnctx);
2059 BN_CTX_free(bnctx);
2060
2061 return res ? 0 : -1;
2062}
2063
2064
2065int crypto_bignum_sub(const struct crypto_bignum *a,
2066 const struct crypto_bignum *b,
2067 struct crypto_bignum *c)
2068{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002069 if (TEST_FAIL())
2070 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002071 return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
2072 0 : -1;
2073}
2074
2075
2076int crypto_bignum_div(const struct crypto_bignum *a,
2077 const struct crypto_bignum *b,
2078 struct crypto_bignum *c)
2079{
2080 int res;
2081
2082 BN_CTX *bnctx;
2083
Dmitry Shmidte4663042016-04-04 10:07:49 -07002084 if (TEST_FAIL())
2085 return -1;
2086
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002087 bnctx = BN_CTX_new();
2088 if (bnctx == NULL)
2089 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002090#ifndef OPENSSL_IS_BORINGSSL
2091 BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
2092#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002093 res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
2094 (const BIGNUM *) b, bnctx);
2095 BN_CTX_free(bnctx);
2096
2097 return res ? 0 : -1;
2098}
2099
2100
Hai Shalomc3565922019-10-28 11:58:20 -07002101int crypto_bignum_addmod(const struct crypto_bignum *a,
2102 const struct crypto_bignum *b,
2103 const struct crypto_bignum *c,
2104 struct crypto_bignum *d)
2105{
2106 int res;
2107 BN_CTX *bnctx;
2108
2109 if (TEST_FAIL())
2110 return -1;
2111
2112 bnctx = BN_CTX_new();
2113 if (!bnctx)
2114 return -1;
2115 res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
2116 (const BIGNUM *) c, bnctx);
2117 BN_CTX_free(bnctx);
2118
2119 return res ? 0 : -1;
2120}
2121
2122
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002123int crypto_bignum_mulmod(const struct crypto_bignum *a,
2124 const struct crypto_bignum *b,
2125 const struct crypto_bignum *c,
2126 struct crypto_bignum *d)
2127{
2128 int res;
2129
2130 BN_CTX *bnctx;
2131
Dmitry Shmidte4663042016-04-04 10:07:49 -07002132 if (TEST_FAIL())
2133 return -1;
2134
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002135 bnctx = BN_CTX_new();
2136 if (bnctx == NULL)
2137 return -1;
2138 res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
2139 (const BIGNUM *) c, bnctx);
2140 BN_CTX_free(bnctx);
2141
2142 return res ? 0 : -1;
2143}
2144
2145
Hai Shalomc3565922019-10-28 11:58:20 -07002146int crypto_bignum_sqrmod(const struct crypto_bignum *a,
2147 const struct crypto_bignum *b,
2148 struct crypto_bignum *c)
2149{
2150 int res;
2151 BN_CTX *bnctx;
2152
2153 if (TEST_FAIL())
2154 return -1;
2155
2156 bnctx = BN_CTX_new();
2157 if (!bnctx)
2158 return -1;
2159 res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
2160 bnctx);
2161 BN_CTX_free(bnctx);
2162
2163 return res ? 0 : -1;
2164}
2165
2166
Roshan Pius3a1667e2018-07-03 15:17:14 -07002167int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
2168 struct crypto_bignum *r)
2169{
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002170 return BN_rshift((BIGNUM *) r, (const BIGNUM *) a, n) == 1 ? 0 : -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002171}
2172
2173
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002174int crypto_bignum_cmp(const struct crypto_bignum *a,
2175 const struct crypto_bignum *b)
2176{
2177 return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b);
2178}
2179
2180
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002181int crypto_bignum_is_zero(const struct crypto_bignum *a)
2182{
2183 return BN_is_zero((const BIGNUM *) a);
2184}
2185
2186
2187int crypto_bignum_is_one(const struct crypto_bignum *a)
2188{
2189 return BN_is_one((const BIGNUM *) a);
2190}
2191
2192
Roshan Pius3a1667e2018-07-03 15:17:14 -07002193int crypto_bignum_is_odd(const struct crypto_bignum *a)
2194{
2195 return BN_is_odd((const BIGNUM *) a);
2196}
2197
2198
Dmitry Shmidt41712582015-06-29 11:02:15 -07002199int crypto_bignum_legendre(const struct crypto_bignum *a,
2200 const struct crypto_bignum *p)
2201{
2202 BN_CTX *bnctx;
2203 BIGNUM *exp = NULL, *tmp = NULL;
2204 int res = -2;
Hai Shalom021b0b52019-04-10 11:17:58 -07002205 unsigned int mask;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002206
Dmitry Shmidte4663042016-04-04 10:07:49 -07002207 if (TEST_FAIL())
2208 return -2;
2209
Dmitry Shmidt41712582015-06-29 11:02:15 -07002210 bnctx = BN_CTX_new();
2211 if (bnctx == NULL)
2212 return -2;
2213
2214 exp = BN_new();
2215 tmp = BN_new();
2216 if (!exp || !tmp ||
2217 /* exp = (p-1) / 2 */
2218 !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
2219 !BN_rshift1(exp, exp) ||
Hai Shalom021b0b52019-04-10 11:17:58 -07002220 !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
2221 (const BIGNUM *) p, bnctx, NULL))
Dmitry Shmidt41712582015-06-29 11:02:15 -07002222 goto fail;
2223
Hai Shalom021b0b52019-04-10 11:17:58 -07002224 /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
2225 * constant time selection to avoid branches here. */
2226 res = -1;
2227 mask = const_time_eq(BN_is_word(tmp, 1), 1);
2228 res = const_time_select_int(mask, 1, res);
2229 mask = const_time_eq(BN_is_zero(tmp), 1);
2230 res = const_time_select_int(mask, 0, res);
Dmitry Shmidt41712582015-06-29 11:02:15 -07002231
2232fail:
2233 BN_clear_free(tmp);
2234 BN_clear_free(exp);
2235 BN_CTX_free(bnctx);
2236 return res;
2237}
2238
2239
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002240#ifdef CONFIG_ECC
2241
2242struct crypto_ec {
2243 EC_GROUP *group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002244 int nid;
Sunil8cd6f4d2022-06-28 18:40:46 +00002245 int iana_group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002246 BN_CTX *bnctx;
2247 BIGNUM *prime;
2248 BIGNUM *order;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002249 BIGNUM *a;
2250 BIGNUM *b;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002251};
2252
Hai Shaloma20dcd72022-02-04 13:43:00 -08002253
2254static int crypto_ec_group_2_nid(int group)
2255{
2256 /* Map from IANA registry for IKE D-H groups to OpenSSL NID */
2257 switch (group) {
2258 case 19:
2259 return NID_X9_62_prime256v1;
2260 case 20:
2261 return NID_secp384r1;
2262 case 21:
2263 return NID_secp521r1;
2264 case 25:
2265 return NID_X9_62_prime192v1;
2266 case 26:
2267 return NID_secp224r1;
2268#ifdef NID_brainpoolP224r1
2269 case 27:
2270 return NID_brainpoolP224r1;
2271#endif /* NID_brainpoolP224r1 */
2272#ifdef NID_brainpoolP256r1
2273 case 28:
2274 return NID_brainpoolP256r1;
2275#endif /* NID_brainpoolP256r1 */
2276#ifdef NID_brainpoolP384r1
2277 case 29:
2278 return NID_brainpoolP384r1;
2279#endif /* NID_brainpoolP384r1 */
2280#ifdef NID_brainpoolP512r1
2281 case 30:
2282 return NID_brainpoolP512r1;
2283#endif /* NID_brainpoolP512r1 */
2284 default:
2285 return -1;
2286 }
2287}
2288
2289
Sunil8cd6f4d2022-06-28 18:40:46 +00002290#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2291static const char * crypto_ec_group_2_name(int group)
2292{
2293 /* Map from IANA registry for IKE D-H groups to OpenSSL group name */
2294 switch (group) {
2295 case 19:
2296 return "prime256v1";
2297 case 20:
2298 return "secp384r1";
2299 case 21:
2300 return "secp521r1";
2301 case 25:
2302 return "prime192v1";
2303 case 26:
2304 return "secp224r1";
2305#ifdef NID_brainpoolP224r1
2306 case 27:
2307 return "brainpoolP224r1";
2308#endif /* NID_brainpoolP224r1 */
2309#ifdef NID_brainpoolP256r1
2310 case 28:
2311 return "brainpoolP256r1";
2312#endif /* NID_brainpoolP256r1 */
2313#ifdef NID_brainpoolP384r1
2314 case 29:
2315 return "brainpoolP384r1";
2316#endif /* NID_brainpoolP384r1 */
2317#ifdef NID_brainpoolP512r1
2318 case 30:
2319 return "brainpoolP512r1";
2320#endif /* NID_brainpoolP512r1 */
2321 default:
2322 return NULL;
2323 }
2324}
2325#endif /* OpenSSL version >= 3.0 */
2326
2327
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002328struct crypto_ec * crypto_ec_init(int group)
2329{
2330 struct crypto_ec *e;
2331 int nid;
2332
Hai Shaloma20dcd72022-02-04 13:43:00 -08002333 nid = crypto_ec_group_2_nid(group);
2334 if (nid < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002335 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002336
2337 e = os_zalloc(sizeof(*e));
2338 if (e == NULL)
2339 return NULL;
2340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002341 e->nid = nid;
Sunil8cd6f4d2022-06-28 18:40:46 +00002342 e->iana_group = group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002343 e->bnctx = BN_CTX_new();
2344 e->group = EC_GROUP_new_by_curve_name(nid);
2345 e->prime = BN_new();
2346 e->order = BN_new();
Dmitry Shmidt41712582015-06-29 11:02:15 -07002347 e->a = BN_new();
2348 e->b = BN_new();
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002349 if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
Dmitry Shmidt41712582015-06-29 11:02:15 -07002350 e->order == NULL || e->a == NULL || e->b == NULL ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002351 !EC_GROUP_get_curve(e->group, e->prime, e->a, e->b, e->bnctx) ||
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002352 !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
2353 crypto_ec_deinit(e);
2354 e = NULL;
2355 }
2356
2357 return e;
2358}
2359
2360
2361void crypto_ec_deinit(struct crypto_ec *e)
2362{
2363 if (e == NULL)
2364 return;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002365 BN_clear_free(e->b);
2366 BN_clear_free(e->a);
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002367 BN_clear_free(e->order);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002368 BN_clear_free(e->prime);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002369 EC_GROUP_free(e->group);
2370 BN_CTX_free(e->bnctx);
2371 os_free(e);
2372}
2373
2374
2375struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
2376{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002377 if (TEST_FAIL())
2378 return NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002379 if (e == NULL)
2380 return NULL;
2381 return (struct crypto_ec_point *) EC_POINT_new(e->group);
2382}
2383
2384
2385size_t crypto_ec_prime_len(struct crypto_ec *e)
2386{
2387 return BN_num_bytes(e->prime);
2388}
2389
2390
2391size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
2392{
2393 return BN_num_bits(e->prime);
2394}
2395
2396
Roshan Pius3a1667e2018-07-03 15:17:14 -07002397size_t crypto_ec_order_len(struct crypto_ec *e)
2398{
2399 return BN_num_bytes(e->order);
2400}
2401
2402
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002403const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
2404{
2405 return (const struct crypto_bignum *) e->prime;
2406}
2407
2408
2409const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
2410{
2411 return (const struct crypto_bignum *) e->order;
2412}
2413
2414
Hai Shalomc3565922019-10-28 11:58:20 -07002415const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e)
2416{
2417 return (const struct crypto_bignum *) e->a;
2418}
2419
2420
2421const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
2422{
2423 return (const struct crypto_bignum *) e->b;
2424}
2425
2426
Hai Shaloma20dcd72022-02-04 13:43:00 -08002427const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
2428{
2429 return (const struct crypto_ec_point *)
2430 EC_GROUP_get0_generator(e->group);
2431}
2432
2433
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002434void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
2435{
2436 if (clear)
2437 EC_POINT_clear_free((EC_POINT *) p);
2438 else
2439 EC_POINT_free((EC_POINT *) p);
2440}
2441
2442
Roshan Pius3a1667e2018-07-03 15:17:14 -07002443int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
2444 struct crypto_bignum *x)
2445{
Sunil Ravia04bd252022-05-02 22:54:18 -07002446 return EC_POINT_get_affine_coordinates(e->group,
2447 (const EC_POINT *) p,
2448 (BIGNUM *) x, NULL,
2449 e->bnctx) == 1 ? 0 : -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002450}
2451
2452
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002453int crypto_ec_point_to_bin(struct crypto_ec *e,
2454 const struct crypto_ec_point *point, u8 *x, u8 *y)
2455{
2456 BIGNUM *x_bn, *y_bn;
2457 int ret = -1;
2458 int len = BN_num_bytes(e->prime);
2459
Dmitry Shmidte4663042016-04-04 10:07:49 -07002460 if (TEST_FAIL())
2461 return -1;
2462
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002463 x_bn = BN_new();
2464 y_bn = BN_new();
2465
2466 if (x_bn && y_bn &&
Sunil Ravia04bd252022-05-02 22:54:18 -07002467 EC_POINT_get_affine_coordinates(e->group, (EC_POINT *) point,
2468 x_bn, y_bn, e->bnctx)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002469 if (x) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002470 ret = crypto_bignum_to_bin(
2471 (struct crypto_bignum *) x_bn, x, len, len);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002472 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002473 if (ret >= 0 && y) {
2474 ret = crypto_bignum_to_bin(
2475 (struct crypto_bignum *) y_bn, y, len, len);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002476 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002477
2478 if (ret > 0)
2479 ret = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002480 }
2481
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002482 BN_clear_free(x_bn);
2483 BN_clear_free(y_bn);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002484 return ret;
2485}
2486
2487
2488struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
2489 const u8 *val)
2490{
2491 BIGNUM *x, *y;
2492 EC_POINT *elem;
2493 int len = BN_num_bytes(e->prime);
2494
Dmitry Shmidte4663042016-04-04 10:07:49 -07002495 if (TEST_FAIL())
2496 return NULL;
2497
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002498 x = BN_bin2bn(val, len, NULL);
2499 y = BN_bin2bn(val + len, len, NULL);
2500 elem = EC_POINT_new(e->group);
2501 if (x == NULL || y == NULL || elem == NULL) {
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002502 BN_clear_free(x);
2503 BN_clear_free(y);
2504 EC_POINT_clear_free(elem);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002505 return NULL;
2506 }
2507
Sunil Ravia04bd252022-05-02 22:54:18 -07002508 if (!EC_POINT_set_affine_coordinates(e->group, elem, x, y, e->bnctx)) {
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002509 EC_POINT_clear_free(elem);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002510 elem = NULL;
2511 }
2512
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07002513 BN_clear_free(x);
2514 BN_clear_free(y);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002515
2516 return (struct crypto_ec_point *) elem;
2517}
2518
2519
2520int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
2521 const struct crypto_ec_point *b,
2522 struct crypto_ec_point *c)
2523{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002524 if (TEST_FAIL())
2525 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002526 return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
2527 (const EC_POINT *) b, e->bnctx) ? 0 : -1;
2528}
2529
2530
2531int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
2532 const struct crypto_bignum *b,
2533 struct crypto_ec_point *res)
2534{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002535 if (TEST_FAIL())
2536 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002537 return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
2538 (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
2539 ? 0 : -1;
2540}
2541
2542
2543int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
2544{
Dmitry Shmidte4663042016-04-04 10:07:49 -07002545 if (TEST_FAIL())
2546 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002547 return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
2548}
2549
2550
Dmitry Shmidt41712582015-06-29 11:02:15 -07002551struct crypto_bignum *
2552crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
2553 const struct crypto_bignum *x)
2554{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002555 BIGNUM *tmp;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002556
Dmitry Shmidte4663042016-04-04 10:07:49 -07002557 if (TEST_FAIL())
2558 return NULL;
2559
Dmitry Shmidt41712582015-06-29 11:02:15 -07002560 tmp = BN_new();
Dmitry Shmidt41712582015-06-29 11:02:15 -07002561
Hai Shaloma20dcd72022-02-04 13:43:00 -08002562 /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
2563 if (tmp &&
Dmitry Shmidt41712582015-06-29 11:02:15 -07002564 BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002565 BN_mod_add_quick(tmp, e->a, tmp, e->prime) &&
Dmitry Shmidt41712582015-06-29 11:02:15 -07002566 BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002567 BN_mod_add_quick(tmp, tmp, e->b, e->prime))
2568 return (struct crypto_bignum *) tmp;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002569
2570 BN_clear_free(tmp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002571 return NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07002572}
2573
2574
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002575int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
2576 const struct crypto_ec_point *p)
2577{
2578 return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p);
2579}
2580
2581
2582int crypto_ec_point_is_on_curve(struct crypto_ec *e,
2583 const struct crypto_ec_point *p)
2584{
Dmitry Shmidt41712582015-06-29 11:02:15 -07002585 return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p,
2586 e->bnctx) == 1;
2587}
2588
2589
2590int crypto_ec_point_cmp(const struct crypto_ec *e,
2591 const struct crypto_ec_point *a,
2592 const struct crypto_ec_point *b)
2593{
2594 return EC_POINT_cmp(e->group, (const EC_POINT *) a,
2595 (const EC_POINT *) b, e->bnctx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002596}
2597
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002598
Hai Shaloma20dcd72022-02-04 13:43:00 -08002599void crypto_ec_point_debug_print(const struct crypto_ec *e,
2600 const struct crypto_ec_point *p,
2601 const char *title)
2602{
2603 BIGNUM *x, *y;
2604 char *x_str = NULL, *y_str = NULL;
2605
2606 x = BN_new();
2607 y = BN_new();
2608 if (!x || !y ||
Sunil Ravia04bd252022-05-02 22:54:18 -07002609 EC_POINT_get_affine_coordinates(e->group, (const EC_POINT *) p,
2610 x, y, e->bnctx) != 1)
Hai Shaloma20dcd72022-02-04 13:43:00 -08002611 goto fail;
2612
2613 x_str = BN_bn2hex(x);
2614 y_str = BN_bn2hex(y);
2615 if (!x_str || !y_str)
2616 goto fail;
2617
2618 wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
2619
2620fail:
2621 OPENSSL_free(x_str);
2622 OPENSSL_free(y_str);
2623 BN_free(x);
2624 BN_free(y);
2625}
2626
2627
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002628struct crypto_ecdh {
2629 struct crypto_ec *ec;
2630 EVP_PKEY *pkey;
2631};
2632
2633struct crypto_ecdh * crypto_ecdh_init(int group)
2634{
Sunil Ravia04bd252022-05-02 22:54:18 -07002635#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2636 struct crypto_ecdh *ecdh;
2637 const char *name;
2638
2639 ecdh = os_zalloc(sizeof(*ecdh));
2640 if (!ecdh)
2641 goto fail;
2642
2643 ecdh->ec = crypto_ec_init(group);
2644 if (!ecdh->ec)
2645 goto fail;
2646
2647 name = OSSL_EC_curve_nid2name(ecdh->ec->nid);
2648 if (!name)
2649 goto fail;
2650
2651 ecdh->pkey = EVP_EC_gen(name);
2652 if (!ecdh->pkey)
2653 goto fail;
2654
2655done:
2656 return ecdh;
2657fail:
2658 crypto_ecdh_deinit(ecdh);
2659 ecdh = NULL;
2660 goto done;
2661#else /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002662 struct crypto_ecdh *ecdh;
2663 EVP_PKEY *params = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002664 EC_KEY *ec_params = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002665 EVP_PKEY_CTX *kctx = NULL;
2666
2667 ecdh = os_zalloc(sizeof(*ecdh));
2668 if (!ecdh)
2669 goto fail;
2670
2671 ecdh->ec = crypto_ec_init(group);
2672 if (!ecdh->ec)
2673 goto fail;
2674
Roshan Pius3a1667e2018-07-03 15:17:14 -07002675 ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid);
2676 if (!ec_params) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002677 wpa_printf(MSG_ERROR,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002678 "OpenSSL: Failed to generate EC_KEY parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002679 goto fail;
2680 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002681 EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
2682 params = EVP_PKEY_new();
2683 if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002684 wpa_printf(MSG_ERROR,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002685 "OpenSSL: Failed to generate EVP_PKEY parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002686 goto fail;
2687 }
2688
2689 kctx = EVP_PKEY_CTX_new(params, NULL);
2690 if (!kctx)
2691 goto fail;
2692
2693 if (EVP_PKEY_keygen_init(kctx) != 1) {
2694 wpa_printf(MSG_ERROR,
2695 "OpenSSL: EVP_PKEY_keygen_init failed: %s",
2696 ERR_error_string(ERR_get_error(), NULL));
2697 goto fail;
2698 }
2699
2700 if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) {
2701 wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s",
2702 ERR_error_string(ERR_get_error(), NULL));
2703 goto fail;
2704 }
2705
2706done:
Hai Shalom81f62d82019-07-22 12:10:00 -07002707 EC_KEY_free(ec_params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002708 EVP_PKEY_free(params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002709 EVP_PKEY_CTX_free(kctx);
2710
2711 return ecdh;
2712fail:
2713 crypto_ecdh_deinit(ecdh);
2714 ecdh = NULL;
2715 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07002716#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002717}
2718
2719
Hai Shaloma20dcd72022-02-04 13:43:00 -08002720struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
2721{
Sunil Ravia04bd252022-05-02 22:54:18 -07002722#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2723 struct crypto_ecdh *ecdh;
2724
2725 ecdh = os_zalloc(sizeof(*ecdh));
2726 if (!ecdh)
2727 goto fail;
2728
2729 ecdh->ec = crypto_ec_init(group);
2730 if (!ecdh->ec)
2731 goto fail;
2732
2733 ecdh->pkey = EVP_PKEY_dup((EVP_PKEY *) own_key);
2734 if (!ecdh->pkey)
2735 goto fail;
2736
2737 return ecdh;
2738fail:
2739 crypto_ecdh_deinit(ecdh);
2740 return NULL;
2741#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002742 struct crypto_ecdh *ecdh;
2743
2744 ecdh = os_zalloc(sizeof(*ecdh));
2745 if (!ecdh)
2746 goto fail;
2747
2748 ecdh->ec = crypto_ec_init(group);
2749 if (!ecdh->ec)
2750 goto fail;
2751
2752 ecdh->pkey = EVP_PKEY_new();
2753 if (!ecdh->pkey ||
2754 EVP_PKEY_assign_EC_KEY(ecdh->pkey,
2755 EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key))
2756 != 1)
2757 goto fail;
2758
2759 return ecdh;
2760fail:
2761 crypto_ecdh_deinit(ecdh);
2762 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07002763#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002764}
2765
2766
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002767struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
2768{
Sunil Ravia04bd252022-05-02 22:54:18 -07002769#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2770 struct wpabuf *buf = NULL;
2771 unsigned char *pub;
2772 size_t len, exp_len;
2773
2774 len = EVP_PKEY_get1_encoded_public_key(ecdh->pkey, &pub);
2775 if (len == 0)
2776 return NULL;
2777
2778 /* Encoded using SECG SEC 1, Sec. 2.3.4 format */
2779 exp_len = 1 + 2 * crypto_ec_prime_len(ecdh->ec);
2780 if (len != exp_len) {
2781 wpa_printf(MSG_ERROR,
2782 "OpenSSL:%s: Unexpected encoded public key length %zu (expected %zu)",
2783 __func__, len, exp_len);
2784 goto fail;
2785 }
2786 buf = wpabuf_alloc_copy(pub + 1, inc_y ? len - 1 : len / 2);
2787fail:
2788 OPENSSL_free(pub);
2789 return buf;
2790#else /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002791 struct wpabuf *buf = NULL;
2792 EC_KEY *eckey;
2793 const EC_POINT *pubkey;
2794 BIGNUM *x, *y = NULL;
2795 int len = BN_num_bytes(ecdh->ec->prime);
2796 int res;
2797
2798 eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey);
2799 if (!eckey)
2800 return NULL;
2801
2802 pubkey = EC_KEY_get0_public_key(eckey);
2803 if (!pubkey)
2804 return NULL;
2805
2806 x = BN_new();
2807 if (inc_y) {
2808 y = BN_new();
2809 if (!y)
2810 goto fail;
2811 }
2812 buf = wpabuf_alloc(inc_y ? 2 * len : len);
2813 if (!x || !buf)
2814 goto fail;
2815
Sunil Ravia04bd252022-05-02 22:54:18 -07002816 if (EC_POINT_get_affine_coordinates(ecdh->ec->group, pubkey,
2817 x, y, ecdh->ec->bnctx) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002818 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07002819 "OpenSSL: EC_POINT_get_affine_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002820 ERR_error_string(ERR_get_error(), NULL));
2821 goto fail;
2822 }
2823
2824 res = crypto_bignum_to_bin((struct crypto_bignum *) x,
2825 wpabuf_put(buf, len), len, len);
2826 if (res < 0)
2827 goto fail;
2828
2829 if (inc_y) {
2830 res = crypto_bignum_to_bin((struct crypto_bignum *) y,
2831 wpabuf_put(buf, len), len, len);
2832 if (res < 0)
2833 goto fail;
2834 }
2835
2836done:
2837 BN_clear_free(x);
2838 BN_clear_free(y);
2839 EC_KEY_free(eckey);
2840
2841 return buf;
2842fail:
2843 wpabuf_free(buf);
2844 buf = NULL;
2845 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07002846#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002847}
2848
2849
2850struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
2851 const u8 *key, size_t len)
2852{
Sunil Ravia04bd252022-05-02 22:54:18 -07002853#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2854 EVP_PKEY *peerkey = EVP_PKEY_new();
2855 EVP_PKEY_CTX *ctx;
2856 size_t res_len;
2857 struct wpabuf *res = NULL;
2858 u8 *peer;
2859
2860 /* Encode using SECG SEC 1, Sec. 2.3.4 format */
2861 peer = os_malloc(1 + len);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002862 if (!peer) {
2863 EVP_PKEY_free(peerkey);
Sunil Ravia04bd252022-05-02 22:54:18 -07002864 return NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002865 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002866 peer[0] = inc_y ? 0x04 : 0x02;
2867 os_memcpy(peer + 1, key, len);
2868
2869 if (!peerkey ||
2870 EVP_PKEY_copy_parameters(peerkey, ecdh->pkey) != 1 ||
2871 EVP_PKEY_set1_encoded_public_key(peerkey, peer, 1 + len) != 1) {
2872 wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_set1_encoded_public_key failed: %s",
2873 ERR_error_string(ERR_get_error(), NULL));
2874 EVP_PKEY_free(peerkey);
2875 os_free(peer);
2876 return NULL;
2877 }
2878 os_free(peer);
2879
2880 ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL);
2881 if (!ctx ||
2882 EVP_PKEY_derive_init(ctx) != 1 ||
2883 EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 ||
2884 EVP_PKEY_derive(ctx, NULL, &res_len) != 1 ||
2885 !(res = wpabuf_alloc(res_len)) ||
2886 EVP_PKEY_derive(ctx, wpabuf_mhead(res), &res_len) != 1) {
2887 wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_derive failed: %s",
2888 ERR_error_string(ERR_get_error(), NULL));
2889 wpabuf_free(res);
2890 res = NULL;
2891 } else {
2892 wpabuf_put(res, res_len);
2893 }
2894
2895 EVP_PKEY_free(peerkey);
2896 EVP_PKEY_CTX_free(ctx);
2897 return res;
2898#else /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002899 BIGNUM *x, *y = NULL;
2900 EVP_PKEY_CTX *ctx = NULL;
2901 EVP_PKEY *peerkey = NULL;
2902 struct wpabuf *secret = NULL;
2903 size_t secret_len;
2904 EC_POINT *pub;
2905 EC_KEY *eckey = NULL;
2906
2907 x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL);
2908 pub = EC_POINT_new(ecdh->ec->group);
2909 if (!x || !pub)
2910 goto fail;
2911
2912 if (inc_y) {
2913 y = BN_bin2bn(key + len / 2, len / 2, NULL);
2914 if (!y)
2915 goto fail;
Sunil Ravia04bd252022-05-02 22:54:18 -07002916 if (!EC_POINT_set_affine_coordinates(ecdh->ec->group, pub,
2917 x, y, ecdh->ec->bnctx)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002918 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07002919 "OpenSSL: EC_POINT_set_affine_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002920 ERR_error_string(ERR_get_error(), NULL));
2921 goto fail;
2922 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002923 } else if (!EC_POINT_set_compressed_coordinates(ecdh->ec->group,
2924 pub, x, 0,
2925 ecdh->ec->bnctx)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002926 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07002927 "OpenSSL: EC_POINT_set_compressed_coordinates failed: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928 ERR_error_string(ERR_get_error(), NULL));
2929 goto fail;
2930 }
2931
2932 if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) {
2933 wpa_printf(MSG_ERROR,
2934 "OpenSSL: ECDH peer public key is not on curve");
2935 goto fail;
2936 }
2937
2938 eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid);
2939 if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) {
2940 wpa_printf(MSG_ERROR,
2941 "OpenSSL: EC_KEY_set_public_key failed: %s",
2942 ERR_error_string(ERR_get_error(), NULL));
2943 goto fail;
2944 }
2945
2946 peerkey = EVP_PKEY_new();
2947 if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1)
2948 goto fail;
2949
2950 ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL);
2951 if (!ctx || EVP_PKEY_derive_init(ctx) != 1 ||
2952 EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 ||
2953 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) {
2954 wpa_printf(MSG_ERROR,
2955 "OpenSSL: EVP_PKEY_derive(1) failed: %s",
2956 ERR_error_string(ERR_get_error(), NULL));
2957 goto fail;
2958 }
2959
2960 secret = wpabuf_alloc(secret_len);
2961 if (!secret)
2962 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07002963 if (EVP_PKEY_derive(ctx, wpabuf_put(secret, 0), &secret_len) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002964 wpa_printf(MSG_ERROR,
2965 "OpenSSL: EVP_PKEY_derive(2) failed: %s",
2966 ERR_error_string(ERR_get_error(), NULL));
2967 goto fail;
2968 }
Hai Shalomc3565922019-10-28 11:58:20 -07002969 if (secret->size != secret_len)
2970 wpa_printf(MSG_DEBUG,
2971 "OpenSSL: EVP_PKEY_derive(2) changed secret_len %d -> %d",
2972 (int) secret->size, (int) secret_len);
2973 wpabuf_put(secret, secret_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002974
2975done:
2976 BN_free(x);
2977 BN_free(y);
2978 EC_KEY_free(eckey);
2979 EC_POINT_free(pub);
2980 EVP_PKEY_CTX_free(ctx);
2981 EVP_PKEY_free(peerkey);
2982 return secret;
2983fail:
2984 wpabuf_free(secret);
2985 secret = NULL;
2986 goto done;
Sunil Ravia04bd252022-05-02 22:54:18 -07002987#endif /* OpenSSL version >= 3.0 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002988}
2989
2990
2991void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
2992{
2993 if (ecdh) {
2994 crypto_ec_deinit(ecdh->ec);
2995 EVP_PKEY_free(ecdh->pkey);
2996 os_free(ecdh);
2997 }
2998}
2999
Hai Shalomfdcde762020-04-02 11:19:20 -07003000
3001size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
3002{
3003 return crypto_ec_prime_len(ecdh->ec);
3004}
3005
Hai Shalom899fcc72020-10-19 14:38:18 -07003006
Hai Shalom899fcc72020-10-19 14:38:18 -07003007struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
3008{
Sunil8cd6f4d2022-06-28 18:40:46 +00003009#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3010 EVP_PKEY *pkey = NULL;
3011 OSSL_DECODER_CTX *ctx;
3012
3013 ctx = OSSL_DECODER_CTX_new_for_pkey(
3014 &pkey, "DER", NULL, "EC",
3015 OSSL_KEYMGMT_SELECT_KEYPAIR |
3016 OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
3017 NULL, NULL);
3018 if (!ctx ||
3019 OSSL_DECODER_from_data(ctx, &der, &der_len) != 1) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003020 wpa_printf(MSG_INFO,
3021 "OpenSSL: Decoding EC private key (DER) failed: %s",
Sunil8cd6f4d2022-06-28 18:40:46 +00003022 ERR_error_string(ERR_get_error(), NULL));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003023 if (ctx)
3024 OSSL_DECODER_CTX_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003025 goto fail;
3026 }
3027
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003028 OSSL_DECODER_CTX_free(ctx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003029 return (struct crypto_ec_key *) pkey;
3030fail:
3031 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
3032 return NULL;
3033#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003034 EVP_PKEY *pkey = NULL;
3035 EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003036
Hai Shaloma20dcd72022-02-04 13:43:00 -08003037 eckey = d2i_ECPrivateKey(NULL, &der, der_len);
3038 if (!eckey) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003039 wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s",
3040 ERR_error_string(ERR_get_error(), NULL));
3041 goto fail;
3042 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003043 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
Hai Shalom899fcc72020-10-19 14:38:18 -07003044
Hai Shaloma20dcd72022-02-04 13:43:00 -08003045 pkey = EVP_PKEY_new();
3046 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3047 EC_KEY_free(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003048 goto fail;
3049 }
3050
Hai Shaloma20dcd72022-02-04 13:43:00 -08003051 return (struct crypto_ec_key *) pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003052fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003053 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003054 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003055#endif /* OpenSSL version >= 3.0 */
Hai Shalom899fcc72020-10-19 14:38:18 -07003056}
3057
3058
Sunil Ravi89eba102022-09-13 21:04:37 -07003059struct crypto_ec_key * crypto_ec_key_set_priv(int group,
3060 const u8 *raw, size_t raw_len)
3061{
3062#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3063 const char *group_name;
3064 OSSL_PARAM params[4];
3065 EVP_PKEY_CTX *ctx = NULL;
3066 EVP_PKEY *pkey = NULL;
3067 BIGNUM *priv;
3068 EC_POINT *pub = NULL;
3069 EC_GROUP *ec_group = NULL;
3070 size_t len;
3071 u8 *pub_bin = NULL;
3072 u8 *priv_bin = NULL;
3073 int priv_bin_len;
3074
3075 group_name = crypto_ec_group_2_name(group);
3076 if (!group_name)
3077 return NULL;
3078
3079 priv = BN_bin2bn(raw, raw_len, NULL);
3080 if (!priv)
3081 return NULL;
3082 priv_bin = os_malloc(raw_len);
3083 if (!priv_bin)
3084 goto fail;
3085 priv_bin_len = BN_bn2lebinpad(priv, priv_bin, raw_len);
3086 if (priv_bin_len < 0)
3087 goto fail;
3088
3089 ec_group = EC_GROUP_new_by_curve_name(crypto_ec_group_2_nid(group));
3090 if (!ec_group)
3091 goto fail;
3092 pub = EC_POINT_new(ec_group);
3093 if (!pub ||
3094 EC_POINT_mul(ec_group, pub, priv, NULL, NULL, NULL) != 1)
3095 goto fail;
3096 len = EC_POINT_point2oct(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED,
3097 NULL, 0, NULL);
3098 if (len == 0)
3099 goto fail;
3100 pub_bin = os_malloc(len);
3101 if (!pub_bin)
3102 goto fail;
3103 len = EC_POINT_point2oct(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED,
3104 pub_bin, len, NULL);
3105 if (len == 0)
3106 goto fail;
3107
3108 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
3109 (char *) group_name, 0);
3110 params[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY,
3111 priv_bin, priv_bin_len);
3112 params[2] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
3113 pub_bin, len);
3114 params[3] = OSSL_PARAM_construct_end();
3115
3116 ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
3117 if (!ctx ||
3118 EVP_PKEY_fromdata_init(ctx) <= 0 ||
3119 EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
3120 goto fail;
3121
3122out:
3123 bin_clear_free(priv_bin, raw_len);
3124 os_free(pub_bin);
3125 BN_clear_free(priv);
3126 EVP_PKEY_CTX_free(ctx);
3127 EC_POINT_free(pub);
3128 EC_GROUP_free(ec_group);
3129 return (struct crypto_ec_key *) pkey;
3130
3131fail:
3132 EVP_PKEY_free(pkey);
3133 pkey = NULL;
3134 goto out;
3135#else /* OpenSSL version >= 3.0 */
3136 EC_KEY *eckey = NULL;
3137 EVP_PKEY *pkey = NULL;
3138 BIGNUM *priv = NULL;
3139 int nid;
3140 const EC_GROUP *ec_group;
3141 EC_POINT *pub = NULL;
3142
3143 nid = crypto_ec_group_2_nid(group);
3144 if (nid < 0) {
3145 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3146 return NULL;
3147 }
3148
3149 eckey = EC_KEY_new_by_curve_name(nid);
3150 priv = BN_bin2bn(raw, raw_len, NULL);
3151 if (!eckey || !priv ||
3152 EC_KEY_set_private_key(eckey, priv) != 1) {
3153 wpa_printf(MSG_ERROR,
3154 "OpenSSL: Failed to set EC_KEY: %s",
3155 ERR_error_string(ERR_get_error(), NULL));
3156 goto fail;
3157 }
3158
3159 ec_group = EC_KEY_get0_group(eckey);
3160 if (!ec_group)
3161 goto fail;
3162 pub = EC_POINT_new(ec_group);
3163 if (!pub ||
3164 EC_POINT_mul(ec_group, pub, priv, NULL, NULL, NULL) != 1 ||
3165 EC_KEY_set_public_key(eckey, pub) != 1) {
3166 wpa_printf(MSG_ERROR,
3167 "OpenSSL: Failed to set EC_KEY(pub): %s",
3168 ERR_error_string(ERR_get_error(), NULL));
3169 goto fail;
3170 }
3171
3172 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3173
3174 pkey = EVP_PKEY_new();
3175 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3176 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3177 goto fail;
3178 }
3179
3180out:
3181 BN_clear_free(priv);
3182 EC_POINT_free(pub);
3183 return (struct crypto_ec_key *) pkey;
3184
3185fail:
3186 EC_KEY_free(eckey);
3187 EVP_PKEY_free(pkey);
3188 pkey = NULL;
3189 goto out;
3190#endif /* OpenSSL version >= 3.0 */
3191}
3192
3193
Hai Shalom899fcc72020-10-19 14:38:18 -07003194struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
3195{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003196 EVP_PKEY *pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003197
Hai Shaloma20dcd72022-02-04 13:43:00 -08003198 pkey = d2i_PUBKEY(NULL, &der, der_len);
3199 if (!pkey) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003200 wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s",
3201 ERR_error_string(ERR_get_error(), NULL));
3202 goto fail;
3203 }
3204
Hai Shaloma20dcd72022-02-04 13:43:00 -08003205 /* Ensure this is an EC key */
Sunil8cd6f4d2022-06-28 18:40:46 +00003206#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3207 if (!EVP_PKEY_is_a(pkey, "EC"))
3208 goto fail;
3209#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003210 if (!EVP_PKEY_get0_EC_KEY(pkey))
Hai Shalom899fcc72020-10-19 14:38:18 -07003211 goto fail;
Sunil8cd6f4d2022-06-28 18:40:46 +00003212#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003213 return (struct crypto_ec_key *) pkey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003214fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003215 crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003216 return NULL;
3217}
3218
3219
Hai Shaloma20dcd72022-02-04 13:43:00 -08003220struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x,
3221 const u8 *buf_y, size_t len)
3222{
Sunil8cd6f4d2022-06-28 18:40:46 +00003223#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3224 const char *group_name;
3225 OSSL_PARAM params[3];
3226 u8 *pub;
3227 EVP_PKEY_CTX *ctx;
3228 EVP_PKEY *pkey = NULL;
3229
3230 group_name = crypto_ec_group_2_name(group);
3231 if (!group_name)
3232 return NULL;
3233
3234 pub = os_malloc(1 + len * 2);
3235 if (!pub)
3236 return NULL;
3237 pub[0] = 0x04; /* uncompressed */
3238 os_memcpy(pub + 1, buf_x, len);
3239 os_memcpy(pub + 1 + len, buf_y, len);
3240
3241 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
3242 (char *) group_name, 0);
3243 params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
3244 pub, 1 + len * 2);
3245 params[2] = OSSL_PARAM_construct_end();
3246
3247 ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
3248 if (!ctx) {
3249 os_free(pub);
3250 return NULL;
3251 }
3252 if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
3253 EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
3254 os_free(pub);
3255 EVP_PKEY_CTX_free(ctx);
3256 return NULL;
3257 }
3258
3259 os_free(pub);
3260 EVP_PKEY_CTX_free(ctx);
3261
3262 return (struct crypto_ec_key *) pkey;
3263#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003264 EC_KEY *eckey = NULL;
3265 EVP_PKEY *pkey = NULL;
3266 EC_GROUP *ec_group = NULL;
3267 BN_CTX *ctx;
3268 EC_POINT *point = NULL;
3269 BIGNUM *x = NULL, *y = NULL;
3270 int nid;
3271
3272 if (!buf_x || !buf_y)
3273 return NULL;
3274
3275 nid = crypto_ec_group_2_nid(group);
3276 if (nid < 0) {
3277 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3278 return NULL;
3279 }
3280
3281 ctx = BN_CTX_new();
3282 if (!ctx)
3283 goto fail;
3284
3285 ec_group = EC_GROUP_new_by_curve_name(nid);
3286 if (!ec_group)
3287 goto fail;
3288
3289 x = BN_bin2bn(buf_x, len, NULL);
3290 y = BN_bin2bn(buf_y, len, NULL);
3291 point = EC_POINT_new(ec_group);
3292 if (!x || !y || !point)
3293 goto fail;
3294
Sunil Ravia04bd252022-05-02 22:54:18 -07003295 if (!EC_POINT_set_affine_coordinates(ec_group, point, x, y, ctx)) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003296 wpa_printf(MSG_ERROR,
Sunil Ravia04bd252022-05-02 22:54:18 -07003297 "OpenSSL: EC_POINT_set_affine_coordinates failed: %s",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003298 ERR_error_string(ERR_get_error(), NULL));
3299 goto fail;
3300 }
3301
3302 if (!EC_POINT_is_on_curve(ec_group, point, ctx) ||
3303 EC_POINT_is_at_infinity(ec_group, point)) {
3304 wpa_printf(MSG_ERROR, "OpenSSL: Invalid point");
3305 goto fail;
3306 }
3307
3308 eckey = EC_KEY_new();
3309 if (!eckey ||
3310 EC_KEY_set_group(eckey, ec_group) != 1 ||
3311 EC_KEY_set_public_key(eckey, point) != 1) {
3312 wpa_printf(MSG_ERROR,
3313 "OpenSSL: Failed to set EC_KEY: %s",
3314 ERR_error_string(ERR_get_error(), NULL));
3315 goto fail;
3316 }
3317 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3318
3319 pkey = EVP_PKEY_new();
3320 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3321 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3322 goto fail;
3323 }
3324
3325out:
3326 EC_GROUP_free(ec_group);
3327 BN_free(x);
3328 BN_free(y);
3329 EC_POINT_free(point);
3330 BN_CTX_free(ctx);
3331 return (struct crypto_ec_key *) pkey;
3332
3333fail:
3334 EC_KEY_free(eckey);
3335 EVP_PKEY_free(pkey);
3336 pkey = NULL;
3337 goto out;
Sunil8cd6f4d2022-06-28 18:40:46 +00003338#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003339}
3340
3341
3342struct crypto_ec_key *
3343crypto_ec_key_set_pub_point(struct crypto_ec *ec,
3344 const struct crypto_ec_point *pub)
3345{
Sunil8cd6f4d2022-06-28 18:40:46 +00003346#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3347 int len = BN_num_bytes(ec->prime);
3348 struct crypto_ec_key *key;
3349 u8 *buf;
3350
3351 buf = os_malloc(2 * len);
3352 if (!buf)
3353 return NULL;
3354 if (crypto_ec_point_to_bin(ec, pub, buf, buf + len) < 0) {
3355 os_free(buf);
3356 return NULL;
3357 }
3358
3359 key = crypto_ec_key_set_pub(ec->iana_group, buf, buf + len, len);
3360 os_free(buf);
3361
3362 return key;
3363#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003364 EC_KEY *eckey;
3365 EVP_PKEY *pkey = NULL;
3366
3367 eckey = EC_KEY_new();
3368 if (!eckey ||
3369 EC_KEY_set_group(eckey, ec->group) != 1 ||
3370 EC_KEY_set_public_key(eckey, (const EC_POINT *) pub) != 1) {
3371 wpa_printf(MSG_ERROR,
3372 "OpenSSL: Failed to set EC_KEY: %s",
3373 ERR_error_string(ERR_get_error(), NULL));
3374 goto fail;
3375 }
3376 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3377
3378 pkey = EVP_PKEY_new();
3379 if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
3380 wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
3381 goto fail;
3382 }
3383
3384out:
3385 return (struct crypto_ec_key *) pkey;
3386
3387fail:
3388 EVP_PKEY_free(pkey);
3389 EC_KEY_free(eckey);
3390 pkey = NULL;
3391 goto out;
Sunil8cd6f4d2022-06-28 18:40:46 +00003392#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003393}
3394
3395
3396struct crypto_ec_key * crypto_ec_key_gen(int group)
3397{
Sunil8cd6f4d2022-06-28 18:40:46 +00003398#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3399 EVP_PKEY_CTX *ctx;
3400 OSSL_PARAM params[2];
3401 const char *group_name;
3402 EVP_PKEY *pkey = NULL;
3403
3404 group_name = crypto_ec_group_2_name(group);
3405 if (!group_name)
3406 return NULL;
3407
3408 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
3409 (char *) group_name, 0);
3410 params[1] = OSSL_PARAM_construct_end();
3411
3412 ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
3413 if (!ctx ||
3414 EVP_PKEY_keygen_init(ctx) != 1 ||
3415 EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
3416 EVP_PKEY_generate(ctx, &pkey) != 1) {
3417 wpa_printf(MSG_INFO,
3418 "OpenSSL: failed to generate EC keypair: %s",
3419 ERR_error_string(ERR_get_error(), NULL));
3420 pkey = NULL;
3421 }
3422
3423 EVP_PKEY_CTX_free(ctx);
3424
3425 return (struct crypto_ec_key *) pkey;
3426#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003427 EVP_PKEY_CTX *kctx = NULL;
3428 EC_KEY *ec_params = NULL, *eckey;
3429 EVP_PKEY *params = NULL, *key = NULL;
3430 int nid;
3431
3432 nid = crypto_ec_group_2_nid(group);
3433 if (nid < 0) {
3434 wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
3435 return NULL;
3436 }
3437
3438 ec_params = EC_KEY_new_by_curve_name(nid);
3439 if (!ec_params) {
3440 wpa_printf(MSG_ERROR,
3441 "OpenSSL: Failed to generate EC_KEY parameters");
3442 goto fail;
3443 }
3444 EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
3445 params = EVP_PKEY_new();
3446 if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
3447 wpa_printf(MSG_ERROR,
3448 "OpenSSL: Failed to generate EVP_PKEY parameters");
3449 goto fail;
3450 }
3451
3452 kctx = EVP_PKEY_CTX_new(params, NULL);
3453 if (!kctx ||
3454 EVP_PKEY_keygen_init(kctx) != 1 ||
3455 EVP_PKEY_keygen(kctx, &key) != 1) {
3456 wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC key");
3457 key = NULL;
3458 goto fail;
3459 }
3460
3461 eckey = EVP_PKEY_get1_EC_KEY(key);
3462 if (!eckey) {
3463 key = NULL;
3464 goto fail;
3465 }
3466 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
3467 EC_KEY_free(eckey);
3468
3469fail:
3470 EC_KEY_free(ec_params);
3471 EVP_PKEY_free(params);
3472 EVP_PKEY_CTX_free(kctx);
3473 return (struct crypto_ec_key *) key;
Sunil8cd6f4d2022-06-28 18:40:46 +00003474#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003475}
3476
3477
Hai Shalom899fcc72020-10-19 14:38:18 -07003478void crypto_ec_key_deinit(struct crypto_ec_key *key)
3479{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003480 EVP_PKEY_free((EVP_PKEY *) key);
Hai Shalom899fcc72020-10-19 14:38:18 -07003481}
3482
3483
Hai Shaloma20dcd72022-02-04 13:43:00 -08003484#ifdef OPENSSL_IS_BORINGSSL
3485
3486/* BoringSSL version of i2d_PUBKEY() always outputs public EC key using
3487 * uncompressed form so define a custom function to export EC pubkey using
3488 * the compressed format that is explicitly required for some protocols. */
3489
3490#include <openssl/asn1.h>
3491#include <openssl/asn1t.h>
3492
3493typedef struct {
3494 /* AlgorithmIdentifier ecPublicKey with optional parameters present
3495 * as an OID identifying the curve */
3496 X509_ALGOR *alg;
3497 /* Compressed format public key per ANSI X9.63 */
3498 ASN1_BIT_STRING *pub_key;
3499} EC_COMP_PUBKEY;
3500
3501ASN1_SEQUENCE(EC_COMP_PUBKEY) = {
3502 ASN1_SIMPLE(EC_COMP_PUBKEY, alg, X509_ALGOR),
3503 ASN1_SIMPLE(EC_COMP_PUBKEY, pub_key, ASN1_BIT_STRING)
3504} ASN1_SEQUENCE_END(EC_COMP_PUBKEY);
3505
3506IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY);
3507
3508#endif /* OPENSSL_IS_BORINGSSL */
3509
3510
Hai Shalom899fcc72020-10-19 14:38:18 -07003511struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
3512{
Sunil8cd6f4d2022-06-28 18:40:46 +00003513 EVP_PKEY *pkey = (EVP_PKEY *) key;
3514#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3515 OSSL_ENCODER_CTX *ctx;
3516 int selection;
3517 unsigned char *pdata = NULL;
3518 size_t pdata_len = 0;
3519 EVP_PKEY *copy = NULL;
3520 struct wpabuf *buf = NULL;
3521
3522 if (EVP_PKEY_get_ec_point_conv_form(pkey) !=
3523 POINT_CONVERSION_COMPRESSED) {
3524 copy = EVP_PKEY_dup(pkey);
3525 if (!copy)
3526 return NULL;
3527 if (EVP_PKEY_set_utf8_string_param(
3528 copy, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
3529 OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED) !=
3530 1) {
3531 wpa_printf(MSG_INFO,
3532 "OpenSSL: Failed to set compressed format");
3533 EVP_PKEY_free(copy);
3534 return NULL;
3535 }
3536 pkey = copy;
3537 }
3538
3539 selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS |
3540 OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
3541
3542 ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER",
3543 "SubjectPublicKeyInfo",
3544 NULL);
3545 if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) {
3546 wpa_printf(MSG_INFO,
3547 "OpenSSL: Failed to encode SubjectPublicKeyInfo: %s",
3548 ERR_error_string(ERR_get_error(), NULL));
3549 pdata = NULL;
3550 }
3551 OSSL_ENCODER_CTX_free(ctx);
3552 if (pdata) {
3553 buf = wpabuf_alloc_copy(pdata, pdata_len);
3554 OPENSSL_free(pdata);
3555 }
3556
3557 EVP_PKEY_free(copy);
3558
3559 return buf;
3560#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003561#ifdef OPENSSL_IS_BORINGSSL
3562 unsigned char *der = NULL;
3563 int der_len;
3564 const EC_KEY *eckey;
3565 struct wpabuf *ret = NULL;
3566 size_t len;
3567 const EC_GROUP *group;
3568 const EC_POINT *point;
3569 BN_CTX *ctx;
3570 EC_COMP_PUBKEY *pubkey = NULL;
3571 int nid;
3572
3573 ctx = BN_CTX_new();
Sunil8cd6f4d2022-06-28 18:40:46 +00003574 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003575 if (!ctx || !eckey)
3576 goto fail;
3577
3578 group = EC_KEY_get0_group(eckey);
3579 point = EC_KEY_get0_public_key(eckey);
3580 if (!group || !point)
3581 goto fail;
3582 nid = EC_GROUP_get_curve_name(group);
3583
3584 pubkey = EC_COMP_PUBKEY_new();
3585 if (!pubkey ||
3586 X509_ALGOR_set0(pubkey->alg, OBJ_nid2obj(EVP_PKEY_EC),
3587 V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
3588 goto fail;
3589
3590 len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
3591 NULL, 0, ctx);
3592 if (len == 0)
3593 goto fail;
3594
3595 der = OPENSSL_malloc(len);
3596 if (!der)
3597 goto fail;
3598 len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
3599 der, len, ctx);
3600
3601 OPENSSL_free(pubkey->pub_key->data);
3602 pubkey->pub_key->data = der;
3603 der = NULL;
3604 pubkey->pub_key->length = len;
3605 /* No unused bits */
3606 pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
3607 pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
3608
3609 der_len = i2d_EC_COMP_PUBKEY(pubkey, &der);
3610 if (der_len <= 0) {
3611 wpa_printf(MSG_ERROR,
3612 "BoringSSL: Failed to build DER encoded public key");
3613 goto fail;
3614 }
3615
3616 ret = wpabuf_alloc_copy(der, der_len);
3617fail:
3618 EC_COMP_PUBKEY_free(pubkey);
3619 OPENSSL_free(der);
3620 BN_CTX_free(ctx);
3621 return ret;
3622#else /* OPENSSL_IS_BORINGSSL */
Hai Shalom899fcc72020-10-19 14:38:18 -07003623 unsigned char *der = NULL;
3624 int der_len;
3625 struct wpabuf *buf;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003626 EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07003627
Sunil8cd6f4d2022-06-28 18:40:46 +00003628 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003629 if (!eckey)
3630 return NULL;
3631
3632 /* For now, all users expect COMPRESSED form */
3633 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
3634
Hai Shaloma20dcd72022-02-04 13:43:00 -08003635 der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
3636 EC_KEY_free(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07003637 if (der_len <= 0) {
3638 wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
3639 ERR_error_string(ERR_get_error(), NULL));
3640 return NULL;
3641 }
3642
3643 buf = wpabuf_alloc_copy(der, der_len);
3644 OPENSSL_free(der);
3645 return buf;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003646#endif /* OPENSSL_IS_BORINGSSL */
Sunil8cd6f4d2022-06-28 18:40:46 +00003647#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003648}
3649
3650
3651struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
3652 bool include_pub)
3653{
Sunil8cd6f4d2022-06-28 18:40:46 +00003654 EVP_PKEY *pkey = (EVP_PKEY *) key;
3655#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3656 OSSL_ENCODER_CTX *ctx;
3657 int selection;
3658 unsigned char *pdata = NULL;
3659 size_t pdata_len = 0;
3660 struct wpabuf *buf;
3661 EVP_PKEY *copy = NULL;
3662
3663 selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS |
3664 OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
3665 if (include_pub) {
3666 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
3667 } else {
3668 /* Not including OSSL_KEYMGMT_SELECT_PUBLIC_KEY does not seem
3669 * to really be sufficient, so clone the key and explicitly
3670 * mark it not to include the public key. */
3671 copy = EVP_PKEY_dup(pkey);
3672 if (!copy)
3673 return NULL;
3674 EVP_PKEY_set_int_param(copy, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC,
3675 0);
3676 pkey = copy;
3677 }
3678
3679 ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER",
3680 "type-specific", NULL);
3681 if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) {
3682 OSSL_ENCODER_CTX_free(ctx);
3683 EVP_PKEY_free(copy);
3684 return NULL;
3685 }
3686 OSSL_ENCODER_CTX_free(ctx);
3687 buf = wpabuf_alloc_copy(pdata, pdata_len);
3688 OPENSSL_free(pdata);
3689 EVP_PKEY_free(copy);
3690 return buf;
3691#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003692 EC_KEY *eckey;
3693 unsigned char *der = NULL;
3694 int der_len;
3695 struct wpabuf *buf;
3696 unsigned int key_flags;
3697
Sunil8cd6f4d2022-06-28 18:40:46 +00003698 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003699 if (!eckey)
3700 return NULL;
3701
3702 key_flags = EC_KEY_get_enc_flags(eckey);
3703 if (include_pub)
3704 key_flags &= ~EC_PKEY_NO_PUBKEY;
3705 else
3706 key_flags |= EC_PKEY_NO_PUBKEY;
3707 EC_KEY_set_enc_flags(eckey, key_flags);
3708
3709 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
3710
3711 der_len = i2d_ECPrivateKey(eckey, &der);
3712 EC_KEY_free(eckey);
3713 if (der_len <= 0)
3714 return NULL;
3715 buf = wpabuf_alloc_copy(der, der_len);
3716 OPENSSL_free(der);
3717
3718 return buf;
Sunil8cd6f4d2022-06-28 18:40:46 +00003719#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003720}
3721
3722
3723struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
3724 int prefix)
3725{
Sunil8cd6f4d2022-06-28 18:40:46 +00003726 EVP_PKEY *pkey = (EVP_PKEY *) key;
3727#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3728 struct wpabuf *buf;
3729 unsigned char *pos;
3730 size_t pub_len = OSSL_PARAM_UNMODIFIED;
3731
3732 buf = NULL;
3733 if (!EVP_PKEY_is_a(pkey, "EC") ||
3734 EVP_PKEY_get_octet_string_param(pkey,
3735 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
3736 NULL, 0, &pub_len) < 0 ||
3737 pub_len == OSSL_PARAM_UNMODIFIED ||
3738 !(buf = wpabuf_alloc(pub_len)) ||
3739 EVP_PKEY_get_octet_string_param(pkey,
3740 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
3741 wpabuf_put(buf, pub_len),
3742 pub_len, NULL) != 1 ||
3743 wpabuf_head_u8(buf)[0] != 0x04) {
3744 wpa_printf(MSG_INFO,
3745 "OpenSSL: Failed to get encoded public key: %s",
3746 ERR_error_string(ERR_get_error(), NULL));
3747 wpabuf_free(buf);
3748 return NULL;
3749 }
3750
3751 if (!prefix) {
3752 /* Remove 0x04 prefix if requested */
3753 pos = wpabuf_mhead(buf);
3754 os_memmove(pos, pos + 1, pub_len - 1);
3755 buf->used--;
3756 }
3757
3758 return buf;
3759#else /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003760 int len, res;
3761 EC_KEY *eckey;
3762 struct wpabuf *buf;
3763 unsigned char *pos;
3764
Sunil8cd6f4d2022-06-28 18:40:46 +00003765 eckey = EVP_PKEY_get1_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003766 if (!eckey)
3767 return NULL;
3768 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
3769 len = i2o_ECPublicKey(eckey, NULL);
3770 if (len <= 0) {
3771 wpa_printf(MSG_ERROR,
3772 "OpenSSL: Failed to determine public key encoding length");
3773 EC_KEY_free(eckey);
3774 return NULL;
3775 }
3776
3777 buf = wpabuf_alloc(len);
3778 if (!buf) {
3779 EC_KEY_free(eckey);
3780 return NULL;
3781 }
3782
3783 pos = wpabuf_put(buf, len);
3784 res = i2o_ECPublicKey(eckey, &pos);
3785 EC_KEY_free(eckey);
3786 if (res != len) {
3787 wpa_printf(MSG_ERROR,
3788 "OpenSSL: Failed to encode public key (res=%d/%d)",
3789 res, len);
3790 wpabuf_free(buf);
3791 return NULL;
3792 }
3793
3794 if (!prefix) {
3795 /* Remove 0x04 prefix if requested */
3796 pos = wpabuf_mhead(buf);
3797 os_memmove(pos, pos + 1, len - 1);
3798 buf->used--;
3799 }
3800
3801 return buf;
Sunil8cd6f4d2022-06-28 18:40:46 +00003802#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003803}
3804
3805
Sunil8cd6f4d2022-06-28 18:40:46 +00003806struct crypto_ec_point *
Hai Shaloma20dcd72022-02-04 13:43:00 -08003807crypto_ec_key_get_public_key(struct crypto_ec_key *key)
3808{
Sunil8cd6f4d2022-06-28 18:40:46 +00003809 EVP_PKEY *pkey = (EVP_PKEY *) key;
3810#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3811 char group[64];
3812 unsigned char pub[256];
3813 size_t len;
3814 EC_POINT *point = NULL;
3815 EC_GROUP *grp;
3816 int res = 0;
3817 OSSL_PARAM params[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003818
Sunil8cd6f4d2022-06-28 18:40:46 +00003819 if (!EVP_PKEY_is_a(pkey, "EC") ||
3820 EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
3821 group, sizeof(group), &len) != 1 ||
3822 EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
3823 pub, sizeof(pub), &len) != 1)
3824 return NULL;
3825
3826 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
3827 group, 0);
3828 params[1] = OSSL_PARAM_construct_end();
3829 grp = EC_GROUP_new_from_params(params, NULL, NULL);
3830 if (!grp)
3831 goto fail;
3832 point = EC_POINT_new(grp);
3833 if (!point)
3834 goto fail;
3835 res = EC_POINT_oct2point(grp, point, pub, len, NULL);
3836
3837fail:
3838 if (res != 1) {
3839 EC_POINT_free(point);
3840 point = NULL;
3841 }
3842
3843 EC_GROUP_free(grp);
3844
3845 return (struct crypto_ec_point *) point;
3846#else /* OpenSSL version >= 3.0 */
3847 const EC_KEY *eckey;
3848 const EC_POINT *point;
3849 const EC_GROUP *group;
3850
3851 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003852 if (!eckey)
3853 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003854 group = EC_KEY_get0_group(eckey);
3855 if (!group)
3856 return NULL;
3857 point = EC_KEY_get0_public_key(eckey);
3858 if (!point)
3859 return NULL;
3860 return (struct crypto_ec_point *) EC_POINT_dup(point, group);
3861#endif /* OpenSSL version >= 3.0 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003862}
3863
3864
Sunil8cd6f4d2022-06-28 18:40:46 +00003865struct crypto_bignum *
Hai Shaloma20dcd72022-02-04 13:43:00 -08003866crypto_ec_key_get_private_key(struct crypto_ec_key *key)
3867{
Sunil8cd6f4d2022-06-28 18:40:46 +00003868 EVP_PKEY *pkey = (EVP_PKEY *) key;
3869#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3870 BIGNUM *bn = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003871
Sunil8cd6f4d2022-06-28 18:40:46 +00003872 if (!EVP_PKEY_is_a(pkey, "EC") ||
3873 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &bn) != 1)
3874 return NULL;
3875 return (struct crypto_bignum *) bn;
3876#else /* OpenSSL version >= 3.0 */
3877 const EC_KEY *eckey;
3878 const BIGNUM *bn;
3879
3880 eckey = EVP_PKEY_get0_EC_KEY(pkey);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003881 if (!eckey)
3882 return NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00003883 bn = EC_KEY_get0_private_key(eckey);
3884 if (!bn)
3885 return NULL;
3886 return (struct crypto_bignum *) BN_dup(bn);
3887#endif /* OpenSSL version >= 3.0 */
Hai Shalom899fcc72020-10-19 14:38:18 -07003888}
3889
3890
3891struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
3892 size_t len)
3893{
3894 EVP_PKEY_CTX *pkctx;
3895 struct wpabuf *sig_der;
3896 size_t sig_len;
3897
Hai Shaloma20dcd72022-02-04 13:43:00 -08003898 sig_len = EVP_PKEY_size((EVP_PKEY *) key);
Hai Shalom899fcc72020-10-19 14:38:18 -07003899 sig_der = wpabuf_alloc(sig_len);
3900 if (!sig_der)
3901 return NULL;
3902
Hai Shaloma20dcd72022-02-04 13:43:00 -08003903 pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07003904 if (!pkctx ||
3905 EVP_PKEY_sign_init(pkctx) <= 0 ||
3906 EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len,
3907 data, len) <= 0) {
3908 wpabuf_free(sig_der);
3909 sig_der = NULL;
3910 } else {
3911 wpabuf_put(sig_der, sig_len);
3912 }
3913
3914 EVP_PKEY_CTX_free(pkctx);
3915 return sig_der;
3916}
3917
3918
Sunil Ravia04bd252022-05-02 22:54:18 -07003919static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key)
Hai Shaloma20dcd72022-02-04 13:43:00 -08003920{
Sunil Ravia04bd252022-05-02 22:54:18 -07003921#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3922 char gname[50];
3923 int nid;
3924 EC_GROUP *group;
3925 BIGNUM *prime = NULL;
3926 int prime_len = -1;
3927
3928 if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname),
3929 NULL) != 1)
3930 return -1;
3931 nid = OBJ_txt2nid(gname);
3932 group = EC_GROUP_new_by_curve_name(nid);
3933 prime = BN_new();
3934 if (!group || !prime)
Sunil Ravi88611412024-06-28 17:34:56 +00003935 return -1;
Sunil Ravia04bd252022-05-02 22:54:18 -07003936 if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1)
3937 prime_len = BN_num_bytes(prime);
3938 EC_GROUP_free(group);
3939 BN_free(prime);
3940 return prime_len;
3941#else
Hai Shaloma20dcd72022-02-04 13:43:00 -08003942 const EC_GROUP *group;
3943 const EC_KEY *eckey;
3944 BIGNUM *prime = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07003945 int prime_len = -1;
3946
3947 eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
3948 if (!eckey)
3949 goto fail;
3950 group = EC_KEY_get0_group(eckey);
3951 prime = BN_new();
3952 if (!prime || !group ||
3953 !EC_GROUP_get_curve(group, prime, NULL, NULL, NULL))
3954 goto fail;
3955 prime_len = BN_num_bytes(prime);
3956fail:
3957 BN_free(prime);
3958 return prime_len;
3959#endif
3960}
3961
3962
3963struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
3964 const u8 *data, size_t len)
3965{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003966 ECDSA_SIG *sig = NULL;
3967 const BIGNUM *r, *s;
3968 u8 *r_buf, *s_buf;
3969 struct wpabuf *buf;
3970 const unsigned char *p;
3971 int prime_len;
3972
Sunil Ravia04bd252022-05-02 22:54:18 -07003973 prime_len = openssl_evp_pkey_ec_prime_len(key);
3974 if (prime_len < 0)
3975 return NULL;
3976
Hai Shaloma20dcd72022-02-04 13:43:00 -08003977 buf = crypto_ec_key_sign(key, data, len);
3978 if (!buf)
3979 return NULL;
3980
3981 /* Extract (r,s) from Ecdsa-Sig-Value */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003982
3983 p = wpabuf_head(buf);
3984 sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf));
3985 if (!sig)
3986 goto fail;
3987 ECDSA_SIG_get0(sig, &r, &s);
3988
3989 /* Re-use wpabuf returned by crypto_ec_key_sign() */
3990 buf->used = 0;
3991 r_buf = wpabuf_put(buf, prime_len);
3992 s_buf = wpabuf_put(buf, prime_len);
3993 if (crypto_bignum_to_bin((const struct crypto_bignum *) r, r_buf,
3994 prime_len, prime_len) < 0 ||
3995 crypto_bignum_to_bin((const struct crypto_bignum *) s, s_buf,
3996 prime_len, prime_len) < 0)
3997 goto fail;
3998
3999out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004000 ECDSA_SIG_free(sig);
4001 return buf;
4002fail:
4003 wpabuf_clear_free(buf);
4004 buf = NULL;
4005 goto out;
4006}
4007
4008
Hai Shalom899fcc72020-10-19 14:38:18 -07004009int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
4010 size_t len, const u8 *sig, size_t sig_len)
4011{
4012 EVP_PKEY_CTX *pkctx;
4013 int ret;
4014
Hai Shaloma20dcd72022-02-04 13:43:00 -08004015 pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004016 if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) {
4017 EVP_PKEY_CTX_free(pkctx);
4018 return -1;
4019 }
4020
4021 ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len);
4022 EVP_PKEY_CTX_free(pkctx);
4023 if (ret == 1)
4024 return 1; /* signature ok */
4025 if (ret == 0)
4026 return 0; /* incorrect signature */
4027 return -1;
4028}
4029
4030
Hai Shaloma20dcd72022-02-04 13:43:00 -08004031int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
4032 const u8 *data, size_t len,
4033 const u8 *r, size_t r_len,
4034 const u8 *s, size_t s_len)
4035{
4036 ECDSA_SIG *sig;
4037 BIGNUM *r_bn, *s_bn;
4038 unsigned char *der = NULL;
4039 int der_len;
4040 int ret = -1;
4041
4042 r_bn = BN_bin2bn(r, r_len, NULL);
4043 s_bn = BN_bin2bn(s, s_len, NULL);
4044 sig = ECDSA_SIG_new();
4045 if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1)
4046 goto fail;
4047 r_bn = NULL;
4048 s_bn = NULL;
4049
4050 der_len = i2d_ECDSA_SIG(sig, &der);
4051 if (der_len <= 0) {
4052 wpa_printf(MSG_DEBUG,
4053 "OpenSSL: Could not DER encode signature");
4054 goto fail;
4055 }
4056
4057 ret = crypto_ec_key_verify_signature(key, data, len, der, der_len);
4058
4059fail:
4060 OPENSSL_free(der);
4061 BN_free(r_bn);
4062 BN_free(s_bn);
4063 ECDSA_SIG_free(sig);
4064 return ret;
4065}
4066
4067
Hai Shalom899fcc72020-10-19 14:38:18 -07004068int crypto_ec_key_group(struct crypto_ec_key *key)
4069{
Sunil Ravia04bd252022-05-02 22:54:18 -07004070#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4071 char gname[50];
4072 int nid;
4073
4074 if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname),
4075 NULL) != 1)
4076 return -1;
4077 nid = OBJ_txt2nid(gname);
4078#else
Hai Shaloma20dcd72022-02-04 13:43:00 -08004079 const EC_KEY *eckey;
Hai Shalom899fcc72020-10-19 14:38:18 -07004080 const EC_GROUP *group;
4081 int nid;
4082
Hai Shaloma20dcd72022-02-04 13:43:00 -08004083 eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
4084 if (!eckey)
4085 return -1;
4086 group = EC_KEY_get0_group(eckey);
Hai Shalom899fcc72020-10-19 14:38:18 -07004087 if (!group)
4088 return -1;
4089 nid = EC_GROUP_get_curve_name(group);
Sunil Ravia04bd252022-05-02 22:54:18 -07004090#endif
Hai Shalom899fcc72020-10-19 14:38:18 -07004091 switch (nid) {
4092 case NID_X9_62_prime256v1:
4093 return 19;
4094 case NID_secp384r1:
4095 return 20;
4096 case NID_secp521r1:
4097 return 21;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004098#ifdef NID_brainpoolP256r1
4099 case NID_brainpoolP256r1:
4100 return 28;
4101#endif /* NID_brainpoolP256r1 */
4102#ifdef NID_brainpoolP384r1
4103 case NID_brainpoolP384r1:
4104 return 29;
4105#endif /* NID_brainpoolP384r1 */
4106#ifdef NID_brainpoolP512r1
4107 case NID_brainpoolP512r1:
4108 return 30;
4109#endif /* NID_brainpoolP512r1 */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004110 default:
4111 wpa_printf(MSG_ERROR,
4112 "OpenSSL: Unsupported curve (nid=%d) in EC key",
4113 nid);
4114 return -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07004115 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004116}
4117
Hai Shaloma20dcd72022-02-04 13:43:00 -08004118
4119int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
4120{
Sunil Ravia04bd252022-05-02 22:54:18 -07004121#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4122 if (EVP_PKEY_eq((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1)
4123 return -1;
4124#else
Hai Shaloma20dcd72022-02-04 13:43:00 -08004125 if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1)
4126 return -1;
Sunil Ravia04bd252022-05-02 22:54:18 -07004127#endif
Hai Shaloma20dcd72022-02-04 13:43:00 -08004128 return 0;
4129}
4130
4131
4132void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
4133 const char *title)
4134{
4135 BIO *out;
4136 size_t rlen;
4137 char *txt;
4138 int res;
4139
4140 out = BIO_new(BIO_s_mem());
4141 if (!out)
4142 return;
4143
4144 EVP_PKEY_print_private(out, (EVP_PKEY *) key, 0, NULL);
4145 rlen = BIO_ctrl_pending(out);
4146 txt = os_malloc(rlen + 1);
4147 if (txt) {
4148 res = BIO_read(out, txt, rlen);
4149 if (res > 0) {
4150 txt[res] = '\0';
4151 wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
4152 }
4153 os_free(txt);
4154 }
4155 BIO_free(out);
4156}
4157
4158
4159struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
4160{
4161#ifdef OPENSSL_IS_BORINGSSL
4162 CBS pkcs7_cbs;
4163#else /* OPENSSL_IS_BORINGSSL */
4164 PKCS7 *p7 = NULL;
4165 const unsigned char *p = wpabuf_head(pkcs7);
4166#endif /* OPENSSL_IS_BORINGSSL */
4167 STACK_OF(X509) *certs;
4168 int i, num;
4169 BIO *out = NULL;
4170 size_t rlen;
4171 struct wpabuf *pem = NULL;
4172 int res;
4173
4174#ifdef OPENSSL_IS_BORINGSSL
4175 certs = sk_X509_new_null();
4176 if (!certs)
4177 goto fail;
4178 CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7));
4179 if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
4180 wpa_printf(MSG_INFO,
4181 "OpenSSL: Could not parse PKCS#7 object: %s",
4182 ERR_error_string(ERR_get_error(), NULL));
4183 goto fail;
4184 }
4185#else /* OPENSSL_IS_BORINGSSL */
4186 p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
4187 if (!p7) {
4188 wpa_printf(MSG_INFO,
4189 "OpenSSL: Could not parse PKCS#7 object: %s",
4190 ERR_error_string(ERR_get_error(), NULL));
4191 goto fail;
4192 }
4193
4194 switch (OBJ_obj2nid(p7->type)) {
4195 case NID_pkcs7_signed:
4196 certs = p7->d.sign->cert;
4197 break;
4198 case NID_pkcs7_signedAndEnveloped:
4199 certs = p7->d.signed_and_enveloped->cert;
4200 break;
4201 default:
4202 certs = NULL;
4203 break;
4204 }
4205#endif /* OPENSSL_IS_BORINGSSL */
4206
4207 if (!certs || ((num = sk_X509_num(certs)) == 0)) {
4208 wpa_printf(MSG_INFO,
4209 "OpenSSL: No certificates found in PKCS#7 object");
4210 goto fail;
4211 }
4212
4213 out = BIO_new(BIO_s_mem());
4214 if (!out)
4215 goto fail;
4216
4217 for (i = 0; i < num; i++) {
4218 X509 *cert = sk_X509_value(certs, i);
4219
4220 PEM_write_bio_X509(out, cert);
4221 }
4222
4223 rlen = BIO_ctrl_pending(out);
4224 pem = wpabuf_alloc(rlen);
4225 if (!pem)
4226 goto fail;
4227 res = BIO_read(out, wpabuf_put(pem, 0), rlen);
4228 if (res <= 0) {
4229 wpabuf_free(pem);
4230 pem = NULL;
4231 goto fail;
4232 }
4233 wpabuf_put(pem, res);
4234
4235fail:
4236#ifdef OPENSSL_IS_BORINGSSL
4237 if (certs)
4238 sk_X509_pop_free(certs, X509_free);
4239#else /* OPENSSL_IS_BORINGSSL */
4240 PKCS7_free(p7);
4241#endif /* OPENSSL_IS_BORINGSSL */
4242 if (out)
4243 BIO_free_all(out);
4244
4245 return pem;
4246}
4247
4248
4249struct crypto_csr * crypto_csr_init()
4250{
4251 return (struct crypto_csr *)X509_REQ_new();
4252}
4253
4254
4255struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
4256{
4257 X509_REQ *csr;
4258 EVP_PKEY *pkey = NULL;
4259 const u8 *der = wpabuf_head(req);
4260
4261 csr = d2i_X509_REQ(NULL, &der, wpabuf_len(req));
4262 if (!csr)
4263 return NULL;
4264
4265 pkey = X509_REQ_get_pubkey((X509_REQ *)csr);
4266 if (!pkey)
4267 goto fail;
4268
4269 if (X509_REQ_verify((X509_REQ *)csr, pkey) != 1)
4270 goto fail;
4271
4272 return (struct crypto_csr *)csr;
4273fail:
4274 X509_REQ_free(csr);
4275 return NULL;
4276}
4277
4278
4279void crypto_csr_deinit(struct crypto_csr *csr)
4280{
4281 X509_REQ_free((X509_REQ *)csr);
4282}
4283
4284
4285int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key)
4286{
4287 if (!X509_REQ_set_pubkey((X509_REQ *)csr, (EVP_PKEY *)key))
4288 return -1;
4289
4290 return 0;
4291}
4292
4293
4294int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
4295 const char *name)
4296{
4297 X509_NAME *n;
4298 int nid;
4299
4300 switch (type) {
4301 case CSR_NAME_CN:
4302 nid = NID_commonName;
4303 break;
4304 case CSR_NAME_SN:
4305 nid = NID_surname;
4306 break;
4307 case CSR_NAME_C:
4308 nid = NID_countryName;
4309 break;
4310 case CSR_NAME_O:
4311 nid = NID_organizationName;
4312 break;
4313 case CSR_NAME_OU:
4314 nid = NID_organizationalUnitName;
4315 break;
4316 default:
4317 return -1;
4318 }
4319
4320 n = X509_REQ_get_subject_name((X509_REQ *) csr);
4321 if (!n)
4322 return -1;
4323
4324#if OPENSSL_VERSION_NUMBER < 0x10100000L
4325 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8,
4326 (unsigned char *) name,
4327 os_strlen(name), -1, 0))
4328 return -1;
4329#else
4330 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8,
4331 (const unsigned char *) name,
4332 os_strlen(name), -1, 0))
4333 return -1;
4334#endif
4335
4336 return 0;
4337}
4338
4339
4340int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
4341 int attr_type, const u8 *value, size_t len)
4342{
4343 int nid;
4344
4345 switch (attr) {
4346 case CSR_ATTR_CHALLENGE_PASSWORD:
4347 nid = NID_pkcs9_challengePassword;
4348 break;
4349 default:
4350 return -1;
4351 }
4352
4353 if (!X509_REQ_add1_attr_by_NID((X509_REQ *) csr, nid, attr_type, value,
4354 len))
4355 return -1;
4356
4357 return 0;
4358}
4359
4360
4361const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
4362 enum crypto_csr_attr attr,
4363 size_t *len, int *type)
4364{
4365 X509_ATTRIBUTE *attrib;
4366 ASN1_TYPE *attrib_type;
4367 ASN1_STRING *data;
4368 int loc;
4369 int nid;
4370
4371 switch (attr) {
4372 case CSR_ATTR_CHALLENGE_PASSWORD:
4373 nid = NID_pkcs9_challengePassword;
4374 break;
4375 default:
4376 return NULL;
4377 }
4378
4379 loc = X509_REQ_get_attr_by_NID((X509_REQ *) csr, nid, -1);
4380 if (loc < 0)
4381 return NULL;
4382
4383 attrib = X509_REQ_get_attr((X509_REQ *) csr, loc);
4384 if (!attrib)
4385 return NULL;
4386
4387 attrib_type = X509_ATTRIBUTE_get0_type(attrib, 0);
4388 if (!attrib_type)
4389 return NULL;
4390 *type = ASN1_TYPE_get(attrib_type);
4391 data = X509_ATTRIBUTE_get0_data(attrib, 0, *type, NULL);
4392 if (!data)
4393 return NULL;
4394 *len = ASN1_STRING_length(data);
4395 return ASN1_STRING_get0_data(data);
4396}
4397
4398
4399struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
4400 struct crypto_ec_key *key,
4401 enum crypto_hash_alg algo)
4402{
4403 const EVP_MD *sign_md;
4404 struct wpabuf *buf;
4405 unsigned char *der = NULL;
4406 int der_len;
4407
4408 switch (algo) {
4409 case CRYPTO_HASH_ALG_SHA256:
4410 sign_md = EVP_sha256();
4411 break;
4412 case CRYPTO_HASH_ALG_SHA384:
4413 sign_md = EVP_sha384();
4414 break;
4415 case CRYPTO_HASH_ALG_SHA512:
4416 sign_md = EVP_sha512();
4417 break;
4418 default:
4419 return NULL;
4420 }
4421
4422 if (!X509_REQ_sign((X509_REQ *) csr, (EVP_PKEY *) key, sign_md))
4423 return NULL;
4424
4425 der_len = i2d_X509_REQ((X509_REQ *) csr, &der);
4426 if (der_len < 0)
4427 return NULL;
4428
4429 buf = wpabuf_alloc_copy(der, der_len);
4430 OPENSSL_free(der);
4431
4432 return buf;
4433}
4434
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004435#endif /* CONFIG_ECC */
Sunil Ravia04bd252022-05-02 22:54:18 -07004436
4437
4438static EVP_PKEY * crypto_rsa_key_read_public(FILE *f)
4439{
4440 EVP_PKEY *pkey;
4441 X509 *x509;
Sunil8cd6f4d2022-06-28 18:40:46 +00004442 const ASN1_TIME *not_before, *not_after;
4443 int res_before, res_after;
Sunil Ravia04bd252022-05-02 22:54:18 -07004444
4445 pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
4446 if (pkey)
4447 return pkey;
4448
4449 rewind(f);
4450 x509 = PEM_read_X509(f, NULL, NULL, NULL);
4451 if (!x509)
4452 return NULL;
4453
Sunil8cd6f4d2022-06-28 18:40:46 +00004454 not_before = X509_get0_notBefore(x509);
4455 not_after = X509_get0_notAfter(x509);
4456 if (!not_before || !not_after)
4457 goto fail;
4458 res_before = X509_cmp_current_time(not_before);
4459 res_after = X509_cmp_current_time(not_after);
4460 if (!res_before || !res_after)
4461 goto fail;
4462 if (res_before > 0 || res_after < 0) {
4463 wpa_printf(MSG_INFO,
4464 "OpenSSL: Certificate for RSA public key is not valid at this time (%d %d)",
4465 res_before, res_after);
4466 goto fail;
4467 }
4468
Sunil Ravia04bd252022-05-02 22:54:18 -07004469 pkey = X509_get_pubkey(x509);
4470 X509_free(x509);
4471
4472 if (!pkey)
4473 return NULL;
4474 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
Sunil8cd6f4d2022-06-28 18:40:46 +00004475 wpa_printf(MSG_INFO, "OpenSSL: No RSA public key found");
Sunil Ravia04bd252022-05-02 22:54:18 -07004476 EVP_PKEY_free(pkey);
4477 return NULL;
4478 }
4479
4480 return pkey;
Sunil8cd6f4d2022-06-28 18:40:46 +00004481fail:
4482 X509_free(x509);
4483 return NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004484}
4485
4486
4487struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key)
4488{
4489 FILE *f;
4490 EVP_PKEY *pkey;
4491
4492 f = fopen(file, "r");
4493 if (!f)
4494 return NULL;
4495 if (private_key)
4496 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
4497 else
4498 pkey = crypto_rsa_key_read_public(f);
4499 fclose(f);
4500 return (struct crypto_rsa_key *) pkey;
4501}
4502
4503
4504#ifndef OPENSSL_NO_SHA256
4505
4506struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key,
4507 const struct wpabuf *in)
4508{
4509#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L
4510 EVP_PKEY *pkey = (EVP_PKEY *) key;
4511 EVP_PKEY_CTX *pkctx;
4512 struct wpabuf *res = NULL;
4513 size_t outlen;
4514
4515 pkctx = EVP_PKEY_CTX_new(pkey, NULL);
4516 if (!pkctx)
4517 goto fail;
4518
4519 if (EVP_PKEY_encrypt_init(pkctx) != 1 ||
4520 EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
4521 EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 ||
4522 EVP_PKEY_encrypt(pkctx, NULL, &outlen, wpabuf_head(in),
4523 wpabuf_len(in)) != 1 ||
4524 !(res = wpabuf_alloc(outlen)) ||
4525 EVP_PKEY_encrypt(pkctx, wpabuf_put(res, 0), &outlen,
4526 wpabuf_head(in), wpabuf_len(in)) != 1) {
4527 wpabuf_free(res);
4528 res = NULL;
4529 goto fail;
4530 }
4531 wpabuf_put(res, outlen);
4532
4533fail:
4534 EVP_PKEY_CTX_free(pkctx);
4535 return res;
4536#else
4537 wpa_printf(MSG_ERROR, "%s() not supported", __func__);
4538 return NULL;
4539#endif
4540}
4541
4542
4543struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key,
4544 const struct wpabuf *in)
4545{
4546#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x30400000L
4547 EVP_PKEY *pkey = (EVP_PKEY *) key;
4548 EVP_PKEY_CTX *pkctx;
4549 struct wpabuf *res = NULL;
4550 size_t outlen;
4551
4552 pkctx = EVP_PKEY_CTX_new(pkey, NULL);
4553 if (!pkctx)
4554 goto fail;
4555
4556 if (EVP_PKEY_decrypt_init(pkctx) != 1 ||
4557 EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
4558 EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 ||
4559 EVP_PKEY_decrypt(pkctx, NULL, &outlen, wpabuf_head(in),
4560 wpabuf_len(in)) != 1 ||
4561 !(res = wpabuf_alloc(outlen)) ||
4562 EVP_PKEY_decrypt(pkctx, wpabuf_put(res, 0), &outlen,
4563 wpabuf_head(in), wpabuf_len(in)) != 1) {
4564 wpabuf_free(res);
4565 res = NULL;
4566 goto fail;
4567 }
4568 wpabuf_put(res, outlen);
4569
4570fail:
4571 EVP_PKEY_CTX_free(pkctx);
4572 return res;
4573#else
4574 wpa_printf(MSG_ERROR, "%s() not supported", __func__);
4575 return NULL;
4576#endif
4577}
4578
4579#endif /* OPENSSL_NO_SHA256 */
4580
4581
4582void crypto_rsa_key_free(struct crypto_rsa_key *key)
4583{
4584 EVP_PKEY_free((EVP_PKEY *) key);
4585}
4586
4587
Sunil Ravi89eba102022-09-13 21:04:37 -07004588#ifdef CONFIG_DPP3
4589
4590#define HPKE_MAX_SHARED_SECRET_LEN 66
4591#define HPKE_MAX_HASH_LEN 64
4592#define HPKE_MAX_KEY_LEN 32
4593#define HPKE_MAX_NONCE_LEN 12
4594#define HPKE_MAX_PUB_LEN (1 + 2 * 66)
4595
4596struct hpke_context {
4597 /* KEM */
4598 enum hpke_kem_id kem_id;
4599 int kem_nid;
4600 int iana_group;
4601 size_t n_pk;
4602 size_t n_secret;
4603 const EVP_MD *kem_h;
4604 size_t kem_n_h;
4605
4606 /* KDF */
4607 enum hpke_kdf_id kdf_id;
4608 const EVP_MD *kdf_h;
4609 size_t n_h;
4610
4611 /* AEAD */
4612 enum hpke_aead_id aead_id;
4613 const EVP_CIPHER *cipher;
4614 size_t n_k;
4615 size_t n_n;
4616 size_t n_t;
4617 u8 key[HPKE_MAX_KEY_LEN];
4618 u8 base_nonce[HPKE_MAX_NONCE_LEN];
4619};
4620
4621
4622static void hpke_free_context(struct hpke_context *ctx)
4623{
4624 bin_clear_free(ctx, sizeof(*ctx));
4625}
4626
4627
4628static struct hpke_context * hpke_get_context(enum hpke_kem_id kem_id,
4629 enum hpke_kdf_id kdf_id,
4630 enum hpke_aead_id aead_id,
4631 struct crypto_ec_key *key)
4632{
4633 struct hpke_context *ctx;
4634 int group;
4635
4636 ctx = os_zalloc(sizeof(*ctx));
4637 if (!ctx)
4638 return NULL;
4639
4640 ctx->kem_id = kem_id;
4641 switch (kem_id) {
4642 case HPKE_DHKEM_P256_HKDF_SHA256:
4643 ctx->kem_nid = NID_X9_62_prime256v1;
4644 ctx->iana_group = 19;
4645 ctx->n_pk = 65;
4646 ctx->n_secret = 32;
4647 ctx->kem_h = EVP_sha256();
4648 ctx->kem_n_h = 32;
4649 break;
4650 case HPKE_DHKEM_P384_HKDF_SHA384:
4651 ctx->kem_nid = NID_secp384r1;
4652 ctx->iana_group = 20;
4653 ctx->n_pk = 97;
4654 ctx->n_secret = 48;
4655 ctx->kem_h = EVP_sha384();
4656 ctx->kem_n_h = 48;
4657 break;
4658 case HPKE_DHKEM_P521_HKDF_SHA512:
4659 ctx->kem_nid = NID_secp521r1;
4660 ctx->iana_group = 21;
4661 ctx->n_pk = 133;
4662 ctx->n_secret = 64;
4663 ctx->kem_h = EVP_sha512();
4664 ctx->kem_n_h = 64;
4665 break;
4666 default:
4667 goto fail;
4668 }
4669
4670 ctx->kdf_id = kdf_id;
4671 switch (kdf_id) {
4672 case HPKE_KDF_HKDF_SHA256:
4673 ctx->kdf_h = EVP_sha256();
4674 ctx->n_h = 32;
4675 break;
4676 case HPKE_KDF_HKDF_SHA384:
4677 ctx->kdf_h = EVP_sha384();
4678 ctx->n_h = 48;
4679 break;
4680 case HPKE_KDF_HKDF_SHA512:
4681 ctx->kdf_h = EVP_sha512();
4682 ctx->n_h = 64;
4683 break;
4684 default:
4685 goto fail;
4686 }
4687
4688 ctx->aead_id = aead_id;
4689 switch (aead_id) {
4690 case HPKE_AEAD_AES_128_GCM:
4691 ctx->cipher = EVP_aes_128_gcm();
4692 ctx->n_k = 16;
4693 ctx->n_n = 12;
4694 ctx->n_t = 16;
4695 break;
4696 case HPKE_AEAD_AES_256_GCM:
4697 ctx->cipher = EVP_aes_256_gcm();
4698 ctx->n_k = 32;
4699 ctx->n_n = 12;
4700 ctx->n_t = 16;
4701 break;
4702 default:
4703 goto fail;
4704 }
4705
4706 /* Convert BP-256/384/512 to P-256/384/521 for DPP */
4707 group = crypto_ec_key_group(key);
4708 if (group == 28 && ctx->iana_group == 19) {
4709 ctx->iana_group = 28;
4710 } else if (group == 29 && ctx->iana_group == 20) {
4711 ctx->iana_group = 29;
4712 } else if (group == 30 && ctx->iana_group == 21) {
4713 ctx->iana_group = 30;
4714 ctx->n_pk = 129;
4715 }
4716 if (group != ctx->iana_group) {
4717 wpa_printf(MSG_INFO, "OpenSSL:%s:group mismatch (%d != %d)",
4718 __func__, group, ctx->iana_group);
4719 goto fail;
4720 }
4721
4722 return ctx;
4723fail:
4724 hpke_free_context(ctx);
4725 return NULL;
4726}
4727
4728
4729static size_t hpke_suite_id(struct hpke_context *ctx, bool kem, u8 *suite_id)
4730{
4731 size_t suite_id_len;
4732
4733 if (kem) {
4734 os_memcpy(suite_id, "KEM", 3);
4735 WPA_PUT_BE16(&suite_id[3], ctx->kem_id);
4736 suite_id_len = 5;
4737 } else {
4738 os_memcpy(suite_id, "HPKE", 4);
4739 WPA_PUT_BE16(&suite_id[4], ctx->kem_id);
4740 WPA_PUT_BE16(&suite_id[6], ctx->kdf_id);
4741 WPA_PUT_BE16(&suite_id[8], ctx->aead_id);
4742 suite_id_len = 10;
4743 }
4744 return suite_id_len;
4745}
4746
4747
4748static int hpke_labeled_extract(struct hpke_context *ctx, bool kem,
4749 const u8 *salt, size_t salt_len,
4750 const char *label,
4751 const u8 *ikm, size_t ikm_len, u8 *prk)
4752{
4753 u8 zero[HPKE_MAX_HASH_LEN];
4754 u8 suite_id[10];
4755 size_t suite_id_len;
4756 unsigned int mdlen = kem ? ctx->kem_n_h : ctx->n_h;
4757#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4758 EVP_MAC *hmac;
4759 OSSL_PARAM params[2];
4760 EVP_MAC_CTX *hctx;
4761 size_t mlen;
4762 int res;
4763#else /* OpenSSL version >= 3.0 */
4764 HMAC_CTX *hctx;
4765 int res;
4766#endif /* OpenSSL version >= 3.0 */
4767
4768 if (!salt || !salt_len) {
4769 salt_len = mdlen;
4770 os_memset(zero, 0, salt_len);
4771 salt = zero;
4772 }
4773
4774 suite_id_len = hpke_suite_id(ctx, kem, suite_id);
4775
4776 /* labeled_ikm = concat("HPKE-v1", suite_id, label, ikm)
4777 * return Extract(salt, labeled_ikm) */
4778
4779#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4780 hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
4781 if (!hmac)
4782 return -1;
4783
4784 params[0] = OSSL_PARAM_construct_utf8_string(
4785 "digest",
4786 (char *) EVP_MD_get0_name(kem ? ctx->kem_h : ctx->kdf_h), 0);
4787 params[1] = OSSL_PARAM_construct_end();
4788
4789 hctx = EVP_MAC_CTX_new(hmac);
4790 EVP_MAC_free(hmac);
4791 if (!hctx)
4792 return -1;
4793
4794 if (EVP_MAC_init(hctx, salt, salt_len, params) != 1)
4795 goto fail;
4796
4797 if (EVP_MAC_update(hctx, (const unsigned char *) "HPKE-v1", 7) != 1 ||
4798 EVP_MAC_update(hctx, suite_id, suite_id_len) != 1 ||
4799 EVP_MAC_update(hctx, (const unsigned char *) label,
4800 os_strlen(label)) != 1 ||
4801 EVP_MAC_update(hctx, ikm, ikm_len) != 1)
4802 goto fail;
4803
4804 res = EVP_MAC_final(hctx, prk, &mlen, mdlen);
4805 EVP_MAC_CTX_free(hctx);
4806
4807 return res == 1 ? 0 : -1;
4808fail:
4809 EVP_MAC_CTX_free(hctx);
4810 return -1;
4811#else /* OpenSSL version >= 3.0 */
4812 hctx = HMAC_CTX_new();
4813 if (!hctx)
4814 return -1;
4815 res = HMAC_Init_ex(hctx, salt, salt_len, kem ? ctx->kem_h : ctx->kdf_h,
4816 NULL);
4817 if (res != 1)
4818 goto done;
4819
4820 HMAC_Update(hctx, (const unsigned char *) "HPKE-v1", 7);
4821 HMAC_Update(hctx, suite_id, suite_id_len);
4822 HMAC_Update(hctx, (const unsigned char *) label, os_strlen(label));
4823 HMAC_Update(hctx, ikm, ikm_len);
4824
4825 res = HMAC_Final(hctx, prk, &mdlen);
4826done:
4827 HMAC_CTX_free(hctx);
4828
4829 return res == 1 ? 0 : -1;
4830#endif /* OpenSSL version >= 3.0 */
4831}
4832
4833
4834static int
4835hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
4836 const char *label, const u8 *info, size_t info_len,
4837 u8 *out, size_t out_len)
4838{
4839 u8 suite_id[10];
4840 size_t suite_id_len;
4841 u8 hash[HPKE_MAX_HASH_LEN];
4842 u8 iter = 0;
4843 size_t label_len = os_strlen(label);
4844 u8 *pos;
4845 size_t left = out_len, clen;
4846 int res = -1;
4847 u8 *labeled_info;
4848 size_t labeled_info_len;
4849#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4850 EVP_MAC *hmac;
4851 OSSL_PARAM params[2];
4852 EVP_MAC_CTX *hctx = NULL;
4853 size_t mdlen;
4854#else /* OpenSSL version >= 3.0 */
4855 HMAC_CTX *hctx;
4856 unsigned int mdlen;
4857#endif /* OpenSSL version >= 3.0 */
4858
4859 /* labeled_info = concat(I2OSP(L, 2), "HPKE-v1", suite_id,
4860 * label, info)
4861 * return Expand(prk, labeled_info, L) */
4862 suite_id_len = hpke_suite_id(ctx, kem, suite_id);
4863 labeled_info_len = 2 + 7 + suite_id_len + label_len + info_len;
4864 labeled_info = os_malloc(labeled_info_len);
4865 if (!labeled_info)
4866 return -1;
4867 pos = labeled_info;
4868 WPA_PUT_BE16(pos, out_len);
4869 pos += 2;
4870 os_memcpy(pos, "HPKE-v1", 7);
4871 pos += 7;
4872 os_memcpy(pos, suite_id, suite_id_len);
4873 pos += suite_id_len;
4874 os_memcpy(pos, label, label_len);
4875 pos += label_len;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004876 if (info && info_len)
Sunil Ravi89eba102022-09-13 21:04:37 -07004877 os_memcpy(pos, info, info_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07004878
4879 pos = out;
4880#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4881 hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
4882 if (!hmac)
Sunil Ravi88611412024-06-28 17:34:56 +00004883 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004884
4885 params[0] = OSSL_PARAM_construct_utf8_string(
4886 "digest",
4887 (char *) EVP_MD_get0_name(kem ? ctx->kem_h : ctx->kdf_h), 0);
4888 params[1] = OSSL_PARAM_construct_end();
4889#else /* OpenSSL version >= 3.0 */
4890 hctx = HMAC_CTX_new();
4891 if (!hctx)
Sunil Ravi88611412024-06-28 17:34:56 +00004892 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004893#endif /* OpenSSL version >= 3.0 */
4894
4895 while (left > 0) {
4896 mdlen = kem ? ctx->kem_n_h : ctx->n_h;
4897#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4898 EVP_MAC_CTX_free(hctx);
4899 hctx = EVP_MAC_CTX_new(hmac);
4900 if (!hctx)
Sunil Ravi88611412024-06-28 17:34:56 +00004901 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004902
4903 if (EVP_MAC_init(hctx, prk, mdlen, params) != 1)
4904 goto fail;
4905
4906 if (iter > 0 && EVP_MAC_update(hctx, hash, mdlen) != 1)
4907 goto fail;
4908 if (iter == 255)
4909 goto fail;
4910 iter++;
4911
4912 if (EVP_MAC_update(hctx, labeled_info, labeled_info_len) != 1 ||
4913 EVP_MAC_update(hctx, &iter, sizeof(iter)) != 1)
4914 goto fail;
4915
4916 if (EVP_MAC_final(hctx, hash, &mdlen, mdlen) != 1)
4917 goto fail;
4918#else /* OpenSSL version >= 3.0 */
4919 if (HMAC_Init_ex(hctx, prk, mdlen,
4920 kem ? ctx->kem_h : ctx->kdf_h,
4921 NULL) != 1)
4922 goto fail;
4923
4924 if (iter > 0)
4925 HMAC_Update(hctx, hash, mdlen);
4926 if (iter == 255)
4927 goto fail;
4928 iter++;
4929 HMAC_Update(hctx, labeled_info, labeled_info_len);
4930 HMAC_Update(hctx, &iter, sizeof(iter));
4931
4932 if (HMAC_Final(hctx, hash, &mdlen) != 1)
4933 goto fail;
4934 HMAC_CTX_reset(hctx);
4935#endif /* OpenSSL version >= 3.0 */
4936
4937 clen = left > mdlen ? mdlen : left;
4938 os_memcpy(pos, hash, clen);
4939 pos += clen;
4940 left -= clen;
4941 }
4942 res = 0;
4943fail:
4944#if OPENSSL_VERSION_NUMBER >= 0x30000000L
4945 EVP_MAC_free(hmac);
4946 EVP_MAC_CTX_free(hctx);
4947#else /* OpenSSL version >= 3.0 */
4948 HMAC_CTX_free(hctx);
4949#endif /* OpenSSL version >= 3.0 */
4950 os_free(labeled_info);
4951
4952 return res;
4953}
4954
4955
4956static int hpke_extract_and_expand(struct hpke_context *ctx,
4957 const u8 *dhss, size_t dhss_len,
4958 const u8 *enc, size_t enc_len,
4959 const u8 *pk_rm, size_t pk_rm_len,
4960 u8 *shared_secret)
4961{
4962 u8 kem_context[2 * HPKE_MAX_PUB_LEN];
4963 u8 eae_prk[HPKE_MAX_HASH_LEN];
4964
4965 /* eae_prk = LabeledExtract("", "eae_prk", dh) */
4966 if (hpke_labeled_extract(ctx, true, NULL, 0, "eae_prk", dhss, dhss_len,
4967 eae_prk) < 0)
4968 return -1;
4969
4970 if (enc_len > HPKE_MAX_PUB_LEN || pk_rm_len > HPKE_MAX_PUB_LEN)
4971 return -1;
4972 /* kem_context = concat(enc, pkRm) */
4973 os_memcpy(kem_context, enc, enc_len);
4974 os_memcpy(&kem_context[enc_len], pk_rm, pk_rm_len);
4975
4976 /* shared_secret = LabeledExpand(eae_prk, "shared_secret",
4977 * kem_context, Nsecret) */
4978 if (hpke_labeled_expand(ctx, true, eae_prk, "shared_secret",
4979 kem_context, enc_len + pk_rm_len,
4980 shared_secret, ctx->n_secret) < 0)
4981 return -1;
4982
4983 forced_memzero(eae_prk, sizeof(eae_prk));
4984 return 0;
4985}
4986
4987
4988static int hpke_key_schedule(struct hpke_context *ctx, const u8 *shared_secret,
4989 const u8 *info, size_t info_len)
4990{
4991 u8 key_schedule_context[1 + 2 * HPKE_MAX_HASH_LEN];
4992 u8 secret[HPKE_MAX_HASH_LEN];
4993 int res = -1;
4994
4995 /* key_schedule_context = concat(mode, psk_id_hash, info_hash) */
4996 key_schedule_context[0] = HPKE_MODE_BASE;
4997
4998 /* psk_id_hash = LabeledExtract("", "psk_id_hash", psk_id) */
4999 if (hpke_labeled_extract(ctx, false, NULL, 0, "psk_id_hash",
5000 NULL, 0, &key_schedule_context[1]) < 0)
5001 goto fail;
5002
5003 /* info_hash = LabeledExtract("", "info_hash", info) */
5004 if (hpke_labeled_extract(ctx, false, NULL, 0, "info_hash",
5005 info, info_len,
5006 &key_schedule_context[1 + ctx->n_h]) < 0)
5007 goto fail;
5008
5009 /* secret = LabeledExtract(shared_secret, "secret", psk) */
5010 if (hpke_labeled_extract(ctx, false, shared_secret, ctx->n_secret,
5011 "secret", NULL, 0, secret) < 0)
5012 goto fail;
5013
5014 /* key = LabeledExpand(secret, "key", key_schedule_context, Nk) */
5015 if (hpke_labeled_expand(ctx, false, secret, "key",
5016 key_schedule_context, 1 + 2 * ctx->n_h,
5017 ctx->key, ctx->n_k) < 0)
5018 goto fail;
5019
5020 /* base_nonce = LabeledExpand(secret, "base_nonce",
5021 * key_schedule_context, Nn) */
5022 if (hpke_labeled_expand(ctx, false, secret, "base_nonce",
5023 key_schedule_context, 1 + 2 * ctx->n_h,
5024 ctx->base_nonce, ctx->n_n) < 0)
5025 goto fail;
5026 res = 0;
5027fail:
5028 forced_memzero(key_schedule_context, sizeof(key_schedule_context));
5029 forced_memzero(secret, sizeof(secret));
5030 return res;
5031}
5032
5033
5034static int hpke_encap(struct hpke_context *ctx, struct crypto_ec_key *pk_r,
5035 u8 *shared_secret, u8 *enc)
5036{
5037 EVP_PKEY_CTX *pctx = NULL;
5038 struct crypto_ec_key *sk_e;
5039 int res = -1;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005040 u8 *dhss = NULL;
5041 size_t dhss_len = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07005042 struct wpabuf *enc_buf = NULL, *pk_rm = NULL;
5043
5044 /* skE, pkE = GenerateKeyPair() */
5045 sk_e = crypto_ec_key_gen(ctx->iana_group);
5046 if (!sk_e) {
5047 wpa_printf(MSG_INFO, "OpenSSL:%s:Could not generate key pair",
5048 __func__);
5049 goto fail;
5050 }
5051
5052 /* dh = DH(skE, pkR) */
5053 dhss_len = sizeof(dhss);
5054 pctx = EVP_PKEY_CTX_new((EVP_PKEY *) sk_e, NULL);
5055 if (!pctx ||
5056 EVP_PKEY_derive_init(pctx) != 1 ||
5057 EVP_PKEY_derive_set_peer(pctx, (EVP_PKEY *) pk_r) != 1 ||
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005058 EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 ||
5059 !(dhss = os_malloc(dhss_len)) ||
Sunil Ravi89eba102022-09-13 21:04:37 -07005060 EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 ||
5061 dhss_len > HPKE_MAX_SHARED_SECRET_LEN) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005062 wpa_printf(MSG_INFO,
5063 "OpenSSL: hpke_encap: EVP_PKEY_derive failed (dhss_len=%zu): %s",
5064 dhss_len, ERR_error_string(ERR_get_error(), NULL));
Sunil Ravi89eba102022-09-13 21:04:37 -07005065 goto fail;
5066 }
5067
5068 /* enc = SerializePublicKey(pkE) */
5069 enc_buf = crypto_ec_key_get_pubkey_point(sk_e, 1);
5070 if (!enc_buf)
5071 goto fail;
5072 os_memcpy(enc, wpabuf_head(enc_buf), wpabuf_len(enc_buf));
5073
5074 /* pkRm = SerializePublicKey(pkR) */
5075 pk_rm = crypto_ec_key_get_pubkey_point(pk_r, 1);
5076 if (!pk_rm)
5077 goto fail;
5078
5079 /* kem_context = concat(enc, pkRm) */
5080 /* shared_secret = ExtractAndExpand(dh, kem_context) */
5081 /* return shared_secret, enc */
5082 res = hpke_extract_and_expand(ctx, dhss, dhss_len, enc, ctx->n_pk,
5083 wpabuf_head(pk_rm),
5084 wpabuf_len(pk_rm), shared_secret);
5085fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005086 bin_clear_free(dhss, dhss_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07005087 crypto_ec_key_deinit(sk_e);
5088 EVP_PKEY_CTX_free(pctx);
5089 wpabuf_free(enc_buf);
5090 wpabuf_free(pk_rm);
5091 return res;
5092}
5093
5094
5095static struct wpabuf *
5096hpke_aead_seal(struct hpke_context *ctx, const u8 *aad, size_t aad_len,
5097 const u8 *pt, size_t pt_len)
5098{
5099 EVP_CIPHER_CTX *cctx;
5100 int len = 0;
5101 struct wpabuf *ct = NULL;
5102
5103 /* No need to xor in sequence number since we support only the
5104 * single-shot API, i.e., base_nonce can be used as-is. */
5105
5106 cctx = EVP_CIPHER_CTX_new();
5107 if (!cctx ||
5108 EVP_EncryptInit_ex(cctx, ctx->cipher, NULL, ctx->key,
5109 ctx->base_nonce) != 1) {
5110 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptInit_ex failed",
5111 __func__);
5112 goto fail;
5113 }
5114 if (aad && aad_len &&
5115 EVP_EncryptUpdate(cctx, NULL, &len, aad, aad_len) != 1) {
5116 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_EncryptUpdate(AAD) failed",
5117 __func__);
5118 goto fail;
5119 }
5120 ct = wpabuf_alloc(pt_len + AES_BLOCK_SIZE + ctx->n_t);
5121 if (!ct)
5122 goto fail;
5123 if (EVP_EncryptUpdate(cctx, wpabuf_put(ct, 0), &len, pt, pt_len) != 1) {
5124 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_EncryptUpdate failed",
5125 __func__);
5126 goto fail;
5127 }
5128 wpabuf_put(ct, len);
5129
5130 if (EVP_EncryptFinal(cctx, wpabuf_put(ct, 0), &len) != 1) {
5131 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptFinal failed",
5132 __func__);
5133 wpabuf_free(ct);
5134 ct = NULL;
5135 goto fail;
5136 }
5137
5138 if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG, ctx->n_t,
5139 wpabuf_put(ct, ctx->n_t)) != 1) {
5140 wpa_printf(MSG_INFO, "OpenSSL:%s:Could not get tag",
5141 __func__);
5142 wpabuf_free(ct);
5143 ct = NULL;
5144 goto fail;
5145 }
5146fail:
5147 EVP_CIPHER_CTX_free(cctx);
5148 return ct;
5149}
5150
5151
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005152static struct wpabuf * hpke_base_seal_int(enum hpke_kem_id kem_id,
5153 enum hpke_kdf_id kdf_id,
5154 enum hpke_aead_id aead_id,
5155 struct crypto_ec_key *peer_pub,
5156 const u8 *info, size_t info_len,
5157 const u8 *aad, size_t aad_len,
5158 const u8 *pt, size_t pt_len)
Sunil Ravi89eba102022-09-13 21:04:37 -07005159{
5160 struct hpke_context *ctx;
5161 u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN];
5162 u8 enc[1 + 2 * HPKE_MAX_PUB_LEN];
5163 struct wpabuf *ct = NULL, *enc_ct = NULL;
5164
5165 ctx = hpke_get_context(kem_id, kdf_id, aead_id, peer_pub);
5166 if (!ctx)
5167 return NULL;
5168
5169 /* shared_secret, enc = Encap(pkR) */
5170 if (hpke_encap(ctx, peer_pub, shared_secret, enc) < 0)
5171 goto fail;
5172
5173 /* KeyScheduleS(mode_base, shared_secret, info,
5174 * default_psk, default_psk_id) */
5175 if (hpke_key_schedule(ctx, shared_secret, info, info_len) < 0)
5176 goto fail;
5177
5178 /* ct = ctx.Seal(aad, pt) */
5179 ct = hpke_aead_seal(ctx, aad, aad_len, pt, pt_len);
5180 if (!ct)
5181 goto fail;
5182
5183 /* return enc, ct */
5184 enc_ct = wpabuf_alloc(ctx->n_pk + wpabuf_len(ct));
5185 if (!enc_ct)
5186 goto fail;
5187 wpabuf_put_data(enc_ct, enc, ctx->n_pk);
5188 wpabuf_put_buf(enc_ct, ct);
5189
5190fail:
5191 forced_memzero(shared_secret, sizeof(shared_secret));
5192 hpke_free_context(ctx);
5193 wpabuf_free(ct);
5194 return enc_ct;
5195}
5196
5197
5198static int hpke_decap(struct hpke_context *ctx, const u8 *enc,
5199 size_t enc_ct_len, struct crypto_ec_key *sk_r,
5200 u8 *shared_secret)
5201{
5202 EVP_PKEY_CTX *pctx = NULL;
5203 struct wpabuf *pk_rm = NULL;
5204 size_t len;
5205 int res = -1;
5206 struct crypto_ec_key *pk_e = NULL;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005207 u8 *dhss = NULL;
5208 size_t dhss_len = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07005209
5210 /* pkE = DeserializePublicKey(enc) */
5211 if (enc_ct_len < ctx->n_pk)
5212 return -1; /* not enough room for enc */
5213 if (enc[0] != 0x04)
5214 return -1; /* not in uncompressed form */
5215 len = (ctx->n_pk - 1) / 2;
5216 pk_e = crypto_ec_key_set_pub(ctx->iana_group, &enc[1],
5217 &enc[1 + len], len);
5218 if (!pk_e)
5219 return -1; /* invalid public key point */
5220 /* dh = DH(skR, pkE) */
Sunil Ravi89eba102022-09-13 21:04:37 -07005221 pctx = EVP_PKEY_CTX_new((EVP_PKEY *) sk_r, NULL);
5222 if (!pctx ||
5223 EVP_PKEY_derive_init(pctx) != 1 ||
5224 EVP_PKEY_derive_set_peer(pctx, (EVP_PKEY *) pk_e) != 1 ||
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005225 EVP_PKEY_derive(pctx, NULL, &dhss_len) != 1 ||
5226 !(dhss = os_malloc(dhss_len)) ||
Sunil Ravi89eba102022-09-13 21:04:37 -07005227 EVP_PKEY_derive(pctx, dhss, &dhss_len) != 1 ||
5228 dhss_len > HPKE_MAX_SHARED_SECRET_LEN) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005229 wpa_printf(MSG_INFO,
5230 "OpenSSL: hpke_decap: EVP_PKEY_derive failed (dhss_len=%zu): %s",
5231 dhss_len, ERR_error_string(ERR_get_error(), NULL));
Sunil Ravi89eba102022-09-13 21:04:37 -07005232 goto fail;
5233 }
5234
5235 /* pkRm = SerializePublicKey(pk(skR)) */
5236 pk_rm = crypto_ec_key_get_pubkey_point(sk_r, 1);
5237 if (!pk_rm)
5238 goto fail;
5239
5240 /* kem_context = concat(enc, pkRm) */
5241 /* shared_secret = ExtractAndExpand(dh, kem_context) */
5242 res = hpke_extract_and_expand(ctx, dhss, dhss_len, enc, ctx->n_pk,
5243 wpabuf_head(pk_rm),
5244 wpabuf_len(pk_rm), shared_secret);
5245fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00005246 bin_clear_free(dhss, dhss_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07005247 crypto_ec_key_deinit(pk_e);
5248 EVP_PKEY_CTX_free(pctx);
5249 wpabuf_free(pk_rm);
5250 return res;
5251}
5252
5253
5254static struct wpabuf *
5255hpke_aead_open(struct hpke_context *ctx, const u8 *aad, size_t aad_len,
5256 const u8 *ct, size_t ct_len)
5257{
5258 EVP_CIPHER_CTX *cctx;
5259 int len = 0;
5260 const u8 *tag;
5261 struct wpabuf *pt = NULL;
5262
5263 if (ct_len < ctx->n_t)
5264 return NULL;
5265 tag = ct + ct_len - ctx->n_t;
5266 ct_len -= ctx->n_t;
5267
5268 /* No need to xor in sequence number since we support only the
5269 * single-shot API, i.e., base_nonce can be used as-is. */
5270
5271 cctx = EVP_CIPHER_CTX_new();
5272 if (!cctx ||
5273 EVP_DecryptInit_ex(cctx, ctx->cipher, NULL, ctx->key,
5274 ctx->base_nonce) != 1) {
5275 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptInit_ex failed",
5276 __func__);
5277 goto fail;
5278 }
5279 if (aad && aad_len &&
5280 EVP_DecryptUpdate(cctx, NULL, &len, aad, aad_len) != 1) {
5281 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptUpdate(AAD) failed",
5282 __func__);
5283 goto fail;
5284 }
5285 pt = wpabuf_alloc(ct_len + AES_BLOCK_SIZE);
5286 if (!pt)
5287 goto fail;
5288 if (EVP_DecryptUpdate(cctx, wpabuf_put(pt, 0), &len, ct, ct_len) != 1) {
5289 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptUpdate failed",
5290 __func__);
5291 goto fail;
5292 }
5293 wpabuf_put(pt, len);
5294
5295 if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_SET_TAG, ctx->n_t,
5296 (void *) tag) != 1) {
5297 wpa_printf(MSG_INFO, "OpenSSL:%s:Could not set tag",
5298 __func__);
5299 wpabuf_free(pt);
5300 pt = NULL;
5301 goto fail;
5302 }
5303
5304 if (EVP_DecryptFinal(cctx, wpabuf_put(pt, 0), &len) != 1) {
5305 wpa_printf(MSG_INFO, "OpenSSL:%s:EVP_DecryptFinal failed",
5306 __func__);
5307 wpabuf_free(pt);
5308 pt = NULL;
5309 }
5310fail:
5311 EVP_CIPHER_CTX_free(cctx);
5312 return pt;
5313}
5314
5315
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005316static struct wpabuf * hpke_base_open_int(enum hpke_kem_id kem_id,
5317 enum hpke_kdf_id kdf_id,
5318 enum hpke_aead_id aead_id,
5319 struct crypto_ec_key *own_priv,
5320 const u8 *info, size_t info_len,
5321 const u8 *aad, size_t aad_len,
5322 const u8 *enc_ct, size_t enc_ct_len)
Sunil Ravi89eba102022-09-13 21:04:37 -07005323{
5324 struct hpke_context *ctx;
5325 u8 shared_secret[HPKE_MAX_SHARED_SECRET_LEN];
5326 struct wpabuf *pt = NULL;
5327
5328 ctx = hpke_get_context(kem_id, kdf_id, aead_id, own_priv);
5329 if (!ctx)
5330 return NULL;
5331
5332 /* shared_secret = Decap(enc, skR) */
5333 if (hpke_decap(ctx, enc_ct, enc_ct_len, own_priv, shared_secret) < 0)
5334 goto fail;
5335
5336 /* KeyScheduleR(mode_base, shared_secret, info,
5337 * default_psk, default_psk_id) */
5338 if (hpke_key_schedule(ctx, shared_secret, info, info_len) < 0)
5339 goto fail;
5340
5341 /* return ctx.Open(aad, ct) */
5342 pt = hpke_aead_open(ctx, aad, aad_len,
5343 &enc_ct[ctx->n_pk], enc_ct_len - ctx->n_pk);
5344
5345fail:
5346 forced_memzero(shared_secret, sizeof(shared_secret));
5347 hpke_free_context(ctx);
5348 return pt;
5349}
5350
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005351
5352#if OPENSSL_VERSION_NUMBER >= 0x30200000L
5353
5354static bool hpke_set_suite(OSSL_HPKE_SUITE *suite,
5355 enum hpke_kem_id kem_id,
5356 enum hpke_kdf_id kdf_id,
5357 enum hpke_aead_id aead_id)
5358{
5359 os_memset(suite, 0, sizeof(*suite));
5360
5361 switch (kem_id) {
5362 case HPKE_DHKEM_P256_HKDF_SHA256:
5363 suite->kem_id = OSSL_HPKE_KEM_ID_P256;
5364 break;
5365 case HPKE_DHKEM_P384_HKDF_SHA384:
5366 suite->kem_id = OSSL_HPKE_KEM_ID_P384;
5367 break;
5368 case HPKE_DHKEM_P521_HKDF_SHA512:
5369 suite->kem_id = OSSL_HPKE_KEM_ID_P521;
5370 break;
5371 default:
5372 return false;
5373 }
5374
5375 switch (kdf_id) {
5376 case HPKE_KDF_HKDF_SHA256:
5377 suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA256;
5378 break;
5379 case HPKE_KDF_HKDF_SHA384:
5380 suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA384;
5381 break;
5382 case HPKE_KDF_HKDF_SHA512:
5383 suite->kdf_id = OSSL_HPKE_KDF_ID_HKDF_SHA512;
5384 break;
5385 default:
5386 return false;
5387 }
5388
5389 switch (aead_id) {
5390 case HPKE_AEAD_AES_128_GCM:
5391 suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_128;
5392 break;
5393 case HPKE_AEAD_AES_256_GCM:
5394 suite->aead_id = OSSL_HPKE_AEAD_ID_AES_GCM_256;
5395 break;
5396 default:
5397 return false;
5398 }
5399
5400 if (!OSSL_HPKE_suite_check(*suite)) {
5401 wpa_printf(MSG_INFO,
5402 "OpenSSL: HPKE suite kem_id=%d kdf_id=%d aead_id=%d not supported",
5403 kem_id, kdf_id, aead_id);
5404 return false;
5405 }
5406
5407 return true;
5408}
5409
5410
5411struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
5412 enum hpke_kdf_id kdf_id,
5413 enum hpke_aead_id aead_id,
5414 struct crypto_ec_key *peer_pub,
5415 const u8 *info, size_t info_len,
5416 const u8 *aad, size_t aad_len,
5417 const u8 *pt, size_t pt_len)
5418{
5419 OSSL_HPKE_SUITE suite;
5420 OSSL_HPKE_CTX *ctx = NULL;
5421 struct wpabuf *res = NULL, *buf, *pub = NULL;
5422 size_t enc_len, ct_len;
5423 int group;
5424
5425 group = crypto_ec_key_group(peer_pub);
5426 if (group == 28 || group == 29 || group == 30) {
5427 /* Use the internal routines for the special DPP use case with
5428 * brainpool curves, */
5429 return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub,
5430 info, info_len, aad, aad_len,
5431 pt, pt_len);
5432 }
5433
5434
5435 if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id))
5436 return NULL;
5437
5438 enc_len = OSSL_HPKE_get_public_encap_size(suite);
5439 ct_len = OSSL_HPKE_get_ciphertext_size(suite, pt_len);
5440 buf = wpabuf_alloc(enc_len + ct_len);
5441 if (!buf)
5442 goto out;
5443
5444 pub = crypto_ec_key_get_pubkey_point(peer_pub, 1);
5445 if (!pub)
5446 goto out;
5447
5448 ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite,
5449 OSSL_HPKE_ROLE_SENDER, NULL, NULL);
5450 if (!ctx)
5451 goto out;
5452
5453 if (OSSL_HPKE_encap(ctx, wpabuf_put(buf, 0), &enc_len,
5454 wpabuf_head(pub), wpabuf_len(pub),
5455 info, info_len) != 1) {
5456 wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_encap failed: %s",
5457 ERR_error_string(ERR_get_error(), NULL));
5458 goto out;
5459 }
5460 wpabuf_put(buf, enc_len);
5461
5462 if (OSSL_HPKE_seal(ctx, wpabuf_put(buf, 0), &ct_len, aad, aad_len,
5463 pt, pt_len) != 1) {
5464 wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_seal failed: %s",
5465 ERR_error_string(ERR_get_error(), NULL));
5466 goto out;
5467 }
5468 wpabuf_put(buf, ct_len);
5469 res = buf;
5470 buf = NULL;
5471
5472out:
5473 OSSL_HPKE_CTX_free(ctx);
5474 wpabuf_free(buf);
5475 wpabuf_free(pub);
5476 return res;
5477}
5478
5479
5480struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
5481 enum hpke_kdf_id kdf_id,
5482 enum hpke_aead_id aead_id,
5483 struct crypto_ec_key *own_priv,
5484 const u8 *info, size_t info_len,
5485 const u8 *aad, size_t aad_len,
5486 const u8 *enc_ct, size_t enc_ct_len)
5487{
5488 OSSL_HPKE_SUITE suite;
5489 OSSL_HPKE_CTX *ctx;
5490 struct wpabuf *buf = NULL, *res = NULL;
5491 size_t len, enc_len;
5492 int group;
5493
5494 group = crypto_ec_key_group(own_priv);
5495 if (group == 28 || group == 29 || group == 30) {
5496 /* Use the internal routines for the special DPP use case with
5497 * brainpool curves, */
5498 return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv,
5499 info, info_len, aad, aad_len,
5500 enc_ct, enc_ct_len);
5501 }
5502
5503 if (!hpke_set_suite(&suite, kem_id, kdf_id, aead_id))
5504 return NULL;
5505
5506 enc_len = OSSL_HPKE_get_public_encap_size(suite);
5507 if (enc_ct_len < enc_len) {
5508 wpa_printf(MSG_DEBUG, "OpenSSL: Too short HPKE enc_ct data");
5509 return NULL;
5510 }
5511
5512 ctx = OSSL_HPKE_CTX_new(OSSL_HPKE_MODE_BASE, suite,
5513 OSSL_HPKE_ROLE_RECEIVER, NULL, NULL);
5514 if (!ctx)
5515 goto out;
5516
5517 if (OSSL_HPKE_decap(ctx, enc_ct, enc_len, (EVP_PKEY *) own_priv,
5518 info, info_len) != 1) {
5519 wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_decap failed: %s",
5520 ERR_error_string(ERR_get_error(), NULL));
5521 goto out;
5522 }
5523
5524 len = enc_ct_len;
5525 buf = wpabuf_alloc(len);
5526 if (!buf)
5527 goto out;
5528
5529 if (OSSL_HPKE_open(ctx, wpabuf_put(buf, 0), &len, aad, aad_len,
5530 enc_ct + enc_len, enc_ct_len - enc_len) != 1) {
5531 wpa_printf(MSG_DEBUG, "OpenSSL: OSSL_HPKE_open failed: %s",
5532 ERR_error_string(ERR_get_error(), NULL));
5533 goto out;
5534 }
5535
5536 wpabuf_put(buf, len);
5537 res = buf;
5538 buf = NULL;
5539
5540out:
5541 OSSL_HPKE_CTX_free(ctx);
5542 wpabuf_free(buf);
5543 return res;
5544}
5545
5546#else /* OpenSSL < 3.2 */
5547
5548struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
5549 enum hpke_kdf_id kdf_id,
5550 enum hpke_aead_id aead_id,
5551 struct crypto_ec_key *peer_pub,
5552 const u8 *info, size_t info_len,
5553 const u8 *aad, size_t aad_len,
5554 const u8 *pt, size_t pt_len)
5555{
5556 return hpke_base_seal_int(kem_id, kdf_id, aead_id, peer_pub,
5557 info, info_len, aad, aad_len, pt, pt_len);
5558}
5559
5560
5561struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
5562 enum hpke_kdf_id kdf_id,
5563 enum hpke_aead_id aead_id,
5564 struct crypto_ec_key *own_priv,
5565 const u8 *info, size_t info_len,
5566 const u8 *aad, size_t aad_len,
5567 const u8 *enc_ct, size_t enc_ct_len)
5568{
5569 return hpke_base_open_int(kem_id, kdf_id, aead_id, own_priv,
5570 info, info_len, aad, aad_len,
5571 enc_ct, enc_ct_len);
5572}
5573
5574#endif /* OpenSSL < 3.2 */
5575
Sunil Ravi89eba102022-09-13 21:04:37 -07005576#endif /* CONFIG_DPP3 */
5577
5578
Sunil Ravia04bd252022-05-02 22:54:18 -07005579void crypto_unload(void)
5580{
5581 openssl_unload_legacy_provider();
5582}