xref: /freebsd/contrib/wpa/src/crypto/crypto_libtomcrypt.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
339beb93cSSam Leffler  * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler #include <tomcrypt.h>
1139beb93cSSam Leffler 
1239beb93cSSam Leffler #include "common.h"
1339beb93cSSam Leffler #include "crypto.h"
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #ifndef mp_init_multi
1639beb93cSSam Leffler #define mp_init_multi                ltc_init_multi
1739beb93cSSam Leffler #define mp_clear_multi               ltc_deinit_multi
1839beb93cSSam Leffler #define mp_unsigned_bin_size(a)      ltc_mp.unsigned_size(a)
1939beb93cSSam Leffler #define mp_to_unsigned_bin(a, b)     ltc_mp.unsigned_write(a, b)
2039beb93cSSam Leffler #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
2139beb93cSSam Leffler #define mp_exptmod(a,b,c,d)          ltc_mp.exptmod(a,b,c,d)
2239beb93cSSam Leffler #endif
2339beb93cSSam Leffler 
2439beb93cSSam Leffler 
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)25e28a4053SRui Paulo int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
2639beb93cSSam Leffler {
2739beb93cSSam Leffler 	hash_state md;
2839beb93cSSam Leffler 	size_t i;
2939beb93cSSam Leffler 
3039beb93cSSam Leffler 	md4_init(&md);
3139beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
3239beb93cSSam Leffler 		md4_process(&md, addr[i], len[i]);
3339beb93cSSam Leffler 	md4_done(&md, mac);
34e28a4053SRui Paulo 	return 0;
3539beb93cSSam Leffler }
3639beb93cSSam Leffler 
3739beb93cSSam Leffler 
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)3885732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
3939beb93cSSam Leffler {
4039beb93cSSam Leffler 	u8 pkey[8], next, tmp;
4139beb93cSSam Leffler 	int i;
4239beb93cSSam Leffler 	symmetric_key skey;
4339beb93cSSam Leffler 
4439beb93cSSam Leffler 	/* Add parity bits to the key */
4539beb93cSSam Leffler 	next = 0;
4639beb93cSSam Leffler 	for (i = 0; i < 7; i++) {
4739beb93cSSam Leffler 		tmp = key[i];
4839beb93cSSam Leffler 		pkey[i] = (tmp >> i) | next | 1;
4939beb93cSSam Leffler 		next = tmp << (7 - i);
5039beb93cSSam Leffler 	}
5139beb93cSSam Leffler 	pkey[i] = next | 1;
5239beb93cSSam Leffler 
5339beb93cSSam Leffler 	des_setup(pkey, 8, 0, &skey);
5439beb93cSSam Leffler 	des_ecb_encrypt(clear, cypher, &skey);
5539beb93cSSam Leffler 	des_done(&skey);
5685732ac8SCy Schubert 	return 0;
5739beb93cSSam Leffler }
5839beb93cSSam Leffler 
5939beb93cSSam Leffler 
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)60e28a4053SRui Paulo int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
6139beb93cSSam Leffler {
6239beb93cSSam Leffler 	hash_state md;
6339beb93cSSam Leffler 	size_t i;
6439beb93cSSam Leffler 
6539beb93cSSam Leffler 	md5_init(&md);
6639beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
6739beb93cSSam Leffler 		md5_process(&md, addr[i], len[i]);
6839beb93cSSam Leffler 	md5_done(&md, mac);
69e28a4053SRui Paulo 	return 0;
7039beb93cSSam Leffler }
7139beb93cSSam Leffler 
7239beb93cSSam Leffler 
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)73e28a4053SRui Paulo int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
7439beb93cSSam Leffler {
7539beb93cSSam Leffler 	hash_state md;
7639beb93cSSam Leffler 	size_t i;
7739beb93cSSam Leffler 
7839beb93cSSam Leffler 	sha1_init(&md);
7939beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
8039beb93cSSam Leffler 		sha1_process(&md, addr[i], len[i]);
8139beb93cSSam Leffler 	sha1_done(&md, mac);
82e28a4053SRui Paulo 	return 0;
8339beb93cSSam Leffler }
8439beb93cSSam Leffler 
8539beb93cSSam Leffler 
aes_encrypt_init(const u8 * key,size_t len)8639beb93cSSam Leffler void * aes_encrypt_init(const u8 *key, size_t len)
8739beb93cSSam Leffler {
8839beb93cSSam Leffler 	symmetric_key *skey;
8939beb93cSSam Leffler 	skey = os_malloc(sizeof(*skey));
9039beb93cSSam Leffler 	if (skey == NULL)
9139beb93cSSam Leffler 		return NULL;
9239beb93cSSam Leffler 	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
9339beb93cSSam Leffler 		os_free(skey);
9439beb93cSSam Leffler 		return NULL;
9539beb93cSSam Leffler 	}
9639beb93cSSam Leffler 	return skey;
9739beb93cSSam Leffler }
9839beb93cSSam Leffler 
9939beb93cSSam Leffler 
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)10085732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
10139beb93cSSam Leffler {
10239beb93cSSam Leffler 	symmetric_key *skey = ctx;
10385732ac8SCy Schubert 	return aes_ecb_encrypt(plain, crypt, skey) == CRYPT_OK ? 0 : -1;
10439beb93cSSam Leffler }
10539beb93cSSam Leffler 
10639beb93cSSam Leffler 
aes_encrypt_deinit(void * ctx)10739beb93cSSam Leffler void aes_encrypt_deinit(void *ctx)
10839beb93cSSam Leffler {
10939beb93cSSam Leffler 	symmetric_key *skey = ctx;
11039beb93cSSam Leffler 	aes_done(skey);
11139beb93cSSam Leffler 	os_free(skey);
11239beb93cSSam Leffler }
11339beb93cSSam Leffler 
11439beb93cSSam Leffler 
aes_decrypt_init(const u8 * key,size_t len)11539beb93cSSam Leffler void * aes_decrypt_init(const u8 *key, size_t len)
11639beb93cSSam Leffler {
11739beb93cSSam Leffler 	symmetric_key *skey;
11839beb93cSSam Leffler 	skey = os_malloc(sizeof(*skey));
11939beb93cSSam Leffler 	if (skey == NULL)
12039beb93cSSam Leffler 		return NULL;
12139beb93cSSam Leffler 	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
12239beb93cSSam Leffler 		os_free(skey);
12339beb93cSSam Leffler 		return NULL;
12439beb93cSSam Leffler 	}
12539beb93cSSam Leffler 	return skey;
12639beb93cSSam Leffler }
12739beb93cSSam Leffler 
12839beb93cSSam Leffler 
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)12985732ac8SCy Schubert int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
13039beb93cSSam Leffler {
13139beb93cSSam Leffler 	symmetric_key *skey = ctx;
13285732ac8SCy Schubert 	return aes_ecb_encrypt(plain, (u8 *) crypt, skey) == CRYPT_OK ? 0 : -1;
13339beb93cSSam Leffler }
13439beb93cSSam Leffler 
13539beb93cSSam Leffler 
aes_decrypt_deinit(void * ctx)13639beb93cSSam Leffler void aes_decrypt_deinit(void *ctx)
13739beb93cSSam Leffler {
13839beb93cSSam Leffler 	symmetric_key *skey = ctx;
13939beb93cSSam Leffler 	aes_done(skey);
14039beb93cSSam Leffler 	os_free(skey);
14139beb93cSSam Leffler }
14239beb93cSSam Leffler 
14339beb93cSSam Leffler 
14439beb93cSSam Leffler struct crypto_hash {
14539beb93cSSam Leffler 	enum crypto_hash_alg alg;
14639beb93cSSam Leffler 	int error;
14739beb93cSSam Leffler 	union {
14839beb93cSSam Leffler 		hash_state md;
14939beb93cSSam Leffler 		hmac_state hmac;
15039beb93cSSam Leffler 	} u;
15139beb93cSSam Leffler };
15239beb93cSSam Leffler 
15339beb93cSSam Leffler 
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)15439beb93cSSam Leffler struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
15539beb93cSSam Leffler 				      size_t key_len)
15639beb93cSSam Leffler {
15739beb93cSSam Leffler 	struct crypto_hash *ctx;
15839beb93cSSam Leffler 
15939beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
16039beb93cSSam Leffler 	if (ctx == NULL)
16139beb93cSSam Leffler 		return NULL;
16239beb93cSSam Leffler 
16339beb93cSSam Leffler 	ctx->alg = alg;
16439beb93cSSam Leffler 
16539beb93cSSam Leffler 	switch (alg) {
16639beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
16739beb93cSSam Leffler 		if (md5_init(&ctx->u.md) != CRYPT_OK)
16839beb93cSSam Leffler 			goto fail;
16939beb93cSSam Leffler 		break;
17039beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
17139beb93cSSam Leffler 		if (sha1_init(&ctx->u.md) != CRYPT_OK)
17239beb93cSSam Leffler 			goto fail;
17339beb93cSSam Leffler 		break;
17439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
17539beb93cSSam Leffler 		if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
17639beb93cSSam Leffler 		    CRYPT_OK)
17739beb93cSSam Leffler 			goto fail;
17839beb93cSSam Leffler 		break;
17939beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
18039beb93cSSam Leffler 		if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
18139beb93cSSam Leffler 		    CRYPT_OK)
18239beb93cSSam Leffler 			goto fail;
18339beb93cSSam Leffler 		break;
18439beb93cSSam Leffler 	default:
18539beb93cSSam Leffler 		goto fail;
18639beb93cSSam Leffler 	}
18739beb93cSSam Leffler 
18839beb93cSSam Leffler 	return ctx;
18939beb93cSSam Leffler 
19039beb93cSSam Leffler fail:
19139beb93cSSam Leffler 	os_free(ctx);
19239beb93cSSam Leffler 	return NULL;
19339beb93cSSam Leffler }
19439beb93cSSam Leffler 
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)19539beb93cSSam Leffler void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
19639beb93cSSam Leffler {
19739beb93cSSam Leffler 	if (ctx == NULL || ctx->error)
19839beb93cSSam Leffler 		return;
19939beb93cSSam Leffler 
20039beb93cSSam Leffler 	switch (ctx->alg) {
20139beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
20239beb93cSSam Leffler 		ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
20339beb93cSSam Leffler 		break;
20439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
20539beb93cSSam Leffler 		ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
20639beb93cSSam Leffler 		break;
20739beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
20839beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
20939beb93cSSam Leffler 		ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
21039beb93cSSam Leffler 		break;
21139beb93cSSam Leffler 	}
21239beb93cSSam Leffler }
21339beb93cSSam Leffler 
21439beb93cSSam Leffler 
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)21539beb93cSSam Leffler int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
21639beb93cSSam Leffler {
21739beb93cSSam Leffler 	int ret = 0;
21839beb93cSSam Leffler 	unsigned long clen;
21939beb93cSSam Leffler 
22039beb93cSSam Leffler 	if (ctx == NULL)
22139beb93cSSam Leffler 		return -2;
22239beb93cSSam Leffler 
22339beb93cSSam Leffler 	if (mac == NULL || len == NULL) {
22439beb93cSSam Leffler 		os_free(ctx);
22539beb93cSSam Leffler 		return 0;
22639beb93cSSam Leffler 	}
22739beb93cSSam Leffler 
22839beb93cSSam Leffler 	if (ctx->error) {
22939beb93cSSam Leffler 		os_free(ctx);
23039beb93cSSam Leffler 		return -2;
23139beb93cSSam Leffler 	}
23239beb93cSSam Leffler 
23339beb93cSSam Leffler 	switch (ctx->alg) {
23439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
23539beb93cSSam Leffler 		if (*len < 16) {
23639beb93cSSam Leffler 			*len = 16;
23739beb93cSSam Leffler 			os_free(ctx);
23839beb93cSSam Leffler 			return -1;
23939beb93cSSam Leffler 		}
24039beb93cSSam Leffler 		*len = 16;
24139beb93cSSam Leffler 		if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
24239beb93cSSam Leffler 			ret = -2;
24339beb93cSSam Leffler 		break;
24439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
24539beb93cSSam Leffler 		if (*len < 20) {
24639beb93cSSam Leffler 			*len = 20;
24739beb93cSSam Leffler 			os_free(ctx);
24839beb93cSSam Leffler 			return -1;
24939beb93cSSam Leffler 		}
25039beb93cSSam Leffler 		*len = 20;
25139beb93cSSam Leffler 		if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
25239beb93cSSam Leffler 			ret = -2;
25339beb93cSSam Leffler 		break;
25439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
25539beb93cSSam Leffler 		if (*len < 20) {
25639beb93cSSam Leffler 			*len = 20;
25739beb93cSSam Leffler 			os_free(ctx);
25839beb93cSSam Leffler 			return -1;
25939beb93cSSam Leffler 		}
26039beb93cSSam Leffler 		/* continue */
26139beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
26239beb93cSSam Leffler 		if (*len < 16) {
26339beb93cSSam Leffler 			*len = 16;
26439beb93cSSam Leffler 			os_free(ctx);
26539beb93cSSam Leffler 			return -1;
26639beb93cSSam Leffler 		}
26739beb93cSSam Leffler 		clen = *len;
26839beb93cSSam Leffler 		if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
26939beb93cSSam Leffler 			os_free(ctx);
27039beb93cSSam Leffler 			return -1;
27139beb93cSSam Leffler 		}
27239beb93cSSam Leffler 		*len = clen;
27339beb93cSSam Leffler 		break;
27439beb93cSSam Leffler 	default:
27539beb93cSSam Leffler 		ret = -2;
27639beb93cSSam Leffler 		break;
27739beb93cSSam Leffler 	}
27839beb93cSSam Leffler 
27939beb93cSSam Leffler 	os_free(ctx);
28039beb93cSSam Leffler 
2814bc52338SCy Schubert 	if (TEST_FAIL())
2824bc52338SCy Schubert 		return -1;
2834bc52338SCy Schubert 
28439beb93cSSam Leffler 	return ret;
28539beb93cSSam Leffler }
28639beb93cSSam Leffler 
28739beb93cSSam Leffler 
28839beb93cSSam Leffler struct crypto_cipher {
28939beb93cSSam Leffler 	int rc4;
29039beb93cSSam Leffler 	union {
29139beb93cSSam Leffler 		symmetric_CBC cbc;
29239beb93cSSam Leffler 		struct {
29339beb93cSSam Leffler 			size_t used_bytes;
29439beb93cSSam Leffler 			u8 key[16];
29539beb93cSSam Leffler 			size_t keylen;
29639beb93cSSam Leffler 		} rc4;
29739beb93cSSam Leffler 	} u;
29839beb93cSSam Leffler };
29939beb93cSSam Leffler 
30039beb93cSSam Leffler 
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)30139beb93cSSam Leffler struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
30239beb93cSSam Leffler 					  const u8 *iv, const u8 *key,
30339beb93cSSam Leffler 					  size_t key_len)
30439beb93cSSam Leffler {
30539beb93cSSam Leffler 	struct crypto_cipher *ctx;
30639beb93cSSam Leffler 	int idx, res, rc4 = 0;
30739beb93cSSam Leffler 
30839beb93cSSam Leffler 	switch (alg) {
30939beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_AES:
31039beb93cSSam Leffler 		idx = find_cipher("aes");
31139beb93cSSam Leffler 		break;
31239beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_3DES:
31339beb93cSSam Leffler 		idx = find_cipher("3des");
31439beb93cSSam Leffler 		break;
31539beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_DES:
31639beb93cSSam Leffler 		idx = find_cipher("des");
31739beb93cSSam Leffler 		break;
31839beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC2:
31939beb93cSSam Leffler 		idx = find_cipher("rc2");
32039beb93cSSam Leffler 		break;
32139beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC4:
32239beb93cSSam Leffler 		idx = -1;
32339beb93cSSam Leffler 		rc4 = 1;
32439beb93cSSam Leffler 		break;
32539beb93cSSam Leffler 	default:
32639beb93cSSam Leffler 		return NULL;
32739beb93cSSam Leffler 	}
32839beb93cSSam Leffler 
32939beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
33039beb93cSSam Leffler 	if (ctx == NULL)
33139beb93cSSam Leffler 		return NULL;
33239beb93cSSam Leffler 
33339beb93cSSam Leffler 	if (rc4) {
33439beb93cSSam Leffler 		ctx->rc4 = 1;
33539beb93cSSam Leffler 		if (key_len > sizeof(ctx->u.rc4.key)) {
33639beb93cSSam Leffler 			os_free(ctx);
33739beb93cSSam Leffler 			return NULL;
33839beb93cSSam Leffler 		}
33939beb93cSSam Leffler 		ctx->u.rc4.keylen = key_len;
34039beb93cSSam Leffler 		os_memcpy(ctx->u.rc4.key, key, key_len);
34139beb93cSSam Leffler 	} else {
34239beb93cSSam Leffler 		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
34339beb93cSSam Leffler 		if (res != CRYPT_OK) {
34439beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
34539beb93cSSam Leffler 				   "failed: %s", error_to_string(res));
34639beb93cSSam Leffler 			os_free(ctx);
34739beb93cSSam Leffler 			return NULL;
34839beb93cSSam Leffler 		}
34939beb93cSSam Leffler 	}
35039beb93cSSam Leffler 
35139beb93cSSam Leffler 	return ctx;
35239beb93cSSam Leffler }
35339beb93cSSam Leffler 
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)35439beb93cSSam Leffler int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
35539beb93cSSam Leffler 			  u8 *crypt, size_t len)
35639beb93cSSam Leffler {
35739beb93cSSam Leffler 	int res;
35839beb93cSSam Leffler 
35939beb93cSSam Leffler 	if (ctx->rc4) {
36039beb93cSSam Leffler 		if (plain != crypt)
36139beb93cSSam Leffler 			os_memcpy(crypt, plain, len);
36239beb93cSSam Leffler 		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
36339beb93cSSam Leffler 			 ctx->u.rc4.used_bytes, crypt, len);
36439beb93cSSam Leffler 		ctx->u.rc4.used_bytes += len;
36539beb93cSSam Leffler 		return 0;
36639beb93cSSam Leffler 	}
36739beb93cSSam Leffler 
36839beb93cSSam Leffler 	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
36939beb93cSSam Leffler 	if (res != CRYPT_OK) {
37039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
37139beb93cSSam Leffler 			   "failed: %s", error_to_string(res));
37239beb93cSSam Leffler 		return -1;
37339beb93cSSam Leffler 	}
37439beb93cSSam Leffler 	return 0;
37539beb93cSSam Leffler }
37639beb93cSSam Leffler 
37739beb93cSSam Leffler 
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)37839beb93cSSam Leffler int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
37939beb93cSSam Leffler 			  u8 *plain, size_t len)
38039beb93cSSam Leffler {
38139beb93cSSam Leffler 	int res;
38239beb93cSSam Leffler 
38339beb93cSSam Leffler 	if (ctx->rc4) {
38439beb93cSSam Leffler 		if (plain != crypt)
38539beb93cSSam Leffler 			os_memcpy(plain, crypt, len);
38639beb93cSSam Leffler 		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
38739beb93cSSam Leffler 			 ctx->u.rc4.used_bytes, plain, len);
38839beb93cSSam Leffler 		ctx->u.rc4.used_bytes += len;
38939beb93cSSam Leffler 		return 0;
39039beb93cSSam Leffler 	}
39139beb93cSSam Leffler 
39239beb93cSSam Leffler 	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
39339beb93cSSam Leffler 	if (res != CRYPT_OK) {
39439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
39539beb93cSSam Leffler 			   "failed: %s", error_to_string(res));
39639beb93cSSam Leffler 		return -1;
39739beb93cSSam Leffler 	}
39839beb93cSSam Leffler 
39939beb93cSSam Leffler 	return 0;
40039beb93cSSam Leffler }
40139beb93cSSam Leffler 
40239beb93cSSam Leffler 
crypto_cipher_deinit(struct crypto_cipher * ctx)40339beb93cSSam Leffler void crypto_cipher_deinit(struct crypto_cipher *ctx)
40439beb93cSSam Leffler {
40539beb93cSSam Leffler 	if (!ctx->rc4)
40639beb93cSSam Leffler 		cbc_done(&ctx->u.cbc);
40739beb93cSSam Leffler 	os_free(ctx);
40839beb93cSSam Leffler }
40939beb93cSSam Leffler 
41039beb93cSSam Leffler 
41139beb93cSSam Leffler struct crypto_public_key {
41239beb93cSSam Leffler 	rsa_key rsa;
41339beb93cSSam Leffler };
41439beb93cSSam Leffler 
41539beb93cSSam Leffler struct crypto_private_key {
41639beb93cSSam Leffler 	rsa_key rsa;
41739beb93cSSam Leffler };
41839beb93cSSam Leffler 
41939beb93cSSam Leffler 
crypto_public_key_import(const u8 * key,size_t len)42039beb93cSSam Leffler struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
42139beb93cSSam Leffler {
42239beb93cSSam Leffler 	int res;
42339beb93cSSam Leffler 	struct crypto_public_key *pk;
42439beb93cSSam Leffler 
42539beb93cSSam Leffler 	pk = os_zalloc(sizeof(*pk));
42639beb93cSSam Leffler 	if (pk == NULL)
42739beb93cSSam Leffler 		return NULL;
42839beb93cSSam Leffler 
42939beb93cSSam Leffler 	res = rsa_import(key, len, &pk->rsa);
43039beb93cSSam Leffler 	if (res != CRYPT_OK) {
43139beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
43239beb93cSSam Leffler 			   "public key (res=%d '%s')",
43339beb93cSSam Leffler 			   res, error_to_string(res));
43439beb93cSSam Leffler 		os_free(pk);
43539beb93cSSam Leffler 		return NULL;
43639beb93cSSam Leffler 	}
43739beb93cSSam Leffler 
43839beb93cSSam Leffler 	if (pk->rsa.type != PK_PUBLIC) {
43939beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
44039beb93cSSam Leffler 			   "correct type");
44139beb93cSSam Leffler 		rsa_free(&pk->rsa);
44239beb93cSSam Leffler 		os_free(pk);
44339beb93cSSam Leffler 		return NULL;
44439beb93cSSam Leffler 	}
44539beb93cSSam Leffler 
44639beb93cSSam Leffler 	return pk;
44739beb93cSSam Leffler }
44839beb93cSSam Leffler 
44939beb93cSSam Leffler 
crypto_private_key_import(const u8 * key,size_t len,const char * passwd)45039beb93cSSam Leffler struct crypto_private_key * crypto_private_key_import(const u8 *key,
451e28a4053SRui Paulo 						      size_t len,
452e28a4053SRui Paulo 						      const char *passwd)
45339beb93cSSam Leffler {
45439beb93cSSam Leffler 	int res;
45539beb93cSSam Leffler 	struct crypto_private_key *pk;
45639beb93cSSam Leffler 
45739beb93cSSam Leffler 	pk = os_zalloc(sizeof(*pk));
45839beb93cSSam Leffler 	if (pk == NULL)
45939beb93cSSam Leffler 		return NULL;
46039beb93cSSam Leffler 
46139beb93cSSam Leffler 	res = rsa_import(key, len, &pk->rsa);
46239beb93cSSam Leffler 	if (res != CRYPT_OK) {
46339beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
46439beb93cSSam Leffler 			   "private key (res=%d '%s')",
46539beb93cSSam Leffler 			   res, error_to_string(res));
46639beb93cSSam Leffler 		os_free(pk);
46739beb93cSSam Leffler 		return NULL;
46839beb93cSSam Leffler 	}
46939beb93cSSam Leffler 
47039beb93cSSam Leffler 	if (pk->rsa.type != PK_PRIVATE) {
47139beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
47239beb93cSSam Leffler 			   "correct type");
47339beb93cSSam Leffler 		rsa_free(&pk->rsa);
47439beb93cSSam Leffler 		os_free(pk);
47539beb93cSSam Leffler 		return NULL;
47639beb93cSSam Leffler 	}
47739beb93cSSam Leffler 
47839beb93cSSam Leffler 	return pk;
47939beb93cSSam Leffler }
48039beb93cSSam Leffler 
48139beb93cSSam Leffler 
crypto_public_key_from_cert(const u8 * buf,size_t len)48239beb93cSSam Leffler struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
48339beb93cSSam Leffler 						       size_t len)
48439beb93cSSam Leffler {
48539beb93cSSam Leffler 	/* No X.509 support in LibTomCrypt */
48639beb93cSSam Leffler 	return NULL;
48739beb93cSSam Leffler }
48839beb93cSSam Leffler 
48939beb93cSSam Leffler 
pkcs1_generate_encryption_block(u8 block_type,size_t modlen,const u8 * in,size_t inlen,u8 * out,size_t * outlen)49039beb93cSSam Leffler static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
49139beb93cSSam Leffler 					   const u8 *in, size_t inlen,
49239beb93cSSam Leffler 					   u8 *out, size_t *outlen)
49339beb93cSSam Leffler {
49439beb93cSSam Leffler 	size_t ps_len;
49539beb93cSSam Leffler 	u8 *pos;
49639beb93cSSam Leffler 
49739beb93cSSam Leffler 	/*
49839beb93cSSam Leffler 	 * PKCS #1 v1.5, 8.1:
49939beb93cSSam Leffler 	 *
50039beb93cSSam Leffler 	 * EB = 00 || BT || PS || 00 || D
50139beb93cSSam Leffler 	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
50239beb93cSSam Leffler 	 * PS = k-3-||D||; at least eight octets
50339beb93cSSam Leffler 	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
50439beb93cSSam Leffler 	 * k = length of modulus in octets (modlen)
50539beb93cSSam Leffler 	 */
50639beb93cSSam Leffler 
50739beb93cSSam Leffler 	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
50839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
50939beb93cSSam Leffler 			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
51039beb93cSSam Leffler 			   __func__, (unsigned long) modlen,
51139beb93cSSam Leffler 			   (unsigned long) *outlen,
51239beb93cSSam Leffler 			   (unsigned long) inlen);
51339beb93cSSam Leffler 		return -1;
51439beb93cSSam Leffler 	}
51539beb93cSSam Leffler 
51639beb93cSSam Leffler 	pos = out;
51739beb93cSSam Leffler 	*pos++ = 0x00;
51839beb93cSSam Leffler 	*pos++ = block_type; /* BT */
51939beb93cSSam Leffler 	ps_len = modlen - inlen - 3;
52039beb93cSSam Leffler 	switch (block_type) {
52139beb93cSSam Leffler 	case 0:
52239beb93cSSam Leffler 		os_memset(pos, 0x00, ps_len);
52339beb93cSSam Leffler 		pos += ps_len;
52439beb93cSSam Leffler 		break;
52539beb93cSSam Leffler 	case 1:
52639beb93cSSam Leffler 		os_memset(pos, 0xff, ps_len);
52739beb93cSSam Leffler 		pos += ps_len;
52839beb93cSSam Leffler 		break;
52939beb93cSSam Leffler 	case 2:
53039beb93cSSam Leffler 		if (os_get_random(pos, ps_len) < 0) {
53139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
53239beb93cSSam Leffler 				   "random data for PS", __func__);
53339beb93cSSam Leffler 			return -1;
53439beb93cSSam Leffler 		}
53539beb93cSSam Leffler 		while (ps_len--) {
53639beb93cSSam Leffler 			if (*pos == 0x00)
53739beb93cSSam Leffler 				*pos = 0x01;
53839beb93cSSam Leffler 			pos++;
53939beb93cSSam Leffler 		}
54039beb93cSSam Leffler 		break;
54139beb93cSSam Leffler 	default:
54239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
54339beb93cSSam Leffler 			   "%d", __func__, block_type);
54439beb93cSSam Leffler 		return -1;
54539beb93cSSam Leffler 	}
54639beb93cSSam Leffler 	*pos++ = 0x00;
54739beb93cSSam Leffler 	os_memcpy(pos, in, inlen); /* D */
54839beb93cSSam Leffler 
54939beb93cSSam Leffler 	return 0;
55039beb93cSSam Leffler }
55139beb93cSSam Leffler 
55239beb93cSSam Leffler 
crypto_rsa_encrypt_pkcs1(int block_type,rsa_key * key,int key_type,const u8 * in,size_t inlen,u8 * out,size_t * outlen)55339beb93cSSam Leffler static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
55439beb93cSSam Leffler 				    const u8 *in, size_t inlen,
55539beb93cSSam Leffler 				    u8 *out, size_t *outlen)
55639beb93cSSam Leffler {
55739beb93cSSam Leffler 	unsigned long len, modlen;
55839beb93cSSam Leffler 	int res;
55939beb93cSSam Leffler 
56039beb93cSSam Leffler 	modlen = mp_unsigned_bin_size(key->N);
56139beb93cSSam Leffler 
56239beb93cSSam Leffler 	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
56339beb93cSSam Leffler 					    out, outlen) < 0)
56439beb93cSSam Leffler 		return -1;
56539beb93cSSam Leffler 
56639beb93cSSam Leffler 	len = *outlen;
56739beb93cSSam Leffler 	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
56839beb93cSSam Leffler 	if (res != CRYPT_OK) {
56939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
57039beb93cSSam Leffler 			   error_to_string(res));
57139beb93cSSam Leffler 		return -1;
57239beb93cSSam Leffler 	}
57339beb93cSSam Leffler 	*outlen = len;
57439beb93cSSam Leffler 
57539beb93cSSam Leffler 	return 0;
57639beb93cSSam Leffler }
57739beb93cSSam Leffler 
57839beb93cSSam Leffler 
crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)57939beb93cSSam Leffler int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
58039beb93cSSam Leffler 					const u8 *in, size_t inlen,
58139beb93cSSam Leffler 					u8 *out, size_t *outlen)
58239beb93cSSam Leffler {
58339beb93cSSam Leffler 	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
58439beb93cSSam Leffler 					out, outlen);
58539beb93cSSam Leffler }
58639beb93cSSam Leffler 
58739beb93cSSam Leffler 
crypto_private_key_sign_pkcs1(struct crypto_private_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)58839beb93cSSam Leffler int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
58939beb93cSSam Leffler 				  const u8 *in, size_t inlen,
59039beb93cSSam Leffler 				  u8 *out, size_t *outlen)
59139beb93cSSam Leffler {
59239beb93cSSam Leffler 	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
59339beb93cSSam Leffler 					out, outlen);
59439beb93cSSam Leffler }
59539beb93cSSam Leffler 
59639beb93cSSam Leffler 
crypto_public_key_free(struct crypto_public_key * key)59739beb93cSSam Leffler void crypto_public_key_free(struct crypto_public_key *key)
59839beb93cSSam Leffler {
59939beb93cSSam Leffler 	if (key) {
60039beb93cSSam Leffler 		rsa_free(&key->rsa);
60139beb93cSSam Leffler 		os_free(key);
60239beb93cSSam Leffler 	}
60339beb93cSSam Leffler }
60439beb93cSSam Leffler 
60539beb93cSSam Leffler 
crypto_private_key_free(struct crypto_private_key * key)60639beb93cSSam Leffler void crypto_private_key_free(struct crypto_private_key *key)
60739beb93cSSam Leffler {
60839beb93cSSam Leffler 	if (key) {
60939beb93cSSam Leffler 		rsa_free(&key->rsa);
61039beb93cSSam Leffler 		os_free(key);
61139beb93cSSam Leffler 	}
61239beb93cSSam Leffler }
61339beb93cSSam Leffler 
61439beb93cSSam Leffler 
crypto_public_key_decrypt_pkcs1(struct crypto_public_key * key,const u8 * crypt,size_t crypt_len,u8 * plain,size_t * plain_len)61539beb93cSSam Leffler int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
61639beb93cSSam Leffler 				    const u8 *crypt, size_t crypt_len,
61739beb93cSSam Leffler 				    u8 *plain, size_t *plain_len)
61839beb93cSSam Leffler {
61939beb93cSSam Leffler 	int res;
62039beb93cSSam Leffler 	unsigned long len;
62139beb93cSSam Leffler 	u8 *pos;
62239beb93cSSam Leffler 
62339beb93cSSam Leffler 	len = *plain_len;
62439beb93cSSam Leffler 	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
62539beb93cSSam Leffler 			  &key->rsa);
62639beb93cSSam Leffler 	if (res != CRYPT_OK) {
62739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
62839beb93cSSam Leffler 			   error_to_string(res));
62939beb93cSSam Leffler 		return -1;
63039beb93cSSam Leffler 	}
63139beb93cSSam Leffler 
63239beb93cSSam Leffler 	/*
63339beb93cSSam Leffler 	 * PKCS #1 v1.5, 8.1:
63439beb93cSSam Leffler 	 *
63539beb93cSSam Leffler 	 * EB = 00 || BT || PS || 00 || D
63639beb93cSSam Leffler 	 * BT = 01
63739beb93cSSam Leffler 	 * PS = k-3-||D|| times FF
63839beb93cSSam Leffler 	 * k = length of modulus in octets
63939beb93cSSam Leffler 	 */
64039beb93cSSam Leffler 
64139beb93cSSam Leffler 	if (len < 3 + 8 + 16 /* min hash len */ ||
64239beb93cSSam Leffler 	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
64339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
64439beb93cSSam Leffler 			   "structure");
64539beb93cSSam Leffler 		return -1;
64639beb93cSSam Leffler 	}
64739beb93cSSam Leffler 
64839beb93cSSam Leffler 	pos = plain + 3;
64939beb93cSSam Leffler 	while (pos < plain + len && *pos == 0xff)
65039beb93cSSam Leffler 		pos++;
65139beb93cSSam Leffler 	if (pos - plain - 2 < 8) {
65239beb93cSSam Leffler 		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
65339beb93cSSam Leffler 		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
65439beb93cSSam Leffler 			   "padding");
65539beb93cSSam Leffler 		return -1;
65639beb93cSSam Leffler 	}
65739beb93cSSam Leffler 
65839beb93cSSam Leffler 	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
65939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
66039beb93cSSam Leffler 			   "structure (2)");
66139beb93cSSam Leffler 		return -1;
66239beb93cSSam Leffler 	}
66339beb93cSSam Leffler 	pos++;
66439beb93cSSam Leffler 	len -= pos - plain;
66539beb93cSSam Leffler 
66639beb93cSSam Leffler 	/* Strip PKCS #1 header */
66739beb93cSSam Leffler 	os_memmove(plain, pos, len);
66839beb93cSSam Leffler 	*plain_len = len;
66939beb93cSSam Leffler 
67039beb93cSSam Leffler 	return 0;
67139beb93cSSam Leffler }
67239beb93cSSam Leffler 
67339beb93cSSam Leffler 
crypto_global_init(void)67439beb93cSSam Leffler int crypto_global_init(void)
67539beb93cSSam Leffler {
67639beb93cSSam Leffler 	ltc_mp = tfm_desc;
67739beb93cSSam Leffler 	/* TODO: only register algorithms that are really needed */
67839beb93cSSam Leffler 	if (register_hash(&md4_desc) < 0 ||
67939beb93cSSam Leffler 	    register_hash(&md5_desc) < 0 ||
68039beb93cSSam Leffler 	    register_hash(&sha1_desc) < 0 ||
68139beb93cSSam Leffler 	    register_cipher(&aes_desc) < 0 ||
68239beb93cSSam Leffler 	    register_cipher(&des_desc) < 0 ||
68339beb93cSSam Leffler 	    register_cipher(&des3_desc) < 0) {
68439beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
68539beb93cSSam Leffler 			   "hash/cipher functions");
68639beb93cSSam Leffler 		return -1;
68739beb93cSSam Leffler 	}
68839beb93cSSam Leffler 
68939beb93cSSam Leffler 	return 0;
69039beb93cSSam Leffler }
69139beb93cSSam Leffler 
69239beb93cSSam Leffler 
crypto_global_deinit(void)69339beb93cSSam Leffler void crypto_global_deinit(void)
69439beb93cSSam Leffler {
69539beb93cSSam Leffler }
69639beb93cSSam Leffler 
69739beb93cSSam Leffler 
698e28a4053SRui Paulo #ifdef CONFIG_MODEXP
69939beb93cSSam Leffler 
crypto_dh_init(u8 generator,const u8 * prime,size_t prime_len,u8 * privkey,u8 * pubkey)70085732ac8SCy Schubert int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
70185732ac8SCy Schubert 		   u8 *pubkey)
70285732ac8SCy Schubert {
70385732ac8SCy Schubert 	size_t pubkey_len, pad;
70485732ac8SCy Schubert 
70585732ac8SCy Schubert 	if (os_get_random(privkey, prime_len) < 0)
70685732ac8SCy Schubert 		return -1;
70785732ac8SCy Schubert 	if (os_memcmp(privkey, prime, prime_len) > 0) {
70885732ac8SCy Schubert 		/* Make sure private value is smaller than prime */
70985732ac8SCy Schubert 		privkey[0] = 0;
71085732ac8SCy Schubert 	}
71185732ac8SCy Schubert 
71285732ac8SCy Schubert 	pubkey_len = prime_len;
71385732ac8SCy Schubert 	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
71485732ac8SCy Schubert 			   pubkey, &pubkey_len) < 0)
71585732ac8SCy Schubert 		return -1;
71685732ac8SCy Schubert 	if (pubkey_len < prime_len) {
71785732ac8SCy Schubert 		pad = prime_len - pubkey_len;
71885732ac8SCy Schubert 		os_memmove(pubkey + pad, pubkey, pubkey_len);
71985732ac8SCy Schubert 		os_memset(pubkey, 0, pad);
72085732ac8SCy Schubert 	}
72185732ac8SCy Schubert 
72285732ac8SCy Schubert 	return 0;
72385732ac8SCy Schubert }
72485732ac8SCy Schubert 
72585732ac8SCy Schubert 
crypto_dh_derive_secret(u8 generator,const u8 * prime,size_t prime_len,const u8 * order,size_t order_len,const u8 * privkey,size_t privkey_len,const u8 * pubkey,size_t pubkey_len,u8 * secret,size_t * len)72685732ac8SCy Schubert int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
7274bc52338SCy Schubert 			    const u8 *order, size_t order_len,
72885732ac8SCy Schubert 			    const u8 *privkey, size_t privkey_len,
72985732ac8SCy Schubert 			    const u8 *pubkey, size_t pubkey_len,
73085732ac8SCy Schubert 			    u8 *secret, size_t *len)
73185732ac8SCy Schubert {
7324bc52338SCy Schubert 	/* TODO: check pubkey */
73385732ac8SCy Schubert 	return crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
73485732ac8SCy Schubert 			      prime, prime_len, secret, len);
73585732ac8SCy Schubert }
73685732ac8SCy Schubert 
73785732ac8SCy Schubert 
crypto_mod_exp(const u8 * base,size_t base_len,const u8 * power,size_t power_len,const u8 * modulus,size_t modulus_len,u8 * result,size_t * result_len)73839beb93cSSam Leffler int crypto_mod_exp(const u8 *base, size_t base_len,
73939beb93cSSam Leffler 		   const u8 *power, size_t power_len,
74039beb93cSSam Leffler 		   const u8 *modulus, size_t modulus_len,
74139beb93cSSam Leffler 		   u8 *result, size_t *result_len)
74239beb93cSSam Leffler {
74339beb93cSSam Leffler 	void *b, *p, *m, *r;
74439beb93cSSam Leffler 
74539beb93cSSam Leffler 	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
74639beb93cSSam Leffler 		return -1;
74739beb93cSSam Leffler 
74839beb93cSSam Leffler 	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
74939beb93cSSam Leffler 	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
75039beb93cSSam Leffler 	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
75139beb93cSSam Leffler 		goto fail;
75239beb93cSSam Leffler 
75339beb93cSSam Leffler 	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
75439beb93cSSam Leffler 		goto fail;
75539beb93cSSam Leffler 
75639beb93cSSam Leffler 	*result_len = mp_unsigned_bin_size(r);
75739beb93cSSam Leffler 	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
75839beb93cSSam Leffler 		goto fail;
75939beb93cSSam Leffler 
76039beb93cSSam Leffler 	mp_clear_multi(b, p, m, r, NULL);
76139beb93cSSam Leffler 	return 0;
76239beb93cSSam Leffler 
76339beb93cSSam Leffler fail:
76439beb93cSSam Leffler 	mp_clear_multi(b, p, m, r, NULL);
76539beb93cSSam Leffler 	return -1;
76639beb93cSSam Leffler }
76739beb93cSSam Leffler 
768e28a4053SRui Paulo #endif /* CONFIG_MODEXP */
769*a90b9d01SCy Schubert 
770*a90b9d01SCy Schubert 
crypto_unload(void)771*a90b9d01SCy Schubert void crypto_unload(void)
772*a90b9d01SCy Schubert {
773*a90b9d01SCy Schubert }
774