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