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