1/*
2 * WPA Supplicant / wrapper functions for libgcrypt
3 * Copyright (c) 2004-2009, 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 <gcrypt.h>
17
18#include "common.h"
19#include "crypto.h"
20
21void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
22{
23	gcry_md_hd_t hd;
24	unsigned char *p;
25	size_t i;
26
27	if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
28		return;
29	for (i = 0; i < num_elem; i++)
30		gcry_md_write(hd, addr[i], len[i]);
31	p = gcry_md_read(hd, GCRY_MD_MD4);
32	if (p)
33		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
34	gcry_md_close(hd);
35}
36
37
38void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
39{
40	gcry_cipher_hd_t hd;
41	u8 pkey[8], next, tmp;
42	int i;
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	gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
54	gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
55	gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
56	gcry_cipher_close(hd);
57}
58
59
60void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
61{
62	gcry_md_hd_t hd;
63	unsigned char *p;
64	size_t i;
65
66	if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
67		return;
68	for (i = 0; i < num_elem; i++)
69		gcry_md_write(hd, addr[i], len[i]);
70	p = gcry_md_read(hd, GCRY_MD_MD5);
71	if (p)
72		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
73	gcry_md_close(hd);
74}
75
76
77void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
78{
79	gcry_md_hd_t hd;
80	unsigned char *p;
81	size_t i;
82
83	if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
84		return;
85	for (i = 0; i < num_elem; i++)
86		gcry_md_write(hd, addr[i], len[i]);
87	p = gcry_md_read(hd, GCRY_MD_SHA1);
88	if (p)
89		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
90	gcry_md_close(hd);
91}
92
93
94#ifndef CONFIG_NO_FIPS186_2_PRF
95int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
96{
97	/* FIX: how to do this with libgcrypt? */
98	return -1;
99}
100#endif /* CONFIG_NO_FIPS186_2_PRF */
101
102
103void * aes_encrypt_init(const u8 *key, size_t len)
104{
105	gcry_cipher_hd_t hd;
106
107	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
108	    GPG_ERR_NO_ERROR) {
109		printf("cipher open failed\n");
110		return NULL;
111	}
112	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
113		printf("setkey failed\n");
114		gcry_cipher_close(hd);
115		return NULL;
116	}
117
118	return hd;
119}
120
121
122void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
123{
124	gcry_cipher_hd_t hd = ctx;
125	gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
126}
127
128
129void aes_encrypt_deinit(void *ctx)
130{
131	gcry_cipher_hd_t hd = ctx;
132	gcry_cipher_close(hd);
133}
134
135
136void * aes_decrypt_init(const u8 *key, size_t len)
137{
138	gcry_cipher_hd_t hd;
139
140	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
141	    GPG_ERR_NO_ERROR)
142		return NULL;
143	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
144		gcry_cipher_close(hd);
145		return NULL;
146	}
147
148	return hd;
149}
150
151
152void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
153{
154	gcry_cipher_hd_t hd = ctx;
155	gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
156}
157
158
159void aes_decrypt_deinit(void *ctx)
160{
161	gcry_cipher_hd_t hd = ctx;
162	gcry_cipher_close(hd);
163}
164
165
166int crypto_mod_exp(const u8 *base, size_t base_len,
167		   const u8 *power, size_t power_len,
168		   const u8 *modulus, size_t modulus_len,
169		   u8 *result, size_t *result_len)
170{
171	gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
172		bn_result = NULL;
173	int ret = -1;
174
175	if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
176	    GPG_ERR_NO_ERROR ||
177	    gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
178	    GPG_ERR_NO_ERROR ||
179	    gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
180			  NULL) != GPG_ERR_NO_ERROR)
181		goto error;
182	bn_result = gcry_mpi_new(modulus_len * 8);
183
184	gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
185
186	if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
187			   bn_result) != GPG_ERR_NO_ERROR)
188		goto error;
189
190	ret = 0;
191
192error:
193	gcry_mpi_release(bn_base);
194	gcry_mpi_release(bn_exp);
195	gcry_mpi_release(bn_modulus);
196	gcry_mpi_release(bn_result);
197	return ret;
198}
199
200
201struct crypto_cipher {
202	gcry_cipher_hd_t enc;
203	gcry_cipher_hd_t dec;
204};
205
206
207struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
208					  const u8 *iv, const u8 *key,
209					  size_t key_len)
210{
211	struct crypto_cipher *ctx;
212	gcry_error_t res;
213	enum gcry_cipher_algos a;
214	int ivlen;
215
216	ctx = os_zalloc(sizeof(*ctx));
217	if (ctx == NULL)
218		return NULL;
219
220	switch (alg) {
221	case CRYPTO_CIPHER_ALG_RC4:
222		a = GCRY_CIPHER_ARCFOUR;
223		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
224				       0);
225		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
226		break;
227	case CRYPTO_CIPHER_ALG_AES:
228		if (key_len == 24)
229			a = GCRY_CIPHER_AES192;
230		else if (key_len == 32)
231			a = GCRY_CIPHER_AES256;
232		else
233			a = GCRY_CIPHER_AES;
234		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
235		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
236		break;
237	case CRYPTO_CIPHER_ALG_3DES:
238		a = GCRY_CIPHER_3DES;
239		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
240		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
241		break;
242	case CRYPTO_CIPHER_ALG_DES:
243		a = GCRY_CIPHER_DES;
244		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
245		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
246		break;
247	case CRYPTO_CIPHER_ALG_RC2:
248		if (key_len == 5)
249			a = GCRY_CIPHER_RFC2268_40;
250		else
251			a = GCRY_CIPHER_RFC2268_128;
252		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
253		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
254		break;
255	default:
256		os_free(ctx);
257		return NULL;
258	}
259
260	if (res != GPG_ERR_NO_ERROR) {
261		os_free(ctx);
262		return NULL;
263	}
264
265	if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
266	    gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
267		gcry_cipher_close(ctx->enc);
268		gcry_cipher_close(ctx->dec);
269		os_free(ctx);
270		return NULL;
271	}
272
273	ivlen = gcry_cipher_get_algo_blklen(a);
274	if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
275	    gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
276		gcry_cipher_close(ctx->enc);
277		gcry_cipher_close(ctx->dec);
278		os_free(ctx);
279		return NULL;
280	}
281
282	return ctx;
283}
284
285
286int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
287			  u8 *crypt, size_t len)
288{
289	if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
290	    GPG_ERR_NO_ERROR)
291		return -1;
292	return 0;
293}
294
295
296int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
297			  u8 *plain, size_t len)
298{
299	if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
300	    GPG_ERR_NO_ERROR)
301		return -1;
302	return 0;
303}
304
305
306void crypto_cipher_deinit(struct crypto_cipher *ctx)
307{
308	gcry_cipher_close(ctx->enc);
309	gcry_cipher_close(ctx->dec);
310	os_free(ctx);
311}
312