xref: /freebsd/contrib/wpa/src/crypto/crypto_gnutls.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * WPA Supplicant / wrapper functions for libgcrypt
339beb93cSSam Leffler  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler #include <gcrypt.h>
1739beb93cSSam Leffler 
1839beb93cSSam Leffler #include "common.h"
1939beb93cSSam Leffler #include "crypto.h"
2039beb93cSSam Leffler 
2139beb93cSSam Leffler void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
2239beb93cSSam Leffler {
2339beb93cSSam Leffler 	gcry_md_hd_t hd;
2439beb93cSSam Leffler 	unsigned char *p;
2539beb93cSSam Leffler 	size_t i;
2639beb93cSSam Leffler 
2739beb93cSSam Leffler 	if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
2839beb93cSSam Leffler 		return;
2939beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
3039beb93cSSam Leffler 		gcry_md_write(hd, addr[i], len[i]);
3139beb93cSSam Leffler 	p = gcry_md_read(hd, GCRY_MD_MD4);
3239beb93cSSam Leffler 	if (p)
3339beb93cSSam Leffler 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
3439beb93cSSam Leffler 	gcry_md_close(hd);
3539beb93cSSam Leffler }
3639beb93cSSam Leffler 
3739beb93cSSam Leffler 
3839beb93cSSam Leffler void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
3939beb93cSSam Leffler {
4039beb93cSSam Leffler 	gcry_cipher_hd_t hd;
4139beb93cSSam Leffler 	u8 pkey[8], next, tmp;
4239beb93cSSam Leffler 	int i;
4339beb93cSSam Leffler 
4439beb93cSSam Leffler 	/* Add parity bits to the key */
4539beb93cSSam Leffler 	next = 0;
4639beb93cSSam Leffler 	for (i = 0; i < 7; i++) {
4739beb93cSSam Leffler 		tmp = key[i];
4839beb93cSSam Leffler 		pkey[i] = (tmp >> i) | next | 1;
4939beb93cSSam Leffler 		next = tmp << (7 - i);
5039beb93cSSam Leffler 	}
5139beb93cSSam Leffler 	pkey[i] = next | 1;
5239beb93cSSam Leffler 
5339beb93cSSam Leffler 	gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
5439beb93cSSam Leffler 	gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
5539beb93cSSam Leffler 	gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
5639beb93cSSam Leffler 	gcry_cipher_close(hd);
5739beb93cSSam Leffler }
5839beb93cSSam Leffler 
5939beb93cSSam Leffler 
6039beb93cSSam Leffler #ifdef EAP_TLS_FUNCS
6139beb93cSSam Leffler void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
6239beb93cSSam Leffler {
6339beb93cSSam Leffler 	gcry_md_hd_t hd;
6439beb93cSSam Leffler 	unsigned char *p;
6539beb93cSSam Leffler 	size_t i;
6639beb93cSSam Leffler 
6739beb93cSSam Leffler 	if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
6839beb93cSSam Leffler 		return;
6939beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
7039beb93cSSam Leffler 		gcry_md_write(hd, addr[i], len[i]);
7139beb93cSSam Leffler 	p = gcry_md_read(hd, GCRY_MD_MD5);
7239beb93cSSam Leffler 	if (p)
7339beb93cSSam Leffler 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
7439beb93cSSam Leffler 	gcry_md_close(hd);
7539beb93cSSam Leffler }
7639beb93cSSam Leffler 
7739beb93cSSam Leffler 
7839beb93cSSam Leffler void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
7939beb93cSSam Leffler {
8039beb93cSSam Leffler 	gcry_md_hd_t hd;
8139beb93cSSam Leffler 	unsigned char *p;
8239beb93cSSam Leffler 	size_t i;
8339beb93cSSam Leffler 
8439beb93cSSam Leffler 	if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
8539beb93cSSam Leffler 		return;
8639beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
8739beb93cSSam Leffler 		gcry_md_write(hd, addr[i], len[i]);
8839beb93cSSam Leffler 	p = gcry_md_read(hd, GCRY_MD_SHA1);
8939beb93cSSam Leffler 	if (p)
9039beb93cSSam Leffler 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
9139beb93cSSam Leffler 	gcry_md_close(hd);
9239beb93cSSam Leffler }
9339beb93cSSam Leffler 
9439beb93cSSam Leffler 
9539beb93cSSam Leffler #ifndef CONFIG_NO_FIPS186_2_PRF
9639beb93cSSam Leffler int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
9739beb93cSSam Leffler {
9839beb93cSSam Leffler 	/* FIX: how to do this with libgcrypt? */
9939beb93cSSam Leffler 	return -1;
10039beb93cSSam Leffler }
10139beb93cSSam Leffler #endif /* CONFIG_NO_FIPS186_2_PRF */
10239beb93cSSam Leffler 
10339beb93cSSam Leffler 
10439beb93cSSam Leffler void * aes_encrypt_init(const u8 *key, size_t len)
10539beb93cSSam Leffler {
10639beb93cSSam Leffler 	gcry_cipher_hd_t hd;
10739beb93cSSam Leffler 
10839beb93cSSam Leffler 	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
10939beb93cSSam Leffler 	    GPG_ERR_NO_ERROR) {
11039beb93cSSam Leffler 		printf("cipher open failed\n");
11139beb93cSSam Leffler 		return NULL;
11239beb93cSSam Leffler 	}
11339beb93cSSam Leffler 	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
11439beb93cSSam Leffler 		printf("setkey failed\n");
11539beb93cSSam Leffler 		gcry_cipher_close(hd);
11639beb93cSSam Leffler 		return NULL;
11739beb93cSSam Leffler 	}
11839beb93cSSam Leffler 
11939beb93cSSam Leffler 	return hd;
12039beb93cSSam Leffler }
12139beb93cSSam Leffler 
12239beb93cSSam Leffler 
12339beb93cSSam Leffler void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
12439beb93cSSam Leffler {
12539beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
12639beb93cSSam Leffler 	gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
12739beb93cSSam Leffler }
12839beb93cSSam Leffler 
12939beb93cSSam Leffler 
13039beb93cSSam Leffler void aes_encrypt_deinit(void *ctx)
13139beb93cSSam Leffler {
13239beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
13339beb93cSSam Leffler 	gcry_cipher_close(hd);
13439beb93cSSam Leffler }
13539beb93cSSam Leffler 
13639beb93cSSam Leffler 
13739beb93cSSam Leffler void * aes_decrypt_init(const u8 *key, size_t len)
13839beb93cSSam Leffler {
13939beb93cSSam Leffler 	gcry_cipher_hd_t hd;
14039beb93cSSam Leffler 
14139beb93cSSam Leffler 	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
14239beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
14339beb93cSSam Leffler 		return NULL;
14439beb93cSSam Leffler 	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
14539beb93cSSam Leffler 		gcry_cipher_close(hd);
14639beb93cSSam Leffler 		return NULL;
14739beb93cSSam Leffler 	}
14839beb93cSSam Leffler 
14939beb93cSSam Leffler 	return hd;
15039beb93cSSam Leffler }
15139beb93cSSam Leffler 
15239beb93cSSam Leffler 
15339beb93cSSam Leffler void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
15439beb93cSSam Leffler {
15539beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
15639beb93cSSam Leffler 	gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
15739beb93cSSam Leffler }
15839beb93cSSam Leffler 
15939beb93cSSam Leffler 
16039beb93cSSam Leffler void aes_decrypt_deinit(void *ctx)
16139beb93cSSam Leffler {
16239beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
16339beb93cSSam Leffler 	gcry_cipher_close(hd);
16439beb93cSSam Leffler }
16539beb93cSSam Leffler #endif /* EAP_TLS_FUNCS */
16639beb93cSSam Leffler 
16739beb93cSSam Leffler 
16839beb93cSSam Leffler int crypto_mod_exp(const u8 *base, size_t base_len,
16939beb93cSSam Leffler 		   const u8 *power, size_t power_len,
17039beb93cSSam Leffler 		   const u8 *modulus, size_t modulus_len,
17139beb93cSSam Leffler 		   u8 *result, size_t *result_len)
17239beb93cSSam Leffler {
17339beb93cSSam Leffler 	gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
17439beb93cSSam Leffler 		bn_result = NULL;
17539beb93cSSam Leffler 	int ret = -1;
17639beb93cSSam Leffler 
17739beb93cSSam Leffler 	if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
17839beb93cSSam Leffler 	    GPG_ERR_NO_ERROR ||
17939beb93cSSam Leffler 	    gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
18039beb93cSSam Leffler 	    GPG_ERR_NO_ERROR ||
18139beb93cSSam Leffler 	    gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
18239beb93cSSam Leffler 			  NULL) != GPG_ERR_NO_ERROR)
18339beb93cSSam Leffler 		goto error;
18439beb93cSSam Leffler 	bn_result = gcry_mpi_new(modulus_len * 8);
18539beb93cSSam Leffler 
18639beb93cSSam Leffler 	gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
18739beb93cSSam Leffler 
18839beb93cSSam Leffler 	if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
18939beb93cSSam Leffler 			   bn_result) != GPG_ERR_NO_ERROR)
19039beb93cSSam Leffler 		goto error;
19139beb93cSSam Leffler 
19239beb93cSSam Leffler 	ret = 0;
19339beb93cSSam Leffler 
19439beb93cSSam Leffler error:
19539beb93cSSam Leffler 	gcry_mpi_release(bn_base);
19639beb93cSSam Leffler 	gcry_mpi_release(bn_exp);
19739beb93cSSam Leffler 	gcry_mpi_release(bn_modulus);
19839beb93cSSam Leffler 	gcry_mpi_release(bn_result);
19939beb93cSSam Leffler 	return ret;
20039beb93cSSam Leffler }
20139beb93cSSam Leffler 
20239beb93cSSam Leffler 
20339beb93cSSam Leffler struct crypto_cipher {
20439beb93cSSam Leffler 	gcry_cipher_hd_t enc;
20539beb93cSSam Leffler 	gcry_cipher_hd_t dec;
20639beb93cSSam Leffler };
20739beb93cSSam Leffler 
20839beb93cSSam Leffler 
20939beb93cSSam Leffler struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
21039beb93cSSam Leffler 					  const u8 *iv, const u8 *key,
21139beb93cSSam Leffler 					  size_t key_len)
21239beb93cSSam Leffler {
21339beb93cSSam Leffler 	struct crypto_cipher *ctx;
21439beb93cSSam Leffler 	gcry_error_t res;
21539beb93cSSam Leffler 	enum gcry_cipher_algos a;
21639beb93cSSam Leffler 	int ivlen;
21739beb93cSSam Leffler 
21839beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
21939beb93cSSam Leffler 	if (ctx == NULL)
22039beb93cSSam Leffler 		return NULL;
22139beb93cSSam Leffler 
22239beb93cSSam Leffler 	switch (alg) {
22339beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC4:
22439beb93cSSam Leffler 		a = GCRY_CIPHER_ARCFOUR;
22539beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
22639beb93cSSam Leffler 				       0);
22739beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
22839beb93cSSam Leffler 		break;
22939beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_AES:
23039beb93cSSam Leffler 		if (key_len == 24)
23139beb93cSSam Leffler 			a = GCRY_CIPHER_AES192;
23239beb93cSSam Leffler 		else if (key_len == 32)
23339beb93cSSam Leffler 			a = GCRY_CIPHER_AES256;
23439beb93cSSam Leffler 		else
23539beb93cSSam Leffler 			a = GCRY_CIPHER_AES;
23639beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
23739beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
23839beb93cSSam Leffler 		break;
23939beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_3DES:
24039beb93cSSam Leffler 		a = GCRY_CIPHER_3DES;
24139beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
24239beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
24339beb93cSSam Leffler 		break;
24439beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_DES:
24539beb93cSSam Leffler 		a = GCRY_CIPHER_DES;
24639beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
24739beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
24839beb93cSSam Leffler 		break;
24939beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC2:
25039beb93cSSam Leffler 		if (key_len == 5)
25139beb93cSSam Leffler 			a = GCRY_CIPHER_RFC2268_40;
25239beb93cSSam Leffler 		else
25339beb93cSSam Leffler 			a = GCRY_CIPHER_RFC2268_128;
25439beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
25539beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
25639beb93cSSam Leffler 		break;
25739beb93cSSam Leffler 	default:
25839beb93cSSam Leffler 		os_free(ctx);
25939beb93cSSam Leffler 		return NULL;
26039beb93cSSam Leffler 	}
26139beb93cSSam Leffler 
26239beb93cSSam Leffler 	if (res != GPG_ERR_NO_ERROR) {
26339beb93cSSam Leffler 		os_free(ctx);
26439beb93cSSam Leffler 		return NULL;
26539beb93cSSam Leffler 	}
26639beb93cSSam Leffler 
26739beb93cSSam Leffler 	if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
26839beb93cSSam Leffler 	    gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
26939beb93cSSam Leffler 		gcry_cipher_close(ctx->enc);
27039beb93cSSam Leffler 		gcry_cipher_close(ctx->dec);
27139beb93cSSam Leffler 		os_free(ctx);
27239beb93cSSam Leffler 		return NULL;
27339beb93cSSam Leffler 	}
27439beb93cSSam Leffler 
27539beb93cSSam Leffler 	ivlen = gcry_cipher_get_algo_blklen(a);
27639beb93cSSam Leffler 	if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
27739beb93cSSam Leffler 	    gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
27839beb93cSSam Leffler 		gcry_cipher_close(ctx->enc);
27939beb93cSSam Leffler 		gcry_cipher_close(ctx->dec);
28039beb93cSSam Leffler 		os_free(ctx);
28139beb93cSSam Leffler 		return NULL;
28239beb93cSSam Leffler 	}
28339beb93cSSam Leffler 
28439beb93cSSam Leffler 	return ctx;
28539beb93cSSam Leffler }
28639beb93cSSam Leffler 
28739beb93cSSam Leffler 
28839beb93cSSam Leffler int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
28939beb93cSSam Leffler 			  u8 *crypt, size_t len)
29039beb93cSSam Leffler {
29139beb93cSSam Leffler 	if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
29239beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
29339beb93cSSam Leffler 		return -1;
29439beb93cSSam Leffler 	return 0;
29539beb93cSSam Leffler }
29639beb93cSSam Leffler 
29739beb93cSSam Leffler 
29839beb93cSSam Leffler int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
29939beb93cSSam Leffler 			  u8 *plain, size_t len)
30039beb93cSSam Leffler {
30139beb93cSSam Leffler 	if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
30239beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
30339beb93cSSam Leffler 		return -1;
30439beb93cSSam Leffler 	return 0;
30539beb93cSSam Leffler }
30639beb93cSSam Leffler 
30739beb93cSSam Leffler 
30839beb93cSSam Leffler void crypto_cipher_deinit(struct crypto_cipher *ctx)
30939beb93cSSam Leffler {
31039beb93cSSam Leffler 	gcry_cipher_close(ctx->enc);
31139beb93cSSam Leffler 	gcry_cipher_close(ctx->dec);
31239beb93cSSam Leffler 	os_free(ctx);
31339beb93cSSam Leffler }
314