1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * WPA Supplicant / wrapper functions for libgcrypt
3e5b75505Sopenharmony_ci * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci#include <gcrypt.h>
11e5b75505Sopenharmony_ci
12e5b75505Sopenharmony_ci#include "common.h"
13e5b75505Sopenharmony_ci#include "md5.h"
14e5b75505Sopenharmony_ci#include "sha1.h"
15e5b75505Sopenharmony_ci#include "sha256.h"
16e5b75505Sopenharmony_ci#include "sha384.h"
17e5b75505Sopenharmony_ci#include "sha512.h"
18e5b75505Sopenharmony_ci#include "crypto.h"
19e5b75505Sopenharmony_ci
20e5b75505Sopenharmony_cistatic int gnutls_digest_vector(int algo, size_t num_elem,
21e5b75505Sopenharmony_ci				const u8 *addr[], const size_t *len, u8 *mac)
22e5b75505Sopenharmony_ci{
23e5b75505Sopenharmony_ci	gcry_md_hd_t hd;
24e5b75505Sopenharmony_ci	unsigned char *p;
25e5b75505Sopenharmony_ci	size_t i;
26e5b75505Sopenharmony_ci
27e5b75505Sopenharmony_ci	if (TEST_FAIL())
28e5b75505Sopenharmony_ci		return -1;
29e5b75505Sopenharmony_ci
30e5b75505Sopenharmony_ci	if (gcry_md_open(&hd, algo, 0) != GPG_ERR_NO_ERROR)
31e5b75505Sopenharmony_ci		return -1;
32e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
33e5b75505Sopenharmony_ci		gcry_md_write(hd, addr[i], len[i]);
34e5b75505Sopenharmony_ci	p = gcry_md_read(hd, algo);
35e5b75505Sopenharmony_ci	if (p)
36e5b75505Sopenharmony_ci		memcpy(mac, p, gcry_md_get_algo_dlen(algo));
37e5b75505Sopenharmony_ci	gcry_md_close(hd);
38e5b75505Sopenharmony_ci	return 0;
39e5b75505Sopenharmony_ci}
40e5b75505Sopenharmony_ci
41e5b75505Sopenharmony_ci
42e5b75505Sopenharmony_ciint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
43e5b75505Sopenharmony_ci{
44e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_MD4, num_elem, addr, len, mac);
45e5b75505Sopenharmony_ci}
46e5b75505Sopenharmony_ci
47e5b75505Sopenharmony_ci
48e5b75505Sopenharmony_ciint des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
49e5b75505Sopenharmony_ci{
50e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd;
51e5b75505Sopenharmony_ci	u8 pkey[8], next, tmp;
52e5b75505Sopenharmony_ci	int i;
53e5b75505Sopenharmony_ci
54e5b75505Sopenharmony_ci	/* Add parity bits to the key */
55e5b75505Sopenharmony_ci	next = 0;
56e5b75505Sopenharmony_ci	for (i = 0; i < 7; i++) {
57e5b75505Sopenharmony_ci		tmp = key[i];
58e5b75505Sopenharmony_ci		pkey[i] = (tmp >> i) | next | 1;
59e5b75505Sopenharmony_ci		next = tmp << (7 - i);
60e5b75505Sopenharmony_ci	}
61e5b75505Sopenharmony_ci	pkey[i] = next | 1;
62e5b75505Sopenharmony_ci
63e5b75505Sopenharmony_ci	gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
64e5b75505Sopenharmony_ci	gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
65e5b75505Sopenharmony_ci	gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
66e5b75505Sopenharmony_ci	gcry_cipher_close(hd);
67e5b75505Sopenharmony_ci	return 0;
68e5b75505Sopenharmony_ci}
69e5b75505Sopenharmony_ci
70e5b75505Sopenharmony_ci
71e5b75505Sopenharmony_ciint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
72e5b75505Sopenharmony_ci{
73e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_MD5, num_elem, addr, len, mac);
74e5b75505Sopenharmony_ci}
75e5b75505Sopenharmony_ci
76e5b75505Sopenharmony_ci
77e5b75505Sopenharmony_ciint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
78e5b75505Sopenharmony_ci{
79e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_SHA1, num_elem, addr, len, mac);
80e5b75505Sopenharmony_ci}
81e5b75505Sopenharmony_ci
82e5b75505Sopenharmony_ci
83e5b75505Sopenharmony_ciint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
84e5b75505Sopenharmony_ci{
85e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_SHA256, num_elem, addr, len, mac);
86e5b75505Sopenharmony_ci}
87e5b75505Sopenharmony_ci
88e5b75505Sopenharmony_ci
89e5b75505Sopenharmony_ciint sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
90e5b75505Sopenharmony_ci{
91e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_SHA384, num_elem, addr, len, mac);
92e5b75505Sopenharmony_ci}
93e5b75505Sopenharmony_ci
94e5b75505Sopenharmony_ci
95e5b75505Sopenharmony_ciint sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
96e5b75505Sopenharmony_ci{
97e5b75505Sopenharmony_ci	return gnutls_digest_vector(GCRY_MD_SHA512, num_elem, addr, len, mac);
98e5b75505Sopenharmony_ci}
99e5b75505Sopenharmony_ci
100e5b75505Sopenharmony_ci
101e5b75505Sopenharmony_cistatic int gnutls_hmac_vector(int algo, const u8 *key, size_t key_len,
102e5b75505Sopenharmony_ci			      size_t num_elem, const u8 *addr[],
103e5b75505Sopenharmony_ci			      const size_t *len, u8 *mac)
104e5b75505Sopenharmony_ci{
105e5b75505Sopenharmony_ci	gcry_md_hd_t hd;
106e5b75505Sopenharmony_ci	unsigned char *p;
107e5b75505Sopenharmony_ci	size_t i;
108e5b75505Sopenharmony_ci
109e5b75505Sopenharmony_ci	if (TEST_FAIL())
110e5b75505Sopenharmony_ci		return -1;
111e5b75505Sopenharmony_ci
112e5b75505Sopenharmony_ci	if (gcry_md_open(&hd, algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
113e5b75505Sopenharmony_ci		return -1;
114e5b75505Sopenharmony_ci	if (gcry_md_setkey(hd, key, key_len) != GPG_ERR_NO_ERROR) {
115e5b75505Sopenharmony_ci		gcry_md_close(hd);
116e5b75505Sopenharmony_ci		return -1;
117e5b75505Sopenharmony_ci	}
118e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
119e5b75505Sopenharmony_ci		gcry_md_write(hd, addr[i], len[i]);
120e5b75505Sopenharmony_ci	p = gcry_md_read(hd, algo);
121e5b75505Sopenharmony_ci	if (p)
122e5b75505Sopenharmony_ci		memcpy(mac, p, gcry_md_get_algo_dlen(algo));
123e5b75505Sopenharmony_ci	gcry_md_close(hd);
124e5b75505Sopenharmony_ci	return 0;
125e5b75505Sopenharmony_ci}
126e5b75505Sopenharmony_ci
127e5b75505Sopenharmony_ci
128e5b75505Sopenharmony_ciint hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
129e5b75505Sopenharmony_ci		    const u8 *addr[], const size_t *len, u8 *mac)
130e5b75505Sopenharmony_ci{
131e5b75505Sopenharmony_ci	return gnutls_hmac_vector(GCRY_MD_MD5, key, key_len, num_elem, addr,
132e5b75505Sopenharmony_ci				  len, mac);
133e5b75505Sopenharmony_ci}
134e5b75505Sopenharmony_ci
135e5b75505Sopenharmony_ci
136e5b75505Sopenharmony_ciint hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
137e5b75505Sopenharmony_ci	     u8 *mac)
138e5b75505Sopenharmony_ci{
139e5b75505Sopenharmony_ci	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
140e5b75505Sopenharmony_ci}
141e5b75505Sopenharmony_ci
142e5b75505Sopenharmony_ci
143e5b75505Sopenharmony_ciint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
144e5b75505Sopenharmony_ci		     const u8 *addr[], const size_t *len, u8 *mac)
145e5b75505Sopenharmony_ci{
146e5b75505Sopenharmony_ci	return gnutls_hmac_vector(GCRY_MD_SHA1, key, key_len, num_elem, addr,
147e5b75505Sopenharmony_ci				  len, mac);
148e5b75505Sopenharmony_ci}
149e5b75505Sopenharmony_ci
150e5b75505Sopenharmony_ci
151e5b75505Sopenharmony_ciint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
152e5b75505Sopenharmony_ci	       u8 *mac)
153e5b75505Sopenharmony_ci{
154e5b75505Sopenharmony_ci	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
155e5b75505Sopenharmony_ci}
156e5b75505Sopenharmony_ci
157e5b75505Sopenharmony_ci
158e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
159e5b75505Sopenharmony_ci
160e5b75505Sopenharmony_ciint hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
161e5b75505Sopenharmony_ci		       const u8 *addr[], const size_t *len, u8 *mac)
162e5b75505Sopenharmony_ci{
163e5b75505Sopenharmony_ci	return gnutls_hmac_vector(GCRY_MD_SHA256, key, key_len, num_elem, addr,
164e5b75505Sopenharmony_ci				  len, mac);
165e5b75505Sopenharmony_ci}
166e5b75505Sopenharmony_ci
167e5b75505Sopenharmony_ci
168e5b75505Sopenharmony_ciint hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
169e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
170e5b75505Sopenharmony_ci{
171e5b75505Sopenharmony_ci	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
172e5b75505Sopenharmony_ci}
173e5b75505Sopenharmony_ci
174e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
175e5b75505Sopenharmony_ci
176e5b75505Sopenharmony_ci
177e5b75505Sopenharmony_ci#ifdef CONFIG_SHA384
178e5b75505Sopenharmony_ci
179e5b75505Sopenharmony_ciint hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
180e5b75505Sopenharmony_ci		       const u8 *addr[], const size_t *len, u8 *mac)
181e5b75505Sopenharmony_ci{
182e5b75505Sopenharmony_ci	return gnutls_hmac_vector(GCRY_MD_SHA384, key, key_len, num_elem, addr,
183e5b75505Sopenharmony_ci				  len, mac);
184e5b75505Sopenharmony_ci}
185e5b75505Sopenharmony_ci
186e5b75505Sopenharmony_ci
187e5b75505Sopenharmony_ciint hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
188e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
189e5b75505Sopenharmony_ci{
190e5b75505Sopenharmony_ci	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
191e5b75505Sopenharmony_ci}
192e5b75505Sopenharmony_ci
193e5b75505Sopenharmony_ci#endif /* CONFIG_SHA384 */
194e5b75505Sopenharmony_ci
195e5b75505Sopenharmony_ci
196e5b75505Sopenharmony_ci#ifdef CONFIG_SHA512
197e5b75505Sopenharmony_ci
198e5b75505Sopenharmony_ciint hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
199e5b75505Sopenharmony_ci		       const u8 *addr[], const size_t *len, u8 *mac)
200e5b75505Sopenharmony_ci{
201e5b75505Sopenharmony_ci	return gnutls_hmac_vector(GCRY_MD_SHA512, key, key_len, num_elem, addr,
202e5b75505Sopenharmony_ci				  len, mac);
203e5b75505Sopenharmony_ci}
204e5b75505Sopenharmony_ci
205e5b75505Sopenharmony_ci
206e5b75505Sopenharmony_ciint hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
207e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
208e5b75505Sopenharmony_ci{
209e5b75505Sopenharmony_ci	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
210e5b75505Sopenharmony_ci}
211e5b75505Sopenharmony_ci
212e5b75505Sopenharmony_ci#endif /* CONFIG_SHA512 */
213e5b75505Sopenharmony_ci
214e5b75505Sopenharmony_ci
215e5b75505Sopenharmony_civoid * aes_encrypt_init(const u8 *key, size_t len)
216e5b75505Sopenharmony_ci{
217e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd;
218e5b75505Sopenharmony_ci
219e5b75505Sopenharmony_ci	if (TEST_FAIL())
220e5b75505Sopenharmony_ci		return NULL;
221e5b75505Sopenharmony_ci
222e5b75505Sopenharmony_ci	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
223e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR) {
224e5b75505Sopenharmony_ci		printf("cipher open failed\n");
225e5b75505Sopenharmony_ci		return NULL;
226e5b75505Sopenharmony_ci	}
227e5b75505Sopenharmony_ci	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
228e5b75505Sopenharmony_ci		printf("setkey failed\n");
229e5b75505Sopenharmony_ci		gcry_cipher_close(hd);
230e5b75505Sopenharmony_ci		return NULL;
231e5b75505Sopenharmony_ci	}
232e5b75505Sopenharmony_ci
233e5b75505Sopenharmony_ci	return hd;
234e5b75505Sopenharmony_ci}
235e5b75505Sopenharmony_ci
236e5b75505Sopenharmony_ci
237e5b75505Sopenharmony_ciint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
238e5b75505Sopenharmony_ci{
239e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd = ctx;
240e5b75505Sopenharmony_ci	gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
241e5b75505Sopenharmony_ci	return 0;
242e5b75505Sopenharmony_ci}
243e5b75505Sopenharmony_ci
244e5b75505Sopenharmony_ci
245e5b75505Sopenharmony_civoid aes_encrypt_deinit(void *ctx)
246e5b75505Sopenharmony_ci{
247e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd = ctx;
248e5b75505Sopenharmony_ci	gcry_cipher_close(hd);
249e5b75505Sopenharmony_ci}
250e5b75505Sopenharmony_ci
251e5b75505Sopenharmony_ci
252e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len)
253e5b75505Sopenharmony_ci{
254e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd;
255e5b75505Sopenharmony_ci
256e5b75505Sopenharmony_ci	if (TEST_FAIL())
257e5b75505Sopenharmony_ci		return NULL;
258e5b75505Sopenharmony_ci
259e5b75505Sopenharmony_ci	if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
260e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR)
261e5b75505Sopenharmony_ci		return NULL;
262e5b75505Sopenharmony_ci	if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
263e5b75505Sopenharmony_ci		gcry_cipher_close(hd);
264e5b75505Sopenharmony_ci		return NULL;
265e5b75505Sopenharmony_ci	}
266e5b75505Sopenharmony_ci
267e5b75505Sopenharmony_ci	return hd;
268e5b75505Sopenharmony_ci}
269e5b75505Sopenharmony_ci
270e5b75505Sopenharmony_ci
271e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
272e5b75505Sopenharmony_ci{
273e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd = ctx;
274e5b75505Sopenharmony_ci	gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
275e5b75505Sopenharmony_ci	return 0;
276e5b75505Sopenharmony_ci}
277e5b75505Sopenharmony_ci
278e5b75505Sopenharmony_ci
279e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx)
280e5b75505Sopenharmony_ci{
281e5b75505Sopenharmony_ci	gcry_cipher_hd_t hd = ctx;
282e5b75505Sopenharmony_ci	gcry_cipher_close(hd);
283e5b75505Sopenharmony_ci}
284e5b75505Sopenharmony_ci
285e5b75505Sopenharmony_ci
286e5b75505Sopenharmony_ciint crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
287e5b75505Sopenharmony_ci		   u8 *pubkey)
288e5b75505Sopenharmony_ci{
289e5b75505Sopenharmony_ci	size_t pubkey_len, pad;
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci	if (os_get_random(privkey, prime_len) < 0)
292e5b75505Sopenharmony_ci		return -1;
293e5b75505Sopenharmony_ci	if (os_memcmp(privkey, prime, prime_len) > 0) {
294e5b75505Sopenharmony_ci		/* Make sure private value is smaller than prime */
295e5b75505Sopenharmony_ci		privkey[0] = 0;
296e5b75505Sopenharmony_ci	}
297e5b75505Sopenharmony_ci
298e5b75505Sopenharmony_ci	pubkey_len = prime_len;
299e5b75505Sopenharmony_ci	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
300e5b75505Sopenharmony_ci			   pubkey, &pubkey_len) < 0)
301e5b75505Sopenharmony_ci		return -1;
302e5b75505Sopenharmony_ci	if (pubkey_len < prime_len) {
303e5b75505Sopenharmony_ci		pad = prime_len - pubkey_len;
304e5b75505Sopenharmony_ci		os_memmove(pubkey + pad, pubkey, pubkey_len);
305e5b75505Sopenharmony_ci		os_memset(pubkey, 0, pad);
306e5b75505Sopenharmony_ci	}
307e5b75505Sopenharmony_ci
308e5b75505Sopenharmony_ci	return 0;
309e5b75505Sopenharmony_ci}
310e5b75505Sopenharmony_ci
311e5b75505Sopenharmony_ci
312e5b75505Sopenharmony_ciint crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
313e5b75505Sopenharmony_ci			    const u8 *order, size_t order_len,
314e5b75505Sopenharmony_ci			    const u8 *privkey, size_t privkey_len,
315e5b75505Sopenharmony_ci			    const u8 *pubkey, size_t pubkey_len,
316e5b75505Sopenharmony_ci			    u8 *secret, size_t *len)
317e5b75505Sopenharmony_ci{
318e5b75505Sopenharmony_ci	gcry_mpi_t pub = NULL;
319e5b75505Sopenharmony_ci	int res = -1;
320e5b75505Sopenharmony_ci
321e5b75505Sopenharmony_ci	if (pubkey_len > prime_len ||
322e5b75505Sopenharmony_ci	    (pubkey_len == prime_len &&
323e5b75505Sopenharmony_ci	     os_memcmp(pubkey, prime, prime_len) >= 0))
324e5b75505Sopenharmony_ci		return -1;
325e5b75505Sopenharmony_ci
326e5b75505Sopenharmony_ci	if (gcry_mpi_scan(&pub, GCRYMPI_FMT_USG, pubkey, pubkey_len, NULL) !=
327e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR ||
328e5b75505Sopenharmony_ci	    gcry_mpi_cmp_ui(pub, 1) <= 0)
329e5b75505Sopenharmony_ci		goto fail;
330e5b75505Sopenharmony_ci
331e5b75505Sopenharmony_ci	if (order) {
332e5b75505Sopenharmony_ci		gcry_mpi_t p = NULL, q = NULL, tmp;
333e5b75505Sopenharmony_ci		int failed;
334e5b75505Sopenharmony_ci
335e5b75505Sopenharmony_ci		/* verify: pubkey^q == 1 mod p */
336e5b75505Sopenharmony_ci		tmp = gcry_mpi_new(prime_len * 8);
337e5b75505Sopenharmony_ci		failed = !tmp ||
338e5b75505Sopenharmony_ci			gcry_mpi_scan(&p, GCRYMPI_FMT_USG, prime, prime_len,
339e5b75505Sopenharmony_ci				      NULL) != GPG_ERR_NO_ERROR ||
340e5b75505Sopenharmony_ci			gcry_mpi_scan(&q, GCRYMPI_FMT_USG, order, order_len,
341e5b75505Sopenharmony_ci				      NULL) != GPG_ERR_NO_ERROR;
342e5b75505Sopenharmony_ci		if (!failed) {
343e5b75505Sopenharmony_ci			gcry_mpi_powm(tmp, pub, q, p);
344e5b75505Sopenharmony_ci			failed = gcry_mpi_cmp_ui(tmp, 1) != 0;
345e5b75505Sopenharmony_ci		}
346e5b75505Sopenharmony_ci		gcry_mpi_release(p);
347e5b75505Sopenharmony_ci		gcry_mpi_release(q);
348e5b75505Sopenharmony_ci		gcry_mpi_release(tmp);
349e5b75505Sopenharmony_ci		if (failed)
350e5b75505Sopenharmony_ci			goto fail;
351e5b75505Sopenharmony_ci	}
352e5b75505Sopenharmony_ci
353e5b75505Sopenharmony_ci	res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
354e5b75505Sopenharmony_ci			     prime, prime_len, secret, len);
355e5b75505Sopenharmony_cifail:
356e5b75505Sopenharmony_ci	gcry_mpi_release(pub);
357e5b75505Sopenharmony_ci	return res;
358e5b75505Sopenharmony_ci}
359e5b75505Sopenharmony_ci
360e5b75505Sopenharmony_ci
361e5b75505Sopenharmony_ciint crypto_mod_exp(const u8 *base, size_t base_len,
362e5b75505Sopenharmony_ci		   const u8 *power, size_t power_len,
363e5b75505Sopenharmony_ci		   const u8 *modulus, size_t modulus_len,
364e5b75505Sopenharmony_ci		   u8 *result, size_t *result_len)
365e5b75505Sopenharmony_ci{
366e5b75505Sopenharmony_ci	gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
367e5b75505Sopenharmony_ci		bn_result = NULL;
368e5b75505Sopenharmony_ci	int ret = -1;
369e5b75505Sopenharmony_ci
370e5b75505Sopenharmony_ci	if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
371e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR ||
372e5b75505Sopenharmony_ci	    gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
373e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR ||
374e5b75505Sopenharmony_ci	    gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
375e5b75505Sopenharmony_ci			  NULL) != GPG_ERR_NO_ERROR)
376e5b75505Sopenharmony_ci		goto error;
377e5b75505Sopenharmony_ci	bn_result = gcry_mpi_new(modulus_len * 8);
378e5b75505Sopenharmony_ci
379e5b75505Sopenharmony_ci	gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
380e5b75505Sopenharmony_ci
381e5b75505Sopenharmony_ci	if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
382e5b75505Sopenharmony_ci			   bn_result) != GPG_ERR_NO_ERROR)
383e5b75505Sopenharmony_ci		goto error;
384e5b75505Sopenharmony_ci
385e5b75505Sopenharmony_ci	ret = 0;
386e5b75505Sopenharmony_ci
387e5b75505Sopenharmony_cierror:
388e5b75505Sopenharmony_ci	gcry_mpi_release(bn_base);
389e5b75505Sopenharmony_ci	gcry_mpi_release(bn_exp);
390e5b75505Sopenharmony_ci	gcry_mpi_release(bn_modulus);
391e5b75505Sopenharmony_ci	gcry_mpi_release(bn_result);
392e5b75505Sopenharmony_ci	return ret;
393e5b75505Sopenharmony_ci}
394e5b75505Sopenharmony_ci
395e5b75505Sopenharmony_ci
396e5b75505Sopenharmony_cistruct crypto_cipher {
397e5b75505Sopenharmony_ci	gcry_cipher_hd_t enc;
398e5b75505Sopenharmony_ci	gcry_cipher_hd_t dec;
399e5b75505Sopenharmony_ci};
400e5b75505Sopenharmony_ci
401e5b75505Sopenharmony_ci
402e5b75505Sopenharmony_cistruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
403e5b75505Sopenharmony_ci					  const u8 *iv, const u8 *key,
404e5b75505Sopenharmony_ci					  size_t key_len)
405e5b75505Sopenharmony_ci{
406e5b75505Sopenharmony_ci	struct crypto_cipher *ctx;
407e5b75505Sopenharmony_ci	gcry_error_t res;
408e5b75505Sopenharmony_ci	enum gcry_cipher_algos a;
409e5b75505Sopenharmony_ci	int ivlen;
410e5b75505Sopenharmony_ci
411e5b75505Sopenharmony_ci	ctx = os_zalloc(sizeof(*ctx));
412e5b75505Sopenharmony_ci	if (ctx == NULL)
413e5b75505Sopenharmony_ci		return NULL;
414e5b75505Sopenharmony_ci
415e5b75505Sopenharmony_ci	switch (alg) {
416e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_RC4:
417e5b75505Sopenharmony_ci		a = GCRY_CIPHER_ARCFOUR;
418e5b75505Sopenharmony_ci		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
419e5b75505Sopenharmony_ci				       0);
420e5b75505Sopenharmony_ci		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
421e5b75505Sopenharmony_ci		break;
422e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_AES:
423e5b75505Sopenharmony_ci		if (key_len == 24)
424e5b75505Sopenharmony_ci			a = GCRY_CIPHER_AES192;
425e5b75505Sopenharmony_ci		else if (key_len == 32)
426e5b75505Sopenharmony_ci			a = GCRY_CIPHER_AES256;
427e5b75505Sopenharmony_ci		else
428e5b75505Sopenharmony_ci			a = GCRY_CIPHER_AES;
429e5b75505Sopenharmony_ci		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
430e5b75505Sopenharmony_ci		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
431e5b75505Sopenharmony_ci		break;
432e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_3DES:
433e5b75505Sopenharmony_ci		a = GCRY_CIPHER_3DES;
434e5b75505Sopenharmony_ci		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
435e5b75505Sopenharmony_ci		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
436e5b75505Sopenharmony_ci		break;
437e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_DES:
438e5b75505Sopenharmony_ci		a = GCRY_CIPHER_DES;
439e5b75505Sopenharmony_ci		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
440e5b75505Sopenharmony_ci		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
441e5b75505Sopenharmony_ci		break;
442e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_RC2:
443e5b75505Sopenharmony_ci		if (key_len == 5)
444e5b75505Sopenharmony_ci			a = GCRY_CIPHER_RFC2268_40;
445e5b75505Sopenharmony_ci		else
446e5b75505Sopenharmony_ci			a = GCRY_CIPHER_RFC2268_128;
447e5b75505Sopenharmony_ci		res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
448e5b75505Sopenharmony_ci		gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
449e5b75505Sopenharmony_ci		break;
450e5b75505Sopenharmony_ci	default:
451e5b75505Sopenharmony_ci		os_free(ctx);
452e5b75505Sopenharmony_ci		return NULL;
453e5b75505Sopenharmony_ci	}
454e5b75505Sopenharmony_ci
455e5b75505Sopenharmony_ci	if (res != GPG_ERR_NO_ERROR) {
456e5b75505Sopenharmony_ci		os_free(ctx);
457e5b75505Sopenharmony_ci		return NULL;
458e5b75505Sopenharmony_ci	}
459e5b75505Sopenharmony_ci
460e5b75505Sopenharmony_ci	if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
461e5b75505Sopenharmony_ci	    gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
462e5b75505Sopenharmony_ci		gcry_cipher_close(ctx->enc);
463e5b75505Sopenharmony_ci		gcry_cipher_close(ctx->dec);
464e5b75505Sopenharmony_ci		os_free(ctx);
465e5b75505Sopenharmony_ci		return NULL;
466e5b75505Sopenharmony_ci	}
467e5b75505Sopenharmony_ci
468e5b75505Sopenharmony_ci	ivlen = gcry_cipher_get_algo_blklen(a);
469e5b75505Sopenharmony_ci	if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
470e5b75505Sopenharmony_ci	    gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
471e5b75505Sopenharmony_ci		gcry_cipher_close(ctx->enc);
472e5b75505Sopenharmony_ci		gcry_cipher_close(ctx->dec);
473e5b75505Sopenharmony_ci		os_free(ctx);
474e5b75505Sopenharmony_ci		return NULL;
475e5b75505Sopenharmony_ci	}
476e5b75505Sopenharmony_ci
477e5b75505Sopenharmony_ci	return ctx;
478e5b75505Sopenharmony_ci}
479e5b75505Sopenharmony_ci
480e5b75505Sopenharmony_ci
481e5b75505Sopenharmony_ciint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
482e5b75505Sopenharmony_ci			  u8 *crypt, size_t len)
483e5b75505Sopenharmony_ci{
484e5b75505Sopenharmony_ci	if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
485e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR)
486e5b75505Sopenharmony_ci		return -1;
487e5b75505Sopenharmony_ci	return 0;
488e5b75505Sopenharmony_ci}
489e5b75505Sopenharmony_ci
490e5b75505Sopenharmony_ci
491e5b75505Sopenharmony_ciint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
492e5b75505Sopenharmony_ci			  u8 *plain, size_t len)
493e5b75505Sopenharmony_ci{
494e5b75505Sopenharmony_ci	if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
495e5b75505Sopenharmony_ci	    GPG_ERR_NO_ERROR)
496e5b75505Sopenharmony_ci		return -1;
497e5b75505Sopenharmony_ci	return 0;
498e5b75505Sopenharmony_ci}
499e5b75505Sopenharmony_ci
500e5b75505Sopenharmony_ci
501e5b75505Sopenharmony_civoid crypto_cipher_deinit(struct crypto_cipher *ctx)
502e5b75505Sopenharmony_ci{
503e5b75505Sopenharmony_ci	gcry_cipher_close(ctx->enc);
504e5b75505Sopenharmony_ci	gcry_cipher_close(ctx->dec);
505e5b75505Sopenharmony_ci	os_free(ctx);
506e5b75505Sopenharmony_ci}
507