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