1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * Wrapper functions for libnettle and libgmp
3e5b75505Sopenharmony_ci * Copyright (c) 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 <nettle/nettle-meta.h>
11e5b75505Sopenharmony_ci#include <nettle/des.h>
12e5b75505Sopenharmony_ci#undef des_encrypt
13e5b75505Sopenharmony_ci#include <nettle/hmac.h>
14e5b75505Sopenharmony_ci#include <nettle/aes.h>
15e5b75505Sopenharmony_ci#undef aes_encrypt
16e5b75505Sopenharmony_ci#undef aes_decrypt
17e5b75505Sopenharmony_ci#include <nettle/arcfour.h>
18e5b75505Sopenharmony_ci#include <nettle/bignum.h>
19e5b75505Sopenharmony_ci
20e5b75505Sopenharmony_ci#include "common.h"
21e5b75505Sopenharmony_ci#include "md5.h"
22e5b75505Sopenharmony_ci#include "sha1.h"
23e5b75505Sopenharmony_ci#include "sha256.h"
24e5b75505Sopenharmony_ci#include "sha384.h"
25e5b75505Sopenharmony_ci#include "sha512.h"
26e5b75505Sopenharmony_ci#include "crypto.h"
27e5b75505Sopenharmony_ci
28e5b75505Sopenharmony_ci
29e5b75505Sopenharmony_ciint des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
30e5b75505Sopenharmony_ci{
31e5b75505Sopenharmony_ci	struct des_ctx ctx;
32e5b75505Sopenharmony_ci	u8 pkey[8], next, tmp;
33e5b75505Sopenharmony_ci	int i;
34e5b75505Sopenharmony_ci
35e5b75505Sopenharmony_ci	/* Add parity bits to the key */
36e5b75505Sopenharmony_ci	next = 0;
37e5b75505Sopenharmony_ci	for (i = 0; i < 7; i++) {
38e5b75505Sopenharmony_ci		tmp = key[i];
39e5b75505Sopenharmony_ci		pkey[i] = (tmp >> i) | next | 1;
40e5b75505Sopenharmony_ci		next = tmp << (7 - i);
41e5b75505Sopenharmony_ci	}
42e5b75505Sopenharmony_ci	pkey[i] = next | 1;
43e5b75505Sopenharmony_ci
44e5b75505Sopenharmony_ci	nettle_des_set_key(&ctx, pkey);
45e5b75505Sopenharmony_ci	nettle_des_encrypt(&ctx, DES_BLOCK_SIZE, cypher, clear);
46e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
47e5b75505Sopenharmony_ci	return 0;
48e5b75505Sopenharmony_ci}
49e5b75505Sopenharmony_ci
50e5b75505Sopenharmony_ci
51e5b75505Sopenharmony_cistatic int nettle_digest_vector(const struct nettle_hash *alg, size_t num_elem,
52e5b75505Sopenharmony_ci				const u8 *addr[], const size_t *len, u8 *mac)
53e5b75505Sopenharmony_ci{
54e5b75505Sopenharmony_ci	void *ctx;
55e5b75505Sopenharmony_ci	size_t i;
56e5b75505Sopenharmony_ci
57e5b75505Sopenharmony_ci	if (TEST_FAIL())
58e5b75505Sopenharmony_ci		return -1;
59e5b75505Sopenharmony_ci
60e5b75505Sopenharmony_ci	ctx = os_malloc(alg->context_size);
61e5b75505Sopenharmony_ci	if (!ctx)
62e5b75505Sopenharmony_ci		return -1;
63e5b75505Sopenharmony_ci	alg->init(ctx);
64e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
65e5b75505Sopenharmony_ci		alg->update(ctx, len[i], addr[i]);
66e5b75505Sopenharmony_ci	alg->digest(ctx, alg->digest_size, mac);
67e5b75505Sopenharmony_ci	bin_clear_free(ctx, alg->context_size);
68e5b75505Sopenharmony_ci	return 0;
69e5b75505Sopenharmony_ci}
70e5b75505Sopenharmony_ci
71e5b75505Sopenharmony_ci
72e5b75505Sopenharmony_ciint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
73e5b75505Sopenharmony_ci{
74e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_md4, num_elem, addr, len, mac);
75e5b75505Sopenharmony_ci}
76e5b75505Sopenharmony_ci
77e5b75505Sopenharmony_ci
78e5b75505Sopenharmony_ciint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
79e5b75505Sopenharmony_ci{
80e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_md5, num_elem, addr, len, mac);
81e5b75505Sopenharmony_ci}
82e5b75505Sopenharmony_ci
83e5b75505Sopenharmony_ci
84e5b75505Sopenharmony_ciint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
85e5b75505Sopenharmony_ci{
86e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_sha1, num_elem, addr, len, mac);
87e5b75505Sopenharmony_ci}
88e5b75505Sopenharmony_ci
89e5b75505Sopenharmony_ci
90e5b75505Sopenharmony_ciint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
91e5b75505Sopenharmony_ci{
92e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_sha256, num_elem, addr, len, mac);
93e5b75505Sopenharmony_ci}
94e5b75505Sopenharmony_ci
95e5b75505Sopenharmony_ci
96e5b75505Sopenharmony_ciint sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
97e5b75505Sopenharmony_ci{
98e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_sha384, num_elem, addr, len, mac);
99e5b75505Sopenharmony_ci}
100e5b75505Sopenharmony_ci
101e5b75505Sopenharmony_ci
102e5b75505Sopenharmony_ciint sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
103e5b75505Sopenharmony_ci{
104e5b75505Sopenharmony_ci	return nettle_digest_vector(&nettle_sha512, num_elem, addr, len, mac);
105e5b75505Sopenharmony_ci}
106e5b75505Sopenharmony_ci
107e5b75505Sopenharmony_ci
108e5b75505Sopenharmony_ciint hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
109e5b75505Sopenharmony_ci		    const u8 *addr[], const size_t *len, u8 *mac)
110e5b75505Sopenharmony_ci{
111e5b75505Sopenharmony_ci	struct hmac_md5_ctx ctx;
112e5b75505Sopenharmony_ci	size_t i;
113e5b75505Sopenharmony_ci
114e5b75505Sopenharmony_ci	if (TEST_FAIL())
115e5b75505Sopenharmony_ci		return -1;
116e5b75505Sopenharmony_ci
117e5b75505Sopenharmony_ci	hmac_md5_set_key(&ctx, key_len, key);
118e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
119e5b75505Sopenharmony_ci		hmac_md5_update(&ctx, len[i], addr[i]);
120e5b75505Sopenharmony_ci	hmac_md5_digest(&ctx, MD5_DIGEST_SIZE, mac);
121e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
122e5b75505Sopenharmony_ci	return 0;
123e5b75505Sopenharmony_ci}
124e5b75505Sopenharmony_ci
125e5b75505Sopenharmony_ci
126e5b75505Sopenharmony_ciint hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
127e5b75505Sopenharmony_ci	     u8 *mac)
128e5b75505Sopenharmony_ci{
129e5b75505Sopenharmony_ci	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
130e5b75505Sopenharmony_ci}
131e5b75505Sopenharmony_ci
132e5b75505Sopenharmony_ci
133e5b75505Sopenharmony_ciint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
134e5b75505Sopenharmony_ci		     const u8 *addr[], const size_t *len, u8 *mac)
135e5b75505Sopenharmony_ci{
136e5b75505Sopenharmony_ci	struct hmac_sha1_ctx ctx;
137e5b75505Sopenharmony_ci	size_t i;
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ci	if (TEST_FAIL())
140e5b75505Sopenharmony_ci		return -1;
141e5b75505Sopenharmony_ci
142e5b75505Sopenharmony_ci	hmac_sha1_set_key(&ctx, key_len, key);
143e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
144e5b75505Sopenharmony_ci		hmac_sha1_update(&ctx, len[i], addr[i]);
145e5b75505Sopenharmony_ci	hmac_sha1_digest(&ctx, SHA1_DIGEST_SIZE, mac);
146e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
147e5b75505Sopenharmony_ci	return 0;
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	struct hmac_sha256_ctx ctx;
164e5b75505Sopenharmony_ci	size_t i;
165e5b75505Sopenharmony_ci
166e5b75505Sopenharmony_ci	if (TEST_FAIL())
167e5b75505Sopenharmony_ci		return -1;
168e5b75505Sopenharmony_ci
169e5b75505Sopenharmony_ci	hmac_sha256_set_key(&ctx, key_len, key);
170e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
171e5b75505Sopenharmony_ci		hmac_sha256_update(&ctx, len[i], addr[i]);
172e5b75505Sopenharmony_ci	hmac_sha256_digest(&ctx, SHA256_DIGEST_SIZE, mac);
173e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
174e5b75505Sopenharmony_ci	return 0;
175e5b75505Sopenharmony_ci}
176e5b75505Sopenharmony_ci
177e5b75505Sopenharmony_ci
178e5b75505Sopenharmony_ciint hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
179e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
180e5b75505Sopenharmony_ci{
181e5b75505Sopenharmony_ci	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
182e5b75505Sopenharmony_ci}
183e5b75505Sopenharmony_ci
184e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
185e5b75505Sopenharmony_ci
186e5b75505Sopenharmony_ci
187e5b75505Sopenharmony_ci#ifdef CONFIG_SHA384
188e5b75505Sopenharmony_ci
189e5b75505Sopenharmony_ciint hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
190e5b75505Sopenharmony_ci		       const u8 *addr[], const size_t *len, u8 *mac)
191e5b75505Sopenharmony_ci{
192e5b75505Sopenharmony_ci	struct hmac_sha384_ctx ctx;
193e5b75505Sopenharmony_ci	size_t i;
194e5b75505Sopenharmony_ci
195e5b75505Sopenharmony_ci	if (TEST_FAIL())
196e5b75505Sopenharmony_ci		return -1;
197e5b75505Sopenharmony_ci
198e5b75505Sopenharmony_ci	hmac_sha384_set_key(&ctx, key_len, key);
199e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
200e5b75505Sopenharmony_ci		hmac_sha384_update(&ctx, len[i], addr[i]);
201e5b75505Sopenharmony_ci	hmac_sha384_digest(&ctx, SHA384_DIGEST_SIZE, mac);
202e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
203e5b75505Sopenharmony_ci	return 0;
204e5b75505Sopenharmony_ci}
205e5b75505Sopenharmony_ci
206e5b75505Sopenharmony_ci
207e5b75505Sopenharmony_ciint hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
208e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
209e5b75505Sopenharmony_ci{
210e5b75505Sopenharmony_ci	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
211e5b75505Sopenharmony_ci}
212e5b75505Sopenharmony_ci
213e5b75505Sopenharmony_ci#endif /* CONFIG_SHA384 */
214e5b75505Sopenharmony_ci
215e5b75505Sopenharmony_ci
216e5b75505Sopenharmony_ci#ifdef CONFIG_SHA512
217e5b75505Sopenharmony_ci
218e5b75505Sopenharmony_ciint hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
219e5b75505Sopenharmony_ci		       const u8 *addr[], const size_t *len, u8 *mac)
220e5b75505Sopenharmony_ci{
221e5b75505Sopenharmony_ci	struct hmac_sha512_ctx ctx;
222e5b75505Sopenharmony_ci	size_t i;
223e5b75505Sopenharmony_ci
224e5b75505Sopenharmony_ci	if (TEST_FAIL())
225e5b75505Sopenharmony_ci		return -1;
226e5b75505Sopenharmony_ci
227e5b75505Sopenharmony_ci	hmac_sha512_set_key(&ctx, key_len, key);
228e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
229e5b75505Sopenharmony_ci		hmac_sha512_update(&ctx, len[i], addr[i]);
230e5b75505Sopenharmony_ci	hmac_sha512_digest(&ctx, SHA512_DIGEST_SIZE, mac);
231e5b75505Sopenharmony_ci	os_memset(&ctx, 0, sizeof(ctx));
232e5b75505Sopenharmony_ci	return 0;
233e5b75505Sopenharmony_ci}
234e5b75505Sopenharmony_ci
235e5b75505Sopenharmony_ci
236e5b75505Sopenharmony_ciint hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
237e5b75505Sopenharmony_ci		size_t data_len, u8 *mac)
238e5b75505Sopenharmony_ci{
239e5b75505Sopenharmony_ci	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
240e5b75505Sopenharmony_ci}
241e5b75505Sopenharmony_ci
242e5b75505Sopenharmony_ci#endif /* CONFIG_SHA512 */
243e5b75505Sopenharmony_ci
244e5b75505Sopenharmony_ci
245e5b75505Sopenharmony_civoid * aes_encrypt_init(const u8 *key, size_t len)
246e5b75505Sopenharmony_ci{
247e5b75505Sopenharmony_ci	struct aes_ctx *ctx;
248e5b75505Sopenharmony_ci
249e5b75505Sopenharmony_ci	if (TEST_FAIL())
250e5b75505Sopenharmony_ci		return NULL;
251e5b75505Sopenharmony_ci	ctx = os_malloc(sizeof(*ctx));
252e5b75505Sopenharmony_ci	if (!ctx)
253e5b75505Sopenharmony_ci		return NULL;
254e5b75505Sopenharmony_ci
255e5b75505Sopenharmony_ci	nettle_aes_set_encrypt_key(ctx, len, key);
256e5b75505Sopenharmony_ci
257e5b75505Sopenharmony_ci	return ctx;
258e5b75505Sopenharmony_ci}
259e5b75505Sopenharmony_ci
260e5b75505Sopenharmony_ci
261e5b75505Sopenharmony_ciint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
262e5b75505Sopenharmony_ci{
263e5b75505Sopenharmony_ci	struct aes_ctx *actx = ctx;
264e5b75505Sopenharmony_ci	nettle_aes_encrypt(actx, AES_BLOCK_SIZE, crypt, plain);
265e5b75505Sopenharmony_ci	return 0;
266e5b75505Sopenharmony_ci}
267e5b75505Sopenharmony_ci
268e5b75505Sopenharmony_ci
269e5b75505Sopenharmony_civoid aes_encrypt_deinit(void *ctx)
270e5b75505Sopenharmony_ci{
271e5b75505Sopenharmony_ci	struct aes_ctx *actx = ctx;
272e5b75505Sopenharmony_ci	bin_clear_free(actx, sizeof(*actx));
273e5b75505Sopenharmony_ci}
274e5b75505Sopenharmony_ci
275e5b75505Sopenharmony_ci
276e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len)
277e5b75505Sopenharmony_ci{
278e5b75505Sopenharmony_ci	struct aes_ctx *ctx;
279e5b75505Sopenharmony_ci
280e5b75505Sopenharmony_ci	if (TEST_FAIL())
281e5b75505Sopenharmony_ci		return NULL;
282e5b75505Sopenharmony_ci	ctx = os_malloc(sizeof(*ctx));
283e5b75505Sopenharmony_ci	if (!ctx)
284e5b75505Sopenharmony_ci		return NULL;
285e5b75505Sopenharmony_ci
286e5b75505Sopenharmony_ci	nettle_aes_set_decrypt_key(ctx, len, key);
287e5b75505Sopenharmony_ci
288e5b75505Sopenharmony_ci	return ctx;
289e5b75505Sopenharmony_ci}
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci
292e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
293e5b75505Sopenharmony_ci{
294e5b75505Sopenharmony_ci	struct aes_ctx *actx = ctx;
295e5b75505Sopenharmony_ci	nettle_aes_decrypt(actx, AES_BLOCK_SIZE, plain, crypt);
296e5b75505Sopenharmony_ci	return 0;
297e5b75505Sopenharmony_ci}
298e5b75505Sopenharmony_ci
299e5b75505Sopenharmony_ci
300e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx)
301e5b75505Sopenharmony_ci{
302e5b75505Sopenharmony_ci	struct aes_ctx *actx = ctx;
303e5b75505Sopenharmony_ci	bin_clear_free(actx, sizeof(*actx));
304e5b75505Sopenharmony_ci}
305e5b75505Sopenharmony_ci
306e5b75505Sopenharmony_ci
307e5b75505Sopenharmony_ciint crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
308e5b75505Sopenharmony_ci		   u8 *pubkey)
309e5b75505Sopenharmony_ci{
310e5b75505Sopenharmony_ci	size_t pubkey_len, pad;
311e5b75505Sopenharmony_ci
312e5b75505Sopenharmony_ci	if (os_get_random(privkey, prime_len) < 0)
313e5b75505Sopenharmony_ci		return -1;
314e5b75505Sopenharmony_ci	if (os_memcmp(privkey, prime, prime_len) > 0) {
315e5b75505Sopenharmony_ci		/* Make sure private value is smaller than prime */
316e5b75505Sopenharmony_ci		privkey[0] = 0;
317e5b75505Sopenharmony_ci	}
318e5b75505Sopenharmony_ci
319e5b75505Sopenharmony_ci	pubkey_len = prime_len;
320e5b75505Sopenharmony_ci	if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
321e5b75505Sopenharmony_ci			   pubkey, &pubkey_len) < 0)
322e5b75505Sopenharmony_ci		return -1;
323e5b75505Sopenharmony_ci	if (pubkey_len < prime_len) {
324e5b75505Sopenharmony_ci		pad = prime_len - pubkey_len;
325e5b75505Sopenharmony_ci		os_memmove(pubkey + pad, pubkey, pubkey_len);
326e5b75505Sopenharmony_ci		os_memset(pubkey, 0, pad);
327e5b75505Sopenharmony_ci	}
328e5b75505Sopenharmony_ci
329e5b75505Sopenharmony_ci	return 0;
330e5b75505Sopenharmony_ci}
331e5b75505Sopenharmony_ci
332e5b75505Sopenharmony_ci
333e5b75505Sopenharmony_ciint crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
334e5b75505Sopenharmony_ci			    const u8 *order, size_t order_len,
335e5b75505Sopenharmony_ci			    const u8 *privkey, size_t privkey_len,
336e5b75505Sopenharmony_ci			    const u8 *pubkey, size_t pubkey_len,
337e5b75505Sopenharmony_ci			    u8 *secret, size_t *len)
338e5b75505Sopenharmony_ci{
339e5b75505Sopenharmony_ci	mpz_t pub;
340e5b75505Sopenharmony_ci	int res = -1;
341e5b75505Sopenharmony_ci
342e5b75505Sopenharmony_ci	if (pubkey_len > prime_len ||
343e5b75505Sopenharmony_ci	    (pubkey_len == prime_len &&
344e5b75505Sopenharmony_ci	     os_memcmp(pubkey, prime, prime_len) >= 0))
345e5b75505Sopenharmony_ci		return -1;
346e5b75505Sopenharmony_ci
347e5b75505Sopenharmony_ci	mpz_init(pub);
348e5b75505Sopenharmony_ci	mpz_import(pub, pubkey_len, 1, 1, 1, 0, pubkey);
349e5b75505Sopenharmony_ci	if (mpz_cmp_d(pub, 1) <= 0)
350e5b75505Sopenharmony_ci		goto fail;
351e5b75505Sopenharmony_ci
352e5b75505Sopenharmony_ci	if (order) {
353e5b75505Sopenharmony_ci		mpz_t p, q, tmp;
354e5b75505Sopenharmony_ci		int failed;
355e5b75505Sopenharmony_ci
356e5b75505Sopenharmony_ci		/* verify: pubkey^q == 1 mod p */
357e5b75505Sopenharmony_ci		mpz_inits(p, q, tmp, NULL);
358e5b75505Sopenharmony_ci		mpz_import(p, prime_len, 1, 1, 1, 0, prime);
359e5b75505Sopenharmony_ci		mpz_import(q, order_len, 1, 1, 1, 0, order);
360e5b75505Sopenharmony_ci		mpz_powm(tmp, pub, q, p);
361e5b75505Sopenharmony_ci		failed = mpz_cmp_d(tmp, 1) != 0;
362e5b75505Sopenharmony_ci		mpz_clears(p, q, tmp, NULL);
363e5b75505Sopenharmony_ci		if (failed)
364e5b75505Sopenharmony_ci			goto fail;
365e5b75505Sopenharmony_ci	}
366e5b75505Sopenharmony_ci
367e5b75505Sopenharmony_ci	res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
368e5b75505Sopenharmony_ci			     prime, prime_len, secret, len);
369e5b75505Sopenharmony_cifail:
370e5b75505Sopenharmony_ci	mpz_clear(pub);
371e5b75505Sopenharmony_ci	return res;
372e5b75505Sopenharmony_ci}
373e5b75505Sopenharmony_ci
374e5b75505Sopenharmony_ci
375e5b75505Sopenharmony_ciint crypto_mod_exp(const u8 *base, size_t base_len,
376e5b75505Sopenharmony_ci		   const u8 *power, size_t power_len,
377e5b75505Sopenharmony_ci		   const u8 *modulus, size_t modulus_len,
378e5b75505Sopenharmony_ci		   u8 *result, size_t *result_len)
379e5b75505Sopenharmony_ci{
380e5b75505Sopenharmony_ci	mpz_t bn_base, bn_exp, bn_modulus, bn_result;
381e5b75505Sopenharmony_ci	int ret = -1;
382e5b75505Sopenharmony_ci	size_t len;
383e5b75505Sopenharmony_ci
384e5b75505Sopenharmony_ci	mpz_inits(bn_base, bn_exp, bn_modulus, bn_result, NULL);
385e5b75505Sopenharmony_ci	mpz_import(bn_base, base_len, 1, 1, 1, 0, base);
386e5b75505Sopenharmony_ci	mpz_import(bn_exp, power_len, 1, 1, 1, 0, power);
387e5b75505Sopenharmony_ci	mpz_import(bn_modulus, modulus_len, 1, 1, 1, 0, modulus);
388e5b75505Sopenharmony_ci
389e5b75505Sopenharmony_ci	mpz_powm(bn_result, bn_base, bn_exp, bn_modulus);
390e5b75505Sopenharmony_ci	len = mpz_sizeinbase(bn_result, 2);
391e5b75505Sopenharmony_ci	len = (len + 7) / 8;
392e5b75505Sopenharmony_ci	if (*result_len < len)
393e5b75505Sopenharmony_ci		goto error;
394e5b75505Sopenharmony_ci	mpz_export(result, result_len, 1, 1, 1, 0, bn_result);
395e5b75505Sopenharmony_ci	ret = 0;
396e5b75505Sopenharmony_ci
397e5b75505Sopenharmony_cierror:
398e5b75505Sopenharmony_ci	mpz_clears(bn_base, bn_exp, bn_modulus, bn_result, NULL);
399e5b75505Sopenharmony_ci	return ret;
400e5b75505Sopenharmony_ci}
401e5b75505Sopenharmony_ci
402e5b75505Sopenharmony_ci
403e5b75505Sopenharmony_cistruct crypto_cipher {
404e5b75505Sopenharmony_ci	enum crypto_cipher_alg alg;
405e5b75505Sopenharmony_ci	union {
406e5b75505Sopenharmony_ci		struct arcfour_ctx arcfour_ctx;
407e5b75505Sopenharmony_ci	} u;
408e5b75505Sopenharmony_ci};
409e5b75505Sopenharmony_ci
410e5b75505Sopenharmony_ci
411e5b75505Sopenharmony_cistruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
412e5b75505Sopenharmony_ci					  const u8 *iv, const u8 *key,
413e5b75505Sopenharmony_ci					  size_t key_len)
414e5b75505Sopenharmony_ci{
415e5b75505Sopenharmony_ci	struct crypto_cipher *ctx;
416e5b75505Sopenharmony_ci
417e5b75505Sopenharmony_ci	ctx = os_zalloc(sizeof(*ctx));
418e5b75505Sopenharmony_ci	if (!ctx)
419e5b75505Sopenharmony_ci		return NULL;
420e5b75505Sopenharmony_ci
421e5b75505Sopenharmony_ci	ctx->alg = alg;
422e5b75505Sopenharmony_ci
423e5b75505Sopenharmony_ci	switch (alg) {
424e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_RC4:
425e5b75505Sopenharmony_ci		nettle_arcfour_set_key(&ctx->u.arcfour_ctx, key_len, key);
426e5b75505Sopenharmony_ci		break;
427e5b75505Sopenharmony_ci	default:
428e5b75505Sopenharmony_ci		os_free(ctx);
429e5b75505Sopenharmony_ci		return NULL;
430e5b75505Sopenharmony_ci	}
431e5b75505Sopenharmony_ci
432e5b75505Sopenharmony_ci	return ctx;
433e5b75505Sopenharmony_ci}
434e5b75505Sopenharmony_ci
435e5b75505Sopenharmony_ci
436e5b75505Sopenharmony_ciint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
437e5b75505Sopenharmony_ci			  u8 *crypt, size_t len)
438e5b75505Sopenharmony_ci{
439e5b75505Sopenharmony_ci	switch (ctx->alg) {
440e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_RC4:
441e5b75505Sopenharmony_ci		nettle_arcfour_crypt(&ctx->u.arcfour_ctx, len, crypt, plain);
442e5b75505Sopenharmony_ci		break;
443e5b75505Sopenharmony_ci	default:
444e5b75505Sopenharmony_ci		return -1;
445e5b75505Sopenharmony_ci	}
446e5b75505Sopenharmony_ci
447e5b75505Sopenharmony_ci	return 0;
448e5b75505Sopenharmony_ci}
449e5b75505Sopenharmony_ci
450e5b75505Sopenharmony_ci
451e5b75505Sopenharmony_ciint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
452e5b75505Sopenharmony_ci			  u8 *plain, size_t len)
453e5b75505Sopenharmony_ci{
454e5b75505Sopenharmony_ci	switch (ctx->alg) {
455e5b75505Sopenharmony_ci	case CRYPTO_CIPHER_ALG_RC4:
456e5b75505Sopenharmony_ci		nettle_arcfour_crypt(&ctx->u.arcfour_ctx, len, plain, crypt);
457e5b75505Sopenharmony_ci		break;
458e5b75505Sopenharmony_ci	default:
459e5b75505Sopenharmony_ci		return -1;
460e5b75505Sopenharmony_ci	}
461e5b75505Sopenharmony_ci
462e5b75505Sopenharmony_ci	return 0;
463e5b75505Sopenharmony_ci}
464e5b75505Sopenharmony_ci
465e5b75505Sopenharmony_ci
466e5b75505Sopenharmony_civoid crypto_cipher_deinit(struct crypto_cipher *ctx)
467e5b75505Sopenharmony_ci{
468e5b75505Sopenharmony_ci	bin_clear_free(ctx, sizeof(*ctx));
469e5b75505Sopenharmony_ci}
470