xref: /freebsd/contrib/wpa/src/crypto/crypto_wolfssl.c (revision 4b72b91a7132df1f77bbae194e1071ac621f1edb)
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"
1385732ac8SCy Schubert 
1485732ac8SCy Schubert /* wolfSSL headers */
1585732ac8SCy Schubert #include <wolfssl/options.h>
1685732ac8SCy Schubert #include <wolfssl/wolfcrypt/md4.h>
1785732ac8SCy Schubert #include <wolfssl/wolfcrypt/md5.h>
1885732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha.h>
1985732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha256.h>
2085732ac8SCy Schubert #include <wolfssl/wolfcrypt/sha512.h>
2185732ac8SCy Schubert #include <wolfssl/wolfcrypt/hmac.h>
2285732ac8SCy Schubert #include <wolfssl/wolfcrypt/pwdbased.h>
2385732ac8SCy Schubert #include <wolfssl/wolfcrypt/arc4.h>
2485732ac8SCy Schubert #include <wolfssl/wolfcrypt/des3.h>
2585732ac8SCy Schubert #include <wolfssl/wolfcrypt/aes.h>
2685732ac8SCy Schubert #include <wolfssl/wolfcrypt/dh.h>
2785732ac8SCy Schubert #include <wolfssl/wolfcrypt/cmac.h>
2885732ac8SCy Schubert #include <wolfssl/wolfcrypt/ecc.h>
2985732ac8SCy Schubert #include <wolfssl/openssl/bn.h>
3085732ac8SCy Schubert 
3185732ac8SCy Schubert 
3285732ac8SCy Schubert #ifndef CONFIG_FIPS
3385732ac8SCy Schubert 
3485732ac8SCy Schubert int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3585732ac8SCy Schubert {
3685732ac8SCy Schubert 	Md4 md4;
3785732ac8SCy Schubert 	size_t i;
3885732ac8SCy Schubert 
3985732ac8SCy Schubert 	if (TEST_FAIL())
4085732ac8SCy Schubert 		return -1;
4185732ac8SCy Schubert 
4285732ac8SCy Schubert 	wc_InitMd4(&md4);
4385732ac8SCy Schubert 
4485732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
4585732ac8SCy Schubert 		wc_Md4Update(&md4, addr[i], len[i]);
4685732ac8SCy Schubert 
4785732ac8SCy Schubert 	wc_Md4Final(&md4, mac);
4885732ac8SCy Schubert 
4985732ac8SCy Schubert 	return 0;
5085732ac8SCy Schubert }
5185732ac8SCy Schubert 
5285732ac8SCy Schubert 
5385732ac8SCy Schubert int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
5485732ac8SCy Schubert {
5585732ac8SCy Schubert 	wc_Md5 md5;
5685732ac8SCy Schubert 	size_t i;
5785732ac8SCy Schubert 
5885732ac8SCy Schubert 	if (TEST_FAIL())
5985732ac8SCy Schubert 		return -1;
6085732ac8SCy Schubert 
6185732ac8SCy Schubert 	wc_InitMd5(&md5);
6285732ac8SCy Schubert 
6385732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
6485732ac8SCy Schubert 		wc_Md5Update(&md5, addr[i], len[i]);
6585732ac8SCy Schubert 
6685732ac8SCy Schubert 	wc_Md5Final(&md5, mac);
6785732ac8SCy Schubert 
6885732ac8SCy Schubert 	return 0;
6985732ac8SCy Schubert }
7085732ac8SCy Schubert 
7185732ac8SCy Schubert #endif /* CONFIG_FIPS */
7285732ac8SCy Schubert 
7385732ac8SCy Schubert 
7485732ac8SCy Schubert int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
7585732ac8SCy Schubert {
7685732ac8SCy Schubert 	wc_Sha sha;
7785732ac8SCy Schubert 	size_t i;
7885732ac8SCy Schubert 
7985732ac8SCy Schubert 	if (TEST_FAIL())
8085732ac8SCy Schubert 		return -1;
8185732ac8SCy Schubert 
8285732ac8SCy Schubert 	wc_InitSha(&sha);
8385732ac8SCy Schubert 
8485732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
8585732ac8SCy Schubert 		wc_ShaUpdate(&sha, addr[i], len[i]);
8685732ac8SCy Schubert 
8785732ac8SCy Schubert 	wc_ShaFinal(&sha, mac);
8885732ac8SCy Schubert 
8985732ac8SCy Schubert 	return 0;
9085732ac8SCy Schubert }
9185732ac8SCy Schubert 
9285732ac8SCy Schubert 
9385732ac8SCy Schubert #ifndef NO_SHA256_WRAPPER
9485732ac8SCy Schubert int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
9585732ac8SCy Schubert 		  u8 *mac)
9685732ac8SCy Schubert {
9785732ac8SCy Schubert 	wc_Sha256 sha256;
9885732ac8SCy Schubert 	size_t i;
9985732ac8SCy Schubert 
10085732ac8SCy Schubert 	if (TEST_FAIL())
10185732ac8SCy Schubert 		return -1;
10285732ac8SCy Schubert 
10385732ac8SCy Schubert 	wc_InitSha256(&sha256);
10485732ac8SCy Schubert 
10585732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
10685732ac8SCy Schubert 		wc_Sha256Update(&sha256, addr[i], len[i]);
10785732ac8SCy Schubert 
10885732ac8SCy Schubert 	wc_Sha256Final(&sha256, mac);
10985732ac8SCy Schubert 
11085732ac8SCy Schubert 	return 0;
11185732ac8SCy Schubert }
11285732ac8SCy Schubert #endif /* NO_SHA256_WRAPPER */
11385732ac8SCy Schubert 
11485732ac8SCy Schubert 
11585732ac8SCy Schubert #ifdef CONFIG_SHA384
11685732ac8SCy Schubert int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
11785732ac8SCy Schubert 		  u8 *mac)
11885732ac8SCy Schubert {
11985732ac8SCy Schubert 	wc_Sha384 sha384;
12085732ac8SCy Schubert 	size_t i;
12185732ac8SCy Schubert 
12285732ac8SCy Schubert 	if (TEST_FAIL())
12385732ac8SCy Schubert 		return -1;
12485732ac8SCy Schubert 
12585732ac8SCy Schubert 	wc_InitSha384(&sha384);
12685732ac8SCy Schubert 
12785732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
12885732ac8SCy Schubert 		wc_Sha384Update(&sha384, addr[i], len[i]);
12985732ac8SCy Schubert 
13085732ac8SCy Schubert 	wc_Sha384Final(&sha384, mac);
13185732ac8SCy Schubert 
13285732ac8SCy Schubert 	return 0;
13385732ac8SCy Schubert }
13485732ac8SCy Schubert #endif /* CONFIG_SHA384 */
13585732ac8SCy Schubert 
13685732ac8SCy Schubert 
13785732ac8SCy Schubert #ifdef CONFIG_SHA512
13885732ac8SCy Schubert int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
13985732ac8SCy Schubert 		  u8 *mac)
14085732ac8SCy Schubert {
14185732ac8SCy Schubert 	wc_Sha512 sha512;
14285732ac8SCy Schubert 	size_t i;
14385732ac8SCy Schubert 
14485732ac8SCy Schubert 	if (TEST_FAIL())
14585732ac8SCy Schubert 		return -1;
14685732ac8SCy Schubert 
14785732ac8SCy Schubert 	wc_InitSha512(&sha512);
14885732ac8SCy Schubert 
14985732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
15085732ac8SCy Schubert 		wc_Sha512Update(&sha512, addr[i], len[i]);
15185732ac8SCy Schubert 
15285732ac8SCy Schubert 	wc_Sha512Final(&sha512, mac);
15385732ac8SCy Schubert 
15485732ac8SCy Schubert 	return 0;
15585732ac8SCy Schubert }
15685732ac8SCy Schubert #endif /* CONFIG_SHA512 */
15785732ac8SCy Schubert 
15885732ac8SCy Schubert 
15985732ac8SCy Schubert static int wolfssl_hmac_vector(int type, const u8 *key,
16085732ac8SCy Schubert 			       size_t key_len, size_t num_elem,
16185732ac8SCy Schubert 			       const u8 *addr[], const size_t *len, u8 *mac,
16285732ac8SCy Schubert 			       unsigned int mdlen)
16385732ac8SCy Schubert {
16485732ac8SCy Schubert 	Hmac hmac;
16585732ac8SCy Schubert 	size_t i;
16685732ac8SCy Schubert 
16785732ac8SCy Schubert 	(void) mdlen;
16885732ac8SCy Schubert 
16985732ac8SCy Schubert 	if (TEST_FAIL())
17085732ac8SCy Schubert 		return -1;
17185732ac8SCy Schubert 
17285732ac8SCy Schubert 	if (wc_HmacSetKey(&hmac, type, key, (word32) key_len) != 0)
17385732ac8SCy Schubert 		return -1;
17485732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
17585732ac8SCy Schubert 		if (wc_HmacUpdate(&hmac, addr[i], len[i]) != 0)
17685732ac8SCy Schubert 			return -1;
17785732ac8SCy Schubert 	if (wc_HmacFinal(&hmac, mac) != 0)
17885732ac8SCy Schubert 		return -1;
17985732ac8SCy Schubert 	return 0;
18085732ac8SCy Schubert }
18185732ac8SCy Schubert 
18285732ac8SCy Schubert 
18385732ac8SCy Schubert #ifndef CONFIG_FIPS
18485732ac8SCy Schubert 
18585732ac8SCy Schubert int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
18685732ac8SCy Schubert 		    const u8 *addr[], const size_t *len, u8 *mac)
18785732ac8SCy Schubert {
18885732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_MD5, key, key_len, num_elem, addr, len,
18985732ac8SCy Schubert 				   mac, 16);
19085732ac8SCy Schubert }
19185732ac8SCy Schubert 
19285732ac8SCy Schubert 
19385732ac8SCy Schubert int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
19485732ac8SCy Schubert 	     u8 *mac)
19585732ac8SCy Schubert {
19685732ac8SCy Schubert 	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
19785732ac8SCy Schubert }
19885732ac8SCy Schubert 
19985732ac8SCy Schubert #endif /* CONFIG_FIPS */
20085732ac8SCy Schubert 
20185732ac8SCy Schubert 
20285732ac8SCy Schubert int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
20385732ac8SCy Schubert 		     const u8 *addr[], const size_t *len, u8 *mac)
20485732ac8SCy Schubert {
20585732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA, key, key_len, num_elem, addr, len,
20685732ac8SCy Schubert 				   mac, 20);
20785732ac8SCy Schubert }
20885732ac8SCy Schubert 
20985732ac8SCy Schubert 
21085732ac8SCy Schubert int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
21185732ac8SCy Schubert 	      u8 *mac)
21285732ac8SCy Schubert {
21385732ac8SCy Schubert 	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
21485732ac8SCy Schubert }
21585732ac8SCy Schubert 
21685732ac8SCy Schubert 
21785732ac8SCy Schubert #ifdef CONFIG_SHA256
21885732ac8SCy Schubert 
21985732ac8SCy Schubert int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
22085732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
22185732ac8SCy Schubert {
22285732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA256, key, key_len, num_elem, addr, len,
22385732ac8SCy Schubert 				   mac, 32);
22485732ac8SCy Schubert }
22585732ac8SCy Schubert 
22685732ac8SCy Schubert 
22785732ac8SCy Schubert int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
22885732ac8SCy Schubert 		size_t data_len, u8 *mac)
22985732ac8SCy Schubert {
23085732ac8SCy Schubert 	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
23185732ac8SCy Schubert }
23285732ac8SCy Schubert 
23385732ac8SCy Schubert #endif /* CONFIG_SHA256 */
23485732ac8SCy Schubert 
23585732ac8SCy Schubert 
23685732ac8SCy Schubert #ifdef CONFIG_SHA384
23785732ac8SCy Schubert 
23885732ac8SCy Schubert int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
23985732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
24085732ac8SCy Schubert {
24185732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA384, key, key_len, num_elem, addr, len,
24285732ac8SCy Schubert 				   mac, 48);
24385732ac8SCy Schubert }
24485732ac8SCy Schubert 
24585732ac8SCy Schubert 
24685732ac8SCy Schubert int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
24785732ac8SCy Schubert 		size_t data_len, u8 *mac)
24885732ac8SCy Schubert {
24985732ac8SCy Schubert 	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
25085732ac8SCy Schubert }
25185732ac8SCy Schubert 
25285732ac8SCy Schubert #endif /* CONFIG_SHA384 */
25385732ac8SCy Schubert 
25485732ac8SCy Schubert 
25585732ac8SCy Schubert #ifdef CONFIG_SHA512
25685732ac8SCy Schubert 
25785732ac8SCy Schubert int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
25885732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
25985732ac8SCy Schubert {
26085732ac8SCy Schubert 	return wolfssl_hmac_vector(WC_SHA512, key, key_len, num_elem, addr, len,
26185732ac8SCy Schubert 				   mac, 64);
26285732ac8SCy Schubert }
26385732ac8SCy Schubert 
26485732ac8SCy Schubert 
26585732ac8SCy Schubert int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
26685732ac8SCy Schubert 		size_t data_len, u8 *mac)
26785732ac8SCy Schubert {
26885732ac8SCy Schubert 	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
26985732ac8SCy Schubert }
27085732ac8SCy Schubert 
27185732ac8SCy Schubert #endif /* CONFIG_SHA512 */
27285732ac8SCy Schubert 
27385732ac8SCy Schubert 
27485732ac8SCy Schubert int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
27585732ac8SCy Schubert 		int iterations, u8 *buf, size_t buflen)
27685732ac8SCy Schubert {
27785732ac8SCy Schubert 	if (wc_PBKDF2(buf, (const byte*)passphrase, os_strlen(passphrase), ssid,
27885732ac8SCy Schubert 		      ssid_len, iterations, buflen, WC_SHA) != 0)
27985732ac8SCy Schubert 		return -1;
28085732ac8SCy Schubert 	return 0;
28185732ac8SCy Schubert }
28285732ac8SCy Schubert 
28385732ac8SCy Schubert 
28485732ac8SCy Schubert #ifdef CONFIG_DES
28585732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
28685732ac8SCy Schubert {
28785732ac8SCy Schubert 	Des des;
28885732ac8SCy Schubert 	u8  pkey[8], next, tmp;
28985732ac8SCy Schubert 	int i;
29085732ac8SCy Schubert 
29185732ac8SCy Schubert 	/* Add parity bits to the key */
29285732ac8SCy Schubert 	next = 0;
29385732ac8SCy Schubert 	for (i = 0; i < 7; i++) {
29485732ac8SCy Schubert 		tmp = key[i];
29585732ac8SCy Schubert 		pkey[i] = (tmp >> i) | next | 1;
29685732ac8SCy Schubert 		next = tmp << (7 - i);
29785732ac8SCy Schubert 	}
29885732ac8SCy Schubert 	pkey[i] = next | 1;
29985732ac8SCy Schubert 
30085732ac8SCy Schubert 	wc_Des_SetKey(&des, pkey, NULL, DES_ENCRYPTION);
30185732ac8SCy Schubert 	wc_Des_EcbEncrypt(&des, cypher, clear, DES_BLOCK_SIZE);
30285732ac8SCy Schubert 
30385732ac8SCy Schubert 	return 0;
30485732ac8SCy Schubert }
30585732ac8SCy Schubert #endif /* CONFIG_DES */
30685732ac8SCy Schubert 
30785732ac8SCy Schubert 
30885732ac8SCy Schubert void * aes_encrypt_init(const u8 *key, size_t len)
30985732ac8SCy Schubert {
31085732ac8SCy Schubert 	Aes *aes;
31185732ac8SCy Schubert 
31285732ac8SCy Schubert 	if (TEST_FAIL())
31385732ac8SCy Schubert 		return NULL;
31485732ac8SCy Schubert 
31585732ac8SCy Schubert 	aes = os_malloc(sizeof(Aes));
31685732ac8SCy Schubert 	if (!aes)
31785732ac8SCy Schubert 		return NULL;
31885732ac8SCy Schubert 
31985732ac8SCy Schubert 	if (wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION) < 0) {
32085732ac8SCy Schubert 		os_free(aes);
32185732ac8SCy Schubert 		return NULL;
32285732ac8SCy Schubert 	}
32385732ac8SCy Schubert 
32485732ac8SCy Schubert 	return aes;
32585732ac8SCy Schubert }
32685732ac8SCy Schubert 
32785732ac8SCy Schubert 
32885732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
32985732ac8SCy Schubert {
33085732ac8SCy Schubert 	wc_AesEncryptDirect(ctx, crypt, plain);
33185732ac8SCy Schubert 	return 0;
33285732ac8SCy Schubert }
33385732ac8SCy Schubert 
33485732ac8SCy Schubert 
33585732ac8SCy Schubert void aes_encrypt_deinit(void *ctx)
33685732ac8SCy Schubert {
33785732ac8SCy Schubert 	os_free(ctx);
33885732ac8SCy Schubert }
33985732ac8SCy Schubert 
34085732ac8SCy Schubert 
34185732ac8SCy Schubert void * aes_decrypt_init(const u8 *key, size_t len)
34285732ac8SCy Schubert {
34385732ac8SCy Schubert 	Aes *aes;
34485732ac8SCy Schubert 
34585732ac8SCy Schubert 	if (TEST_FAIL())
34685732ac8SCy Schubert 		return NULL;
34785732ac8SCy Schubert 
34885732ac8SCy Schubert 	aes = os_malloc(sizeof(Aes));
34985732ac8SCy Schubert 	if (!aes)
35085732ac8SCy Schubert 		return NULL;
35185732ac8SCy Schubert 
35285732ac8SCy Schubert 	if (wc_AesSetKey(aes, key, len, NULL, AES_DECRYPTION) < 0) {
35385732ac8SCy Schubert 		os_free(aes);
35485732ac8SCy Schubert 		return NULL;
35585732ac8SCy Schubert 	}
35685732ac8SCy Schubert 
35785732ac8SCy Schubert 	return aes;
35885732ac8SCy Schubert }
35985732ac8SCy Schubert 
36085732ac8SCy Schubert 
36185732ac8SCy Schubert int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
36285732ac8SCy Schubert {
36385732ac8SCy Schubert 	wc_AesDecryptDirect(ctx, plain, crypt);
36485732ac8SCy Schubert 	return 0;
36585732ac8SCy Schubert }
36685732ac8SCy Schubert 
36785732ac8SCy Schubert 
36885732ac8SCy Schubert void aes_decrypt_deinit(void *ctx)
36985732ac8SCy Schubert {
37085732ac8SCy Schubert 	os_free(ctx);
37185732ac8SCy Schubert }
37285732ac8SCy Schubert 
37385732ac8SCy Schubert 
37485732ac8SCy Schubert int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
37585732ac8SCy Schubert {
37685732ac8SCy Schubert 	Aes aes;
37785732ac8SCy Schubert 	int ret;
37885732ac8SCy Schubert 
37985732ac8SCy Schubert 	if (TEST_FAIL())
38085732ac8SCy Schubert 		return -1;
38185732ac8SCy Schubert 
38285732ac8SCy Schubert 	ret = wc_AesSetKey(&aes, key, 16, iv, AES_ENCRYPTION);
38385732ac8SCy Schubert 	if (ret != 0)
38485732ac8SCy Schubert 		return -1;
38585732ac8SCy Schubert 
38685732ac8SCy Schubert 	ret = wc_AesCbcEncrypt(&aes, data, data, data_len);
38785732ac8SCy Schubert 	if (ret != 0)
38885732ac8SCy Schubert 		return -1;
38985732ac8SCy Schubert 	return 0;
39085732ac8SCy Schubert }
39185732ac8SCy Schubert 
39285732ac8SCy Schubert 
39385732ac8SCy Schubert int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
39485732ac8SCy Schubert {
39585732ac8SCy Schubert 	Aes aes;
39685732ac8SCy Schubert 	int ret;
39785732ac8SCy Schubert 
39885732ac8SCy Schubert 	if (TEST_FAIL())
39985732ac8SCy Schubert 		return -1;
40085732ac8SCy Schubert 
40185732ac8SCy Schubert 	ret = wc_AesSetKey(&aes, key, 16, iv, AES_DECRYPTION);
40285732ac8SCy Schubert 	if (ret != 0)
40385732ac8SCy Schubert 		return -1;
40485732ac8SCy Schubert 
40585732ac8SCy Schubert 	ret = wc_AesCbcDecrypt(&aes, data, data, data_len);
40685732ac8SCy Schubert 	if (ret != 0)
40785732ac8SCy Schubert 		return -1;
40885732ac8SCy Schubert 	return 0;
40985732ac8SCy Schubert }
41085732ac8SCy Schubert 
41185732ac8SCy Schubert 
41285732ac8SCy Schubert int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
41385732ac8SCy Schubert {
41485732ac8SCy Schubert 	int ret;
41585732ac8SCy Schubert 
41685732ac8SCy Schubert 	if (TEST_FAIL())
41785732ac8SCy Schubert 		return -1;
41885732ac8SCy Schubert 
41985732ac8SCy Schubert 	ret = wc_AesKeyWrap(kek, kek_len, plain, n * 8, cipher, (n + 1) * 8,
42085732ac8SCy Schubert 			    NULL);
42185732ac8SCy Schubert 	return ret != (n + 1) * 8 ? -1 : 0;
42285732ac8SCy Schubert }
42385732ac8SCy Schubert 
42485732ac8SCy Schubert 
42585732ac8SCy Schubert int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
42685732ac8SCy Schubert 	       u8 *plain)
42785732ac8SCy Schubert {
42885732ac8SCy Schubert 	int ret;
42985732ac8SCy Schubert 
43085732ac8SCy Schubert 	if (TEST_FAIL())
43185732ac8SCy Schubert 		return -1;
43285732ac8SCy Schubert 
43385732ac8SCy Schubert 	ret = wc_AesKeyUnWrap(kek, kek_len, cipher, (n + 1) * 8, plain, n * 8,
43485732ac8SCy Schubert 			      NULL);
43585732ac8SCy Schubert 	return ret != n * 8 ? -1 : 0;
43685732ac8SCy Schubert }
43785732ac8SCy Schubert 
43885732ac8SCy Schubert 
43985732ac8SCy Schubert #ifndef CONFIG_NO_RC4
44085732ac8SCy Schubert int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data,
44185732ac8SCy Schubert 	     size_t data_len)
44285732ac8SCy Schubert {
44385732ac8SCy Schubert #ifndef NO_RC4
44485732ac8SCy Schubert 	Arc4 arc4;
44585732ac8SCy Schubert 	unsigned char skip_buf[16];
44685732ac8SCy Schubert 
44785732ac8SCy Schubert 	wc_Arc4SetKey(&arc4, key, keylen);
44885732ac8SCy Schubert 
44985732ac8SCy Schubert 	while (skip >= sizeof(skip_buf)) {
45085732ac8SCy Schubert 		size_t len = skip;
45185732ac8SCy Schubert 
45285732ac8SCy Schubert 		if (len > sizeof(skip_buf))
45385732ac8SCy Schubert 			len = sizeof(skip_buf);
45485732ac8SCy Schubert 		wc_Arc4Process(&arc4, skip_buf, skip_buf, len);
45585732ac8SCy Schubert 		skip -= len;
45685732ac8SCy Schubert 	}
45785732ac8SCy Schubert 
45885732ac8SCy Schubert 	wc_Arc4Process(&arc4, data, data, data_len);
45985732ac8SCy Schubert 
46085732ac8SCy Schubert 	return 0;
46185732ac8SCy Schubert #else /* NO_RC4 */
46285732ac8SCy Schubert 	return -1;
46385732ac8SCy Schubert #endif /* NO_RC4 */
46485732ac8SCy Schubert }
46585732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
46685732ac8SCy Schubert 
46785732ac8SCy Schubert 
46885732ac8SCy Schubert #if defined(EAP_IKEV2) || defined(EAP_IKEV2_DYNAMIC) \
46985732ac8SCy Schubert 		       || defined(EAP_SERVER_IKEV2)
47085732ac8SCy Schubert union wolfssl_cipher {
47185732ac8SCy Schubert 	Aes aes;
47285732ac8SCy Schubert 	Des3 des3;
47385732ac8SCy Schubert 	Arc4 arc4;
47485732ac8SCy Schubert };
47585732ac8SCy Schubert 
47685732ac8SCy Schubert struct crypto_cipher {
47785732ac8SCy Schubert 	enum crypto_cipher_alg alg;
47885732ac8SCy Schubert 	union wolfssl_cipher enc;
47985732ac8SCy Schubert 	union wolfssl_cipher dec;
48085732ac8SCy Schubert };
48185732ac8SCy Schubert 
48285732ac8SCy Schubert struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
48385732ac8SCy Schubert 					  const u8 *iv, const u8 *key,
48485732ac8SCy Schubert 					  size_t key_len)
48585732ac8SCy Schubert {
48685732ac8SCy Schubert 	struct crypto_cipher *ctx;
48785732ac8SCy Schubert 
48885732ac8SCy Schubert 	ctx = os_zalloc(sizeof(*ctx));
48985732ac8SCy Schubert 	if (!ctx)
49085732ac8SCy Schubert 		return NULL;
49185732ac8SCy Schubert 
49285732ac8SCy Schubert 	switch (alg) {
49385732ac8SCy Schubert #ifndef CONFIG_NO_RC4
49485732ac8SCy Schubert #ifndef NO_RC4
49585732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
49685732ac8SCy Schubert 		wc_Arc4SetKey(&ctx->enc.arc4, key, key_len);
49785732ac8SCy Schubert 		wc_Arc4SetKey(&ctx->dec.arc4, key, key_len);
49885732ac8SCy Schubert 		break;
49985732ac8SCy Schubert #endif /* NO_RC4 */
50085732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
50185732ac8SCy Schubert #ifndef NO_AES
50285732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
50385732ac8SCy Schubert 		switch (key_len) {
50485732ac8SCy Schubert 		case 16:
50585732ac8SCy Schubert 		case 24:
50685732ac8SCy Schubert 		case 32:
50785732ac8SCy Schubert 			break;
50885732ac8SCy Schubert 		default:
50985732ac8SCy Schubert 			os_free(ctx);
51085732ac8SCy Schubert 			return NULL;
51185732ac8SCy Schubert 		}
51285732ac8SCy Schubert 		if (wc_AesSetKey(&ctx->enc.aes, key, key_len, iv,
51385732ac8SCy Schubert 				 AES_ENCRYPTION) ||
51485732ac8SCy Schubert 		    wc_AesSetKey(&ctx->dec.aes, key, key_len, iv,
51585732ac8SCy Schubert 				 AES_DECRYPTION)) {
51685732ac8SCy Schubert 			os_free(ctx);
51785732ac8SCy Schubert 			return NULL;
51885732ac8SCy Schubert 		}
51985732ac8SCy Schubert 		break;
52085732ac8SCy Schubert #endif /* NO_AES */
52185732ac8SCy Schubert #ifndef NO_DES3
52285732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
52385732ac8SCy Schubert 		if (key_len != DES3_KEYLEN ||
52485732ac8SCy Schubert 		    wc_Des3_SetKey(&ctx->enc.des3, key, iv, DES_ENCRYPTION) ||
52585732ac8SCy Schubert 		    wc_Des3_SetKey(&ctx->dec.des3, key, iv, DES_DECRYPTION)) {
52685732ac8SCy Schubert 			os_free(ctx);
52785732ac8SCy Schubert 			return NULL;
52885732ac8SCy Schubert 		}
52985732ac8SCy Schubert 		break;
53085732ac8SCy Schubert #endif /* NO_DES3 */
53185732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC2:
53285732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_DES:
53385732ac8SCy Schubert 	default:
53485732ac8SCy Schubert 		os_free(ctx);
53585732ac8SCy Schubert 		return NULL;
53685732ac8SCy Schubert 	}
53785732ac8SCy Schubert 
53885732ac8SCy Schubert 	ctx->alg = alg;
53985732ac8SCy Schubert 
54085732ac8SCy Schubert 	return ctx;
54185732ac8SCy Schubert }
54285732ac8SCy Schubert 
54385732ac8SCy Schubert 
54485732ac8SCy Schubert int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
54585732ac8SCy Schubert 			  u8 *crypt, size_t len)
54685732ac8SCy Schubert {
54785732ac8SCy Schubert 	switch (ctx->alg) {
54885732ac8SCy Schubert #ifndef CONFIG_NO_RC4
54985732ac8SCy Schubert #ifndef NO_RC4
55085732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
55185732ac8SCy Schubert 		wc_Arc4Process(&ctx->enc.arc4, crypt, plain, len);
55285732ac8SCy Schubert 		return 0;
55385732ac8SCy Schubert #endif /* NO_RC4 */
55485732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
55585732ac8SCy Schubert #ifndef NO_AES
55685732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
55785732ac8SCy Schubert 		if (wc_AesCbcEncrypt(&ctx->enc.aes, crypt, plain, len) != 0)
55885732ac8SCy Schubert 			return -1;
55985732ac8SCy Schubert 		return 0;
56085732ac8SCy Schubert #endif /* NO_AES */
56185732ac8SCy Schubert #ifndef NO_DES3
56285732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
56385732ac8SCy Schubert 		if (wc_Des3_CbcEncrypt(&ctx->enc.des3, crypt, plain, len) != 0)
56485732ac8SCy Schubert 			return -1;
56585732ac8SCy Schubert 		return 0;
56685732ac8SCy Schubert #endif /* NO_DES3 */
56785732ac8SCy Schubert 	default:
56885732ac8SCy Schubert 		return -1;
56985732ac8SCy Schubert 	}
57085732ac8SCy Schubert 	return -1;
57185732ac8SCy Schubert }
57285732ac8SCy Schubert 
57385732ac8SCy Schubert 
57485732ac8SCy Schubert int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
57585732ac8SCy Schubert 			  u8 *plain, size_t len)
57685732ac8SCy Schubert {
57785732ac8SCy Schubert 	switch (ctx->alg) {
57885732ac8SCy Schubert #ifndef CONFIG_NO_RC4
57985732ac8SCy Schubert #ifndef NO_RC4
58085732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_RC4:
58185732ac8SCy Schubert 		wc_Arc4Process(&ctx->dec.arc4, plain, crypt, len);
58285732ac8SCy Schubert 		return 0;
58385732ac8SCy Schubert #endif /* NO_RC4 */
58485732ac8SCy Schubert #endif /* CONFIG_NO_RC4 */
58585732ac8SCy Schubert #ifndef NO_AES
58685732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_AES:
58785732ac8SCy Schubert 		if (wc_AesCbcDecrypt(&ctx->dec.aes, plain, crypt, len) != 0)
58885732ac8SCy Schubert 			return -1;
58985732ac8SCy Schubert 		return 0;
59085732ac8SCy Schubert #endif /* NO_AES */
59185732ac8SCy Schubert #ifndef NO_DES3
59285732ac8SCy Schubert 	case CRYPTO_CIPHER_ALG_3DES:
59385732ac8SCy Schubert 		if (wc_Des3_CbcDecrypt(&ctx->dec.des3, plain, crypt, len) != 0)
59485732ac8SCy Schubert 			return -1;
59585732ac8SCy Schubert 		return 0;
59685732ac8SCy Schubert #endif /* NO_DES3 */
59785732ac8SCy Schubert 	default:
59885732ac8SCy Schubert 		return -1;
59985732ac8SCy Schubert 	}
60085732ac8SCy Schubert 	return -1;
60185732ac8SCy Schubert }
60285732ac8SCy Schubert 
60385732ac8SCy Schubert 
60485732ac8SCy Schubert void crypto_cipher_deinit(struct crypto_cipher *ctx)
60585732ac8SCy Schubert {
60685732ac8SCy Schubert 	os_free(ctx);
60785732ac8SCy Schubert }
60885732ac8SCy Schubert 
60985732ac8SCy Schubert #endif
61085732ac8SCy Schubert 
61185732ac8SCy Schubert 
612*4b72b91aSCy Schubert #ifdef CONFIG_WPS
61385732ac8SCy Schubert 
61485732ac8SCy Schubert static const unsigned char RFC3526_PRIME_1536[] = {
61585732ac8SCy Schubert 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
61685732ac8SCy Schubert 	0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
61785732ac8SCy Schubert 	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
61885732ac8SCy Schubert 	0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
61985732ac8SCy Schubert 	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
62085732ac8SCy Schubert 	0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
62185732ac8SCy Schubert 	0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
62285732ac8SCy Schubert 	0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
62385732ac8SCy Schubert 	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
62485732ac8SCy Schubert 	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
62585732ac8SCy Schubert 	0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
62685732ac8SCy Schubert 	0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
62785732ac8SCy Schubert 	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
62885732ac8SCy Schubert 	0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
62985732ac8SCy Schubert 	0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
63085732ac8SCy Schubert 	0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
63185732ac8SCy Schubert };
63285732ac8SCy Schubert 
63385732ac8SCy Schubert static const unsigned char RFC3526_GENERATOR_1536[] = {
63485732ac8SCy Schubert 	0x02
63585732ac8SCy Schubert };
63685732ac8SCy Schubert 
63785732ac8SCy Schubert #define RFC3526_LEN sizeof(RFC3526_PRIME_1536)
63885732ac8SCy Schubert 
63985732ac8SCy Schubert 
64085732ac8SCy Schubert void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
64185732ac8SCy Schubert {
64285732ac8SCy Schubert 	WC_RNG rng;
64385732ac8SCy Schubert 	DhKey *ret = NULL;
64485732ac8SCy Schubert 	DhKey *dh = NULL;
64585732ac8SCy Schubert 	struct wpabuf *privkey = NULL;
64685732ac8SCy Schubert 	struct wpabuf *pubkey = NULL;
64785732ac8SCy Schubert 	word32 priv_sz, pub_sz;
64885732ac8SCy Schubert 
64985732ac8SCy Schubert 	*priv = NULL;
65085732ac8SCy Schubert 	wpabuf_free(*publ);
65185732ac8SCy Schubert 	*publ = NULL;
65285732ac8SCy Schubert 
65385732ac8SCy Schubert 	dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
65485732ac8SCy Schubert 	if (!dh)
65585732ac8SCy Schubert 		return NULL;
65685732ac8SCy Schubert 	wc_InitDhKey(dh);
65785732ac8SCy Schubert 
65885732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0) {
65985732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
66085732ac8SCy Schubert 		return NULL;
66185732ac8SCy Schubert 	}
66285732ac8SCy Schubert 
66385732ac8SCy Schubert 	privkey = wpabuf_alloc(RFC3526_LEN);
66485732ac8SCy Schubert 	pubkey = wpabuf_alloc(RFC3526_LEN);
66585732ac8SCy Schubert 	if (!privkey || !pubkey)
66685732ac8SCy Schubert 		goto done;
66785732ac8SCy Schubert 
66885732ac8SCy Schubert 	if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
66985732ac8SCy Schubert 			RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
67085732ac8SCy Schubert 	    != 0)
67185732ac8SCy Schubert 		goto done;
67285732ac8SCy Schubert 
67385732ac8SCy Schubert 	if (wc_DhGenerateKeyPair(dh, &rng, wpabuf_mhead(privkey), &priv_sz,
67485732ac8SCy Schubert 				 wpabuf_mhead(pubkey), &pub_sz) != 0)
67585732ac8SCy Schubert 		goto done;
67685732ac8SCy Schubert 
67785732ac8SCy Schubert 	wpabuf_put(privkey, priv_sz);
67885732ac8SCy Schubert 	wpabuf_put(pubkey, pub_sz);
67985732ac8SCy Schubert 
68085732ac8SCy Schubert 	ret = dh;
68185732ac8SCy Schubert 	*priv = privkey;
68285732ac8SCy Schubert 	*publ = pubkey;
68385732ac8SCy Schubert 	dh = NULL;
68485732ac8SCy Schubert 	privkey = NULL;
68585732ac8SCy Schubert 	pubkey = NULL;
68685732ac8SCy Schubert done:
68785732ac8SCy Schubert 	wpabuf_clear_free(pubkey);
68885732ac8SCy Schubert 	wpabuf_clear_free(privkey);
68985732ac8SCy Schubert 	if (dh) {
69085732ac8SCy Schubert 		wc_FreeDhKey(dh);
69185732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
69285732ac8SCy Schubert 	}
69385732ac8SCy Schubert 	wc_FreeRng(&rng);
69485732ac8SCy Schubert 	return ret;
69585732ac8SCy Schubert }
69685732ac8SCy Schubert 
69785732ac8SCy Schubert 
698*4b72b91aSCy Schubert #ifdef CONFIG_WPS_NFC
699*4b72b91aSCy Schubert 
70085732ac8SCy Schubert void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
70185732ac8SCy Schubert {
70285732ac8SCy Schubert 	DhKey *ret = NULL;
70385732ac8SCy Schubert 	DhKey *dh;
70485732ac8SCy Schubert 	byte *secret;
70585732ac8SCy Schubert 	word32 secret_sz;
70685732ac8SCy Schubert 
70785732ac8SCy Schubert 	dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
70885732ac8SCy Schubert 	if (!dh)
70985732ac8SCy Schubert 		return NULL;
71085732ac8SCy Schubert 	wc_InitDhKey(dh);
71185732ac8SCy Schubert 
71285732ac8SCy Schubert 	secret = XMALLOC(RFC3526_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER);
71385732ac8SCy Schubert 	if (!secret)
71485732ac8SCy Schubert 		goto done;
71585732ac8SCy Schubert 
71685732ac8SCy Schubert 	if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536),
71785732ac8SCy Schubert 			RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536))
71885732ac8SCy Schubert 	    != 0)
71985732ac8SCy Schubert 		goto done;
72085732ac8SCy Schubert 
72185732ac8SCy Schubert 	if (wc_DhAgree(dh, secret, &secret_sz, wpabuf_head(priv),
72285732ac8SCy Schubert 		       wpabuf_len(priv), RFC3526_GENERATOR_1536,
72385732ac8SCy Schubert 		       sizeof(RFC3526_GENERATOR_1536)) != 0)
72485732ac8SCy Schubert 		goto done;
72585732ac8SCy Schubert 
72685732ac8SCy Schubert 	if (secret_sz != wpabuf_len(publ) ||
72785732ac8SCy Schubert 	    os_memcmp(secret, wpabuf_head(publ), secret_sz) != 0)
72885732ac8SCy Schubert 		goto done;
72985732ac8SCy Schubert 
73085732ac8SCy Schubert 	ret = dh;
73185732ac8SCy Schubert 	dh = NULL;
73285732ac8SCy Schubert done:
73385732ac8SCy Schubert 	if (dh) {
73485732ac8SCy Schubert 		wc_FreeDhKey(dh);
73585732ac8SCy Schubert 		XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER);
73685732ac8SCy Schubert 	}
73785732ac8SCy Schubert 	XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
73885732ac8SCy Schubert 	return ret;
73985732ac8SCy Schubert }
74085732ac8SCy Schubert 
741*4b72b91aSCy Schubert #endif /* CONFIG_WPS_NFC */
742*4b72b91aSCy Schubert 
74385732ac8SCy Schubert 
74485732ac8SCy Schubert struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
74585732ac8SCy Schubert 				  const struct wpabuf *own_private)
74685732ac8SCy Schubert {
74785732ac8SCy Schubert 	struct wpabuf *ret = NULL;
74885732ac8SCy Schubert 	struct wpabuf *secret;
74985732ac8SCy Schubert 	word32 secret_sz;
75085732ac8SCy Schubert 
75185732ac8SCy Schubert 	secret = wpabuf_alloc(RFC3526_LEN);
75285732ac8SCy Schubert 	if (!secret)
75385732ac8SCy Schubert 		goto done;
75485732ac8SCy Schubert 
75585732ac8SCy Schubert 	if (wc_DhAgree(ctx, wpabuf_mhead(secret), &secret_sz,
75685732ac8SCy Schubert 		       wpabuf_head(own_private), wpabuf_len(own_private),
75785732ac8SCy Schubert 		       wpabuf_head(peer_public), wpabuf_len(peer_public)) != 0)
75885732ac8SCy Schubert 		goto done;
75985732ac8SCy Schubert 
76085732ac8SCy Schubert 	wpabuf_put(secret, secret_sz);
76185732ac8SCy Schubert 
76285732ac8SCy Schubert 	ret = secret;
76385732ac8SCy Schubert 	secret = NULL;
76485732ac8SCy Schubert done:
76585732ac8SCy Schubert 	wpabuf_clear_free(secret);
76685732ac8SCy Schubert 	return ret;
76785732ac8SCy Schubert }
76885732ac8SCy Schubert 
76985732ac8SCy Schubert 
77085732ac8SCy Schubert void dh5_free(void *ctx)
77185732ac8SCy Schubert {
77285732ac8SCy Schubert 	if (!ctx)
77385732ac8SCy Schubert 		return;
77485732ac8SCy Schubert 
77585732ac8SCy Schubert 	wc_FreeDhKey(ctx);
77685732ac8SCy Schubert 	XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
77785732ac8SCy Schubert }
77885732ac8SCy Schubert 
779*4b72b91aSCy Schubert #endif /* CONFIG_WPS */
78085732ac8SCy Schubert 
78185732ac8SCy Schubert 
78285732ac8SCy Schubert int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
78385732ac8SCy Schubert 		   u8 *pubkey)
78485732ac8SCy Schubert {
78585732ac8SCy Schubert 	int ret = -1;
78685732ac8SCy Schubert 	WC_RNG rng;
78785732ac8SCy Schubert 	DhKey *dh = NULL;
78885732ac8SCy Schubert 	word32 priv_sz, pub_sz;
78985732ac8SCy Schubert 
79085732ac8SCy Schubert 	if (TEST_FAIL())
79185732ac8SCy Schubert 		return -1;
79285732ac8SCy Schubert 
79385732ac8SCy Schubert 	dh = os_malloc(sizeof(DhKey));
79485732ac8SCy Schubert 	if (!dh)
79585732ac8SCy Schubert 		return -1;
79685732ac8SCy Schubert 	wc_InitDhKey(dh);
79785732ac8SCy Schubert 
79885732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0) {
79985732ac8SCy Schubert 		os_free(dh);
80085732ac8SCy Schubert 		return -1;
80185732ac8SCy Schubert 	}
80285732ac8SCy Schubert 
80385732ac8SCy Schubert 	if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
80485732ac8SCy Schubert 		goto done;
80585732ac8SCy Schubert 
80685732ac8SCy Schubert 	if (wc_DhGenerateKeyPair(dh, &rng, privkey, &priv_sz, pubkey, &pub_sz)
80785732ac8SCy Schubert 	    != 0)
80885732ac8SCy Schubert 		goto done;
80985732ac8SCy Schubert 
81085732ac8SCy Schubert 	if (priv_sz < prime_len) {
81185732ac8SCy Schubert 		size_t pad_sz = prime_len - priv_sz;
81285732ac8SCy Schubert 
81385732ac8SCy Schubert 		os_memmove(privkey + pad_sz, privkey, priv_sz);
81485732ac8SCy Schubert 		os_memset(privkey, 0, pad_sz);
81585732ac8SCy Schubert 	}
81685732ac8SCy Schubert 
81785732ac8SCy Schubert 	if (pub_sz < prime_len) {
81885732ac8SCy Schubert 		size_t pad_sz = prime_len - pub_sz;
81985732ac8SCy Schubert 
82085732ac8SCy Schubert 		os_memmove(pubkey + pad_sz, pubkey, pub_sz);
82185732ac8SCy Schubert 		os_memset(pubkey, 0, pad_sz);
82285732ac8SCy Schubert 	}
82385732ac8SCy Schubert 	ret = 0;
82485732ac8SCy Schubert done:
82585732ac8SCy Schubert 	wc_FreeDhKey(dh);
82685732ac8SCy Schubert 	os_free(dh);
82785732ac8SCy Schubert 	wc_FreeRng(&rng);
82885732ac8SCy Schubert 	return ret;
82985732ac8SCy Schubert }
83085732ac8SCy Schubert 
83185732ac8SCy Schubert 
83285732ac8SCy Schubert int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
8334bc52338SCy Schubert 			    const u8 *order, size_t order_len,
83485732ac8SCy Schubert 			    const u8 *privkey, size_t privkey_len,
83585732ac8SCy Schubert 			    const u8 *pubkey, size_t pubkey_len,
83685732ac8SCy Schubert 			    u8 *secret, size_t *len)
83785732ac8SCy Schubert {
83885732ac8SCy Schubert 	int ret = -1;
83985732ac8SCy Schubert 	DhKey *dh;
84085732ac8SCy Schubert 	word32 secret_sz;
84185732ac8SCy Schubert 
84285732ac8SCy Schubert 	dh = os_malloc(sizeof(DhKey));
84385732ac8SCy Schubert 	if (!dh)
84485732ac8SCy Schubert 		return -1;
84585732ac8SCy Schubert 	wc_InitDhKey(dh);
84685732ac8SCy Schubert 
84785732ac8SCy Schubert 	if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0)
84885732ac8SCy Schubert 		goto done;
84985732ac8SCy Schubert 
85085732ac8SCy Schubert 	if (wc_DhAgree(dh, secret, &secret_sz, privkey, privkey_len, pubkey,
85185732ac8SCy Schubert 		       pubkey_len) != 0)
85285732ac8SCy Schubert 		goto done;
85385732ac8SCy Schubert 
85485732ac8SCy Schubert 	*len = secret_sz;
85585732ac8SCy Schubert 	ret = 0;
85685732ac8SCy Schubert done:
85785732ac8SCy Schubert 	wc_FreeDhKey(dh);
85885732ac8SCy Schubert 	os_free(dh);
85985732ac8SCy Schubert 	return ret;
86085732ac8SCy Schubert }
86185732ac8SCy Schubert 
86285732ac8SCy Schubert 
86385732ac8SCy Schubert #ifdef CONFIG_FIPS
86485732ac8SCy Schubert int crypto_get_random(void *buf, size_t len)
86585732ac8SCy Schubert {
86685732ac8SCy Schubert 	int ret = 0;
86785732ac8SCy Schubert 	WC_RNG rng;
86885732ac8SCy Schubert 
86985732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
87085732ac8SCy Schubert 		return -1;
87185732ac8SCy Schubert 	if (wc_RNG_GenerateBlock(&rng, buf, len) != 0)
87285732ac8SCy Schubert 		ret = -1;
87385732ac8SCy Schubert 	wc_FreeRng(&rng);
87485732ac8SCy Schubert 	return ret;
87585732ac8SCy Schubert }
87685732ac8SCy Schubert #endif /* CONFIG_FIPS */
87785732ac8SCy Schubert 
87885732ac8SCy Schubert 
87985732ac8SCy Schubert #if defined(EAP_PWD) || defined(EAP_SERVER_PWD)
88085732ac8SCy Schubert struct crypto_hash {
88185732ac8SCy Schubert 	Hmac hmac;
88285732ac8SCy Schubert 	int size;
88385732ac8SCy Schubert };
88485732ac8SCy Schubert 
88585732ac8SCy Schubert 
88685732ac8SCy Schubert struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
88785732ac8SCy Schubert 				      size_t key_len)
88885732ac8SCy Schubert {
88985732ac8SCy Schubert 	struct crypto_hash *ret = NULL;
89085732ac8SCy Schubert 	struct crypto_hash *hash;
89185732ac8SCy Schubert 	int type;
89285732ac8SCy Schubert 
89385732ac8SCy Schubert 	hash = os_zalloc(sizeof(*hash));
89485732ac8SCy Schubert 	if (!hash)
89585732ac8SCy Schubert 		goto done;
89685732ac8SCy Schubert 
89785732ac8SCy Schubert 	switch (alg) {
89885732ac8SCy Schubert #ifndef NO_MD5
89985732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_MD5:
90085732ac8SCy Schubert 		hash->size = 16;
90185732ac8SCy Schubert 		type = WC_MD5;
90285732ac8SCy Schubert 		break;
90385732ac8SCy Schubert #endif /* NO_MD5 */
90485732ac8SCy Schubert #ifndef NO_SHA
90585732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_SHA1:
90685732ac8SCy Schubert 		type = WC_SHA;
90785732ac8SCy Schubert 		hash->size = 20;
90885732ac8SCy Schubert 		break;
90985732ac8SCy Schubert #endif /* NO_SHA */
91085732ac8SCy Schubert #ifdef CONFIG_SHA256
91185732ac8SCy Schubert #ifndef NO_SHA256
91285732ac8SCy Schubert 	case CRYPTO_HASH_ALG_HMAC_SHA256:
91385732ac8SCy Schubert 		type = WC_SHA256;
91485732ac8SCy Schubert 		hash->size = 32;
91585732ac8SCy Schubert 		break;
91685732ac8SCy Schubert #endif /* NO_SHA256 */
91785732ac8SCy Schubert #endif /* CONFIG_SHA256 */
91885732ac8SCy Schubert 	default:
91985732ac8SCy Schubert 		goto done;
92085732ac8SCy Schubert 	}
92185732ac8SCy Schubert 
92285732ac8SCy Schubert 	if (wc_HmacSetKey(&hash->hmac, type, key, key_len) != 0)
92385732ac8SCy Schubert 		goto done;
92485732ac8SCy Schubert 
92585732ac8SCy Schubert 	ret = hash;
92685732ac8SCy Schubert 	hash = NULL;
92785732ac8SCy Schubert done:
92885732ac8SCy Schubert 	os_free(hash);
92985732ac8SCy Schubert 	return ret;
93085732ac8SCy Schubert }
93185732ac8SCy Schubert 
93285732ac8SCy Schubert 
93385732ac8SCy Schubert void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
93485732ac8SCy Schubert {
93585732ac8SCy Schubert 	if (!ctx)
93685732ac8SCy Schubert 		return;
93785732ac8SCy Schubert 	wc_HmacUpdate(&ctx->hmac, data, len);
93885732ac8SCy Schubert }
93985732ac8SCy Schubert 
94085732ac8SCy Schubert 
94185732ac8SCy Schubert int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
94285732ac8SCy Schubert {
94385732ac8SCy Schubert 	int ret = 0;
94485732ac8SCy Schubert 
94585732ac8SCy Schubert 	if (!ctx)
94685732ac8SCy Schubert 		return -2;
94785732ac8SCy Schubert 
94885732ac8SCy Schubert 	if (!mac || !len)
94985732ac8SCy Schubert 		goto done;
95085732ac8SCy Schubert 
95185732ac8SCy Schubert 	if (wc_HmacFinal(&ctx->hmac, mac) != 0) {
95285732ac8SCy Schubert 		ret = -1;
95385732ac8SCy Schubert 		goto done;
95485732ac8SCy Schubert 	}
95585732ac8SCy Schubert 
95685732ac8SCy Schubert 	*len = ctx->size;
95785732ac8SCy Schubert 	ret = 0;
95885732ac8SCy Schubert done:
95985732ac8SCy Schubert 	bin_clear_free(ctx, sizeof(*ctx));
9604bc52338SCy Schubert 	if (TEST_FAIL())
9614bc52338SCy Schubert 		return -1;
96285732ac8SCy Schubert 	return ret;
96385732ac8SCy Schubert }
96485732ac8SCy Schubert 
96585732ac8SCy Schubert #endif
96685732ac8SCy Schubert 
96785732ac8SCy Schubert 
96885732ac8SCy Schubert int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
96985732ac8SCy Schubert 		     const u8 *addr[], const size_t *len, u8 *mac)
97085732ac8SCy Schubert {
97185732ac8SCy Schubert 	Cmac cmac;
97285732ac8SCy Schubert 	size_t i;
97385732ac8SCy Schubert 	word32 sz;
97485732ac8SCy Schubert 
97585732ac8SCy Schubert 	if (TEST_FAIL())
97685732ac8SCy Schubert 		return -1;
97785732ac8SCy Schubert 
97885732ac8SCy Schubert 	if (wc_InitCmac(&cmac, key, key_len, WC_CMAC_AES, NULL) != 0)
97985732ac8SCy Schubert 		return -1;
98085732ac8SCy Schubert 
98185732ac8SCy Schubert 	for (i = 0; i < num_elem; i++)
98285732ac8SCy Schubert 		if (wc_CmacUpdate(&cmac, addr[i], len[i]) != 0)
98385732ac8SCy Schubert 			return -1;
98485732ac8SCy Schubert 
98585732ac8SCy Schubert 	sz = AES_BLOCK_SIZE;
98685732ac8SCy Schubert 	if (wc_CmacFinal(&cmac, mac, &sz) != 0 || sz != AES_BLOCK_SIZE)
98785732ac8SCy Schubert 		return -1;
98885732ac8SCy Schubert 
98985732ac8SCy Schubert 	return 0;
99085732ac8SCy Schubert }
99185732ac8SCy Schubert 
99285732ac8SCy Schubert 
99385732ac8SCy Schubert int omac1_aes_128_vector(const u8 *key, size_t num_elem,
99485732ac8SCy Schubert 			 const u8 *addr[], const size_t *len, u8 *mac)
99585732ac8SCy Schubert {
99685732ac8SCy Schubert 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
99785732ac8SCy Schubert }
99885732ac8SCy Schubert 
99985732ac8SCy Schubert 
100085732ac8SCy Schubert int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
100185732ac8SCy Schubert {
100285732ac8SCy Schubert 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
100385732ac8SCy Schubert }
100485732ac8SCy Schubert 
100585732ac8SCy Schubert 
100685732ac8SCy Schubert int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
100785732ac8SCy Schubert {
100885732ac8SCy Schubert 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
100985732ac8SCy Schubert }
101085732ac8SCy Schubert 
101185732ac8SCy Schubert 
101285732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init(void)
101385732ac8SCy Schubert {
101485732ac8SCy Schubert 	mp_int *a;
101585732ac8SCy Schubert 
101685732ac8SCy Schubert 	if (TEST_FAIL())
101785732ac8SCy Schubert 		return NULL;
101885732ac8SCy Schubert 
101985732ac8SCy Schubert 	a = os_malloc(sizeof(*a));
102085732ac8SCy Schubert 	if (!a || mp_init(a) != MP_OKAY) {
102185732ac8SCy Schubert 		os_free(a);
102285732ac8SCy Schubert 		a = NULL;
102385732ac8SCy Schubert 	}
102485732ac8SCy Schubert 
102585732ac8SCy Schubert 	return (struct crypto_bignum *) a;
102685732ac8SCy Schubert }
102785732ac8SCy Schubert 
102885732ac8SCy Schubert 
102985732ac8SCy Schubert struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
103085732ac8SCy Schubert {
103185732ac8SCy Schubert 	mp_int *a;
103285732ac8SCy Schubert 
103385732ac8SCy Schubert 	if (TEST_FAIL())
103485732ac8SCy Schubert 		return NULL;
103585732ac8SCy Schubert 
103685732ac8SCy Schubert 	a = (mp_int *) crypto_bignum_init();
103785732ac8SCy Schubert 	if (!a)
103885732ac8SCy Schubert 		return NULL;
103985732ac8SCy Schubert 
104085732ac8SCy Schubert 	if (mp_read_unsigned_bin(a, buf, len) != MP_OKAY) {
104185732ac8SCy Schubert 		os_free(a);
104285732ac8SCy Schubert 		a = NULL;
104385732ac8SCy Schubert 	}
104485732ac8SCy Schubert 
104585732ac8SCy Schubert 	return (struct crypto_bignum *) a;
104685732ac8SCy Schubert }
104785732ac8SCy Schubert 
104885732ac8SCy Schubert 
1049c1d255d3SCy Schubert struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
1050c1d255d3SCy Schubert {
1051c1d255d3SCy Schubert 	mp_int *a;
1052c1d255d3SCy Schubert 
1053c1d255d3SCy Schubert 	if (TEST_FAIL())
1054c1d255d3SCy Schubert 		return NULL;
1055c1d255d3SCy Schubert 
1056c1d255d3SCy Schubert 	a = (mp_int *) crypto_bignum_init();
1057c1d255d3SCy Schubert 	if (!a)
1058c1d255d3SCy Schubert 		return NULL;
1059c1d255d3SCy Schubert 
1060c1d255d3SCy Schubert 	if (mp_set_int(a, val) != MP_OKAY) {
1061c1d255d3SCy Schubert 		os_free(a);
1062c1d255d3SCy Schubert 		a = NULL;
1063c1d255d3SCy Schubert 	}
1064c1d255d3SCy Schubert 
1065c1d255d3SCy Schubert 	return (struct crypto_bignum *) a;
1066c1d255d3SCy Schubert }
1067c1d255d3SCy Schubert 
1068c1d255d3SCy Schubert 
106985732ac8SCy Schubert void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
107085732ac8SCy Schubert {
107185732ac8SCy Schubert 	if (!n)
107285732ac8SCy Schubert 		return;
107385732ac8SCy Schubert 
107485732ac8SCy Schubert 	if (clear)
107585732ac8SCy Schubert 		mp_forcezero((mp_int *) n);
107685732ac8SCy Schubert 	mp_clear((mp_int *) n);
107785732ac8SCy Schubert 	os_free((mp_int *) n);
107885732ac8SCy Schubert }
107985732ac8SCy Schubert 
108085732ac8SCy Schubert 
108185732ac8SCy Schubert int crypto_bignum_to_bin(const struct crypto_bignum *a,
108285732ac8SCy Schubert 			 u8 *buf, size_t buflen, size_t padlen)
108385732ac8SCy Schubert {
108485732ac8SCy Schubert 	int num_bytes, offset;
108585732ac8SCy Schubert 
108685732ac8SCy Schubert 	if (TEST_FAIL())
108785732ac8SCy Schubert 		return -1;
108885732ac8SCy Schubert 
108985732ac8SCy Schubert 	if (padlen > buflen)
109085732ac8SCy Schubert 		return -1;
109185732ac8SCy Schubert 
109285732ac8SCy Schubert 	num_bytes = (mp_count_bits((mp_int *) a) + 7) / 8;
109385732ac8SCy Schubert 	if ((size_t) num_bytes > buflen)
109485732ac8SCy Schubert 		return -1;
109585732ac8SCy Schubert 	if (padlen > (size_t) num_bytes)
109685732ac8SCy Schubert 		offset = padlen - num_bytes;
109785732ac8SCy Schubert 	else
109885732ac8SCy Schubert 		offset = 0;
109985732ac8SCy Schubert 
110085732ac8SCy Schubert 	os_memset(buf, 0, offset);
110185732ac8SCy Schubert 	mp_to_unsigned_bin((mp_int *) a, buf + offset);
110285732ac8SCy Schubert 
110385732ac8SCy Schubert 	return num_bytes + offset;
110485732ac8SCy Schubert }
110585732ac8SCy Schubert 
110685732ac8SCy Schubert 
110785732ac8SCy Schubert int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
110885732ac8SCy Schubert {
110985732ac8SCy Schubert 	int ret = 0;
111085732ac8SCy Schubert 	WC_RNG rng;
1111c1d255d3SCy Schubert 	size_t len;
1112c1d255d3SCy Schubert 	u8 *buf;
111385732ac8SCy Schubert 
11144bc52338SCy Schubert 	if (TEST_FAIL())
11154bc52338SCy Schubert 		return -1;
111685732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
111785732ac8SCy Schubert 		return -1;
1118c1d255d3SCy Schubert 	len = (mp_count_bits((mp_int *) m) + 7) / 8;
1119c1d255d3SCy Schubert 	buf = os_malloc(len);
1120c1d255d3SCy Schubert 	if (!buf || wc_RNG_GenerateBlock(&rng, buf, len) != 0 ||
1121c1d255d3SCy Schubert 	    mp_read_unsigned_bin((mp_int *) r, buf, len) != MP_OKAY ||
112285732ac8SCy Schubert 	    mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0)
112385732ac8SCy Schubert 		ret = -1;
112485732ac8SCy Schubert 	wc_FreeRng(&rng);
1125c1d255d3SCy Schubert 	bin_clear_free(buf, len);
112685732ac8SCy Schubert 	return ret;
112785732ac8SCy Schubert }
112885732ac8SCy Schubert 
112985732ac8SCy Schubert 
113085732ac8SCy Schubert int crypto_bignum_add(const struct crypto_bignum *a,
113185732ac8SCy Schubert 		      const struct crypto_bignum *b,
113285732ac8SCy Schubert 		      struct crypto_bignum *r)
113385732ac8SCy Schubert {
113485732ac8SCy Schubert 	return mp_add((mp_int *) a, (mp_int *) b,
113585732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
113685732ac8SCy Schubert }
113785732ac8SCy Schubert 
113885732ac8SCy Schubert 
113985732ac8SCy Schubert int crypto_bignum_mod(const struct crypto_bignum *a,
114085732ac8SCy Schubert 		      const struct crypto_bignum *m,
114185732ac8SCy Schubert 		      struct crypto_bignum *r)
114285732ac8SCy Schubert {
114385732ac8SCy Schubert 	return mp_mod((mp_int *) a, (mp_int *) m,
114485732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
114585732ac8SCy Schubert }
114685732ac8SCy Schubert 
114785732ac8SCy Schubert 
114885732ac8SCy Schubert int crypto_bignum_exptmod(const struct crypto_bignum *b,
114985732ac8SCy Schubert 			  const struct crypto_bignum *e,
115085732ac8SCy Schubert 			  const struct crypto_bignum *m,
115185732ac8SCy Schubert 			  struct crypto_bignum *r)
115285732ac8SCy Schubert {
115385732ac8SCy Schubert 	if (TEST_FAIL())
115485732ac8SCy Schubert 		return -1;
115585732ac8SCy Schubert 
115685732ac8SCy Schubert 	return mp_exptmod((mp_int *) b, (mp_int *) e, (mp_int *) m,
115785732ac8SCy Schubert 			  (mp_int *) r) == MP_OKAY ?  0 : -1;
115885732ac8SCy Schubert }
115985732ac8SCy Schubert 
116085732ac8SCy Schubert 
116185732ac8SCy Schubert int crypto_bignum_inverse(const struct crypto_bignum *a,
116285732ac8SCy Schubert 			  const struct crypto_bignum *m,
116385732ac8SCy Schubert 			  struct crypto_bignum *r)
116485732ac8SCy Schubert {
116585732ac8SCy Schubert 	if (TEST_FAIL())
116685732ac8SCy Schubert 		return -1;
116785732ac8SCy Schubert 
116885732ac8SCy Schubert 	return mp_invmod((mp_int *) a, (mp_int *) m,
116985732ac8SCy Schubert 			 (mp_int *) r) == MP_OKAY ? 0 : -1;
117085732ac8SCy Schubert }
117185732ac8SCy Schubert 
117285732ac8SCy Schubert 
117385732ac8SCy Schubert int crypto_bignum_sub(const struct crypto_bignum *a,
117485732ac8SCy Schubert 		      const struct crypto_bignum *b,
117585732ac8SCy Schubert 		      struct crypto_bignum *r)
117685732ac8SCy Schubert {
117785732ac8SCy Schubert 	if (TEST_FAIL())
117885732ac8SCy Schubert 		return -1;
117985732ac8SCy Schubert 
1180c1d255d3SCy Schubert 	return mp_sub((mp_int *) a, (mp_int *) b,
118185732ac8SCy Schubert 		      (mp_int *) r) == MP_OKAY ? 0 : -1;
118285732ac8SCy Schubert }
118385732ac8SCy Schubert 
118485732ac8SCy Schubert 
118585732ac8SCy Schubert int crypto_bignum_div(const struct crypto_bignum *a,
118685732ac8SCy Schubert 		      const struct crypto_bignum *b,
118785732ac8SCy Schubert 		      struct crypto_bignum *d)
118885732ac8SCy Schubert {
118985732ac8SCy Schubert 	if (TEST_FAIL())
119085732ac8SCy Schubert 		return -1;
119185732ac8SCy Schubert 
119285732ac8SCy Schubert 	return mp_div((mp_int *) a, (mp_int *) b, (mp_int *) d,
119385732ac8SCy Schubert 		      NULL) == MP_OKAY ? 0 : -1;
119485732ac8SCy Schubert }
119585732ac8SCy Schubert 
119685732ac8SCy Schubert 
1197c1d255d3SCy Schubert int crypto_bignum_addmod(const struct crypto_bignum *a,
1198c1d255d3SCy Schubert 			 const struct crypto_bignum *b,
1199c1d255d3SCy Schubert 			 const struct crypto_bignum *c,
1200c1d255d3SCy Schubert 			 struct crypto_bignum *d)
1201c1d255d3SCy Schubert {
1202c1d255d3SCy Schubert 	if (TEST_FAIL())
1203c1d255d3SCy Schubert 		return -1;
1204c1d255d3SCy Schubert 
1205c1d255d3SCy Schubert 	return mp_addmod((mp_int *) a, (mp_int *) b, (mp_int *) c,
1206c1d255d3SCy Schubert 			 (mp_int *) d) == MP_OKAY ?  0 : -1;
1207c1d255d3SCy Schubert }
1208c1d255d3SCy Schubert 
1209c1d255d3SCy Schubert 
121085732ac8SCy Schubert int crypto_bignum_mulmod(const struct crypto_bignum *a,
121185732ac8SCy Schubert 			 const struct crypto_bignum *b,
121285732ac8SCy Schubert 			 const struct crypto_bignum *m,
121385732ac8SCy Schubert 			 struct crypto_bignum *d)
121485732ac8SCy Schubert {
121585732ac8SCy Schubert 	if (TEST_FAIL())
121685732ac8SCy Schubert 		return -1;
121785732ac8SCy Schubert 
121885732ac8SCy Schubert 	return mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) m,
121985732ac8SCy Schubert 			 (mp_int *) d) == MP_OKAY ?  0 : -1;
122085732ac8SCy Schubert }
122185732ac8SCy Schubert 
122285732ac8SCy Schubert 
1223c1d255d3SCy Schubert int crypto_bignum_sqrmod(const struct crypto_bignum *a,
1224c1d255d3SCy Schubert 			 const struct crypto_bignum *b,
1225c1d255d3SCy Schubert 			 struct crypto_bignum *c)
1226c1d255d3SCy Schubert {
1227c1d255d3SCy Schubert 	if (TEST_FAIL())
1228c1d255d3SCy Schubert 		return -1;
1229c1d255d3SCy Schubert 
1230c1d255d3SCy Schubert 	return mp_sqrmod((mp_int *) a, (mp_int *) b,
1231c1d255d3SCy Schubert 			 (mp_int *) c) == MP_OKAY ?  0 : -1;
1232c1d255d3SCy Schubert }
1233c1d255d3SCy Schubert 
1234c1d255d3SCy Schubert 
123585732ac8SCy Schubert int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
123685732ac8SCy Schubert 			 struct crypto_bignum *r)
123785732ac8SCy Schubert {
123885732ac8SCy Schubert 	if (mp_copy((mp_int *) a, (mp_int *) r) != MP_OKAY)
123985732ac8SCy Schubert 		return -1;
124085732ac8SCy Schubert 	mp_rshb((mp_int *) r, n);
124185732ac8SCy Schubert 	return 0;
124285732ac8SCy Schubert }
124385732ac8SCy Schubert 
124485732ac8SCy Schubert 
124585732ac8SCy Schubert int crypto_bignum_cmp(const struct crypto_bignum *a,
124685732ac8SCy Schubert 		      const struct crypto_bignum *b)
124785732ac8SCy Schubert {
124885732ac8SCy Schubert 	return mp_cmp((mp_int *) a, (mp_int *) b);
124985732ac8SCy Schubert }
125085732ac8SCy Schubert 
125185732ac8SCy Schubert 
125285732ac8SCy Schubert int crypto_bignum_is_zero(const struct crypto_bignum *a)
125385732ac8SCy Schubert {
125485732ac8SCy Schubert 	return mp_iszero((mp_int *) a);
125585732ac8SCy Schubert }
125685732ac8SCy Schubert 
125785732ac8SCy Schubert 
125885732ac8SCy Schubert int crypto_bignum_is_one(const struct crypto_bignum *a)
125985732ac8SCy Schubert {
126085732ac8SCy Schubert 	return mp_isone((const mp_int *) a);
126185732ac8SCy Schubert }
126285732ac8SCy Schubert 
126385732ac8SCy Schubert int crypto_bignum_is_odd(const struct crypto_bignum *a)
126485732ac8SCy Schubert {
126585732ac8SCy Schubert 	return mp_isodd((mp_int *) a);
126685732ac8SCy Schubert }
126785732ac8SCy Schubert 
126885732ac8SCy Schubert 
126985732ac8SCy Schubert int crypto_bignum_legendre(const struct crypto_bignum *a,
127085732ac8SCy Schubert 			   const struct crypto_bignum *p)
127185732ac8SCy Schubert {
127285732ac8SCy Schubert 	mp_int t;
127385732ac8SCy Schubert 	int ret;
127485732ac8SCy Schubert 	int res = -2;
127585732ac8SCy Schubert 
127685732ac8SCy Schubert 	if (TEST_FAIL())
127785732ac8SCy Schubert 		return -2;
127885732ac8SCy Schubert 
127985732ac8SCy Schubert 	if (mp_init(&t) != MP_OKAY)
128085732ac8SCy Schubert 		return -2;
128185732ac8SCy Schubert 
128285732ac8SCy Schubert 	/* t = (p-1) / 2 */
128385732ac8SCy Schubert 	ret = mp_sub_d((mp_int *) p, 1, &t);
128485732ac8SCy Schubert 	if (ret == MP_OKAY)
128585732ac8SCy Schubert 		mp_rshb(&t, 1);
128685732ac8SCy Schubert 	if (ret == MP_OKAY)
128785732ac8SCy Schubert 		ret = mp_exptmod((mp_int *) a, &t, (mp_int *) p, &t);
128885732ac8SCy Schubert 	if (ret == MP_OKAY) {
128985732ac8SCy Schubert 		if (mp_isone(&t))
129085732ac8SCy Schubert 			res = 1;
129185732ac8SCy Schubert 		else if (mp_iszero(&t))
129285732ac8SCy Schubert 			res = 0;
129385732ac8SCy Schubert 		else
129485732ac8SCy Schubert 			res = -1;
129585732ac8SCy Schubert 	}
129685732ac8SCy Schubert 
129785732ac8SCy Schubert 	mp_clear(&t);
129885732ac8SCy Schubert 	return res;
129985732ac8SCy Schubert }
130085732ac8SCy Schubert 
130185732ac8SCy Schubert 
130285732ac8SCy Schubert #ifdef CONFIG_ECC
130385732ac8SCy Schubert 
130485732ac8SCy Schubert int ecc_map(ecc_point *, mp_int *, mp_digit);
130585732ac8SCy Schubert int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
130685732ac8SCy Schubert 			     mp_int *a, mp_int *modulus, mp_digit mp);
130785732ac8SCy Schubert 
130885732ac8SCy Schubert struct crypto_ec {
130985732ac8SCy Schubert 	ecc_key key;
131085732ac8SCy Schubert 	mp_int a;
131185732ac8SCy Schubert 	mp_int prime;
131285732ac8SCy Schubert 	mp_int order;
131385732ac8SCy Schubert 	mp_digit mont_b;
131485732ac8SCy Schubert 	mp_int b;
131585732ac8SCy Schubert };
131685732ac8SCy Schubert 
131785732ac8SCy Schubert 
131885732ac8SCy Schubert struct crypto_ec * crypto_ec_init(int group)
131985732ac8SCy Schubert {
132085732ac8SCy Schubert 	int built = 0;
132185732ac8SCy Schubert 	struct crypto_ec *e;
132285732ac8SCy Schubert 	int curve_id;
132385732ac8SCy Schubert 
132485732ac8SCy Schubert 	/* Map from IANA registry for IKE D-H groups to OpenSSL NID */
132585732ac8SCy Schubert 	switch (group) {
132685732ac8SCy Schubert 	case 19:
132785732ac8SCy Schubert 		curve_id = ECC_SECP256R1;
132885732ac8SCy Schubert 		break;
132985732ac8SCy Schubert 	case 20:
133085732ac8SCy Schubert 		curve_id = ECC_SECP384R1;
133185732ac8SCy Schubert 		break;
133285732ac8SCy Schubert 	case 21:
133385732ac8SCy Schubert 		curve_id = ECC_SECP521R1;
133485732ac8SCy Schubert 		break;
133585732ac8SCy Schubert 	case 25:
133685732ac8SCy Schubert 		curve_id = ECC_SECP192R1;
133785732ac8SCy Schubert 		break;
133885732ac8SCy Schubert 	case 26:
133985732ac8SCy Schubert 		curve_id = ECC_SECP224R1;
134085732ac8SCy Schubert 		break;
134185732ac8SCy Schubert #ifdef HAVE_ECC_BRAINPOOL
134285732ac8SCy Schubert 	case 27:
134385732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP224R1;
134485732ac8SCy Schubert 		break;
134585732ac8SCy Schubert 	case 28:
134685732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP256R1;
134785732ac8SCy Schubert 		break;
134885732ac8SCy Schubert 	case 29:
134985732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP384R1;
135085732ac8SCy Schubert 		break;
135185732ac8SCy Schubert 	case 30:
135285732ac8SCy Schubert 		curve_id = ECC_BRAINPOOLP512R1;
135385732ac8SCy Schubert 		break;
135485732ac8SCy Schubert #endif /* HAVE_ECC_BRAINPOOL */
135585732ac8SCy Schubert 	default:
135685732ac8SCy Schubert 		return NULL;
135785732ac8SCy Schubert 	}
135885732ac8SCy Schubert 
135985732ac8SCy Schubert 	e = os_zalloc(sizeof(*e));
136085732ac8SCy Schubert 	if (!e)
136185732ac8SCy Schubert 		return NULL;
136285732ac8SCy Schubert 
136385732ac8SCy Schubert 	if (wc_ecc_init(&e->key) != 0 ||
136485732ac8SCy Schubert 	    wc_ecc_set_curve(&e->key, 0, curve_id) != 0 ||
136585732ac8SCy Schubert 	    mp_init(&e->a) != MP_OKAY ||
136685732ac8SCy Schubert 	    mp_init(&e->prime) != MP_OKAY ||
136785732ac8SCy Schubert 	    mp_init(&e->order) != MP_OKAY ||
136885732ac8SCy Schubert 	    mp_init(&e->b) != MP_OKAY ||
136985732ac8SCy Schubert 	    mp_read_radix(&e->a, e->key.dp->Af, 16) != MP_OKAY ||
137085732ac8SCy Schubert 	    mp_read_radix(&e->b, e->key.dp->Bf, 16) != MP_OKAY ||
137185732ac8SCy Schubert 	    mp_read_radix(&e->prime, e->key.dp->prime, 16) != MP_OKAY ||
137285732ac8SCy Schubert 	    mp_read_radix(&e->order, e->key.dp->order, 16) != MP_OKAY ||
137385732ac8SCy Schubert 	    mp_montgomery_setup(&e->prime, &e->mont_b) != MP_OKAY)
137485732ac8SCy Schubert 		goto done;
137585732ac8SCy Schubert 
137685732ac8SCy Schubert 	built = 1;
137785732ac8SCy Schubert done:
137885732ac8SCy Schubert 	if (!built) {
137985732ac8SCy Schubert 		crypto_ec_deinit(e);
138085732ac8SCy Schubert 		e = NULL;
138185732ac8SCy Schubert 	}
138285732ac8SCy Schubert 	return e;
138385732ac8SCy Schubert }
138485732ac8SCy Schubert 
138585732ac8SCy Schubert 
138685732ac8SCy Schubert void crypto_ec_deinit(struct crypto_ec* e)
138785732ac8SCy Schubert {
138885732ac8SCy Schubert 	if (!e)
138985732ac8SCy Schubert 		return;
139085732ac8SCy Schubert 
139185732ac8SCy Schubert 	mp_clear(&e->b);
139285732ac8SCy Schubert 	mp_clear(&e->order);
139385732ac8SCy Schubert 	mp_clear(&e->prime);
139485732ac8SCy Schubert 	mp_clear(&e->a);
139585732ac8SCy Schubert 	wc_ecc_free(&e->key);
139685732ac8SCy Schubert 	os_free(e);
139785732ac8SCy Schubert }
139885732ac8SCy Schubert 
139985732ac8SCy Schubert 
140085732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
140185732ac8SCy Schubert {
140285732ac8SCy Schubert 	if (TEST_FAIL())
140385732ac8SCy Schubert 		return NULL;
140485732ac8SCy Schubert 	if (!e)
140585732ac8SCy Schubert 		return NULL;
140685732ac8SCy Schubert 	return (struct crypto_ec_point *) wc_ecc_new_point();
140785732ac8SCy Schubert }
140885732ac8SCy Schubert 
140985732ac8SCy Schubert 
141085732ac8SCy Schubert size_t crypto_ec_prime_len(struct crypto_ec *e)
141185732ac8SCy Schubert {
141285732ac8SCy Schubert 	return (mp_count_bits(&e->prime) + 7) / 8;
141385732ac8SCy Schubert }
141485732ac8SCy Schubert 
141585732ac8SCy Schubert 
141685732ac8SCy Schubert size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
141785732ac8SCy Schubert {
141885732ac8SCy Schubert 	return mp_count_bits(&e->prime);
141985732ac8SCy Schubert }
142085732ac8SCy Schubert 
142185732ac8SCy Schubert 
142285732ac8SCy Schubert size_t crypto_ec_order_len(struct crypto_ec *e)
142385732ac8SCy Schubert {
142485732ac8SCy Schubert 	return (mp_count_bits(&e->order) + 7) / 8;
142585732ac8SCy Schubert }
142685732ac8SCy Schubert 
142785732ac8SCy Schubert 
142885732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
142985732ac8SCy Schubert {
143085732ac8SCy Schubert 	return (const struct crypto_bignum *) &e->prime;
143185732ac8SCy Schubert }
143285732ac8SCy Schubert 
143385732ac8SCy Schubert 
143485732ac8SCy Schubert const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
143585732ac8SCy Schubert {
143685732ac8SCy Schubert 	return (const struct crypto_bignum *) &e->order;
143785732ac8SCy Schubert }
143885732ac8SCy Schubert 
143985732ac8SCy Schubert 
1440c1d255d3SCy Schubert const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e)
1441c1d255d3SCy Schubert {
1442c1d255d3SCy Schubert 	return (const struct crypto_bignum *) &e->a;
1443c1d255d3SCy Schubert }
1444c1d255d3SCy Schubert 
1445c1d255d3SCy Schubert 
1446c1d255d3SCy Schubert const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
1447c1d255d3SCy Schubert {
1448c1d255d3SCy Schubert 	return (const struct crypto_bignum *) &e->b;
1449c1d255d3SCy Schubert }
1450c1d255d3SCy Schubert 
1451c1d255d3SCy Schubert 
145285732ac8SCy Schubert void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
145385732ac8SCy Schubert {
145485732ac8SCy Schubert 	ecc_point *point = (ecc_point *) p;
145585732ac8SCy Schubert 
145685732ac8SCy Schubert 	if (!p)
145785732ac8SCy Schubert 		return;
145885732ac8SCy Schubert 
145985732ac8SCy Schubert 	if (clear) {
146085732ac8SCy Schubert 		mp_forcezero(point->x);
146185732ac8SCy Schubert 		mp_forcezero(point->y);
146285732ac8SCy Schubert 		mp_forcezero(point->z);
146385732ac8SCy Schubert 	}
146485732ac8SCy Schubert 	wc_ecc_del_point(point);
146585732ac8SCy Schubert }
146685732ac8SCy Schubert 
146785732ac8SCy Schubert 
146885732ac8SCy Schubert int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
146985732ac8SCy Schubert 		      struct crypto_bignum *x)
147085732ac8SCy Schubert {
147185732ac8SCy Schubert 	return mp_copy(((ecc_point *) p)->x, (mp_int *) x) == MP_OKAY ? 0 : -1;
147285732ac8SCy Schubert }
147385732ac8SCy Schubert 
147485732ac8SCy Schubert 
147585732ac8SCy Schubert int crypto_ec_point_to_bin(struct crypto_ec *e,
147685732ac8SCy Schubert 			   const struct crypto_ec_point *point, u8 *x, u8 *y)
147785732ac8SCy Schubert {
147885732ac8SCy Schubert 	ecc_point *p = (ecc_point *) point;
147985732ac8SCy Schubert 
148085732ac8SCy Schubert 	if (TEST_FAIL())
148185732ac8SCy Schubert 		return -1;
148285732ac8SCy Schubert 
148385732ac8SCy Schubert 	if (!mp_isone(p->z)) {
148485732ac8SCy Schubert 		if (ecc_map(p, &e->prime, e->mont_b) != MP_OKAY)
148585732ac8SCy Schubert 			return -1;
148685732ac8SCy Schubert 	}
148785732ac8SCy Schubert 
148885732ac8SCy Schubert 	if (x) {
148985732ac8SCy Schubert 		if (crypto_bignum_to_bin((struct crypto_bignum *)p->x, x,
149085732ac8SCy Schubert 					 e->key.dp->size,
149185732ac8SCy Schubert 					 e->key.dp->size) <= 0)
149285732ac8SCy Schubert 			return -1;
149385732ac8SCy Schubert 	}
149485732ac8SCy Schubert 
149585732ac8SCy Schubert 	if (y) {
149685732ac8SCy Schubert 		if (crypto_bignum_to_bin((struct crypto_bignum *) p->y, y,
149785732ac8SCy Schubert 					 e->key.dp->size,
149885732ac8SCy Schubert 					 e->key.dp->size) <= 0)
149985732ac8SCy Schubert 			return -1;
150085732ac8SCy Schubert 	}
150185732ac8SCy Schubert 
150285732ac8SCy Schubert 	return 0;
150385732ac8SCy Schubert }
150485732ac8SCy Schubert 
150585732ac8SCy Schubert 
150685732ac8SCy Schubert struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
150785732ac8SCy Schubert 						  const u8 *val)
150885732ac8SCy Schubert {
150985732ac8SCy Schubert 	ecc_point *point = NULL;
151085732ac8SCy Schubert 	int loaded = 0;
151185732ac8SCy Schubert 
151285732ac8SCy Schubert 	if (TEST_FAIL())
151385732ac8SCy Schubert 		return NULL;
151485732ac8SCy Schubert 
151585732ac8SCy Schubert 	point = wc_ecc_new_point();
151685732ac8SCy Schubert 	if (!point)
151785732ac8SCy Schubert 		goto done;
151885732ac8SCy Schubert 
151985732ac8SCy Schubert 	if (mp_read_unsigned_bin(point->x, val, e->key.dp->size) != MP_OKAY)
152085732ac8SCy Schubert 		goto done;
152185732ac8SCy Schubert 	val += e->key.dp->size;
152285732ac8SCy Schubert 	if (mp_read_unsigned_bin(point->y, val, e->key.dp->size) != MP_OKAY)
152385732ac8SCy Schubert 		goto done;
152485732ac8SCy Schubert 	mp_set(point->z, 1);
152585732ac8SCy Schubert 
152685732ac8SCy Schubert 	loaded = 1;
152785732ac8SCy Schubert done:
152885732ac8SCy Schubert 	if (!loaded) {
152985732ac8SCy Schubert 		wc_ecc_del_point(point);
153085732ac8SCy Schubert 		point = NULL;
153185732ac8SCy Schubert 	}
153285732ac8SCy Schubert 	return (struct crypto_ec_point *) point;
153385732ac8SCy Schubert }
153485732ac8SCy Schubert 
153585732ac8SCy Schubert 
153685732ac8SCy Schubert int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
153785732ac8SCy Schubert 			const struct crypto_ec_point *b,
153885732ac8SCy Schubert 			struct crypto_ec_point *c)
153985732ac8SCy Schubert {
154085732ac8SCy Schubert 	mp_int mu;
154185732ac8SCy Schubert 	ecc_point *ta = NULL, *tb = NULL;
154285732ac8SCy Schubert 	ecc_point *pa = (ecc_point *) a, *pb = (ecc_point *) b;
154385732ac8SCy Schubert 	mp_int *modulus = &e->prime;
154485732ac8SCy Schubert 	int ret;
154585732ac8SCy Schubert 
154685732ac8SCy Schubert 	if (TEST_FAIL())
154785732ac8SCy Schubert 		return -1;
154885732ac8SCy Schubert 
154985732ac8SCy Schubert 	ret = mp_init(&mu);
155085732ac8SCy Schubert 	if (ret != MP_OKAY)
155185732ac8SCy Schubert 		return -1;
155285732ac8SCy Schubert 
155385732ac8SCy Schubert 	ret = mp_montgomery_calc_normalization(&mu, modulus);
155485732ac8SCy Schubert 	if (ret != MP_OKAY) {
155585732ac8SCy Schubert 		mp_clear(&mu);
155685732ac8SCy Schubert 		return -1;
155785732ac8SCy Schubert 	}
155885732ac8SCy Schubert 
155985732ac8SCy Schubert 	if (!mp_isone(&mu)) {
156085732ac8SCy Schubert 		ta = wc_ecc_new_point();
156185732ac8SCy Schubert 		if (!ta) {
156285732ac8SCy Schubert 			mp_clear(&mu);
156385732ac8SCy Schubert 			return -1;
156485732ac8SCy Schubert 		}
156585732ac8SCy Schubert 		tb = wc_ecc_new_point();
156685732ac8SCy Schubert 		if (!tb) {
156785732ac8SCy Schubert 			wc_ecc_del_point(ta);
156885732ac8SCy Schubert 			mp_clear(&mu);
156985732ac8SCy Schubert 			return -1;
157085732ac8SCy Schubert 		}
157185732ac8SCy Schubert 
157285732ac8SCy Schubert 		if (mp_mulmod(pa->x, &mu, modulus, ta->x) != MP_OKAY ||
157385732ac8SCy Schubert 		    mp_mulmod(pa->y, &mu, modulus, ta->y) != MP_OKAY ||
157485732ac8SCy Schubert 		    mp_mulmod(pa->z, &mu, modulus, ta->z) != MP_OKAY ||
157585732ac8SCy Schubert 		    mp_mulmod(pb->x, &mu, modulus, tb->x) != MP_OKAY ||
157685732ac8SCy Schubert 		    mp_mulmod(pb->y, &mu, modulus, tb->y) != MP_OKAY ||
157785732ac8SCy Schubert 		    mp_mulmod(pb->z, &mu, modulus, tb->z) != MP_OKAY) {
157885732ac8SCy Schubert 			ret = -1;
157985732ac8SCy Schubert 			goto end;
158085732ac8SCy Schubert 		}
158185732ac8SCy Schubert 		pa = ta;
158285732ac8SCy Schubert 		pb = tb;
158385732ac8SCy Schubert 	}
158485732ac8SCy Schubert 
158585732ac8SCy Schubert 	ret = ecc_projective_add_point(pa, pb, (ecc_point *) c, &e->a,
158685732ac8SCy Schubert 				       &e->prime, e->mont_b);
158785732ac8SCy Schubert 	if (ret != 0) {
158885732ac8SCy Schubert 		ret = -1;
158985732ac8SCy Schubert 		goto end;
159085732ac8SCy Schubert 	}
159185732ac8SCy Schubert 
159285732ac8SCy Schubert 	if (ecc_map((ecc_point *) c, &e->prime, e->mont_b) != MP_OKAY)
159385732ac8SCy Schubert 		ret = -1;
159485732ac8SCy Schubert 	else
159585732ac8SCy Schubert 		ret = 0;
159685732ac8SCy Schubert end:
159785732ac8SCy Schubert 	wc_ecc_del_point(tb);
159885732ac8SCy Schubert 	wc_ecc_del_point(ta);
159985732ac8SCy Schubert 	mp_clear(&mu);
160085732ac8SCy Schubert 	return ret;
160185732ac8SCy Schubert }
160285732ac8SCy Schubert 
160385732ac8SCy Schubert 
160485732ac8SCy Schubert int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
160585732ac8SCy Schubert 			const struct crypto_bignum *b,
160685732ac8SCy Schubert 			struct crypto_ec_point *res)
160785732ac8SCy Schubert {
160885732ac8SCy Schubert 	int ret;
160985732ac8SCy Schubert 
161085732ac8SCy Schubert 	if (TEST_FAIL())
161185732ac8SCy Schubert 		return -1;
161285732ac8SCy Schubert 
161385732ac8SCy Schubert 	ret = wc_ecc_mulmod((mp_int *) b, (ecc_point *) p, (ecc_point *) res,
161485732ac8SCy Schubert 			    &e->a, &e->prime, 1);
161585732ac8SCy Schubert 	return ret == 0 ? 0 : -1;
161685732ac8SCy Schubert }
161785732ac8SCy Schubert 
161885732ac8SCy Schubert 
161985732ac8SCy Schubert int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
162085732ac8SCy Schubert {
162185732ac8SCy Schubert 	ecc_point *point = (ecc_point *) p;
162285732ac8SCy Schubert 
162385732ac8SCy Schubert 	if (TEST_FAIL())
162485732ac8SCy Schubert 		return -1;
162585732ac8SCy Schubert 
162685732ac8SCy Schubert 	if (mp_sub(&e->prime, point->y, point->y) != MP_OKAY)
162785732ac8SCy Schubert 		return -1;
162885732ac8SCy Schubert 
162985732ac8SCy Schubert 	return 0;
163085732ac8SCy Schubert }
163185732ac8SCy Schubert 
163285732ac8SCy Schubert 
163385732ac8SCy Schubert int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
163485732ac8SCy Schubert 				  struct crypto_ec_point *p,
163585732ac8SCy Schubert 				  const struct crypto_bignum *x, int y_bit)
163685732ac8SCy Schubert {
163785732ac8SCy Schubert 	byte buf[1 + 2 * MAX_ECC_BYTES];
163885732ac8SCy Schubert 	int ret;
163985732ac8SCy Schubert 	int prime_len = crypto_ec_prime_len(e);
164085732ac8SCy Schubert 
164185732ac8SCy Schubert 	if (TEST_FAIL())
164285732ac8SCy Schubert 		return -1;
164385732ac8SCy Schubert 
164485732ac8SCy Schubert 	buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
164585732ac8SCy Schubert 	ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len);
164685732ac8SCy Schubert 	if (ret <= 0)
164785732ac8SCy Schubert 		return -1;
164885732ac8SCy Schubert 	ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx,
164985732ac8SCy Schubert 				      (ecc_point *) p);
165085732ac8SCy Schubert 	if (ret != 0)
165185732ac8SCy Schubert 		return -1;
165285732ac8SCy Schubert 
165385732ac8SCy Schubert 	return 0;
165485732ac8SCy Schubert }
165585732ac8SCy Schubert 
165685732ac8SCy Schubert 
165785732ac8SCy Schubert struct crypto_bignum *
165885732ac8SCy Schubert crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
165985732ac8SCy Schubert 			      const struct crypto_bignum *x)
166085732ac8SCy Schubert {
166185732ac8SCy Schubert 	mp_int *y2 = NULL;
166285732ac8SCy Schubert 	mp_int t;
166385732ac8SCy Schubert 	int calced = 0;
166485732ac8SCy Schubert 
166585732ac8SCy Schubert 	if (TEST_FAIL())
166685732ac8SCy Schubert 		return NULL;
166785732ac8SCy Schubert 
166885732ac8SCy Schubert 	if (mp_init(&t) != MP_OKAY)
166985732ac8SCy Schubert 		return NULL;
167085732ac8SCy Schubert 
167185732ac8SCy Schubert 	y2 = (mp_int *) crypto_bignum_init();
167285732ac8SCy Schubert 	if (!y2)
167385732ac8SCy Schubert 		goto done;
167485732ac8SCy Schubert 
167585732ac8SCy Schubert 	if (mp_sqrmod((mp_int *) x, &e->prime, y2) != 0 ||
167685732ac8SCy Schubert 	    mp_mulmod((mp_int *) x, y2, &e->prime, y2) != 0 ||
167785732ac8SCy Schubert 	    mp_mulmod((mp_int *) x, &e->a, &e->prime, &t) != 0 ||
167885732ac8SCy Schubert 	    mp_addmod(y2, &t, &e->prime, y2) != 0 ||
167985732ac8SCy Schubert 	    mp_addmod(y2, &e->b, &e->prime, y2) != 0)
168085732ac8SCy Schubert 		goto done;
168185732ac8SCy Schubert 
168285732ac8SCy Schubert 	calced = 1;
168385732ac8SCy Schubert done:
168485732ac8SCy Schubert 	if (!calced) {
168585732ac8SCy Schubert 		if (y2) {
168685732ac8SCy Schubert 			mp_clear(y2);
168785732ac8SCy Schubert 			os_free(y2);
168885732ac8SCy Schubert 		}
168985732ac8SCy Schubert 		mp_clear(&t);
169085732ac8SCy Schubert 	}
169185732ac8SCy Schubert 
169285732ac8SCy Schubert 	return (struct crypto_bignum *) y2;
169385732ac8SCy Schubert }
169485732ac8SCy Schubert 
169585732ac8SCy Schubert 
169685732ac8SCy Schubert int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
169785732ac8SCy Schubert 				   const struct crypto_ec_point *p)
169885732ac8SCy Schubert {
169985732ac8SCy Schubert 	return wc_ecc_point_is_at_infinity((ecc_point *) p);
170085732ac8SCy Schubert }
170185732ac8SCy Schubert 
170285732ac8SCy Schubert 
170385732ac8SCy Schubert int crypto_ec_point_is_on_curve(struct crypto_ec *e,
170485732ac8SCy Schubert 				const struct crypto_ec_point *p)
170585732ac8SCy Schubert {
170685732ac8SCy Schubert 	return wc_ecc_is_point((ecc_point *) p, &e->a, &e->b, &e->prime) ==
170785732ac8SCy Schubert 		MP_OKAY;
170885732ac8SCy Schubert }
170985732ac8SCy Schubert 
171085732ac8SCy Schubert 
171185732ac8SCy Schubert int crypto_ec_point_cmp(const struct crypto_ec *e,
171285732ac8SCy Schubert 			const struct crypto_ec_point *a,
171385732ac8SCy Schubert 			const struct crypto_ec_point *b)
171485732ac8SCy Schubert {
171585732ac8SCy Schubert 	return wc_ecc_cmp_point((ecc_point *) a, (ecc_point *) b);
171685732ac8SCy Schubert }
171785732ac8SCy Schubert 
171885732ac8SCy Schubert 
171985732ac8SCy Schubert struct crypto_ecdh {
172085732ac8SCy Schubert 	struct crypto_ec *ec;
172185732ac8SCy Schubert };
172285732ac8SCy Schubert 
172385732ac8SCy Schubert struct crypto_ecdh * crypto_ecdh_init(int group)
172485732ac8SCy Schubert {
172585732ac8SCy Schubert 	struct crypto_ecdh *ecdh = NULL;
172685732ac8SCy Schubert 	WC_RNG rng;
172785732ac8SCy Schubert 	int ret;
172885732ac8SCy Schubert 
172985732ac8SCy Schubert 	if (wc_InitRng(&rng) != 0)
173085732ac8SCy Schubert 		goto fail;
173185732ac8SCy Schubert 
173285732ac8SCy Schubert 	ecdh = os_zalloc(sizeof(*ecdh));
173385732ac8SCy Schubert 	if (!ecdh)
173485732ac8SCy Schubert 		goto fail;
173585732ac8SCy Schubert 
173685732ac8SCy Schubert 	ecdh->ec = crypto_ec_init(group);
173785732ac8SCy Schubert 	if (!ecdh->ec)
173885732ac8SCy Schubert 		goto fail;
173985732ac8SCy Schubert 
174085732ac8SCy Schubert 	ret = wc_ecc_make_key_ex(&rng, ecdh->ec->key.dp->size, &ecdh->ec->key,
174185732ac8SCy Schubert 				 ecdh->ec->key.dp->id);
174285732ac8SCy Schubert 	if (ret < 0)
174385732ac8SCy Schubert 		goto fail;
174485732ac8SCy Schubert 
174585732ac8SCy Schubert done:
174685732ac8SCy Schubert 	wc_FreeRng(&rng);
174785732ac8SCy Schubert 
174885732ac8SCy Schubert 	return ecdh;
174985732ac8SCy Schubert fail:
175085732ac8SCy Schubert 	crypto_ecdh_deinit(ecdh);
175185732ac8SCy Schubert 	ecdh = NULL;
175285732ac8SCy Schubert 	goto done;
175385732ac8SCy Schubert }
175485732ac8SCy Schubert 
175585732ac8SCy Schubert 
175685732ac8SCy Schubert void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
175785732ac8SCy Schubert {
175885732ac8SCy Schubert 	if (ecdh) {
175985732ac8SCy Schubert 		crypto_ec_deinit(ecdh->ec);
176085732ac8SCy Schubert 		os_free(ecdh);
176185732ac8SCy Schubert 	}
176285732ac8SCy Schubert }
176385732ac8SCy Schubert 
176485732ac8SCy Schubert 
176585732ac8SCy Schubert struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
176685732ac8SCy Schubert {
176785732ac8SCy Schubert 	struct wpabuf *buf = NULL;
176885732ac8SCy Schubert 	int ret;
176985732ac8SCy Schubert 	int len = ecdh->ec->key.dp->size;
177085732ac8SCy Schubert 
177185732ac8SCy Schubert 	buf = wpabuf_alloc(inc_y ? 2 * len : len);
177285732ac8SCy Schubert 	if (!buf)
177385732ac8SCy Schubert 		goto fail;
177485732ac8SCy Schubert 
177585732ac8SCy Schubert 	ret = crypto_bignum_to_bin((struct crypto_bignum *)
177685732ac8SCy Schubert 				   ecdh->ec->key.pubkey.x, wpabuf_put(buf, len),
177785732ac8SCy Schubert 				   len, len);
177885732ac8SCy Schubert 	if (ret < 0)
177985732ac8SCy Schubert 		goto fail;
178085732ac8SCy Schubert 	if (inc_y) {
178185732ac8SCy Schubert 		ret = crypto_bignum_to_bin((struct crypto_bignum *)
178285732ac8SCy Schubert 					   ecdh->ec->key.pubkey.y,
178385732ac8SCy Schubert 					   wpabuf_put(buf, len), len, len);
178485732ac8SCy Schubert 		if (ret < 0)
178585732ac8SCy Schubert 			goto fail;
178685732ac8SCy Schubert 	}
178785732ac8SCy Schubert 
178885732ac8SCy Schubert done:
178985732ac8SCy Schubert 	return buf;
179085732ac8SCy Schubert fail:
179185732ac8SCy Schubert 	wpabuf_free(buf);
179285732ac8SCy Schubert 	buf = NULL;
179385732ac8SCy Schubert 	goto done;
179485732ac8SCy Schubert }
179585732ac8SCy Schubert 
179685732ac8SCy Schubert 
179785732ac8SCy Schubert struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
179885732ac8SCy Schubert 					const u8 *key, size_t len)
179985732ac8SCy Schubert {
180085732ac8SCy Schubert 	int ret;
180185732ac8SCy Schubert 	struct wpabuf *pubkey = NULL;
180285732ac8SCy Schubert 	struct wpabuf *secret = NULL;
180385732ac8SCy Schubert 	word32 key_len = ecdh->ec->key.dp->size;
180485732ac8SCy Schubert 	ecc_point *point = NULL;
180585732ac8SCy Schubert 	size_t need_key_len = inc_y ? 2 * key_len : key_len;
180685732ac8SCy Schubert 
180785732ac8SCy Schubert 	if (len < need_key_len)
180885732ac8SCy Schubert 		goto fail;
180985732ac8SCy Schubert 	pubkey = wpabuf_alloc(1 + 2 * key_len);
181085732ac8SCy Schubert 	if (!pubkey)
181185732ac8SCy Schubert 		goto fail;
181285732ac8SCy Schubert 	wpabuf_put_u8(pubkey, inc_y ? ECC_POINT_UNCOMP : ECC_POINT_COMP_EVEN);
181385732ac8SCy Schubert 	wpabuf_put_data(pubkey, key, need_key_len);
181485732ac8SCy Schubert 
181585732ac8SCy Schubert 	point = wc_ecc_new_point();
181685732ac8SCy Schubert 	if (!point)
181785732ac8SCy Schubert 		goto fail;
181885732ac8SCy Schubert 
181985732ac8SCy Schubert 	ret = wc_ecc_import_point_der(wpabuf_mhead(pubkey), 1 + 2 * key_len,
182085732ac8SCy Schubert 				      ecdh->ec->key.idx, point);
182185732ac8SCy Schubert 	if (ret != MP_OKAY)
182285732ac8SCy Schubert 		goto fail;
182385732ac8SCy Schubert 
182485732ac8SCy Schubert 	secret = wpabuf_alloc(key_len);
182585732ac8SCy Schubert 	if (!secret)
182685732ac8SCy Schubert 		goto fail;
182785732ac8SCy Schubert 
182885732ac8SCy Schubert 	ret = wc_ecc_shared_secret_ex(&ecdh->ec->key, point,
182985732ac8SCy Schubert 				      wpabuf_put(secret, key_len), &key_len);
183085732ac8SCy Schubert 	if (ret != MP_OKAY)
183185732ac8SCy Schubert 		goto fail;
183285732ac8SCy Schubert 
183385732ac8SCy Schubert done:
183485732ac8SCy Schubert 	wc_ecc_del_point(point);
183585732ac8SCy Schubert 	wpabuf_free(pubkey);
183685732ac8SCy Schubert 	return secret;
183785732ac8SCy Schubert fail:
183885732ac8SCy Schubert 	wpabuf_free(secret);
183985732ac8SCy Schubert 	secret = NULL;
184085732ac8SCy Schubert 	goto done;
184185732ac8SCy Schubert }
184285732ac8SCy Schubert 
1843c1d255d3SCy Schubert 
1844c1d255d3SCy Schubert size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
1845c1d255d3SCy Schubert {
1846c1d255d3SCy Schubert 	return crypto_ec_prime_len(ecdh->ec);
1847c1d255d3SCy Schubert }
1848c1d255d3SCy Schubert 
184985732ac8SCy Schubert #endif /* CONFIG_ECC */
1850