crypto_libtomcrypt.c revision 189251
1178784Skmacy/*
2178784Skmacy * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
3178784Skmacy * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
4178784Skmacy *
5178784Skmacy * This program is free software; you can redistribute it and/or modify
6178784Skmacy * it under the terms of the GNU General Public License version 2 as
7178784Skmacy * published by the Free Software Foundation.
8178784Skmacy *
9178784Skmacy * Alternatively, this software may be distributed under the terms of BSD
10178784Skmacy * license.
11178784Skmacy *
12178784Skmacy * See README and COPYING for more details.
13178784Skmacy */
14178784Skmacy
15178784Skmacy#include "includes.h"
16178784Skmacy#include <tomcrypt.h>
17178784Skmacy
18178784Skmacy#include "common.h"
19178784Skmacy#include "rc4.h"
20178784Skmacy#include "crypto.h"
21178784Skmacy
22178784Skmacy#ifndef mp_init_multi
23178784Skmacy#define mp_init_multi                ltc_init_multi
24178784Skmacy#define mp_clear_multi               ltc_deinit_multi
25178784Skmacy#define mp_unsigned_bin_size(a)      ltc_mp.unsigned_size(a)
26178784Skmacy#define mp_to_unsigned_bin(a, b)     ltc_mp.unsigned_write(a, b)
27178784Skmacy#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
28178784Skmacy#define mp_exptmod(a,b,c,d)          ltc_mp.exptmod(a,b,c,d)
29178784Skmacy#endif
30178784Skmacy
31178784Skmacy
32178784Skmacyvoid md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
33178784Skmacy{
34178784Skmacy	hash_state md;
35178784Skmacy	size_t i;
36178784Skmacy
37178784Skmacy	md4_init(&md);
38178784Skmacy	for (i = 0; i < num_elem; i++)
39178784Skmacy		md4_process(&md, addr[i], len[i]);
40178784Skmacy	md4_done(&md, mac);
41178784Skmacy}
42178784Skmacy
43178784Skmacy
44178784Skmacyvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
45178784Skmacy{
46178784Skmacy	u8 pkey[8], next, tmp;
47178784Skmacy	int i;
48178784Skmacy	symmetric_key skey;
49178784Skmacy
50178784Skmacy	/* Add parity bits to the key */
51178784Skmacy	next = 0;
52178784Skmacy	for (i = 0; i < 7; i++) {
53178784Skmacy		tmp = key[i];
54178784Skmacy		pkey[i] = (tmp >> i) | next | 1;
55178784Skmacy		next = tmp << (7 - i);
56178784Skmacy	}
57178784Skmacy	pkey[i] = next | 1;
58178784Skmacy
59178784Skmacy	des_setup(pkey, 8, 0, &skey);
60178784Skmacy	des_ecb_encrypt(clear, cypher, &skey);
61178784Skmacy	des_done(&skey);
62178784Skmacy}
63178784Skmacy
64178784Skmacy
65178784Skmacy#ifdef EAP_TLS_FUNCS
66178784Skmacyvoid md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
67178784Skmacy{
68178784Skmacy	hash_state md;
69178784Skmacy	size_t i;
70178784Skmacy
71178784Skmacy	md5_init(&md);
72178784Skmacy	for (i = 0; i < num_elem; i++)
73178784Skmacy		md5_process(&md, addr[i], len[i]);
74178784Skmacy	md5_done(&md, mac);
75178784Skmacy}
76178784Skmacy
77178784Skmacy
78178784Skmacyvoid sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
79178784Skmacy{
80178784Skmacy	hash_state md;
81178784Skmacy	size_t i;
82178784Skmacy
83178784Skmacy	sha1_init(&md);
84178784Skmacy	for (i = 0; i < num_elem; i++)
85178784Skmacy		sha1_process(&md, addr[i], len[i]);
86178784Skmacy	sha1_done(&md, mac);
87178784Skmacy}
88178784Skmacy
89178784Skmacy
90178784Skmacyvoid * aes_encrypt_init(const u8 *key, size_t len)
91178784Skmacy{
92178784Skmacy	symmetric_key *skey;
93178784Skmacy	skey = os_malloc(sizeof(*skey));
94178784Skmacy	if (skey == NULL)
95178784Skmacy		return NULL;
96178784Skmacy	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
97178784Skmacy		os_free(skey);
98178784Skmacy		return NULL;
99178784Skmacy	}
100178784Skmacy	return skey;
101178784Skmacy}
102178784Skmacy
103178784Skmacy
104178784Skmacyvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
105178784Skmacy{
106178784Skmacy	symmetric_key *skey = ctx;
107178784Skmacy	aes_ecb_encrypt(plain, crypt, skey);
108178784Skmacy}
109178784Skmacy
110178784Skmacy
111178784Skmacyvoid aes_encrypt_deinit(void *ctx)
112178784Skmacy{
113178784Skmacy	symmetric_key *skey = ctx;
114178784Skmacy	aes_done(skey);
115178784Skmacy	os_free(skey);
116178784Skmacy}
117178784Skmacy
118178784Skmacy
119178784Skmacyvoid * aes_decrypt_init(const u8 *key, size_t len)
120178784Skmacy{
121178784Skmacy	symmetric_key *skey;
122178784Skmacy	skey = os_malloc(sizeof(*skey));
123178784Skmacy	if (skey == NULL)
124178784Skmacy		return NULL;
125178784Skmacy	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
126178784Skmacy		os_free(skey);
127178784Skmacy		return NULL;
128178784Skmacy	}
129178784Skmacy	return skey;
130178784Skmacy}
131178784Skmacy
132178784Skmacy
133178784Skmacyvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
134178784Skmacy{
135178784Skmacy	symmetric_key *skey = ctx;
136178784Skmacy	aes_ecb_encrypt(plain, (u8 *) crypt, skey);
137178784Skmacy}
138178784Skmacy
139178784Skmacy
140178784Skmacyvoid aes_decrypt_deinit(void *ctx)
141178784Skmacy{
142178784Skmacy	symmetric_key *skey = ctx;
143178784Skmacy	aes_done(skey);
144178784Skmacy	os_free(skey);
145178784Skmacy}
146178784Skmacy
147178784Skmacy
148178784Skmacy#ifdef CONFIG_TLS_INTERNAL
149178784Skmacy
150178784Skmacystruct crypto_hash {
151178784Skmacy	enum crypto_hash_alg alg;
152178784Skmacy	int error;
153178784Skmacy	union {
154178784Skmacy		hash_state md;
155178784Skmacy		hmac_state hmac;
156178784Skmacy	} u;
157178784Skmacy};
158178784Skmacy
159178784Skmacy
160178784Skmacystruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
161178784Skmacy				      size_t key_len)
162178784Skmacy{
163178784Skmacy	struct crypto_hash *ctx;
164178784Skmacy
165178784Skmacy	ctx = os_zalloc(sizeof(*ctx));
166178784Skmacy	if (ctx == NULL)
167178784Skmacy		return NULL;
168178784Skmacy
169178784Skmacy	ctx->alg = alg;
170178784Skmacy
171178784Skmacy	switch (alg) {
172178784Skmacy	case CRYPTO_HASH_ALG_MD5:
173178784Skmacy		if (md5_init(&ctx->u.md) != CRYPT_OK)
174178784Skmacy			goto fail;
175178784Skmacy		break;
176178784Skmacy	case CRYPTO_HASH_ALG_SHA1:
177178784Skmacy		if (sha1_init(&ctx->u.md) != CRYPT_OK)
178178784Skmacy			goto fail;
179178784Skmacy		break;
180178784Skmacy	case CRYPTO_HASH_ALG_HMAC_MD5:
181178784Skmacy		if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
182178784Skmacy		    CRYPT_OK)
183178784Skmacy			goto fail;
184178784Skmacy		break;
185178784Skmacy	case CRYPTO_HASH_ALG_HMAC_SHA1:
186178784Skmacy		if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
187178784Skmacy		    CRYPT_OK)
188178784Skmacy			goto fail;
189178784Skmacy		break;
190178784Skmacy	default:
191178784Skmacy		goto fail;
192178784Skmacy	}
193178784Skmacy
194178784Skmacy	return ctx;
195178784Skmacy
196178784Skmacyfail:
197178784Skmacy	os_free(ctx);
198178784Skmacy	return NULL;
199178784Skmacy}
200178784Skmacy
201178784Skmacyvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
202178784Skmacy{
203178784Skmacy	if (ctx == NULL || ctx->error)
204178784Skmacy		return;
205178784Skmacy
206178784Skmacy	switch (ctx->alg) {
207178784Skmacy	case CRYPTO_HASH_ALG_MD5:
208178784Skmacy		ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
209178784Skmacy		break;
210178784Skmacy	case CRYPTO_HASH_ALG_SHA1:
211178784Skmacy		ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
212178784Skmacy		break;
213178784Skmacy	case CRYPTO_HASH_ALG_HMAC_MD5:
214178784Skmacy	case CRYPTO_HASH_ALG_HMAC_SHA1:
215178784Skmacy		ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
216178784Skmacy		break;
217178784Skmacy	}
218178784Skmacy}
219178784Skmacy
220178784Skmacy
221178784Skmacyint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
222178784Skmacy{
223178784Skmacy	int ret = 0;
224178784Skmacy	unsigned long clen;
225178784Skmacy
226178784Skmacy	if (ctx == NULL)
227178784Skmacy		return -2;
228178784Skmacy
229178784Skmacy	if (mac == NULL || len == NULL) {
230178784Skmacy		os_free(ctx);
231178784Skmacy		return 0;
232178784Skmacy	}
233178784Skmacy
234178784Skmacy	if (ctx->error) {
235178784Skmacy		os_free(ctx);
236178784Skmacy		return -2;
237178784Skmacy	}
238178784Skmacy
239178784Skmacy	switch (ctx->alg) {
240178784Skmacy	case CRYPTO_HASH_ALG_MD5:
241178784Skmacy		if (*len < 16) {
242178784Skmacy			*len = 16;
243178784Skmacy			os_free(ctx);
244178784Skmacy			return -1;
245178784Skmacy		}
246178784Skmacy		*len = 16;
247178784Skmacy		if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
248178784Skmacy			ret = -2;
249178784Skmacy		break;
250178784Skmacy	case CRYPTO_HASH_ALG_SHA1:
251178784Skmacy		if (*len < 20) {
252178784Skmacy			*len = 20;
253178784Skmacy			os_free(ctx);
254178784Skmacy			return -1;
255178784Skmacy		}
256178784Skmacy		*len = 20;
257178784Skmacy		if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
258178784Skmacy			ret = -2;
259178784Skmacy		break;
260178784Skmacy	case CRYPTO_HASH_ALG_HMAC_SHA1:
261178784Skmacy		if (*len < 20) {
262178784Skmacy			*len = 20;
263178784Skmacy			os_free(ctx);
264178784Skmacy			return -1;
265178784Skmacy		}
266178784Skmacy		/* continue */
267178784Skmacy	case CRYPTO_HASH_ALG_HMAC_MD5:
268178784Skmacy		if (*len < 16) {
269178784Skmacy			*len = 16;
270178784Skmacy			os_free(ctx);
271178784Skmacy			return -1;
272178784Skmacy		}
273178784Skmacy		clen = *len;
274178784Skmacy		if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
275178784Skmacy			os_free(ctx);
276178784Skmacy			return -1;
277178784Skmacy		}
278178784Skmacy		*len = clen;
279178784Skmacy		break;
280178784Skmacy	default:
281178784Skmacy		ret = -2;
282178784Skmacy		break;
283178784Skmacy	}
284178784Skmacy
285178784Skmacy	os_free(ctx);
286178784Skmacy
287178784Skmacy	return ret;
288178784Skmacy}
289178784Skmacy
290178784Skmacy
291178784Skmacystruct crypto_cipher {
292178784Skmacy	int rc4;
293178784Skmacy	union {
294178784Skmacy		symmetric_CBC cbc;
295178784Skmacy		struct {
296178784Skmacy			size_t used_bytes;
297178784Skmacy			u8 key[16];
298178784Skmacy			size_t keylen;
299178784Skmacy		} rc4;
300178784Skmacy	} u;
301178784Skmacy};
302178784Skmacy
303178784Skmacy
304178784Skmacystruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
305178784Skmacy					  const u8 *iv, const u8 *key,
306178784Skmacy					  size_t key_len)
307178784Skmacy{
308178784Skmacy	struct crypto_cipher *ctx;
309178784Skmacy	int idx, res, rc4 = 0;
310178784Skmacy
311178784Skmacy	switch (alg) {
312178784Skmacy	case CRYPTO_CIPHER_ALG_AES:
313178784Skmacy		idx = find_cipher("aes");
314178784Skmacy		break;
315178784Skmacy	case CRYPTO_CIPHER_ALG_3DES:
316178784Skmacy		idx = find_cipher("3des");
317178784Skmacy		break;
318178784Skmacy	case CRYPTO_CIPHER_ALG_DES:
319178784Skmacy		idx = find_cipher("des");
320178784Skmacy		break;
321178784Skmacy	case CRYPTO_CIPHER_ALG_RC2:
322178784Skmacy		idx = find_cipher("rc2");
323178784Skmacy		break;
324178784Skmacy	case CRYPTO_CIPHER_ALG_RC4:
325178784Skmacy		idx = -1;
326178784Skmacy		rc4 = 1;
327178784Skmacy		break;
328178784Skmacy	default:
329178784Skmacy		return NULL;
330178784Skmacy	}
331178784Skmacy
332178784Skmacy	ctx = os_zalloc(sizeof(*ctx));
333178784Skmacy	if (ctx == NULL)
334178784Skmacy		return NULL;
335178784Skmacy
336178784Skmacy	if (rc4) {
337178784Skmacy		ctx->rc4 = 1;
338178784Skmacy		if (key_len > sizeof(ctx->u.rc4.key)) {
339178784Skmacy			os_free(ctx);
340178784Skmacy			return NULL;
341178784Skmacy		}
342178784Skmacy		ctx->u.rc4.keylen = key_len;
343178784Skmacy		os_memcpy(ctx->u.rc4.key, key, key_len);
344178784Skmacy	} else {
345178784Skmacy		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
346178784Skmacy		if (res != CRYPT_OK) {
347178784Skmacy			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
348178784Skmacy				   "failed: %s", error_to_string(res));
349178784Skmacy			os_free(ctx);
350178784Skmacy			return NULL;
351178784Skmacy		}
352178784Skmacy	}
353178784Skmacy
354178784Skmacy	return ctx;
355178784Skmacy}
356178784Skmacy
357178784Skmacyint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
358178784Skmacy			  u8 *crypt, size_t len)
359178784Skmacy{
360178784Skmacy	int res;
361178784Skmacy
362178784Skmacy	if (ctx->rc4) {
363178784Skmacy		if (plain != crypt)
364178784Skmacy			os_memcpy(crypt, plain, len);
365178784Skmacy		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
366178784Skmacy			 ctx->u.rc4.used_bytes, crypt, len);
367178784Skmacy		ctx->u.rc4.used_bytes += len;
368178784Skmacy		return 0;
369178784Skmacy	}
370178784Skmacy
371178784Skmacy	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
372178784Skmacy	if (res != CRYPT_OK) {
373178784Skmacy		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
374178784Skmacy			   "failed: %s", error_to_string(res));
375178784Skmacy		return -1;
376178784Skmacy	}
377178784Skmacy	return 0;
378178784Skmacy}
379178784Skmacy
380178784Skmacy
381178784Skmacyint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
382178784Skmacy			  u8 *plain, size_t len)
383178784Skmacy{
384178784Skmacy	int res;
385178784Skmacy
386178784Skmacy	if (ctx->rc4) {
387178784Skmacy		if (plain != crypt)
388178784Skmacy			os_memcpy(plain, crypt, len);
389178784Skmacy		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
390178784Skmacy			 ctx->u.rc4.used_bytes, plain, len);
391178784Skmacy		ctx->u.rc4.used_bytes += len;
392178784Skmacy		return 0;
393178784Skmacy	}
394178784Skmacy
395178784Skmacy	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
396178784Skmacy	if (res != CRYPT_OK) {
397178784Skmacy		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
398178784Skmacy			   "failed: %s", error_to_string(res));
399178784Skmacy		return -1;
400178784Skmacy	}
401178784Skmacy
402178784Skmacy	return 0;
403178784Skmacy}
404178784Skmacy
405178784Skmacy
406178784Skmacyvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
407178784Skmacy{
408178784Skmacy	if (!ctx->rc4)
409178784Skmacy		cbc_done(&ctx->u.cbc);
410178784Skmacy	os_free(ctx);
411178784Skmacy}
412178784Skmacy
413178784Skmacy
414178784Skmacystruct crypto_public_key {
415178784Skmacy	rsa_key rsa;
416178784Skmacy};
417178784Skmacy
418178784Skmacystruct crypto_private_key {
419178784Skmacy	rsa_key rsa;
420178784Skmacy};
421178784Skmacy
422178784Skmacy
423178784Skmacystruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
424178784Skmacy{
425178784Skmacy	int res;
426178784Skmacy	struct crypto_public_key *pk;
427178784Skmacy
428178784Skmacy	pk = os_zalloc(sizeof(*pk));
429178784Skmacy	if (pk == NULL)
430178784Skmacy		return NULL;
431178784Skmacy
432178784Skmacy	res = rsa_import(key, len, &pk->rsa);
433178784Skmacy	if (res != CRYPT_OK) {
434178784Skmacy		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
435178784Skmacy			   "public key (res=%d '%s')",
436178784Skmacy			   res, error_to_string(res));
437178784Skmacy		os_free(pk);
438178784Skmacy		return NULL;
439178784Skmacy	}
440178784Skmacy
441178784Skmacy	if (pk->rsa.type != PK_PUBLIC) {
442178784Skmacy		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
443178784Skmacy			   "correct type");
444178784Skmacy		rsa_free(&pk->rsa);
445178784Skmacy		os_free(pk);
446178784Skmacy		return NULL;
447178784Skmacy	}
448178784Skmacy
449178784Skmacy	return pk;
450178784Skmacy}
451178784Skmacy
452178784Skmacy
453178784Skmacystruct crypto_private_key * crypto_private_key_import(const u8 *key,
454178784Skmacy						      size_t len)
455178784Skmacy{
456178784Skmacy	int res;
457178784Skmacy	struct crypto_private_key *pk;
458178784Skmacy
459178784Skmacy	pk = os_zalloc(sizeof(*pk));
460178784Skmacy	if (pk == NULL)
461178784Skmacy		return NULL;
462178784Skmacy
463178784Skmacy	res = rsa_import(key, len, &pk->rsa);
464178784Skmacy	if (res != CRYPT_OK) {
465178784Skmacy		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
466178784Skmacy			   "private key (res=%d '%s')",
467178784Skmacy			   res, error_to_string(res));
468178784Skmacy		os_free(pk);
469178784Skmacy		return NULL;
470178784Skmacy	}
471178784Skmacy
472178784Skmacy	if (pk->rsa.type != PK_PRIVATE) {
473178784Skmacy		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
474178784Skmacy			   "correct type");
475178784Skmacy		rsa_free(&pk->rsa);
476178784Skmacy		os_free(pk);
477178784Skmacy		return NULL;
478178784Skmacy	}
479178784Skmacy
480178784Skmacy	return pk;
481178784Skmacy}
482178784Skmacy
483178784Skmacy
484178784Skmacystruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
485178784Skmacy						       size_t len)
486178784Skmacy{
487178784Skmacy	/* No X.509 support in LibTomCrypt */
488178784Skmacy	return NULL;
489178784Skmacy}
490178784Skmacy
491178784Skmacy
492178784Skmacystatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
493178784Skmacy					   const u8 *in, size_t inlen,
494178784Skmacy					   u8 *out, size_t *outlen)
495178784Skmacy{
496178784Skmacy	size_t ps_len;
497178784Skmacy	u8 *pos;
498178784Skmacy
499178784Skmacy	/*
500178784Skmacy	 * PKCS #1 v1.5, 8.1:
501178784Skmacy	 *
502178784Skmacy	 * EB = 00 || BT || PS || 00 || D
503178784Skmacy	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
504178784Skmacy	 * PS = k-3-||D||; at least eight octets
505178784Skmacy	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
506178784Skmacy	 * k = length of modulus in octets (modlen)
507178784Skmacy	 */
508178784Skmacy
509178784Skmacy	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
510178784Skmacy		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
511178784Skmacy			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
512178784Skmacy			   __func__, (unsigned long) modlen,
513178784Skmacy			   (unsigned long) *outlen,
514178784Skmacy			   (unsigned long) inlen);
515178784Skmacy		return -1;
516178784Skmacy	}
517178784Skmacy
518178784Skmacy	pos = out;
519178784Skmacy	*pos++ = 0x00;
520178784Skmacy	*pos++ = block_type; /* BT */
521178784Skmacy	ps_len = modlen - inlen - 3;
522178784Skmacy	switch (block_type) {
523178784Skmacy	case 0:
524178784Skmacy		os_memset(pos, 0x00, ps_len);
525178784Skmacy		pos += ps_len;
526178784Skmacy		break;
527178784Skmacy	case 1:
528178784Skmacy		os_memset(pos, 0xff, ps_len);
529178784Skmacy		pos += ps_len;
530178784Skmacy		break;
531178784Skmacy	case 2:
532178784Skmacy		if (os_get_random(pos, ps_len) < 0) {
533178784Skmacy			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
534178784Skmacy				   "random data for PS", __func__);
535178784Skmacy			return -1;
536178784Skmacy		}
537178784Skmacy		while (ps_len--) {
538178784Skmacy			if (*pos == 0x00)
539178784Skmacy				*pos = 0x01;
540178784Skmacy			pos++;
541178784Skmacy		}
542178784Skmacy		break;
543178784Skmacy	default:
544178784Skmacy		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
545178784Skmacy			   "%d", __func__, block_type);
546178784Skmacy		return -1;
547178784Skmacy	}
548178784Skmacy	*pos++ = 0x00;
549178784Skmacy	os_memcpy(pos, in, inlen); /* D */
550178784Skmacy
551178784Skmacy	return 0;
552178784Skmacy}
553178784Skmacy
554178784Skmacy
555178784Skmacystatic int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
556178784Skmacy				    const u8 *in, size_t inlen,
557178784Skmacy				    u8 *out, size_t *outlen)
558178784Skmacy{
559178784Skmacy	unsigned long len, modlen;
560178784Skmacy	int res;
561178784Skmacy
562178784Skmacy	modlen = mp_unsigned_bin_size(key->N);
563178784Skmacy
564178784Skmacy	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
565178784Skmacy					    out, outlen) < 0)
566178784Skmacy		return -1;
567178784Skmacy
568178784Skmacy	len = *outlen;
569178784Skmacy	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
570178784Skmacy	if (res != CRYPT_OK) {
571178784Skmacy		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
572178784Skmacy			   error_to_string(res));
573178784Skmacy		return -1;
574178784Skmacy	}
575178784Skmacy	*outlen = len;
576178784Skmacy
577178784Skmacy	return 0;
578178784Skmacy}
579178784Skmacy
580178784Skmacy
581178784Skmacyint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
582178784Skmacy					const u8 *in, size_t inlen,
583178784Skmacy					u8 *out, size_t *outlen)
584178784Skmacy{
585178784Skmacy	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
586178784Skmacy					out, outlen);
587178784Skmacy}
588178784Skmacy
589178784Skmacy
590178784Skmacyint crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
591178784Skmacy				  const u8 *in, size_t inlen,
592178784Skmacy				  u8 *out, size_t *outlen)
593178784Skmacy{
594178784Skmacy	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
595178784Skmacy					out, outlen);
596178784Skmacy}
597178784Skmacy
598178784Skmacy
599178784Skmacyvoid crypto_public_key_free(struct crypto_public_key *key)
600178784Skmacy{
601178784Skmacy	if (key) {
602178784Skmacy		rsa_free(&key->rsa);
603178784Skmacy		os_free(key);
604178784Skmacy	}
605178784Skmacy}
606178784Skmacy
607178784Skmacy
608178784Skmacyvoid crypto_private_key_free(struct crypto_private_key *key)
609178784Skmacy{
610178784Skmacy	if (key) {
611178784Skmacy		rsa_free(&key->rsa);
612178784Skmacy		os_free(key);
613178784Skmacy	}
614178784Skmacy}
615178784Skmacy
616178784Skmacy
617178784Skmacyint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
618178784Skmacy				    const u8 *crypt, size_t crypt_len,
619178784Skmacy				    u8 *plain, size_t *plain_len)
620178784Skmacy{
621178784Skmacy	int res;
622178784Skmacy	unsigned long len;
623178784Skmacy	u8 *pos;
624178784Skmacy
625178784Skmacy	len = *plain_len;
626178784Skmacy	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
627178784Skmacy			  &key->rsa);
628178784Skmacy	if (res != CRYPT_OK) {
629178784Skmacy		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
630178784Skmacy			   error_to_string(res));
631178784Skmacy		return -1;
632178784Skmacy	}
633178784Skmacy
634178784Skmacy	/*
635178784Skmacy	 * PKCS #1 v1.5, 8.1:
636178784Skmacy	 *
637178784Skmacy	 * EB = 00 || BT || PS || 00 || D
638178784Skmacy	 * BT = 01
639178784Skmacy	 * PS = k-3-||D|| times FF
640178784Skmacy	 * k = length of modulus in octets
641178784Skmacy	 */
642178784Skmacy
643178784Skmacy	if (len < 3 + 8 + 16 /* min hash len */ ||
644178784Skmacy	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
645178784Skmacy		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
646178784Skmacy			   "structure");
647178784Skmacy		return -1;
648178784Skmacy	}
649178784Skmacy
650178784Skmacy	pos = plain + 3;
651178784Skmacy	while (pos < plain + len && *pos == 0xff)
652178784Skmacy		pos++;
653178784Skmacy	if (pos - plain - 2 < 8) {
654178784Skmacy		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
655178784Skmacy		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
656178784Skmacy			   "padding");
657178784Skmacy		return -1;
658178784Skmacy	}
659178784Skmacy
660178784Skmacy	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
661178784Skmacy		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
662178784Skmacy			   "structure (2)");
663178784Skmacy		return -1;
664178784Skmacy	}
665178784Skmacy	pos++;
666178784Skmacy	len -= pos - plain;
667178784Skmacy
668178784Skmacy	/* Strip PKCS #1 header */
669178784Skmacy	os_memmove(plain, pos, len);
670178784Skmacy	*plain_len = len;
671178784Skmacy
672178784Skmacy	return 0;
673178784Skmacy}
674178784Skmacy
675178784Skmacy
676178784Skmacyint crypto_global_init(void)
677178784Skmacy{
678178784Skmacy	ltc_mp = tfm_desc;
679178784Skmacy	/* TODO: only register algorithms that are really needed */
680178784Skmacy	if (register_hash(&md4_desc) < 0 ||
681178784Skmacy	    register_hash(&md5_desc) < 0 ||
682178784Skmacy	    register_hash(&sha1_desc) < 0 ||
683178784Skmacy	    register_cipher(&aes_desc) < 0 ||
684178784Skmacy	    register_cipher(&des_desc) < 0 ||
685178784Skmacy	    register_cipher(&des3_desc) < 0) {
686178784Skmacy		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
687178784Skmacy			   "hash/cipher functions");
688178784Skmacy		return -1;
689178784Skmacy	}
690178784Skmacy
691178784Skmacy	return 0;
692178784Skmacy}
693178784Skmacy
694178784Skmacy
695178784Skmacyvoid crypto_global_deinit(void)
696178784Skmacy{
697178784Skmacy}
698178784Skmacy
699178784Skmacy
700178784Skmacy#ifdef EAP_FAST
701178784Skmacy
702178784Skmacyint crypto_mod_exp(const u8 *base, size_t base_len,
703178784Skmacy		   const u8 *power, size_t power_len,
704178784Skmacy		   const u8 *modulus, size_t modulus_len,
705178784Skmacy		   u8 *result, size_t *result_len)
706178784Skmacy{
707178784Skmacy	void *b, *p, *m, *r;
708178784Skmacy
709178784Skmacy	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
710178784Skmacy		return -1;
711178784Skmacy
712178784Skmacy	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
713178784Skmacy	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
714178784Skmacy	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
715178784Skmacy		goto fail;
716178784Skmacy
717178784Skmacy	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
718178784Skmacy		goto fail;
719178784Skmacy
720178784Skmacy	*result_len = mp_unsigned_bin_size(r);
721178784Skmacy	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
722178784Skmacy		goto fail;
723178784Skmacy
724178784Skmacy	mp_clear_multi(b, p, m, r, NULL);
725178784Skmacy	return 0;
726178784Skmacy
727178784Skmacyfail:
728178784Skmacy	mp_clear_multi(b, p, m, r, NULL);
729178784Skmacy	return -1;
730178784Skmacy}
731178784Skmacy
732178784Skmacy#endif /* EAP_FAST */
733178784Skmacy
734178784Skmacy#endif /* CONFIG_TLS_INTERNAL */
735178784Skmacy
736178784Skmacy#endif /* EAP_TLS_FUNCS */
737178784Skmacy