xref: /freebsd/contrib/wpa/src/crypto/crypto_wolfssl.c (revision 85732ac8bccbc0adcf5a261ea1ffec8ca7b3a92d)
1*85732ac8SCy Schubert /*
2*85732ac8SCy Schubert  * Wrapper functions for libwolfssl
3*85732ac8SCy Schubert  * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
4*85732ac8SCy Schubert  *
5*85732ac8SCy Schubert  * This software may be distributed under the terms of the BSD license.
6*85732ac8SCy Schubert  * See README for more details.
7*85732ac8SCy Schubert  */
8*85732ac8SCy Schubert 
9*85732ac8SCy Schubert #include "includes.h"
10*85732ac8SCy Schubert 
11*85732ac8SCy Schubert #include "common.h"
12*85732ac8SCy Schubert #include "crypto.h"
13*85732ac8SCy Schubert 
14*85732ac8SCy Schubert /* wolfSSL headers */
15*85732ac8SCy Schubert #include <wolfssl/options.h>
16*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/md4.h>
17*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/md5.h>
18*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha.h>
19*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha256.h>
20*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha512.h>
21*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/hmac.h>
22*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/pwdbased.h>
23*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/arc4.h>
24*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/des3.h>
25*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/aes.h>
26*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/dh.h>
27*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/cmac.h>
28*85732ac8SCy Schubert #include <wolfssl/wolfcrypt/ecc.h>
29*85732ac8SCy Schubert #include <wolfssl/openssl/bn.h>
30*85732ac8SCy Schubert 
31*85732ac8SCy Schubert 
32*85732ac8SCy Schubert #ifndef CONFIG_FIPS
33*85732ac8SCy Schubert 
34*85732ac8SCy Schubert int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
35*85732ac8SCy Schubert {
36*85732ac8SCy Schubert 	Md4 md4;
37*85732ac8SCy Schubert 	size_t i;
38*85732ac8SCy Schubert 
39*85732ac8SCy Schubert 	if (TEST_FAIL())
40*85732ac8SCy Schubert 		return -1;
41*85732ac8SCy Schubert 
42*85732ac8SCy Schubert 	wc_InitMd4(&md4);
43*85732ac8SCy Schubert 
44*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
45*85732ac8SCy Schubert 		wc_Md4Update(&md4, addr[i], len[i]);
46*85732ac8SCy Schubert 
47*85732ac8SCy Schubert 	wc_Md4Final(&md4, mac);
48*85732ac8SCy Schubert 
49*85732ac8SCy Schubert 	return 0;
50*85732ac8SCy Schubert }
51*85732ac8SCy Schubert 
52*85732ac8SCy Schubert 
53*85732ac8SCy Schubert int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
54*85732ac8SCy Schubert {
55*85732ac8SCy Schubert 	wc_Md5 md5;
56*85732ac8SCy Schubert 	size_t i;
57*85732ac8SCy Schubert 
58*85732ac8SCy Schubert 	if (TEST_FAIL())
59*85732ac8SCy Schubert 		return -1;
60*85732ac8SCy Schubert 
61*85732ac8SCy Schubert 	wc_InitMd5(&md5);
62*85732ac8SCy Schubert 
63*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
64*85732ac8SCy Schubert 		wc_Md5Update(&md5, addr[i], len[i]);
65*85732ac8SCy Schubert 
66*85732ac8SCy Schubert 	wc_Md5Final(&md5, mac);
67*85732ac8SCy Schubert 
68*85732ac8SCy Schubert 	return 0;
69*85732ac8SCy Schubert }
70*85732ac8SCy Schubert 
71*85732ac8SCy Schubert #endif /* CONFIG_FIPS */
72*85732ac8SCy Schubert 
73*85732ac8SCy Schubert 
74*85732ac8SCy Schubert int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
75*85732ac8SCy Schubert {
76*85732ac8SCy Schubert 	wc_Sha sha;
77*85732ac8SCy Schubert 	size_t i;
78*85732ac8SCy Schubert 
79*85732ac8SCy Schubert 	if (TEST_FAIL())
80*85732ac8SCy Schubert 		return -1;
81*85732ac8SCy Schubert 
82*85732ac8SCy Schubert 	wc_InitSha(&sha);
83*85732ac8SCy Schubert 
84*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
85*85732ac8SCy Schubert 		wc_ShaUpdate(&sha, addr[i], len[i]);
86*85732ac8SCy Schubert 
87*85732ac8SCy Schubert 	wc_ShaFinal(&sha, mac);
88*85732ac8SCy Schubert 
89*85732ac8SCy Schubert 	return 0;
90*85732ac8SCy Schubert }
91*85732ac8SCy Schubert 
92*85732ac8SCy Schubert 
93*85732ac8SCy Schubert #ifndef NO_SHA256_WRAPPER
94*85732ac8SCy Schubert int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
95*85732ac8SCy Schubert 		  u8 *mac)
96*85732ac8SCy Schubert {
97*85732ac8SCy Schubert 	wc_Sha256 sha256;
98*85732ac8SCy Schubert 	size_t i;
99*85732ac8SCy Schubert 
100*85732ac8SCy Schubert 	if (TEST_FAIL())
101*85732ac8SCy Schubert 		return -1;
102*85732ac8SCy Schubert 
103*85732ac8SCy Schubert 	wc_InitSha256(&sha256);
104*85732ac8SCy Schubert 
105*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
106*85732ac8SCy Schubert 		wc_Sha256Update(&sha256, addr[i], len[i]);
107*85732ac8SCy Schubert 
108*85732ac8SCy Schubert 	wc_Sha256Final(&sha256, mac);
109*85732ac8SCy Schubert 
110*85732ac8SCy Schubert 	return 0;
111*85732ac8SCy Schubert }
112*85732ac8SCy Schubert #endif /* NO_SHA256_WRAPPER */
113*85732ac8SCy Schubert 
114*85732ac8SCy Schubert 
115*85732ac8SCy Schubert #ifdef CONFIG_SHA384
116*85732ac8SCy Schubert int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
117*85732ac8SCy Schubert 		  u8 *mac)
118*85732ac8SCy Schubert {
119*85732ac8SCy Schubert 	wc_Sha384 sha384;
120*85732ac8SCy Schubert 	size_t i;
121*85732ac8SCy Schubert 
122*85732ac8SCy Schubert 	if (TEST_FAIL())
123*85732ac8SCy Schubert 		return -1;
124*85732ac8SCy Schubert 
125*85732ac8SCy Schubert 	wc_InitSha384(&sha384);
126*85732ac8SCy Schubert 
127*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
128*85732ac8SCy Schubert 		wc_Sha384Update(&sha384, addr[i], len[i]);
129*85732ac8SCy Schubert 
130*85732ac8SCy Schubert 	wc_Sha384Final(&sha384, mac);
131*85732ac8SCy Schubert 
132*85732ac8SCy Schubert 	return 0;
133*85732ac8SCy Schubert }
134*85732ac8SCy Schubert #endif /* CONFIG_SHA384 */
135*85732ac8SCy Schubert 
136*85732ac8SCy Schubert 
137*85732ac8SCy Schubert #ifdef CONFIG_SHA512
138*85732ac8SCy Schubert int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
139*85732ac8SCy Schubert 		  u8 *mac)
140*85732ac8SCy Schubert {
141*85732ac8SCy Schubert 	wc_Sha512 sha512;
142*85732ac8SCy Schubert 	size_t i;
143*85732ac8SCy Schubert 
144*85732ac8SCy Schubert 	if (TEST_FAIL())
145*85732ac8SCy Schubert 		return -1;
146*85732ac8SCy Schubert 
147*85732ac8SCy Schubert 	wc_InitSha512(&sha512);
148*85732ac8SCy Schubert 
149*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
150*85732ac8SCy Schubert 		wc_Sha512Update(&sha512, addr[i], len[i]);
151*85732ac8SCy Schubert 
152*85732ac8SCy Schubert 	wc_Sha512Final(&sha512, mac);
153*85732ac8SCy Schubert 
154*85732ac8SCy Schubert 	return 0;
155*85732ac8SCy Schubert }
156*85732ac8SCy Schubert #endif /* CONFIG_SHA512 */
157*85732ac8SCy Schubert 
158*85732ac8SCy Schubert 
159*85732ac8SCy Schubert static int wolfssl_hmac_vector(int type, const u8 *key,
160*85732ac8SCy Schubert 			       size_t key_len, size_t num_elem,
161*85732ac8SCy Schubert 			       const u8 *addr[], const size_t *len, u8 *mac,
162*85732ac8SCy Schubert 			       unsigned int mdlen)
163*85732ac8SCy Schubert {
164*85732ac8SCy Schubert 	Hmac hmac;
165*85732ac8SCy Schubert 	size_t i;
166*85732ac8SCy Schubert 
167*85732ac8SCy Schubert 	(void) mdlen;
168*85732ac8SCy Schubert 
169*85732ac8SCy Schubert 	if (TEST_FAIL())
170*85732ac8SCy Schubert 		return -1;
171*85732ac8SCy Schubert 
172*85732ac8SCy Schubert 	if (wc_HmacSetKey(&hmac, type, key, (word32) key_len) != 0)
173*85732ac8SCy Schubert 		return -1;
174*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
175*85732ac8SCy Schubert 		if (wc_HmacUpdate(&hmac, addr[i], len[i]) != 0)
176*85732ac8SCy Schubert 			return -1;
177*85732ac8SCy Schubert 	if (wc_HmacFinal(&hmac, mac) != 0)
178*85732ac8SCy Schubert 		return -1;
179*85732ac8SCy Schubert 	return 0;
180*85732ac8SCy Schubert }
181*85732ac8SCy Schubert 
182*85732ac8SCy Schubert 
183*85732ac8SCy Schubert #ifndef CONFIG_FIPS
184*85732ac8SCy Schubert 
185*85732ac8SCy Schubert int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
186*85732ac8SCy Schubert 		    const u8 *addr[], const size_t *len, u8 *mac)
187*85732ac8SCy Schubert {
188*85732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_MD5, key, key_len, num_elem, addr, len,
189*85732ac8SCy Schubert 				   mac, 16);
190*85732ac8SCy Schubert }
191*85732ac8SCy Schubert 
192*85732ac8SCy Schubert 
193*85732ac8SCy Schubert int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
194*85732ac8SCy Schubert 	     u8 *mac)
195*85732ac8SCy Schubert {
196*85732ac8SCy Schubert 	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
197*85732ac8SCy Schubert }
198*85732ac8SCy Schubert 
199*85732ac8SCy Schubert #endif /* CONFIG_FIPS */
200*85732ac8SCy Schubert 
201*85732ac8SCy Schubert 
202*85732ac8SCy Schubert int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
203*85732ac8SCy Schubert 		     const u8 *addr[], const size_t *len, u8 *mac)
204*85732ac8SCy Schubert {
205*85732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA, key, key_len, num_elem, addr, len,
206*85732ac8SCy Schubert 				   mac, 20);
207*85732ac8SCy Schubert }
208*85732ac8SCy Schubert 
209*85732ac8SCy Schubert 
210*85732ac8SCy Schubert int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
211*85732ac8SCy Schubert 	      u8 *mac)
212*85732ac8SCy Schubert {
213*85732ac8SCy Schubert 	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
214*85732ac8SCy Schubert }
215*85732ac8SCy Schubert 
216*85732ac8SCy Schubert 
217*85732ac8SCy Schubert #ifdef CONFIG_SHA256
218*85732ac8SCy Schubert 
219*85732ac8SCy Schubert int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
220*85732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
221*85732ac8SCy Schubert {
222*85732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA256, key, key_len, num_elem, addr, len,
223*85732ac8SCy Schubert 				   mac, 32);
224*85732ac8SCy Schubert }
225*85732ac8SCy Schubert 
226*85732ac8SCy Schubert 
227*85732ac8SCy Schubert int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
228*85732ac8SCy Schubert 		size_t data_len, u8 *mac)
229*85732ac8SCy Schubert {
230*85732ac8SCy Schubert 	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
231*85732ac8SCy Schubert }
232*85732ac8SCy Schubert 
233*85732ac8SCy Schubert #endif /* CONFIG_SHA256 */
234*85732ac8SCy Schubert 
235*85732ac8SCy Schubert 
236*85732ac8SCy Schubert #ifdef CONFIG_SHA384
237*85732ac8SCy Schubert 
238*85732ac8SCy Schubert int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
239*85732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
240*85732ac8SCy Schubert {
241*85732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA384, key, key_len, num_elem, addr, len,
242*85732ac8SCy Schubert 				   mac, 48);
243*85732ac8SCy Schubert }
244*85732ac8SCy Schubert 
245*85732ac8SCy Schubert 
246*85732ac8SCy Schubert int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
247*85732ac8SCy Schubert 		size_t data_len, u8 *mac)
248*85732ac8SCy Schubert {
249*85732ac8SCy Schubert 	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
250*85732ac8SCy Schubert }
251*85732ac8SCy Schubert 
252*85732ac8SCy Schubert #endif /* CONFIG_SHA384 */
253*85732ac8SCy Schubert 
254*85732ac8SCy Schubert 
255*85732ac8SCy Schubert #ifdef CONFIG_SHA512
256*85732ac8SCy Schubert 
257*85732ac8SCy Schubert int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
258*85732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
259*85732ac8SCy Schubert {
260*85732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA512, key, key_len, num_elem, addr, len,
261*85732ac8SCy Schubert 				   mac, 64);
262*85732ac8SCy Schubert }
263*85732ac8SCy Schubert 
264*85732ac8SCy Schubert 
265*85732ac8SCy Schubert int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
266*85732ac8SCy Schubert 		size_t data_len, u8 *mac)
267*85732ac8SCy Schubert {
268*85732ac8SCy Schubert 	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
269*85732ac8SCy Schubert }
270*85732ac8SCy Schubert 
271*85732ac8SCy Schubert #endif /* CONFIG_SHA512 */
272*85732ac8SCy Schubert 
273*85732ac8SCy Schubert 
274*85732ac8SCy Schubert int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
275*85732ac8SCy Schubert 		int iterations, u8 *buf, size_t buflen)
276*85732ac8SCy Schubert {
277*85732ac8SCy Schubert 	if (wc_PBKDF2(buf, (const byte*)passphrase, os_strlen(passphrase), ssid,
278*85732ac8SCy Schubert 		      ssid_len, iterations, buflen, WC_SHA) != 0)
279*85732ac8SCy Schubert 		return -1;
280*85732ac8SCy Schubert 	return 0;
281*85732ac8SCy Schubert }
282*85732ac8SCy Schubert 
283*85732ac8SCy Schubert 
284*85732ac8SCy Schubert #ifdef CONFIG_DES
285*85732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
286*85732ac8SCy Schubert {
287*85732ac8SCy Schubert 	Des des;
288*85732ac8SCy Schubert 	u8  pkey[8], next, tmp;
289*85732ac8SCy Schubert 	int i;
290*85732ac8SCy Schubert 
291*85732ac8SCy Schubert 	/* Add parity bits to the key */
292*85732ac8SCy Schubert 	next = 0;
293*85732ac8SCy Schubert 	for (i = 0; i < 7; i++) {
294*85732ac8SCy Schubert 		tmp = key[i];
295*85732ac8SCy Schubert 		pkey[i] = (tmp >> i) | next | 1;
296*85732ac8SCy Schubert 		next = tmp << (7 - i);
297*85732ac8SCy Schubert 	}
298*85732ac8SCy Schubert 	pkey[i] = next | 1;
299*85732ac8SCy Schubert 
300*85732ac8SCy Schubert 	wc_Des_SetKey(&des, pkey, NULL, DES_ENCRYPTION);
301*85732ac8SCy Schubert 	wc_Des_EcbEncrypt(&des, cypher, clear, DES_BLOCK_SIZE);
302*85732ac8SCy Schubert 
303*85732ac8SCy Schubert 	return 0;
304*85732ac8SCy Schubert }
305*85732ac8SCy Schubert #endif /* CONFIG_DES */
306*85732ac8SCy Schubert 
307*85732ac8SCy Schubert 
308*85732ac8SCy Schubert void * aes_encrypt_init(const u8 *key, size_t len)
309*85732ac8SCy Schubert {
310*85732ac8SCy Schubert 	Aes *aes;
311*85732ac8SCy Schubert 
312*85732ac8SCy Schubert 	if (TEST_FAIL())
313*85732ac8SCy Schubert 		return NULL;
314*85732ac8SCy Schubert 
315*85732ac8SCy Schubert 	aes = os_malloc(sizeof(Aes));
316*85732ac8SCy Schubert 	if (!aes)
317*85732ac8SCy Schubert 		return NULL;
318*85732ac8SCy Schubert 
319*85732ac8SCy Schubert 	if (wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION) < 0) {
320*85732ac8SCy Schubert 		os_free(aes);
321*85732ac8SCy Schubert 		return NULL;
322*85732ac8SCy Schubert 	}
323*85732ac8SCy Schubert 
324*85732ac8SCy Schubert 	return aes;
325*85732ac8SCy Schubert }
326*85732ac8SCy Schubert 
327*85732ac8SCy Schubert 
328*85732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
329*85732ac8SCy Schubert {
330*85732ac8SCy Schubert 	wc_AesEncryptDirect(ctx, crypt, plain);
331*85732ac8SCy Schubert 	return 0;
332*85732ac8SCy Schubert }
333*85732ac8SCy Schubert 
334*85732ac8SCy Schubert 
335*85732ac8SCy Schubert void aes_encrypt_deinit(void *ctx)
336*85732ac8SCy Schubert {
337*85732ac8SCy Schubert 	os_free(ctx);
338*85732ac8SCy Schubert }
339*85732ac8SCy Schubert 
340*85732ac8SCy Schubert 
341*85732ac8SCy Schubert void * aes_decrypt_init(const u8 *key, size_t len)
342*85732ac8SCy Schubert {
343*85732ac8SCy Schubert 	Aes *aes;
344*85732ac8SCy Schubert 
345*85732ac8SCy Schubert 	if (TEST_FAIL())
346*85732ac8SCy Schubert 		return NULL;
347*85732ac8SCy Schubert 
348*85732ac8SCy Schubert 	aes = os_malloc(sizeof(Aes));
349*85732ac8SCy Schubert 	if (!aes)
350*85732ac8SCy Schubert 		return NULL;
351*85732ac8SCy Schubert 
352*85732ac8SCy Schubert 	if (wc_AesSetKey(aes, key, len, NULL, AES_DECRYPTION) < 0) {
353*85732ac8SCy Schubert 		os_free(aes);
354*85732ac8SCy Schubert 		return NULL;
355*85732ac8SCy Schubert 	}
356*85732ac8SCy Schubert 
357*85732ac8SCy Schubert 	return aes;
358*85732ac8SCy Schubert }
359*85732ac8SCy Schubert 
360*85732ac8SCy Schubert 
361*85732ac8SCy Schubert int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
362*85732ac8SCy Schubert {
363*85732ac8SCy Schubert 	wc_AesDecryptDirect(ctx, plain, crypt);
364*85732ac8SCy Schubert 	return 0;
365*85732ac8SCy Schubert }
366*85732ac8SCy Schubert 
367*85732ac8SCy Schubert 
368*85732ac8SCy Schubert void aes_decrypt_deinit(void *ctx)
369*85732ac8SCy Schubert {
370*85732ac8SCy Schubert 	os_free(ctx);
371*85732ac8SCy Schubert }
372*85732ac8SCy Schubert 
373*85732ac8SCy Schubert 
374*85732ac8SCy Schubert int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
375*85732ac8SCy Schubert {
376*85732ac8SCy Schubert 	Aes aes;
377*85732ac8SCy Schubert 	int ret;
378*85732ac8SCy Schubert 
379*85732ac8SCy Schubert 	if (TEST_FAIL())
380*85732ac8SCy Schubert 		return -1;
381*85732ac8SCy Schubert 
382*85732ac8SCy Schubert 	ret = wc_AesSetKey(&aes, key, 16, iv, AES_ENCRYPTION);
383*85732ac8SCy Schubert 	if (ret != 0)
384*85732ac8SCy Schubert 		return -1;
385*85732ac8SCy Schubert 
386*85732ac8SCy Schubert 	ret = wc_AesCbcEncrypt(&aes, data, data, data_len);
387*85732ac8SCy Schubert 	if (ret != 0)
388*85732ac8SCy Schubert 		return -1;
389*85732ac8SCy Schubert 	return 0;
390*85732ac8SCy Schubert }
391*85732ac8SCy Schubert 
392*85732ac8SCy Schubert 
393*85732ac8SCy Schubert int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
394*85732ac8SCy Schubert {
395*85732ac8SCy Schubert 	Aes aes;
396*85732ac8SCy Schubert 	int ret;
397*85732ac8SCy Schubert 
398*85732ac8SCy Schubert 	if (TEST_FAIL())
399*85732ac8SCy Schubert 		return -1;
400*85732ac8SCy Schubert 
401*85732ac8SCy Schubert 	ret = wc_AesSetKey(&aes, key, 16, iv, AES_DECRYPTION);
402*85732ac8SCy Schubert 	if (ret != 0)
403*85732ac8SCy Schubert 		return -1;
404*85732ac8SCy Schubert 
405*85732ac8SCy Schubert 	ret = wc_AesCbcDecrypt(&aes, data, data, data_len);
406*85732ac8SCy Schubert 	if (ret != 0)
407*85732ac8SCy Schubert 		return -1;
408*85732ac8SCy Schubert 	return 0;
409*85732ac8SCy Schubert }
410*85732ac8SCy Schubert 
411*85732ac8SCy Schubert 
412*85732ac8SCy Schubert int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
413*85732ac8SCy Schubert {
414*85732ac8SCy Schubert 	int ret;
415*85732ac8SCy Schubert 
416*85732ac8SCy Schubert 	if (TEST_FAIL())
417*85732ac8SCy Schubert 		return -1;
418*85732ac8SCy Schubert 
419*85732ac8SCy Schubert 	ret = wc_AesKeyWrap(kek, kek_len, plain, n * 8, cipher, (n + 1) * 8,
420*85732ac8SCy Schubert 			    NULL);
421*85732ac8SCy Schubert 	return ret != (n + 1) * 8 ? -1 : 0;
422*85732ac8SCy Schubert }
423*85732ac8SCy Schubert 
424*85732ac8SCy Schubert 
425*85732ac8SCy Schubert int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
426*85732ac8SCy Schubert 	       u8 *plain)
427*85732ac8SCy Schubert {
428*85732ac8SCy Schubert 	int ret;
429*85732ac8SCy Schubert 
430*85732ac8SCy Schubert 	if (TEST_FAIL())
431*85732ac8SCy Schubert 		return -1;
432*85732ac8SCy Schubert 
433*85732ac8SCy Schubert 	ret = wc_AesKeyUnWrap(kek, kek_len, cipher, (n + 1) * 8, plain, n * 8,
434*85732ac8SCy Schubert 			      NULL);
435*85732ac8SCy Schubert 	return ret != n * 8 ? -1 : 0;
436*85732ac8SCy Schubert }
437*85732ac8SCy Schubert 
438*85732ac8SCy Schubert 
439*85732ac8SCy Schubert #ifndef CONFIG_NO_RC4
440*85732ac8SCy Schubert int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data,
441*85732ac8SCy Schubert 	     size_t data_len)
442*85732ac8SCy Schubert {
443*85732ac8SCy Schubert #ifndef NO_RC4
444*85732ac8SCy Schubert 	Arc4 arc4;
445*85732ac8SCy Schubert 	unsigned char skip_buf[16];
446*85732ac8SCy Schubert 
447*85732ac8SCy Schubert 	wc_Arc4SetKey(&arc4, key, keylen);
448*85732ac8SCy Schubert 
449*85732ac8SCy Schubert 	while (skip >= sizeof(skip_buf)) {
450*85732ac8SCy Schubert 		size_t len = skip;
451*85732ac8SCy Schubert 
452*85732ac8SCy Schubert 		if (len > sizeof(skip_buf))
453*85732ac8SCy Schubert 			len = sizeof(skip_buf);
454*85732ac8SCy Schubert 		wc_Arc4Process(&arc4, skip_buf, skip_buf, len);
455*85732ac8SCy Schubert 		skip -= len;
456*85732ac8SCy Schubert 	}
457*85732ac8SCy Schubert 
458*85732ac8SCy Schubert 	wc_Arc4Process(&arc4, data, data, data_len);
459*85732ac8SCy Schubert 
460*85732ac8SCy Schubert 	return 0;
461*85732ac8SCy Schubert #else /* NO_RC4 */
462*85732ac8SCy Schubert 	return -1;
463*85732ac8SCy Schubert #endif /* NO_RC4 */
464*85732ac8SCy Schubert }
465*85732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
466*85732ac8SCy Schubert 
467*85732ac8SCy Schubert 
468*85732ac8SCy Schubert #if defined(EAP_IKEV2) || defined(EAP_IKEV2_DYNAMIC) \
469*85732ac8SCy Schubert 		       || defined(EAP_SERVER_IKEV2)
470*85732ac8SCy Schubert union wolfssl_cipher {
471*85732ac8SCy Schubert 	Aes aes;
472*85732ac8SCy Schubert 	Des3 des3;
473*85732ac8SCy Schubert 	Arc4 arc4;
474*85732ac8SCy Schubert };
475*85732ac8SCy Schubert 
476*85732ac8SCy Schubert struct crypto_cipher {
477*85732ac8SCy Schubert 	enum crypto_cipher_alg alg;
478*85732ac8SCy Schubert 	union wolfssl_cipher enc;
479*85732ac8SCy Schubert 	union wolfssl_cipher dec;
480*85732ac8SCy Schubert };
481*85732ac8SCy Schubert 
482*85732ac8SCy Schubert struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
483*85732ac8SCy Schubert 					  const u8 *iv, const u8 *key,
484*85732ac8SCy Schubert 					  size_t key_len)
485*85732ac8SCy Schubert {
486*85732ac8SCy Schubert 	struct crypto_cipher *ctx;
487*85732ac8SCy Schubert 
488*85732ac8SCy Schubert 	ctx = os_zalloc(sizeof(*ctx));
489*85732ac8SCy Schubert 	if (!ctx)
490*85732ac8SCy Schubert 		return NULL;
491*85732ac8SCy Schubert 
492*85732ac8SCy Schubert 	switch (alg) {
493*85732ac8SCy Schubert #ifndef CONFIG_NO_RC4
494*85732ac8SCy Schubert #ifndef NO_RC4
495*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
496*85732ac8SCy Schubert 		wc_Arc4SetKey(&ctx->enc.arc4, key, key_len);
497*85732ac8SCy Schubert 		wc_Arc4SetKey(&ctx->dec.arc4, key, key_len);
498*85732ac8SCy Schubert 		break;
499*85732ac8SCy Schubert #endif /* NO_RC4 */
500*85732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
501*85732ac8SCy Schubert #ifndef NO_AES
502*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
503*85732ac8SCy Schubert 		switch (key_len) {
504*85732ac8SCy Schubert 		case 16:
505*85732ac8SCy Schubert 		case 24:
506*85732ac8SCy Schubert 		case 32:
507*85732ac8SCy Schubert 			break;
508*85732ac8SCy Schubert 		default:
509*85732ac8SCy Schubert 			os_free(ctx);
510*85732ac8SCy Schubert 			return NULL;
511*85732ac8SCy Schubert 		}
512*85732ac8SCy Schubert 		if (wc_AesSetKey(&ctx->enc.aes, key, key_len, iv,
513*85732ac8SCy Schubert 				 AES_ENCRYPTION) ||
514*85732ac8SCy Schubert 		    wc_AesSetKey(&ctx->dec.aes, key, key_len, iv,
515*85732ac8SCy Schubert 				 AES_DECRYPTION)) {
516*85732ac8SCy Schubert 			os_free(ctx);
517*85732ac8SCy Schubert 			return NULL;
518*85732ac8SCy Schubert 		}
519*85732ac8SCy Schubert 		break;
520*85732ac8SCy Schubert #endif /* NO_AES */
521*85732ac8SCy Schubert #ifndef NO_DES3
522*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
523*85732ac8SCy Schubert 		if (key_len != DES3_KEYLEN ||
524*85732ac8SCy Schubert 		    wc_Des3_SetKey(&ctx->enc.des3, key, iv, DES_ENCRYPTION) ||
525*85732ac8SCy Schubert 		    wc_Des3_SetKey(&ctx->dec.des3, key, iv, DES_DECRYPTION)) {
526*85732ac8SCy Schubert 			os_free(ctx);
527*85732ac8SCy Schubert 			return NULL;
528*85732ac8SCy Schubert 		}
529*85732ac8SCy Schubert 		break;
530*85732ac8SCy Schubert #endif /* NO_DES3 */
531*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC2:
532*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_DES:
533*85732ac8SCy Schubert 	default:
534*85732ac8SCy Schubert 		os_free(ctx);
535*85732ac8SCy Schubert 		return NULL;
536*85732ac8SCy Schubert 	}
537*85732ac8SCy Schubert 
538*85732ac8SCy Schubert 	ctx->alg = alg;
539*85732ac8SCy Schubert 
540*85732ac8SCy Schubert 	return ctx;
541*85732ac8SCy Schubert }
542*85732ac8SCy Schubert 
543*85732ac8SCy Schubert 
544*85732ac8SCy Schubert int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
545*85732ac8SCy Schubert 			  u8 *crypt, size_t len)
546*85732ac8SCy Schubert {
547*85732ac8SCy Schubert 	switch (ctx->alg) {
548*85732ac8SCy Schubert #ifndef CONFIG_NO_RC4
549*85732ac8SCy Schubert #ifndef NO_RC4
550*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
551*85732ac8SCy Schubert 		wc_Arc4Process(&ctx->enc.arc4, crypt, plain, len);
552*85732ac8SCy Schubert 		return 0;
553*85732ac8SCy Schubert #endif /* NO_RC4 */
554*85732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
555*85732ac8SCy Schubert #ifndef NO_AES
556*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
557*85732ac8SCy Schubert 		if (wc_AesCbcEncrypt(&ctx->enc.aes, crypt, plain, len) != 0)
558*85732ac8SCy Schubert 			return -1;
559*85732ac8SCy Schubert 		return 0;
560*85732ac8SCy Schubert #endif /* NO_AES */
561*85732ac8SCy Schubert #ifndef NO_DES3
562*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
563*85732ac8SCy Schubert 		if (wc_Des3_CbcEncrypt(&ctx->enc.des3, crypt, plain, len) != 0)
564*85732ac8SCy Schubert 			return -1;
565*85732ac8SCy Schubert 		return 0;
566*85732ac8SCy Schubert #endif /* NO_DES3 */
567*85732ac8SCy Schubert 	default:
568*85732ac8SCy Schubert 		return -1;
569*85732ac8SCy Schubert 	}
570*85732ac8SCy Schubert 	return -1;
571*85732ac8SCy Schubert }
572*85732ac8SCy Schubert 
573*85732ac8SCy Schubert 
574*85732ac8SCy Schubert int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
575*85732ac8SCy Schubert 			  u8 *plain, size_t len)
576*85732ac8SCy Schubert {
577*85732ac8SCy Schubert 	switch (ctx->alg) {
578*85732ac8SCy Schubert #ifndef CONFIG_NO_RC4
579*85732ac8SCy Schubert #ifndef NO_RC4
580*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
581*85732ac8SCy Schubert 		wc_Arc4Process(&ctx->dec.arc4, plain, crypt, len);
582*85732ac8SCy Schubert 		return 0;
583*85732ac8SCy Schubert #endif /* NO_RC4 */
584*85732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
585*85732ac8SCy Schubert #ifndef NO_AES
586*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
587*85732ac8SCy Schubert 		if (wc_AesCbcDecrypt(&ctx->dec.aes, plain, crypt, len) != 0)
588*85732ac8SCy Schubert 			return -1;
589*85732ac8SCy Schubert 		return 0;
590*85732ac8SCy Schubert #endif /* NO_AES */
591*85732ac8SCy Schubert #ifndef NO_DES3
592*85732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
593*85732ac8SCy Schubert 		if (wc_Des3_CbcDecrypt(&ctx->dec.des3, plain, crypt, len) != 0)
594*85732ac8SCy Schubert 			return -1;
595*85732ac8SCy Schubert 		return 0;
596*85732ac8SCy Schubert #endif /* NO_DES3 */
597*85732ac8SCy Schubert 	default:
598*85732ac8SCy Schubert 		return -1;
599*85732ac8SCy Schubert 	}
600*85732ac8SCy Schubert 	return -1;
601*85732ac8SCy Schubert }
602*85732ac8SCy Schubert 
603*85732ac8SCy Schubert 
604*85732ac8SCy Schubert void crypto_cipher_deinit(struct crypto_cipher *ctx)
605*85732ac8SCy Schubert {
606*85732ac8SCy Schubert 	os_free(ctx);
607*85732ac8SCy Schubert }
608*85732ac8SCy Schubert 
609*85732ac8SCy Schubert #endif
610*85732ac8SCy Schubert 
611*85732ac8SCy Schubert 
612*85732ac8SCy Schubert #ifdef CONFIG_WPS_NFC
613*85732ac8SCy Schubert 
614*85732ac8SCy Schubert static const unsigned char RFC3526_PRIME_1536[] = {
615*85732ac8SCy Schubert 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
616*85732ac8SCy Schubert 	0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
617*85732ac8SCy Schubert 	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
618*85732ac8SCy Schubert 	0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
619*85732ac8SCy Schubert 	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
620*85732ac8SCy Schubert 	0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
621*85732ac8SCy Schubert 	0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
622*85732ac8SCy Schubert 	0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
623*85732ac8SCy Schubert 	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
624*85732ac8SCy Schubert 	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
625*85732ac8SCy Schubert 	0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
626*85732ac8SCy Schubert 	0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
627*85732ac8SCy Schubert 	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
628*85732ac8SCy Schubert 	0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
629*85732ac8SCy Schubert 	0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
630*85732ac8SCy Schubert 	0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
631*85732ac8SCy Schubert };
632*85732ac8SCy Schubert 
633*85732ac8SCy Schubert static const unsigned char RFC3526_GENERATOR_1536[] = {
634*85732ac8SCy Schubert 	0x02
635*85732ac8SCy Schubert };
636*85732ac8SCy Schubert 
637*85732ac8SCy Schubert #define RFC3526_LEN sizeof(RFC3526_PRIME_1536)
638*85732ac8SCy Schubert 
639*85732ac8SCy Schubert 
640*85732ac8SCy Schubert void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
641*85732ac8SCy Schubert {
642*85732ac8SCy Schubert 	WC_RNG rng;
643*85732ac8SCy Schubert 	DhKey *ret = NULL;
644*85732ac8SCy Schubert 	DhKey *dh = NULL;
645*85732ac8SCy Schubert 	struct wpabuf *privkey = NULL;
646*85732ac8SCy Schubert 	struct wpabuf *pubkey = NULL;
647*85732ac8SCy Schubert 	word32 priv_sz, pub_sz;
648*85732ac8SCy Schubert 
649*85732ac8SCy Schubert 	*priv = NULL;
650*85732ac8SCy Schubert 	wpabuf_free(*publ);
651*85732ac8SCy Schubert 	*publ = NULL;
652*85732ac8SCy Schubert 
653*85732ac8SCy Schubert 	dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
654*85732ac8SCy Schubert 	if (!dh)
655*85732ac8SCy Schubert 		return NULL;
656*85732ac8SCy Schubert 	wc_InitDhKey(dh);
657*85732ac8SCy Schubert 
658*85732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0) {
659*85732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
660*85732ac8SCy Schubert 		return NULL;
661*85732ac8SCy Schubert 	}
662*85732ac8SCy Schubert 
663*85732ac8SCy Schubert 	privkey = wpabuf_alloc(RFC3526_LEN);
664*85732ac8SCy Schubert 	pubkey = wpabuf_alloc(RFC3526_LEN);
665*85732ac8SCy Schubert 	if (!privkey || !pubkey)
666*85732ac8SCy Schubert 		goto done;
667*85732ac8SCy Schubert 
668*85732ac8SCy Schubert 	if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
669*85732ac8SCy Schubert 			RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
670*85732ac8SCy Schubert 	    != 0)
671*85732ac8SCy Schubert 		goto done;
672*85732ac8SCy Schubert 
673*85732ac8SCy Schubert 	if (wc_DhGenerateKeyPair(dh, &rng, wpabuf_mhead(privkey), &priv_sz,
674*85732ac8SCy Schubert 				 wpabuf_mhead(pubkey), &pub_sz) != 0)
675*85732ac8SCy Schubert 		goto done;
676*85732ac8SCy Schubert 
677*85732ac8SCy Schubert 	wpabuf_put(privkey, priv_sz);
678*85732ac8SCy Schubert 	wpabuf_put(pubkey, pub_sz);
679*85732ac8SCy Schubert 
680*85732ac8SCy Schubert 	ret = dh;
681*85732ac8SCy Schubert 	*priv = privkey;
682*85732ac8SCy Schubert 	*publ = pubkey;
683*85732ac8SCy Schubert 	dh = NULL;
684*85732ac8SCy Schubert 	privkey = NULL;
685*85732ac8SCy Schubert 	pubkey = NULL;
686*85732ac8SCy Schubert done:
687*85732ac8SCy Schubert 	wpabuf_clear_free(pubkey);
688*85732ac8SCy Schubert 	wpabuf_clear_free(privkey);
689*85732ac8SCy Schubert 	if (dh) {
690*85732ac8SCy Schubert 		wc_FreeDhKey(dh);
691*85732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
692*85732ac8SCy Schubert 	}
693*85732ac8SCy Schubert 	wc_FreeRng(&rng);
694*85732ac8SCy Schubert 	return ret;
695*85732ac8SCy Schubert }
696*85732ac8SCy Schubert 
697*85732ac8SCy Schubert 
698*85732ac8SCy Schubert void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
699*85732ac8SCy Schubert {
700*85732ac8SCy Schubert 	DhKey *ret = NULL;
701*85732ac8SCy Schubert 	DhKey *dh;
702*85732ac8SCy Schubert 	byte *secret;
703*85732ac8SCy Schubert 	word32 secret_sz;
704*85732ac8SCy Schubert 
705*85732ac8SCy Schubert 	dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
706*85732ac8SCy Schubert 	if (!dh)
707*85732ac8SCy Schubert 		return NULL;
708*85732ac8SCy Schubert 	wc_InitDhKey(dh);
709*85732ac8SCy Schubert 
710*85732ac8SCy Schubert 	secret = XMALLOC(RFC3526_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER);
711*85732ac8SCy Schubert 	if (!secret)
712*85732ac8SCy Schubert 		goto done;
713*85732ac8SCy Schubert 
714*85732ac8SCy Schubert 	if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
715*85732ac8SCy Schubert 			RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
716*85732ac8SCy Schubert 	    != 0)
717*85732ac8SCy Schubert 		goto done;
718*85732ac8SCy Schubert 
719*85732ac8SCy Schubert 	if (wc_DhAgree(dh, secret, &secret_sz, wpabuf_head(priv),
720*85732ac8SCy Schubert 		       wpabuf_len(priv), RFC3526_GENERATOR_1536,
721*85732ac8SCy Schubert 		       sizeof(RFC3526_GENERATOR_1536)) != 0)
722*85732ac8SCy Schubert 		goto done;
723*85732ac8SCy Schubert 
724*85732ac8SCy Schubert 	if (secret_sz != wpabuf_len(publ) ||
725*85732ac8SCy Schubert 	    os_memcmp(secret, wpabuf_head(publ), secret_sz) != 0)
726*85732ac8SCy Schubert 		goto done;
727*85732ac8SCy Schubert 
728*85732ac8SCy Schubert 	ret = dh;
729*85732ac8SCy Schubert 	dh = NULL;
730*85732ac8SCy Schubert done:
731*85732ac8SCy Schubert 	if (dh) {
732*85732ac8SCy Schubert 		wc_FreeDhKey(dh);
733*85732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
734*85732ac8SCy Schubert 	}
735*85732ac8SCy Schubert 	XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
736*85732ac8SCy Schubert 	return ret;
737*85732ac8SCy Schubert }
738*85732ac8SCy Schubert 
739*85732ac8SCy Schubert 
740*85732ac8SCy Schubert struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
741*85732ac8SCy Schubert 				  const struct wpabuf *own_private)
742*85732ac8SCy Schubert {
743*85732ac8SCy Schubert 	struct wpabuf *ret = NULL;
744*85732ac8SCy Schubert 	struct wpabuf *secret;
745*85732ac8SCy Schubert 	word32 secret_sz;
746*85732ac8SCy Schubert 
747*85732ac8SCy Schubert 	secret = wpabuf_alloc(RFC3526_LEN);
748*85732ac8SCy Schubert 	if (!secret)
749*85732ac8SCy Schubert 		goto done;
750*85732ac8SCy Schubert 
751*85732ac8SCy Schubert 	if (wc_DhAgree(ctx, wpabuf_mhead(secret), &secret_sz,
752*85732ac8SCy Schubert 		       wpabuf_head(own_private), wpabuf_len(own_private),
753*85732ac8SCy Schubert 		       wpabuf_head(peer_public), wpabuf_len(peer_public)) != 0)
754*85732ac8SCy Schubert 		goto done;
755*85732ac8SCy Schubert 
756*85732ac8SCy Schubert 	wpabuf_put(secret, secret_sz);
757*85732ac8SCy Schubert 
758*85732ac8SCy Schubert 	ret = secret;
759*85732ac8SCy Schubert 	secret = NULL;
760*85732ac8SCy Schubert done:
761*85732ac8SCy Schubert 	wpabuf_clear_free(secret);
762*85732ac8SCy Schubert 	return ret;
763*85732ac8SCy Schubert }
764*85732ac8SCy Schubert 
765*85732ac8SCy Schubert 
766*85732ac8SCy Schubert void dh5_free(void *ctx)
767*85732ac8SCy Schubert {
768*85732ac8SCy Schubert 	if (!ctx)
769*85732ac8SCy Schubert 		return;
770*85732ac8SCy Schubert 
771*85732ac8SCy Schubert 	wc_FreeDhKey(ctx);
772*85732ac8SCy Schubert 	XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
773*85732ac8SCy Schubert }
774*85732ac8SCy Schubert 
775*85732ac8SCy Schubert #endif /* CONFIG_WPS_NFC */
776*85732ac8SCy Schubert 
777*85732ac8SCy Schubert 
778*85732ac8SCy Schubert int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
779*85732ac8SCy Schubert 		   u8 *pubkey)
780*85732ac8SCy Schubert {
781*85732ac8SCy Schubert 	int ret = -1;
782*85732ac8SCy Schubert 	WC_RNG rng;
783*85732ac8SCy Schubert 	DhKey *dh = NULL;
784*85732ac8SCy Schubert 	word32 priv_sz, pub_sz;
785*85732ac8SCy Schubert 
786*85732ac8SCy Schubert 	if (TEST_FAIL())
787*85732ac8SCy Schubert 		return -1;
788*85732ac8SCy Schubert 
789*85732ac8SCy Schubert 	dh = os_malloc(sizeof(DhKey));
790*85732ac8SCy Schubert 	if (!dh)
791*85732ac8SCy Schubert 		return -1;
792*85732ac8SCy Schubert 	wc_InitDhKey(dh);
793*85732ac8SCy Schubert 
794*85732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0) {
795*85732ac8SCy Schubert 		os_free(dh);
796*85732ac8SCy Schubert 		return -1;
797*85732ac8SCy Schubert 	}
798*85732ac8SCy Schubert 
799*85732ac8SCy Schubert 	if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
800*85732ac8SCy Schubert 		goto done;
801*85732ac8SCy Schubert 
802*85732ac8SCy Schubert 	if (wc_DhGenerateKeyPair(dh, &rng, privkey, &priv_sz, pubkey, &pub_sz)
803*85732ac8SCy Schubert 	    != 0)
804*85732ac8SCy Schubert 		goto done;
805*85732ac8SCy Schubert 
806*85732ac8SCy Schubert 	if (priv_sz < prime_len) {
807*85732ac8SCy Schubert 		size_t pad_sz = prime_len - priv_sz;
808*85732ac8SCy Schubert 
809*85732ac8SCy Schubert 		os_memmove(privkey + pad_sz, privkey, priv_sz);
810*85732ac8SCy Schubert 		os_memset(privkey, 0, pad_sz);
811*85732ac8SCy Schubert 	}
812*85732ac8SCy Schubert 
813*85732ac8SCy Schubert 	if (pub_sz < prime_len) {
814*85732ac8SCy Schubert 		size_t pad_sz = prime_len - pub_sz;
815*85732ac8SCy Schubert 
816*85732ac8SCy Schubert 		os_memmove(pubkey + pad_sz, pubkey, pub_sz);
817*85732ac8SCy Schubert 		os_memset(pubkey, 0, pad_sz);
818*85732ac8SCy Schubert 	}
819*85732ac8SCy Schubert 	ret = 0;
820*85732ac8SCy Schubert done:
821*85732ac8SCy Schubert 	wc_FreeDhKey(dh);
822*85732ac8SCy Schubert 	os_free(dh);
823*85732ac8SCy Schubert 	wc_FreeRng(&rng);
824*85732ac8SCy Schubert 	return ret;
825*85732ac8SCy Schubert }
826*85732ac8SCy Schubert 
827*85732ac8SCy Schubert 
828*85732ac8SCy Schubert int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
829*85732ac8SCy Schubert 			    const u8 *privkey, size_t privkey_len,
830*85732ac8SCy Schubert 			    const u8 *pubkey, size_t pubkey_len,
831*85732ac8SCy Schubert 			    u8 *secret, size_t *len)
832*85732ac8SCy Schubert {
833*85732ac8SCy Schubert 	int ret = -1;
834*85732ac8SCy Schubert 	DhKey *dh;
835*85732ac8SCy Schubert 	word32 secret_sz;
836*85732ac8SCy Schubert 
837*85732ac8SCy Schubert 	dh = os_malloc(sizeof(DhKey));
838*85732ac8SCy Schubert 	if (!dh)
839*85732ac8SCy Schubert 		return -1;
840*85732ac8SCy Schubert 	wc_InitDhKey(dh);
841*85732ac8SCy Schubert 
842*85732ac8SCy Schubert 	if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
843*85732ac8SCy Schubert 		goto done;
844*85732ac8SCy Schubert 
845*85732ac8SCy Schubert 	if (wc_DhAgree(dh, secret, &secret_sz, privkey, privkey_len, pubkey,
846*85732ac8SCy Schubert 		       pubkey_len) != 0)
847*85732ac8SCy Schubert 		goto done;
848*85732ac8SCy Schubert 
849*85732ac8SCy Schubert 	*len = secret_sz;
850*85732ac8SCy Schubert 	ret = 0;
851*85732ac8SCy Schubert done:
852*85732ac8SCy Schubert 	wc_FreeDhKey(dh);
853*85732ac8SCy Schubert 	os_free(dh);
854*85732ac8SCy Schubert 	return ret;
855*85732ac8SCy Schubert }
856*85732ac8SCy Schubert 
857*85732ac8SCy Schubert 
858*85732ac8SCy Schubert #ifdef CONFIG_FIPS
859*85732ac8SCy Schubert int crypto_get_random(void *buf, size_t len)
860*85732ac8SCy Schubert {
861*85732ac8SCy Schubert 	int ret = 0;
862*85732ac8SCy Schubert 	WC_RNG rng;
863*85732ac8SCy Schubert 
864*85732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
865*85732ac8SCy Schubert 		return -1;
866*85732ac8SCy Schubert 	if (wc_RNG_GenerateBlock(&rng, buf, len) != 0)
867*85732ac8SCy Schubert 		ret = -1;
868*85732ac8SCy Schubert 	wc_FreeRng(&rng);
869*85732ac8SCy Schubert 	return ret;
870*85732ac8SCy Schubert }
871*85732ac8SCy Schubert #endif /* CONFIG_FIPS */
872*85732ac8SCy Schubert 
873*85732ac8SCy Schubert 
874*85732ac8SCy Schubert #if defined(EAP_PWD) || defined(EAP_SERVER_PWD)
875*85732ac8SCy Schubert struct crypto_hash {
876*85732ac8SCy Schubert 	Hmac hmac;
877*85732ac8SCy Schubert 	int size;
878*85732ac8SCy Schubert };
879*85732ac8SCy Schubert 
880*85732ac8SCy Schubert 
881*85732ac8SCy Schubert struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
882*85732ac8SCy Schubert 				      size_t key_len)
883*85732ac8SCy Schubert {
884*85732ac8SCy Schubert 	struct crypto_hash *ret = NULL;
885*85732ac8SCy Schubert 	struct crypto_hash *hash;
886*85732ac8SCy Schubert 	int type;
887*85732ac8SCy Schubert 
888*85732ac8SCy Schubert 	hash = os_zalloc(sizeof(*hash));
889*85732ac8SCy Schubert 	if (!hash)
890*85732ac8SCy Schubert 		goto done;
891*85732ac8SCy Schubert 
892*85732ac8SCy Schubert 	switch (alg) {
893*85732ac8SCy Schubert #ifndef NO_MD5
894*85732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_MD5:
895*85732ac8SCy Schubert 		hash->size = 16;
896*85732ac8SCy Schubert 		type = WC_MD5;
897*85732ac8SCy Schubert 		break;
898*85732ac8SCy Schubert #endif /* NO_MD5 */
899*85732ac8SCy Schubert #ifndef NO_SHA
900*85732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_SHA1:
901*85732ac8SCy Schubert 		type = WC_SHA;
902*85732ac8SCy Schubert 		hash->size = 20;
903*85732ac8SCy Schubert 		break;
904*85732ac8SCy Schubert #endif /* NO_SHA */
905*85732ac8SCy Schubert #ifdef CONFIG_SHA256
906*85732ac8SCy Schubert #ifndef NO_SHA256
907*85732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_SHA256:
908*85732ac8SCy Schubert 		type = WC_SHA256;
909*85732ac8SCy Schubert 		hash->size = 32;
910*85732ac8SCy Schubert 		break;
911*85732ac8SCy Schubert #endif /* NO_SHA256 */
912*85732ac8SCy Schubert #endif /* CONFIG_SHA256 */
913*85732ac8SCy Schubert 	default:
914*85732ac8SCy Schubert 		goto done;
915*85732ac8SCy Schubert 	}
916*85732ac8SCy Schubert 
917*85732ac8SCy Schubert 	if (wc_HmacSetKey(&hash->hmac, type, key, key_len) != 0)
918*85732ac8SCy Schubert 		goto done;
919*85732ac8SCy Schubert 
920*85732ac8SCy Schubert 	ret = hash;
921*85732ac8SCy Schubert 	hash = NULL;
922*85732ac8SCy Schubert done:
923*85732ac8SCy Schubert 	os_free(hash);
924*85732ac8SCy Schubert 	return ret;
925*85732ac8SCy Schubert }
926*85732ac8SCy Schubert 
927*85732ac8SCy Schubert 
928*85732ac8SCy Schubert void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
929*85732ac8SCy Schubert {
930*85732ac8SCy Schubert 	if (!ctx)
931*85732ac8SCy Schubert 		return;
932*85732ac8SCy Schubert 	wc_HmacUpdate(&ctx->hmac, data, len);
933*85732ac8SCy Schubert }
934*85732ac8SCy Schubert 
935*85732ac8SCy Schubert 
936*85732ac8SCy Schubert int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
937*85732ac8SCy Schubert {
938*85732ac8SCy Schubert 	int ret = 0;
939*85732ac8SCy Schubert 
940*85732ac8SCy Schubert 	if (!ctx)
941*85732ac8SCy Schubert 		return -2;
942*85732ac8SCy Schubert 
943*85732ac8SCy Schubert 	if (!mac || !len)
944*85732ac8SCy Schubert 		goto done;
945*85732ac8SCy Schubert 
946*85732ac8SCy Schubert 	if (wc_HmacFinal(&ctx->hmac, mac) != 0) {
947*85732ac8SCy Schubert 		ret = -1;
948*85732ac8SCy Schubert 		goto done;
949*85732ac8SCy Schubert 	}
950*85732ac8SCy Schubert 
951*85732ac8SCy Schubert 	*len = ctx->size;
952*85732ac8SCy Schubert 	ret = 0;
953*85732ac8SCy Schubert done:
954*85732ac8SCy Schubert 	bin_clear_free(ctx, sizeof(*ctx));
955*85732ac8SCy Schubert 	return ret;
956*85732ac8SCy Schubert }
957*85732ac8SCy Schubert 
958*85732ac8SCy Schubert #endif
959*85732ac8SCy Schubert 
960*85732ac8SCy Schubert 
961*85732ac8SCy Schubert int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
962*85732ac8SCy Schubert 		     const u8 *addr[], const size_t *len, u8 *mac)
963*85732ac8SCy Schubert {
964*85732ac8SCy Schubert 	Cmac cmac;
965*85732ac8SCy Schubert 	size_t i;
966*85732ac8SCy Schubert 	word32 sz;
967*85732ac8SCy Schubert 
968*85732ac8SCy Schubert 	if (TEST_FAIL())
969*85732ac8SCy Schubert 		return -1;
970*85732ac8SCy Schubert 
971*85732ac8SCy Schubert 	if (wc_InitCmac(&cmac, key, key_len, WC_CMAC_AES, NULL) != 0)
972*85732ac8SCy Schubert 		return -1;
973*85732ac8SCy Schubert 
974*85732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
975*85732ac8SCy Schubert 		if (wc_CmacUpdate(&cmac, addr[i], len[i]) != 0)
976*85732ac8SCy Schubert 			return -1;
977*85732ac8SCy Schubert 
978*85732ac8SCy Schubert 	sz = AES_BLOCK_SIZE;
979*85732ac8SCy Schubert 	if (wc_CmacFinal(&cmac, mac, &sz) != 0 || sz != AES_BLOCK_SIZE)
980*85732ac8SCy Schubert 		return -1;
981*85732ac8SCy Schubert 
982*85732ac8SCy Schubert 	return 0;
983*85732ac8SCy Schubert }
984*85732ac8SCy Schubert 
985*85732ac8SCy Schubert 
986*85732ac8SCy Schubert int omac1_aes_128_vector(const u8 *key, size_t num_elem,
987*85732ac8SCy Schubert 			 const u8 *addr[], const size_t *len, u8 *mac)
988*85732ac8SCy Schubert {
989*85732ac8SCy Schubert 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
990*85732ac8SCy Schubert }
991*85732ac8SCy Schubert 
992*85732ac8SCy Schubert 
993*85732ac8SCy Schubert int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
994*85732ac8SCy Schubert {
995*85732ac8SCy Schubert 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
996*85732ac8SCy Schubert }
997*85732ac8SCy Schubert 
998*85732ac8SCy Schubert 
999*85732ac8SCy Schubert int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1000*85732ac8SCy Schubert {
1001*85732ac8SCy Schubert 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
1002*85732ac8SCy Schubert }
1003*85732ac8SCy Schubert 
1004*85732ac8SCy Schubert 
1005*85732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init(void)
1006*85732ac8SCy Schubert {
1007*85732ac8SCy Schubert 	mp_int *a;
1008*85732ac8SCy Schubert 
1009*85732ac8SCy Schubert 	if (TEST_FAIL())
1010*85732ac8SCy Schubert 		return NULL;
1011*85732ac8SCy Schubert 
1012*85732ac8SCy Schubert 	a = os_malloc(sizeof(*a));
1013*85732ac8SCy Schubert 	if (!a || mp_init(a) != MP_OKAY) {
1014*85732ac8SCy Schubert 		os_free(a);
1015*85732ac8SCy Schubert 		a = NULL;
1016*85732ac8SCy Schubert 	}
1017*85732ac8SCy Schubert 
1018*85732ac8SCy Schubert 	return (struct crypto_bignum *) a;
1019*85732ac8SCy Schubert }
1020*85732ac8SCy Schubert 
1021*85732ac8SCy Schubert 
1022*85732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
1023*85732ac8SCy Schubert {
1024*85732ac8SCy Schubert 	mp_int *a;
1025*85732ac8SCy Schubert 
1026*85732ac8SCy Schubert 	if (TEST_FAIL())
1027*85732ac8SCy Schubert 		return NULL;
1028*85732ac8SCy Schubert 
1029*85732ac8SCy Schubert 	a = (mp_int *) crypto_bignum_init();
1030*85732ac8SCy Schubert 	if (!a)
1031*85732ac8SCy Schubert 		return NULL;
1032*85732ac8SCy Schubert 
1033*85732ac8SCy Schubert 	if (mp_read_unsigned_bin(a, buf, len) != MP_OKAY) {
1034*85732ac8SCy Schubert 		os_free(a);
1035*85732ac8SCy Schubert 		a = NULL;
1036*85732ac8SCy Schubert 	}
1037*85732ac8SCy Schubert 
1038*85732ac8SCy Schubert 	return (struct crypto_bignum *) a;
1039*85732ac8SCy Schubert }
1040*85732ac8SCy Schubert 
1041*85732ac8SCy Schubert 
1042*85732ac8SCy Schubert void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
1043*85732ac8SCy Schubert {
1044*85732ac8SCy Schubert 	if (!n)
1045*85732ac8SCy Schubert 		return;
1046*85732ac8SCy Schubert 
1047*85732ac8SCy Schubert 	if (clear)
1048*85732ac8SCy Schubert 		mp_forcezero((mp_int *) n);
1049*85732ac8SCy Schubert 	mp_clear((mp_int *) n);
1050*85732ac8SCy Schubert 	os_free((mp_int *) n);
1051*85732ac8SCy Schubert }
1052*85732ac8SCy Schubert 
1053*85732ac8SCy Schubert 
1054*85732ac8SCy Schubert int crypto_bignum_to_bin(const struct crypto_bignum *a,
1055*85732ac8SCy Schubert 			 u8 *buf, size_t buflen, size_t padlen)
1056*85732ac8SCy Schubert {
1057*85732ac8SCy Schubert 	int num_bytes, offset;
1058*85732ac8SCy Schubert 
1059*85732ac8SCy Schubert 	if (TEST_FAIL())
1060*85732ac8SCy Schubert 		return -1;
1061*85732ac8SCy Schubert 
1062*85732ac8SCy Schubert 	if (padlen > buflen)
1063*85732ac8SCy Schubert 		return -1;
1064*85732ac8SCy Schubert 
1065*85732ac8SCy Schubert 	num_bytes = (mp_count_bits((mp_int *) a) + 7) / 8;
1066*85732ac8SCy Schubert 	if ((size_t) num_bytes > buflen)
1067*85732ac8SCy Schubert 		return -1;
1068*85732ac8SCy Schubert 	if (padlen > (size_t) num_bytes)
1069*85732ac8SCy Schubert 		offset = padlen - num_bytes;
1070*85732ac8SCy Schubert 	else
1071*85732ac8SCy Schubert 		offset = 0;
1072*85732ac8SCy Schubert 
1073*85732ac8SCy Schubert 	os_memset(buf, 0, offset);
1074*85732ac8SCy Schubert 	mp_to_unsigned_bin((mp_int *) a, buf + offset);
1075*85732ac8SCy Schubert 
1076*85732ac8SCy Schubert 	return num_bytes + offset;
1077*85732ac8SCy Schubert }
1078*85732ac8SCy Schubert 
1079*85732ac8SCy Schubert 
1080*85732ac8SCy Schubert int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
1081*85732ac8SCy Schubert {
1082*85732ac8SCy Schubert 	int ret = 0;
1083*85732ac8SCy Schubert 	WC_RNG rng;
1084*85732ac8SCy Schubert 
1085*85732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
1086*85732ac8SCy Schubert 		return -1;
1087*85732ac8SCy Schubert 	if (mp_rand_prime((mp_int *) r,
1088*85732ac8SCy Schubert 			  (mp_count_bits((mp_int *) m) + 7) / 8 * 2,
1089*85732ac8SCy Schubert 			  &rng, NULL) != 0)
1090*85732ac8SCy Schubert 		ret = -1;
1091*85732ac8SCy Schubert 	if (ret == 0 &&
1092*85732ac8SCy Schubert 	    mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0)
1093*85732ac8SCy Schubert 		ret = -1;
1094*85732ac8SCy Schubert 	wc_FreeRng(&rng);
1095*85732ac8SCy Schubert 	return ret;
1096*85732ac8SCy Schubert }
1097*85732ac8SCy Schubert 
1098*85732ac8SCy Schubert 
1099*85732ac8SCy Schubert int crypto_bignum_add(const struct crypto_bignum *a,
1100*85732ac8SCy Schubert 		      const struct crypto_bignum *b,
1101*85732ac8SCy Schubert 		      struct crypto_bignum *r)
1102*85732ac8SCy Schubert {
1103*85732ac8SCy Schubert 	return mp_add((mp_int *) a, (mp_int *) b,
1104*85732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
1105*85732ac8SCy Schubert }
1106*85732ac8SCy Schubert 
1107*85732ac8SCy Schubert 
1108*85732ac8SCy Schubert int crypto_bignum_mod(const struct crypto_bignum *a,
1109*85732ac8SCy Schubert 		      const struct crypto_bignum *m,
1110*85732ac8SCy Schubert 		      struct crypto_bignum *r)
1111*85732ac8SCy Schubert {
1112*85732ac8SCy Schubert 	return mp_mod((mp_int *) a, (mp_int *) m,
1113*85732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
1114*85732ac8SCy Schubert }
1115*85732ac8SCy Schubert 
1116*85732ac8SCy Schubert 
1117*85732ac8SCy Schubert int crypto_bignum_exptmod(const struct crypto_bignum *b,
1118*85732ac8SCy Schubert 			  const struct crypto_bignum *e,
1119*85732ac8SCy Schubert 			  const struct crypto_bignum *m,
1120*85732ac8SCy Schubert 			  struct crypto_bignum *r)
1121*85732ac8SCy Schubert {
1122*85732ac8SCy Schubert 	if (TEST_FAIL())
1123*85732ac8SCy Schubert 		return -1;
1124*85732ac8SCy Schubert 
1125*85732ac8SCy Schubert 	return mp_exptmod((mp_int *) b, (mp_int *) e, (mp_int *) m,
1126*85732ac8SCy Schubert 			  (mp_int *) r) == MP_OKAY ?  0 : -1;
1127*85732ac8SCy Schubert }
1128*85732ac8SCy Schubert 
1129*85732ac8SCy Schubert 
1130*85732ac8SCy Schubert int crypto_bignum_inverse(const struct crypto_bignum *a,
1131*85732ac8SCy Schubert 			  const struct crypto_bignum *m,
1132*85732ac8SCy Schubert 			  struct crypto_bignum *r)
1133*85732ac8SCy Schubert {
1134*85732ac8SCy Schubert 	if (TEST_FAIL())
1135*85732ac8SCy Schubert 		return -1;
1136*85732ac8SCy Schubert 
1137*85732ac8SCy Schubert 	return mp_invmod((mp_int *) a, (mp_int *) m,
1138*85732ac8SCy Schubert 			 (mp_int *) r) == MP_OKAY ? 0 : -1;
1139*85732ac8SCy Schubert }
1140*85732ac8SCy Schubert 
1141*85732ac8SCy Schubert 
1142*85732ac8SCy Schubert int crypto_bignum_sub(const struct crypto_bignum *a,
1143*85732ac8SCy Schubert 		      const struct crypto_bignum *b,
1144*85732ac8SCy Schubert 		      struct crypto_bignum *r)
1145*85732ac8SCy Schubert {
1146*85732ac8SCy Schubert 	if (TEST_FAIL())
1147*85732ac8SCy Schubert 		return -1;
1148*85732ac8SCy Schubert 
1149*85732ac8SCy Schubert 	return mp_add((mp_int *) a, (mp_int *) b,
1150*85732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
1151*85732ac8SCy Schubert }
1152*85732ac8SCy Schubert 
1153*85732ac8SCy Schubert 
1154*85732ac8SCy Schubert int crypto_bignum_div(const struct crypto_bignum *a,
1155*85732ac8SCy Schubert 		      const struct crypto_bignum *b,
1156*85732ac8SCy Schubert 		      struct crypto_bignum *d)
1157*85732ac8SCy Schubert {
1158*85732ac8SCy Schubert 	if (TEST_FAIL())
1159*85732ac8SCy Schubert 		return -1;
1160*85732ac8SCy Schubert 
1161*85732ac8SCy Schubert 	return mp_div((mp_int *) a, (mp_int *) b, (mp_int *) d,
1162*85732ac8SCy Schubert 		      NULL) == MP_OKAY ? 0 : -1;
1163*85732ac8SCy Schubert }
1164*85732ac8SCy Schubert 
1165*85732ac8SCy Schubert 
1166*85732ac8SCy Schubert int crypto_bignum_mulmod(const struct crypto_bignum *a,
1167*85732ac8SCy Schubert 			 const struct crypto_bignum *b,
1168*85732ac8SCy Schubert 			 const struct crypto_bignum *m,
1169*85732ac8SCy Schubert 			 struct crypto_bignum *d)
1170*85732ac8SCy Schubert {
1171*85732ac8SCy Schubert 	if (TEST_FAIL())
1172*85732ac8SCy Schubert 		return -1;
1173*85732ac8SCy Schubert 
1174*85732ac8SCy Schubert 	return mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) m,
1175*85732ac8SCy Schubert 			 (mp_int *) d) == MP_OKAY ?  0 : -1;
1176*85732ac8SCy Schubert }
1177*85732ac8SCy Schubert 
1178*85732ac8SCy Schubert 
1179*85732ac8SCy Schubert int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
1180*85732ac8SCy Schubert 			 struct crypto_bignum *r)
1181*85732ac8SCy Schubert {
1182*85732ac8SCy Schubert 	if (mp_copy((mp_int *) a, (mp_int *) r) != MP_OKAY)
1183*85732ac8SCy Schubert 		return -1;
1184*85732ac8SCy Schubert 	mp_rshb((mp_int *) r, n);
1185*85732ac8SCy Schubert 	return 0;
1186*85732ac8SCy Schubert }
1187*85732ac8SCy Schubert 
1188*85732ac8SCy Schubert 
1189*85732ac8SCy Schubert int crypto_bignum_cmp(const struct crypto_bignum *a,
1190*85732ac8SCy Schubert 		      const struct crypto_bignum *b)
1191*85732ac8SCy Schubert {
1192*85732ac8SCy Schubert 	return mp_cmp((mp_int *) a, (mp_int *) b);
1193*85732ac8SCy Schubert }
1194*85732ac8SCy Schubert 
1195*85732ac8SCy Schubert 
1196*85732ac8SCy Schubert int crypto_bignum_bits(const struct crypto_bignum *a)
1197*85732ac8SCy Schubert {
1198*85732ac8SCy Schubert 	return mp_count_bits((mp_int *) a);
1199*85732ac8SCy Schubert }
1200*85732ac8SCy Schubert 
1201*85732ac8SCy Schubert 
1202*85732ac8SCy Schubert int crypto_bignum_is_zero(const struct crypto_bignum *a)
1203*85732ac8SCy Schubert {
1204*85732ac8SCy Schubert 	return mp_iszero((mp_int *) a);
1205*85732ac8SCy Schubert }
1206*85732ac8SCy Schubert 
1207*85732ac8SCy Schubert 
1208*85732ac8SCy Schubert int crypto_bignum_is_one(const struct crypto_bignum *a)
1209*85732ac8SCy Schubert {
1210*85732ac8SCy Schubert 	return mp_isone((const mp_int *) a);
1211*85732ac8SCy Schubert }
1212*85732ac8SCy Schubert 
1213*85732ac8SCy Schubert int crypto_bignum_is_odd(const struct crypto_bignum *a)
1214*85732ac8SCy Schubert {
1215*85732ac8SCy Schubert 	return mp_isodd((mp_int *) a);
1216*85732ac8SCy Schubert }
1217*85732ac8SCy Schubert 
1218*85732ac8SCy Schubert 
1219*85732ac8SCy Schubert int crypto_bignum_legendre(const struct crypto_bignum *a,
1220*85732ac8SCy Schubert 			   const struct crypto_bignum *p)
1221*85732ac8SCy Schubert {
1222*85732ac8SCy Schubert 	mp_int t;
1223*85732ac8SCy Schubert 	int ret;
1224*85732ac8SCy Schubert 	int res = -2;
1225*85732ac8SCy Schubert 
1226*85732ac8SCy Schubert 	if (TEST_FAIL())
1227*85732ac8SCy Schubert 		return -2;
1228*85732ac8SCy Schubert 
1229*85732ac8SCy Schubert 	if (mp_init(&t) != MP_OKAY)
1230*85732ac8SCy Schubert 		return -2;
1231*85732ac8SCy Schubert 
1232*85732ac8SCy Schubert 	/* t = (p-1) / 2 */
1233*85732ac8SCy Schubert 	ret = mp_sub_d((mp_int *) p, 1, &t);
1234*85732ac8SCy Schubert 	if (ret == MP_OKAY)
1235*85732ac8SCy Schubert 		mp_rshb(&t, 1);
1236*85732ac8SCy Schubert 	if (ret == MP_OKAY)
1237*85732ac8SCy Schubert 		ret = mp_exptmod((mp_int *) a, &t, (mp_int *) p, &t);
1238*85732ac8SCy Schubert 	if (ret == MP_OKAY) {
1239*85732ac8SCy Schubert 		if (mp_isone(&t))
1240*85732ac8SCy Schubert 			res = 1;
1241*85732ac8SCy Schubert 		else if (mp_iszero(&t))
1242*85732ac8SCy Schubert 			res = 0;
1243*85732ac8SCy Schubert 		else
1244*85732ac8SCy Schubert 			res = -1;
1245*85732ac8SCy Schubert 	}
1246*85732ac8SCy Schubert 
1247*85732ac8SCy Schubert 	mp_clear(&t);
1248*85732ac8SCy Schubert 	return res;
1249*85732ac8SCy Schubert }
1250*85732ac8SCy Schubert 
1251*85732ac8SCy Schubert 
1252*85732ac8SCy Schubert #ifdef CONFIG_ECC
1253*85732ac8SCy Schubert 
1254*85732ac8SCy Schubert int ecc_map(ecc_point *, mp_int *, mp_digit);
1255*85732ac8SCy Schubert int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
1256*85732ac8SCy Schubert 			     mp_int *a, mp_int *modulus, mp_digit mp);
1257*85732ac8SCy Schubert 
1258*85732ac8SCy Schubert struct crypto_ec {
1259*85732ac8SCy Schubert 	ecc_key key;
1260*85732ac8SCy Schubert 	mp_int a;
1261*85732ac8SCy Schubert 	mp_int prime;
1262*85732ac8SCy Schubert 	mp_int order;
1263*85732ac8SCy Schubert 	mp_digit mont_b;
1264*85732ac8SCy Schubert 	mp_int b;
1265*85732ac8SCy Schubert };
1266*85732ac8SCy Schubert 
1267*85732ac8SCy Schubert 
1268*85732ac8SCy Schubert struct crypto_ec * crypto_ec_init(int group)
1269*85732ac8SCy Schubert {
1270*85732ac8SCy Schubert 	int built = 0;
1271*85732ac8SCy Schubert 	struct crypto_ec *e;
1272*85732ac8SCy Schubert 	int curve_id;
1273*85732ac8SCy Schubert 
1274*85732ac8SCy Schubert 	/* Map from IANA registry for IKE D-H groups to OpenSSL NID */
1275*85732ac8SCy Schubert 	switch (group) {
1276*85732ac8SCy Schubert 	case 19:
1277*85732ac8SCy Schubert 		curve_id = ECC_SECP256R1;
1278*85732ac8SCy Schubert 		break;
1279*85732ac8SCy Schubert 	case 20:
1280*85732ac8SCy Schubert 		curve_id = ECC_SECP384R1;
1281*85732ac8SCy Schubert 		break;
1282*85732ac8SCy Schubert 	case 21:
1283*85732ac8SCy Schubert 		curve_id = ECC_SECP521R1;
1284*85732ac8SCy Schubert 		break;
1285*85732ac8SCy Schubert 	case 25:
1286*85732ac8SCy Schubert 		curve_id = ECC_SECP192R1;
1287*85732ac8SCy Schubert 		break;
1288*85732ac8SCy Schubert 	case 26:
1289*85732ac8SCy Schubert 		curve_id = ECC_SECP224R1;
1290*85732ac8SCy Schubert 		break;
1291*85732ac8SCy Schubert #ifdef HAVE_ECC_BRAINPOOL
1292*85732ac8SCy Schubert 	case 27:
1293*85732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP224R1;
1294*85732ac8SCy Schubert 		break;
1295*85732ac8SCy Schubert 	case 28:
1296*85732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP256R1;
1297*85732ac8SCy Schubert 		break;
1298*85732ac8SCy Schubert 	case 29:
1299*85732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP384R1;
1300*85732ac8SCy Schubert 		break;
1301*85732ac8SCy Schubert 	case 30:
1302*85732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP512R1;
1303*85732ac8SCy Schubert 		break;
1304*85732ac8SCy Schubert #endif /* HAVE_ECC_BRAINPOOL */
1305*85732ac8SCy Schubert 	default:
1306*85732ac8SCy Schubert 		return NULL;
1307*85732ac8SCy Schubert 	}
1308*85732ac8SCy Schubert 
1309*85732ac8SCy Schubert 	e = os_zalloc(sizeof(*e));
1310*85732ac8SCy Schubert 	if (!e)
1311*85732ac8SCy Schubert 		return NULL;
1312*85732ac8SCy Schubert 
1313*85732ac8SCy Schubert 	if (wc_ecc_init(&e->key) != 0 ||
1314*85732ac8SCy Schubert 	    wc_ecc_set_curve(&e->key, 0, curve_id) != 0 ||
1315*85732ac8SCy Schubert 	    mp_init(&e->a) != MP_OKAY ||
1316*85732ac8SCy Schubert 	    mp_init(&e->prime) != MP_OKAY ||
1317*85732ac8SCy Schubert 	    mp_init(&e->order) != MP_OKAY ||
1318*85732ac8SCy Schubert 	    mp_init(&e->b) != MP_OKAY ||
1319*85732ac8SCy Schubert 	    mp_read_radix(&e->a, e->key.dp->Af, 16) != MP_OKAY ||
1320*85732ac8SCy Schubert 	    mp_read_radix(&e->b, e->key.dp->Bf, 16) != MP_OKAY ||
1321*85732ac8SCy Schubert 	    mp_read_radix(&e->prime, e->key.dp->prime, 16) != MP_OKAY ||
1322*85732ac8SCy Schubert 	    mp_read_radix(&e->order, e->key.dp->order, 16) != MP_OKAY ||
1323*85732ac8SCy Schubert 	    mp_montgomery_setup(&e->prime, &e->mont_b) != MP_OKAY)
1324*85732ac8SCy Schubert 		goto done;
1325*85732ac8SCy Schubert 
1326*85732ac8SCy Schubert 	built = 1;
1327*85732ac8SCy Schubert done:
1328*85732ac8SCy Schubert 	if (!built) {
1329*85732ac8SCy Schubert 		crypto_ec_deinit(e);
1330*85732ac8SCy Schubert 		e = NULL;
1331*85732ac8SCy Schubert 	}
1332*85732ac8SCy Schubert 	return e;
1333*85732ac8SCy Schubert }
1334*85732ac8SCy Schubert 
1335*85732ac8SCy Schubert 
1336*85732ac8SCy Schubert void crypto_ec_deinit(struct crypto_ec* e)
1337*85732ac8SCy Schubert {
1338*85732ac8SCy Schubert 	if (!e)
1339*85732ac8SCy Schubert 		return;
1340*85732ac8SCy Schubert 
1341*85732ac8SCy Schubert 	mp_clear(&e->b);
1342*85732ac8SCy Schubert 	mp_clear(&e->order);
1343*85732ac8SCy Schubert 	mp_clear(&e->prime);
1344*85732ac8SCy Schubert 	mp_clear(&e->a);
1345*85732ac8SCy Schubert 	wc_ecc_free(&e->key);
1346*85732ac8SCy Schubert 	os_free(e);
1347*85732ac8SCy Schubert }
1348*85732ac8SCy Schubert 
1349*85732ac8SCy Schubert 
1350*85732ac8SCy Schubert int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor)
1351*85732ac8SCy Schubert {
1352*85732ac8SCy Schubert 	if (!e || !cofactor)
1353*85732ac8SCy Schubert 		return -1;
1354*85732ac8SCy Schubert 
1355*85732ac8SCy Schubert 	mp_set((mp_int *) cofactor, e->key.dp->cofactor);
1356*85732ac8SCy Schubert 	return 0;
1357*85732ac8SCy Schubert }
1358*85732ac8SCy Schubert 
1359*85732ac8SCy Schubert 
1360*85732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
1361*85732ac8SCy Schubert {
1362*85732ac8SCy Schubert 	if (TEST_FAIL())
1363*85732ac8SCy Schubert 		return NULL;
1364*85732ac8SCy Schubert 	if (!e)
1365*85732ac8SCy Schubert 		return NULL;
1366*85732ac8SCy Schubert 	return (struct crypto_ec_point *) wc_ecc_new_point();
1367*85732ac8SCy Schubert }
1368*85732ac8SCy Schubert 
1369*85732ac8SCy Schubert 
1370*85732ac8SCy Schubert size_t crypto_ec_prime_len(struct crypto_ec *e)
1371*85732ac8SCy Schubert {
1372*85732ac8SCy Schubert 	return (mp_count_bits(&e->prime) + 7) / 8;
1373*85732ac8SCy Schubert }
1374*85732ac8SCy Schubert 
1375*85732ac8SCy Schubert 
1376*85732ac8SCy Schubert size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
1377*85732ac8SCy Schubert {
1378*85732ac8SCy Schubert 	return mp_count_bits(&e->prime);
1379*85732ac8SCy Schubert }
1380*85732ac8SCy Schubert 
1381*85732ac8SCy Schubert 
1382*85732ac8SCy Schubert size_t crypto_ec_order_len(struct crypto_ec *e)
1383*85732ac8SCy Schubert {
1384*85732ac8SCy Schubert 	return (mp_count_bits(&e->order) + 7) / 8;
1385*85732ac8SCy Schubert }
1386*85732ac8SCy Schubert 
1387*85732ac8SCy Schubert 
1388*85732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
1389*85732ac8SCy Schubert {
1390*85732ac8SCy Schubert 	return (const struct crypto_bignum *) &e->prime;
1391*85732ac8SCy Schubert }
1392*85732ac8SCy Schubert 
1393*85732ac8SCy Schubert 
1394*85732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
1395*85732ac8SCy Schubert {
1396*85732ac8SCy Schubert 	return (const struct crypto_bignum *) &e->order;
1397*85732ac8SCy Schubert }
1398*85732ac8SCy Schubert 
1399*85732ac8SCy Schubert 
1400*85732ac8SCy Schubert void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
1401*85732ac8SCy Schubert {
1402*85732ac8SCy Schubert 	ecc_point *point = (ecc_point *) p;
1403*85732ac8SCy Schubert 
1404*85732ac8SCy Schubert 	if (!p)
1405*85732ac8SCy Schubert 		return;
1406*85732ac8SCy Schubert 
1407*85732ac8SCy Schubert 	if (clear) {
1408*85732ac8SCy Schubert 		mp_forcezero(point->x);
1409*85732ac8SCy Schubert 		mp_forcezero(point->y);
1410*85732ac8SCy Schubert 		mp_forcezero(point->z);
1411*85732ac8SCy Schubert 	}
1412*85732ac8SCy Schubert 	wc_ecc_del_point(point);
1413*85732ac8SCy Schubert }
1414*85732ac8SCy Schubert 
1415*85732ac8SCy Schubert 
1416*85732ac8SCy Schubert int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
1417*85732ac8SCy Schubert 		      struct crypto_bignum *x)
1418*85732ac8SCy Schubert {
1419*85732ac8SCy Schubert 	return mp_copy(((ecc_point *) p)->x, (mp_int *) x) == MP_OKAY ? 0 : -1;
1420*85732ac8SCy Schubert }
1421*85732ac8SCy Schubert 
1422*85732ac8SCy Schubert 
1423*85732ac8SCy Schubert int crypto_ec_point_to_bin(struct crypto_ec *e,
1424*85732ac8SCy Schubert 			   const struct crypto_ec_point *point, u8 *x, u8 *y)
1425*85732ac8SCy Schubert {
1426*85732ac8SCy Schubert 	ecc_point *p = (ecc_point *) point;
1427*85732ac8SCy Schubert 
1428*85732ac8SCy Schubert 	if (TEST_FAIL())
1429*85732ac8SCy Schubert 		return -1;
1430*85732ac8SCy Schubert 
1431*85732ac8SCy Schubert 	if (!mp_isone(p->z)) {
1432*85732ac8SCy Schubert 		if (ecc_map(p, &e->prime, e->mont_b) != MP_OKAY)
1433*85732ac8SCy Schubert 			return -1;
1434*85732ac8SCy Schubert 	}
1435*85732ac8SCy Schubert 
1436*85732ac8SCy Schubert 	if (x) {
1437*85732ac8SCy Schubert 		if (crypto_bignum_to_bin((struct crypto_bignum *)p->x, x,
1438*85732ac8SCy Schubert 					 e->key.dp->size,
1439*85732ac8SCy Schubert 					 e->key.dp->size) <= 0)
1440*85732ac8SCy Schubert 			return -1;
1441*85732ac8SCy Schubert 	}
1442*85732ac8SCy Schubert 
1443*85732ac8SCy Schubert 	if (y) {
1444*85732ac8SCy Schubert 		if (crypto_bignum_to_bin((struct crypto_bignum *) p->y, y,
1445*85732ac8SCy Schubert 					 e->key.dp->size,
1446*85732ac8SCy Schubert 					 e->key.dp->size) <= 0)
1447*85732ac8SCy Schubert 			return -1;
1448*85732ac8SCy Schubert 	}
1449*85732ac8SCy Schubert 
1450*85732ac8SCy Schubert 	return 0;
1451*85732ac8SCy Schubert }
1452*85732ac8SCy Schubert 
1453*85732ac8SCy Schubert 
1454*85732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
1455*85732ac8SCy Schubert 						  const u8 *val)
1456*85732ac8SCy Schubert {
1457*85732ac8SCy Schubert 	ecc_point *point = NULL;
1458*85732ac8SCy Schubert 	int loaded = 0;
1459*85732ac8SCy Schubert 
1460*85732ac8SCy Schubert 	if (TEST_FAIL())
1461*85732ac8SCy Schubert 		return NULL;
1462*85732ac8SCy Schubert 
1463*85732ac8SCy Schubert 	point = wc_ecc_new_point();
1464*85732ac8SCy Schubert 	if (!point)
1465*85732ac8SCy Schubert 		goto done;
1466*85732ac8SCy Schubert 
1467*85732ac8SCy Schubert 	if (mp_read_unsigned_bin(point->x, val, e->key.dp->size) != MP_OKAY)
1468*85732ac8SCy Schubert 		goto done;
1469*85732ac8SCy Schubert 	val += e->key.dp->size;
1470*85732ac8SCy Schubert 	if (mp_read_unsigned_bin(point->y, val, e->key.dp->size) != MP_OKAY)
1471*85732ac8SCy Schubert 		goto done;
1472*85732ac8SCy Schubert 	mp_set(point->z, 1);
1473*85732ac8SCy Schubert 
1474*85732ac8SCy Schubert 	loaded = 1;
1475*85732ac8SCy Schubert done:
1476*85732ac8SCy Schubert 	if (!loaded) {
1477*85732ac8SCy Schubert 		wc_ecc_del_point(point);
1478*85732ac8SCy Schubert 		point = NULL;
1479*85732ac8SCy Schubert 	}
1480*85732ac8SCy Schubert 	return (struct crypto_ec_point *) point;
1481*85732ac8SCy Schubert }
1482*85732ac8SCy Schubert 
1483*85732ac8SCy Schubert 
1484*85732ac8SCy Schubert int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
1485*85732ac8SCy Schubert 			const struct crypto_ec_point *b,
1486*85732ac8SCy Schubert 			struct crypto_ec_point *c)
1487*85732ac8SCy Schubert {
1488*85732ac8SCy Schubert 	mp_int mu;
1489*85732ac8SCy Schubert 	ecc_point *ta = NULL, *tb = NULL;
1490*85732ac8SCy Schubert 	ecc_point *pa = (ecc_point *) a, *pb = (ecc_point *) b;
1491*85732ac8SCy Schubert 	mp_int *modulus = &e->prime;
1492*85732ac8SCy Schubert 	int ret;
1493*85732ac8SCy Schubert 
1494*85732ac8SCy Schubert 	if (TEST_FAIL())
1495*85732ac8SCy Schubert 		return -1;
1496*85732ac8SCy Schubert 
1497*85732ac8SCy Schubert 	ret = mp_init(&mu);
1498*85732ac8SCy Schubert 	if (ret != MP_OKAY)
1499*85732ac8SCy Schubert 		return -1;
1500*85732ac8SCy Schubert 
1501*85732ac8SCy Schubert 	ret = mp_montgomery_calc_normalization(&mu, modulus);
1502*85732ac8SCy Schubert 	if (ret != MP_OKAY) {
1503*85732ac8SCy Schubert 		mp_clear(&mu);
1504*85732ac8SCy Schubert 		return -1;
1505*85732ac8SCy Schubert 	}
1506*85732ac8SCy Schubert 
1507*85732ac8SCy Schubert 	if (!mp_isone(&mu)) {
1508*85732ac8SCy Schubert 		ta = wc_ecc_new_point();
1509*85732ac8SCy Schubert 		if (!ta) {
1510*85732ac8SCy Schubert 			mp_clear(&mu);
1511*85732ac8SCy Schubert 			return -1;
1512*85732ac8SCy Schubert 		}
1513*85732ac8SCy Schubert 		tb = wc_ecc_new_point();
1514*85732ac8SCy Schubert 		if (!tb) {
1515*85732ac8SCy Schubert 			wc_ecc_del_point(ta);
1516*85732ac8SCy Schubert 			mp_clear(&mu);
1517*85732ac8SCy Schubert 			return -1;
1518*85732ac8SCy Schubert 		}
1519*85732ac8SCy Schubert 
1520*85732ac8SCy Schubert 		if (mp_mulmod(pa->x, &mu, modulus, ta->x) != MP_OKAY ||
1521*85732ac8SCy Schubert 		    mp_mulmod(pa->y, &mu, modulus, ta->y) != MP_OKAY ||
1522*85732ac8SCy Schubert 		    mp_mulmod(pa->z, &mu, modulus, ta->z) != MP_OKAY ||
1523*85732ac8SCy Schubert 		    mp_mulmod(pb->x, &mu, modulus, tb->x) != MP_OKAY ||
1524*85732ac8SCy Schubert 		    mp_mulmod(pb->y, &mu, modulus, tb->y) != MP_OKAY ||
1525*85732ac8SCy Schubert 		    mp_mulmod(pb->z, &mu, modulus, tb->z) != MP_OKAY) {
1526*85732ac8SCy Schubert 			ret = -1;
1527*85732ac8SCy Schubert 			goto end;
1528*85732ac8SCy Schubert 		}
1529*85732ac8SCy Schubert 		pa = ta;
1530*85732ac8SCy Schubert 		pb = tb;
1531*85732ac8SCy Schubert 	}
1532*85732ac8SCy Schubert 
1533*85732ac8SCy Schubert 	ret = ecc_projective_add_point(pa, pb, (ecc_point *) c, &e->a,
1534*85732ac8SCy Schubert 				       &e->prime, e->mont_b);
1535*85732ac8SCy Schubert 	if (ret != 0) {
1536*85732ac8SCy Schubert 		ret = -1;
1537*85732ac8SCy Schubert 		goto end;
1538*85732ac8SCy Schubert 	}
1539*85732ac8SCy Schubert 
1540*85732ac8SCy Schubert 	if (ecc_map((ecc_point *) c, &e->prime, e->mont_b) != MP_OKAY)
1541*85732ac8SCy Schubert 		ret = -1;
1542*85732ac8SCy Schubert 	else
1543*85732ac8SCy Schubert 		ret = 0;
1544*85732ac8SCy Schubert end:
1545*85732ac8SCy Schubert 	wc_ecc_del_point(tb);
1546*85732ac8SCy Schubert 	wc_ecc_del_point(ta);
1547*85732ac8SCy Schubert 	mp_clear(&mu);
1548*85732ac8SCy Schubert 	return ret;
1549*85732ac8SCy Schubert }
1550*85732ac8SCy Schubert 
1551*85732ac8SCy Schubert 
1552*85732ac8SCy Schubert int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
1553*85732ac8SCy Schubert 			const struct crypto_bignum *b,
1554*85732ac8SCy Schubert 			struct crypto_ec_point *res)
1555*85732ac8SCy Schubert {
1556*85732ac8SCy Schubert 	int ret;
1557*85732ac8SCy Schubert 
1558*85732ac8SCy Schubert 	if (TEST_FAIL())
1559*85732ac8SCy Schubert 		return -1;
1560*85732ac8SCy Schubert 
1561*85732ac8SCy Schubert 	ret = wc_ecc_mulmod((mp_int *) b, (ecc_point *) p, (ecc_point *) res,
1562*85732ac8SCy Schubert 			    &e->a, &e->prime, 1);
1563*85732ac8SCy Schubert 	return ret == 0 ? 0 : -1;
1564*85732ac8SCy Schubert }
1565*85732ac8SCy Schubert 
1566*85732ac8SCy Schubert 
1567*85732ac8SCy Schubert int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
1568*85732ac8SCy Schubert {
1569*85732ac8SCy Schubert 	ecc_point *point = (ecc_point *) p;
1570*85732ac8SCy Schubert 
1571*85732ac8SCy Schubert 	if (TEST_FAIL())
1572*85732ac8SCy Schubert 		return -1;
1573*85732ac8SCy Schubert 
1574*85732ac8SCy Schubert 	if (mp_sub(&e->prime, point->y, point->y) != MP_OKAY)
1575*85732ac8SCy Schubert 		return -1;
1576*85732ac8SCy Schubert 
1577*85732ac8SCy Schubert 	return 0;
1578*85732ac8SCy Schubert }
1579*85732ac8SCy Schubert 
1580*85732ac8SCy Schubert 
1581*85732ac8SCy Schubert int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
1582*85732ac8SCy Schubert 				  struct crypto_ec_point *p,
1583*85732ac8SCy Schubert 				  const struct crypto_bignum *x, int y_bit)
1584*85732ac8SCy Schubert {
1585*85732ac8SCy Schubert 	byte buf[1 + 2 * MAX_ECC_BYTES];
1586*85732ac8SCy Schubert 	int ret;
1587*85732ac8SCy Schubert 	int prime_len = crypto_ec_prime_len(e);
1588*85732ac8SCy Schubert 
1589*85732ac8SCy Schubert 	if (TEST_FAIL())
1590*85732ac8SCy Schubert 		return -1;
1591*85732ac8SCy Schubert 
1592*85732ac8SCy Schubert 	buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
1593*85732ac8SCy Schubert 	ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len);
1594*85732ac8SCy Schubert 	if (ret <= 0)
1595*85732ac8SCy Schubert 		return -1;
1596*85732ac8SCy Schubert 	ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx,
1597*85732ac8SCy Schubert 				      (ecc_point *) p);
1598*85732ac8SCy Schubert 	if (ret != 0)
1599*85732ac8SCy Schubert 		return -1;
1600*85732ac8SCy Schubert 
1601*85732ac8SCy Schubert 	return 0;
1602*85732ac8SCy Schubert }
1603*85732ac8SCy Schubert 
1604*85732ac8SCy Schubert 
1605*85732ac8SCy Schubert struct crypto_bignum *
1606*85732ac8SCy Schubert crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
1607*85732ac8SCy Schubert 			      const struct crypto_bignum *x)
1608*85732ac8SCy Schubert {
1609*85732ac8SCy Schubert 	mp_int *y2 = NULL;
1610*85732ac8SCy Schubert 	mp_int t;
1611*85732ac8SCy Schubert 	int calced = 0;
1612*85732ac8SCy Schubert 
1613*85732ac8SCy Schubert 	if (TEST_FAIL())
1614*85732ac8SCy Schubert 		return NULL;
1615*85732ac8SCy Schubert 
1616*85732ac8SCy Schubert 	if (mp_init(&t) != MP_OKAY)
1617*85732ac8SCy Schubert 		return NULL;
1618*85732ac8SCy Schubert 
1619*85732ac8SCy Schubert 	y2 = (mp_int *) crypto_bignum_init();
1620*85732ac8SCy Schubert 	if (!y2)
1621*85732ac8SCy Schubert 		goto done;
1622*85732ac8SCy Schubert 
1623*85732ac8SCy Schubert 	if (mp_sqrmod((mp_int *) x, &e->prime, y2) != 0 ||
1624*85732ac8SCy Schubert 	    mp_mulmod((mp_int *) x, y2, &e->prime, y2) != 0 ||
1625*85732ac8SCy Schubert 	    mp_mulmod((mp_int *) x, &e->a, &e->prime, &t) != 0 ||
1626*85732ac8SCy Schubert 	    mp_addmod(y2, &t, &e->prime, y2) != 0 ||
1627*85732ac8SCy Schubert 	    mp_addmod(y2, &e->b, &e->prime, y2) != 0)
1628*85732ac8SCy Schubert 		goto done;
1629*85732ac8SCy Schubert 
1630*85732ac8SCy Schubert 	calced = 1;
1631*85732ac8SCy Schubert done:
1632*85732ac8SCy Schubert 	if (!calced) {
1633*85732ac8SCy Schubert 		if (y2) {
1634*85732ac8SCy Schubert 			mp_clear(y2);
1635*85732ac8SCy Schubert 			os_free(y2);
1636*85732ac8SCy Schubert 		}
1637*85732ac8SCy Schubert 		mp_clear(&t);
1638*85732ac8SCy Schubert 	}
1639*85732ac8SCy Schubert 
1640*85732ac8SCy Schubert 	return (struct crypto_bignum *) y2;
1641*85732ac8SCy Schubert }
1642*85732ac8SCy Schubert 
1643*85732ac8SCy Schubert 
1644*85732ac8SCy Schubert int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
1645*85732ac8SCy Schubert 				   const struct crypto_ec_point *p)
1646*85732ac8SCy Schubert {
1647*85732ac8SCy Schubert 	return wc_ecc_point_is_at_infinity((ecc_point *) p);
1648*85732ac8SCy Schubert }
1649*85732ac8SCy Schubert 
1650*85732ac8SCy Schubert 
1651*85732ac8SCy Schubert int crypto_ec_point_is_on_curve(struct crypto_ec *e,
1652*85732ac8SCy Schubert 				const struct crypto_ec_point *p)
1653*85732ac8SCy Schubert {
1654*85732ac8SCy Schubert 	return wc_ecc_is_point((ecc_point *) p, &e->a, &e->b, &e->prime) ==
1655*85732ac8SCy Schubert 		MP_OKAY;
1656*85732ac8SCy Schubert }
1657*85732ac8SCy Schubert 
1658*85732ac8SCy Schubert 
1659*85732ac8SCy Schubert int crypto_ec_point_cmp(const struct crypto_ec *e,
1660*85732ac8SCy Schubert 			const struct crypto_ec_point *a,
1661*85732ac8SCy Schubert 			const struct crypto_ec_point *b)
1662*85732ac8SCy Schubert {
1663*85732ac8SCy Schubert 	return wc_ecc_cmp_point((ecc_point *) a, (ecc_point *) b);
1664*85732ac8SCy Schubert }
1665*85732ac8SCy Schubert 
1666*85732ac8SCy Schubert 
1667*85732ac8SCy Schubert struct crypto_ecdh {
1668*85732ac8SCy Schubert 	struct crypto_ec *ec;
1669*85732ac8SCy Schubert };
1670*85732ac8SCy Schubert 
1671*85732ac8SCy Schubert struct crypto_ecdh * crypto_ecdh_init(int group)
1672*85732ac8SCy Schubert {
1673*85732ac8SCy Schubert 	struct crypto_ecdh *ecdh = NULL;
1674*85732ac8SCy Schubert 	WC_RNG rng;
1675*85732ac8SCy Schubert 	int ret;
1676*85732ac8SCy Schubert 
1677*85732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
1678*85732ac8SCy Schubert 		goto fail;
1679*85732ac8SCy Schubert 
1680*85732ac8SCy Schubert 	ecdh = os_zalloc(sizeof(*ecdh));
1681*85732ac8SCy Schubert 	if (!ecdh)
1682*85732ac8SCy Schubert 		goto fail;
1683*85732ac8SCy Schubert 
1684*85732ac8SCy Schubert 	ecdh->ec = crypto_ec_init(group);
1685*85732ac8SCy Schubert 	if (!ecdh->ec)
1686*85732ac8SCy Schubert 		goto fail;
1687*85732ac8SCy Schubert 
1688*85732ac8SCy Schubert 	ret = wc_ecc_make_key_ex(&rng, ecdh->ec->key.dp->size, &ecdh->ec->key,
1689*85732ac8SCy Schubert 				 ecdh->ec->key.dp->id);
1690*85732ac8SCy Schubert 	if (ret < 0)
1691*85732ac8SCy Schubert 		goto fail;
1692*85732ac8SCy Schubert 
1693*85732ac8SCy Schubert done:
1694*85732ac8SCy Schubert 	wc_FreeRng(&rng);
1695*85732ac8SCy Schubert 
1696*85732ac8SCy Schubert 	return ecdh;
1697*85732ac8SCy Schubert fail:
1698*85732ac8SCy Schubert 	crypto_ecdh_deinit(ecdh);
1699*85732ac8SCy Schubert 	ecdh = NULL;
1700*85732ac8SCy Schubert 	goto done;
1701*85732ac8SCy Schubert }
1702*85732ac8SCy Schubert 
1703*85732ac8SCy Schubert 
1704*85732ac8SCy Schubert void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
1705*85732ac8SCy Schubert {
1706*85732ac8SCy Schubert 	if (ecdh) {
1707*85732ac8SCy Schubert 		crypto_ec_deinit(ecdh->ec);
1708*85732ac8SCy Schubert 		os_free(ecdh);
1709*85732ac8SCy Schubert 	}
1710*85732ac8SCy Schubert }
1711*85732ac8SCy Schubert 
1712*85732ac8SCy Schubert 
1713*85732ac8SCy Schubert struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
1714*85732ac8SCy Schubert {
1715*85732ac8SCy Schubert 	struct wpabuf *buf = NULL;
1716*85732ac8SCy Schubert 	int ret;
1717*85732ac8SCy Schubert 	int len = ecdh->ec->key.dp->size;
1718*85732ac8SCy Schubert 
1719*85732ac8SCy Schubert 	buf = wpabuf_alloc(inc_y ? 2 * len : len);
1720*85732ac8SCy Schubert 	if (!buf)
1721*85732ac8SCy Schubert 		goto fail;
1722*85732ac8SCy Schubert 
1723*85732ac8SCy Schubert 	ret = crypto_bignum_to_bin((struct crypto_bignum *)
1724*85732ac8SCy Schubert 				   ecdh->ec->key.pubkey.x, wpabuf_put(buf, len),
1725*85732ac8SCy Schubert 				   len, len);
1726*85732ac8SCy Schubert 	if (ret < 0)
1727*85732ac8SCy Schubert 		goto fail;
1728*85732ac8SCy Schubert 	if (inc_y) {
1729*85732ac8SCy Schubert 		ret = crypto_bignum_to_bin((struct crypto_bignum *)
1730*85732ac8SCy Schubert 					   ecdh->ec->key.pubkey.y,
1731*85732ac8SCy Schubert 					   wpabuf_put(buf, len), len, len);
1732*85732ac8SCy Schubert 		if (ret < 0)
1733*85732ac8SCy Schubert 			goto fail;
1734*85732ac8SCy Schubert 	}
1735*85732ac8SCy Schubert 
1736*85732ac8SCy Schubert done:
1737*85732ac8SCy Schubert 	return buf;
1738*85732ac8SCy Schubert fail:
1739*85732ac8SCy Schubert 	wpabuf_free(buf);
1740*85732ac8SCy Schubert 	buf = NULL;
1741*85732ac8SCy Schubert 	goto done;
1742*85732ac8SCy Schubert }
1743*85732ac8SCy Schubert 
1744*85732ac8SCy Schubert 
1745*85732ac8SCy Schubert struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
1746*85732ac8SCy Schubert 					const u8 *key, size_t len)
1747*85732ac8SCy Schubert {
1748*85732ac8SCy Schubert 	int ret;
1749*85732ac8SCy Schubert 	struct wpabuf *pubkey = NULL;
1750*85732ac8SCy Schubert 	struct wpabuf *secret = NULL;
1751*85732ac8SCy Schubert 	word32 key_len = ecdh->ec->key.dp->size;
1752*85732ac8SCy Schubert 	ecc_point *point = NULL;
1753*85732ac8SCy Schubert 	size_t need_key_len = inc_y ? 2 * key_len : key_len;
1754*85732ac8SCy Schubert 
1755*85732ac8SCy Schubert 	if (len < need_key_len)
1756*85732ac8SCy Schubert 		goto fail;
1757*85732ac8SCy Schubert 	pubkey = wpabuf_alloc(1 + 2 * key_len);
1758*85732ac8SCy Schubert 	if (!pubkey)
1759*85732ac8SCy Schubert 		goto fail;
1760*85732ac8SCy Schubert 	wpabuf_put_u8(pubkey, inc_y ? ECC_POINT_UNCOMP : ECC_POINT_COMP_EVEN);
1761*85732ac8SCy Schubert 	wpabuf_put_data(pubkey, key, need_key_len);
1762*85732ac8SCy Schubert 
1763*85732ac8SCy Schubert 	point = wc_ecc_new_point();
1764*85732ac8SCy Schubert 	if (!point)
1765*85732ac8SCy Schubert 		goto fail;
1766*85732ac8SCy Schubert 
1767*85732ac8SCy Schubert 	ret = wc_ecc_import_point_der(wpabuf_mhead(pubkey), 1 + 2 * key_len,
1768*85732ac8SCy Schubert 				      ecdh->ec->key.idx, point);
1769*85732ac8SCy Schubert 	if (ret != MP_OKAY)
1770*85732ac8SCy Schubert 		goto fail;
1771*85732ac8SCy Schubert 
1772*85732ac8SCy Schubert 	secret = wpabuf_alloc(key_len);
1773*85732ac8SCy Schubert 	if (!secret)
1774*85732ac8SCy Schubert 		goto fail;
1775*85732ac8SCy Schubert 
1776*85732ac8SCy Schubert 	ret = wc_ecc_shared_secret_ex(&ecdh->ec->key, point,
1777*85732ac8SCy Schubert 				      wpabuf_put(secret, key_len), &key_len);
1778*85732ac8SCy Schubert 	if (ret != MP_OKAY)
1779*85732ac8SCy Schubert 		goto fail;
1780*85732ac8SCy Schubert 
1781*85732ac8SCy Schubert done:
1782*85732ac8SCy Schubert 	wc_ecc_del_point(point);
1783*85732ac8SCy Schubert 	wpabuf_free(pubkey);
1784*85732ac8SCy Schubert 	return secret;
1785*85732ac8SCy Schubert fail:
1786*85732ac8SCy Schubert 	wpabuf_free(secret);
1787*85732ac8SCy Schubert 	secret = NULL;
1788*85732ac8SCy Schubert 	goto done;
1789*85732ac8SCy Schubert }
1790*85732ac8SCy Schubert 
1791*85732ac8SCy Schubert #endif /* CONFIG_ECC */
1792