18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / wrapper functions for libgcrypt
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <gcrypt.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_hd_t hd;
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char *p;
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_md_write(hd, addr[i], len[i]);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = gcry_md_read(hd, GCRY_MD_MD4);
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p)
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_close(hd);
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pkey[8], next, tmp;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Add parity bits to the key */
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	next = 0;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 7; i++) {
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = key[i];
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pkey[i] = (tmp >> i) | next | 1;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = tmp << (7 - i);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pkey[i] = next | 1;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_close(hd);
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_hd_t hd;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char *p;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_md_write(hd, addr[i], len[i]);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = gcry_md_read(hd, GCRY_MD_MD5);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p)
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_close(hd);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_hd_t hd;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char *p;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_md_write(hd, addr[i], len[i]);
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = gcry_md_read(hd, GCRY_MD_SHA1);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_md_close(hd);
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_encrypt_init(const u8 *key, size_t len)
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR) {
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("cipher open failed\n");
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("setkey failed\n");
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(hd);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return hd;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd = ctx;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt_deinit(void *ctx)
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd = ctx;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_close(hd);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_decrypt_init(const u8 *key, size_t len)
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(hd);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return hd;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd = ctx;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt_deinit(void *ctx)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t hd = ctx;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_close(hd);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *power, size_t power_len,
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *modulus, size_t modulus_len,
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   u8 *result, size_t *result_len)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bn_result = NULL;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR ||
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR ||
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  NULL) != GPG_ERR_NO_ERROR)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto error;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bn_result = gcry_mpi_new(modulus_len * 8);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   bn_result) != GPG_ERR_NO_ERROR)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto error;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror:
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_release(bn_base);
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_release(bn_exp);
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_release(bn_modulus);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_mpi_release(bn_result);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher {
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t enc;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_hd_t dec;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *iv, const u8 *key,
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t key_len)
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_cipher *ctx;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_error_t res;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum gcry_cipher_algos a;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ivlen;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		a = GCRY_CIPHER_ARCFOUR;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       0);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_len == 24)
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			a = GCRY_CIPHER_AES192;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (key_len == 32)
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			a = GCRY_CIPHER_AES256;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			a = GCRY_CIPHER_AES;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		a = GCRY_CIPHER_3DES;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_DES:
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		a = GCRY_CIPHER_DES;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC2:
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_len == 5)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			a = GCRY_CIPHER_RFC2268_40;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			a = GCRY_CIPHER_RFC2268_128;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != GPG_ERR_NO_ERROR) {
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(ctx->enc);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(ctx->dec);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ivlen = gcry_cipher_get_algo_blklen(a);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(ctx->enc);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gcry_cipher_close(ctx->dec);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *crypt, size_t len)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *plain, size_t len)
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    GPG_ERR_NO_ERROR)
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_close(ctx->enc);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gcry_cipher_close(ctx->dec);
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
300