185732ac8SCy Schubert /*
285732ac8SCy Schubert * Wrapper functions for libwolfssl
385732ac8SCy Schubert * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
485732ac8SCy Schubert *
585732ac8SCy Schubert * This software may be distributed under the terms of the BSD license.
685732ac8SCy Schubert * See README for more details.
785732ac8SCy Schubert */
885732ac8SCy Schubert
985732ac8SCy Schubert #include "includes.h"
1085732ac8SCy Schubert
1185732ac8SCy Schubert #include "common.h"
1285732ac8SCy Schubert #include "crypto.h"
13*a90b9d01SCy Schubert #include "tls/asn1.h"
1485732ac8SCy Schubert
1585732ac8SCy Schubert /* wolfSSL headers */
16*a90b9d01SCy Schubert #include <wolfssl/options.h> /* options.h needs to be included first */
17*a90b9d01SCy Schubert #include <wolfssl/version.h>
18*a90b9d01SCy Schubert #include <wolfssl/openssl/bn.h>
19*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/aes.h>
20*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/arc4.h>
21*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/asn_public.h>
22*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/cmac.h>
23*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/des3.h>
24*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/dh.h>
25*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/ecc.h>
26*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/error-crypt.h>
27*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/hmac.h>
2885732ac8SCy Schubert #include <wolfssl/wolfcrypt/md4.h>
2985732ac8SCy Schubert #include <wolfssl/wolfcrypt/md5.h>
30*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/pkcs7.h>
31*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/pwdbased.h>
3285732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha.h>
3385732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha256.h>
3485732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha512.h>
35*a90b9d01SCy Schubert
36*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
37*a90b9d01SCy Schubert #ifndef HAVE_FIPS
38*a90b9d01SCy Schubert #warning "You are compiling wpa_supplicant/hostapd in FIPS mode but wolfSSL is not configured for FIPS mode."
39*a90b9d01SCy Schubert #endif /* HAVE_FIPS */
40*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
41*a90b9d01SCy Schubert
42*a90b9d01SCy Schubert
43*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
44*a90b9d01SCy Schubert #if !defined(HAVE_FIPS_VERSION) || HAVE_FIPS_VERSION <= 2
45*a90b9d01SCy Schubert #define WOLFSSL_OLD_FIPS
46*a90b9d01SCy Schubert #endif
47*a90b9d01SCy Schubert #endif
48*a90b9d01SCy Schubert
49*a90b9d01SCy Schubert #if LIBWOLFSSL_VERSION_HEX < 0x05004000
wc_EccPublicKeyToDer_ex(ecc_key * key,byte * output,word32 inLen,int with_AlgCurve,int comp)50*a90b9d01SCy Schubert static int wc_EccPublicKeyToDer_ex(ecc_key *key, byte *output,
51*a90b9d01SCy Schubert word32 inLen, int with_AlgCurve,
52*a90b9d01SCy Schubert int comp)
53*a90b9d01SCy Schubert {
54*a90b9d01SCy Schubert return wc_EccPublicKeyToDer(key, output, inLen, with_AlgCurve);
55*a90b9d01SCy Schubert }
56*a90b9d01SCy Schubert #endif /* version < 5.4.0 */
57*a90b9d01SCy Schubert
58*a90b9d01SCy Schubert #define LOG_WOLF_ERROR_VA(msg, ...) \
59*a90b9d01SCy Schubert wpa_printf(MSG_ERROR, "wolfSSL: %s:%d " msg, \
60*a90b9d01SCy Schubert __func__, __LINE__, __VA_ARGS__)
61*a90b9d01SCy Schubert
62*a90b9d01SCy Schubert #define LOG_WOLF_ERROR(msg) \
63*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("%s", (msg))
64*a90b9d01SCy Schubert
65*a90b9d01SCy Schubert #define LOG_WOLF_ERROR_FUNC(func, err) \
66*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA(#func " failed with err: %d %s", \
67*a90b9d01SCy Schubert (err), wc_GetErrorString(err))
68*a90b9d01SCy Schubert
69*a90b9d01SCy Schubert #define LOG_WOLF_ERROR_FUNC_NULL(func) \
70*a90b9d01SCy Schubert LOG_WOLF_ERROR(#func " failed with NULL return")
71*a90b9d01SCy Schubert
72*a90b9d01SCy Schubert #define LOG_INVALID_PARAMETERS() \
73*a90b9d01SCy Schubert LOG_WOLF_ERROR("invalid input parameters")
74*a90b9d01SCy Schubert
75*a90b9d01SCy Schubert
76*a90b9d01SCy Schubert /* Helper functions to make type allocation uniform */
77*a90b9d01SCy Schubert
wc_rng_init(void)78*a90b9d01SCy Schubert static WC_RNG * wc_rng_init(void)
79*a90b9d01SCy Schubert {
80*a90b9d01SCy Schubert WC_RNG *ret;
81*a90b9d01SCy Schubert
82*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
83*a90b9d01SCy Schubert ret = os_zalloc(sizeof(WC_RNG));
84*a90b9d01SCy Schubert if (!ret) {
85*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_zalloc);
86*a90b9d01SCy Schubert } else {
87*a90b9d01SCy Schubert int err;
88*a90b9d01SCy Schubert
89*a90b9d01SCy Schubert err = wc_InitRng(ret);
90*a90b9d01SCy Schubert if (err != 0) {
91*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitRng, err);
92*a90b9d01SCy Schubert os_free(ret);
93*a90b9d01SCy Schubert ret = NULL;
94*a90b9d01SCy Schubert }
95*a90b9d01SCy Schubert }
96*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
97*a90b9d01SCy Schubert ret = wc_rng_new(NULL, 0, NULL);
98*a90b9d01SCy Schubert if (!ret)
99*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_rng_new);
100*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
101*a90b9d01SCy Schubert
102*a90b9d01SCy Schubert return ret;
103*a90b9d01SCy Schubert }
104*a90b9d01SCy Schubert
105*a90b9d01SCy Schubert
wc_rng_deinit(WC_RNG * rng)106*a90b9d01SCy Schubert static void wc_rng_deinit(WC_RNG *rng)
107*a90b9d01SCy Schubert {
108*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
109*a90b9d01SCy Schubert wc_FreeRng(rng);
110*a90b9d01SCy Schubert os_free(rng);
111*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
112*a90b9d01SCy Schubert wc_rng_free(rng);
113*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
114*a90b9d01SCy Schubert }
115*a90b9d01SCy Schubert
116*a90b9d01SCy Schubert
ecc_key_init(void)117*a90b9d01SCy Schubert static ecc_key * ecc_key_init(void)
118*a90b9d01SCy Schubert {
119*a90b9d01SCy Schubert ecc_key *ret;
120*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
121*a90b9d01SCy Schubert int err;
122*a90b9d01SCy Schubert
123*a90b9d01SCy Schubert ret = os_zalloc(sizeof(ecc_key));
124*a90b9d01SCy Schubert if (!ret) {
125*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_zalloc);
126*a90b9d01SCy Schubert } else {
127*a90b9d01SCy Schubert err = wc_ecc_init_ex(ret, NULL, INVALID_DEVID);
128*a90b9d01SCy Schubert if (err != 0) {
129*a90b9d01SCy Schubert LOG_WOLF_ERROR("wc_ecc_init_ex failed");
130*a90b9d01SCy Schubert os_free(ret);
131*a90b9d01SCy Schubert ret = NULL;
132*a90b9d01SCy Schubert }
133*a90b9d01SCy Schubert }
134*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
135*a90b9d01SCy Schubert ret = wc_ecc_key_new(NULL);
136*a90b9d01SCy Schubert if (!ret)
137*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_ecc_key_new);
138*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
139*a90b9d01SCy Schubert
140*a90b9d01SCy Schubert return ret;
141*a90b9d01SCy Schubert }
142*a90b9d01SCy Schubert
143*a90b9d01SCy Schubert
ecc_key_deinit(ecc_key * key)144*a90b9d01SCy Schubert static void ecc_key_deinit(ecc_key *key)
145*a90b9d01SCy Schubert {
146*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
147*a90b9d01SCy Schubert wc_ecc_free(key);
148*a90b9d01SCy Schubert os_free(key);
149*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
150*a90b9d01SCy Schubert wc_ecc_key_free(key);
151*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
152*a90b9d01SCy Schubert }
153*a90b9d01SCy Schubert
154*a90b9d01SCy Schubert /* end of helper functions */
15585732ac8SCy Schubert
15685732ac8SCy Schubert
15785732ac8SCy Schubert #ifndef CONFIG_FIPS
15885732ac8SCy Schubert
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)15985732ac8SCy Schubert int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
16085732ac8SCy Schubert {
16185732ac8SCy Schubert Md4 md4;
16285732ac8SCy Schubert size_t i;
16385732ac8SCy Schubert
16485732ac8SCy Schubert if (TEST_FAIL())
16585732ac8SCy Schubert return -1;
16685732ac8SCy Schubert
16785732ac8SCy Schubert wc_InitMd4(&md4);
16885732ac8SCy Schubert
16985732ac8SCy Schubert for (i = 0; i < num_elem; i++)
17085732ac8SCy Schubert wc_Md4Update(&md4, addr[i], len[i]);
17185732ac8SCy Schubert
17285732ac8SCy Schubert wc_Md4Final(&md4, mac);
17385732ac8SCy Schubert
17485732ac8SCy Schubert return 0;
17585732ac8SCy Schubert }
17685732ac8SCy Schubert
17785732ac8SCy Schubert
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)17885732ac8SCy Schubert int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
17985732ac8SCy Schubert {
18085732ac8SCy Schubert wc_Md5 md5;
18185732ac8SCy Schubert size_t i;
182*a90b9d01SCy Schubert int err;
183*a90b9d01SCy Schubert int ret = -1;
18485732ac8SCy Schubert
18585732ac8SCy Schubert if (TEST_FAIL())
18685732ac8SCy Schubert return -1;
18785732ac8SCy Schubert
188*a90b9d01SCy Schubert err = wc_InitMd5(&md5);
189*a90b9d01SCy Schubert if (err != 0) {
190*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitMd5, err);
191*a90b9d01SCy Schubert return -1;
192*a90b9d01SCy Schubert }
19385732ac8SCy Schubert
194*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
195*a90b9d01SCy Schubert err = wc_Md5Update(&md5, addr[i], len[i]);
196*a90b9d01SCy Schubert if (err != 0) {
197*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Md5Update, err);
198*a90b9d01SCy Schubert goto fail;
199*a90b9d01SCy Schubert }
200*a90b9d01SCy Schubert }
20185732ac8SCy Schubert
202*a90b9d01SCy Schubert err = wc_Md5Final(&md5, mac);
203*a90b9d01SCy Schubert if (err != 0) {
204*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Md5Final, err);
205*a90b9d01SCy Schubert goto fail;
206*a90b9d01SCy Schubert }
20785732ac8SCy Schubert
208*a90b9d01SCy Schubert ret = 0;
209*a90b9d01SCy Schubert fail:
210*a90b9d01SCy Schubert wc_Md5Free(&md5);
211*a90b9d01SCy Schubert return ret;
21285732ac8SCy Schubert }
21385732ac8SCy Schubert
21485732ac8SCy Schubert #endif /* CONFIG_FIPS */
21585732ac8SCy Schubert
21685732ac8SCy Schubert
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)21785732ac8SCy Schubert int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
21885732ac8SCy Schubert {
21985732ac8SCy Schubert wc_Sha sha;
22085732ac8SCy Schubert size_t i;
221*a90b9d01SCy Schubert int err;
222*a90b9d01SCy Schubert int ret = -1;
22385732ac8SCy Schubert
22485732ac8SCy Schubert if (TEST_FAIL())
22585732ac8SCy Schubert return -1;
22685732ac8SCy Schubert
227*a90b9d01SCy Schubert err = wc_InitSha(&sha);
228*a90b9d01SCy Schubert if (err != 0) {
229*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitSha, err);
230*a90b9d01SCy Schubert return -1;
231*a90b9d01SCy Schubert }
23285732ac8SCy Schubert
233*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
234*a90b9d01SCy Schubert err = wc_ShaUpdate(&sha, addr[i], len[i]);
235*a90b9d01SCy Schubert if (err != 0) {
236*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ShaUpdate, err);
237*a90b9d01SCy Schubert goto fail;
238*a90b9d01SCy Schubert }
239*a90b9d01SCy Schubert }
24085732ac8SCy Schubert
241*a90b9d01SCy Schubert err = wc_ShaFinal(&sha, mac);
242*a90b9d01SCy Schubert if (err != 0) {
243*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ShaFinal, err);
244*a90b9d01SCy Schubert goto fail;
245*a90b9d01SCy Schubert }
24685732ac8SCy Schubert
247*a90b9d01SCy Schubert ret = 0;
248*a90b9d01SCy Schubert fail:
249*a90b9d01SCy Schubert wc_ShaFree(&sha);
250*a90b9d01SCy Schubert return ret;
25185732ac8SCy Schubert }
25285732ac8SCy Schubert
25385732ac8SCy Schubert
25485732ac8SCy Schubert #ifndef NO_SHA256_WRAPPER
sha256_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)25585732ac8SCy Schubert int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
25685732ac8SCy Schubert u8 *mac)
25785732ac8SCy Schubert {
25885732ac8SCy Schubert wc_Sha256 sha256;
25985732ac8SCy Schubert size_t i;
260*a90b9d01SCy Schubert int err;
261*a90b9d01SCy Schubert int ret = -1;
26285732ac8SCy Schubert
26385732ac8SCy Schubert if (TEST_FAIL())
26485732ac8SCy Schubert return -1;
26585732ac8SCy Schubert
266*a90b9d01SCy Schubert err = wc_InitSha256(&sha256);
267*a90b9d01SCy Schubert if (err != 0) {
268*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitSha256, err);
269*a90b9d01SCy Schubert return -1;
270*a90b9d01SCy Schubert }
27185732ac8SCy Schubert
272*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
273*a90b9d01SCy Schubert err = wc_Sha256Update(&sha256, addr[i], len[i]);
274*a90b9d01SCy Schubert if (err != 0) {
275*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha256Update, err);
276*a90b9d01SCy Schubert goto fail;
277*a90b9d01SCy Schubert }
278*a90b9d01SCy Schubert }
27985732ac8SCy Schubert
280*a90b9d01SCy Schubert err = wc_Sha256Final(&sha256, mac);
281*a90b9d01SCy Schubert if (err != 0) {
282*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha256Final, err);
283*a90b9d01SCy Schubert goto fail;
284*a90b9d01SCy Schubert }
28585732ac8SCy Schubert
286*a90b9d01SCy Schubert ret = 0;
287*a90b9d01SCy Schubert fail:
288*a90b9d01SCy Schubert wc_Sha256Free(&sha256);
289*a90b9d01SCy Schubert return ret;
29085732ac8SCy Schubert }
29185732ac8SCy Schubert #endif /* NO_SHA256_WRAPPER */
29285732ac8SCy Schubert
29385732ac8SCy Schubert
29485732ac8SCy Schubert #ifdef CONFIG_SHA384
sha384_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)29585732ac8SCy Schubert int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
29685732ac8SCy Schubert u8 *mac)
29785732ac8SCy Schubert {
29885732ac8SCy Schubert wc_Sha384 sha384;
29985732ac8SCy Schubert size_t i;
300*a90b9d01SCy Schubert int err;
301*a90b9d01SCy Schubert int ret = -1;
30285732ac8SCy Schubert
30385732ac8SCy Schubert if (TEST_FAIL())
30485732ac8SCy Schubert return -1;
30585732ac8SCy Schubert
306*a90b9d01SCy Schubert err = wc_InitSha384(&sha384);
307*a90b9d01SCy Schubert if (err != 0) {
308*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitSha384, err);
309*a90b9d01SCy Schubert return -1;
310*a90b9d01SCy Schubert }
31185732ac8SCy Schubert
312*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
313*a90b9d01SCy Schubert err = wc_Sha384Update(&sha384, addr[i], len[i]);
314*a90b9d01SCy Schubert if (err != 0) {
315*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha384Update, err);
316*a90b9d01SCy Schubert goto fail;
317*a90b9d01SCy Schubert }
318*a90b9d01SCy Schubert }
31985732ac8SCy Schubert
320*a90b9d01SCy Schubert err = wc_Sha384Final(&sha384, mac);
321*a90b9d01SCy Schubert if (err != 0) {
322*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha384Final, err);
323*a90b9d01SCy Schubert goto fail;
324*a90b9d01SCy Schubert }
32585732ac8SCy Schubert
326*a90b9d01SCy Schubert ret = 0;
327*a90b9d01SCy Schubert fail:
328*a90b9d01SCy Schubert wc_Sha384Free(&sha384);
329*a90b9d01SCy Schubert return ret;
33085732ac8SCy Schubert }
33185732ac8SCy Schubert #endif /* CONFIG_SHA384 */
33285732ac8SCy Schubert
33385732ac8SCy Schubert
33485732ac8SCy Schubert #ifdef CONFIG_SHA512
sha512_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)33585732ac8SCy Schubert int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
33685732ac8SCy Schubert u8 *mac)
33785732ac8SCy Schubert {
33885732ac8SCy Schubert wc_Sha512 sha512;
33985732ac8SCy Schubert size_t i;
340*a90b9d01SCy Schubert int err;
341*a90b9d01SCy Schubert int ret = -1;
34285732ac8SCy Schubert
34385732ac8SCy Schubert if (TEST_FAIL())
34485732ac8SCy Schubert return -1;
34585732ac8SCy Schubert
346*a90b9d01SCy Schubert err = wc_InitSha512(&sha512);
347*a90b9d01SCy Schubert if (err != 0) {
348*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitSha512, err);
349*a90b9d01SCy Schubert return -1;
350*a90b9d01SCy Schubert }
35185732ac8SCy Schubert
352*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
353*a90b9d01SCy Schubert err = wc_Sha512Update(&sha512, addr[i], len[i]);
354*a90b9d01SCy Schubert if (err != 0) {
355*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha512Update, err);
356*a90b9d01SCy Schubert goto fail;
357*a90b9d01SCy Schubert }
358*a90b9d01SCy Schubert }
35985732ac8SCy Schubert
360*a90b9d01SCy Schubert err = wc_Sha512Final(&sha512, mac);
361*a90b9d01SCy Schubert if (err != 0) {
362*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_Sha512Final, err);
363*a90b9d01SCy Schubert goto fail;
364*a90b9d01SCy Schubert }
36585732ac8SCy Schubert
366*a90b9d01SCy Schubert ret = 0;
367*a90b9d01SCy Schubert fail:
368*a90b9d01SCy Schubert wc_Sha512Free(&sha512);
369*a90b9d01SCy Schubert return ret;
37085732ac8SCy Schubert }
37185732ac8SCy Schubert #endif /* CONFIG_SHA512 */
37285732ac8SCy Schubert
37385732ac8SCy Schubert
wolfssl_hmac_vector(int type,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac,unsigned int mdlen)37485732ac8SCy Schubert static int wolfssl_hmac_vector(int type, const u8 *key,
37585732ac8SCy Schubert size_t key_len, size_t num_elem,
37685732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac,
37785732ac8SCy Schubert unsigned int mdlen)
37885732ac8SCy Schubert {
37985732ac8SCy Schubert Hmac hmac;
38085732ac8SCy Schubert size_t i;
381*a90b9d01SCy Schubert int err;
382*a90b9d01SCy Schubert int ret = -1;
38385732ac8SCy Schubert
38485732ac8SCy Schubert (void) mdlen;
38585732ac8SCy Schubert
38685732ac8SCy Schubert if (TEST_FAIL())
38785732ac8SCy Schubert return -1;
38885732ac8SCy Schubert
389*a90b9d01SCy Schubert err = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
390*a90b9d01SCy Schubert if (err != 0) {
391*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_HmacInit, err);
39285732ac8SCy Schubert return -1;
393*a90b9d01SCy Schubert }
394*a90b9d01SCy Schubert
395*a90b9d01SCy Schubert err = wc_HmacSetKey(&hmac, type, key, (word32) key_len);
396*a90b9d01SCy Schubert if (err != 0) {
397*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_HmacSetKey, err);
398*a90b9d01SCy Schubert goto fail;
399*a90b9d01SCy Schubert }
400*a90b9d01SCy Schubert
401*a90b9d01SCy Schubert for (i = 0; i < num_elem; i++) {
402*a90b9d01SCy Schubert err = wc_HmacUpdate(&hmac, addr[i], len[i]);
403*a90b9d01SCy Schubert if (err != 0) {
404*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_HmacUpdate, err);
405*a90b9d01SCy Schubert goto fail;
406*a90b9d01SCy Schubert }
407*a90b9d01SCy Schubert }
408*a90b9d01SCy Schubert err = wc_HmacFinal(&hmac, mac);
409*a90b9d01SCy Schubert if (err != 0) {
410*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_HmacFinal, err);
411*a90b9d01SCy Schubert goto fail;
412*a90b9d01SCy Schubert }
413*a90b9d01SCy Schubert
414*a90b9d01SCy Schubert ret = 0;
415*a90b9d01SCy Schubert fail:
416*a90b9d01SCy Schubert wc_HmacFree(&hmac);
417*a90b9d01SCy Schubert return ret;
41885732ac8SCy Schubert }
41985732ac8SCy Schubert
42085732ac8SCy Schubert
42185732ac8SCy Schubert #ifndef CONFIG_FIPS
42285732ac8SCy Schubert
hmac_md5_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)42385732ac8SCy Schubert int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
42485732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
42585732ac8SCy Schubert {
42685732ac8SCy Schubert return wolfssl_hmac_vector(WC_MD5, key, key_len, num_elem, addr, len,
42785732ac8SCy Schubert mac, 16);
42885732ac8SCy Schubert }
42985732ac8SCy Schubert
43085732ac8SCy Schubert
hmac_md5(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)43185732ac8SCy Schubert int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
43285732ac8SCy Schubert u8 *mac)
43385732ac8SCy Schubert {
43485732ac8SCy Schubert return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
43585732ac8SCy Schubert }
43685732ac8SCy Schubert
43785732ac8SCy Schubert #endif /* CONFIG_FIPS */
43885732ac8SCy Schubert
43985732ac8SCy Schubert
hmac_sha1_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)44085732ac8SCy Schubert int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
44185732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
44285732ac8SCy Schubert {
44385732ac8SCy Schubert return wolfssl_hmac_vector(WC_SHA, key, key_len, num_elem, addr, len,
44485732ac8SCy Schubert mac, 20);
44585732ac8SCy Schubert }
44685732ac8SCy Schubert
44785732ac8SCy Schubert
hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)44885732ac8SCy Schubert int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
44985732ac8SCy Schubert u8 *mac)
45085732ac8SCy Schubert {
45185732ac8SCy Schubert return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
45285732ac8SCy Schubert }
45385732ac8SCy Schubert
45485732ac8SCy Schubert
45585732ac8SCy Schubert #ifdef CONFIG_SHA256
45685732ac8SCy Schubert
hmac_sha256_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)45785732ac8SCy Schubert int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
45885732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
45985732ac8SCy Schubert {
46085732ac8SCy Schubert return wolfssl_hmac_vector(WC_SHA256, key, key_len, num_elem, addr, len,
46185732ac8SCy Schubert mac, 32);
46285732ac8SCy Schubert }
46385732ac8SCy Schubert
46485732ac8SCy Schubert
hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)46585732ac8SCy Schubert int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
46685732ac8SCy Schubert size_t data_len, u8 *mac)
46785732ac8SCy Schubert {
46885732ac8SCy Schubert return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
46985732ac8SCy Schubert }
47085732ac8SCy Schubert
47185732ac8SCy Schubert #endif /* CONFIG_SHA256 */
47285732ac8SCy Schubert
47385732ac8SCy Schubert
47485732ac8SCy Schubert #ifdef CONFIG_SHA384
47585732ac8SCy Schubert
hmac_sha384_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)47685732ac8SCy Schubert int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
47785732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
47885732ac8SCy Schubert {
47985732ac8SCy Schubert return wolfssl_hmac_vector(WC_SHA384, key, key_len, num_elem, addr, len,
48085732ac8SCy Schubert mac, 48);
48185732ac8SCy Schubert }
48285732ac8SCy Schubert
48385732ac8SCy Schubert
hmac_sha384(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)48485732ac8SCy Schubert int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
48585732ac8SCy Schubert size_t data_len, u8 *mac)
48685732ac8SCy Schubert {
48785732ac8SCy Schubert return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
48885732ac8SCy Schubert }
48985732ac8SCy Schubert
49085732ac8SCy Schubert #endif /* CONFIG_SHA384 */
49185732ac8SCy Schubert
49285732ac8SCy Schubert
49385732ac8SCy Schubert #ifdef CONFIG_SHA512
49485732ac8SCy Schubert
hmac_sha512_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)49585732ac8SCy Schubert int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
49685732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
49785732ac8SCy Schubert {
49885732ac8SCy Schubert return wolfssl_hmac_vector(WC_SHA512, key, key_len, num_elem, addr, len,
49985732ac8SCy Schubert mac, 64);
50085732ac8SCy Schubert }
50185732ac8SCy Schubert
50285732ac8SCy Schubert
hmac_sha512(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)50385732ac8SCy Schubert int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
50485732ac8SCy Schubert size_t data_len, u8 *mac)
50585732ac8SCy Schubert {
50685732ac8SCy Schubert return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
50785732ac8SCy Schubert }
50885732ac8SCy Schubert
50985732ac8SCy Schubert #endif /* CONFIG_SHA512 */
51085732ac8SCy Schubert
51185732ac8SCy Schubert
pbkdf2_sha1(const char * passphrase,const u8 * ssid,size_t ssid_len,int iterations,u8 * buf,size_t buflen)51285732ac8SCy Schubert int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
51385732ac8SCy Schubert int iterations, u8 *buf, size_t buflen)
51485732ac8SCy Schubert {
515*a90b9d01SCy Schubert int ret;
516*a90b9d01SCy Schubert
517*a90b9d01SCy Schubert ret = wc_PBKDF2(buf, (const byte *) passphrase, os_strlen(passphrase),
518*a90b9d01SCy Schubert ssid, ssid_len, iterations, buflen, WC_SHA);
519*a90b9d01SCy Schubert if (ret != 0) {
520*a90b9d01SCy Schubert if (ret == HMAC_MIN_KEYLEN_E) {
521*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("wolfSSL: Password is too short. Make sure your password is at least %d characters long. This is a requirement for FIPS builds.",
522*a90b9d01SCy Schubert HMAC_FIPS_MIN_KEY);
523*a90b9d01SCy Schubert }
52485732ac8SCy Schubert return -1;
525*a90b9d01SCy Schubert }
52685732ac8SCy Schubert return 0;
52785732ac8SCy Schubert }
52885732ac8SCy Schubert
52985732ac8SCy Schubert
53085732ac8SCy Schubert #ifdef CONFIG_DES
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)53185732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
53285732ac8SCy Schubert {
53385732ac8SCy Schubert Des des;
53485732ac8SCy Schubert u8 pkey[8], next, tmp;
53585732ac8SCy Schubert int i;
53685732ac8SCy Schubert
53785732ac8SCy Schubert /* Add parity bits to the key */
53885732ac8SCy Schubert next = 0;
53985732ac8SCy Schubert for (i = 0; i < 7; i++) {
54085732ac8SCy Schubert tmp = key[i];
54185732ac8SCy Schubert pkey[i] = (tmp >> i) | next | 1;
54285732ac8SCy Schubert next = tmp << (7 - i);
54385732ac8SCy Schubert }
54485732ac8SCy Schubert pkey[i] = next | 1;
54585732ac8SCy Schubert
54685732ac8SCy Schubert wc_Des_SetKey(&des, pkey, NULL, DES_ENCRYPTION);
54785732ac8SCy Schubert wc_Des_EcbEncrypt(&des, cypher, clear, DES_BLOCK_SIZE);
54885732ac8SCy Schubert
54985732ac8SCy Schubert return 0;
55085732ac8SCy Schubert }
55185732ac8SCy Schubert #endif /* CONFIG_DES */
55285732ac8SCy Schubert
55385732ac8SCy Schubert
aes_encrypt_init(const u8 * key,size_t len)55485732ac8SCy Schubert void * aes_encrypt_init(const u8 *key, size_t len)
55585732ac8SCy Schubert {
55685732ac8SCy Schubert Aes *aes;
557*a90b9d01SCy Schubert int err;
55885732ac8SCy Schubert
55985732ac8SCy Schubert if (TEST_FAIL())
56085732ac8SCy Schubert return NULL;
56185732ac8SCy Schubert
56285732ac8SCy Schubert aes = os_malloc(sizeof(Aes));
563*a90b9d01SCy Schubert if (!aes) {
564*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
56585732ac8SCy Schubert return NULL;
566*a90b9d01SCy Schubert }
56785732ac8SCy Schubert
568*a90b9d01SCy Schubert err = wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION);
569*a90b9d01SCy Schubert if (err < 0) {
570*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_AesSetKey, err);
57185732ac8SCy Schubert os_free(aes);
57285732ac8SCy Schubert return NULL;
57385732ac8SCy Schubert }
57485732ac8SCy Schubert
57585732ac8SCy Schubert return aes;
57685732ac8SCy Schubert }
57785732ac8SCy Schubert
57885732ac8SCy Schubert
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)57985732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
58085732ac8SCy Schubert {
581*a90b9d01SCy Schubert #if defined(HAVE_FIPS) && \
582*a90b9d01SCy Schubert (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2))
583*a90b9d01SCy Schubert /* Old FIPS has void return on this API */
58485732ac8SCy Schubert wc_AesEncryptDirect(ctx, crypt, plain);
585*a90b9d01SCy Schubert #else
586*a90b9d01SCy Schubert int err = wc_AesEncryptDirect(ctx, crypt, plain);
587*a90b9d01SCy Schubert
588*a90b9d01SCy Schubert if (err != 0) {
589*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_AesEncryptDirect, err);
590*a90b9d01SCy Schubert return -1;
591*a90b9d01SCy Schubert }
592*a90b9d01SCy Schubert #endif
59385732ac8SCy Schubert return 0;
59485732ac8SCy Schubert }
59585732ac8SCy Schubert
59685732ac8SCy Schubert
aes_encrypt_deinit(void * ctx)59785732ac8SCy Schubert void aes_encrypt_deinit(void *ctx)
59885732ac8SCy Schubert {
59985732ac8SCy Schubert os_free(ctx);
60085732ac8SCy Schubert }
60185732ac8SCy Schubert
60285732ac8SCy Schubert
aes_decrypt_init(const u8 * key,size_t len)60385732ac8SCy Schubert void * aes_decrypt_init(const u8 *key, size_t len)
60485732ac8SCy Schubert {
60585732ac8SCy Schubert Aes *aes;
606*a90b9d01SCy Schubert int err;
60785732ac8SCy Schubert
60885732ac8SCy Schubert if (TEST_FAIL())
60985732ac8SCy Schubert return NULL;
61085732ac8SCy Schubert
61185732ac8SCy Schubert aes = os_malloc(sizeof(Aes));
612*a90b9d01SCy Schubert if (!aes) {
613*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
61485732ac8SCy Schubert return NULL;
615*a90b9d01SCy Schubert }
61685732ac8SCy Schubert
617*a90b9d01SCy Schubert err = wc_AesSetKey(aes, key, len, NULL, AES_DECRYPTION);
618*a90b9d01SCy Schubert if (err < 0) {
619*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_AesSetKey, err);
62085732ac8SCy Schubert os_free(aes);
62185732ac8SCy Schubert return NULL;
62285732ac8SCy Schubert }
62385732ac8SCy Schubert
62485732ac8SCy Schubert return aes;
62585732ac8SCy Schubert }
62685732ac8SCy Schubert
62785732ac8SCy Schubert
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)62885732ac8SCy Schubert int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
62985732ac8SCy Schubert {
630*a90b9d01SCy Schubert #if defined(HAVE_FIPS) && \
631*a90b9d01SCy Schubert (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2))
632*a90b9d01SCy Schubert /* Old FIPS has void return on this API */
63385732ac8SCy Schubert wc_AesDecryptDirect(ctx, plain, crypt);
634*a90b9d01SCy Schubert #else
635*a90b9d01SCy Schubert int err = wc_AesDecryptDirect(ctx, plain, crypt);
636*a90b9d01SCy Schubert
637*a90b9d01SCy Schubert if (err != 0) {
638*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_AesDecryptDirect, err);
639*a90b9d01SCy Schubert return -1;
640*a90b9d01SCy Schubert }
641*a90b9d01SCy Schubert #endif
64285732ac8SCy Schubert return 0;
64385732ac8SCy Schubert }
64485732ac8SCy Schubert
64585732ac8SCy Schubert
aes_decrypt_deinit(void * ctx)64685732ac8SCy Schubert void aes_decrypt_deinit(void *ctx)
64785732ac8SCy Schubert {
64885732ac8SCy Schubert os_free(ctx);
64985732ac8SCy Schubert }
65085732ac8SCy Schubert
65185732ac8SCy Schubert
aes_128_cbc_encrypt(const u8 * key,const u8 * iv,u8 * data,size_t data_len)65285732ac8SCy Schubert int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
65385732ac8SCy Schubert {
65485732ac8SCy Schubert Aes aes;
65585732ac8SCy Schubert int ret;
65685732ac8SCy Schubert
65785732ac8SCy Schubert if (TEST_FAIL())
65885732ac8SCy Schubert return -1;
65985732ac8SCy Schubert
66085732ac8SCy Schubert ret = wc_AesSetKey(&aes, key, 16, iv, AES_ENCRYPTION);
66185732ac8SCy Schubert if (ret != 0)
66285732ac8SCy Schubert return -1;
66385732ac8SCy Schubert
66485732ac8SCy Schubert ret = wc_AesCbcEncrypt(&aes, data, data, data_len);
66585732ac8SCy Schubert if (ret != 0)
66685732ac8SCy Schubert return -1;
66785732ac8SCy Schubert return 0;
66885732ac8SCy Schubert }
66985732ac8SCy Schubert
67085732ac8SCy Schubert
aes_128_cbc_decrypt(const u8 * key,const u8 * iv,u8 * data,size_t data_len)67185732ac8SCy Schubert int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
67285732ac8SCy Schubert {
67385732ac8SCy Schubert Aes aes;
67485732ac8SCy Schubert int ret;
67585732ac8SCy Schubert
67685732ac8SCy Schubert if (TEST_FAIL())
67785732ac8SCy Schubert return -1;
67885732ac8SCy Schubert
67985732ac8SCy Schubert ret = wc_AesSetKey(&aes, key, 16, iv, AES_DECRYPTION);
68085732ac8SCy Schubert if (ret != 0)
68185732ac8SCy Schubert return -1;
68285732ac8SCy Schubert
68385732ac8SCy Schubert ret = wc_AesCbcDecrypt(&aes, data, data, data_len);
68485732ac8SCy Schubert if (ret != 0)
68585732ac8SCy Schubert return -1;
68685732ac8SCy Schubert return 0;
68785732ac8SCy Schubert }
68885732ac8SCy Schubert
68985732ac8SCy Schubert
690*a90b9d01SCy Schubert #ifndef CONFIG_FIPS
691*a90b9d01SCy Schubert #ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP
aes_wrap(const u8 * kek,size_t kek_len,int n,const u8 * plain,u8 * cipher)69285732ac8SCy Schubert int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
69385732ac8SCy Schubert {
694*a90b9d01SCy Schubert #ifdef HAVE_AES_KEYWRAP
69585732ac8SCy Schubert int ret;
69685732ac8SCy Schubert
69785732ac8SCy Schubert if (TEST_FAIL())
69885732ac8SCy Schubert return -1;
69985732ac8SCy Schubert
70085732ac8SCy Schubert ret = wc_AesKeyWrap(kek, kek_len, plain, n * 8, cipher, (n + 1) * 8,
70185732ac8SCy Schubert NULL);
70285732ac8SCy Schubert return ret != (n + 1) * 8 ? -1 : 0;
703*a90b9d01SCy Schubert #else /* HAVE_AES_KEYWRAP */
704*a90b9d01SCy Schubert return -1;
705*a90b9d01SCy Schubert #endif /* HAVE_AES_KEYWRAP */
70685732ac8SCy Schubert }
70785732ac8SCy Schubert
70885732ac8SCy Schubert
aes_unwrap(const u8 * kek,size_t kek_len,int n,const u8 * cipher,u8 * plain)70985732ac8SCy Schubert int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
71085732ac8SCy Schubert u8 *plain)
71185732ac8SCy Schubert {
712*a90b9d01SCy Schubert #ifdef HAVE_AES_KEYWRAP
71385732ac8SCy Schubert int ret;
71485732ac8SCy Schubert
71585732ac8SCy Schubert if (TEST_FAIL())
71685732ac8SCy Schubert return -1;
71785732ac8SCy Schubert
71885732ac8SCy Schubert ret = wc_AesKeyUnWrap(kek, kek_len, cipher, (n + 1) * 8, plain, n * 8,
71985732ac8SCy Schubert NULL);
72085732ac8SCy Schubert return ret != n * 8 ? -1 : 0;
721*a90b9d01SCy Schubert #else /* HAVE_AES_KEYWRAP */
722*a90b9d01SCy Schubert return -1;
723*a90b9d01SCy Schubert #endif /* HAVE_AES_KEYWRAP */
72485732ac8SCy Schubert }
725*a90b9d01SCy Schubert #endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */
726*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
72785732ac8SCy Schubert
72885732ac8SCy Schubert
72985732ac8SCy Schubert #ifndef CONFIG_NO_RC4
rc4_skip(const u8 * key,size_t keylen,size_t skip,u8 * data,size_t data_len)73085732ac8SCy Schubert int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data,
73185732ac8SCy Schubert size_t data_len)
73285732ac8SCy Schubert {
73385732ac8SCy Schubert #ifndef NO_RC4
73485732ac8SCy Schubert Arc4 arc4;
73585732ac8SCy Schubert unsigned char skip_buf[16];
73685732ac8SCy Schubert
73785732ac8SCy Schubert wc_Arc4SetKey(&arc4, key, keylen);
73885732ac8SCy Schubert
73985732ac8SCy Schubert while (skip >= sizeof(skip_buf)) {
74085732ac8SCy Schubert size_t len = skip;
74185732ac8SCy Schubert
74285732ac8SCy Schubert if (len > sizeof(skip_buf))
74385732ac8SCy Schubert len = sizeof(skip_buf);
74485732ac8SCy Schubert wc_Arc4Process(&arc4, skip_buf, skip_buf, len);
74585732ac8SCy Schubert skip -= len;
74685732ac8SCy Schubert }
74785732ac8SCy Schubert
74885732ac8SCy Schubert wc_Arc4Process(&arc4, data, data, data_len);
74985732ac8SCy Schubert
75085732ac8SCy Schubert return 0;
75185732ac8SCy Schubert #else /* NO_RC4 */
75285732ac8SCy Schubert return -1;
75385732ac8SCy Schubert #endif /* NO_RC4 */
75485732ac8SCy Schubert }
75585732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
75685732ac8SCy Schubert
75785732ac8SCy Schubert
75885732ac8SCy Schubert #if defined(EAP_IKEV2) || defined(EAP_IKEV2_DYNAMIC) \
75985732ac8SCy Schubert || defined(EAP_SERVER_IKEV2)
76085732ac8SCy Schubert union wolfssl_cipher {
76185732ac8SCy Schubert Aes aes;
76285732ac8SCy Schubert Des3 des3;
76385732ac8SCy Schubert Arc4 arc4;
76485732ac8SCy Schubert };
76585732ac8SCy Schubert
76685732ac8SCy Schubert struct crypto_cipher {
76785732ac8SCy Schubert enum crypto_cipher_alg alg;
76885732ac8SCy Schubert union wolfssl_cipher enc;
76985732ac8SCy Schubert union wolfssl_cipher dec;
77085732ac8SCy Schubert };
77185732ac8SCy Schubert
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)77285732ac8SCy Schubert struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
77385732ac8SCy Schubert const u8 *iv, const u8 *key,
77485732ac8SCy Schubert size_t key_len)
77585732ac8SCy Schubert {
77685732ac8SCy Schubert struct crypto_cipher *ctx;
77785732ac8SCy Schubert
77885732ac8SCy Schubert ctx = os_zalloc(sizeof(*ctx));
77985732ac8SCy Schubert if (!ctx)
78085732ac8SCy Schubert return NULL;
78185732ac8SCy Schubert
78285732ac8SCy Schubert switch (alg) {
78385732ac8SCy Schubert #ifndef CONFIG_NO_RC4
78485732ac8SCy Schubert #ifndef NO_RC4
78585732ac8SCy Schubert case CRYPTO_CIPHER_ALG_RC4:
78685732ac8SCy Schubert wc_Arc4SetKey(&ctx->enc.arc4, key, key_len);
78785732ac8SCy Schubert wc_Arc4SetKey(&ctx->dec.arc4, key, key_len);
78885732ac8SCy Schubert break;
78985732ac8SCy Schubert #endif /* NO_RC4 */
79085732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
79185732ac8SCy Schubert #ifndef NO_AES
79285732ac8SCy Schubert case CRYPTO_CIPHER_ALG_AES:
79385732ac8SCy Schubert switch (key_len) {
79485732ac8SCy Schubert case 16:
79585732ac8SCy Schubert case 24:
79685732ac8SCy Schubert case 32:
79785732ac8SCy Schubert break;
79885732ac8SCy Schubert default:
79985732ac8SCy Schubert os_free(ctx);
80085732ac8SCy Schubert return NULL;
80185732ac8SCy Schubert }
80285732ac8SCy Schubert if (wc_AesSetKey(&ctx->enc.aes, key, key_len, iv,
80385732ac8SCy Schubert AES_ENCRYPTION) ||
80485732ac8SCy Schubert wc_AesSetKey(&ctx->dec.aes, key, key_len, iv,
80585732ac8SCy Schubert AES_DECRYPTION)) {
80685732ac8SCy Schubert os_free(ctx);
80785732ac8SCy Schubert return NULL;
80885732ac8SCy Schubert }
80985732ac8SCy Schubert break;
81085732ac8SCy Schubert #endif /* NO_AES */
81185732ac8SCy Schubert #ifndef NO_DES3
81285732ac8SCy Schubert case CRYPTO_CIPHER_ALG_3DES:
81385732ac8SCy Schubert if (key_len != DES3_KEYLEN ||
81485732ac8SCy Schubert wc_Des3_SetKey(&ctx->enc.des3, key, iv, DES_ENCRYPTION) ||
81585732ac8SCy Schubert wc_Des3_SetKey(&ctx->dec.des3, key, iv, DES_DECRYPTION)) {
81685732ac8SCy Schubert os_free(ctx);
81785732ac8SCy Schubert return NULL;
81885732ac8SCy Schubert }
81985732ac8SCy Schubert break;
82085732ac8SCy Schubert #endif /* NO_DES3 */
82185732ac8SCy Schubert case CRYPTO_CIPHER_ALG_RC2:
82285732ac8SCy Schubert case CRYPTO_CIPHER_ALG_DES:
82385732ac8SCy Schubert default:
82485732ac8SCy Schubert os_free(ctx);
82585732ac8SCy Schubert return NULL;
82685732ac8SCy Schubert }
82785732ac8SCy Schubert
82885732ac8SCy Schubert ctx->alg = alg;
82985732ac8SCy Schubert
83085732ac8SCy Schubert return ctx;
83185732ac8SCy Schubert }
83285732ac8SCy Schubert
83385732ac8SCy Schubert
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)83485732ac8SCy Schubert int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
83585732ac8SCy Schubert u8 *crypt, size_t len)
83685732ac8SCy Schubert {
83785732ac8SCy Schubert switch (ctx->alg) {
83885732ac8SCy Schubert #ifndef CONFIG_NO_RC4
83985732ac8SCy Schubert #ifndef NO_RC4
84085732ac8SCy Schubert case CRYPTO_CIPHER_ALG_RC4:
84185732ac8SCy Schubert wc_Arc4Process(&ctx->enc.arc4, crypt, plain, len);
84285732ac8SCy Schubert return 0;
84385732ac8SCy Schubert #endif /* NO_RC4 */
84485732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
84585732ac8SCy Schubert #ifndef NO_AES
84685732ac8SCy Schubert case CRYPTO_CIPHER_ALG_AES:
84785732ac8SCy Schubert if (wc_AesCbcEncrypt(&ctx->enc.aes, crypt, plain, len) != 0)
84885732ac8SCy Schubert return -1;
84985732ac8SCy Schubert return 0;
85085732ac8SCy Schubert #endif /* NO_AES */
85185732ac8SCy Schubert #ifndef NO_DES3
85285732ac8SCy Schubert case CRYPTO_CIPHER_ALG_3DES:
85385732ac8SCy Schubert if (wc_Des3_CbcEncrypt(&ctx->enc.des3, crypt, plain, len) != 0)
85485732ac8SCy Schubert return -1;
85585732ac8SCy Schubert return 0;
85685732ac8SCy Schubert #endif /* NO_DES3 */
85785732ac8SCy Schubert default:
85885732ac8SCy Schubert return -1;
85985732ac8SCy Schubert }
86085732ac8SCy Schubert return -1;
86185732ac8SCy Schubert }
86285732ac8SCy Schubert
86385732ac8SCy Schubert
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)86485732ac8SCy Schubert int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
86585732ac8SCy Schubert u8 *plain, size_t len)
86685732ac8SCy Schubert {
86785732ac8SCy Schubert switch (ctx->alg) {
86885732ac8SCy Schubert #ifndef CONFIG_NO_RC4
86985732ac8SCy Schubert #ifndef NO_RC4
87085732ac8SCy Schubert case CRYPTO_CIPHER_ALG_RC4:
87185732ac8SCy Schubert wc_Arc4Process(&ctx->dec.arc4, plain, crypt, len);
87285732ac8SCy Schubert return 0;
87385732ac8SCy Schubert #endif /* NO_RC4 */
87485732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
87585732ac8SCy Schubert #ifndef NO_AES
87685732ac8SCy Schubert case CRYPTO_CIPHER_ALG_AES:
87785732ac8SCy Schubert if (wc_AesCbcDecrypt(&ctx->dec.aes, plain, crypt, len) != 0)
87885732ac8SCy Schubert return -1;
87985732ac8SCy Schubert return 0;
88085732ac8SCy Schubert #endif /* NO_AES */
88185732ac8SCy Schubert #ifndef NO_DES3
88285732ac8SCy Schubert case CRYPTO_CIPHER_ALG_3DES:
88385732ac8SCy Schubert if (wc_Des3_CbcDecrypt(&ctx->dec.des3, plain, crypt, len) != 0)
88485732ac8SCy Schubert return -1;
88585732ac8SCy Schubert return 0;
88685732ac8SCy Schubert #endif /* NO_DES3 */
88785732ac8SCy Schubert default:
88885732ac8SCy Schubert return -1;
88985732ac8SCy Schubert }
89085732ac8SCy Schubert return -1;
89185732ac8SCy Schubert }
89285732ac8SCy Schubert
89385732ac8SCy Schubert
crypto_cipher_deinit(struct crypto_cipher * ctx)89485732ac8SCy Schubert void crypto_cipher_deinit(struct crypto_cipher *ctx)
89585732ac8SCy Schubert {
89685732ac8SCy Schubert os_free(ctx);
89785732ac8SCy Schubert }
89885732ac8SCy Schubert
89985732ac8SCy Schubert #endif
90085732ac8SCy Schubert
90185732ac8SCy Schubert
9024b72b91aSCy Schubert #ifdef CONFIG_WPS
90385732ac8SCy Schubert
90485732ac8SCy Schubert static const unsigned char RFC3526_PRIME_1536[] = {
90585732ac8SCy Schubert 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
90685732ac8SCy Schubert 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
90785732ac8SCy Schubert 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
90885732ac8SCy Schubert 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
90985732ac8SCy Schubert 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
91085732ac8SCy Schubert 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
91185732ac8SCy Schubert 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
91285732ac8SCy Schubert 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
91385732ac8SCy Schubert 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
91485732ac8SCy Schubert 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
91585732ac8SCy Schubert 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
91685732ac8SCy Schubert 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
91785732ac8SCy Schubert 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
91885732ac8SCy Schubert 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
91985732ac8SCy Schubert 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
92085732ac8SCy Schubert 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
92185732ac8SCy Schubert };
92285732ac8SCy Schubert
92385732ac8SCy Schubert static const unsigned char RFC3526_GENERATOR_1536[] = {
92485732ac8SCy Schubert 0x02
92585732ac8SCy Schubert };
92685732ac8SCy Schubert
92785732ac8SCy Schubert #define RFC3526_LEN sizeof(RFC3526_PRIME_1536)
92885732ac8SCy Schubert
92985732ac8SCy Schubert
dh5_init(struct wpabuf ** priv,struct wpabuf ** publ)93085732ac8SCy Schubert void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
93185732ac8SCy Schubert {
93285732ac8SCy Schubert WC_RNG rng;
93385732ac8SCy Schubert DhKey *ret = NULL;
93485732ac8SCy Schubert DhKey *dh = NULL;
93585732ac8SCy Schubert struct wpabuf *privkey = NULL;
93685732ac8SCy Schubert struct wpabuf *pubkey = NULL;
93785732ac8SCy Schubert word32 priv_sz, pub_sz;
93885732ac8SCy Schubert
93985732ac8SCy Schubert *priv = NULL;
94085732ac8SCy Schubert wpabuf_free(*publ);
94185732ac8SCy Schubert *publ = NULL;
94285732ac8SCy Schubert
94385732ac8SCy Schubert dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
94485732ac8SCy Schubert if (!dh)
94585732ac8SCy Schubert return NULL;
94685732ac8SCy Schubert wc_InitDhKey(dh);
94785732ac8SCy Schubert
94885732ac8SCy Schubert if (wc_InitRng(&rng) != 0) {
94985732ac8SCy Schubert XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
95085732ac8SCy Schubert return NULL;
95185732ac8SCy Schubert }
95285732ac8SCy Schubert
95385732ac8SCy Schubert privkey = wpabuf_alloc(RFC3526_LEN);
95485732ac8SCy Schubert pubkey = wpabuf_alloc(RFC3526_LEN);
95585732ac8SCy Schubert if (!privkey || !pubkey)
95685732ac8SCy Schubert goto done;
95785732ac8SCy Schubert
95885732ac8SCy Schubert if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
95985732ac8SCy Schubert RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
96085732ac8SCy Schubert != 0)
96185732ac8SCy Schubert goto done;
96285732ac8SCy Schubert
963*a90b9d01SCy Schubert priv_sz = pub_sz = RFC3526_LEN;
96485732ac8SCy Schubert if (wc_DhGenerateKeyPair(dh, &rng, wpabuf_mhead(privkey), &priv_sz,
96585732ac8SCy Schubert wpabuf_mhead(pubkey), &pub_sz) != 0)
96685732ac8SCy Schubert goto done;
96785732ac8SCy Schubert
96885732ac8SCy Schubert wpabuf_put(privkey, priv_sz);
96985732ac8SCy Schubert wpabuf_put(pubkey, pub_sz);
97085732ac8SCy Schubert
97185732ac8SCy Schubert ret = dh;
97285732ac8SCy Schubert *priv = privkey;
97385732ac8SCy Schubert *publ = pubkey;
97485732ac8SCy Schubert dh = NULL;
97585732ac8SCy Schubert privkey = NULL;
97685732ac8SCy Schubert pubkey = NULL;
97785732ac8SCy Schubert done:
97885732ac8SCy Schubert wpabuf_clear_free(pubkey);
97985732ac8SCy Schubert wpabuf_clear_free(privkey);
98085732ac8SCy Schubert if (dh) {
98185732ac8SCy Schubert wc_FreeDhKey(dh);
98285732ac8SCy Schubert XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
98385732ac8SCy Schubert }
98485732ac8SCy Schubert wc_FreeRng(&rng);
98585732ac8SCy Schubert return ret;
98685732ac8SCy Schubert }
98785732ac8SCy Schubert
98885732ac8SCy Schubert
9894b72b91aSCy Schubert #ifdef CONFIG_WPS_NFC
9904b72b91aSCy Schubert
dh5_init_fixed(const struct wpabuf * priv,const struct wpabuf * publ)99185732ac8SCy Schubert void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
99285732ac8SCy Schubert {
99385732ac8SCy Schubert DhKey *ret = NULL;
99485732ac8SCy Schubert DhKey *dh;
99585732ac8SCy Schubert byte *secret;
99685732ac8SCy Schubert word32 secret_sz;
99785732ac8SCy Schubert
99885732ac8SCy Schubert dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
99985732ac8SCy Schubert if (!dh)
100085732ac8SCy Schubert return NULL;
100185732ac8SCy Schubert wc_InitDhKey(dh);
100285732ac8SCy Schubert
100385732ac8SCy Schubert secret = XMALLOC(RFC3526_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER);
100485732ac8SCy Schubert if (!secret)
100585732ac8SCy Schubert goto done;
100685732ac8SCy Schubert
100785732ac8SCy Schubert if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
100885732ac8SCy Schubert RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
100985732ac8SCy Schubert != 0)
101085732ac8SCy Schubert goto done;
101185732ac8SCy Schubert
101285732ac8SCy Schubert if (wc_DhAgree(dh, secret, &secret_sz, wpabuf_head(priv),
101385732ac8SCy Schubert wpabuf_len(priv), RFC3526_GENERATOR_1536,
101485732ac8SCy Schubert sizeof(RFC3526_GENERATOR_1536)) != 0)
101585732ac8SCy Schubert goto done;
101685732ac8SCy Schubert
101785732ac8SCy Schubert if (secret_sz != wpabuf_len(publ) ||
101885732ac8SCy Schubert os_memcmp(secret, wpabuf_head(publ), secret_sz) != 0)
101985732ac8SCy Schubert goto done;
102085732ac8SCy Schubert
102185732ac8SCy Schubert ret = dh;
102285732ac8SCy Schubert dh = NULL;
102385732ac8SCy Schubert done:
102485732ac8SCy Schubert if (dh) {
102585732ac8SCy Schubert wc_FreeDhKey(dh);
102685732ac8SCy Schubert XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
102785732ac8SCy Schubert }
102885732ac8SCy Schubert XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
102985732ac8SCy Schubert return ret;
103085732ac8SCy Schubert }
103185732ac8SCy Schubert
10324b72b91aSCy Schubert #endif /* CONFIG_WPS_NFC */
10334b72b91aSCy Schubert
103485732ac8SCy Schubert
dh5_derive_shared(void * ctx,const struct wpabuf * peer_public,const struct wpabuf * own_private)103585732ac8SCy Schubert struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
103685732ac8SCy Schubert const struct wpabuf *own_private)
103785732ac8SCy Schubert {
103885732ac8SCy Schubert struct wpabuf *ret = NULL;
103985732ac8SCy Schubert struct wpabuf *secret;
104085732ac8SCy Schubert word32 secret_sz;
104185732ac8SCy Schubert
104285732ac8SCy Schubert secret = wpabuf_alloc(RFC3526_LEN);
104385732ac8SCy Schubert if (!secret)
104485732ac8SCy Schubert goto done;
104585732ac8SCy Schubert
104685732ac8SCy Schubert if (wc_DhAgree(ctx, wpabuf_mhead(secret), &secret_sz,
104785732ac8SCy Schubert wpabuf_head(own_private), wpabuf_len(own_private),
104885732ac8SCy Schubert wpabuf_head(peer_public), wpabuf_len(peer_public)) != 0)
104985732ac8SCy Schubert goto done;
105085732ac8SCy Schubert
105185732ac8SCy Schubert wpabuf_put(secret, secret_sz);
105285732ac8SCy Schubert
105385732ac8SCy Schubert ret = secret;
105485732ac8SCy Schubert secret = NULL;
105585732ac8SCy Schubert done:
105685732ac8SCy Schubert wpabuf_clear_free(secret);
105785732ac8SCy Schubert return ret;
105885732ac8SCy Schubert }
105985732ac8SCy Schubert
106085732ac8SCy Schubert
dh5_free(void * ctx)106185732ac8SCy Schubert void dh5_free(void *ctx)
106285732ac8SCy Schubert {
106385732ac8SCy Schubert if (!ctx)
106485732ac8SCy Schubert return;
106585732ac8SCy Schubert
106685732ac8SCy Schubert wc_FreeDhKey(ctx);
106785732ac8SCy Schubert XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
106885732ac8SCy Schubert }
106985732ac8SCy Schubert
10704b72b91aSCy Schubert #endif /* CONFIG_WPS */
107185732ac8SCy Schubert
107285732ac8SCy Schubert
crypto_dh_init(u8 generator,const u8 * prime,size_t prime_len,u8 * privkey,u8 * pubkey)107385732ac8SCy Schubert int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
107485732ac8SCy Schubert u8 *pubkey)
107585732ac8SCy Schubert {
107685732ac8SCy Schubert int ret = -1;
107785732ac8SCy Schubert WC_RNG rng;
107885732ac8SCy Schubert DhKey *dh = NULL;
107985732ac8SCy Schubert word32 priv_sz, pub_sz;
108085732ac8SCy Schubert
108185732ac8SCy Schubert if (TEST_FAIL())
108285732ac8SCy Schubert return -1;
108385732ac8SCy Schubert
108485732ac8SCy Schubert dh = os_malloc(sizeof(DhKey));
108585732ac8SCy Schubert if (!dh)
108685732ac8SCy Schubert return -1;
108785732ac8SCy Schubert wc_InitDhKey(dh);
108885732ac8SCy Schubert
108985732ac8SCy Schubert if (wc_InitRng(&rng) != 0) {
109085732ac8SCy Schubert os_free(dh);
109185732ac8SCy Schubert return -1;
109285732ac8SCy Schubert }
109385732ac8SCy Schubert
109485732ac8SCy Schubert if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
109585732ac8SCy Schubert goto done;
109685732ac8SCy Schubert
1097*a90b9d01SCy Schubert priv_sz = pub_sz = prime_len;
109885732ac8SCy Schubert if (wc_DhGenerateKeyPair(dh, &rng, privkey, &priv_sz, pubkey, &pub_sz)
109985732ac8SCy Schubert != 0)
110085732ac8SCy Schubert goto done;
110185732ac8SCy Schubert
110285732ac8SCy Schubert if (priv_sz < prime_len) {
110385732ac8SCy Schubert size_t pad_sz = prime_len - priv_sz;
110485732ac8SCy Schubert
110585732ac8SCy Schubert os_memmove(privkey + pad_sz, privkey, priv_sz);
110685732ac8SCy Schubert os_memset(privkey, 0, pad_sz);
110785732ac8SCy Schubert }
110885732ac8SCy Schubert
110985732ac8SCy Schubert if (pub_sz < prime_len) {
111085732ac8SCy Schubert size_t pad_sz = prime_len - pub_sz;
111185732ac8SCy Schubert
111285732ac8SCy Schubert os_memmove(pubkey + pad_sz, pubkey, pub_sz);
111385732ac8SCy Schubert os_memset(pubkey, 0, pad_sz);
111485732ac8SCy Schubert }
111585732ac8SCy Schubert ret = 0;
111685732ac8SCy Schubert done:
111785732ac8SCy Schubert wc_FreeDhKey(dh);
111885732ac8SCy Schubert os_free(dh);
111985732ac8SCy Schubert wc_FreeRng(&rng);
112085732ac8SCy Schubert return ret;
112185732ac8SCy Schubert }
112285732ac8SCy Schubert
112385732ac8SCy Schubert
crypto_dh_derive_secret(u8 generator,const u8 * prime,size_t prime_len,const u8 * order,size_t order_len,const u8 * privkey,size_t privkey_len,const u8 * pubkey,size_t pubkey_len,u8 * secret,size_t * len)112485732ac8SCy Schubert int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
11254bc52338SCy Schubert const u8 *order, size_t order_len,
112685732ac8SCy Schubert const u8 *privkey, size_t privkey_len,
112785732ac8SCy Schubert const u8 *pubkey, size_t pubkey_len,
112885732ac8SCy Schubert u8 *secret, size_t *len)
112985732ac8SCy Schubert {
113085732ac8SCy Schubert int ret = -1;
113185732ac8SCy Schubert DhKey *dh;
113285732ac8SCy Schubert word32 secret_sz;
113385732ac8SCy Schubert
113485732ac8SCy Schubert dh = os_malloc(sizeof(DhKey));
113585732ac8SCy Schubert if (!dh)
113685732ac8SCy Schubert return -1;
113785732ac8SCy Schubert wc_InitDhKey(dh);
113885732ac8SCy Schubert
113985732ac8SCy Schubert if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
114085732ac8SCy Schubert goto done;
114185732ac8SCy Schubert
114285732ac8SCy Schubert if (wc_DhAgree(dh, secret, &secret_sz, privkey, privkey_len, pubkey,
114385732ac8SCy Schubert pubkey_len) != 0)
114485732ac8SCy Schubert goto done;
114585732ac8SCy Schubert
114685732ac8SCy Schubert *len = secret_sz;
114785732ac8SCy Schubert ret = 0;
114885732ac8SCy Schubert done:
114985732ac8SCy Schubert wc_FreeDhKey(dh);
115085732ac8SCy Schubert os_free(dh);
115185732ac8SCy Schubert return ret;
115285732ac8SCy Schubert }
115385732ac8SCy Schubert
115485732ac8SCy Schubert
115585732ac8SCy Schubert #ifdef CONFIG_FIPS
crypto_get_random(void * buf,size_t len)115685732ac8SCy Schubert int crypto_get_random(void *buf, size_t len)
115785732ac8SCy Schubert {
115885732ac8SCy Schubert int ret = 0;
115985732ac8SCy Schubert WC_RNG rng;
116085732ac8SCy Schubert
116185732ac8SCy Schubert if (wc_InitRng(&rng) != 0)
116285732ac8SCy Schubert return -1;
116385732ac8SCy Schubert if (wc_RNG_GenerateBlock(&rng, buf, len) != 0)
116485732ac8SCy Schubert ret = -1;
116585732ac8SCy Schubert wc_FreeRng(&rng);
116685732ac8SCy Schubert return ret;
116785732ac8SCy Schubert }
116885732ac8SCy Schubert #endif /* CONFIG_FIPS */
116985732ac8SCy Schubert
117085732ac8SCy Schubert
117185732ac8SCy Schubert #if defined(EAP_PWD) || defined(EAP_SERVER_PWD)
117285732ac8SCy Schubert struct crypto_hash {
117385732ac8SCy Schubert Hmac hmac;
117485732ac8SCy Schubert int size;
117585732ac8SCy Schubert };
117685732ac8SCy Schubert
117785732ac8SCy Schubert
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)117885732ac8SCy Schubert struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
117985732ac8SCy Schubert size_t key_len)
118085732ac8SCy Schubert {
118185732ac8SCy Schubert struct crypto_hash *ret = NULL;
118285732ac8SCy Schubert struct crypto_hash *hash;
118385732ac8SCy Schubert int type;
118485732ac8SCy Schubert
118585732ac8SCy Schubert hash = os_zalloc(sizeof(*hash));
118685732ac8SCy Schubert if (!hash)
118785732ac8SCy Schubert goto done;
118885732ac8SCy Schubert
118985732ac8SCy Schubert switch (alg) {
119085732ac8SCy Schubert #ifndef NO_MD5
119185732ac8SCy Schubert case CRYPTO_HASH_ALG_HMAC_MD5:
119285732ac8SCy Schubert hash->size = 16;
119385732ac8SCy Schubert type = WC_MD5;
119485732ac8SCy Schubert break;
119585732ac8SCy Schubert #endif /* NO_MD5 */
119685732ac8SCy Schubert #ifndef NO_SHA
119785732ac8SCy Schubert case CRYPTO_HASH_ALG_HMAC_SHA1:
119885732ac8SCy Schubert type = WC_SHA;
119985732ac8SCy Schubert hash->size = 20;
120085732ac8SCy Schubert break;
120185732ac8SCy Schubert #endif /* NO_SHA */
120285732ac8SCy Schubert #ifdef CONFIG_SHA256
120385732ac8SCy Schubert #ifndef NO_SHA256
120485732ac8SCy Schubert case CRYPTO_HASH_ALG_HMAC_SHA256:
120585732ac8SCy Schubert type = WC_SHA256;
120685732ac8SCy Schubert hash->size = 32;
120785732ac8SCy Schubert break;
120885732ac8SCy Schubert #endif /* NO_SHA256 */
120985732ac8SCy Schubert #endif /* CONFIG_SHA256 */
121085732ac8SCy Schubert default:
121185732ac8SCy Schubert goto done;
121285732ac8SCy Schubert }
121385732ac8SCy Schubert
1214*a90b9d01SCy Schubert if (wc_HmacInit(&hash->hmac, NULL, INVALID_DEVID) != 0 ||
1215*a90b9d01SCy Schubert wc_HmacSetKey(&hash->hmac, type, key, key_len) != 0)
121685732ac8SCy Schubert goto done;
121785732ac8SCy Schubert
121885732ac8SCy Schubert ret = hash;
121985732ac8SCy Schubert hash = NULL;
122085732ac8SCy Schubert done:
122185732ac8SCy Schubert os_free(hash);
122285732ac8SCy Schubert return ret;
122385732ac8SCy Schubert }
122485732ac8SCy Schubert
122585732ac8SCy Schubert
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)122685732ac8SCy Schubert void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
122785732ac8SCy Schubert {
122885732ac8SCy Schubert if (!ctx)
122985732ac8SCy Schubert return;
123085732ac8SCy Schubert wc_HmacUpdate(&ctx->hmac, data, len);
123185732ac8SCy Schubert }
123285732ac8SCy Schubert
123385732ac8SCy Schubert
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)123485732ac8SCy Schubert int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
123585732ac8SCy Schubert {
123685732ac8SCy Schubert int ret = 0;
123785732ac8SCy Schubert
123885732ac8SCy Schubert if (!ctx)
123985732ac8SCy Schubert return -2;
124085732ac8SCy Schubert
124185732ac8SCy Schubert if (!mac || !len)
124285732ac8SCy Schubert goto done;
124385732ac8SCy Schubert
124485732ac8SCy Schubert if (wc_HmacFinal(&ctx->hmac, mac) != 0) {
124585732ac8SCy Schubert ret = -1;
124685732ac8SCy Schubert goto done;
124785732ac8SCy Schubert }
124885732ac8SCy Schubert
124985732ac8SCy Schubert *len = ctx->size;
125085732ac8SCy Schubert ret = 0;
125185732ac8SCy Schubert done:
125285732ac8SCy Schubert bin_clear_free(ctx, sizeof(*ctx));
12534bc52338SCy Schubert if (TEST_FAIL())
12544bc52338SCy Schubert return -1;
125585732ac8SCy Schubert return ret;
125685732ac8SCy Schubert }
125785732ac8SCy Schubert
125885732ac8SCy Schubert #endif
125985732ac8SCy Schubert
126085732ac8SCy Schubert
omac1_aes_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)126185732ac8SCy Schubert int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
126285732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
126385732ac8SCy Schubert {
126485732ac8SCy Schubert Cmac cmac;
126585732ac8SCy Schubert size_t i;
126685732ac8SCy Schubert word32 sz;
126785732ac8SCy Schubert
126885732ac8SCy Schubert if (TEST_FAIL())
126985732ac8SCy Schubert return -1;
127085732ac8SCy Schubert
127185732ac8SCy Schubert if (wc_InitCmac(&cmac, key, key_len, WC_CMAC_AES, NULL) != 0)
127285732ac8SCy Schubert return -1;
127385732ac8SCy Schubert
127485732ac8SCy Schubert for (i = 0; i < num_elem; i++)
127585732ac8SCy Schubert if (wc_CmacUpdate(&cmac, addr[i], len[i]) != 0)
127685732ac8SCy Schubert return -1;
127785732ac8SCy Schubert
127885732ac8SCy Schubert sz = AES_BLOCK_SIZE;
127985732ac8SCy Schubert if (wc_CmacFinal(&cmac, mac, &sz) != 0 || sz != AES_BLOCK_SIZE)
128085732ac8SCy Schubert return -1;
128185732ac8SCy Schubert
128285732ac8SCy Schubert return 0;
128385732ac8SCy Schubert }
128485732ac8SCy Schubert
128585732ac8SCy Schubert
omac1_aes_128_vector(const u8 * key,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)128685732ac8SCy Schubert int omac1_aes_128_vector(const u8 *key, size_t num_elem,
128785732ac8SCy Schubert const u8 *addr[], const size_t *len, u8 *mac)
128885732ac8SCy Schubert {
128985732ac8SCy Schubert return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
129085732ac8SCy Schubert }
129185732ac8SCy Schubert
129285732ac8SCy Schubert
omac1_aes_128(const u8 * key,const u8 * data,size_t data_len,u8 * mac)129385732ac8SCy Schubert int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
129485732ac8SCy Schubert {
129585732ac8SCy Schubert return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
129685732ac8SCy Schubert }
129785732ac8SCy Schubert
129885732ac8SCy Schubert
omac1_aes_256(const u8 * key,const u8 * data,size_t data_len,u8 * mac)129985732ac8SCy Schubert int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
130085732ac8SCy Schubert {
130185732ac8SCy Schubert return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
130285732ac8SCy Schubert }
130385732ac8SCy Schubert
130485732ac8SCy Schubert
crypto_bignum_init(void)130585732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init(void)
130685732ac8SCy Schubert {
130785732ac8SCy Schubert mp_int *a;
130885732ac8SCy Schubert
130985732ac8SCy Schubert if (TEST_FAIL())
131085732ac8SCy Schubert return NULL;
131185732ac8SCy Schubert
131285732ac8SCy Schubert a = os_malloc(sizeof(*a));
131385732ac8SCy Schubert if (!a || mp_init(a) != MP_OKAY) {
131485732ac8SCy Schubert os_free(a);
131585732ac8SCy Schubert a = NULL;
131685732ac8SCy Schubert }
131785732ac8SCy Schubert
131885732ac8SCy Schubert return (struct crypto_bignum *) a;
131985732ac8SCy Schubert }
132085732ac8SCy Schubert
132185732ac8SCy Schubert
crypto_bignum_init_set(const u8 * buf,size_t len)132285732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
132385732ac8SCy Schubert {
132485732ac8SCy Schubert mp_int *a;
132585732ac8SCy Schubert
132685732ac8SCy Schubert if (TEST_FAIL())
132785732ac8SCy Schubert return NULL;
132885732ac8SCy Schubert
132985732ac8SCy Schubert a = (mp_int *) crypto_bignum_init();
133085732ac8SCy Schubert if (!a)
133185732ac8SCy Schubert return NULL;
133285732ac8SCy Schubert
133385732ac8SCy Schubert if (mp_read_unsigned_bin(a, buf, len) != MP_OKAY) {
133485732ac8SCy Schubert os_free(a);
133585732ac8SCy Schubert a = NULL;
133685732ac8SCy Schubert }
133785732ac8SCy Schubert
133885732ac8SCy Schubert return (struct crypto_bignum *) a;
133985732ac8SCy Schubert }
134085732ac8SCy Schubert
134185732ac8SCy Schubert
crypto_bignum_init_uint(unsigned int val)1342c1d255d3SCy Schubert struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
1343c1d255d3SCy Schubert {
1344c1d255d3SCy Schubert mp_int *a;
1345c1d255d3SCy Schubert
1346c1d255d3SCy Schubert if (TEST_FAIL())
1347c1d255d3SCy Schubert return NULL;
1348c1d255d3SCy Schubert
1349c1d255d3SCy Schubert a = (mp_int *) crypto_bignum_init();
1350c1d255d3SCy Schubert if (!a)
1351c1d255d3SCy Schubert return NULL;
1352c1d255d3SCy Schubert
1353c1d255d3SCy Schubert if (mp_set_int(a, val) != MP_OKAY) {
1354c1d255d3SCy Schubert os_free(a);
1355c1d255d3SCy Schubert a = NULL;
1356c1d255d3SCy Schubert }
1357c1d255d3SCy Schubert
1358c1d255d3SCy Schubert return (struct crypto_bignum *) a;
1359c1d255d3SCy Schubert }
1360c1d255d3SCy Schubert
1361c1d255d3SCy Schubert
crypto_bignum_deinit(struct crypto_bignum * n,int clear)136285732ac8SCy Schubert void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
136385732ac8SCy Schubert {
136485732ac8SCy Schubert if (!n)
136585732ac8SCy Schubert return;
136685732ac8SCy Schubert
136785732ac8SCy Schubert if (clear)
136885732ac8SCy Schubert mp_forcezero((mp_int *) n);
136985732ac8SCy Schubert mp_clear((mp_int *) n);
137085732ac8SCy Schubert os_free((mp_int *) n);
137185732ac8SCy Schubert }
137285732ac8SCy Schubert
137385732ac8SCy Schubert
crypto_bignum_to_bin(const struct crypto_bignum * a,u8 * buf,size_t buflen,size_t padlen)137485732ac8SCy Schubert int crypto_bignum_to_bin(const struct crypto_bignum *a,
137585732ac8SCy Schubert u8 *buf, size_t buflen, size_t padlen)
137685732ac8SCy Schubert {
137785732ac8SCy Schubert int num_bytes, offset;
137885732ac8SCy Schubert
137985732ac8SCy Schubert if (TEST_FAIL())
138085732ac8SCy Schubert return -1;
138185732ac8SCy Schubert
138285732ac8SCy Schubert if (padlen > buflen)
138385732ac8SCy Schubert return -1;
138485732ac8SCy Schubert
138585732ac8SCy Schubert num_bytes = (mp_count_bits((mp_int *) a) + 7) / 8;
138685732ac8SCy Schubert if ((size_t) num_bytes > buflen)
138785732ac8SCy Schubert return -1;
138885732ac8SCy Schubert if (padlen > (size_t) num_bytes)
138985732ac8SCy Schubert offset = padlen - num_bytes;
139085732ac8SCy Schubert else
139185732ac8SCy Schubert offset = 0;
139285732ac8SCy Schubert
139385732ac8SCy Schubert os_memset(buf, 0, offset);
139485732ac8SCy Schubert mp_to_unsigned_bin((mp_int *) a, buf + offset);
139585732ac8SCy Schubert
139685732ac8SCy Schubert return num_bytes + offset;
139785732ac8SCy Schubert }
139885732ac8SCy Schubert
139985732ac8SCy Schubert
crypto_bignum_rand(struct crypto_bignum * r,const struct crypto_bignum * m)140085732ac8SCy Schubert int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
140185732ac8SCy Schubert {
140285732ac8SCy Schubert int ret = 0;
140385732ac8SCy Schubert WC_RNG rng;
1404c1d255d3SCy Schubert size_t len;
1405c1d255d3SCy Schubert u8 *buf;
140685732ac8SCy Schubert
14074bc52338SCy Schubert if (TEST_FAIL())
14084bc52338SCy Schubert return -1;
140985732ac8SCy Schubert if (wc_InitRng(&rng) != 0)
141085732ac8SCy Schubert return -1;
1411c1d255d3SCy Schubert len = (mp_count_bits((mp_int *) m) + 7) / 8;
1412c1d255d3SCy Schubert buf = os_malloc(len);
1413c1d255d3SCy Schubert if (!buf || wc_RNG_GenerateBlock(&rng, buf, len) != 0 ||
1414c1d255d3SCy Schubert mp_read_unsigned_bin((mp_int *) r, buf, len) != MP_OKAY ||
141585732ac8SCy Schubert mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0)
141685732ac8SCy Schubert ret = -1;
141785732ac8SCy Schubert wc_FreeRng(&rng);
1418c1d255d3SCy Schubert bin_clear_free(buf, len);
141985732ac8SCy Schubert return ret;
142085732ac8SCy Schubert }
142185732ac8SCy Schubert
142285732ac8SCy Schubert
crypto_bignum_add(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * r)142385732ac8SCy Schubert int crypto_bignum_add(const struct crypto_bignum *a,
142485732ac8SCy Schubert const struct crypto_bignum *b,
142585732ac8SCy Schubert struct crypto_bignum *r)
142685732ac8SCy Schubert {
142785732ac8SCy Schubert return mp_add((mp_int *) a, (mp_int *) b,
142885732ac8SCy Schubert (mp_int *) r) == MP_OKAY ? 0 : -1;
142985732ac8SCy Schubert }
143085732ac8SCy Schubert
143185732ac8SCy Schubert
crypto_bignum_mod(const struct crypto_bignum * a,const struct crypto_bignum * m,struct crypto_bignum * r)143285732ac8SCy Schubert int crypto_bignum_mod(const struct crypto_bignum *a,
143385732ac8SCy Schubert const struct crypto_bignum *m,
143485732ac8SCy Schubert struct crypto_bignum *r)
143585732ac8SCy Schubert {
143685732ac8SCy Schubert return mp_mod((mp_int *) a, (mp_int *) m,
143785732ac8SCy Schubert (mp_int *) r) == MP_OKAY ? 0 : -1;
143885732ac8SCy Schubert }
143985732ac8SCy Schubert
144085732ac8SCy Schubert
crypto_bignum_exptmod(const struct crypto_bignum * b,const struct crypto_bignum * e,const struct crypto_bignum * m,struct crypto_bignum * r)144185732ac8SCy Schubert int crypto_bignum_exptmod(const struct crypto_bignum *b,
144285732ac8SCy Schubert const struct crypto_bignum *e,
144385732ac8SCy Schubert const struct crypto_bignum *m,
144485732ac8SCy Schubert struct crypto_bignum *r)
144585732ac8SCy Schubert {
144685732ac8SCy Schubert if (TEST_FAIL())
144785732ac8SCy Schubert return -1;
144885732ac8SCy Schubert
144985732ac8SCy Schubert return mp_exptmod((mp_int *) b, (mp_int *) e, (mp_int *) m,
145085732ac8SCy Schubert (mp_int *) r) == MP_OKAY ? 0 : -1;
145185732ac8SCy Schubert }
145285732ac8SCy Schubert
145385732ac8SCy Schubert
crypto_bignum_inverse(const struct crypto_bignum * a,const struct crypto_bignum * m,struct crypto_bignum * r)145485732ac8SCy Schubert int crypto_bignum_inverse(const struct crypto_bignum *a,
145585732ac8SCy Schubert const struct crypto_bignum *m,
145685732ac8SCy Schubert struct crypto_bignum *r)
145785732ac8SCy Schubert {
145885732ac8SCy Schubert if (TEST_FAIL())
145985732ac8SCy Schubert return -1;
146085732ac8SCy Schubert
146185732ac8SCy Schubert return mp_invmod((mp_int *) a, (mp_int *) m,
146285732ac8SCy Schubert (mp_int *) r) == MP_OKAY ? 0 : -1;
146385732ac8SCy Schubert }
146485732ac8SCy Schubert
146585732ac8SCy Schubert
crypto_bignum_sub(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * r)146685732ac8SCy Schubert int crypto_bignum_sub(const struct crypto_bignum *a,
146785732ac8SCy Schubert const struct crypto_bignum *b,
146885732ac8SCy Schubert struct crypto_bignum *r)
146985732ac8SCy Schubert {
147085732ac8SCy Schubert if (TEST_FAIL())
147185732ac8SCy Schubert return -1;
147285732ac8SCy Schubert
1473c1d255d3SCy Schubert return mp_sub((mp_int *) a, (mp_int *) b,
147485732ac8SCy Schubert (mp_int *) r) == MP_OKAY ? 0 : -1;
147585732ac8SCy Schubert }
147685732ac8SCy Schubert
147785732ac8SCy Schubert
crypto_bignum_div(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * d)147885732ac8SCy Schubert int crypto_bignum_div(const struct crypto_bignum *a,
147985732ac8SCy Schubert const struct crypto_bignum *b,
148085732ac8SCy Schubert struct crypto_bignum *d)
148185732ac8SCy Schubert {
148285732ac8SCy Schubert if (TEST_FAIL())
148385732ac8SCy Schubert return -1;
148485732ac8SCy Schubert
148585732ac8SCy Schubert return mp_div((mp_int *) a, (mp_int *) b, (mp_int *) d,
148685732ac8SCy Schubert NULL) == MP_OKAY ? 0 : -1;
148785732ac8SCy Schubert }
148885732ac8SCy Schubert
148985732ac8SCy Schubert
crypto_bignum_addmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)1490c1d255d3SCy Schubert int crypto_bignum_addmod(const struct crypto_bignum *a,
1491c1d255d3SCy Schubert const struct crypto_bignum *b,
1492c1d255d3SCy Schubert const struct crypto_bignum *c,
1493c1d255d3SCy Schubert struct crypto_bignum *d)
1494c1d255d3SCy Schubert {
1495c1d255d3SCy Schubert if (TEST_FAIL())
1496c1d255d3SCy Schubert return -1;
1497c1d255d3SCy Schubert
1498c1d255d3SCy Schubert return mp_addmod((mp_int *) a, (mp_int *) b, (mp_int *) c,
1499c1d255d3SCy Schubert (mp_int *) d) == MP_OKAY ? 0 : -1;
1500c1d255d3SCy Schubert }
1501c1d255d3SCy Schubert
1502c1d255d3SCy Schubert
crypto_bignum_mulmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * m,struct crypto_bignum * d)150385732ac8SCy Schubert int crypto_bignum_mulmod(const struct crypto_bignum *a,
150485732ac8SCy Schubert const struct crypto_bignum *b,
150585732ac8SCy Schubert const struct crypto_bignum *m,
150685732ac8SCy Schubert struct crypto_bignum *d)
150785732ac8SCy Schubert {
150885732ac8SCy Schubert if (TEST_FAIL())
150985732ac8SCy Schubert return -1;
151085732ac8SCy Schubert
151185732ac8SCy Schubert return mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) m,
151285732ac8SCy Schubert (mp_int *) d) == MP_OKAY ? 0 : -1;
151385732ac8SCy Schubert }
151485732ac8SCy Schubert
151585732ac8SCy Schubert
crypto_bignum_sqrmod(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)1516c1d255d3SCy Schubert int crypto_bignum_sqrmod(const struct crypto_bignum *a,
1517c1d255d3SCy Schubert const struct crypto_bignum *b,
1518c1d255d3SCy Schubert struct crypto_bignum *c)
1519c1d255d3SCy Schubert {
1520c1d255d3SCy Schubert if (TEST_FAIL())
1521c1d255d3SCy Schubert return -1;
1522c1d255d3SCy Schubert
1523c1d255d3SCy Schubert return mp_sqrmod((mp_int *) a, (mp_int *) b,
1524c1d255d3SCy Schubert (mp_int *) c) == MP_OKAY ? 0 : -1;
1525c1d255d3SCy Schubert }
1526c1d255d3SCy Schubert
1527c1d255d3SCy Schubert
crypto_bignum_rshift(const struct crypto_bignum * a,int n,struct crypto_bignum * r)152885732ac8SCy Schubert int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
152985732ac8SCy Schubert struct crypto_bignum *r)
153085732ac8SCy Schubert {
153185732ac8SCy Schubert if (mp_copy((mp_int *) a, (mp_int *) r) != MP_OKAY)
153285732ac8SCy Schubert return -1;
153385732ac8SCy Schubert mp_rshb((mp_int *) r, n);
153485732ac8SCy Schubert return 0;
153585732ac8SCy Schubert }
153685732ac8SCy Schubert
153785732ac8SCy Schubert
crypto_bignum_cmp(const struct crypto_bignum * a,const struct crypto_bignum * b)153885732ac8SCy Schubert int crypto_bignum_cmp(const struct crypto_bignum *a,
153985732ac8SCy Schubert const struct crypto_bignum *b)
154085732ac8SCy Schubert {
154185732ac8SCy Schubert return mp_cmp((mp_int *) a, (mp_int *) b);
154285732ac8SCy Schubert }
154385732ac8SCy Schubert
154485732ac8SCy Schubert
crypto_bignum_is_zero(const struct crypto_bignum * a)154585732ac8SCy Schubert int crypto_bignum_is_zero(const struct crypto_bignum *a)
154685732ac8SCy Schubert {
154785732ac8SCy Schubert return mp_iszero((mp_int *) a);
154885732ac8SCy Schubert }
154985732ac8SCy Schubert
155085732ac8SCy Schubert
crypto_bignum_is_one(const struct crypto_bignum * a)155185732ac8SCy Schubert int crypto_bignum_is_one(const struct crypto_bignum *a)
155285732ac8SCy Schubert {
155385732ac8SCy Schubert return mp_isone((const mp_int *) a);
155485732ac8SCy Schubert }
155585732ac8SCy Schubert
crypto_bignum_is_odd(const struct crypto_bignum * a)155685732ac8SCy Schubert int crypto_bignum_is_odd(const struct crypto_bignum *a)
155785732ac8SCy Schubert {
155885732ac8SCy Schubert return mp_isodd((mp_int *) a);
155985732ac8SCy Schubert }
156085732ac8SCy Schubert
156185732ac8SCy Schubert
crypto_bignum_legendre(const struct crypto_bignum * a,const struct crypto_bignum * p)156285732ac8SCy Schubert int crypto_bignum_legendre(const struct crypto_bignum *a,
156385732ac8SCy Schubert const struct crypto_bignum *p)
156485732ac8SCy Schubert {
156585732ac8SCy Schubert mp_int t;
156685732ac8SCy Schubert int ret;
156785732ac8SCy Schubert int res = -2;
156885732ac8SCy Schubert
156985732ac8SCy Schubert if (TEST_FAIL())
157085732ac8SCy Schubert return -2;
157185732ac8SCy Schubert
157285732ac8SCy Schubert if (mp_init(&t) != MP_OKAY)
157385732ac8SCy Schubert return -2;
157485732ac8SCy Schubert
157585732ac8SCy Schubert /* t = (p-1) / 2 */
157685732ac8SCy Schubert ret = mp_sub_d((mp_int *) p, 1, &t);
157785732ac8SCy Schubert if (ret == MP_OKAY)
157885732ac8SCy Schubert mp_rshb(&t, 1);
157985732ac8SCy Schubert if (ret == MP_OKAY)
158085732ac8SCy Schubert ret = mp_exptmod((mp_int *) a, &t, (mp_int *) p, &t);
158185732ac8SCy Schubert if (ret == MP_OKAY) {
158285732ac8SCy Schubert if (mp_isone(&t))
158385732ac8SCy Schubert res = 1;
158485732ac8SCy Schubert else if (mp_iszero(&t))
158585732ac8SCy Schubert res = 0;
158685732ac8SCy Schubert else
158785732ac8SCy Schubert res = -1;
158885732ac8SCy Schubert }
158985732ac8SCy Schubert
159085732ac8SCy Schubert mp_clear(&t);
159185732ac8SCy Schubert return res;
159285732ac8SCy Schubert }
159385732ac8SCy Schubert
159485732ac8SCy Schubert
159585732ac8SCy Schubert #ifdef CONFIG_ECC
159685732ac8SCy Schubert
crypto_ec_group_2_id(int group)1597*a90b9d01SCy Schubert static int crypto_ec_group_2_id(int group)
1598*a90b9d01SCy Schubert {
1599*a90b9d01SCy Schubert switch (group) {
1600*a90b9d01SCy Schubert case 19:
1601*a90b9d01SCy Schubert return ECC_SECP256R1;
1602*a90b9d01SCy Schubert case 20:
1603*a90b9d01SCy Schubert return ECC_SECP384R1;
1604*a90b9d01SCy Schubert case 21:
1605*a90b9d01SCy Schubert return ECC_SECP521R1;
1606*a90b9d01SCy Schubert case 25:
1607*a90b9d01SCy Schubert return ECC_SECP192R1;
1608*a90b9d01SCy Schubert case 26:
1609*a90b9d01SCy Schubert return ECC_SECP224R1;
1610*a90b9d01SCy Schubert #ifdef HAVE_ECC_BRAINPOOL
1611*a90b9d01SCy Schubert case 27:
1612*a90b9d01SCy Schubert return ECC_BRAINPOOLP224R1;
1613*a90b9d01SCy Schubert case 28:
1614*a90b9d01SCy Schubert return ECC_BRAINPOOLP256R1;
1615*a90b9d01SCy Schubert case 29:
1616*a90b9d01SCy Schubert return ECC_BRAINPOOLP384R1;
1617*a90b9d01SCy Schubert case 30:
1618*a90b9d01SCy Schubert return ECC_BRAINPOOLP512R1;
1619*a90b9d01SCy Schubert #endif /* HAVE_ECC_BRAINPOOL */
1620*a90b9d01SCy Schubert default:
1621*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("Unsupported curve (id=%d) in EC key", group);
1622*a90b9d01SCy Schubert return ECC_CURVE_INVALID;
1623*a90b9d01SCy Schubert }
1624*a90b9d01SCy Schubert }
1625*a90b9d01SCy Schubert
1626*a90b9d01SCy Schubert
162785732ac8SCy Schubert int ecc_map(ecc_point *, mp_int *, mp_digit);
162885732ac8SCy Schubert int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
162985732ac8SCy Schubert mp_int *a, mp_int *modulus, mp_digit mp);
163085732ac8SCy Schubert
163185732ac8SCy Schubert struct crypto_ec {
1632*a90b9d01SCy Schubert ecc_key *key;
1633*a90b9d01SCy Schubert #ifdef CONFIG_DPP
1634*a90b9d01SCy Schubert ecc_point *g; /* Only used in DPP for now */
1635*a90b9d01SCy Schubert #endif /* CONFIG_DPP */
163685732ac8SCy Schubert mp_int a;
163785732ac8SCy Schubert mp_int prime;
163885732ac8SCy Schubert mp_int order;
163985732ac8SCy Schubert mp_digit mont_b;
164085732ac8SCy Schubert mp_int b;
1641*a90b9d01SCy Schubert int curve_id;
1642*a90b9d01SCy Schubert bool own_key; /* Should we free the `key` */
164385732ac8SCy Schubert };
164485732ac8SCy Schubert
164585732ac8SCy Schubert
crypto_ec_init(int group)164685732ac8SCy Schubert struct crypto_ec * crypto_ec_init(int group)
164785732ac8SCy Schubert {
164885732ac8SCy Schubert int built = 0;
164985732ac8SCy Schubert struct crypto_ec *e;
1650*a90b9d01SCy Schubert int curve_id = crypto_ec_group_2_id(group);
1651*a90b9d01SCy Schubert int err;
165285732ac8SCy Schubert
1653*a90b9d01SCy Schubert if (curve_id == ECC_CURVE_INVALID) {
1654*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
165585732ac8SCy Schubert return NULL;
165685732ac8SCy Schubert }
165785732ac8SCy Schubert
165885732ac8SCy Schubert e = os_zalloc(sizeof(*e));
1659*a90b9d01SCy Schubert if (!e) {
1660*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_zalloc);
166185732ac8SCy Schubert return NULL;
1662*a90b9d01SCy Schubert }
166385732ac8SCy Schubert
1664*a90b9d01SCy Schubert e->curve_id = curve_id;
1665*a90b9d01SCy Schubert e->own_key = true;
1666*a90b9d01SCy Schubert e->key = ecc_key_init();
1667*a90b9d01SCy Schubert if (!e->key) {
1668*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(ecc_key_init);
166985732ac8SCy Schubert goto done;
1670*a90b9d01SCy Schubert }
1671*a90b9d01SCy Schubert
1672*a90b9d01SCy Schubert err = wc_ecc_set_curve(e->key, 0, curve_id);
1673*a90b9d01SCy Schubert if (err != 0) {
1674*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_set_curve, err);
1675*a90b9d01SCy Schubert goto done;
1676*a90b9d01SCy Schubert }
1677*a90b9d01SCy Schubert #ifdef CONFIG_DPP
1678*a90b9d01SCy Schubert e->g = wc_ecc_new_point();
1679*a90b9d01SCy Schubert if (!e->g) {
1680*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_ecc_new_point);
1681*a90b9d01SCy Schubert goto done;
1682*a90b9d01SCy Schubert }
1683*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
1684*a90b9d01SCy Schubert /* Setup generator manually in FIPS mode */
1685*a90b9d01SCy Schubert if (!e->key->dp) {
1686*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(e->key->dp);
1687*a90b9d01SCy Schubert goto done;
1688*a90b9d01SCy Schubert }
1689*a90b9d01SCy Schubert err = mp_read_radix(e->g->x, e->key->dp->Gx, MP_RADIX_HEX);
1690*a90b9d01SCy Schubert if (err != MP_OKAY) {
1691*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1692*a90b9d01SCy Schubert goto done;
1693*a90b9d01SCy Schubert }
1694*a90b9d01SCy Schubert err = mp_read_radix(e->g->y, e->key->dp->Gy, MP_RADIX_HEX);
1695*a90b9d01SCy Schubert if (err != MP_OKAY) {
1696*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1697*a90b9d01SCy Schubert goto done;
1698*a90b9d01SCy Schubert }
1699*a90b9d01SCy Schubert err = mp_set(e->g->z, 1);
1700*a90b9d01SCy Schubert if (err != MP_OKAY) {
1701*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_set, err);
1702*a90b9d01SCy Schubert goto done;
1703*a90b9d01SCy Schubert }
1704*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
1705*a90b9d01SCy Schubert err = wc_ecc_get_generator(e->g, wc_ecc_get_curve_idx(curve_id));
1706*a90b9d01SCy Schubert if (err != MP_OKAY) {
1707*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_get_generator, err);
1708*a90b9d01SCy Schubert goto done;
1709*a90b9d01SCy Schubert }
1710*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
1711*a90b9d01SCy Schubert #endif /* CONFIG_DPP */
1712*a90b9d01SCy Schubert err = mp_init_multi(&e->a, &e->prime, &e->order, &e->b, NULL, NULL);
1713*a90b9d01SCy Schubert if (err != MP_OKAY) {
1714*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_init_multi, err);
1715*a90b9d01SCy Schubert goto done;
1716*a90b9d01SCy Schubert }
1717*a90b9d01SCy Schubert err = mp_read_radix(&e->a, e->key->dp->Af, 16);
1718*a90b9d01SCy Schubert if (err != MP_OKAY) {
1719*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1720*a90b9d01SCy Schubert goto done;
1721*a90b9d01SCy Schubert }
1722*a90b9d01SCy Schubert err = mp_read_radix(&e->b, e->key->dp->Bf, 16);
1723*a90b9d01SCy Schubert if (err != MP_OKAY) {
1724*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1725*a90b9d01SCy Schubert goto done;
1726*a90b9d01SCy Schubert }
1727*a90b9d01SCy Schubert err = mp_read_radix(&e->prime, e->key->dp->prime, 16);
1728*a90b9d01SCy Schubert if (err != MP_OKAY) {
1729*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1730*a90b9d01SCy Schubert goto done;
1731*a90b9d01SCy Schubert }
1732*a90b9d01SCy Schubert err = mp_read_radix(&e->order, e->key->dp->order, 16);
1733*a90b9d01SCy Schubert if (err != MP_OKAY) {
1734*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_read_radix, err);
1735*a90b9d01SCy Schubert goto done;
1736*a90b9d01SCy Schubert }
1737*a90b9d01SCy Schubert err = mp_montgomery_setup(&e->prime, &e->mont_b);
1738*a90b9d01SCy Schubert if (err != MP_OKAY) {
1739*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_montgomery_setup, err);
1740*a90b9d01SCy Schubert goto done;
1741*a90b9d01SCy Schubert }
174285732ac8SCy Schubert
174385732ac8SCy Schubert built = 1;
174485732ac8SCy Schubert done:
174585732ac8SCy Schubert if (!built) {
174685732ac8SCy Schubert crypto_ec_deinit(e);
174785732ac8SCy Schubert e = NULL;
174885732ac8SCy Schubert }
174985732ac8SCy Schubert return e;
175085732ac8SCy Schubert }
175185732ac8SCy Schubert
175285732ac8SCy Schubert
crypto_ec_deinit(struct crypto_ec * e)175385732ac8SCy Schubert void crypto_ec_deinit(struct crypto_ec* e)
175485732ac8SCy Schubert {
175585732ac8SCy Schubert if (!e)
175685732ac8SCy Schubert return;
175785732ac8SCy Schubert
175885732ac8SCy Schubert mp_clear(&e->b);
175985732ac8SCy Schubert mp_clear(&e->order);
176085732ac8SCy Schubert mp_clear(&e->prime);
176185732ac8SCy Schubert mp_clear(&e->a);
1762*a90b9d01SCy Schubert #ifdef CONFIG_DPP
1763*a90b9d01SCy Schubert wc_ecc_del_point(e->g);
1764*a90b9d01SCy Schubert #endif /* CONFIG_DPP */
1765*a90b9d01SCy Schubert if (e->own_key)
1766*a90b9d01SCy Schubert ecc_key_deinit(e->key);
176785732ac8SCy Schubert os_free(e);
176885732ac8SCy Schubert }
176985732ac8SCy Schubert
177085732ac8SCy Schubert
crypto_ec_point_init(struct crypto_ec * e)177185732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
177285732ac8SCy Schubert {
177385732ac8SCy Schubert if (TEST_FAIL())
177485732ac8SCy Schubert return NULL;
177585732ac8SCy Schubert if (!e)
177685732ac8SCy Schubert return NULL;
177785732ac8SCy Schubert return (struct crypto_ec_point *) wc_ecc_new_point();
177885732ac8SCy Schubert }
177985732ac8SCy Schubert
178085732ac8SCy Schubert
crypto_ec_prime_len(struct crypto_ec * e)178185732ac8SCy Schubert size_t crypto_ec_prime_len(struct crypto_ec *e)
178285732ac8SCy Schubert {
178385732ac8SCy Schubert return (mp_count_bits(&e->prime) + 7) / 8;
178485732ac8SCy Schubert }
178585732ac8SCy Schubert
178685732ac8SCy Schubert
crypto_ec_prime_len_bits(struct crypto_ec * e)178785732ac8SCy Schubert size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
178885732ac8SCy Schubert {
178985732ac8SCy Schubert return mp_count_bits(&e->prime);
179085732ac8SCy Schubert }
179185732ac8SCy Schubert
179285732ac8SCy Schubert
crypto_ec_order_len(struct crypto_ec * e)179385732ac8SCy Schubert size_t crypto_ec_order_len(struct crypto_ec *e)
179485732ac8SCy Schubert {
179585732ac8SCy Schubert return (mp_count_bits(&e->order) + 7) / 8;
179685732ac8SCy Schubert }
179785732ac8SCy Schubert
179885732ac8SCy Schubert
crypto_ec_get_prime(struct crypto_ec * e)179985732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
180085732ac8SCy Schubert {
180185732ac8SCy Schubert return (const struct crypto_bignum *) &e->prime;
180285732ac8SCy Schubert }
180385732ac8SCy Schubert
180485732ac8SCy Schubert
crypto_ec_get_order(struct crypto_ec * e)180585732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
180685732ac8SCy Schubert {
180785732ac8SCy Schubert return (const struct crypto_bignum *) &e->order;
180885732ac8SCy Schubert }
180985732ac8SCy Schubert
181085732ac8SCy Schubert
crypto_ec_get_a(struct crypto_ec * e)1811c1d255d3SCy Schubert const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e)
1812c1d255d3SCy Schubert {
1813c1d255d3SCy Schubert return (const struct crypto_bignum *) &e->a;
1814c1d255d3SCy Schubert }
1815c1d255d3SCy Schubert
1816c1d255d3SCy Schubert
crypto_ec_get_b(struct crypto_ec * e)1817c1d255d3SCy Schubert const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
1818c1d255d3SCy Schubert {
1819c1d255d3SCy Schubert return (const struct crypto_bignum *) &e->b;
1820c1d255d3SCy Schubert }
1821c1d255d3SCy Schubert
1822c1d255d3SCy Schubert
crypto_ec_point_deinit(struct crypto_ec_point * p,int clear)182385732ac8SCy Schubert void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
182485732ac8SCy Schubert {
182585732ac8SCy Schubert ecc_point *point = (ecc_point *) p;
182685732ac8SCy Schubert
182785732ac8SCy Schubert if (!p)
182885732ac8SCy Schubert return;
182985732ac8SCy Schubert
183085732ac8SCy Schubert if (clear) {
1831*a90b9d01SCy Schubert #ifdef CONFIG_FIPS
183285732ac8SCy Schubert mp_forcezero(point->x);
183385732ac8SCy Schubert mp_forcezero(point->y);
183485732ac8SCy Schubert mp_forcezero(point->z);
1835*a90b9d01SCy Schubert #else /* CONFIG_FIPS */
1836*a90b9d01SCy Schubert wc_ecc_forcezero_point(point);
1837*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */
183885732ac8SCy Schubert }
183985732ac8SCy Schubert wc_ecc_del_point(point);
184085732ac8SCy Schubert }
184185732ac8SCy Schubert
184285732ac8SCy Schubert
1843*a90b9d01SCy Schubert #ifdef CONFIG_DPP
crypto_ec_get_generator(struct crypto_ec * e)1844*a90b9d01SCy Schubert const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
1845*a90b9d01SCy Schubert {
1846*a90b9d01SCy Schubert return (const struct crypto_ec_point *) e->g;
1847*a90b9d01SCy Schubert }
1848*a90b9d01SCy Schubert #endif /* CONFIG_DPP */
1849*a90b9d01SCy Schubert
1850*a90b9d01SCy Schubert
crypto_ec_point_x(struct crypto_ec * e,const struct crypto_ec_point * p,struct crypto_bignum * x)185185732ac8SCy Schubert int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
185285732ac8SCy Schubert struct crypto_bignum *x)
185385732ac8SCy Schubert {
185485732ac8SCy Schubert return mp_copy(((ecc_point *) p)->x, (mp_int *) x) == MP_OKAY ? 0 : -1;
185585732ac8SCy Schubert }
185685732ac8SCy Schubert
185785732ac8SCy Schubert
crypto_ec_point_to_bin(struct crypto_ec * e,const struct crypto_ec_point * point,u8 * x,u8 * y)185885732ac8SCy Schubert int crypto_ec_point_to_bin(struct crypto_ec *e,
185985732ac8SCy Schubert const struct crypto_ec_point *point, u8 *x, u8 *y)
186085732ac8SCy Schubert {
186185732ac8SCy Schubert ecc_point *p = (ecc_point *) point;
1862*a90b9d01SCy Schubert int len;
1863*a90b9d01SCy Schubert int err;
186485732ac8SCy Schubert
186585732ac8SCy Schubert if (TEST_FAIL())
186685732ac8SCy Schubert return -1;
186785732ac8SCy Schubert
186885732ac8SCy Schubert if (!mp_isone(p->z)) {
1869*a90b9d01SCy Schubert err = ecc_map(p, &e->prime, e->mont_b);
1870*a90b9d01SCy Schubert if (err != MP_OKAY) {
1871*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(ecc_map, err);
1872*a90b9d01SCy Schubert return -1;
1873*a90b9d01SCy Schubert }
1874*a90b9d01SCy Schubert }
1875*a90b9d01SCy Schubert
1876*a90b9d01SCy Schubert len = wc_ecc_get_curve_size_from_id(e->curve_id);
1877*a90b9d01SCy Schubert if (len <= 0) {
1878*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_get_curve_size_from_id, len);
1879*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("wc_ecc_get_curve_size_from_id error for curve_id %d", e->curve_id);
188085732ac8SCy Schubert return -1;
188185732ac8SCy Schubert }
188285732ac8SCy Schubert
188385732ac8SCy Schubert if (x) {
188485732ac8SCy Schubert if (crypto_bignum_to_bin((struct crypto_bignum *)p->x, x,
1885*a90b9d01SCy Schubert (size_t) len, (size_t) len) <= 0) {
1886*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_bignum_to_bin, -1);
188785732ac8SCy Schubert return -1;
188885732ac8SCy Schubert }
1889*a90b9d01SCy Schubert }
189085732ac8SCy Schubert
189185732ac8SCy Schubert if (y) {
189285732ac8SCy Schubert if (crypto_bignum_to_bin((struct crypto_bignum *) p->y, y,
1893*a90b9d01SCy Schubert (size_t) len, (size_t) len) <= 0) {
1894*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_bignum_to_bin, -1);
189585732ac8SCy Schubert return -1;
189685732ac8SCy Schubert }
1897*a90b9d01SCy Schubert }
189885732ac8SCy Schubert
189985732ac8SCy Schubert return 0;
190085732ac8SCy Schubert }
190185732ac8SCy Schubert
190285732ac8SCy Schubert
crypto_ec_point_from_bin(struct crypto_ec * e,const u8 * val)190385732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
190485732ac8SCy Schubert const u8 *val)
190585732ac8SCy Schubert {
190685732ac8SCy Schubert ecc_point *point = NULL;
190785732ac8SCy Schubert int loaded = 0;
190885732ac8SCy Schubert
190985732ac8SCy Schubert if (TEST_FAIL())
191085732ac8SCy Schubert return NULL;
191185732ac8SCy Schubert
191285732ac8SCy Schubert point = wc_ecc_new_point();
191385732ac8SCy Schubert if (!point)
191485732ac8SCy Schubert goto done;
191585732ac8SCy Schubert
1916*a90b9d01SCy Schubert if (mp_read_unsigned_bin(point->x, val, e->key->dp->size) != MP_OKAY)
191785732ac8SCy Schubert goto done;
1918*a90b9d01SCy Schubert val += e->key->dp->size;
1919*a90b9d01SCy Schubert if (mp_read_unsigned_bin(point->y, val, e->key->dp->size) != MP_OKAY)
192085732ac8SCy Schubert goto done;
192185732ac8SCy Schubert mp_set(point->z, 1);
192285732ac8SCy Schubert
192385732ac8SCy Schubert loaded = 1;
192485732ac8SCy Schubert done:
192585732ac8SCy Schubert if (!loaded) {
192685732ac8SCy Schubert wc_ecc_del_point(point);
192785732ac8SCy Schubert point = NULL;
192885732ac8SCy Schubert }
192985732ac8SCy Schubert return (struct crypto_ec_point *) point;
193085732ac8SCy Schubert }
193185732ac8SCy Schubert
193285732ac8SCy Schubert
crypto_ec_point_add(struct crypto_ec * e,const struct crypto_ec_point * a,const struct crypto_ec_point * b,struct crypto_ec_point * c)193385732ac8SCy Schubert int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
193485732ac8SCy Schubert const struct crypto_ec_point *b,
193585732ac8SCy Schubert struct crypto_ec_point *c)
193685732ac8SCy Schubert {
193785732ac8SCy Schubert mp_int mu;
193885732ac8SCy Schubert ecc_point *ta = NULL, *tb = NULL;
193985732ac8SCy Schubert ecc_point *pa = (ecc_point *) a, *pb = (ecc_point *) b;
194085732ac8SCy Schubert mp_int *modulus = &e->prime;
194185732ac8SCy Schubert int ret;
194285732ac8SCy Schubert
194385732ac8SCy Schubert if (TEST_FAIL())
194485732ac8SCy Schubert return -1;
194585732ac8SCy Schubert
194685732ac8SCy Schubert ret = mp_init(&mu);
194785732ac8SCy Schubert if (ret != MP_OKAY)
194885732ac8SCy Schubert return -1;
194985732ac8SCy Schubert
195085732ac8SCy Schubert ret = mp_montgomery_calc_normalization(&mu, modulus);
195185732ac8SCy Schubert if (ret != MP_OKAY) {
195285732ac8SCy Schubert mp_clear(&mu);
195385732ac8SCy Schubert return -1;
195485732ac8SCy Schubert }
195585732ac8SCy Schubert
195685732ac8SCy Schubert if (!mp_isone(&mu)) {
195785732ac8SCy Schubert ta = wc_ecc_new_point();
195885732ac8SCy Schubert if (!ta) {
195985732ac8SCy Schubert mp_clear(&mu);
196085732ac8SCy Schubert return -1;
196185732ac8SCy Schubert }
196285732ac8SCy Schubert tb = wc_ecc_new_point();
196385732ac8SCy Schubert if (!tb) {
196485732ac8SCy Schubert wc_ecc_del_point(ta);
196585732ac8SCy Schubert mp_clear(&mu);
196685732ac8SCy Schubert return -1;
196785732ac8SCy Schubert }
196885732ac8SCy Schubert
196985732ac8SCy Schubert if (mp_mulmod(pa->x, &mu, modulus, ta->x) != MP_OKAY ||
197085732ac8SCy Schubert mp_mulmod(pa->y, &mu, modulus, ta->y) != MP_OKAY ||
197185732ac8SCy Schubert mp_mulmod(pa->z, &mu, modulus, ta->z) != MP_OKAY ||
197285732ac8SCy Schubert mp_mulmod(pb->x, &mu, modulus, tb->x) != MP_OKAY ||
197385732ac8SCy Schubert mp_mulmod(pb->y, &mu, modulus, tb->y) != MP_OKAY ||
197485732ac8SCy Schubert mp_mulmod(pb->z, &mu, modulus, tb->z) != MP_OKAY) {
197585732ac8SCy Schubert ret = -1;
197685732ac8SCy Schubert goto end;
197785732ac8SCy Schubert }
197885732ac8SCy Schubert pa = ta;
197985732ac8SCy Schubert pb = tb;
198085732ac8SCy Schubert }
198185732ac8SCy Schubert
198285732ac8SCy Schubert ret = ecc_projective_add_point(pa, pb, (ecc_point *) c, &e->a,
198385732ac8SCy Schubert &e->prime, e->mont_b);
198485732ac8SCy Schubert if (ret != 0) {
198585732ac8SCy Schubert ret = -1;
198685732ac8SCy Schubert goto end;
198785732ac8SCy Schubert }
198885732ac8SCy Schubert
198985732ac8SCy Schubert if (ecc_map((ecc_point *) c, &e->prime, e->mont_b) != MP_OKAY)
199085732ac8SCy Schubert ret = -1;
199185732ac8SCy Schubert else
199285732ac8SCy Schubert ret = 0;
199385732ac8SCy Schubert end:
199485732ac8SCy Schubert wc_ecc_del_point(tb);
199585732ac8SCy Schubert wc_ecc_del_point(ta);
199685732ac8SCy Schubert mp_clear(&mu);
199785732ac8SCy Schubert return ret;
199885732ac8SCy Schubert }
199985732ac8SCy Schubert
200085732ac8SCy Schubert
crypto_ec_point_mul(struct crypto_ec * e,const struct crypto_ec_point * p,const struct crypto_bignum * b,struct crypto_ec_point * res)200185732ac8SCy Schubert int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
200285732ac8SCy Schubert const struct crypto_bignum *b,
200385732ac8SCy Schubert struct crypto_ec_point *res)
200485732ac8SCy Schubert {
200585732ac8SCy Schubert int ret;
200685732ac8SCy Schubert
200785732ac8SCy Schubert if (TEST_FAIL())
200885732ac8SCy Schubert return -1;
200985732ac8SCy Schubert
201085732ac8SCy Schubert ret = wc_ecc_mulmod((mp_int *) b, (ecc_point *) p, (ecc_point *) res,
201185732ac8SCy Schubert &e->a, &e->prime, 1);
201285732ac8SCy Schubert return ret == 0 ? 0 : -1;
201385732ac8SCy Schubert }
201485732ac8SCy Schubert
201585732ac8SCy Schubert
crypto_ec_point_invert(struct crypto_ec * e,struct crypto_ec_point * p)201685732ac8SCy Schubert int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
201785732ac8SCy Schubert {
201885732ac8SCy Schubert ecc_point *point = (ecc_point *) p;
201985732ac8SCy Schubert
202085732ac8SCy Schubert if (TEST_FAIL())
202185732ac8SCy Schubert return -1;
202285732ac8SCy Schubert
202385732ac8SCy Schubert if (mp_sub(&e->prime, point->y, point->y) != MP_OKAY)
202485732ac8SCy Schubert return -1;
202585732ac8SCy Schubert
202685732ac8SCy Schubert return 0;
202785732ac8SCy Schubert }
202885732ac8SCy Schubert
202985732ac8SCy Schubert
203085732ac8SCy Schubert struct crypto_bignum *
crypto_ec_point_compute_y_sqr(struct crypto_ec * e,const struct crypto_bignum * x)203185732ac8SCy Schubert crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
203285732ac8SCy Schubert const struct crypto_bignum *x)
203385732ac8SCy Schubert {
2034*a90b9d01SCy Schubert mp_int *y2;
203585732ac8SCy Schubert
203685732ac8SCy Schubert if (TEST_FAIL())
203785732ac8SCy Schubert return NULL;
203885732ac8SCy Schubert
2039*a90b9d01SCy Schubert /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
204085732ac8SCy Schubert y2 = (mp_int *) crypto_bignum_init();
2041*a90b9d01SCy Schubert if (!y2 ||
2042*a90b9d01SCy Schubert mp_sqrmod((mp_int *) x, &e->prime, y2) != 0 ||
2043*a90b9d01SCy Schubert mp_addmod(y2, &e->a, &e->prime, y2) != 0 ||
204485732ac8SCy Schubert mp_mulmod((mp_int *) x, y2, &e->prime, y2) != 0 ||
2045*a90b9d01SCy Schubert mp_addmod(y2, &e->b, &e->prime, y2) != 0) {
204685732ac8SCy Schubert mp_clear(y2);
204785732ac8SCy Schubert os_free(y2);
2048*a90b9d01SCy Schubert y2 = NULL;
204985732ac8SCy Schubert }
205085732ac8SCy Schubert
205185732ac8SCy Schubert return (struct crypto_bignum *) y2;
205285732ac8SCy Schubert }
205385732ac8SCy Schubert
205485732ac8SCy Schubert
crypto_ec_point_is_at_infinity(struct crypto_ec * e,const struct crypto_ec_point * p)205585732ac8SCy Schubert int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
205685732ac8SCy Schubert const struct crypto_ec_point *p)
205785732ac8SCy Schubert {
205885732ac8SCy Schubert return wc_ecc_point_is_at_infinity((ecc_point *) p);
205985732ac8SCy Schubert }
206085732ac8SCy Schubert
206185732ac8SCy Schubert
crypto_ec_point_is_on_curve(struct crypto_ec * e,const struct crypto_ec_point * p)206285732ac8SCy Schubert int crypto_ec_point_is_on_curve(struct crypto_ec *e,
206385732ac8SCy Schubert const struct crypto_ec_point *p)
206485732ac8SCy Schubert {
206585732ac8SCy Schubert return wc_ecc_is_point((ecc_point *) p, &e->a, &e->b, &e->prime) ==
206685732ac8SCy Schubert MP_OKAY;
206785732ac8SCy Schubert }
206885732ac8SCy Schubert
206985732ac8SCy Schubert
crypto_ec_point_cmp(const struct crypto_ec * e,const struct crypto_ec_point * a,const struct crypto_ec_point * b)207085732ac8SCy Schubert int crypto_ec_point_cmp(const struct crypto_ec *e,
207185732ac8SCy Schubert const struct crypto_ec_point *a,
207285732ac8SCy Schubert const struct crypto_ec_point *b)
207385732ac8SCy Schubert {
207485732ac8SCy Schubert return wc_ecc_cmp_point((ecc_point *) a, (ecc_point *) b);
207585732ac8SCy Schubert }
207685732ac8SCy Schubert
2077*a90b9d01SCy Schubert struct crypto_ec_key {
2078*a90b9d01SCy Schubert ecc_key *eckey;
2079*a90b9d01SCy Schubert WC_RNG *rng; /* Needs to be initialized before use.
2080*a90b9d01SCy Schubert * *NOT* initialized in crypto_ec_key_init */
2081*a90b9d01SCy Schubert };
2082*a90b9d01SCy Schubert
208385732ac8SCy Schubert
208485732ac8SCy Schubert struct crypto_ecdh {
208585732ac8SCy Schubert struct crypto_ec *ec;
2086*a90b9d01SCy Schubert WC_RNG *rng;
208785732ac8SCy Schubert };
208885732ac8SCy Schubert
_crypto_ecdh_init(int group)2089*a90b9d01SCy Schubert static struct crypto_ecdh * _crypto_ecdh_init(int group)
209085732ac8SCy Schubert {
209185732ac8SCy Schubert struct crypto_ecdh *ecdh = NULL;
2092*a90b9d01SCy Schubert #if defined(ECC_TIMING_RESISTANT) && !defined(WOLFSSL_OLD_FIPS)
209385732ac8SCy Schubert int ret;
2094*a90b9d01SCy Schubert #endif /* ECC_TIMING_RESISTANT && !WOLFSSL_OLD_FIPS */
209585732ac8SCy Schubert
209685732ac8SCy Schubert ecdh = os_zalloc(sizeof(*ecdh));
2097*a90b9d01SCy Schubert if (!ecdh) {
2098*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_zalloc);
2099*a90b9d01SCy Schubert return NULL;
2100*a90b9d01SCy Schubert }
2101*a90b9d01SCy Schubert
2102*a90b9d01SCy Schubert ecdh->rng = wc_rng_init();
2103*a90b9d01SCy Schubert if (!ecdh->rng) {
2104*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_rng_init);
210585732ac8SCy Schubert goto fail;
2106*a90b9d01SCy Schubert }
210785732ac8SCy Schubert
210885732ac8SCy Schubert ecdh->ec = crypto_ec_init(group);
2109*a90b9d01SCy Schubert if (!ecdh->ec) {
2110*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_init);
211185732ac8SCy Schubert goto fail;
2112*a90b9d01SCy Schubert }
211385732ac8SCy Schubert
2114*a90b9d01SCy Schubert #if defined(ECC_TIMING_RESISTANT) && !defined(WOLFSSL_OLD_FIPS)
2115*a90b9d01SCy Schubert ret = wc_ecc_set_rng(ecdh->ec->key, ecdh->rng);
2116*a90b9d01SCy Schubert if (ret != 0) {
2117*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_set_rng, ret);
211885732ac8SCy Schubert goto fail;
2119*a90b9d01SCy Schubert }
2120*a90b9d01SCy Schubert #endif /* ECC_TIMING_RESISTANT && !WOLFSSL_OLD_FIPS */
212185732ac8SCy Schubert
212285732ac8SCy Schubert return ecdh;
212385732ac8SCy Schubert fail:
212485732ac8SCy Schubert crypto_ecdh_deinit(ecdh);
2125*a90b9d01SCy Schubert return NULL;
2126*a90b9d01SCy Schubert }
2127*a90b9d01SCy Schubert
2128*a90b9d01SCy Schubert
crypto_ecdh_init(int group)2129*a90b9d01SCy Schubert struct crypto_ecdh * crypto_ecdh_init(int group)
2130*a90b9d01SCy Schubert {
2131*a90b9d01SCy Schubert struct crypto_ecdh *ret = NULL;
2132*a90b9d01SCy Schubert int err;
2133*a90b9d01SCy Schubert
2134*a90b9d01SCy Schubert ret = _crypto_ecdh_init(group);
2135*a90b9d01SCy Schubert
2136*a90b9d01SCy Schubert if (!ret) {
2137*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(_crypto_ecdh_init);
2138*a90b9d01SCy Schubert return NULL;
2139*a90b9d01SCy Schubert }
2140*a90b9d01SCy Schubert
2141*a90b9d01SCy Schubert err = wc_ecc_make_key_ex(ret->rng, 0, ret->ec->key,
2142*a90b9d01SCy Schubert crypto_ec_group_2_id(group));
2143*a90b9d01SCy Schubert if (err != MP_OKAY) {
2144*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_make_key_ex, err);
2145*a90b9d01SCy Schubert crypto_ecdh_deinit(ret);
2146*a90b9d01SCy Schubert ret = NULL;
2147*a90b9d01SCy Schubert }
2148*a90b9d01SCy Schubert
2149*a90b9d01SCy Schubert return ret;
2150*a90b9d01SCy Schubert }
2151*a90b9d01SCy Schubert
2152*a90b9d01SCy Schubert
crypto_ecdh_init2(int group,struct crypto_ec_key * own_key)2153*a90b9d01SCy Schubert struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
2154*a90b9d01SCy Schubert {
2155*a90b9d01SCy Schubert struct crypto_ecdh *ret = NULL;
2156*a90b9d01SCy Schubert
2157*a90b9d01SCy Schubert if (!own_key || crypto_ec_key_group(own_key) != group) {
2158*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2159*a90b9d01SCy Schubert return NULL;
2160*a90b9d01SCy Schubert }
2161*a90b9d01SCy Schubert
2162*a90b9d01SCy Schubert ret = _crypto_ecdh_init(group);
2163*a90b9d01SCy Schubert if (ret) {
2164*a90b9d01SCy Schubert /* Already init'ed to the right group. Enough to substitute the
2165*a90b9d01SCy Schubert * key. */
2166*a90b9d01SCy Schubert ecc_key_deinit(ret->ec->key);
2167*a90b9d01SCy Schubert ret->ec->key = own_key->eckey;
2168*a90b9d01SCy Schubert ret->ec->own_key = false;
2169*a90b9d01SCy Schubert #if defined(ECC_TIMING_RESISTANT) && !defined(WOLFSSL_OLD_FIPS)
2170*a90b9d01SCy Schubert if (!ret->ec->key->rng) {
2171*a90b9d01SCy Schubert int err = wc_ecc_set_rng(ret->ec->key, ret->rng);
2172*a90b9d01SCy Schubert
2173*a90b9d01SCy Schubert if (err != 0)
2174*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_set_rng, err);
2175*a90b9d01SCy Schubert }
2176*a90b9d01SCy Schubert #endif /* ECC_TIMING_RESISTANT && !CONFIG_FIPS */
2177*a90b9d01SCy Schubert }
2178*a90b9d01SCy Schubert
2179*a90b9d01SCy Schubert return ret;
218085732ac8SCy Schubert }
218185732ac8SCy Schubert
218285732ac8SCy Schubert
crypto_ecdh_deinit(struct crypto_ecdh * ecdh)218385732ac8SCy Schubert void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
218485732ac8SCy Schubert {
218585732ac8SCy Schubert if (ecdh) {
2186*a90b9d01SCy Schubert #if defined(ECC_TIMING_RESISTANT) && !defined(WOLFSSL_OLD_FIPS)
2187*a90b9d01SCy Schubert /* Disassociate the rng */
2188*a90b9d01SCy Schubert if (ecdh->ec && ecdh->ec->key &&
2189*a90b9d01SCy Schubert ecdh->ec->key->rng == ecdh->rng)
2190*a90b9d01SCy Schubert (void) wc_ecc_set_rng(ecdh->ec->key, NULL);
2191*a90b9d01SCy Schubert #endif /* ECC_TIMING_RESISTANT && !WOLFSSL_OLD_FIPS */
219285732ac8SCy Schubert crypto_ec_deinit(ecdh->ec);
2193*a90b9d01SCy Schubert wc_rng_deinit(ecdh->rng);
219485732ac8SCy Schubert os_free(ecdh);
219585732ac8SCy Schubert }
219685732ac8SCy Schubert }
219785732ac8SCy Schubert
219885732ac8SCy Schubert
crypto_ecdh_get_pubkey(struct crypto_ecdh * ecdh,int inc_y)219985732ac8SCy Schubert struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
220085732ac8SCy Schubert {
220185732ac8SCy Schubert struct wpabuf *buf = NULL;
220285732ac8SCy Schubert int ret;
2203*a90b9d01SCy Schubert int len = ecdh->ec->key->dp->size;
220485732ac8SCy Schubert
220585732ac8SCy Schubert buf = wpabuf_alloc(inc_y ? 2 * len : len);
220685732ac8SCy Schubert if (!buf)
220785732ac8SCy Schubert goto fail;
220885732ac8SCy Schubert
220985732ac8SCy Schubert ret = crypto_bignum_to_bin((struct crypto_bignum *)
2210*a90b9d01SCy Schubert ecdh->ec->key->pubkey.x, wpabuf_put(buf, len),
221185732ac8SCy Schubert len, len);
221285732ac8SCy Schubert if (ret < 0)
221385732ac8SCy Schubert goto fail;
221485732ac8SCy Schubert if (inc_y) {
221585732ac8SCy Schubert ret = crypto_bignum_to_bin((struct crypto_bignum *)
2216*a90b9d01SCy Schubert ecdh->ec->key->pubkey.y,
221785732ac8SCy Schubert wpabuf_put(buf, len), len, len);
221885732ac8SCy Schubert if (ret < 0)
221985732ac8SCy Schubert goto fail;
222085732ac8SCy Schubert }
222185732ac8SCy Schubert
222285732ac8SCy Schubert done:
222385732ac8SCy Schubert return buf;
222485732ac8SCy Schubert fail:
222585732ac8SCy Schubert wpabuf_free(buf);
222685732ac8SCy Schubert buf = NULL;
222785732ac8SCy Schubert goto done;
222885732ac8SCy Schubert }
222985732ac8SCy Schubert
223085732ac8SCy Schubert
crypto_ecdh_set_peerkey(struct crypto_ecdh * ecdh,int inc_y,const u8 * key,size_t len)223185732ac8SCy Schubert struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
223285732ac8SCy Schubert const u8 *key, size_t len)
223385732ac8SCy Schubert {
223485732ac8SCy Schubert int ret;
223585732ac8SCy Schubert struct wpabuf *pubkey = NULL;
223685732ac8SCy Schubert struct wpabuf *secret = NULL;
2237*a90b9d01SCy Schubert word32 key_len = ecdh->ec->key->dp->size;
223885732ac8SCy Schubert ecc_point *point = NULL;
223985732ac8SCy Schubert size_t need_key_len = inc_y ? 2 * key_len : key_len;
224085732ac8SCy Schubert
2241*a90b9d01SCy Schubert if (len < need_key_len) {
2242*a90b9d01SCy Schubert LOG_WOLF_ERROR("key len too small");
224385732ac8SCy Schubert goto fail;
2244*a90b9d01SCy Schubert }
224585732ac8SCy Schubert pubkey = wpabuf_alloc(1 + 2 * key_len);
2246*a90b9d01SCy Schubert if (!pubkey) {
2247*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
224885732ac8SCy Schubert goto fail;
2249*a90b9d01SCy Schubert }
225085732ac8SCy Schubert wpabuf_put_u8(pubkey, inc_y ? ECC_POINT_UNCOMP : ECC_POINT_COMP_EVEN);
225185732ac8SCy Schubert wpabuf_put_data(pubkey, key, need_key_len);
225285732ac8SCy Schubert
225385732ac8SCy Schubert point = wc_ecc_new_point();
2254*a90b9d01SCy Schubert if (!point) {
2255*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_ecc_new_point);
225685732ac8SCy Schubert goto fail;
2257*a90b9d01SCy Schubert }
225885732ac8SCy Schubert
225985732ac8SCy Schubert ret = wc_ecc_import_point_der(wpabuf_mhead(pubkey), 1 + 2 * key_len,
2260*a90b9d01SCy Schubert ecdh->ec->key->idx, point);
2261*a90b9d01SCy Schubert if (ret != MP_OKAY) {
2262*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_import_point_der, ret);
226385732ac8SCy Schubert goto fail;
2264*a90b9d01SCy Schubert }
226585732ac8SCy Schubert
226685732ac8SCy Schubert secret = wpabuf_alloc(key_len);
2267*a90b9d01SCy Schubert if (!secret) {
2268*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
226985732ac8SCy Schubert goto fail;
2270*a90b9d01SCy Schubert }
227185732ac8SCy Schubert
2272*a90b9d01SCy Schubert ret = wc_ecc_shared_secret_ex(ecdh->ec->key, point,
227385732ac8SCy Schubert wpabuf_put(secret, key_len), &key_len);
2274*a90b9d01SCy Schubert if (ret != MP_OKAY) {
2275*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_shared_secret_ex, ret);
227685732ac8SCy Schubert goto fail;
2277*a90b9d01SCy Schubert }
227885732ac8SCy Schubert
227985732ac8SCy Schubert done:
228085732ac8SCy Schubert wc_ecc_del_point(point);
228185732ac8SCy Schubert wpabuf_free(pubkey);
228285732ac8SCy Schubert return secret;
228385732ac8SCy Schubert fail:
228485732ac8SCy Schubert wpabuf_free(secret);
228585732ac8SCy Schubert secret = NULL;
228685732ac8SCy Schubert goto done;
228785732ac8SCy Schubert }
228885732ac8SCy Schubert
2289c1d255d3SCy Schubert
crypto_ecdh_prime_len(struct crypto_ecdh * ecdh)2290c1d255d3SCy Schubert size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
2291c1d255d3SCy Schubert {
2292c1d255d3SCy Schubert return crypto_ec_prime_len(ecdh->ec);
2293c1d255d3SCy Schubert }
2294c1d255d3SCy Schubert
crypto_ec_key_init(void)2295*a90b9d01SCy Schubert static struct crypto_ec_key * crypto_ec_key_init(void)
2296*a90b9d01SCy Schubert {
2297*a90b9d01SCy Schubert struct crypto_ec_key *key;
2298*a90b9d01SCy Schubert
2299*a90b9d01SCy Schubert key = os_zalloc(sizeof(struct crypto_ec_key));
2300*a90b9d01SCy Schubert if (key) {
2301*a90b9d01SCy Schubert key->eckey = ecc_key_init();
2302*a90b9d01SCy Schubert /* Omit key->rng initialization because it seeds itself and thus
2303*a90b9d01SCy Schubert * consumes entropy that may never be used. Lazy initialize when
2304*a90b9d01SCy Schubert * necessary. */
2305*a90b9d01SCy Schubert if (!key->eckey) {
2306*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(ecc_key_init);
2307*a90b9d01SCy Schubert crypto_ec_key_deinit(key);
2308*a90b9d01SCy Schubert key = NULL;
2309*a90b9d01SCy Schubert }
2310*a90b9d01SCy Schubert }
2311*a90b9d01SCy Schubert return key;
2312*a90b9d01SCy Schubert }
2313*a90b9d01SCy Schubert
2314*a90b9d01SCy Schubert
crypto_ec_key_deinit(struct crypto_ec_key * key)2315*a90b9d01SCy Schubert void crypto_ec_key_deinit(struct crypto_ec_key *key)
2316*a90b9d01SCy Schubert {
2317*a90b9d01SCy Schubert if (key) {
2318*a90b9d01SCy Schubert ecc_key_deinit(key->eckey);
2319*a90b9d01SCy Schubert wc_rng_deinit(key->rng);
2320*a90b9d01SCy Schubert os_free(key);
2321*a90b9d01SCy Schubert }
2322*a90b9d01SCy Schubert }
2323*a90b9d01SCy Schubert
2324*a90b9d01SCy Schubert
crypto_ec_key_init_rng(struct crypto_ec_key * key)2325*a90b9d01SCy Schubert static WC_RNG * crypto_ec_key_init_rng(struct crypto_ec_key *key)
2326*a90b9d01SCy Schubert {
2327*a90b9d01SCy Schubert if (!key->rng) {
2328*a90b9d01SCy Schubert /* Lazy init key->rng */
2329*a90b9d01SCy Schubert key->rng = wc_rng_init();
2330*a90b9d01SCy Schubert if (!key->rng)
2331*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_rng_init);
2332*a90b9d01SCy Schubert }
2333*a90b9d01SCy Schubert return key->rng;
2334*a90b9d01SCy Schubert }
2335*a90b9d01SCy Schubert
2336*a90b9d01SCy Schubert
crypto_ec_key_parse_priv(const u8 * der,size_t der_len)2337*a90b9d01SCy Schubert struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
2338*a90b9d01SCy Schubert {
2339*a90b9d01SCy Schubert struct crypto_ec_key *ret;
2340*a90b9d01SCy Schubert word32 idx = 0;
2341*a90b9d01SCy Schubert int err;
2342*a90b9d01SCy Schubert
2343*a90b9d01SCy Schubert ret = crypto_ec_key_init();
2344*a90b9d01SCy Schubert if (!ret) {
2345*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init);
2346*a90b9d01SCy Schubert goto fail;
2347*a90b9d01SCy Schubert }
2348*a90b9d01SCy Schubert
2349*a90b9d01SCy Schubert err = wc_EccPrivateKeyDecode(der, &idx, ret->eckey, (word32) der_len);
2350*a90b9d01SCy Schubert if (err != 0) {
2351*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_EccPrivateKeyDecode, err);
2352*a90b9d01SCy Schubert goto fail;
2353*a90b9d01SCy Schubert }
2354*a90b9d01SCy Schubert
2355*a90b9d01SCy Schubert return ret;
2356*a90b9d01SCy Schubert fail:
2357*a90b9d01SCy Schubert if (ret)
2358*a90b9d01SCy Schubert crypto_ec_key_deinit(ret);
2359*a90b9d01SCy Schubert return NULL;
2360*a90b9d01SCy Schubert }
2361*a90b9d01SCy Schubert
2362*a90b9d01SCy Schubert
crypto_ec_key_group(struct crypto_ec_key * key)2363*a90b9d01SCy Schubert int crypto_ec_key_group(struct crypto_ec_key *key)
2364*a90b9d01SCy Schubert {
2365*a90b9d01SCy Schubert
2366*a90b9d01SCy Schubert if (!key || !key->eckey || !key->eckey->dp) {
2367*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2368*a90b9d01SCy Schubert return -1;
2369*a90b9d01SCy Schubert }
2370*a90b9d01SCy Schubert
2371*a90b9d01SCy Schubert switch (key->eckey->dp->id) {
2372*a90b9d01SCy Schubert case ECC_SECP256R1:
2373*a90b9d01SCy Schubert return 19;
2374*a90b9d01SCy Schubert case ECC_SECP384R1:
2375*a90b9d01SCy Schubert return 20;
2376*a90b9d01SCy Schubert case ECC_SECP521R1:
2377*a90b9d01SCy Schubert return 21;
2378*a90b9d01SCy Schubert case ECC_SECP192R1:
2379*a90b9d01SCy Schubert return 25;
2380*a90b9d01SCy Schubert case ECC_SECP224R1:
2381*a90b9d01SCy Schubert return 26;
2382*a90b9d01SCy Schubert #ifdef HAVE_ECC_BRAINPOOL
2383*a90b9d01SCy Schubert case ECC_BRAINPOOLP224R1:
2384*a90b9d01SCy Schubert return 27;
2385*a90b9d01SCy Schubert case ECC_BRAINPOOLP256R1:
2386*a90b9d01SCy Schubert return 28;
2387*a90b9d01SCy Schubert case ECC_BRAINPOOLP384R1:
2388*a90b9d01SCy Schubert return 29;
2389*a90b9d01SCy Schubert case ECC_BRAINPOOLP512R1:
2390*a90b9d01SCy Schubert return 30;
2391*a90b9d01SCy Schubert #endif /* HAVE_ECC_BRAINPOOL */
2392*a90b9d01SCy Schubert }
2393*a90b9d01SCy Schubert
2394*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("Unsupported curve (id=%d) in EC key",
2395*a90b9d01SCy Schubert key->eckey->dp->id);
2396*a90b9d01SCy Schubert return -1;
2397*a90b9d01SCy Schubert }
2398*a90b9d01SCy Schubert
2399*a90b9d01SCy Schubert
crypto_ec_key_gen_public_key(struct crypto_ec_key * key)2400*a90b9d01SCy Schubert static int crypto_ec_key_gen_public_key(struct crypto_ec_key *key)
2401*a90b9d01SCy Schubert {
2402*a90b9d01SCy Schubert int err;
2403*a90b9d01SCy Schubert
2404*a90b9d01SCy Schubert #ifdef WOLFSSL_OLD_FIPS
2405*a90b9d01SCy Schubert err = wc_ecc_make_pub(key->eckey, NULL);
2406*a90b9d01SCy Schubert #else /* WOLFSSL_OLD_FIPS */
2407*a90b9d01SCy Schubert /* Have wolfSSL generate the public key to make it available for output
2408*a90b9d01SCy Schubert */
2409*a90b9d01SCy Schubert if (!crypto_ec_key_init_rng(key)) {
2410*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init_rng);
2411*a90b9d01SCy Schubert return -1;
2412*a90b9d01SCy Schubert }
2413*a90b9d01SCy Schubert
2414*a90b9d01SCy Schubert err = wc_ecc_make_pub_ex(key->eckey, NULL, key->rng);
2415*a90b9d01SCy Schubert #endif /* WOLFSSL_OLD_FIPS */
2416*a90b9d01SCy Schubert
2417*a90b9d01SCy Schubert if (err != MP_OKAY) {
2418*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_make_pub_ex, err);
2419*a90b9d01SCy Schubert return -1;
2420*a90b9d01SCy Schubert }
2421*a90b9d01SCy Schubert
2422*a90b9d01SCy Schubert return 0;
2423*a90b9d01SCy Schubert }
2424*a90b9d01SCy Schubert
2425*a90b9d01SCy Schubert
crypto_ec_key_get_subject_public_key(struct crypto_ec_key * key)2426*a90b9d01SCy Schubert struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
2427*a90b9d01SCy Schubert {
2428*a90b9d01SCy Schubert int der_len;
2429*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
2430*a90b9d01SCy Schubert int err;
2431*a90b9d01SCy Schubert
2432*a90b9d01SCy Schubert if (!key || !key->eckey) {
2433*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2434*a90b9d01SCy Schubert goto fail;
2435*a90b9d01SCy Schubert }
2436*a90b9d01SCy Schubert
2437*a90b9d01SCy Schubert #ifdef WOLFSSL_OLD_FIPS
2438*a90b9d01SCy Schubert if (key->eckey->type == ECC_PRIVATEKEY_ONLY &&
2439*a90b9d01SCy Schubert crypto_ec_key_gen_public_key(key) != 0) {
2440*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2441*a90b9d01SCy Schubert goto fail;
2442*a90b9d01SCy Schubert }
2443*a90b9d01SCy Schubert #endif /* WOLFSSL_OLD_FIPS */
2444*a90b9d01SCy Schubert
2445*a90b9d01SCy Schubert der_len = err = wc_EccPublicKeyToDer_ex(key->eckey, NULL, 0, 1, 1);
2446*a90b9d01SCy Schubert if (err == ECC_PRIVATEONLY_E) {
2447*a90b9d01SCy Schubert if (crypto_ec_key_gen_public_key(key) != 0) {
2448*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2449*a90b9d01SCy Schubert goto fail;
2450*a90b9d01SCy Schubert }
2451*a90b9d01SCy Schubert der_len = err = wc_EccPublicKeyToDer_ex(key->eckey, NULL, 0, 1,
2452*a90b9d01SCy Schubert 1);
2453*a90b9d01SCy Schubert }
2454*a90b9d01SCy Schubert if (err <= 0) {
2455*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_EccPublicKeyDerSize, err);
2456*a90b9d01SCy Schubert goto fail;
2457*a90b9d01SCy Schubert }
2458*a90b9d01SCy Schubert
2459*a90b9d01SCy Schubert ret = wpabuf_alloc(der_len);
2460*a90b9d01SCy Schubert if (!ret) {
2461*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
2462*a90b9d01SCy Schubert goto fail;
2463*a90b9d01SCy Schubert }
2464*a90b9d01SCy Schubert
2465*a90b9d01SCy Schubert err = wc_EccPublicKeyToDer_ex(key->eckey, wpabuf_mhead(ret), der_len, 1,
2466*a90b9d01SCy Schubert 1);
2467*a90b9d01SCy Schubert if (err == ECC_PRIVATEONLY_E) {
2468*a90b9d01SCy Schubert if (crypto_ec_key_gen_public_key(key) != 0) {
2469*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2470*a90b9d01SCy Schubert goto fail;
2471*a90b9d01SCy Schubert }
2472*a90b9d01SCy Schubert err = wc_EccPublicKeyToDer_ex(key->eckey, wpabuf_mhead(ret),
2473*a90b9d01SCy Schubert der_len, 1, 1);
2474*a90b9d01SCy Schubert }
2475*a90b9d01SCy Schubert if (err <= 0) {
2476*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_EccPublicKeyToDer, err);
2477*a90b9d01SCy Schubert goto fail;
2478*a90b9d01SCy Schubert }
2479*a90b9d01SCy Schubert der_len = err;
2480*a90b9d01SCy Schubert wpabuf_put(ret, der_len);
2481*a90b9d01SCy Schubert
2482*a90b9d01SCy Schubert return ret;
2483*a90b9d01SCy Schubert
2484*a90b9d01SCy Schubert fail:
2485*a90b9d01SCy Schubert wpabuf_free(ret);
2486*a90b9d01SCy Schubert return NULL;
2487*a90b9d01SCy Schubert }
2488*a90b9d01SCy Schubert
2489*a90b9d01SCy Schubert
crypto_ec_key_parse_pub(const u8 * der,size_t der_len)2490*a90b9d01SCy Schubert struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
2491*a90b9d01SCy Schubert {
2492*a90b9d01SCy Schubert word32 idx = 0;
2493*a90b9d01SCy Schubert struct crypto_ec_key *ret = NULL;
2494*a90b9d01SCy Schubert int err;
2495*a90b9d01SCy Schubert
2496*a90b9d01SCy Schubert ret = crypto_ec_key_init();
2497*a90b9d01SCy Schubert if (!ret) {
2498*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init);
2499*a90b9d01SCy Schubert goto fail;
2500*a90b9d01SCy Schubert }
2501*a90b9d01SCy Schubert
2502*a90b9d01SCy Schubert err = wc_EccPublicKeyDecode(der, &idx, ret->eckey, (word32) der_len);
2503*a90b9d01SCy Schubert if (err != 0) {
2504*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_EccPublicKeyDecode, err);
2505*a90b9d01SCy Schubert goto fail;
2506*a90b9d01SCy Schubert }
2507*a90b9d01SCy Schubert
2508*a90b9d01SCy Schubert return ret;
2509*a90b9d01SCy Schubert fail:
2510*a90b9d01SCy Schubert crypto_ec_key_deinit(ret);
2511*a90b9d01SCy Schubert return NULL;
2512*a90b9d01SCy Schubert }
2513*a90b9d01SCy Schubert
2514*a90b9d01SCy Schubert
crypto_ec_key_sign(struct crypto_ec_key * key,const u8 * data,size_t len)2515*a90b9d01SCy Schubert struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
2516*a90b9d01SCy Schubert size_t len)
2517*a90b9d01SCy Schubert {
2518*a90b9d01SCy Schubert int der_len;
2519*a90b9d01SCy Schubert int err;
2520*a90b9d01SCy Schubert word32 w32_der_len;
2521*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
2522*a90b9d01SCy Schubert
2523*a90b9d01SCy Schubert if (!key || !key->eckey || !data || len == 0) {
2524*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2525*a90b9d01SCy Schubert goto fail;
2526*a90b9d01SCy Schubert }
2527*a90b9d01SCy Schubert
2528*a90b9d01SCy Schubert if (!crypto_ec_key_init_rng(key)) {
2529*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init_rng);
2530*a90b9d01SCy Schubert goto fail;
2531*a90b9d01SCy Schubert }
2532*a90b9d01SCy Schubert
2533*a90b9d01SCy Schubert der_len = wc_ecc_sig_size(key->eckey);
2534*a90b9d01SCy Schubert if (der_len <= 0) {
2535*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_sig_size, der_len);
2536*a90b9d01SCy Schubert goto fail;
2537*a90b9d01SCy Schubert }
2538*a90b9d01SCy Schubert
2539*a90b9d01SCy Schubert ret = wpabuf_alloc(der_len);
2540*a90b9d01SCy Schubert if (!ret) {
2541*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
2542*a90b9d01SCy Schubert goto fail;
2543*a90b9d01SCy Schubert }
2544*a90b9d01SCy Schubert
2545*a90b9d01SCy Schubert w32_der_len = (word32) der_len;
2546*a90b9d01SCy Schubert err = wc_ecc_sign_hash(data, len, wpabuf_mhead(ret), &w32_der_len,
2547*a90b9d01SCy Schubert key->rng, key->eckey);
2548*a90b9d01SCy Schubert if (err != 0) {
2549*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_sign_hash, err);
2550*a90b9d01SCy Schubert goto fail;
2551*a90b9d01SCy Schubert }
2552*a90b9d01SCy Schubert wpabuf_put(ret, w32_der_len);
2553*a90b9d01SCy Schubert
2554*a90b9d01SCy Schubert return ret;
2555*a90b9d01SCy Schubert fail:
2556*a90b9d01SCy Schubert wpabuf_free(ret);
2557*a90b9d01SCy Schubert return NULL;
2558*a90b9d01SCy Schubert }
2559*a90b9d01SCy Schubert
2560*a90b9d01SCy Schubert
crypto_ec_key_verify_signature(struct crypto_ec_key * key,const u8 * data,size_t len,const u8 * sig,size_t sig_len)2561*a90b9d01SCy Schubert int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
2562*a90b9d01SCy Schubert size_t len, const u8 *sig, size_t sig_len)
2563*a90b9d01SCy Schubert {
2564*a90b9d01SCy Schubert int res = 0;
2565*a90b9d01SCy Schubert
2566*a90b9d01SCy Schubert if (!key || !key->eckey || !data || len == 0 || !sig || sig_len == 0) {
2567*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2568*a90b9d01SCy Schubert return -1;
2569*a90b9d01SCy Schubert }
2570*a90b9d01SCy Schubert
2571*a90b9d01SCy Schubert if (wc_ecc_verify_hash(sig, sig_len, data, len, &res, key->eckey) != 0)
2572*a90b9d01SCy Schubert {
2573*a90b9d01SCy Schubert LOG_WOLF_ERROR("wc_ecc_verify_hash failed");
2574*a90b9d01SCy Schubert return -1;
2575*a90b9d01SCy Schubert }
2576*a90b9d01SCy Schubert
2577*a90b9d01SCy Schubert if (res != 1)
2578*a90b9d01SCy Schubert LOG_WOLF_ERROR("crypto_ec_key_verify_signature failed");
2579*a90b9d01SCy Schubert
2580*a90b9d01SCy Schubert return res;
2581*a90b9d01SCy Schubert }
2582*a90b9d01SCy Schubert
258385732ac8SCy Schubert #endif /* CONFIG_ECC */
2584*a90b9d01SCy Schubert
2585*a90b9d01SCy Schubert #ifdef CONFIG_DPP
2586*a90b9d01SCy Schubert
crypto_ec_key_get_ecprivate_key(struct crypto_ec_key * key,bool include_pub)2587*a90b9d01SCy Schubert struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
2588*a90b9d01SCy Schubert bool include_pub)
2589*a90b9d01SCy Schubert {
2590*a90b9d01SCy Schubert int len;
2591*a90b9d01SCy Schubert int err;
2592*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
2593*a90b9d01SCy Schubert
2594*a90b9d01SCy Schubert if (!key || !key->eckey) {
2595*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2596*a90b9d01SCy Schubert return NULL;
2597*a90b9d01SCy Schubert }
2598*a90b9d01SCy Schubert
2599*a90b9d01SCy Schubert #ifdef WOLFSSL_OLD_FIPS
2600*a90b9d01SCy Schubert if (key->eckey->type != ECC_PRIVATEKEY &&
2601*a90b9d01SCy Schubert key->eckey->type != ECC_PRIVATEKEY_ONLY) {
2602*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2603*a90b9d01SCy Schubert return NULL;
2604*a90b9d01SCy Schubert }
2605*a90b9d01SCy Schubert #endif /* WOLFSSL_OLD_FIPS */
2606*a90b9d01SCy Schubert
2607*a90b9d01SCy Schubert len = err = wc_EccKeyDerSize(key->eckey, include_pub);
2608*a90b9d01SCy Schubert if (err == ECC_PRIVATEONLY_E && include_pub) {
2609*a90b9d01SCy Schubert if (crypto_ec_key_gen_public_key(key) != 0) {
2610*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2611*a90b9d01SCy Schubert return NULL;
2612*a90b9d01SCy Schubert }
2613*a90b9d01SCy Schubert len = err = wc_EccKeyDerSize(key->eckey, include_pub);
2614*a90b9d01SCy Schubert }
2615*a90b9d01SCy Schubert if (err <= 0) {
2616*a90b9d01SCy Schubert /* Exception for BAD_FUNC_ARG because higher levels blindly call
2617*a90b9d01SCy Schubert * this function to determine if this is a private key or not.
2618*a90b9d01SCy Schubert * BAD_FUNC_ARG most probably means that key->eckey is a public
2619*a90b9d01SCy Schubert * key not private. */
2620*a90b9d01SCy Schubert if (err != BAD_FUNC_ARG)
2621*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_EccKeyDerSize, err);
2622*a90b9d01SCy Schubert return NULL;
2623*a90b9d01SCy Schubert }
2624*a90b9d01SCy Schubert
2625*a90b9d01SCy Schubert ret = wpabuf_alloc(len);
2626*a90b9d01SCy Schubert if (!ret) {
2627*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
2628*a90b9d01SCy Schubert return NULL;
2629*a90b9d01SCy Schubert }
2630*a90b9d01SCy Schubert
2631*a90b9d01SCy Schubert if (include_pub)
2632*a90b9d01SCy Schubert err = wc_EccKeyToDer(key->eckey, wpabuf_put(ret, len), len);
2633*a90b9d01SCy Schubert else
2634*a90b9d01SCy Schubert err = wc_EccPrivateKeyToDer(key->eckey, wpabuf_put(ret, len),
2635*a90b9d01SCy Schubert len);
2636*a90b9d01SCy Schubert
2637*a90b9d01SCy Schubert if (err != len) {
2638*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("%s failed with err: %d", include_pub ?
2639*a90b9d01SCy Schubert "wc_EccKeyToDer" : "wc_EccPrivateKeyToDer",
2640*a90b9d01SCy Schubert err);
2641*a90b9d01SCy Schubert wpabuf_free(ret);
2642*a90b9d01SCy Schubert ret = NULL;
2643*a90b9d01SCy Schubert }
2644*a90b9d01SCy Schubert
2645*a90b9d01SCy Schubert return ret;
2646*a90b9d01SCy Schubert }
2647*a90b9d01SCy Schubert
2648*a90b9d01SCy Schubert
crypto_ec_key_get_pubkey_point(struct crypto_ec_key * key,int prefix)2649*a90b9d01SCy Schubert struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
2650*a90b9d01SCy Schubert int prefix)
2651*a90b9d01SCy Schubert {
2652*a90b9d01SCy Schubert int err;
2653*a90b9d01SCy Schubert word32 len = 0;
2654*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
2655*a90b9d01SCy Schubert
2656*a90b9d01SCy Schubert if (!key || !key->eckey) {
2657*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2658*a90b9d01SCy Schubert return NULL;
2659*a90b9d01SCy Schubert }
2660*a90b9d01SCy Schubert
2661*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, NULL, &len);
2662*a90b9d01SCy Schubert if (err != LENGTH_ONLY_E) {
2663*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_x963, err);
2664*a90b9d01SCy Schubert goto fail;
2665*a90b9d01SCy Schubert }
2666*a90b9d01SCy Schubert
2667*a90b9d01SCy Schubert ret = wpabuf_alloc(len);
2668*a90b9d01SCy Schubert if (!ret) {
2669*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
2670*a90b9d01SCy Schubert goto fail;
2671*a90b9d01SCy Schubert }
2672*a90b9d01SCy Schubert
2673*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, wpabuf_mhead(ret), &len);
2674*a90b9d01SCy Schubert if (err == ECC_PRIVATEONLY_E) {
2675*a90b9d01SCy Schubert if (crypto_ec_key_gen_public_key(key) != 0) {
2676*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2677*a90b9d01SCy Schubert goto fail;
2678*a90b9d01SCy Schubert }
2679*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, wpabuf_mhead(ret), &len);
2680*a90b9d01SCy Schubert }
2681*a90b9d01SCy Schubert if (err != MP_OKAY) {
2682*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_x963, err);
2683*a90b9d01SCy Schubert goto fail;
2684*a90b9d01SCy Schubert }
2685*a90b9d01SCy Schubert
2686*a90b9d01SCy Schubert if (!prefix)
2687*a90b9d01SCy Schubert os_memmove(wpabuf_mhead(ret), wpabuf_mhead_u8(ret) + 1,
2688*a90b9d01SCy Schubert (size_t)--len);
2689*a90b9d01SCy Schubert wpabuf_put(ret, len);
2690*a90b9d01SCy Schubert
2691*a90b9d01SCy Schubert return ret;
2692*a90b9d01SCy Schubert
2693*a90b9d01SCy Schubert fail:
2694*a90b9d01SCy Schubert wpabuf_free(ret);
2695*a90b9d01SCy Schubert return NULL;
2696*a90b9d01SCy Schubert }
2697*a90b9d01SCy Schubert
2698*a90b9d01SCy Schubert
crypto_ec_key_set_pub(int group,const u8 * x,const u8 * y,size_t len)2699*a90b9d01SCy Schubert struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x,
2700*a90b9d01SCy Schubert const u8 *y, size_t len)
2701*a90b9d01SCy Schubert {
2702*a90b9d01SCy Schubert struct crypto_ec_key *ret = NULL;
2703*a90b9d01SCy Schubert int curve_id = crypto_ec_group_2_id(group);
2704*a90b9d01SCy Schubert int err;
2705*a90b9d01SCy Schubert
2706*a90b9d01SCy Schubert if (!x || !y || len == 0 || curve_id == ECC_CURVE_INVALID ||
2707*a90b9d01SCy Schubert wc_ecc_get_curve_size_from_id(curve_id) != (int) len) {
2708*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2709*a90b9d01SCy Schubert return NULL;
2710*a90b9d01SCy Schubert }
2711*a90b9d01SCy Schubert
2712*a90b9d01SCy Schubert ret = crypto_ec_key_init();
2713*a90b9d01SCy Schubert if (!ret) {
2714*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init);
2715*a90b9d01SCy Schubert return NULL;
2716*a90b9d01SCy Schubert }
2717*a90b9d01SCy Schubert
2718*a90b9d01SCy Schubert /* Cast necessary for FIPS API */
2719*a90b9d01SCy Schubert err = wc_ecc_import_unsigned(ret->eckey, (u8 *) x, (u8 *) y, NULL,
2720*a90b9d01SCy Schubert curve_id);
2721*a90b9d01SCy Schubert if (err != MP_OKAY) {
2722*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_import_unsigned, err);
2723*a90b9d01SCy Schubert crypto_ec_key_deinit(ret);
2724*a90b9d01SCy Schubert return NULL;
2725*a90b9d01SCy Schubert }
2726*a90b9d01SCy Schubert
2727*a90b9d01SCy Schubert return ret;
2728*a90b9d01SCy Schubert }
2729*a90b9d01SCy Schubert
2730*a90b9d01SCy Schubert
crypto_ec_key_cmp(struct crypto_ec_key * key1,struct crypto_ec_key * key2)2731*a90b9d01SCy Schubert int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
2732*a90b9d01SCy Schubert {
2733*a90b9d01SCy Schubert int ret;
2734*a90b9d01SCy Schubert struct wpabuf *key1_buf = crypto_ec_key_get_subject_public_key(key1);
2735*a90b9d01SCy Schubert struct wpabuf *key2_buf = crypto_ec_key_get_subject_public_key(key2);
2736*a90b9d01SCy Schubert
2737*a90b9d01SCy Schubert if ((key1 && !key1_buf) || (key2 && !key2_buf)) {
2738*a90b9d01SCy Schubert LOG_WOLF_ERROR("crypto_ec_key_get_subject_public_key failed");
2739*a90b9d01SCy Schubert return -1;
2740*a90b9d01SCy Schubert }
2741*a90b9d01SCy Schubert
2742*a90b9d01SCy Schubert ret = wpabuf_cmp(key1_buf, key2_buf);
2743*a90b9d01SCy Schubert if (ret != 0)
2744*a90b9d01SCy Schubert ret = -1; /* Default to -1 for different keys */
2745*a90b9d01SCy Schubert
2746*a90b9d01SCy Schubert wpabuf_clear_free(key1_buf);
2747*a90b9d01SCy Schubert wpabuf_clear_free(key2_buf);
2748*a90b9d01SCy Schubert return ret;
2749*a90b9d01SCy Schubert }
2750*a90b9d01SCy Schubert
2751*a90b9d01SCy Schubert
2752*a90b9d01SCy Schubert /* wolfSSL doesn't have a pretty print function for keys so just print out the
2753*a90b9d01SCy Schubert * PEM of the private key. */
crypto_ec_key_debug_print(const struct crypto_ec_key * key,const char * title)2754*a90b9d01SCy Schubert void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
2755*a90b9d01SCy Schubert const char *title)
2756*a90b9d01SCy Schubert {
2757*a90b9d01SCy Schubert struct wpabuf * key_buf;
2758*a90b9d01SCy Schubert struct wpabuf * out = NULL;
2759*a90b9d01SCy Schubert int err;
2760*a90b9d01SCy Schubert int pem_len;
2761*a90b9d01SCy Schubert
2762*a90b9d01SCy Schubert if (!key || !key->eckey) {
2763*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2764*a90b9d01SCy Schubert return;
2765*a90b9d01SCy Schubert }
2766*a90b9d01SCy Schubert
2767*a90b9d01SCy Schubert if (key->eckey->type == ECC_PUBLICKEY)
2768*a90b9d01SCy Schubert key_buf = crypto_ec_key_get_subject_public_key(
2769*a90b9d01SCy Schubert (struct crypto_ec_key *) key);
2770*a90b9d01SCy Schubert else
2771*a90b9d01SCy Schubert key_buf = crypto_ec_key_get_ecprivate_key(
2772*a90b9d01SCy Schubert (struct crypto_ec_key *) key, 1);
2773*a90b9d01SCy Schubert
2774*a90b9d01SCy Schubert if (!key_buf) {
2775*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("%s has returned NULL",
2776*a90b9d01SCy Schubert key->eckey->type == ECC_PUBLICKEY ?
2777*a90b9d01SCy Schubert "crypto_ec_key_get_subject_public_key" :
2778*a90b9d01SCy Schubert "crypto_ec_key_get_ecprivate_key");
2779*a90b9d01SCy Schubert goto fail;
2780*a90b9d01SCy Schubert }
2781*a90b9d01SCy Schubert
2782*a90b9d01SCy Schubert if (!title)
2783*a90b9d01SCy Schubert title = "";
2784*a90b9d01SCy Schubert
2785*a90b9d01SCy Schubert err = wc_DerToPem(wpabuf_head(key_buf), wpabuf_len(key_buf), NULL, 0,
2786*a90b9d01SCy Schubert ECC_TYPE);
2787*a90b9d01SCy Schubert if (err <= 0) {
2788*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_DerToPem, err);
2789*a90b9d01SCy Schubert goto fail;
2790*a90b9d01SCy Schubert }
2791*a90b9d01SCy Schubert pem_len = err;
2792*a90b9d01SCy Schubert
2793*a90b9d01SCy Schubert out = wpabuf_alloc(pem_len + 1);
2794*a90b9d01SCy Schubert if (!out) {
2795*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_DerToPem);
2796*a90b9d01SCy Schubert goto fail;
2797*a90b9d01SCy Schubert }
2798*a90b9d01SCy Schubert
2799*a90b9d01SCy Schubert err = wc_DerToPem(wpabuf_head(key_buf), wpabuf_len(key_buf),
2800*a90b9d01SCy Schubert wpabuf_mhead(out), pem_len, ECC_TYPE);
2801*a90b9d01SCy Schubert if (err <= 0) {
2802*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_DerToPem, err);
2803*a90b9d01SCy Schubert goto fail;
2804*a90b9d01SCy Schubert }
2805*a90b9d01SCy Schubert
2806*a90b9d01SCy Schubert wpabuf_mhead_u8(out)[err] = '\0';
2807*a90b9d01SCy Schubert wpabuf_put(out, err + 1);
2808*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "%s:\n%s", title,
2809*a90b9d01SCy Schubert (const char *) wpabuf_head(out));
2810*a90b9d01SCy Schubert
2811*a90b9d01SCy Schubert fail:
2812*a90b9d01SCy Schubert wpabuf_clear_free(key_buf);
2813*a90b9d01SCy Schubert wpabuf_clear_free(out);
2814*a90b9d01SCy Schubert }
2815*a90b9d01SCy Schubert
2816*a90b9d01SCy Schubert
crypto_ec_point_debug_print(const struct crypto_ec * e,const struct crypto_ec_point * p,const char * title)2817*a90b9d01SCy Schubert void crypto_ec_point_debug_print(const struct crypto_ec *e,
2818*a90b9d01SCy Schubert const struct crypto_ec_point *p,
2819*a90b9d01SCy Schubert const char *title)
2820*a90b9d01SCy Schubert {
2821*a90b9d01SCy Schubert u8 x[ECC_MAXSIZE];
2822*a90b9d01SCy Schubert u8 y[ECC_MAXSIZE];
2823*a90b9d01SCy Schubert int coord_size;
2824*a90b9d01SCy Schubert int err;
2825*a90b9d01SCy Schubert
2826*a90b9d01SCy Schubert if (!p || !e) {
2827*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2828*a90b9d01SCy Schubert return;
2829*a90b9d01SCy Schubert }
2830*a90b9d01SCy Schubert
2831*a90b9d01SCy Schubert coord_size = e->key->dp->size;
2832*a90b9d01SCy Schubert
2833*a90b9d01SCy Schubert if (!title)
2834*a90b9d01SCy Schubert title = "";
2835*a90b9d01SCy Schubert
2836*a90b9d01SCy Schubert err = crypto_ec_point_to_bin((struct crypto_ec *)e, p, x, y);
2837*a90b9d01SCy Schubert if (err != 0) {
2838*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_point_to_bin, err);
2839*a90b9d01SCy Schubert return;
2840*a90b9d01SCy Schubert }
2841*a90b9d01SCy Schubert
2842*a90b9d01SCy Schubert wpa_hexdump(MSG_DEBUG, title, x, coord_size);
2843*a90b9d01SCy Schubert wpa_hexdump(MSG_DEBUG, title, y, coord_size);
2844*a90b9d01SCy Schubert }
2845*a90b9d01SCy Schubert
2846*a90b9d01SCy Schubert
crypto_ec_key_gen(int group)2847*a90b9d01SCy Schubert struct crypto_ec_key * crypto_ec_key_gen(int group)
2848*a90b9d01SCy Schubert {
2849*a90b9d01SCy Schubert int curve_id = crypto_ec_group_2_id(group);
2850*a90b9d01SCy Schubert int err;
2851*a90b9d01SCy Schubert struct crypto_ec_key * ret = NULL;
2852*a90b9d01SCy Schubert
2853*a90b9d01SCy Schubert if (curve_id == ECC_CURVE_INVALID) {
2854*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2855*a90b9d01SCy Schubert return NULL;
2856*a90b9d01SCy Schubert }
2857*a90b9d01SCy Schubert
2858*a90b9d01SCy Schubert ret = crypto_ec_key_init();
2859*a90b9d01SCy Schubert if (!ret) {
2860*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init);
2861*a90b9d01SCy Schubert return NULL;
2862*a90b9d01SCy Schubert }
2863*a90b9d01SCy Schubert
2864*a90b9d01SCy Schubert if (!crypto_ec_key_init_rng(ret)) {
2865*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init_rng);
2866*a90b9d01SCy Schubert goto fail;
2867*a90b9d01SCy Schubert }
2868*a90b9d01SCy Schubert
2869*a90b9d01SCy Schubert err = wc_ecc_make_key_ex(ret->rng, 0, ret->eckey, curve_id);
2870*a90b9d01SCy Schubert if (err != MP_OKAY) {
2871*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_make_key_ex, err);
2872*a90b9d01SCy Schubert goto fail;
2873*a90b9d01SCy Schubert }
2874*a90b9d01SCy Schubert
2875*a90b9d01SCy Schubert return ret;
2876*a90b9d01SCy Schubert fail:
2877*a90b9d01SCy Schubert crypto_ec_key_deinit(ret);
2878*a90b9d01SCy Schubert return NULL;
2879*a90b9d01SCy Schubert }
2880*a90b9d01SCy Schubert
2881*a90b9d01SCy Schubert
crypto_ec_key_verify_signature_r_s(struct crypto_ec_key * key,const u8 * data,size_t len,const u8 * r,size_t r_len,const u8 * s,size_t s_len)2882*a90b9d01SCy Schubert int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
2883*a90b9d01SCy Schubert const u8 *data, size_t len,
2884*a90b9d01SCy Schubert const u8 *r, size_t r_len,
2885*a90b9d01SCy Schubert const u8 *s, size_t s_len)
2886*a90b9d01SCy Schubert {
2887*a90b9d01SCy Schubert int err;
2888*a90b9d01SCy Schubert u8 sig[ECC_MAX_SIG_SIZE];
2889*a90b9d01SCy Schubert word32 sig_len = ECC_MAX_SIG_SIZE;
2890*a90b9d01SCy Schubert
2891*a90b9d01SCy Schubert if (!key || !key->eckey || !data || !len || !r || !r_len ||
2892*a90b9d01SCy Schubert !s || !s_len) {
2893*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2894*a90b9d01SCy Schubert return -1;
2895*a90b9d01SCy Schubert }
2896*a90b9d01SCy Schubert
2897*a90b9d01SCy Schubert err = wc_ecc_rs_raw_to_sig(r, r_len, s, s_len, sig, &sig_len);
2898*a90b9d01SCy Schubert if (err != MP_OKAY) {
2899*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_rs_raw_to_sig, err);
2900*a90b9d01SCy Schubert return -1;
2901*a90b9d01SCy Schubert }
2902*a90b9d01SCy Schubert
2903*a90b9d01SCy Schubert return crypto_ec_key_verify_signature(key, data, len, sig, sig_len);
2904*a90b9d01SCy Schubert }
2905*a90b9d01SCy Schubert
2906*a90b9d01SCy Schubert
crypto_ec_key_get_public_key(struct crypto_ec_key * key)2907*a90b9d01SCy Schubert struct crypto_ec_point * crypto_ec_key_get_public_key(struct crypto_ec_key *key)
2908*a90b9d01SCy Schubert {
2909*a90b9d01SCy Schubert ecc_point *point = NULL;
2910*a90b9d01SCy Schubert int err;
2911*a90b9d01SCy Schubert u8 *der = NULL;
2912*a90b9d01SCy Schubert word32 der_len = 0;
2913*a90b9d01SCy Schubert
2914*a90b9d01SCy Schubert if (!key || !key->eckey || !key->eckey->dp) {
2915*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2916*a90b9d01SCy Schubert goto fail;
2917*a90b9d01SCy Schubert }
2918*a90b9d01SCy Schubert
2919*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, NULL, &der_len);
2920*a90b9d01SCy Schubert if (err != LENGTH_ONLY_E) {
2921*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_x963, err);
2922*a90b9d01SCy Schubert goto fail;
2923*a90b9d01SCy Schubert }
2924*a90b9d01SCy Schubert
2925*a90b9d01SCy Schubert der = os_malloc(der_len);
2926*a90b9d01SCy Schubert if (!der) {
2927*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
2928*a90b9d01SCy Schubert goto fail;
2929*a90b9d01SCy Schubert }
2930*a90b9d01SCy Schubert
2931*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, der, &der_len);
2932*a90b9d01SCy Schubert if (err == ECC_PRIVATEONLY_E) {
2933*a90b9d01SCy Schubert if (crypto_ec_key_gen_public_key(key) != 0) {
2934*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(crypto_ec_key_gen_public_key, -1);
2935*a90b9d01SCy Schubert goto fail;
2936*a90b9d01SCy Schubert }
2937*a90b9d01SCy Schubert err = wc_ecc_export_x963(key->eckey, der, &der_len);
2938*a90b9d01SCy Schubert }
2939*a90b9d01SCy Schubert if (err != MP_OKAY) {
2940*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_x963, err);
2941*a90b9d01SCy Schubert goto fail;
2942*a90b9d01SCy Schubert }
2943*a90b9d01SCy Schubert
2944*a90b9d01SCy Schubert point = wc_ecc_new_point();
2945*a90b9d01SCy Schubert if (!point) {
2946*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_ecc_new_point);
2947*a90b9d01SCy Schubert goto fail;
2948*a90b9d01SCy Schubert }
2949*a90b9d01SCy Schubert
2950*a90b9d01SCy Schubert err = wc_ecc_import_point_der(der, der_len, key->eckey->idx, point);
2951*a90b9d01SCy Schubert if (err != MP_OKAY) {
2952*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_import_point_der, err);
2953*a90b9d01SCy Schubert goto fail;
2954*a90b9d01SCy Schubert }
2955*a90b9d01SCy Schubert
2956*a90b9d01SCy Schubert os_free(der);
2957*a90b9d01SCy Schubert return (struct crypto_ec_point *) point;
2958*a90b9d01SCy Schubert
2959*a90b9d01SCy Schubert fail:
2960*a90b9d01SCy Schubert os_free(der);
2961*a90b9d01SCy Schubert if (point)
2962*a90b9d01SCy Schubert wc_ecc_del_point(point);
2963*a90b9d01SCy Schubert return NULL;
2964*a90b9d01SCy Schubert }
2965*a90b9d01SCy Schubert
2966*a90b9d01SCy Schubert
crypto_ec_key_get_private_key(struct crypto_ec_key * key)2967*a90b9d01SCy Schubert struct crypto_bignum * crypto_ec_key_get_private_key(struct crypto_ec_key *key)
2968*a90b9d01SCy Schubert {
2969*a90b9d01SCy Schubert u8 priv[ECC_MAXSIZE];
2970*a90b9d01SCy Schubert word32 priv_len = ECC_MAXSIZE;
2971*a90b9d01SCy Schubert #ifdef WOLFSSL_OLD_FIPS
2972*a90b9d01SCy Schubert /* Needed to be compliant with the old API */
2973*a90b9d01SCy Schubert u8 qx[ECC_MAXSIZE];
2974*a90b9d01SCy Schubert word32 qx_len = ECC_MAXSIZE;
2975*a90b9d01SCy Schubert u8 qy[ECC_MAXSIZE];
2976*a90b9d01SCy Schubert word32 qy_len = ECC_MAXSIZE;
2977*a90b9d01SCy Schubert #endif /* WOLFSSL_OLD_FIPS */
2978*a90b9d01SCy Schubert struct crypto_bignum *ret = NULL;
2979*a90b9d01SCy Schubert int err;
2980*a90b9d01SCy Schubert
2981*a90b9d01SCy Schubert if (!key || !key->eckey) {
2982*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
2983*a90b9d01SCy Schubert return NULL;
2984*a90b9d01SCy Schubert }
2985*a90b9d01SCy Schubert
2986*a90b9d01SCy Schubert #ifndef WOLFSSL_OLD_FIPS
2987*a90b9d01SCy Schubert err = wc_ecc_export_private_raw(key->eckey, NULL, NULL, NULL, NULL,
2988*a90b9d01SCy Schubert priv, &priv_len);
2989*a90b9d01SCy Schubert #else /* WOLFSSL_OLD_FIPS */
2990*a90b9d01SCy Schubert err = wc_ecc_export_private_raw(key->eckey, qx, &qx_len, qy, &qy_len,
2991*a90b9d01SCy Schubert priv, &priv_len);
2992*a90b9d01SCy Schubert #endif /* WOLFSSL_OLD_FIPS */
2993*a90b9d01SCy Schubert if (err != MP_OKAY) {
2994*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_private_raw, err);
2995*a90b9d01SCy Schubert return NULL;
2996*a90b9d01SCy Schubert }
2997*a90b9d01SCy Schubert
2998*a90b9d01SCy Schubert ret = crypto_bignum_init_set(priv, priv_len);
2999*a90b9d01SCy Schubert forced_memzero(priv, priv_len);
3000*a90b9d01SCy Schubert return ret;
3001*a90b9d01SCy Schubert }
3002*a90b9d01SCy Schubert
3003*a90b9d01SCy Schubert
crypto_ec_key_sign_r_s(struct crypto_ec_key * key,const u8 * data,size_t len)3004*a90b9d01SCy Schubert struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
3005*a90b9d01SCy Schubert const u8 *data, size_t len)
3006*a90b9d01SCy Schubert {
3007*a90b9d01SCy Schubert int err;
3008*a90b9d01SCy Schubert u8 success = 0;
3009*a90b9d01SCy Schubert mp_int r;
3010*a90b9d01SCy Schubert mp_int s;
3011*a90b9d01SCy Schubert u8 rs_init = 0;
3012*a90b9d01SCy Schubert int sz;
3013*a90b9d01SCy Schubert struct wpabuf * ret = NULL;
3014*a90b9d01SCy Schubert
3015*a90b9d01SCy Schubert if (!key || !key->eckey || !key->eckey->dp || !data || !len) {
3016*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3017*a90b9d01SCy Schubert return NULL;
3018*a90b9d01SCy Schubert }
3019*a90b9d01SCy Schubert
3020*a90b9d01SCy Schubert sz = key->eckey->dp->size;
3021*a90b9d01SCy Schubert
3022*a90b9d01SCy Schubert if (!crypto_ec_key_init_rng(key)) {
3023*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init_rng);
3024*a90b9d01SCy Schubert goto fail;
3025*a90b9d01SCy Schubert }
3026*a90b9d01SCy Schubert
3027*a90b9d01SCy Schubert err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL);
3028*a90b9d01SCy Schubert if (err != MP_OKAY) {
3029*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(mp_init_multi, err);
3030*a90b9d01SCy Schubert goto fail;
3031*a90b9d01SCy Schubert }
3032*a90b9d01SCy Schubert rs_init = 1;
3033*a90b9d01SCy Schubert
3034*a90b9d01SCy Schubert err = wc_ecc_sign_hash_ex(data, len, key->rng, key->eckey, &r, &s);
3035*a90b9d01SCy Schubert if (err != MP_OKAY) {
3036*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_sign_hash_ex, err);
3037*a90b9d01SCy Schubert goto fail;
3038*a90b9d01SCy Schubert }
3039*a90b9d01SCy Schubert
3040*a90b9d01SCy Schubert if (mp_unsigned_bin_size(&r) > sz || mp_unsigned_bin_size(&s) > sz) {
3041*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("Unexpected size of r or s (%d %d %d)", sz,
3042*a90b9d01SCy Schubert mp_unsigned_bin_size(&r),
3043*a90b9d01SCy Schubert mp_unsigned_bin_size(&s));
3044*a90b9d01SCy Schubert goto fail;
3045*a90b9d01SCy Schubert }
3046*a90b9d01SCy Schubert
3047*a90b9d01SCy Schubert ret = wpabuf_alloc(2 * sz);
3048*a90b9d01SCy Schubert if (!ret) {
3049*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
3050*a90b9d01SCy Schubert goto fail;
3051*a90b9d01SCy Schubert }
3052*a90b9d01SCy Schubert
3053*a90b9d01SCy Schubert err = mp_to_unsigned_bin_len(&r, wpabuf_put(ret, sz), sz);
3054*a90b9d01SCy Schubert if (err == MP_OKAY)
3055*a90b9d01SCy Schubert err = mp_to_unsigned_bin_len(&s, wpabuf_put(ret, sz), sz);
3056*a90b9d01SCy Schubert if (err != MP_OKAY) {
3057*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_sign_hash_ex, err);
3058*a90b9d01SCy Schubert goto fail;
3059*a90b9d01SCy Schubert }
3060*a90b9d01SCy Schubert
3061*a90b9d01SCy Schubert success = 1;
3062*a90b9d01SCy Schubert fail:
3063*a90b9d01SCy Schubert if (rs_init) {
3064*a90b9d01SCy Schubert mp_free(&r);
3065*a90b9d01SCy Schubert mp_free(&s);
3066*a90b9d01SCy Schubert }
3067*a90b9d01SCy Schubert if (!success) {
3068*a90b9d01SCy Schubert wpabuf_free(ret);
3069*a90b9d01SCy Schubert ret = NULL;
3070*a90b9d01SCy Schubert }
3071*a90b9d01SCy Schubert
3072*a90b9d01SCy Schubert return ret;
3073*a90b9d01SCy Schubert }
3074*a90b9d01SCy Schubert
3075*a90b9d01SCy Schubert
3076*a90b9d01SCy Schubert struct crypto_ec_key *
crypto_ec_key_set_pub_point(struct crypto_ec * e,const struct crypto_ec_point * pub)3077*a90b9d01SCy Schubert crypto_ec_key_set_pub_point(struct crypto_ec *e,
3078*a90b9d01SCy Schubert const struct crypto_ec_point *pub)
3079*a90b9d01SCy Schubert {
3080*a90b9d01SCy Schubert struct crypto_ec_key *ret = NULL;
3081*a90b9d01SCy Schubert int err;
3082*a90b9d01SCy Schubert byte *buf = NULL;
3083*a90b9d01SCy Schubert word32 buf_len = 0;
3084*a90b9d01SCy Schubert
3085*a90b9d01SCy Schubert if (!e || !pub) {
3086*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3087*a90b9d01SCy Schubert return NULL;
3088*a90b9d01SCy Schubert }
3089*a90b9d01SCy Schubert
3090*a90b9d01SCy Schubert /* Export to DER to not mess with wolfSSL internals */
3091*a90b9d01SCy Schubert err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(e->curve_id),
3092*a90b9d01SCy Schubert (ecc_point *) pub, NULL, &buf_len);
3093*a90b9d01SCy Schubert if (err != LENGTH_ONLY_E || !buf_len) {
3094*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_point_der, err);
3095*a90b9d01SCy Schubert goto fail;
3096*a90b9d01SCy Schubert }
3097*a90b9d01SCy Schubert
3098*a90b9d01SCy Schubert buf = os_malloc(buf_len);
3099*a90b9d01SCy Schubert if (!buf) {
3100*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
3101*a90b9d01SCy Schubert goto fail;
3102*a90b9d01SCy Schubert }
3103*a90b9d01SCy Schubert
3104*a90b9d01SCy Schubert err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(e->curve_id),
3105*a90b9d01SCy Schubert (ecc_point *) pub, buf, &buf_len);
3106*a90b9d01SCy Schubert if (err != MP_OKAY) {
3107*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_export_point_der, err);
3108*a90b9d01SCy Schubert goto fail;
3109*a90b9d01SCy Schubert }
3110*a90b9d01SCy Schubert
3111*a90b9d01SCy Schubert ret = crypto_ec_key_init();
3112*a90b9d01SCy Schubert if (!ret) {
3113*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init);
3114*a90b9d01SCy Schubert goto fail;
3115*a90b9d01SCy Schubert }
3116*a90b9d01SCy Schubert
3117*a90b9d01SCy Schubert err = wc_ecc_import_x963_ex(buf, buf_len, ret->eckey, e->curve_id);
3118*a90b9d01SCy Schubert if (err != MP_OKAY) {
3119*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ecc_import_x963_ex, err);
3120*a90b9d01SCy Schubert goto fail;
3121*a90b9d01SCy Schubert }
3122*a90b9d01SCy Schubert
3123*a90b9d01SCy Schubert os_free(buf);
3124*a90b9d01SCy Schubert return ret;
3125*a90b9d01SCy Schubert
3126*a90b9d01SCy Schubert fail:
3127*a90b9d01SCy Schubert os_free(buf);
3128*a90b9d01SCy Schubert crypto_ec_key_deinit(ret);
3129*a90b9d01SCy Schubert return NULL;
3130*a90b9d01SCy Schubert }
3131*a90b9d01SCy Schubert
3132*a90b9d01SCy Schubert
crypto_pkcs7_get_certificates(const struct wpabuf * pkcs7)3133*a90b9d01SCy Schubert struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
3134*a90b9d01SCy Schubert {
3135*a90b9d01SCy Schubert PKCS7 *p7 = NULL;
3136*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
3137*a90b9d01SCy Schubert int err = 0;
3138*a90b9d01SCy Schubert int total_sz = 0;
3139*a90b9d01SCy Schubert int i;
3140*a90b9d01SCy Schubert
3141*a90b9d01SCy Schubert if (!pkcs7) {
3142*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3143*a90b9d01SCy Schubert return NULL;
3144*a90b9d01SCy Schubert }
3145*a90b9d01SCy Schubert
3146*a90b9d01SCy Schubert p7 = wc_PKCS7_New(NULL, INVALID_DEVID);
3147*a90b9d01SCy Schubert if (!p7) {
3148*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wc_PKCS7_New);
3149*a90b9d01SCy Schubert return NULL;
3150*a90b9d01SCy Schubert }
3151*a90b9d01SCy Schubert
3152*a90b9d01SCy Schubert err = wc_PKCS7_VerifySignedData(p7, (byte *) wpabuf_head(pkcs7),
3153*a90b9d01SCy Schubert wpabuf_len(pkcs7));
3154*a90b9d01SCy Schubert if (err != 0) {
3155*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_PKCS7_VerifySignedData, err);
3156*a90b9d01SCy Schubert wc_PKCS7_Free(p7);
3157*a90b9d01SCy Schubert goto fail;
3158*a90b9d01SCy Schubert }
3159*a90b9d01SCy Schubert
3160*a90b9d01SCy Schubert /* Need to access p7 members directly */
3161*a90b9d01SCy Schubert for (i = 0; i < MAX_PKCS7_CERTS; i++) {
3162*a90b9d01SCy Schubert if (p7->certSz[i] == 0)
3163*a90b9d01SCy Schubert continue;
3164*a90b9d01SCy Schubert err = wc_DerToPem(p7->cert[i], p7->certSz[i], NULL, 0,
3165*a90b9d01SCy Schubert CERT_TYPE);
3166*a90b9d01SCy Schubert if (err > 0) {
3167*a90b9d01SCy Schubert total_sz += err;
3168*a90b9d01SCy Schubert } else {
3169*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_DerToPem, err);
3170*a90b9d01SCy Schubert goto fail;
3171*a90b9d01SCy Schubert }
3172*a90b9d01SCy Schubert }
3173*a90b9d01SCy Schubert
3174*a90b9d01SCy Schubert if (total_sz == 0) {
3175*a90b9d01SCy Schubert LOG_WOLF_ERROR("No certificates found in PKCS7 input");
3176*a90b9d01SCy Schubert goto fail;
3177*a90b9d01SCy Schubert }
3178*a90b9d01SCy Schubert
3179*a90b9d01SCy Schubert ret = wpabuf_alloc(total_sz);
3180*a90b9d01SCy Schubert if (!ret) {
3181*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc);
3182*a90b9d01SCy Schubert goto fail;
3183*a90b9d01SCy Schubert }
3184*a90b9d01SCy Schubert
3185*a90b9d01SCy Schubert /* Need to access p7 members directly */
3186*a90b9d01SCy Schubert for (i = 0; i < MAX_PKCS7_CERTS; i++) {
3187*a90b9d01SCy Schubert if (p7->certSz[i] == 0)
3188*a90b9d01SCy Schubert continue;
3189*a90b9d01SCy Schubert /* Not using wpabuf_put() here so that wpabuf_overflow() isn't
3190*a90b9d01SCy Schubert * called in case of a size mismatch. wc_DerToPem() checks if
3191*a90b9d01SCy Schubert * the output is large enough internally. */
3192*a90b9d01SCy Schubert err = wc_DerToPem(p7->cert[i], p7->certSz[i],
3193*a90b9d01SCy Schubert wpabuf_mhead_u8(ret) + wpabuf_len(ret),
3194*a90b9d01SCy Schubert wpabuf_tailroom(ret),
3195*a90b9d01SCy Schubert CERT_TYPE);
3196*a90b9d01SCy Schubert if (err > 0) {
3197*a90b9d01SCy Schubert wpabuf_put(ret, err);
3198*a90b9d01SCy Schubert } else {
3199*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_DerToPem, err);
3200*a90b9d01SCy Schubert wpabuf_free(ret);
3201*a90b9d01SCy Schubert ret = NULL;
3202*a90b9d01SCy Schubert goto fail;
3203*a90b9d01SCy Schubert }
3204*a90b9d01SCy Schubert }
3205*a90b9d01SCy Schubert
3206*a90b9d01SCy Schubert fail:
3207*a90b9d01SCy Schubert if (p7)
3208*a90b9d01SCy Schubert wc_PKCS7_Free(p7);
3209*a90b9d01SCy Schubert return ret;
3210*a90b9d01SCy Schubert }
3211*a90b9d01SCy Schubert
3212*a90b9d01SCy Schubert
3213*a90b9d01SCy Schubert /* BEGIN Certificate Signing Request (CSR) APIs */
3214*a90b9d01SCy Schubert
3215*a90b9d01SCy Schubert enum cert_type {
3216*a90b9d01SCy Schubert cert_type_none = 0,
3217*a90b9d01SCy Schubert cert_type_decoded_cert,
3218*a90b9d01SCy Schubert cert_type_cert,
3219*a90b9d01SCy Schubert };
3220*a90b9d01SCy Schubert
3221*a90b9d01SCy Schubert struct crypto_csr {
3222*a90b9d01SCy Schubert union {
3223*a90b9d01SCy Schubert /* For parsed csr should be read-only for higher levels */
3224*a90b9d01SCy Schubert DecodedCert dc;
3225*a90b9d01SCy Schubert Cert c; /* For generating a csr */
3226*a90b9d01SCy Schubert } req;
3227*a90b9d01SCy Schubert enum cert_type type;
3228*a90b9d01SCy Schubert struct crypto_ec_key *pubkey;
3229*a90b9d01SCy Schubert };
3230*a90b9d01SCy Schubert
3231*a90b9d01SCy Schubert
3232*a90b9d01SCy Schubert /* Helper function to make sure that the correct type is initialized */
crypto_csr_init_type(struct crypto_csr * csr,enum cert_type type,const byte * source,word32 in_sz)3233*a90b9d01SCy Schubert static void crypto_csr_init_type(struct crypto_csr *csr, enum cert_type type,
3234*a90b9d01SCy Schubert const byte *source, word32 in_sz)
3235*a90b9d01SCy Schubert {
3236*a90b9d01SCy Schubert int err;
3237*a90b9d01SCy Schubert
3238*a90b9d01SCy Schubert if (csr->type == type)
3239*a90b9d01SCy Schubert return; /* Already correct type */
3240*a90b9d01SCy Schubert
3241*a90b9d01SCy Schubert switch (csr->type) {
3242*a90b9d01SCy Schubert case cert_type_decoded_cert:
3243*a90b9d01SCy Schubert wc_FreeDecodedCert(&csr->req.dc);
3244*a90b9d01SCy Schubert break;
3245*a90b9d01SCy Schubert case cert_type_cert:
3246*a90b9d01SCy Schubert #ifdef WOLFSSL_CERT_GEN_CACHE
3247*a90b9d01SCy Schubert wc_SetCert_Free(&csr->req.c);
3248*a90b9d01SCy Schubert #endif /* WOLFSSL_CERT_GEN_CACHE */
3249*a90b9d01SCy Schubert break;
3250*a90b9d01SCy Schubert case cert_type_none:
3251*a90b9d01SCy Schubert break;
3252*a90b9d01SCy Schubert }
3253*a90b9d01SCy Schubert
3254*a90b9d01SCy Schubert switch (type) {
3255*a90b9d01SCy Schubert case cert_type_decoded_cert:
3256*a90b9d01SCy Schubert wc_InitDecodedCert(&csr->req.dc, source, in_sz, NULL);
3257*a90b9d01SCy Schubert break;
3258*a90b9d01SCy Schubert case cert_type_cert:
3259*a90b9d01SCy Schubert err = wc_InitCert(&csr->req.c);
3260*a90b9d01SCy Schubert if (err != 0)
3261*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_InitCert, err);
3262*a90b9d01SCy Schubert break;
3263*a90b9d01SCy Schubert case cert_type_none:
3264*a90b9d01SCy Schubert break;
3265*a90b9d01SCy Schubert }
3266*a90b9d01SCy Schubert
3267*a90b9d01SCy Schubert csr->type = type;
3268*a90b9d01SCy Schubert }
3269*a90b9d01SCy Schubert
3270*a90b9d01SCy Schubert
crypto_csr_init(void)3271*a90b9d01SCy Schubert struct crypto_csr * crypto_csr_init(void)
3272*a90b9d01SCy Schubert {
3273*a90b9d01SCy Schubert struct crypto_csr *ret = os_malloc(sizeof(struct crypto_csr));
3274*a90b9d01SCy Schubert
3275*a90b9d01SCy Schubert if (!ret) {
3276*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
3277*a90b9d01SCy Schubert return NULL;
3278*a90b9d01SCy Schubert }
3279*a90b9d01SCy Schubert
3280*a90b9d01SCy Schubert ret->type = cert_type_none;
3281*a90b9d01SCy Schubert crypto_csr_init_type(ret, cert_type_cert, NULL, 0);
3282*a90b9d01SCy Schubert ret->pubkey = NULL;
3283*a90b9d01SCy Schubert
3284*a90b9d01SCy Schubert return ret;
3285*a90b9d01SCy Schubert }
3286*a90b9d01SCy Schubert
3287*a90b9d01SCy Schubert
crypto_csr_deinit(struct crypto_csr * csr)3288*a90b9d01SCy Schubert void crypto_csr_deinit(struct crypto_csr *csr)
3289*a90b9d01SCy Schubert {
3290*a90b9d01SCy Schubert if (csr) {
3291*a90b9d01SCy Schubert crypto_csr_init_type(csr, cert_type_none, NULL, 0);
3292*a90b9d01SCy Schubert crypto_ec_key_deinit(csr->pubkey);
3293*a90b9d01SCy Schubert os_free(csr);
3294*a90b9d01SCy Schubert }
3295*a90b9d01SCy Schubert }
3296*a90b9d01SCy Schubert
3297*a90b9d01SCy Schubert
crypto_csr_set_ec_public_key(struct crypto_csr * csr,struct crypto_ec_key * key)3298*a90b9d01SCy Schubert int crypto_csr_set_ec_public_key(struct crypto_csr *csr,
3299*a90b9d01SCy Schubert struct crypto_ec_key *key)
3300*a90b9d01SCy Schubert {
3301*a90b9d01SCy Schubert struct wpabuf *der = NULL;
3302*a90b9d01SCy Schubert
3303*a90b9d01SCy Schubert if (!csr || !key || !key->eckey) {
3304*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3305*a90b9d01SCy Schubert return -1;
3306*a90b9d01SCy Schubert }
3307*a90b9d01SCy Schubert
3308*a90b9d01SCy Schubert if (csr->pubkey) {
3309*a90b9d01SCy Schubert crypto_ec_key_deinit(csr->pubkey);
3310*a90b9d01SCy Schubert csr->pubkey = NULL;
3311*a90b9d01SCy Schubert }
3312*a90b9d01SCy Schubert
3313*a90b9d01SCy Schubert /* Create copy of key to mitigate use-after-free errors */
3314*a90b9d01SCy Schubert der = crypto_ec_key_get_subject_public_key(key);
3315*a90b9d01SCy Schubert if (!der) {
3316*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_get_subject_public_key);
3317*a90b9d01SCy Schubert return -1;
3318*a90b9d01SCy Schubert }
3319*a90b9d01SCy Schubert
3320*a90b9d01SCy Schubert csr->pubkey = crypto_ec_key_parse_pub(wpabuf_head(der),
3321*a90b9d01SCy Schubert wpabuf_len(der));
3322*a90b9d01SCy Schubert wpabuf_free(der);
3323*a90b9d01SCy Schubert if (!csr->pubkey) {
3324*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_parse_pub);
3325*a90b9d01SCy Schubert return -1;
3326*a90b9d01SCy Schubert }
3327*a90b9d01SCy Schubert
3328*a90b9d01SCy Schubert return 0;
3329*a90b9d01SCy Schubert }
3330*a90b9d01SCy Schubert
3331*a90b9d01SCy Schubert
crypto_csr_set_name(struct crypto_csr * csr,enum crypto_csr_name type,const char * name)3332*a90b9d01SCy Schubert int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
3333*a90b9d01SCy Schubert const char *name)
3334*a90b9d01SCy Schubert {
3335*a90b9d01SCy Schubert int name_len;
3336*a90b9d01SCy Schubert char *dest;
3337*a90b9d01SCy Schubert
3338*a90b9d01SCy Schubert if (!csr || !name) {
3339*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3340*a90b9d01SCy Schubert return -1;
3341*a90b9d01SCy Schubert }
3342*a90b9d01SCy Schubert
3343*a90b9d01SCy Schubert if (csr->type != cert_type_cert) {
3344*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("csr is incorrect type (%d)", csr->type);
3345*a90b9d01SCy Schubert return -1;
3346*a90b9d01SCy Schubert }
3347*a90b9d01SCy Schubert
3348*a90b9d01SCy Schubert name_len = os_strlen(name);
3349*a90b9d01SCy Schubert if (name_len >= CTC_NAME_SIZE) {
3350*a90b9d01SCy Schubert LOG_WOLF_ERROR("name input too long");
3351*a90b9d01SCy Schubert return -1;
3352*a90b9d01SCy Schubert }
3353*a90b9d01SCy Schubert
3354*a90b9d01SCy Schubert switch (type) {
3355*a90b9d01SCy Schubert case CSR_NAME_CN:
3356*a90b9d01SCy Schubert dest = csr->req.c.subject.commonName;
3357*a90b9d01SCy Schubert break;
3358*a90b9d01SCy Schubert case CSR_NAME_SN:
3359*a90b9d01SCy Schubert dest = csr->req.c.subject.sur;
3360*a90b9d01SCy Schubert break;
3361*a90b9d01SCy Schubert case CSR_NAME_C:
3362*a90b9d01SCy Schubert dest = csr->req.c.subject.country;
3363*a90b9d01SCy Schubert break;
3364*a90b9d01SCy Schubert case CSR_NAME_O:
3365*a90b9d01SCy Schubert dest = csr->req.c.subject.org;
3366*a90b9d01SCy Schubert break;
3367*a90b9d01SCy Schubert case CSR_NAME_OU:
3368*a90b9d01SCy Schubert dest = csr->req.c.subject.unit;
3369*a90b9d01SCy Schubert break;
3370*a90b9d01SCy Schubert default:
3371*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3372*a90b9d01SCy Schubert return -1;
3373*a90b9d01SCy Schubert }
3374*a90b9d01SCy Schubert
3375*a90b9d01SCy Schubert os_memcpy(dest, name, name_len);
3376*a90b9d01SCy Schubert dest[name_len] = '\0';
3377*a90b9d01SCy Schubert
3378*a90b9d01SCy Schubert return 0;
3379*a90b9d01SCy Schubert }
3380*a90b9d01SCy Schubert
3381*a90b9d01SCy Schubert
crypto_csr_set_attribute(struct crypto_csr * csr,enum crypto_csr_attr attr,int attr_type,const u8 * value,size_t len)3382*a90b9d01SCy Schubert int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
3383*a90b9d01SCy Schubert int attr_type, const u8 *value, size_t len)
3384*a90b9d01SCy Schubert {
3385*a90b9d01SCy Schubert if (!csr || attr_type != ASN1_TAG_UTF8STRING || !value ||
3386*a90b9d01SCy Schubert len >= CTC_NAME_SIZE) {
3387*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3388*a90b9d01SCy Schubert return -1;
3389*a90b9d01SCy Schubert }
3390*a90b9d01SCy Schubert
3391*a90b9d01SCy Schubert if (csr->type != cert_type_cert) {
3392*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("csr is incorrect type (%d)", csr->type);
3393*a90b9d01SCy Schubert return -1;
3394*a90b9d01SCy Schubert }
3395*a90b9d01SCy Schubert
3396*a90b9d01SCy Schubert switch (attr) {
3397*a90b9d01SCy Schubert case CSR_ATTR_CHALLENGE_PASSWORD:
3398*a90b9d01SCy Schubert os_memcpy(csr->req.c.challengePw, value, len);
3399*a90b9d01SCy Schubert csr->req.c.challengePw[len] = '\0';
3400*a90b9d01SCy Schubert break;
3401*a90b9d01SCy Schubert default:
3402*a90b9d01SCy Schubert return -1;
3403*a90b9d01SCy Schubert }
3404*a90b9d01SCy Schubert
3405*a90b9d01SCy Schubert return 0;
3406*a90b9d01SCy Schubert }
3407*a90b9d01SCy Schubert
3408*a90b9d01SCy Schubert
crypto_csr_get_attribute(struct crypto_csr * csr,enum crypto_csr_attr attr,size_t * len,int * type)3409*a90b9d01SCy Schubert const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
3410*a90b9d01SCy Schubert enum crypto_csr_attr attr,
3411*a90b9d01SCy Schubert size_t *len, int *type)
3412*a90b9d01SCy Schubert {
3413*a90b9d01SCy Schubert if (!csr || !len || !type) {
3414*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3415*a90b9d01SCy Schubert return NULL;;
3416*a90b9d01SCy Schubert }
3417*a90b9d01SCy Schubert
3418*a90b9d01SCy Schubert switch (attr) {
3419*a90b9d01SCy Schubert case CSR_ATTR_CHALLENGE_PASSWORD:
3420*a90b9d01SCy Schubert switch (csr->type) {
3421*a90b9d01SCy Schubert case cert_type_decoded_cert:
3422*a90b9d01SCy Schubert *type = ASN1_TAG_UTF8STRING;
3423*a90b9d01SCy Schubert *len = csr->req.dc.cPwdLen;
3424*a90b9d01SCy Schubert return (const u8 *) csr->req.dc.cPwd;
3425*a90b9d01SCy Schubert case cert_type_cert:
3426*a90b9d01SCy Schubert *type = ASN1_TAG_UTF8STRING;
3427*a90b9d01SCy Schubert *len = os_strlen(csr->req.c.challengePw);
3428*a90b9d01SCy Schubert return (const u8 *) csr->req.c.challengePw;
3429*a90b9d01SCy Schubert case cert_type_none:
3430*a90b9d01SCy Schubert return NULL;
3431*a90b9d01SCy Schubert }
3432*a90b9d01SCy Schubert break;
3433*a90b9d01SCy Schubert }
3434*a90b9d01SCy Schubert return NULL;
3435*a90b9d01SCy Schubert }
3436*a90b9d01SCy Schubert
3437*a90b9d01SCy Schubert
crypto_csr_sign(struct crypto_csr * csr,struct crypto_ec_key * key,enum crypto_hash_alg algo)3438*a90b9d01SCy Schubert struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
3439*a90b9d01SCy Schubert struct crypto_ec_key *key,
3440*a90b9d01SCy Schubert enum crypto_hash_alg algo)
3441*a90b9d01SCy Schubert {
3442*a90b9d01SCy Schubert int err;
3443*a90b9d01SCy Schubert int len;
3444*a90b9d01SCy Schubert u8 *buf = NULL;
3445*a90b9d01SCy Schubert int buf_len;
3446*a90b9d01SCy Schubert struct wpabuf *ret = NULL;
3447*a90b9d01SCy Schubert
3448*a90b9d01SCy Schubert if (!csr || !key || !key->eckey) {
3449*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3450*a90b9d01SCy Schubert return NULL;
3451*a90b9d01SCy Schubert }
3452*a90b9d01SCy Schubert
3453*a90b9d01SCy Schubert if (csr->type != cert_type_cert) {
3454*a90b9d01SCy Schubert LOG_WOLF_ERROR_VA("csr is incorrect type (%d)", csr->type);
3455*a90b9d01SCy Schubert return NULL;
3456*a90b9d01SCy Schubert }
3457*a90b9d01SCy Schubert
3458*a90b9d01SCy Schubert if (!crypto_ec_key_init_rng(key)) {
3459*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_ec_key_init_rng);
3460*a90b9d01SCy Schubert return NULL;
3461*a90b9d01SCy Schubert }
3462*a90b9d01SCy Schubert
3463*a90b9d01SCy Schubert switch (algo) {
3464*a90b9d01SCy Schubert case CRYPTO_HASH_ALG_SHA256:
3465*a90b9d01SCy Schubert csr->req.c.sigType = CTC_SHA256wECDSA;
3466*a90b9d01SCy Schubert break;
3467*a90b9d01SCy Schubert case CRYPTO_HASH_ALG_SHA384:
3468*a90b9d01SCy Schubert csr->req.c.sigType = CTC_SHA384wECDSA;
3469*a90b9d01SCy Schubert break;
3470*a90b9d01SCy Schubert case CRYPTO_HASH_ALG_SHA512:
3471*a90b9d01SCy Schubert csr->req.c.sigType = CTC_SHA512wECDSA;
3472*a90b9d01SCy Schubert break;
3473*a90b9d01SCy Schubert default:
3474*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3475*a90b9d01SCy Schubert return NULL;
3476*a90b9d01SCy Schubert }
3477*a90b9d01SCy Schubert
3478*a90b9d01SCy Schubert /* Pass in large value that is guaranteed to be larger than the
3479*a90b9d01SCy Schubert * necessary buffer */
3480*a90b9d01SCy Schubert err = wc_MakeCertReq(&csr->req.c, NULL, 100000, NULL,
3481*a90b9d01SCy Schubert csr->pubkey->eckey);
3482*a90b9d01SCy Schubert if (err <= 0) {
3483*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_MakeCertReq, err);
3484*a90b9d01SCy Schubert goto fail;
3485*a90b9d01SCy Schubert }
3486*a90b9d01SCy Schubert len = err;
3487*a90b9d01SCy Schubert
3488*a90b9d01SCy Schubert buf_len = len + MAX_SEQ_SZ * 2 + MAX_ENCODED_SIG_SZ;
3489*a90b9d01SCy Schubert buf = os_malloc(buf_len);
3490*a90b9d01SCy Schubert if (!buf) {
3491*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(os_malloc);
3492*a90b9d01SCy Schubert goto fail;
3493*a90b9d01SCy Schubert }
3494*a90b9d01SCy Schubert
3495*a90b9d01SCy Schubert err = wc_MakeCertReq(&csr->req.c, buf, buf_len, NULL,
3496*a90b9d01SCy Schubert csr->pubkey->eckey);
3497*a90b9d01SCy Schubert if (err <= 0) {
3498*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_MakeCertReq, err);
3499*a90b9d01SCy Schubert goto fail;
3500*a90b9d01SCy Schubert }
3501*a90b9d01SCy Schubert len = err;
3502*a90b9d01SCy Schubert
3503*a90b9d01SCy Schubert err = wc_SignCert(len, csr->req.c.sigType, buf, buf_len, NULL,
3504*a90b9d01SCy Schubert key->eckey, key->rng);
3505*a90b9d01SCy Schubert if (err <= 0) {
3506*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_SignCert, err);
3507*a90b9d01SCy Schubert goto fail;
3508*a90b9d01SCy Schubert }
3509*a90b9d01SCy Schubert len = err;
3510*a90b9d01SCy Schubert
3511*a90b9d01SCy Schubert ret = wpabuf_alloc_copy(buf, len);
3512*a90b9d01SCy Schubert if (!ret) {
3513*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc_copy);
3514*a90b9d01SCy Schubert goto fail;
3515*a90b9d01SCy Schubert }
3516*a90b9d01SCy Schubert
3517*a90b9d01SCy Schubert fail:
3518*a90b9d01SCy Schubert os_free(buf);
3519*a90b9d01SCy Schubert return ret;
3520*a90b9d01SCy Schubert }
3521*a90b9d01SCy Schubert
3522*a90b9d01SCy Schubert
crypto_csr_verify(const struct wpabuf * req)3523*a90b9d01SCy Schubert struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
3524*a90b9d01SCy Schubert {
3525*a90b9d01SCy Schubert struct crypto_csr *csr = NULL;
3526*a90b9d01SCy Schubert int err;
3527*a90b9d01SCy Schubert
3528*a90b9d01SCy Schubert if (!req) {
3529*a90b9d01SCy Schubert LOG_INVALID_PARAMETERS();
3530*a90b9d01SCy Schubert return NULL;
3531*a90b9d01SCy Schubert }
3532*a90b9d01SCy Schubert
3533*a90b9d01SCy Schubert csr = crypto_csr_init();
3534*a90b9d01SCy Schubert if (!csr) {
3535*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC_NULL(crypto_csr_init);
3536*a90b9d01SCy Schubert goto fail;
3537*a90b9d01SCy Schubert }
3538*a90b9d01SCy Schubert
3539*a90b9d01SCy Schubert crypto_csr_init_type(csr, cert_type_decoded_cert,
3540*a90b9d01SCy Schubert wpabuf_head(req), wpabuf_len(req));
3541*a90b9d01SCy Schubert err = wc_ParseCert(&csr->req.dc, CERTREQ_TYPE, VERIFY, NULL);
3542*a90b9d01SCy Schubert if (err != 0) {
3543*a90b9d01SCy Schubert LOG_WOLF_ERROR_FUNC(wc_ParseCert, err);
3544*a90b9d01SCy Schubert goto fail;
3545*a90b9d01SCy Schubert }
3546*a90b9d01SCy Schubert
3547*a90b9d01SCy Schubert return csr;
3548*a90b9d01SCy Schubert fail:
3549*a90b9d01SCy Schubert crypto_csr_deinit(csr);
3550*a90b9d01SCy Schubert return NULL;
3551*a90b9d01SCy Schubert }
3552*a90b9d01SCy Schubert
3553*a90b9d01SCy Schubert /* END Certificate Signing Request (CSR) APIs */
3554*a90b9d01SCy Schubert
3555*a90b9d01SCy Schubert #endif /* CONFIG_DPP */
3556*a90b9d01SCy Schubert
3557*a90b9d01SCy Schubert
crypto_unload(void)3558*a90b9d01SCy Schubert void crypto_unload(void)
3559*a90b9d01SCy Schubert {
3560*a90b9d01SCy Schubert }
3561