crypto_libtomcrypt.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
1/*
2 * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
3 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16#include <tomcrypt.h>
17
18#include "common.h"
19#include "crypto.h"
20
21#ifndef mp_init_multi
22#define mp_init_multi                ltc_init_multi
23#define mp_clear_multi               ltc_deinit_multi
24#define mp_unsigned_bin_size(a)      ltc_mp.unsigned_size(a)
25#define mp_to_unsigned_bin(a, b)     ltc_mp.unsigned_write(a, b)
26#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
27#define mp_exptmod(a,b,c,d)          ltc_mp.exptmod(a,b,c,d)
28#endif
29
30
31int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
32{
33	hash_state md;
34	size_t i;
35
36	md4_init(&md);
37	for (i = 0; i < num_elem; i++)
38		md4_process(&md, addr[i], len[i]);
39	md4_done(&md, mac);
40	return 0;
41}
42
43
44void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
45{
46	u8 pkey[8], next, tmp;
47	int i;
48	symmetric_key skey;
49
50	/* Add parity bits to the key */
51	next = 0;
52	for (i = 0; i < 7; i++) {
53		tmp = key[i];
54		pkey[i] = (tmp >> i) | next | 1;
55		next = tmp << (7 - i);
56	}
57	pkey[i] = next | 1;
58
59	des_setup(pkey, 8, 0, &skey);
60	des_ecb_encrypt(clear, cypher, &skey);
61	des_done(&skey);
62}
63
64
65int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
66{
67	hash_state md;
68	size_t i;
69
70	md5_init(&md);
71	for (i = 0; i < num_elem; i++)
72		md5_process(&md, addr[i], len[i]);
73	md5_done(&md, mac);
74	return 0;
75}
76
77
78int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
79{
80	hash_state md;
81	size_t i;
82
83	sha1_init(&md);
84	for (i = 0; i < num_elem; i++)
85		sha1_process(&md, addr[i], len[i]);
86	sha1_done(&md, mac);
87	return 0;
88}
89
90
91void * aes_encrypt_init(const u8 *key, size_t len)
92{
93	symmetric_key *skey;
94	skey = os_malloc(sizeof(*skey));
95	if (skey == NULL)
96		return NULL;
97	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
98		os_free(skey);
99		return NULL;
100	}
101	return skey;
102}
103
104
105void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
106{
107	symmetric_key *skey = ctx;
108	aes_ecb_encrypt(plain, crypt, skey);
109}
110
111
112void aes_encrypt_deinit(void *ctx)
113{
114	symmetric_key *skey = ctx;
115	aes_done(skey);
116	os_free(skey);
117}
118
119
120void * aes_decrypt_init(const u8 *key, size_t len)
121{
122	symmetric_key *skey;
123	skey = os_malloc(sizeof(*skey));
124	if (skey == NULL)
125		return NULL;
126	if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
127		os_free(skey);
128		return NULL;
129	}
130	return skey;
131}
132
133
134void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
135{
136	symmetric_key *skey = ctx;
137	aes_ecb_encrypt(plain, (u8 *) crypt, skey);
138}
139
140
141void aes_decrypt_deinit(void *ctx)
142{
143	symmetric_key *skey = ctx;
144	aes_done(skey);
145	os_free(skey);
146}
147
148
149struct crypto_hash {
150	enum crypto_hash_alg alg;
151	int error;
152	union {
153		hash_state md;
154		hmac_state hmac;
155	} u;
156};
157
158
159struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
160				      size_t key_len)
161{
162	struct crypto_hash *ctx;
163
164	ctx = os_zalloc(sizeof(*ctx));
165	if (ctx == NULL)
166		return NULL;
167
168	ctx->alg = alg;
169
170	switch (alg) {
171	case CRYPTO_HASH_ALG_MD5:
172		if (md5_init(&ctx->u.md) != CRYPT_OK)
173			goto fail;
174		break;
175	case CRYPTO_HASH_ALG_SHA1:
176		if (sha1_init(&ctx->u.md) != CRYPT_OK)
177			goto fail;
178		break;
179	case CRYPTO_HASH_ALG_HMAC_MD5:
180		if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
181		    CRYPT_OK)
182			goto fail;
183		break;
184	case CRYPTO_HASH_ALG_HMAC_SHA1:
185		if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
186		    CRYPT_OK)
187			goto fail;
188		break;
189	default:
190		goto fail;
191	}
192
193	return ctx;
194
195fail:
196	os_free(ctx);
197	return NULL;
198}
199
200void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
201{
202	if (ctx == NULL || ctx->error)
203		return;
204
205	switch (ctx->alg) {
206	case CRYPTO_HASH_ALG_MD5:
207		ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
208		break;
209	case CRYPTO_HASH_ALG_SHA1:
210		ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
211		break;
212	case CRYPTO_HASH_ALG_HMAC_MD5:
213	case CRYPTO_HASH_ALG_HMAC_SHA1:
214		ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
215		break;
216	}
217}
218
219
220int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
221{
222	int ret = 0;
223	unsigned long clen;
224
225	if (ctx == NULL)
226		return -2;
227
228	if (mac == NULL || len == NULL) {
229		os_free(ctx);
230		return 0;
231	}
232
233	if (ctx->error) {
234		os_free(ctx);
235		return -2;
236	}
237
238	switch (ctx->alg) {
239	case CRYPTO_HASH_ALG_MD5:
240		if (*len < 16) {
241			*len = 16;
242			os_free(ctx);
243			return -1;
244		}
245		*len = 16;
246		if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
247			ret = -2;
248		break;
249	case CRYPTO_HASH_ALG_SHA1:
250		if (*len < 20) {
251			*len = 20;
252			os_free(ctx);
253			return -1;
254		}
255		*len = 20;
256		if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
257			ret = -2;
258		break;
259	case CRYPTO_HASH_ALG_HMAC_SHA1:
260		if (*len < 20) {
261			*len = 20;
262			os_free(ctx);
263			return -1;
264		}
265		/* continue */
266	case CRYPTO_HASH_ALG_HMAC_MD5:
267		if (*len < 16) {
268			*len = 16;
269			os_free(ctx);
270			return -1;
271		}
272		clen = *len;
273		if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
274			os_free(ctx);
275			return -1;
276		}
277		*len = clen;
278		break;
279	default:
280		ret = -2;
281		break;
282	}
283
284	os_free(ctx);
285
286	return ret;
287}
288
289
290struct crypto_cipher {
291	int rc4;
292	union {
293		symmetric_CBC cbc;
294		struct {
295			size_t used_bytes;
296			u8 key[16];
297			size_t keylen;
298		} rc4;
299	} u;
300};
301
302
303struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
304					  const u8 *iv, const u8 *key,
305					  size_t key_len)
306{
307	struct crypto_cipher *ctx;
308	int idx, res, rc4 = 0;
309
310	switch (alg) {
311	case CRYPTO_CIPHER_ALG_AES:
312		idx = find_cipher("aes");
313		break;
314	case CRYPTO_CIPHER_ALG_3DES:
315		idx = find_cipher("3des");
316		break;
317	case CRYPTO_CIPHER_ALG_DES:
318		idx = find_cipher("des");
319		break;
320	case CRYPTO_CIPHER_ALG_RC2:
321		idx = find_cipher("rc2");
322		break;
323	case CRYPTO_CIPHER_ALG_RC4:
324		idx = -1;
325		rc4 = 1;
326		break;
327	default:
328		return NULL;
329	}
330
331	ctx = os_zalloc(sizeof(*ctx));
332	if (ctx == NULL)
333		return NULL;
334
335	if (rc4) {
336		ctx->rc4 = 1;
337		if (key_len > sizeof(ctx->u.rc4.key)) {
338			os_free(ctx);
339			return NULL;
340		}
341		ctx->u.rc4.keylen = key_len;
342		os_memcpy(ctx->u.rc4.key, key, key_len);
343	} else {
344		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
345		if (res != CRYPT_OK) {
346			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
347				   "failed: %s", error_to_string(res));
348			os_free(ctx);
349			return NULL;
350		}
351	}
352
353	return ctx;
354}
355
356int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
357			  u8 *crypt, size_t len)
358{
359	int res;
360
361	if (ctx->rc4) {
362		if (plain != crypt)
363			os_memcpy(crypt, plain, len);
364		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
365			 ctx->u.rc4.used_bytes, crypt, len);
366		ctx->u.rc4.used_bytes += len;
367		return 0;
368	}
369
370	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
371	if (res != CRYPT_OK) {
372		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
373			   "failed: %s", error_to_string(res));
374		return -1;
375	}
376	return 0;
377}
378
379
380int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
381			  u8 *plain, size_t len)
382{
383	int res;
384
385	if (ctx->rc4) {
386		if (plain != crypt)
387			os_memcpy(plain, crypt, len);
388		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
389			 ctx->u.rc4.used_bytes, plain, len);
390		ctx->u.rc4.used_bytes += len;
391		return 0;
392	}
393
394	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
395	if (res != CRYPT_OK) {
396		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
397			   "failed: %s", error_to_string(res));
398		return -1;
399	}
400
401	return 0;
402}
403
404
405void crypto_cipher_deinit(struct crypto_cipher *ctx)
406{
407	if (!ctx->rc4)
408		cbc_done(&ctx->u.cbc);
409	os_free(ctx);
410}
411
412
413struct crypto_public_key {
414	rsa_key rsa;
415};
416
417struct crypto_private_key {
418	rsa_key rsa;
419};
420
421
422struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
423{
424	int res;
425	struct crypto_public_key *pk;
426
427	pk = os_zalloc(sizeof(*pk));
428	if (pk == NULL)
429		return NULL;
430
431	res = rsa_import(key, len, &pk->rsa);
432	if (res != CRYPT_OK) {
433		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
434			   "public key (res=%d '%s')",
435			   res, error_to_string(res));
436		os_free(pk);
437		return NULL;
438	}
439
440	if (pk->rsa.type != PK_PUBLIC) {
441		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
442			   "correct type");
443		rsa_free(&pk->rsa);
444		os_free(pk);
445		return NULL;
446	}
447
448	return pk;
449}
450
451
452struct crypto_private_key * crypto_private_key_import(const u8 *key,
453						      size_t len,
454						      const char *passwd)
455{
456	int res;
457	struct crypto_private_key *pk;
458
459	pk = os_zalloc(sizeof(*pk));
460	if (pk == NULL)
461		return NULL;
462
463	res = rsa_import(key, len, &pk->rsa);
464	if (res != CRYPT_OK) {
465		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
466			   "private key (res=%d '%s')",
467			   res, error_to_string(res));
468		os_free(pk);
469		return NULL;
470	}
471
472	if (pk->rsa.type != PK_PRIVATE) {
473		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
474			   "correct type");
475		rsa_free(&pk->rsa);
476		os_free(pk);
477		return NULL;
478	}
479
480	return pk;
481}
482
483
484struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
485						       size_t len)
486{
487	/* No X.509 support in LibTomCrypt */
488	return NULL;
489}
490
491
492static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
493					   const u8 *in, size_t inlen,
494					   u8 *out, size_t *outlen)
495{
496	size_t ps_len;
497	u8 *pos;
498
499	/*
500	 * PKCS #1 v1.5, 8.1:
501	 *
502	 * EB = 00 || BT || PS || 00 || D
503	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
504	 * PS = k-3-||D||; at least eight octets
505	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
506	 * k = length of modulus in octets (modlen)
507	 */
508
509	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
510		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
511			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
512			   __func__, (unsigned long) modlen,
513			   (unsigned long) *outlen,
514			   (unsigned long) inlen);
515		return -1;
516	}
517
518	pos = out;
519	*pos++ = 0x00;
520	*pos++ = block_type; /* BT */
521	ps_len = modlen - inlen - 3;
522	switch (block_type) {
523	case 0:
524		os_memset(pos, 0x00, ps_len);
525		pos += ps_len;
526		break;
527	case 1:
528		os_memset(pos, 0xff, ps_len);
529		pos += ps_len;
530		break;
531	case 2:
532		if (os_get_random(pos, ps_len) < 0) {
533			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
534				   "random data for PS", __func__);
535			return -1;
536		}
537		while (ps_len--) {
538			if (*pos == 0x00)
539				*pos = 0x01;
540			pos++;
541		}
542		break;
543	default:
544		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
545			   "%d", __func__, block_type);
546		return -1;
547	}
548	*pos++ = 0x00;
549	os_memcpy(pos, in, inlen); /* D */
550
551	return 0;
552}
553
554
555static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
556				    const u8 *in, size_t inlen,
557				    u8 *out, size_t *outlen)
558{
559	unsigned long len, modlen;
560	int res;
561
562	modlen = mp_unsigned_bin_size(key->N);
563
564	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
565					    out, outlen) < 0)
566		return -1;
567
568	len = *outlen;
569	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
570	if (res != CRYPT_OK) {
571		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
572			   error_to_string(res));
573		return -1;
574	}
575	*outlen = len;
576
577	return 0;
578}
579
580
581int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
582					const u8 *in, size_t inlen,
583					u8 *out, size_t *outlen)
584{
585	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
586					out, outlen);
587}
588
589
590int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
591				  const u8 *in, size_t inlen,
592				  u8 *out, size_t *outlen)
593{
594	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
595					out, outlen);
596}
597
598
599void crypto_public_key_free(struct crypto_public_key *key)
600{
601	if (key) {
602		rsa_free(&key->rsa);
603		os_free(key);
604	}
605}
606
607
608void crypto_private_key_free(struct crypto_private_key *key)
609{
610	if (key) {
611		rsa_free(&key->rsa);
612		os_free(key);
613	}
614}
615
616
617int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
618				    const u8 *crypt, size_t crypt_len,
619				    u8 *plain, size_t *plain_len)
620{
621	int res;
622	unsigned long len;
623	u8 *pos;
624
625	len = *plain_len;
626	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
627			  &key->rsa);
628	if (res != CRYPT_OK) {
629		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
630			   error_to_string(res));
631		return -1;
632	}
633
634	/*
635	 * PKCS #1 v1.5, 8.1:
636	 *
637	 * EB = 00 || BT || PS || 00 || D
638	 * BT = 01
639	 * PS = k-3-||D|| times FF
640	 * k = length of modulus in octets
641	 */
642
643	if (len < 3 + 8 + 16 /* min hash len */ ||
644	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
645		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
646			   "structure");
647		return -1;
648	}
649
650	pos = plain + 3;
651	while (pos < plain + len && *pos == 0xff)
652		pos++;
653	if (pos - plain - 2 < 8) {
654		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
655		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
656			   "padding");
657		return -1;
658	}
659
660	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
661		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
662			   "structure (2)");
663		return -1;
664	}
665	pos++;
666	len -= pos - plain;
667
668	/* Strip PKCS #1 header */
669	os_memmove(plain, pos, len);
670	*plain_len = len;
671
672	return 0;
673}
674
675
676int crypto_global_init(void)
677{
678	ltc_mp = tfm_desc;
679	/* TODO: only register algorithms that are really needed */
680	if (register_hash(&md4_desc) < 0 ||
681	    register_hash(&md5_desc) < 0 ||
682	    register_hash(&sha1_desc) < 0 ||
683	    register_cipher(&aes_desc) < 0 ||
684	    register_cipher(&des_desc) < 0 ||
685	    register_cipher(&des3_desc) < 0) {
686		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
687			   "hash/cipher functions");
688		return -1;
689	}
690
691	return 0;
692}
693
694
695void crypto_global_deinit(void)
696{
697}
698
699
700#ifdef CONFIG_MODEXP
701
702int crypto_mod_exp(const u8 *base, size_t base_len,
703		   const u8 *power, size_t power_len,
704		   const u8 *modulus, size_t modulus_len,
705		   u8 *result, size_t *result_len)
706{
707	void *b, *p, *m, *r;
708
709	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
710		return -1;
711
712	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
713	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
714	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
715		goto fail;
716
717	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
718		goto fail;
719
720	*result_len = mp_unsigned_bin_size(r);
721	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
722		goto fail;
723
724	mp_clear_multi(b, p, m, r, NULL);
725	return 0;
726
727fail:
728	mp_clear_multi(b, p, m, r, NULL);
729	return -1;
730}
731
732#endif /* CONFIG_MODEXP */
733