xref: /freebsd/contrib/wpa/src/crypto/crypto_gnutls.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * WPA Supplicant / wrapper functions for libgcrypt
385732ac8SCy Schubert  * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler #include <gcrypt.h>
1139beb93cSSam Leffler 
1239beb93cSSam Leffler #include "common.h"
1385732ac8SCy Schubert #include "md5.h"
1485732ac8SCy Schubert #include "sha1.h"
1585732ac8SCy Schubert #include "sha256.h"
1685732ac8SCy Schubert #include "sha384.h"
1785732ac8SCy Schubert #include "sha512.h"
1839beb93cSSam Leffler #include "crypto.h"
1939beb93cSSam Leffler 
gnutls_digest_vector(int algo,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)2085732ac8SCy Schubert static int gnutls_digest_vector(int algo, size_t num_elem,
2185732ac8SCy Schubert 				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 
2785732ac8SCy Schubert 	if (TEST_FAIL())
2885732ac8SCy Schubert 		return -1;
2985732ac8SCy Schubert 
3085732ac8SCy Schubert 	if (gcry_md_open(&hd, algo, 0) != GPG_ERR_NO_ERROR)
31e28a4053SRui Paulo 		return -1;
3239beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
3339beb93cSSam Leffler 		gcry_md_write(hd, addr[i], len[i]);
3485732ac8SCy Schubert 	p = gcry_md_read(hd, algo);
3539beb93cSSam Leffler 	if (p)
3685732ac8SCy Schubert 		memcpy(mac, p, gcry_md_get_algo_dlen(algo));
3739beb93cSSam Leffler 	gcry_md_close(hd);
38e28a4053SRui Paulo 	return 0;
3939beb93cSSam Leffler }
4039beb93cSSam Leffler 
4139beb93cSSam Leffler 
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)4285732ac8SCy Schubert int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
4385732ac8SCy Schubert {
4485732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_MD4, num_elem, addr, len, mac);
4585732ac8SCy Schubert }
4685732ac8SCy Schubert 
4785732ac8SCy Schubert 
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)4885732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
4939beb93cSSam Leffler {
5039beb93cSSam Leffler 	gcry_cipher_hd_t hd;
5139beb93cSSam Leffler 	u8 pkey[8], next, tmp;
5239beb93cSSam Leffler 	int i;
5339beb93cSSam Leffler 
5439beb93cSSam Leffler 	/* Add parity bits to the key */
5539beb93cSSam Leffler 	next = 0;
5639beb93cSSam Leffler 	for (i = 0; i < 7; i++) {
5739beb93cSSam Leffler 		tmp = key[i];
5839beb93cSSam Leffler 		pkey[i] = (tmp >> i) | next | 1;
5939beb93cSSam Leffler 		next = tmp << (7 - i);
6039beb93cSSam Leffler 	}
6139beb93cSSam Leffler 	pkey[i] = next | 1;
6239beb93cSSam Leffler 
6339beb93cSSam Leffler 	gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
6439beb93cSSam Leffler 	gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
6539beb93cSSam Leffler 	gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
6639beb93cSSam Leffler 	gcry_cipher_close(hd);
6785732ac8SCy Schubert 	return 0;
6839beb93cSSam Leffler }
6939beb93cSSam Leffler 
7039beb93cSSam Leffler 
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)71e28a4053SRui Paulo int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
7239beb93cSSam Leffler {
7385732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_MD5, num_elem, addr, len, mac);
7439beb93cSSam Leffler }
7539beb93cSSam Leffler 
7639beb93cSSam Leffler 
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)77e28a4053SRui Paulo int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
7839beb93cSSam Leffler {
7985732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_SHA1, num_elem, addr, len, mac);
8085732ac8SCy Schubert }
8185732ac8SCy Schubert 
8285732ac8SCy Schubert 
sha256_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)8385732ac8SCy Schubert int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
8485732ac8SCy Schubert {
8585732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_SHA256, num_elem, addr, len, mac);
8685732ac8SCy Schubert }
8785732ac8SCy Schubert 
8885732ac8SCy Schubert 
sha384_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)8985732ac8SCy Schubert int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
9085732ac8SCy Schubert {
9185732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_SHA384, num_elem, addr, len, mac);
9285732ac8SCy Schubert }
9385732ac8SCy Schubert 
9485732ac8SCy Schubert 
sha512_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)9585732ac8SCy Schubert int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
9685732ac8SCy Schubert {
9785732ac8SCy Schubert 	return gnutls_digest_vector(GCRY_MD_SHA512, num_elem, addr, len, mac);
9885732ac8SCy Schubert }
9985732ac8SCy Schubert 
10085732ac8SCy Schubert 
gnutls_hmac_vector(int algo,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)10185732ac8SCy Schubert static int gnutls_hmac_vector(int algo, const u8 *key, size_t key_len,
10285732ac8SCy Schubert 			      size_t num_elem, const u8 *addr[],
10385732ac8SCy Schubert 			      const size_t *len, u8 *mac)
10485732ac8SCy Schubert {
10539beb93cSSam Leffler 	gcry_md_hd_t hd;
10639beb93cSSam Leffler 	unsigned char *p;
10739beb93cSSam Leffler 	size_t i;
10839beb93cSSam Leffler 
10985732ac8SCy Schubert 	if (TEST_FAIL())
110e28a4053SRui Paulo 		return -1;
11185732ac8SCy Schubert 
11285732ac8SCy Schubert 	if (gcry_md_open(&hd, algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
11385732ac8SCy Schubert 		return -1;
11485732ac8SCy Schubert 	if (gcry_md_setkey(hd, key, key_len) != GPG_ERR_NO_ERROR) {
11585732ac8SCy Schubert 		gcry_md_close(hd);
11685732ac8SCy Schubert 		return -1;
11785732ac8SCy Schubert 	}
11839beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
11939beb93cSSam Leffler 		gcry_md_write(hd, addr[i], len[i]);
12085732ac8SCy Schubert 	p = gcry_md_read(hd, algo);
12139beb93cSSam Leffler 	if (p)
12285732ac8SCy Schubert 		memcpy(mac, p, gcry_md_get_algo_dlen(algo));
12339beb93cSSam Leffler 	gcry_md_close(hd);
124e28a4053SRui Paulo 	return 0;
12539beb93cSSam Leffler }
12639beb93cSSam Leffler 
12739beb93cSSam Leffler 
hmac_md5_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)12885732ac8SCy Schubert int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
12985732ac8SCy Schubert 		    const u8 *addr[], const size_t *len, u8 *mac)
13085732ac8SCy Schubert {
13185732ac8SCy Schubert 	return gnutls_hmac_vector(GCRY_MD_MD5, key, key_len, num_elem, addr,
13285732ac8SCy Schubert 				  len, mac);
13385732ac8SCy Schubert }
13485732ac8SCy Schubert 
13585732ac8SCy Schubert 
hmac_md5(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)13685732ac8SCy Schubert int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
13785732ac8SCy Schubert 	     u8 *mac)
13885732ac8SCy Schubert {
13985732ac8SCy Schubert 	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
14085732ac8SCy Schubert }
14185732ac8SCy Schubert 
14285732ac8SCy Schubert 
hmac_sha1_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)14385732ac8SCy Schubert int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
14485732ac8SCy Schubert 		     const u8 *addr[], const size_t *len, u8 *mac)
14585732ac8SCy Schubert {
14685732ac8SCy Schubert 	return gnutls_hmac_vector(GCRY_MD_SHA1, key, key_len, num_elem, addr,
14785732ac8SCy Schubert 				  len, mac);
14885732ac8SCy Schubert }
14985732ac8SCy Schubert 
15085732ac8SCy Schubert 
hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)15185732ac8SCy Schubert int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
15285732ac8SCy Schubert 	       u8 *mac)
15385732ac8SCy Schubert {
15485732ac8SCy Schubert 	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
15585732ac8SCy Schubert }
15685732ac8SCy Schubert 
15785732ac8SCy Schubert 
15885732ac8SCy Schubert #ifdef CONFIG_SHA256
15985732ac8SCy Schubert 
hmac_sha256_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)16085732ac8SCy Schubert int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
16185732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
16285732ac8SCy Schubert {
16385732ac8SCy Schubert 	return gnutls_hmac_vector(GCRY_MD_SHA256, key, key_len, num_elem, addr,
16485732ac8SCy Schubert 				  len, mac);
16585732ac8SCy Schubert }
16685732ac8SCy Schubert 
16785732ac8SCy Schubert 
hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)16885732ac8SCy Schubert int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
16985732ac8SCy Schubert 		size_t data_len, u8 *mac)
17085732ac8SCy Schubert {
17185732ac8SCy Schubert 	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
17285732ac8SCy Schubert }
17385732ac8SCy Schubert 
17485732ac8SCy Schubert #endif /* CONFIG_SHA256 */
17585732ac8SCy Schubert 
17685732ac8SCy Schubert 
17785732ac8SCy Schubert #ifdef CONFIG_SHA384
17885732ac8SCy Schubert 
hmac_sha384_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)17985732ac8SCy Schubert int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
18085732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
18185732ac8SCy Schubert {
18285732ac8SCy Schubert 	return gnutls_hmac_vector(GCRY_MD_SHA384, key, key_len, num_elem, addr,
18385732ac8SCy Schubert 				  len, mac);
18485732ac8SCy Schubert }
18585732ac8SCy Schubert 
18685732ac8SCy Schubert 
hmac_sha384(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)18785732ac8SCy Schubert int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
18885732ac8SCy Schubert 		size_t data_len, u8 *mac)
18985732ac8SCy Schubert {
19085732ac8SCy Schubert 	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
19185732ac8SCy Schubert }
19285732ac8SCy Schubert 
19385732ac8SCy Schubert #endif /* CONFIG_SHA384 */
19485732ac8SCy Schubert 
19585732ac8SCy Schubert 
19685732ac8SCy Schubert #ifdef CONFIG_SHA512
19785732ac8SCy Schubert 
hmac_sha512_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)19885732ac8SCy Schubert int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
19985732ac8SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
20085732ac8SCy Schubert {
20185732ac8SCy Schubert 	return gnutls_hmac_vector(GCRY_MD_SHA512, key, key_len, num_elem, addr,
20285732ac8SCy Schubert 				  len, mac);
20385732ac8SCy Schubert }
20485732ac8SCy Schubert 
20585732ac8SCy Schubert 
hmac_sha512(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)20685732ac8SCy Schubert int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
20785732ac8SCy Schubert 		size_t data_len, u8 *mac)
20885732ac8SCy Schubert {
20985732ac8SCy Schubert 	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
21085732ac8SCy Schubert }
21185732ac8SCy Schubert 
21285732ac8SCy Schubert #endif /* CONFIG_SHA512 */
21385732ac8SCy Schubert 
21485732ac8SCy Schubert 
aes_encrypt_init(const u8 * key,size_t len)21539beb93cSSam Leffler void * aes_encrypt_init(const u8 *key, size_t len)
21639beb93cSSam Leffler {
21739beb93cSSam Leffler 	gcry_cipher_hd_t hd;
21839beb93cSSam Leffler 
21985732ac8SCy Schubert 	if (TEST_FAIL())
22085732ac8SCy Schubert 		return NULL;
22185732ac8SCy Schubert 
22239beb93cSSam Leffler 	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
22339beb93cSSam Leffler 	    GPG_ERR_NO_ERROR) {
22439beb93cSSam Leffler 		printf("cipher open failed\n");
22539beb93cSSam Leffler 		return NULL;
22639beb93cSSam Leffler 	}
22739beb93cSSam Leffler 	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
22839beb93cSSam Leffler 		printf("setkey failed\n");
22939beb93cSSam Leffler 		gcry_cipher_close(hd);
23039beb93cSSam Leffler 		return NULL;
23139beb93cSSam Leffler 	}
23239beb93cSSam Leffler 
23339beb93cSSam Leffler 	return hd;
23439beb93cSSam Leffler }
23539beb93cSSam Leffler 
23639beb93cSSam Leffler 
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)23785732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
23839beb93cSSam Leffler {
23939beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
24039beb93cSSam Leffler 	gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
24185732ac8SCy Schubert 	return 0;
24239beb93cSSam Leffler }
24339beb93cSSam Leffler 
24439beb93cSSam Leffler 
aes_encrypt_deinit(void * ctx)24539beb93cSSam Leffler void aes_encrypt_deinit(void *ctx)
24639beb93cSSam Leffler {
24739beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
24839beb93cSSam Leffler 	gcry_cipher_close(hd);
24939beb93cSSam Leffler }
25039beb93cSSam Leffler 
25139beb93cSSam Leffler 
aes_decrypt_init(const u8 * key,size_t len)25239beb93cSSam Leffler void * aes_decrypt_init(const u8 *key, size_t len)
25339beb93cSSam Leffler {
25439beb93cSSam Leffler 	gcry_cipher_hd_t hd;
25539beb93cSSam Leffler 
25685732ac8SCy Schubert 	if (TEST_FAIL())
25785732ac8SCy Schubert 		return NULL;
25885732ac8SCy Schubert 
25939beb93cSSam Leffler 	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
26039beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
26139beb93cSSam Leffler 		return NULL;
26239beb93cSSam Leffler 	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
26339beb93cSSam Leffler 		gcry_cipher_close(hd);
26439beb93cSSam Leffler 		return NULL;
26539beb93cSSam Leffler 	}
26639beb93cSSam Leffler 
26739beb93cSSam Leffler 	return hd;
26839beb93cSSam Leffler }
26939beb93cSSam Leffler 
27039beb93cSSam Leffler 
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)27185732ac8SCy Schubert int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
27239beb93cSSam Leffler {
27339beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
27439beb93cSSam Leffler 	gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
27585732ac8SCy Schubert 	return 0;
27639beb93cSSam Leffler }
27739beb93cSSam Leffler 
27839beb93cSSam Leffler 
aes_decrypt_deinit(void * ctx)27939beb93cSSam Leffler void aes_decrypt_deinit(void *ctx)
28039beb93cSSam Leffler {
28139beb93cSSam Leffler 	gcry_cipher_hd_t hd = ctx;
28239beb93cSSam Leffler 	gcry_cipher_close(hd);
28339beb93cSSam Leffler }
28439beb93cSSam Leffler 
28539beb93cSSam Leffler 
crypto_dh_init(u8 generator,const u8 * prime,size_t prime_len,u8 * privkey,u8 * pubkey)28685732ac8SCy Schubert int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
28785732ac8SCy Schubert 		   u8 *pubkey)
28885732ac8SCy Schubert {
28985732ac8SCy Schubert 	size_t pubkey_len, pad;
29085732ac8SCy Schubert 
29185732ac8SCy Schubert 	if (os_get_random(privkey, prime_len) < 0)
29285732ac8SCy Schubert 		return -1;
29385732ac8SCy Schubert 	if (os_memcmp(privkey, prime, prime_len) > 0) {
29485732ac8SCy Schubert 		/* Make sure private value is smaller than prime */
29585732ac8SCy Schubert 		privkey[0] = 0;
29685732ac8SCy Schubert 	}
29785732ac8SCy Schubert 
29885732ac8SCy Schubert 	pubkey_len = prime_len;
29985732ac8SCy Schubert 	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
30085732ac8SCy Schubert 			   pubkey, &pubkey_len) < 0)
30185732ac8SCy Schubert 		return -1;
30285732ac8SCy Schubert 	if (pubkey_len < prime_len) {
30385732ac8SCy Schubert 		pad = prime_len - pubkey_len;
30485732ac8SCy Schubert 		os_memmove(pubkey + pad, pubkey, pubkey_len);
30585732ac8SCy Schubert 		os_memset(pubkey, 0, pad);
30685732ac8SCy Schubert 	}
30785732ac8SCy Schubert 
30885732ac8SCy Schubert 	return 0;
30985732ac8SCy Schubert }
31085732ac8SCy Schubert 
31185732ac8SCy Schubert 
crypto_dh_derive_secret(u8 generator,const u8 * prime,size_t prime_len,const u8 * order,size_t order_len,const u8 * privkey,size_t privkey_len,const u8 * pubkey,size_t pubkey_len,u8 * secret,size_t * len)31285732ac8SCy Schubert int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
3134bc52338SCy Schubert 			    const u8 *order, size_t order_len,
31485732ac8SCy Schubert 			    const u8 *privkey, size_t privkey_len,
31585732ac8SCy Schubert 			    const u8 *pubkey, size_t pubkey_len,
31685732ac8SCy Schubert 			    u8 *secret, size_t *len)
31785732ac8SCy Schubert {
3184bc52338SCy Schubert 	gcry_mpi_t pub = NULL;
3194bc52338SCy Schubert 	int res = -1;
3204bc52338SCy Schubert 
3214bc52338SCy Schubert 	if (pubkey_len > prime_len ||
3224bc52338SCy Schubert 	    (pubkey_len == prime_len &&
3234bc52338SCy Schubert 	     os_memcmp(pubkey, prime, prime_len) >= 0))
3244bc52338SCy Schubert 		return -1;
3254bc52338SCy Schubert 
3264bc52338SCy Schubert 	if (gcry_mpi_scan(&pub, GCRYMPI_FMT_USG, pubkey, pubkey_len, NULL) !=
3274bc52338SCy Schubert 	    GPG_ERR_NO_ERROR ||
3284bc52338SCy Schubert 	    gcry_mpi_cmp_ui(pub, 1) <= 0)
3294bc52338SCy Schubert 		goto fail;
3304bc52338SCy Schubert 
3314bc52338SCy Schubert 	if (order) {
3324bc52338SCy Schubert 		gcry_mpi_t p = NULL, q = NULL, tmp;
3334bc52338SCy Schubert 		int failed;
3344bc52338SCy Schubert 
3354bc52338SCy Schubert 		/* verify: pubkey^q == 1 mod p */
3364bc52338SCy Schubert 		tmp = gcry_mpi_new(prime_len * 8);
3374bc52338SCy Schubert 		failed = !tmp ||
3384bc52338SCy Schubert 			gcry_mpi_scan(&p, GCRYMPI_FMT_USG, prime, prime_len,
3394bc52338SCy Schubert 				      NULL) != GPG_ERR_NO_ERROR ||
3404bc52338SCy Schubert 			gcry_mpi_scan(&q, GCRYMPI_FMT_USG, order, order_len,
3414bc52338SCy Schubert 				      NULL) != GPG_ERR_NO_ERROR;
3424bc52338SCy Schubert 		if (!failed) {
3434bc52338SCy Schubert 			gcry_mpi_powm(tmp, pub, q, p);
3444bc52338SCy Schubert 			failed = gcry_mpi_cmp_ui(tmp, 1) != 0;
3454bc52338SCy Schubert 		}
3464bc52338SCy Schubert 		gcry_mpi_release(p);
3474bc52338SCy Schubert 		gcry_mpi_release(q);
3484bc52338SCy Schubert 		gcry_mpi_release(tmp);
3494bc52338SCy Schubert 		if (failed)
3504bc52338SCy Schubert 			goto fail;
3514bc52338SCy Schubert 	}
3524bc52338SCy Schubert 
3534bc52338SCy Schubert 	res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
35485732ac8SCy Schubert 			     prime, prime_len, secret, len);
3554bc52338SCy Schubert fail:
3564bc52338SCy Schubert 	gcry_mpi_release(pub);
3574bc52338SCy Schubert 	return res;
35885732ac8SCy Schubert }
35985732ac8SCy Schubert 
36085732ac8SCy Schubert 
crypto_mod_exp(const u8 * base,size_t base_len,const u8 * power,size_t power_len,const u8 * modulus,size_t modulus_len,u8 * result,size_t * result_len)36139beb93cSSam Leffler int crypto_mod_exp(const u8 *base, size_t base_len,
36239beb93cSSam Leffler 		   const u8 *power, size_t power_len,
36339beb93cSSam Leffler 		   const u8 *modulus, size_t modulus_len,
36439beb93cSSam Leffler 		   u8 *result, size_t *result_len)
36539beb93cSSam Leffler {
36639beb93cSSam Leffler 	gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
36739beb93cSSam Leffler 		bn_result = NULL;
36839beb93cSSam Leffler 	int ret = -1;
36939beb93cSSam Leffler 
37039beb93cSSam Leffler 	if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
37139beb93cSSam Leffler 	    GPG_ERR_NO_ERROR ||
37239beb93cSSam Leffler 	    gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
37339beb93cSSam Leffler 	    GPG_ERR_NO_ERROR ||
37439beb93cSSam Leffler 	    gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
37539beb93cSSam Leffler 			  NULL) != GPG_ERR_NO_ERROR)
37639beb93cSSam Leffler 		goto error;
37739beb93cSSam Leffler 	bn_result = gcry_mpi_new(modulus_len * 8);
37839beb93cSSam Leffler 
37939beb93cSSam Leffler 	gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
38039beb93cSSam Leffler 
38139beb93cSSam Leffler 	if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
38239beb93cSSam Leffler 			   bn_result) != GPG_ERR_NO_ERROR)
38339beb93cSSam Leffler 		goto error;
38439beb93cSSam Leffler 
38539beb93cSSam Leffler 	ret = 0;
38639beb93cSSam Leffler 
38739beb93cSSam Leffler error:
38839beb93cSSam Leffler 	gcry_mpi_release(bn_base);
38939beb93cSSam Leffler 	gcry_mpi_release(bn_exp);
39039beb93cSSam Leffler 	gcry_mpi_release(bn_modulus);
39139beb93cSSam Leffler 	gcry_mpi_release(bn_result);
39239beb93cSSam Leffler 	return ret;
39339beb93cSSam Leffler }
39439beb93cSSam Leffler 
39539beb93cSSam Leffler 
39639beb93cSSam Leffler struct crypto_cipher {
39739beb93cSSam Leffler 	gcry_cipher_hd_t enc;
39839beb93cSSam Leffler 	gcry_cipher_hd_t dec;
39939beb93cSSam Leffler };
40039beb93cSSam Leffler 
40139beb93cSSam Leffler 
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)40239beb93cSSam Leffler struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
40339beb93cSSam Leffler 					  const u8 *iv, const u8 *key,
40439beb93cSSam Leffler 					  size_t key_len)
40539beb93cSSam Leffler {
40639beb93cSSam Leffler 	struct crypto_cipher *ctx;
40739beb93cSSam Leffler 	gcry_error_t res;
40839beb93cSSam Leffler 	enum gcry_cipher_algos a;
40939beb93cSSam Leffler 	int ivlen;
41039beb93cSSam Leffler 
41139beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
41239beb93cSSam Leffler 	if (ctx == NULL)
41339beb93cSSam Leffler 		return NULL;
41439beb93cSSam Leffler 
41539beb93cSSam Leffler 	switch (alg) {
41639beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC4:
41739beb93cSSam Leffler 		a = GCRY_CIPHER_ARCFOUR;
41839beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
41939beb93cSSam Leffler 				       0);
42039beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
42139beb93cSSam Leffler 		break;
42239beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_AES:
42339beb93cSSam Leffler 		if (key_len == 24)
42439beb93cSSam Leffler 			a = GCRY_CIPHER_AES192;
42539beb93cSSam Leffler 		else if (key_len == 32)
42639beb93cSSam Leffler 			a = GCRY_CIPHER_AES256;
42739beb93cSSam Leffler 		else
42839beb93cSSam Leffler 			a = GCRY_CIPHER_AES;
42939beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
43039beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
43139beb93cSSam Leffler 		break;
43239beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_3DES:
43339beb93cSSam Leffler 		a = GCRY_CIPHER_3DES;
43439beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
43539beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
43639beb93cSSam Leffler 		break;
43739beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_DES:
43839beb93cSSam Leffler 		a = GCRY_CIPHER_DES;
43939beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
44039beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
44139beb93cSSam Leffler 		break;
44239beb93cSSam Leffler 	case CRYPTO_CIPHER_ALG_RC2:
44339beb93cSSam Leffler 		if (key_len == 5)
44439beb93cSSam Leffler 			a = GCRY_CIPHER_RFC2268_40;
44539beb93cSSam Leffler 		else
44639beb93cSSam Leffler 			a = GCRY_CIPHER_RFC2268_128;
44739beb93cSSam Leffler 		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
44839beb93cSSam Leffler 		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
44939beb93cSSam Leffler 		break;
45039beb93cSSam Leffler 	default:
45139beb93cSSam Leffler 		os_free(ctx);
45239beb93cSSam Leffler 		return NULL;
45339beb93cSSam Leffler 	}
45439beb93cSSam Leffler 
45539beb93cSSam Leffler 	if (res != GPG_ERR_NO_ERROR) {
45639beb93cSSam Leffler 		os_free(ctx);
45739beb93cSSam Leffler 		return NULL;
45839beb93cSSam Leffler 	}
45939beb93cSSam Leffler 
46039beb93cSSam Leffler 	if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
46139beb93cSSam Leffler 	    gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
46239beb93cSSam Leffler 		gcry_cipher_close(ctx->enc);
46339beb93cSSam Leffler 		gcry_cipher_close(ctx->dec);
46439beb93cSSam Leffler 		os_free(ctx);
46539beb93cSSam Leffler 		return NULL;
46639beb93cSSam Leffler 	}
46739beb93cSSam Leffler 
46839beb93cSSam Leffler 	ivlen = gcry_cipher_get_algo_blklen(a);
46939beb93cSSam Leffler 	if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
47039beb93cSSam Leffler 	    gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
47139beb93cSSam Leffler 		gcry_cipher_close(ctx->enc);
47239beb93cSSam Leffler 		gcry_cipher_close(ctx->dec);
47339beb93cSSam Leffler 		os_free(ctx);
47439beb93cSSam Leffler 		return NULL;
47539beb93cSSam Leffler 	}
47639beb93cSSam Leffler 
47739beb93cSSam Leffler 	return ctx;
47839beb93cSSam Leffler }
47939beb93cSSam Leffler 
48039beb93cSSam Leffler 
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)48139beb93cSSam Leffler int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
48239beb93cSSam Leffler 			  u8 *crypt, size_t len)
48339beb93cSSam Leffler {
48439beb93cSSam Leffler 	if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
48539beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
48639beb93cSSam Leffler 		return -1;
48739beb93cSSam Leffler 	return 0;
48839beb93cSSam Leffler }
48939beb93cSSam Leffler 
49039beb93cSSam Leffler 
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)49139beb93cSSam Leffler int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
49239beb93cSSam Leffler 			  u8 *plain, size_t len)
49339beb93cSSam Leffler {
49439beb93cSSam Leffler 	if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
49539beb93cSSam Leffler 	    GPG_ERR_NO_ERROR)
49639beb93cSSam Leffler 		return -1;
49739beb93cSSam Leffler 	return 0;
49839beb93cSSam Leffler }
49939beb93cSSam Leffler 
50039beb93cSSam Leffler 
crypto_cipher_deinit(struct crypto_cipher * ctx)50139beb93cSSam Leffler void crypto_cipher_deinit(struct crypto_cipher *ctx)
50239beb93cSSam Leffler {
50339beb93cSSam Leffler 	gcry_cipher_close(ctx->enc);
50439beb93cSSam Leffler 	gcry_cipher_close(ctx->dec);
50539beb93cSSam Leffler 	os_free(ctx);
50639beb93cSSam Leffler }
507*a90b9d01SCy Schubert 
508*a90b9d01SCy Schubert 
crypto_unload(void)509*a90b9d01SCy Schubert void crypto_unload(void)
510*a90b9d01SCy Schubert {
511*a90b9d01SCy Schubert }
512