18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <tomcrypt.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef mp_init_multi
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_init_multi                ltc_init_multi
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_clear_multi               ltc_deinit_multi
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_unsigned_bin_size(a)      ltc_mp.unsigned_size(a)
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_to_unsigned_bin(a, b)     ltc_mp.unsigned_write(a, b)
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define mp_exptmod(a,b,c,d)          ltc_mp.exptmod(a,b,c,d)
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash_state md;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md4_init(&md);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md4_process(&md, addr[i], len[i]);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md4_done(&md, mac);
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pkey[8], next, tmp;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key skey;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Add parity bits to the key */
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	next = 0;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 7; i++) {
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = key[i];
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pkey[i] = (tmp >> i) | next | 1;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = tmp << (7 - i);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pkey[i] = next | 1;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_setup(pkey, 8, 0, &skey);
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_ecb_encrypt(clear, cypher, &skey);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_done(&skey);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash_state md;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md5_init(&md);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md5_process(&md, addr[i], len[i]);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md5_done(&md, mac);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash_state md;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha1_init(&md);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sha1_process(&md, addr[i], len[i]);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha1_done(&md, mac);
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_encrypt_init(const u8 *key, size_t len)
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	skey = os_malloc(sizeof(*skey));
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (skey == NULL)
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(skey);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return skey;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey = ctx;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_ecb_encrypt(plain, crypt, skey);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt_deinit(void *ctx)
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey = ctx;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_done(skey);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(skey);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_decrypt_init(const u8 *key, size_t len)
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	skey = os_malloc(sizeof(*skey));
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (skey == NULL)
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(skey);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return skey;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey = ctx;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_ecb_encrypt(plain, (u8 *) crypt, skey);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt_deinit(void *ctx)
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	symmetric_key *skey = ctx;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_done(skey);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(skey);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash {
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum crypto_hash_alg alg;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int error;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union {
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hash_state md;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hmac_state hmac;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} u;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t key_len)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_hash *ctx;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->alg = alg;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (md5_init(&ctx->u.md) != CRYPT_OK)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sha1_init(&ctx->u.md) != CRYPT_OK)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    CRYPT_OK)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    CRYPT_OK)
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL || ctx->error)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (ctx->alg) {
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long clen;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mac == NULL || len == NULL) {
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx->error) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (ctx->alg) {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 16) {
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*len = 16;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 16;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -2;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 20) {
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*len = 20;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 20;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -2;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 20) {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*len = 20;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* continue */
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 16) {
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*len = 16;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clen = *len;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = clen;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -2;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher {
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rc4;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		symmetric_CBC cbc;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t used_bytes;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 key[16];
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t keylen;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} rc4;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} u;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *iv, const u8 *key,
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t key_len)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_cipher *ctx;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int idx, res, rc4 = 0;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx = find_cipher("aes");
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx = find_cipher("3des");
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_DES:
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx = find_cipher("des");
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC2:
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx = find_cipher("rc2");
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx = -1;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rc4 = 1;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rc4) {
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->rc4 = 1;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_len > sizeof(ctx->u.rc4.key)) {
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->u.rc4.keylen = key_len;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ctx->u.rc4.key, key, key_len);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res != CRYPT_OK) {
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %s", error_to_string(res));
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *crypt, size_t len)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx->rc4) {
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (plain != crypt)
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(crypt, plain, len);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ctx->u.rc4.used_bytes, crypt, len);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->u.rc4.used_bytes += len;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %s", error_to_string(res));
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *plain, size_t len)
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx->rc4) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (plain != crypt)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(plain, crypt, len);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ctx->u.rc4.used_bytes, plain, len);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->u.rc4.used_bytes += len;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %s", error_to_string(res));
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ctx->rc4)
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cbc_done(&ctx->u.cbc);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key {
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_key rsa;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_private_key {
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsa_key rsa;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_public_key *pk;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pk = os_zalloc(sizeof(*pk));
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pk == NULL)
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = rsa_import(key, len, &pk->rsa);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "public key (res=%d '%s')",
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   res, error_to_string(res));
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pk->rsa.type != PK_PUBLIC) {
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "correct type");
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa_free(&pk->rsa);
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pk;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_private_key * crypto_private_key_import(const u8 *key,
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      size_t len,
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      const char *passwd)
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_private_key *pk;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pk = os_zalloc(sizeof(*pk));
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pk == NULL)
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = rsa_import(key, len, &pk->rsa);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "private key (res=%d '%s')",
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   res, error_to_string(res));
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pk->rsa.type != PK_PRIVATE) {
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "correct type");
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa_free(&pk->rsa);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pk;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       size_t len)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No X.509 support in LibTomCrypt */
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in, size_t inlen,
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *out, size_t *outlen)
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t ps_len;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PKCS #1 v1.5, 8.1:
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PS = k-3-||D||; at least eight octets
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * k = length of modulus in octets (modlen)
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned long) modlen,
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) *outlen,
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) inlen);
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = out;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 0x00;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = block_type; /* BT */
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ps_len = modlen - inlen - 3;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (block_type) {
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 0:
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(pos, 0x00, ps_len);
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ps_len;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 1:
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(pos, 0xff, ps_len);
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ps_len;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 2:
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_get_random(pos, ps_len) < 0) {
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "random data for PS", __func__);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ps_len--) {
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == 0x00)
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*pos = 0x01;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", __func__, block_type);
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 0x00;
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, in, inlen); /* D */
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *in, size_t inlen,
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *out, size_t *outlen)
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long len, modlen;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	modlen = mp_unsigned_bin_size(key->N);
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    out, outlen) < 0)
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = *outlen;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   error_to_string(res));
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*outlen = len;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *in, size_t inlen,
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 *out, size_t *outlen)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					out, outlen);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *in, size_t inlen,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  u8 *out, size_t *outlen)
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					out, outlen);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_public_key_free(struct crypto_public_key *key)
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key) {
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa_free(&key->rsa);
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(key);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_private_key_free(struct crypto_private_key *key)
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key) {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsa_free(&key->rsa);
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(key);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *crypt, size_t crypt_len,
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *plain, size_t *plain_len)
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long len;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = *plain_len;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  &key->rsa);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != CRYPT_OK) {
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   error_to_string(res));
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PKCS #1 v1.5, 8.1:
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * BT = 01
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PS = k-3-||D|| times FF
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * k = length of modulus in octets
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 3 + 8 + 16 /* min hash len */ ||
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "structure");
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = plain + 3;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < plain + len && *pos == 0xff)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos - plain - 2 < 8) {
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "padding");
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "structure (2)");
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= pos - plain;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Strip PKCS #1 header */
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(plain, pos, len);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*plain_len = len;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_global_init(void)
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ltc_mp = tfm_desc;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: only register algorithms that are really needed */
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (register_hash(&md4_desc) < 0 ||
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    register_hash(&md5_desc) < 0 ||
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    register_hash(&sha1_desc) < 0 ||
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    register_cipher(&aes_desc) < 0 ||
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    register_cipher(&des_desc) < 0 ||
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    register_cipher(&des3_desc) < 0) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "hash/cipher functions");
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_global_deinit(void)
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_MODEXP
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *power, size_t power_len,
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *modulus, size_t modulus_len,
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   u8 *result, size_t *result_len)
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *b, *p, *m, *r;
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*result_len = mp_unsigned_bin_size(r);
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mp_clear_multi(b, p, m, r, NULL);
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mp_clear_multi(b, p, m, r, NULL);
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_MODEXP */
727