16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
36d49e1aeSJan Lentfer  * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  */
86d49e1aeSJan Lentfer 
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer #include <tomcrypt.h>
116d49e1aeSJan Lentfer 
126d49e1aeSJan Lentfer #include "common.h"
136d49e1aeSJan Lentfer #include "crypto.h"
146d49e1aeSJan Lentfer 
156d49e1aeSJan Lentfer #ifndef mp_init_multi
166d49e1aeSJan Lentfer #define mp_init_multi                ltc_init_multi
176d49e1aeSJan Lentfer #define mp_clear_multi               ltc_deinit_multi
186d49e1aeSJan Lentfer #define mp_unsigned_bin_size(a)      ltc_mp.unsigned_size(a)
196d49e1aeSJan Lentfer #define mp_to_unsigned_bin(a, b)     ltc_mp.unsigned_write(a, b)
206d49e1aeSJan Lentfer #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
216d49e1aeSJan Lentfer #define mp_exptmod(a,b,c,d)          ltc_mp.exptmod(a,b,c,d)
226d49e1aeSJan Lentfer #endif
236d49e1aeSJan Lentfer 
246d49e1aeSJan Lentfer 
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)253ff40c12SJohn Marino int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
266d49e1aeSJan Lentfer {
276d49e1aeSJan Lentfer 	hash_state md;
286d49e1aeSJan Lentfer 	size_t i;
296d49e1aeSJan Lentfer 
306d49e1aeSJan Lentfer 	md4_init(&md);
316d49e1aeSJan Lentfer 	for (i = 0; i < num_elem; i++)
326d49e1aeSJan Lentfer 		md4_process(&md, addr[i], len[i]);
336d49e1aeSJan Lentfer 	md4_done(&md, mac);
343ff40c12SJohn Marino 	return 0;
356d49e1aeSJan Lentfer }
366d49e1aeSJan Lentfer 
376d49e1aeSJan Lentfer 
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)38*a1157835SDaniel Fojt int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
396d49e1aeSJan Lentfer {
406d49e1aeSJan Lentfer 	u8 pkey[8], next, tmp;
416d49e1aeSJan Lentfer 	int i;
426d49e1aeSJan Lentfer 	symmetric_key skey;
436d49e1aeSJan Lentfer 
446d49e1aeSJan Lentfer 	/* Add parity bits to the key */
456d49e1aeSJan Lentfer 	next = 0;
466d49e1aeSJan Lentfer 	for (i = 0; i < 7; i++) {
476d49e1aeSJan Lentfer 		tmp = key[i];
486d49e1aeSJan Lentfer 		pkey[i] = (tmp >> i) | next | 1;
496d49e1aeSJan Lentfer 		next = tmp << (7 - i);
506d49e1aeSJan Lentfer 	}
516d49e1aeSJan Lentfer 	pkey[i] = next | 1;
526d49e1aeSJan Lentfer 
536d49e1aeSJan Lentfer 	des_setup(pkey, 8, 0, &skey);
546d49e1aeSJan Lentfer 	des_ecb_encrypt(clear, cypher, &skey);
556d49e1aeSJan Lentfer 	des_done(&skey);
56*a1157835SDaniel Fojt 	return 0;
576d49e1aeSJan Lentfer }
586d49e1aeSJan Lentfer 
596d49e1aeSJan Lentfer 
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)603ff40c12SJohn Marino int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
616d49e1aeSJan Lentfer {
626d49e1aeSJan Lentfer 	hash_state md;
636d49e1aeSJan Lentfer 	size_t i;
646d49e1aeSJan Lentfer 
656d49e1aeSJan Lentfer 	md5_init(&md);
666d49e1aeSJan Lentfer 	for (i = 0; i < num_elem; i++)
676d49e1aeSJan Lentfer 		md5_process(&md, addr[i], len[i]);
686d49e1aeSJan Lentfer 	md5_done(&md, mac);
693ff40c12SJohn Marino 	return 0;
706d49e1aeSJan Lentfer }
716d49e1aeSJan Lentfer 
726d49e1aeSJan Lentfer 
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)733ff40c12SJohn Marino int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
746d49e1aeSJan Lentfer {
756d49e1aeSJan Lentfer 	hash_state md;
766d49e1aeSJan Lentfer 	size_t i;
776d49e1aeSJan Lentfer 
786d49e1aeSJan Lentfer 	sha1_init(&md);
796d49e1aeSJan Lentfer 	for (i = 0; i < num_elem; i++)
806d49e1aeSJan Lentfer 		sha1_process(&md, addr[i], len[i]);
816d49e1aeSJan Lentfer 	sha1_done(&md, mac);
823ff40c12SJohn Marino 	return 0;
836d49e1aeSJan Lentfer }
846d49e1aeSJan Lentfer 
856d49e1aeSJan Lentfer 
aes_encrypt_init(const u8 * key,size_t len)866d49e1aeSJan Lentfer void * aes_encrypt_init(const u8 *key, size_t len)
876d49e1aeSJan Lentfer {
886d49e1aeSJan Lentfer 	symmetric_key *skey;
896d49e1aeSJan Lentfer 	skey = os_malloc(sizeof(*skey));
906d49e1aeSJan Lentfer 	if (skey == NULL)
916d49e1aeSJan Lentfer 		return NULL;
926d49e1aeSJan Lentfer 	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
936d49e1aeSJan Lentfer 		os_free(skey);
946d49e1aeSJan Lentfer 		return NULL;
956d49e1aeSJan Lentfer 	}
966d49e1aeSJan Lentfer 	return skey;
976d49e1aeSJan Lentfer }
986d49e1aeSJan Lentfer 
996d49e1aeSJan Lentfer 
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)100*a1157835SDaniel Fojt int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
1016d49e1aeSJan Lentfer {
1026d49e1aeSJan Lentfer 	symmetric_key *skey = ctx;
103*a1157835SDaniel Fojt 	return aes_ecb_encrypt(plain, crypt, skey) == CRYPT_OK ? 0 : -1;
1046d49e1aeSJan Lentfer }
1056d49e1aeSJan Lentfer 
1066d49e1aeSJan Lentfer 
aes_encrypt_deinit(void * ctx)1076d49e1aeSJan Lentfer void aes_encrypt_deinit(void *ctx)
1086d49e1aeSJan Lentfer {
1096d49e1aeSJan Lentfer 	symmetric_key *skey = ctx;
1106d49e1aeSJan Lentfer 	aes_done(skey);
1116d49e1aeSJan Lentfer 	os_free(skey);
1126d49e1aeSJan Lentfer }
1136d49e1aeSJan Lentfer 
1146d49e1aeSJan Lentfer 
aes_decrypt_init(const u8 * key,size_t len)1156d49e1aeSJan Lentfer void * aes_decrypt_init(const u8 *key, size_t len)
1166d49e1aeSJan Lentfer {
1176d49e1aeSJan Lentfer 	symmetric_key *skey;
1186d49e1aeSJan Lentfer 	skey = os_malloc(sizeof(*skey));
1196d49e1aeSJan Lentfer 	if (skey == NULL)
1206d49e1aeSJan Lentfer 		return NULL;
1216d49e1aeSJan Lentfer 	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
1226d49e1aeSJan Lentfer 		os_free(skey);
1236d49e1aeSJan Lentfer 		return NULL;
1246d49e1aeSJan Lentfer 	}
1256d49e1aeSJan Lentfer 	return skey;
1266d49e1aeSJan Lentfer }
1276d49e1aeSJan Lentfer 
1286d49e1aeSJan Lentfer 
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)129*a1157835SDaniel Fojt int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
1306d49e1aeSJan Lentfer {
1316d49e1aeSJan Lentfer 	symmetric_key *skey = ctx;
132*a1157835SDaniel Fojt 	return aes_ecb_encrypt(plain, (u8 *) crypt, skey) == CRYPT_OK ? 0 : -1;
1336d49e1aeSJan Lentfer }
1346d49e1aeSJan Lentfer 
1356d49e1aeSJan Lentfer 
aes_decrypt_deinit(void * ctx)1366d49e1aeSJan Lentfer void aes_decrypt_deinit(void *ctx)
1376d49e1aeSJan Lentfer {
1386d49e1aeSJan Lentfer 	symmetric_key *skey = ctx;
1396d49e1aeSJan Lentfer 	aes_done(skey);
1406d49e1aeSJan Lentfer 	os_free(skey);
1416d49e1aeSJan Lentfer }
1426d49e1aeSJan Lentfer 
1436d49e1aeSJan Lentfer 
1446d49e1aeSJan Lentfer struct crypto_hash {
1456d49e1aeSJan Lentfer 	enum crypto_hash_alg alg;
1466d49e1aeSJan Lentfer 	int error;
1476d49e1aeSJan Lentfer 	union {
1486d49e1aeSJan Lentfer 		hash_state md;
1496d49e1aeSJan Lentfer 		hmac_state hmac;
1506d49e1aeSJan Lentfer 	} u;
1516d49e1aeSJan Lentfer };
1526d49e1aeSJan Lentfer 
1536d49e1aeSJan Lentfer 
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)1546d49e1aeSJan Lentfer struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
1556d49e1aeSJan Lentfer 				      size_t key_len)
1566d49e1aeSJan Lentfer {
1576d49e1aeSJan Lentfer 	struct crypto_hash *ctx;
1586d49e1aeSJan Lentfer 
1596d49e1aeSJan Lentfer 	ctx = os_zalloc(sizeof(*ctx));
1606d49e1aeSJan Lentfer 	if (ctx == NULL)
1616d49e1aeSJan Lentfer 		return NULL;
1626d49e1aeSJan Lentfer 
1636d49e1aeSJan Lentfer 	ctx->alg = alg;
1646d49e1aeSJan Lentfer 
1656d49e1aeSJan Lentfer 	switch (alg) {
1666d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_MD5:
1676d49e1aeSJan Lentfer 		if (md5_init(&ctx->u.md) != CRYPT_OK)
1686d49e1aeSJan Lentfer 			goto fail;
1696d49e1aeSJan Lentfer 		break;
1706d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_SHA1:
1716d49e1aeSJan Lentfer 		if (sha1_init(&ctx->u.md) != CRYPT_OK)
1726d49e1aeSJan Lentfer 			goto fail;
1736d49e1aeSJan Lentfer 		break;
1746d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_MD5:
1756d49e1aeSJan Lentfer 		if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
1766d49e1aeSJan Lentfer 		    CRYPT_OK)
1776d49e1aeSJan Lentfer 			goto fail;
1786d49e1aeSJan Lentfer 		break;
1796d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_SHA1:
1806d49e1aeSJan Lentfer 		if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
1816d49e1aeSJan Lentfer 		    CRYPT_OK)
1826d49e1aeSJan Lentfer 			goto fail;
1836d49e1aeSJan Lentfer 		break;
1846d49e1aeSJan Lentfer 	default:
1856d49e1aeSJan Lentfer 		goto fail;
1866d49e1aeSJan Lentfer 	}
1876d49e1aeSJan Lentfer 
1886d49e1aeSJan Lentfer 	return ctx;
1896d49e1aeSJan Lentfer 
1906d49e1aeSJan Lentfer fail:
1916d49e1aeSJan Lentfer 	os_free(ctx);
1926d49e1aeSJan Lentfer 	return NULL;
1936d49e1aeSJan Lentfer }
1946d49e1aeSJan Lentfer 
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)1956d49e1aeSJan Lentfer void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
1966d49e1aeSJan Lentfer {
1976d49e1aeSJan Lentfer 	if (ctx == NULL || ctx->error)
1986d49e1aeSJan Lentfer 		return;
1996d49e1aeSJan Lentfer 
2006d49e1aeSJan Lentfer 	switch (ctx->alg) {
2016d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_MD5:
2026d49e1aeSJan Lentfer 		ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
2036d49e1aeSJan Lentfer 		break;
2046d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_SHA1:
2056d49e1aeSJan Lentfer 		ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
2066d49e1aeSJan Lentfer 		break;
2076d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_MD5:
2086d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_SHA1:
2096d49e1aeSJan Lentfer 		ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
2106d49e1aeSJan Lentfer 		break;
2116d49e1aeSJan Lentfer 	}
2126d49e1aeSJan Lentfer }
2136d49e1aeSJan Lentfer 
2146d49e1aeSJan Lentfer 
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)2156d49e1aeSJan Lentfer int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
2166d49e1aeSJan Lentfer {
2176d49e1aeSJan Lentfer 	int ret = 0;
2186d49e1aeSJan Lentfer 	unsigned long clen;
2196d49e1aeSJan Lentfer 
2206d49e1aeSJan Lentfer 	if (ctx == NULL)
2216d49e1aeSJan Lentfer 		return -2;
2226d49e1aeSJan Lentfer 
2236d49e1aeSJan Lentfer 	if (mac == NULL || len == NULL) {
2246d49e1aeSJan Lentfer 		os_free(ctx);
2256d49e1aeSJan Lentfer 		return 0;
2266d49e1aeSJan Lentfer 	}
2276d49e1aeSJan Lentfer 
2286d49e1aeSJan Lentfer 	if (ctx->error) {
2296d49e1aeSJan Lentfer 		os_free(ctx);
2306d49e1aeSJan Lentfer 		return -2;
2316d49e1aeSJan Lentfer 	}
2326d49e1aeSJan Lentfer 
2336d49e1aeSJan Lentfer 	switch (ctx->alg) {
2346d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_MD5:
2356d49e1aeSJan Lentfer 		if (*len < 16) {
2366d49e1aeSJan Lentfer 			*len = 16;
2376d49e1aeSJan Lentfer 			os_free(ctx);
2386d49e1aeSJan Lentfer 			return -1;
2396d49e1aeSJan Lentfer 		}
2406d49e1aeSJan Lentfer 		*len = 16;
2416d49e1aeSJan Lentfer 		if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
2426d49e1aeSJan Lentfer 			ret = -2;
2436d49e1aeSJan Lentfer 		break;
2446d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_SHA1:
2456d49e1aeSJan Lentfer 		if (*len < 20) {
2466d49e1aeSJan Lentfer 			*len = 20;
2476d49e1aeSJan Lentfer 			os_free(ctx);
2486d49e1aeSJan Lentfer 			return -1;
2496d49e1aeSJan Lentfer 		}
2506d49e1aeSJan Lentfer 		*len = 20;
2516d49e1aeSJan Lentfer 		if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
2526d49e1aeSJan Lentfer 			ret = -2;
2536d49e1aeSJan Lentfer 		break;
2546d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_SHA1:
2556d49e1aeSJan Lentfer 		if (*len < 20) {
2566d49e1aeSJan Lentfer 			*len = 20;
2576d49e1aeSJan Lentfer 			os_free(ctx);
2586d49e1aeSJan Lentfer 			return -1;
2596d49e1aeSJan Lentfer 		}
2606d49e1aeSJan Lentfer 		/* continue */
2616d49e1aeSJan Lentfer 	case CRYPTO_HASH_ALG_HMAC_MD5:
2626d49e1aeSJan Lentfer 		if (*len < 16) {
2636d49e1aeSJan Lentfer 			*len = 16;
2646d49e1aeSJan Lentfer 			os_free(ctx);
2656d49e1aeSJan Lentfer 			return -1;
2666d49e1aeSJan Lentfer 		}
2676d49e1aeSJan Lentfer 		clen = *len;
2686d49e1aeSJan Lentfer 		if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
2696d49e1aeSJan Lentfer 			os_free(ctx);
2706d49e1aeSJan Lentfer 			return -1;
2716d49e1aeSJan Lentfer 		}
2726d49e1aeSJan Lentfer 		*len = clen;
2736d49e1aeSJan Lentfer 		break;
2746d49e1aeSJan Lentfer 	default:
2756d49e1aeSJan Lentfer 		ret = -2;
2766d49e1aeSJan Lentfer 		break;
2776d49e1aeSJan Lentfer 	}
2786d49e1aeSJan Lentfer 
2796d49e1aeSJan Lentfer 	os_free(ctx);
2806d49e1aeSJan Lentfer 
281*a1157835SDaniel Fojt 	if (TEST_FAIL())
282*a1157835SDaniel Fojt 		return -1;
283*a1157835SDaniel Fojt 
2846d49e1aeSJan Lentfer 	return ret;
2856d49e1aeSJan Lentfer }
2866d49e1aeSJan Lentfer 
2876d49e1aeSJan Lentfer 
2886d49e1aeSJan Lentfer struct crypto_cipher {
2896d49e1aeSJan Lentfer 	int rc4;
2906d49e1aeSJan Lentfer 	union {
2916d49e1aeSJan Lentfer 		symmetric_CBC cbc;
2926d49e1aeSJan Lentfer 		struct {
2936d49e1aeSJan Lentfer 			size_t used_bytes;
2946d49e1aeSJan Lentfer 			u8 key[16];
2956d49e1aeSJan Lentfer 			size_t keylen;
2966d49e1aeSJan Lentfer 		} rc4;
2976d49e1aeSJan Lentfer 	} u;
2986d49e1aeSJan Lentfer };
2996d49e1aeSJan Lentfer 
3006d49e1aeSJan Lentfer 
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)3016d49e1aeSJan Lentfer struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
3026d49e1aeSJan Lentfer 					  const u8 *iv, const u8 *key,
3036d49e1aeSJan Lentfer 					  size_t key_len)
3046d49e1aeSJan Lentfer {
3056d49e1aeSJan Lentfer 	struct crypto_cipher *ctx;
3066d49e1aeSJan Lentfer 	int idx, res, rc4 = 0;
3076d49e1aeSJan Lentfer 
3086d49e1aeSJan Lentfer 	switch (alg) {
3096d49e1aeSJan Lentfer 	case CRYPTO_CIPHER_ALG_AES:
3106d49e1aeSJan Lentfer 		idx = find_cipher("aes");
3116d49e1aeSJan Lentfer 		break;
3126d49e1aeSJan Lentfer 	case CRYPTO_CIPHER_ALG_3DES:
3136d49e1aeSJan Lentfer 		idx = find_cipher("3des");
3146d49e1aeSJan Lentfer 		break;
3156d49e1aeSJan Lentfer 	case CRYPTO_CIPHER_ALG_DES:
3166d49e1aeSJan Lentfer 		idx = find_cipher("des");
3176d49e1aeSJan Lentfer 		break;
3186d49e1aeSJan Lentfer 	case CRYPTO_CIPHER_ALG_RC2:
3196d49e1aeSJan Lentfer 		idx = find_cipher("rc2");
3206d49e1aeSJan Lentfer 		break;
3216d49e1aeSJan Lentfer 	case CRYPTO_CIPHER_ALG_RC4:
3226d49e1aeSJan Lentfer 		idx = -1;
3236d49e1aeSJan Lentfer 		rc4 = 1;
3246d49e1aeSJan Lentfer 		break;
3256d49e1aeSJan Lentfer 	default:
3266d49e1aeSJan Lentfer 		return NULL;
3276d49e1aeSJan Lentfer 	}
3286d49e1aeSJan Lentfer 
3296d49e1aeSJan Lentfer 	ctx = os_zalloc(sizeof(*ctx));
3306d49e1aeSJan Lentfer 	if (ctx == NULL)
3316d49e1aeSJan Lentfer 		return NULL;
3326d49e1aeSJan Lentfer 
3336d49e1aeSJan Lentfer 	if (rc4) {
3346d49e1aeSJan Lentfer 		ctx->rc4 = 1;
3356d49e1aeSJan Lentfer 		if (key_len > sizeof(ctx->u.rc4.key)) {
3366d49e1aeSJan Lentfer 			os_free(ctx);
3376d49e1aeSJan Lentfer 			return NULL;
3386d49e1aeSJan Lentfer 		}
3396d49e1aeSJan Lentfer 		ctx->u.rc4.keylen = key_len;
3406d49e1aeSJan Lentfer 		os_memcpy(ctx->u.rc4.key, key, key_len);
3416d49e1aeSJan Lentfer 	} else {
3426d49e1aeSJan Lentfer 		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
3436d49e1aeSJan Lentfer 		if (res != CRYPT_OK) {
3446d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
3456d49e1aeSJan Lentfer 				   "failed: %s", error_to_string(res));
3466d49e1aeSJan Lentfer 			os_free(ctx);
3476d49e1aeSJan Lentfer 			return NULL;
3486d49e1aeSJan Lentfer 		}
3496d49e1aeSJan Lentfer 	}
3506d49e1aeSJan Lentfer 
3516d49e1aeSJan Lentfer 	return ctx;
3526d49e1aeSJan Lentfer }
3536d49e1aeSJan Lentfer 
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)3546d49e1aeSJan Lentfer int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
3556d49e1aeSJan Lentfer 			  u8 *crypt, size_t len)
3566d49e1aeSJan Lentfer {
3576d49e1aeSJan Lentfer 	int res;
3586d49e1aeSJan Lentfer 
3596d49e1aeSJan Lentfer 	if (ctx->rc4) {
3606d49e1aeSJan Lentfer 		if (plain != crypt)
3616d49e1aeSJan Lentfer 			os_memcpy(crypt, plain, len);
3626d49e1aeSJan Lentfer 		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
3636d49e1aeSJan Lentfer 			 ctx->u.rc4.used_bytes, crypt, len);
3646d49e1aeSJan Lentfer 		ctx->u.rc4.used_bytes += len;
3656d49e1aeSJan Lentfer 		return 0;
3666d49e1aeSJan Lentfer 	}
3676d49e1aeSJan Lentfer 
3686d49e1aeSJan Lentfer 	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
3696d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
3706d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
3716d49e1aeSJan Lentfer 			   "failed: %s", error_to_string(res));
3726d49e1aeSJan Lentfer 		return -1;
3736d49e1aeSJan Lentfer 	}
3746d49e1aeSJan Lentfer 	return 0;
3756d49e1aeSJan Lentfer }
3766d49e1aeSJan Lentfer 
3776d49e1aeSJan Lentfer 
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)3786d49e1aeSJan Lentfer int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
3796d49e1aeSJan Lentfer 			  u8 *plain, size_t len)
3806d49e1aeSJan Lentfer {
3816d49e1aeSJan Lentfer 	int res;
3826d49e1aeSJan Lentfer 
3836d49e1aeSJan Lentfer 	if (ctx->rc4) {
3846d49e1aeSJan Lentfer 		if (plain != crypt)
3856d49e1aeSJan Lentfer 			os_memcpy(plain, crypt, len);
3866d49e1aeSJan Lentfer 		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
3876d49e1aeSJan Lentfer 			 ctx->u.rc4.used_bytes, plain, len);
3886d49e1aeSJan Lentfer 		ctx->u.rc4.used_bytes += len;
3896d49e1aeSJan Lentfer 		return 0;
3906d49e1aeSJan Lentfer 	}
3916d49e1aeSJan Lentfer 
3926d49e1aeSJan Lentfer 	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
3936d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
3946d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
3956d49e1aeSJan Lentfer 			   "failed: %s", error_to_string(res));
3966d49e1aeSJan Lentfer 		return -1;
3976d49e1aeSJan Lentfer 	}
3986d49e1aeSJan Lentfer 
3996d49e1aeSJan Lentfer 	return 0;
4006d49e1aeSJan Lentfer }
4016d49e1aeSJan Lentfer 
4026d49e1aeSJan Lentfer 
crypto_cipher_deinit(struct crypto_cipher * ctx)4036d49e1aeSJan Lentfer void crypto_cipher_deinit(struct crypto_cipher *ctx)
4046d49e1aeSJan Lentfer {
4056d49e1aeSJan Lentfer 	if (!ctx->rc4)
4066d49e1aeSJan Lentfer 		cbc_done(&ctx->u.cbc);
4076d49e1aeSJan Lentfer 	os_free(ctx);
4086d49e1aeSJan Lentfer }
4096d49e1aeSJan Lentfer 
4106d49e1aeSJan Lentfer 
4116d49e1aeSJan Lentfer struct crypto_public_key {
4126d49e1aeSJan Lentfer 	rsa_key rsa;
4136d49e1aeSJan Lentfer };
4146d49e1aeSJan Lentfer 
4156d49e1aeSJan Lentfer struct crypto_private_key {
4166d49e1aeSJan Lentfer 	rsa_key rsa;
4176d49e1aeSJan Lentfer };
4186d49e1aeSJan Lentfer 
4196d49e1aeSJan Lentfer 
crypto_public_key_import(const u8 * key,size_t len)4206d49e1aeSJan Lentfer struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
4216d49e1aeSJan Lentfer {
4226d49e1aeSJan Lentfer 	int res;
4236d49e1aeSJan Lentfer 	struct crypto_public_key *pk;
4246d49e1aeSJan Lentfer 
4256d49e1aeSJan Lentfer 	pk = os_zalloc(sizeof(*pk));
4266d49e1aeSJan Lentfer 	if (pk == NULL)
4276d49e1aeSJan Lentfer 		return NULL;
4286d49e1aeSJan Lentfer 
4296d49e1aeSJan Lentfer 	res = rsa_import(key, len, &pk->rsa);
4306d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
4316d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
4326d49e1aeSJan Lentfer 			   "public key (res=%d '%s')",
4336d49e1aeSJan Lentfer 			   res, error_to_string(res));
4346d49e1aeSJan Lentfer 		os_free(pk);
4356d49e1aeSJan Lentfer 		return NULL;
4366d49e1aeSJan Lentfer 	}
4376d49e1aeSJan Lentfer 
4386d49e1aeSJan Lentfer 	if (pk->rsa.type != PK_PUBLIC) {
4396d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
4406d49e1aeSJan Lentfer 			   "correct type");
4416d49e1aeSJan Lentfer 		rsa_free(&pk->rsa);
4426d49e1aeSJan Lentfer 		os_free(pk);
4436d49e1aeSJan Lentfer 		return NULL;
4446d49e1aeSJan Lentfer 	}
4456d49e1aeSJan Lentfer 
4466d49e1aeSJan Lentfer 	return pk;
4476d49e1aeSJan Lentfer }
4486d49e1aeSJan Lentfer 
4496d49e1aeSJan Lentfer 
crypto_private_key_import(const u8 * key,size_t len,const char * passwd)4506d49e1aeSJan Lentfer struct crypto_private_key * crypto_private_key_import(const u8 *key,
4513ff40c12SJohn Marino 						      size_t len,
4523ff40c12SJohn Marino 						      const char *passwd)
4536d49e1aeSJan Lentfer {
4546d49e1aeSJan Lentfer 	int res;
4556d49e1aeSJan Lentfer 	struct crypto_private_key *pk;
4566d49e1aeSJan Lentfer 
4576d49e1aeSJan Lentfer 	pk = os_zalloc(sizeof(*pk));
4586d49e1aeSJan Lentfer 	if (pk == NULL)
4596d49e1aeSJan Lentfer 		return NULL;
4606d49e1aeSJan Lentfer 
4616d49e1aeSJan Lentfer 	res = rsa_import(key, len, &pk->rsa);
4626d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
4636d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
4646d49e1aeSJan Lentfer 			   "private key (res=%d '%s')",
4656d49e1aeSJan Lentfer 			   res, error_to_string(res));
4666d49e1aeSJan Lentfer 		os_free(pk);
4676d49e1aeSJan Lentfer 		return NULL;
4686d49e1aeSJan Lentfer 	}
4696d49e1aeSJan Lentfer 
4706d49e1aeSJan Lentfer 	if (pk->rsa.type != PK_PRIVATE) {
4716d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
4726d49e1aeSJan Lentfer 			   "correct type");
4736d49e1aeSJan Lentfer 		rsa_free(&pk->rsa);
4746d49e1aeSJan Lentfer 		os_free(pk);
4756d49e1aeSJan Lentfer 		return NULL;
4766d49e1aeSJan Lentfer 	}
4776d49e1aeSJan Lentfer 
4786d49e1aeSJan Lentfer 	return pk;
4796d49e1aeSJan Lentfer }
4806d49e1aeSJan Lentfer 
4816d49e1aeSJan Lentfer 
crypto_public_key_from_cert(const u8 * buf,size_t len)4826d49e1aeSJan Lentfer struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
4836d49e1aeSJan Lentfer 						       size_t len)
4846d49e1aeSJan Lentfer {
4856d49e1aeSJan Lentfer 	/* No X.509 support in LibTomCrypt */
4866d49e1aeSJan Lentfer 	return NULL;
4876d49e1aeSJan Lentfer }
4886d49e1aeSJan Lentfer 
4896d49e1aeSJan Lentfer 
pkcs1_generate_encryption_block(u8 block_type,size_t modlen,const u8 * in,size_t inlen,u8 * out,size_t * outlen)4906d49e1aeSJan Lentfer static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
4916d49e1aeSJan Lentfer 					   const u8 *in, size_t inlen,
4926d49e1aeSJan Lentfer 					   u8 *out, size_t *outlen)
4936d49e1aeSJan Lentfer {
4946d49e1aeSJan Lentfer 	size_t ps_len;
4956d49e1aeSJan Lentfer 	u8 *pos;
4966d49e1aeSJan Lentfer 
4976d49e1aeSJan Lentfer 	/*
4986d49e1aeSJan Lentfer 	 * PKCS #1 v1.5, 8.1:
4996d49e1aeSJan Lentfer 	 *
5006d49e1aeSJan Lentfer 	 * EB = 00 || BT || PS || 00 || D
5016d49e1aeSJan Lentfer 	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
5026d49e1aeSJan Lentfer 	 * PS = k-3-||D||; at least eight octets
5036d49e1aeSJan Lentfer 	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
5046d49e1aeSJan Lentfer 	 * k = length of modulus in octets (modlen)
5056d49e1aeSJan Lentfer 	 */
5066d49e1aeSJan Lentfer 
5076d49e1aeSJan Lentfer 	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
5086d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
5096d49e1aeSJan Lentfer 			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
5106d49e1aeSJan Lentfer 			   __func__, (unsigned long) modlen,
5116d49e1aeSJan Lentfer 			   (unsigned long) *outlen,
5126d49e1aeSJan Lentfer 			   (unsigned long) inlen);
5136d49e1aeSJan Lentfer 		return -1;
5146d49e1aeSJan Lentfer 	}
5156d49e1aeSJan Lentfer 
5166d49e1aeSJan Lentfer 	pos = out;
5176d49e1aeSJan Lentfer 	*pos++ = 0x00;
5186d49e1aeSJan Lentfer 	*pos++ = block_type; /* BT */
5196d49e1aeSJan Lentfer 	ps_len = modlen - inlen - 3;
5206d49e1aeSJan Lentfer 	switch (block_type) {
5216d49e1aeSJan Lentfer 	case 0:
5226d49e1aeSJan Lentfer 		os_memset(pos, 0x00, ps_len);
5236d49e1aeSJan Lentfer 		pos += ps_len;
5246d49e1aeSJan Lentfer 		break;
5256d49e1aeSJan Lentfer 	case 1:
5266d49e1aeSJan Lentfer 		os_memset(pos, 0xff, ps_len);
5276d49e1aeSJan Lentfer 		pos += ps_len;
5286d49e1aeSJan Lentfer 		break;
5296d49e1aeSJan Lentfer 	case 2:
5306d49e1aeSJan Lentfer 		if (os_get_random(pos, ps_len) < 0) {
5316d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
5326d49e1aeSJan Lentfer 				   "random data for PS", __func__);
5336d49e1aeSJan Lentfer 			return -1;
5346d49e1aeSJan Lentfer 		}
5356d49e1aeSJan Lentfer 		while (ps_len--) {
5366d49e1aeSJan Lentfer 			if (*pos == 0x00)
5376d49e1aeSJan Lentfer 				*pos = 0x01;
5386d49e1aeSJan Lentfer 			pos++;
5396d49e1aeSJan Lentfer 		}
5406d49e1aeSJan Lentfer 		break;
5416d49e1aeSJan Lentfer 	default:
5426d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
5436d49e1aeSJan Lentfer 			   "%d", __func__, block_type);
5446d49e1aeSJan Lentfer 		return -1;
5456d49e1aeSJan Lentfer 	}
5466d49e1aeSJan Lentfer 	*pos++ = 0x00;
5476d49e1aeSJan Lentfer 	os_memcpy(pos, in, inlen); /* D */
5486d49e1aeSJan Lentfer 
5496d49e1aeSJan Lentfer 	return 0;
5506d49e1aeSJan Lentfer }
5516d49e1aeSJan Lentfer 
5526d49e1aeSJan Lentfer 
crypto_rsa_encrypt_pkcs1(int block_type,rsa_key * key,int key_type,const u8 * in,size_t inlen,u8 * out,size_t * outlen)5536d49e1aeSJan Lentfer static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
5546d49e1aeSJan Lentfer 				    const u8 *in, size_t inlen,
5556d49e1aeSJan Lentfer 				    u8 *out, size_t *outlen)
5566d49e1aeSJan Lentfer {
5576d49e1aeSJan Lentfer 	unsigned long len, modlen;
5586d49e1aeSJan Lentfer 	int res;
5596d49e1aeSJan Lentfer 
5606d49e1aeSJan Lentfer 	modlen = mp_unsigned_bin_size(key->N);
5616d49e1aeSJan Lentfer 
5626d49e1aeSJan Lentfer 	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
5636d49e1aeSJan Lentfer 					    out, outlen) < 0)
5646d49e1aeSJan Lentfer 		return -1;
5656d49e1aeSJan Lentfer 
5666d49e1aeSJan Lentfer 	len = *outlen;
5676d49e1aeSJan Lentfer 	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
5686d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
5696d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
5706d49e1aeSJan Lentfer 			   error_to_string(res));
5716d49e1aeSJan Lentfer 		return -1;
5726d49e1aeSJan Lentfer 	}
5736d49e1aeSJan Lentfer 	*outlen = len;
5746d49e1aeSJan Lentfer 
5756d49e1aeSJan Lentfer 	return 0;
5766d49e1aeSJan Lentfer }
5776d49e1aeSJan Lentfer 
5786d49e1aeSJan Lentfer 
crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)5796d49e1aeSJan Lentfer int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
5806d49e1aeSJan Lentfer 					const u8 *in, size_t inlen,
5816d49e1aeSJan Lentfer 					u8 *out, size_t *outlen)
5826d49e1aeSJan Lentfer {
5836d49e1aeSJan Lentfer 	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
5846d49e1aeSJan Lentfer 					out, outlen);
5856d49e1aeSJan Lentfer }
5866d49e1aeSJan Lentfer 
5876d49e1aeSJan Lentfer 
crypto_private_key_sign_pkcs1(struct crypto_private_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)5886d49e1aeSJan Lentfer int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
5896d49e1aeSJan Lentfer 				  const u8 *in, size_t inlen,
5906d49e1aeSJan Lentfer 				  u8 *out, size_t *outlen)
5916d49e1aeSJan Lentfer {
5926d49e1aeSJan Lentfer 	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
5936d49e1aeSJan Lentfer 					out, outlen);
5946d49e1aeSJan Lentfer }
5956d49e1aeSJan Lentfer 
5966d49e1aeSJan Lentfer 
crypto_public_key_free(struct crypto_public_key * key)5976d49e1aeSJan Lentfer void crypto_public_key_free(struct crypto_public_key *key)
5986d49e1aeSJan Lentfer {
5996d49e1aeSJan Lentfer 	if (key) {
6006d49e1aeSJan Lentfer 		rsa_free(&key->rsa);
6016d49e1aeSJan Lentfer 		os_free(key);
6026d49e1aeSJan Lentfer 	}
6036d49e1aeSJan Lentfer }
6046d49e1aeSJan Lentfer 
6056d49e1aeSJan Lentfer 
crypto_private_key_free(struct crypto_private_key * key)6066d49e1aeSJan Lentfer void crypto_private_key_free(struct crypto_private_key *key)
6076d49e1aeSJan Lentfer {
6086d49e1aeSJan Lentfer 	if (key) {
6096d49e1aeSJan Lentfer 		rsa_free(&key->rsa);
6106d49e1aeSJan Lentfer 		os_free(key);
6116d49e1aeSJan Lentfer 	}
6126d49e1aeSJan Lentfer }
6136d49e1aeSJan Lentfer 
6146d49e1aeSJan Lentfer 
crypto_public_key_decrypt_pkcs1(struct crypto_public_key * key,const u8 * crypt,size_t crypt_len,u8 * plain,size_t * plain_len)6156d49e1aeSJan Lentfer int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
6166d49e1aeSJan Lentfer 				    const u8 *crypt, size_t crypt_len,
6176d49e1aeSJan Lentfer 				    u8 *plain, size_t *plain_len)
6186d49e1aeSJan Lentfer {
6196d49e1aeSJan Lentfer 	int res;
6206d49e1aeSJan Lentfer 	unsigned long len;
6216d49e1aeSJan Lentfer 	u8 *pos;
6226d49e1aeSJan Lentfer 
6236d49e1aeSJan Lentfer 	len = *plain_len;
6246d49e1aeSJan Lentfer 	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
6256d49e1aeSJan Lentfer 			  &key->rsa);
6266d49e1aeSJan Lentfer 	if (res != CRYPT_OK) {
6276d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
6286d49e1aeSJan Lentfer 			   error_to_string(res));
6296d49e1aeSJan Lentfer 		return -1;
6306d49e1aeSJan Lentfer 	}
6316d49e1aeSJan Lentfer 
6326d49e1aeSJan Lentfer 	/*
6336d49e1aeSJan Lentfer 	 * PKCS #1 v1.5, 8.1:
6346d49e1aeSJan Lentfer 	 *
6356d49e1aeSJan Lentfer 	 * EB = 00 || BT || PS || 00 || D
6366d49e1aeSJan Lentfer 	 * BT = 01
6376d49e1aeSJan Lentfer 	 * PS = k-3-||D|| times FF
6386d49e1aeSJan Lentfer 	 * k = length of modulus in octets
6396d49e1aeSJan Lentfer 	 */
6406d49e1aeSJan Lentfer 
6416d49e1aeSJan Lentfer 	if (len < 3 + 8 + 16 /* min hash len */ ||
6426d49e1aeSJan Lentfer 	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
6436d49e1aeSJan Lentfer 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
6446d49e1aeSJan Lentfer 			   "structure");
6456d49e1aeSJan Lentfer 		return -1;
6466d49e1aeSJan Lentfer 	}
6476d49e1aeSJan Lentfer 
6486d49e1aeSJan Lentfer 	pos = plain + 3;
6496d49e1aeSJan Lentfer 	while (pos < plain + len && *pos == 0xff)
6506d49e1aeSJan Lentfer 		pos++;
6516d49e1aeSJan Lentfer 	if (pos - plain - 2 < 8) {
6526d49e1aeSJan Lentfer 		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
6536d49e1aeSJan Lentfer 		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
6546d49e1aeSJan Lentfer 			   "padding");
6556d49e1aeSJan Lentfer 		return -1;
6566d49e1aeSJan Lentfer 	}
6576d49e1aeSJan Lentfer 
6586d49e1aeSJan Lentfer 	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
6596d49e1aeSJan Lentfer 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
6606d49e1aeSJan Lentfer 			   "structure (2)");
6616d49e1aeSJan Lentfer 		return -1;
6626d49e1aeSJan Lentfer 	}
6636d49e1aeSJan Lentfer 	pos++;
6646d49e1aeSJan Lentfer 	len -= pos - plain;
6656d49e1aeSJan Lentfer 
6666d49e1aeSJan Lentfer 	/* Strip PKCS #1 header */
6676d49e1aeSJan Lentfer 	os_memmove(plain, pos, len);
6686d49e1aeSJan Lentfer 	*plain_len = len;
6696d49e1aeSJan Lentfer 
6706d49e1aeSJan Lentfer 	return 0;
6716d49e1aeSJan Lentfer }
6726d49e1aeSJan Lentfer 
6736d49e1aeSJan Lentfer 
crypto_global_init(void)6746d49e1aeSJan Lentfer int crypto_global_init(void)
6756d49e1aeSJan Lentfer {
6766d49e1aeSJan Lentfer 	ltc_mp = tfm_desc;
6776d49e1aeSJan Lentfer 	/* TODO: only register algorithms that are really needed */
6786d49e1aeSJan Lentfer 	if (register_hash(&md4_desc) < 0 ||
6796d49e1aeSJan Lentfer 	    register_hash(&md5_desc) < 0 ||
6806d49e1aeSJan Lentfer 	    register_hash(&sha1_desc) < 0 ||
6816d49e1aeSJan Lentfer 	    register_cipher(&aes_desc) < 0 ||
6826d49e1aeSJan Lentfer 	    register_cipher(&des_desc) < 0 ||
6836d49e1aeSJan Lentfer 	    register_cipher(&des3_desc) < 0) {
6846d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
6856d49e1aeSJan Lentfer 			   "hash/cipher functions");
6866d49e1aeSJan Lentfer 		return -1;
6876d49e1aeSJan Lentfer 	}
6886d49e1aeSJan Lentfer 
6896d49e1aeSJan Lentfer 	return 0;
6906d49e1aeSJan Lentfer }
6916d49e1aeSJan Lentfer 
6926d49e1aeSJan Lentfer 
crypto_global_deinit(void)6936d49e1aeSJan Lentfer void crypto_global_deinit(void)
6946d49e1aeSJan Lentfer {
6956d49e1aeSJan Lentfer }
6966d49e1aeSJan Lentfer 
6976d49e1aeSJan Lentfer 
6983ff40c12SJohn Marino #ifdef CONFIG_MODEXP
6996d49e1aeSJan Lentfer 
crypto_dh_init(u8 generator,const u8 * prime,size_t prime_len,u8 * privkey,u8 * pubkey)700*a1157835SDaniel Fojt int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
701*a1157835SDaniel Fojt 		   u8 *pubkey)
702*a1157835SDaniel Fojt {
703*a1157835SDaniel Fojt 	size_t pubkey_len, pad;
704*a1157835SDaniel Fojt 
705*a1157835SDaniel Fojt 	if (os_get_random(privkey, prime_len) < 0)
706*a1157835SDaniel Fojt 		return -1;
707*a1157835SDaniel Fojt 	if (os_memcmp(privkey, prime, prime_len) > 0) {
708*a1157835SDaniel Fojt 		/* Make sure private value is smaller than prime */
709*a1157835SDaniel Fojt 		privkey[0] = 0;
710*a1157835SDaniel Fojt 	}
711*a1157835SDaniel Fojt 
712*a1157835SDaniel Fojt 	pubkey_len = prime_len;
713*a1157835SDaniel Fojt 	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
714*a1157835SDaniel Fojt 			   pubkey, &pubkey_len) < 0)
715*a1157835SDaniel Fojt 		return -1;
716*a1157835SDaniel Fojt 	if (pubkey_len < prime_len) {
717*a1157835SDaniel Fojt 		pad = prime_len - pubkey_len;
718*a1157835SDaniel Fojt 		os_memmove(pubkey + pad, pubkey, pubkey_len);
719*a1157835SDaniel Fojt 		os_memset(pubkey, 0, pad);
720*a1157835SDaniel Fojt 	}
721*a1157835SDaniel Fojt 
722*a1157835SDaniel Fojt 	return 0;
723*a1157835SDaniel Fojt }
724*a1157835SDaniel Fojt 
725*a1157835SDaniel Fojt 
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)726*a1157835SDaniel Fojt int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
727*a1157835SDaniel Fojt 			    const u8 *order, size_t order_len,
728*a1157835SDaniel Fojt 			    const u8 *privkey, size_t privkey_len,
729*a1157835SDaniel Fojt 			    const u8 *pubkey, size_t pubkey_len,
730*a1157835SDaniel Fojt 			    u8 *secret, size_t *len)
731*a1157835SDaniel Fojt {
732*a1157835SDaniel Fojt 	/* TODO: check pubkey */
733*a1157835SDaniel Fojt 	return crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
734*a1157835SDaniel Fojt 			      prime, prime_len, secret, len);
735*a1157835SDaniel Fojt }
736*a1157835SDaniel Fojt 
737*a1157835SDaniel Fojt 
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)7386d49e1aeSJan Lentfer int crypto_mod_exp(const u8 *base, size_t base_len,
7396d49e1aeSJan Lentfer 		   const u8 *power, size_t power_len,
7406d49e1aeSJan Lentfer 		   const u8 *modulus, size_t modulus_len,
7416d49e1aeSJan Lentfer 		   u8 *result, size_t *result_len)
7426d49e1aeSJan Lentfer {
7436d49e1aeSJan Lentfer 	void *b, *p, *m, *r;
7446d49e1aeSJan Lentfer 
7456d49e1aeSJan Lentfer 	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
7466d49e1aeSJan Lentfer 		return -1;
7476d49e1aeSJan Lentfer 
7486d49e1aeSJan Lentfer 	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
7496d49e1aeSJan Lentfer 	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
7506d49e1aeSJan Lentfer 	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
7516d49e1aeSJan Lentfer 		goto fail;
7526d49e1aeSJan Lentfer 
7536d49e1aeSJan Lentfer 	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
7546d49e1aeSJan Lentfer 		goto fail;
7556d49e1aeSJan Lentfer 
7566d49e1aeSJan Lentfer 	*result_len = mp_unsigned_bin_size(r);
7576d49e1aeSJan Lentfer 	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
7586d49e1aeSJan Lentfer 		goto fail;
7596d49e1aeSJan Lentfer 
7606d49e1aeSJan Lentfer 	mp_clear_multi(b, p, m, r, NULL);
7616d49e1aeSJan Lentfer 	return 0;
7626d49e1aeSJan Lentfer 
7636d49e1aeSJan Lentfer fail:
7646d49e1aeSJan Lentfer 	mp_clear_multi(b, p, m, r, NULL);
7656d49e1aeSJan Lentfer 	return -1;
7666d49e1aeSJan Lentfer }
7676d49e1aeSJan Lentfer 
7683ff40c12SJohn Marino #endif /* CONFIG_MODEXP */
769