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	if (TEST_FAIL())
282		return -1;
283
284	return ret;
285}
286
287
288struct crypto_cipher {
289	int rc4;
290	union {
291		symmetric_CBC cbc;
292		struct {
293			size_t used_bytes;
294			u8 key[16];
295			size_t keylen;
296		} rc4;
297	} u;
298};
299
300
301struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
302					  const u8 *iv, const u8 *key,
303					  size_t key_len)
304{
305	struct crypto_cipher *ctx;
306	int idx, res, rc4 = 0;
307
308	switch (alg) {
309	case CRYPTO_CIPHER_ALG_AES:
310		idx = find_cipher("aes");
311		break;
312	case CRYPTO_CIPHER_ALG_3DES:
313		idx = find_cipher("3des");
314		break;
315	case CRYPTO_CIPHER_ALG_DES:
316		idx = find_cipher("des");
317		break;
318	case CRYPTO_CIPHER_ALG_RC2:
319		idx = find_cipher("rc2");
320		break;
321	case CRYPTO_CIPHER_ALG_RC4:
322		idx = -1;
323		rc4 = 1;
324		break;
325	default:
326		return NULL;
327	}
328
329	ctx = os_zalloc(sizeof(*ctx));
330	if (ctx == NULL)
331		return NULL;
332
333	if (rc4) {
334		ctx->rc4 = 1;
335		if (key_len > sizeof(ctx->u.rc4.key)) {
336			os_free(ctx);
337			return NULL;
338		}
339		ctx->u.rc4.keylen = key_len;
340		os_memcpy(ctx->u.rc4.key, key, key_len);
341	} else {
342		res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
343		if (res != CRYPT_OK) {
344			wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
345				   "failed: %s", error_to_string(res));
346			os_free(ctx);
347			return NULL;
348		}
349	}
350
351	return ctx;
352}
353
354int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
355			  u8 *crypt, size_t len)
356{
357	int res;
358
359	if (ctx->rc4) {
360		if (plain != crypt)
361			os_memcpy(crypt, plain, len);
362		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
363			 ctx->u.rc4.used_bytes, crypt, len);
364		ctx->u.rc4.used_bytes += len;
365		return 0;
366	}
367
368	res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
369	if (res != CRYPT_OK) {
370		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
371			   "failed: %s", error_to_string(res));
372		return -1;
373	}
374	return 0;
375}
376
377
378int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
379			  u8 *plain, size_t len)
380{
381	int res;
382
383	if (ctx->rc4) {
384		if (plain != crypt)
385			os_memcpy(plain, crypt, len);
386		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
387			 ctx->u.rc4.used_bytes, plain, len);
388		ctx->u.rc4.used_bytes += len;
389		return 0;
390	}
391
392	res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
393	if (res != CRYPT_OK) {
394		wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
395			   "failed: %s", error_to_string(res));
396		return -1;
397	}
398
399	return 0;
400}
401
402
403void crypto_cipher_deinit(struct crypto_cipher *ctx)
404{
405	if (!ctx->rc4)
406		cbc_done(&ctx->u.cbc);
407	os_free(ctx);
408}
409
410
411struct crypto_public_key {
412	rsa_key rsa;
413};
414
415struct crypto_private_key {
416	rsa_key rsa;
417};
418
419
420struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
421{
422	int res;
423	struct crypto_public_key *pk;
424
425	pk = os_zalloc(sizeof(*pk));
426	if (pk == NULL)
427		return NULL;
428
429	res = rsa_import(key, len, &pk->rsa);
430	if (res != CRYPT_OK) {
431		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
432			   "public key (res=%d '%s')",
433			   res, error_to_string(res));
434		os_free(pk);
435		return NULL;
436	}
437
438	if (pk->rsa.type != PK_PUBLIC) {
439		wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
440			   "correct type");
441		rsa_free(&pk->rsa);
442		os_free(pk);
443		return NULL;
444	}
445
446	return pk;
447}
448
449
450struct crypto_private_key * crypto_private_key_import(const u8 *key,
451						      size_t len,
452						      const char *passwd)
453{
454	int res;
455	struct crypto_private_key *pk;
456
457	pk = os_zalloc(sizeof(*pk));
458	if (pk == NULL)
459		return NULL;
460
461	res = rsa_import(key, len, &pk->rsa);
462	if (res != CRYPT_OK) {
463		wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
464			   "private key (res=%d '%s')",
465			   res, error_to_string(res));
466		os_free(pk);
467		return NULL;
468	}
469
470	if (pk->rsa.type != PK_PRIVATE) {
471		wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
472			   "correct type");
473		rsa_free(&pk->rsa);
474		os_free(pk);
475		return NULL;
476	}
477
478	return pk;
479}
480
481
482struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
483						       size_t len)
484{
485	/* No X.509 support in LibTomCrypt */
486	return NULL;
487}
488
489
490static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
491					   const u8 *in, size_t inlen,
492					   u8 *out, size_t *outlen)
493{
494	size_t ps_len;
495	u8 *pos;
496
497	/*
498	 * PKCS #1 v1.5, 8.1:
499	 *
500	 * EB = 00 || BT || PS || 00 || D
501	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
502	 * PS = k-3-||D||; at least eight octets
503	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
504	 * k = length of modulus in octets (modlen)
505	 */
506
507	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
508		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
509			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
510			   __func__, (unsigned long) modlen,
511			   (unsigned long) *outlen,
512			   (unsigned long) inlen);
513		return -1;
514	}
515
516	pos = out;
517	*pos++ = 0x00;
518	*pos++ = block_type; /* BT */
519	ps_len = modlen - inlen - 3;
520	switch (block_type) {
521	case 0:
522		os_memset(pos, 0x00, ps_len);
523		pos += ps_len;
524		break;
525	case 1:
526		os_memset(pos, 0xff, ps_len);
527		pos += ps_len;
528		break;
529	case 2:
530		if (os_get_random(pos, ps_len) < 0) {
531			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
532				   "random data for PS", __func__);
533			return -1;
534		}
535		while (ps_len--) {
536			if (*pos == 0x00)
537				*pos = 0x01;
538			pos++;
539		}
540		break;
541	default:
542		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
543			   "%d", __func__, block_type);
544		return -1;
545	}
546	*pos++ = 0x00;
547	os_memcpy(pos, in, inlen); /* D */
548
549	return 0;
550}
551
552
553static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
554				    const u8 *in, size_t inlen,
555				    u8 *out, size_t *outlen)
556{
557	unsigned long len, modlen;
558	int res;
559
560	modlen = mp_unsigned_bin_size(key->N);
561
562	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
563					    out, outlen) < 0)
564		return -1;
565
566	len = *outlen;
567	res = rsa_exptmod(out, modlen, out, &len, key_type, key);
568	if (res != CRYPT_OK) {
569		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
570			   error_to_string(res));
571		return -1;
572	}
573	*outlen = len;
574
575	return 0;
576}
577
578
579int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
580					const u8 *in, size_t inlen,
581					u8 *out, size_t *outlen)
582{
583	return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
584					out, outlen);
585}
586
587
588int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
589				  const u8 *in, size_t inlen,
590				  u8 *out, size_t *outlen)
591{
592	return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
593					out, outlen);
594}
595
596
597void crypto_public_key_free(struct crypto_public_key *key)
598{
599	if (key) {
600		rsa_free(&key->rsa);
601		os_free(key);
602	}
603}
604
605
606void crypto_private_key_free(struct crypto_private_key *key)
607{
608	if (key) {
609		rsa_free(&key->rsa);
610		os_free(key);
611	}
612}
613
614
615int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
616				    const u8 *crypt, size_t crypt_len,
617				    u8 *plain, size_t *plain_len)
618{
619	int res;
620	unsigned long len;
621	u8 *pos;
622
623	len = *plain_len;
624	res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
625			  &key->rsa);
626	if (res != CRYPT_OK) {
627		wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
628			   error_to_string(res));
629		return -1;
630	}
631
632	/*
633	 * PKCS #1 v1.5, 8.1:
634	 *
635	 * EB = 00 || BT || PS || 00 || D
636	 * BT = 01
637	 * PS = k-3-||D|| times FF
638	 * k = length of modulus in octets
639	 */
640
641	if (len < 3 + 8 + 16 /* min hash len */ ||
642	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
643		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
644			   "structure");
645		return -1;
646	}
647
648	pos = plain + 3;
649	while (pos < plain + len && *pos == 0xff)
650		pos++;
651	if (pos - plain - 2 < 8) {
652		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
653		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
654			   "padding");
655		return -1;
656	}
657
658	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
659		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
660			   "structure (2)");
661		return -1;
662	}
663	pos++;
664	len -= pos - plain;
665
666	/* Strip PKCS #1 header */
667	os_memmove(plain, pos, len);
668	*plain_len = len;
669
670	return 0;
671}
672
673
674int crypto_global_init(void)
675{
676	ltc_mp = tfm_desc;
677	/* TODO: only register algorithms that are really needed */
678	if (register_hash(&md4_desc) < 0 ||
679	    register_hash(&md5_desc) < 0 ||
680	    register_hash(&sha1_desc) < 0 ||
681	    register_cipher(&aes_desc) < 0 ||
682	    register_cipher(&des_desc) < 0 ||
683	    register_cipher(&des3_desc) < 0) {
684		wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
685			   "hash/cipher functions");
686		return -1;
687	}
688
689	return 0;
690}
691
692
693void crypto_global_deinit(void)
694{
695}
696
697
698#ifdef CONFIG_MODEXP
699
700int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
701		   u8 *pubkey)
702{
703	size_t pubkey_len, pad;
704
705	if (os_get_random(privkey, prime_len) < 0)
706		return -1;
707	if (os_memcmp(privkey, prime, prime_len) > 0) {
708		/* Make sure private value is smaller than prime */
709		privkey[0] = 0;
710	}
711
712	pubkey_len = prime_len;
713	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
714			   pubkey, &pubkey_len) < 0)
715		return -1;
716	if (pubkey_len < prime_len) {
717		pad = prime_len - pubkey_len;
718		os_memmove(pubkey + pad, pubkey, pubkey_len);
719		os_memset(pubkey, 0, pad);
720	}
721
722	return 0;
723}
724
725
726int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
727			    const u8 *order, size_t order_len,
728			    const u8 *privkey, size_t privkey_len,
729			    const u8 *pubkey, size_t pubkey_len,
730			    u8 *secret, size_t *len)
731{
732	/* TODO: check pubkey */
733	return crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
734			      prime, prime_len, secret, len);
735}
736
737
738int crypto_mod_exp(const u8 *base, size_t base_len,
739		   const u8 *power, size_t power_len,
740		   const u8 *modulus, size_t modulus_len,
741		   u8 *result, size_t *result_len)
742{
743	void *b, *p, *m, *r;
744
745	if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
746		return -1;
747
748	if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
749	    mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
750	    mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
751		goto fail;
752
753	if (mp_exptmod(b, p, m, r) != CRYPT_OK)
754		goto fail;
755
756	*result_len = mp_unsigned_bin_size(r);
757	if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
758		goto fail;
759
760	mp_clear_multi(b, p, m, r, NULL);
761	return 0;
762
763fail:
764	mp_clear_multi(b, p, m, r, NULL);
765	return -1;
766}
767
768#endif /* CONFIG_MODEXP */
769