1189251Ssam/*
2281806Srpaulo * Wrapper functions for OpenSSL libcrypto
3281806Srpaulo * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam#include <openssl/opensslv.h>
11214734Srpaulo#include <openssl/err.h>
12189251Ssam#include <openssl/des.h>
13189251Ssam#include <openssl/aes.h>
14189251Ssam#include <openssl/bn.h>
15189251Ssam#include <openssl/evp.h>
16214734Srpaulo#include <openssl/dh.h>
17252726Srpaulo#include <openssl/hmac.h>
18252726Srpaulo#include <openssl/rand.h>
19252726Srpaulo#ifdef CONFIG_OPENSSL_CMAC
20252726Srpaulo#include <openssl/cmac.h>
21252726Srpaulo#endif /* CONFIG_OPENSSL_CMAC */
22281806Srpaulo#ifdef CONFIG_ECC
23281806Srpaulo#include <openssl/ec.h>
24281806Srpaulo#endif /* CONFIG_ECC */
25189251Ssam
26189251Ssam#include "common.h"
27214734Srpaulo#include "wpabuf.h"
28214734Srpaulo#include "dh_group5.h"
29281806Srpaulo#include "sha1.h"
30281806Srpaulo#include "sha256.h"
31281806Srpaulo#include "sha384.h"
32189251Ssam#include "crypto.h"
33189251Ssam
34214734Srpaulostatic BIGNUM * get_group5_prime(void)
35214734Srpaulo{
36281806Srpaulo#ifdef OPENSSL_IS_BORINGSSL
37214734Srpaulo	static const unsigned char RFC3526_PRIME_1536[] = {
38214734Srpaulo		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
39214734Srpaulo		0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
40214734Srpaulo		0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
41214734Srpaulo		0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
42214734Srpaulo		0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
43214734Srpaulo		0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
44214734Srpaulo		0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
45214734Srpaulo		0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
46214734Srpaulo		0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
47214734Srpaulo		0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
48214734Srpaulo		0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
49214734Srpaulo		0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
50214734Srpaulo		0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
51214734Srpaulo		0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
52214734Srpaulo		0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
53214734Srpaulo		0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
54214734Srpaulo	};
55214734Srpaulo        return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
56281806Srpaulo#else /* OPENSSL_IS_BORINGSSL */
57214734Srpaulo	return get_rfc3526_prime_1536(NULL);
58281806Srpaulo#endif /* OPENSSL_IS_BORINGSSL */
59214734Srpaulo}
60189251Ssam
61214734Srpaulo#ifdef OPENSSL_NO_SHA256
62214734Srpaulo#define NO_SHA256_WRAPPER
63214734Srpaulo#endif
64214734Srpaulo
65252726Srpaulostatic int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
66252726Srpaulo				 const u8 *addr[], const size_t *len, u8 *mac)
67189251Ssam{
68214734Srpaulo	EVP_MD_CTX ctx;
69189251Ssam	size_t i;
70214734Srpaulo	unsigned int mac_len;
71189251Ssam
72214734Srpaulo	EVP_MD_CTX_init(&ctx);
73214734Srpaulo	if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
74214734Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
75214734Srpaulo			   ERR_error_string(ERR_get_error(), NULL));
76214734Srpaulo		return -1;
77214734Srpaulo	}
78214734Srpaulo	for (i = 0; i < num_elem; i++) {
79214734Srpaulo		if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
80214734Srpaulo			wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
81214734Srpaulo				   "failed: %s",
82214734Srpaulo				   ERR_error_string(ERR_get_error(), NULL));
83214734Srpaulo			return -1;
84214734Srpaulo		}
85214734Srpaulo	}
86214734Srpaulo	if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
87214734Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
88214734Srpaulo			   ERR_error_string(ERR_get_error(), NULL));
89214734Srpaulo		return -1;
90214734Srpaulo	}
91214734Srpaulo
92214734Srpaulo	return 0;
93189251Ssam}
94189251Ssam
95189251Ssam
96289549Srpaulo#ifndef CONFIG_FIPS
97214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
98214734Srpaulo{
99252726Srpaulo	return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
100214734Srpaulo}
101289549Srpaulo#endif /* CONFIG_FIPS */
102214734Srpaulo
103214734Srpaulo
104189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
105189251Ssam{
106189251Ssam	u8 pkey[8], next, tmp;
107189251Ssam	int i;
108189251Ssam	DES_key_schedule ks;
109189251Ssam
110189251Ssam	/* Add parity bits to the key */
111189251Ssam	next = 0;
112189251Ssam	for (i = 0; i < 7; i++) {
113189251Ssam		tmp = key[i];
114189251Ssam		pkey[i] = (tmp >> i) | next | 1;
115189251Ssam		next = tmp << (7 - i);
116189251Ssam	}
117189251Ssam	pkey[i] = next | 1;
118189251Ssam
119281806Srpaulo	DES_set_key((DES_cblock *) &pkey, &ks);
120189251Ssam	DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
121189251Ssam			DES_ENCRYPT);
122189251Ssam}
123189251Ssam
124189251Ssam
125289549Srpaulo#ifndef CONFIG_NO_RC4
126214734Srpauloint rc4_skip(const u8 *key, size_t keylen, size_t skip,
127214734Srpaulo	     u8 *data, size_t data_len)
128189251Ssam{
129214734Srpaulo#ifdef OPENSSL_NO_RC4
130214734Srpaulo	return -1;
131214734Srpaulo#else /* OPENSSL_NO_RC4 */
132214734Srpaulo	EVP_CIPHER_CTX ctx;
133214734Srpaulo	int outl;
134214734Srpaulo	int res = -1;
135214734Srpaulo	unsigned char skip_buf[16];
136189251Ssam
137214734Srpaulo	EVP_CIPHER_CTX_init(&ctx);
138214734Srpaulo	if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
139214734Srpaulo	    !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
140214734Srpaulo	    !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
141214734Srpaulo	    !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
142214734Srpaulo		goto out;
143189251Ssam
144214734Srpaulo	while (skip >= sizeof(skip_buf)) {
145214734Srpaulo		size_t len = skip;
146214734Srpaulo		if (len > sizeof(skip_buf))
147214734Srpaulo			len = sizeof(skip_buf);
148214734Srpaulo		if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
149214734Srpaulo			goto out;
150214734Srpaulo		skip -= len;
151214734Srpaulo	}
152189251Ssam
153214734Srpaulo	if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
154214734Srpaulo		res = 0;
155189251Ssam
156214734Srpauloout:
157214734Srpaulo	EVP_CIPHER_CTX_cleanup(&ctx);
158214734Srpaulo	return res;
159214734Srpaulo#endif /* OPENSSL_NO_RC4 */
160189251Ssam}
161289549Srpaulo#endif /* CONFIG_NO_RC4 */
162189251Ssam
163189251Ssam
164289549Srpaulo#ifndef CONFIG_FIPS
165214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
166189251Ssam{
167252726Srpaulo	return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac);
168189251Ssam}
169289549Srpaulo#endif /* CONFIG_FIPS */
170189251Ssam
171189251Ssam
172214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
173214734Srpaulo{
174252726Srpaulo	return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac);
175214734Srpaulo}
176189251Ssam
177189251Ssam
178214734Srpaulo#ifndef NO_SHA256_WRAPPER
179214734Srpauloint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
180214734Srpaulo		  u8 *mac)
181214734Srpaulo{
182252726Srpaulo	return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac);
183189251Ssam}
184214734Srpaulo#endif /* NO_SHA256_WRAPPER */
185189251Ssam
186189251Ssam
187252726Srpaulostatic const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
188252726Srpaulo{
189252726Srpaulo	switch (keylen) {
190252726Srpaulo	case 16:
191252726Srpaulo		return EVP_aes_128_ecb();
192281806Srpaulo#ifndef OPENSSL_IS_BORINGSSL
193252726Srpaulo	case 24:
194252726Srpaulo		return EVP_aes_192_ecb();
195281806Srpaulo#endif /* OPENSSL_IS_BORINGSSL */
196252726Srpaulo	case 32:
197252726Srpaulo		return EVP_aes_256_ecb();
198252726Srpaulo	}
199252726Srpaulo
200252726Srpaulo	return NULL;
201252726Srpaulo}
202252726Srpaulo
203252726Srpaulo
204189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len)
205189251Ssam{
206252726Srpaulo	EVP_CIPHER_CTX *ctx;
207252726Srpaulo	const EVP_CIPHER *type;
208252726Srpaulo
209252726Srpaulo	type = aes_get_evp_cipher(len);
210252726Srpaulo	if (type == NULL)
211189251Ssam		return NULL;
212252726Srpaulo
213252726Srpaulo	ctx = os_malloc(sizeof(*ctx));
214252726Srpaulo	if (ctx == NULL)
215189251Ssam		return NULL;
216252726Srpaulo	EVP_CIPHER_CTX_init(ctx);
217252726Srpaulo	if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
218252726Srpaulo		os_free(ctx);
219252726Srpaulo		return NULL;
220189251Ssam	}
221252726Srpaulo	EVP_CIPHER_CTX_set_padding(ctx, 0);
222252726Srpaulo	return ctx;
223189251Ssam}
224189251Ssam
225189251Ssam
226189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
227189251Ssam{
228252726Srpaulo	EVP_CIPHER_CTX *c = ctx;
229252726Srpaulo	int clen = 16;
230252726Srpaulo	if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) {
231252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s",
232252726Srpaulo			   ERR_error_string(ERR_get_error(), NULL));
233252726Srpaulo	}
234189251Ssam}
235189251Ssam
236189251Ssam
237189251Ssamvoid aes_encrypt_deinit(void *ctx)
238189251Ssam{
239252726Srpaulo	EVP_CIPHER_CTX *c = ctx;
240252726Srpaulo	u8 buf[16];
241252726Srpaulo	int len = sizeof(buf);
242252726Srpaulo	if (EVP_EncryptFinal_ex(c, buf, &len) != 1) {
243252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: "
244252726Srpaulo			   "%s", ERR_error_string(ERR_get_error(), NULL));
245252726Srpaulo	}
246252726Srpaulo	if (len != 0) {
247252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
248252726Srpaulo			   "in AES encrypt", len);
249252726Srpaulo	}
250252726Srpaulo	EVP_CIPHER_CTX_cleanup(c);
251281806Srpaulo	bin_clear_free(c, sizeof(*c));
252189251Ssam}
253189251Ssam
254189251Ssam
255189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len)
256189251Ssam{
257252726Srpaulo	EVP_CIPHER_CTX *ctx;
258252726Srpaulo	const EVP_CIPHER *type;
259252726Srpaulo
260252726Srpaulo	type = aes_get_evp_cipher(len);
261252726Srpaulo	if (type == NULL)
262189251Ssam		return NULL;
263252726Srpaulo
264252726Srpaulo	ctx = os_malloc(sizeof(*ctx));
265252726Srpaulo	if (ctx == NULL)
266189251Ssam		return NULL;
267252726Srpaulo	EVP_CIPHER_CTX_init(ctx);
268252726Srpaulo	if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
269252726Srpaulo		os_free(ctx);
270252726Srpaulo		return NULL;
271189251Ssam	}
272252726Srpaulo	EVP_CIPHER_CTX_set_padding(ctx, 0);
273252726Srpaulo	return ctx;
274189251Ssam}
275189251Ssam
276189251Ssam
277189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
278189251Ssam{
279252726Srpaulo	EVP_CIPHER_CTX *c = ctx;
280252726Srpaulo	int plen = 16;
281252726Srpaulo	if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) {
282252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s",
283252726Srpaulo			   ERR_error_string(ERR_get_error(), NULL));
284252726Srpaulo	}
285189251Ssam}
286189251Ssam
287189251Ssam
288189251Ssamvoid aes_decrypt_deinit(void *ctx)
289189251Ssam{
290252726Srpaulo	EVP_CIPHER_CTX *c = ctx;
291252726Srpaulo	u8 buf[16];
292252726Srpaulo	int len = sizeof(buf);
293252726Srpaulo	if (EVP_DecryptFinal_ex(c, buf, &len) != 1) {
294252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: "
295252726Srpaulo			   "%s", ERR_error_string(ERR_get_error(), NULL));
296252726Srpaulo	}
297252726Srpaulo	if (len != 0) {
298252726Srpaulo		wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
299252726Srpaulo			   "in AES decrypt", len);
300252726Srpaulo	}
301252726Srpaulo	EVP_CIPHER_CTX_cleanup(c);
302281806Srpaulo	bin_clear_free(c, sizeof(*c));
303189251Ssam}
304189251Ssam
305189251Ssam
306289549Srpaulo#ifndef CONFIG_FIPS
307289549Srpaulo#ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP
308289549Srpaulo
309281806Srpauloint aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
310281806Srpaulo{
311281806Srpaulo	AES_KEY actx;
312281806Srpaulo	int res;
313281806Srpaulo
314281806Srpaulo	if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
315281806Srpaulo		return -1;
316281806Srpaulo	res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
317281806Srpaulo	OPENSSL_cleanse(&actx, sizeof(actx));
318281806Srpaulo	return res <= 0 ? -1 : 0;
319281806Srpaulo}
320281806Srpaulo
321281806Srpaulo
322281806Srpauloint aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
323281806Srpaulo	       u8 *plain)
324281806Srpaulo{
325281806Srpaulo	AES_KEY actx;
326281806Srpaulo	int res;
327281806Srpaulo
328281806Srpaulo	if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
329281806Srpaulo		return -1;
330281806Srpaulo	res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
331281806Srpaulo	OPENSSL_cleanse(&actx, sizeof(actx));
332281806Srpaulo	return res <= 0 ? -1 : 0;
333281806Srpaulo}
334281806Srpaulo
335289549Srpaulo#endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */
336289549Srpaulo#endif /* CONFIG_FIPS */
337281806Srpaulo
338289549Srpaulo
339289549Srpauloint aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
340289549Srpaulo{
341289549Srpaulo	EVP_CIPHER_CTX ctx;
342289549Srpaulo	int clen, len;
343289549Srpaulo	u8 buf[16];
344289549Srpaulo
345289549Srpaulo	EVP_CIPHER_CTX_init(&ctx);
346289549Srpaulo	if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
347289549Srpaulo		return -1;
348289549Srpaulo	EVP_CIPHER_CTX_set_padding(&ctx, 0);
349289549Srpaulo
350289549Srpaulo	clen = data_len;
351289549Srpaulo	if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
352289549Srpaulo	    clen != (int) data_len)
353289549Srpaulo		return -1;
354289549Srpaulo
355289549Srpaulo	len = sizeof(buf);
356289549Srpaulo	if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
357289549Srpaulo		return -1;
358289549Srpaulo	EVP_CIPHER_CTX_cleanup(&ctx);
359289549Srpaulo
360289549Srpaulo	return 0;
361289549Srpaulo}
362289549Srpaulo
363289549Srpaulo
364289549Srpauloint aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
365289549Srpaulo{
366289549Srpaulo	EVP_CIPHER_CTX ctx;
367289549Srpaulo	int plen, len;
368289549Srpaulo	u8 buf[16];
369289549Srpaulo
370289549Srpaulo	EVP_CIPHER_CTX_init(&ctx);
371289549Srpaulo	if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
372289549Srpaulo		return -1;
373289549Srpaulo	EVP_CIPHER_CTX_set_padding(&ctx, 0);
374289549Srpaulo
375289549Srpaulo	plen = data_len;
376289549Srpaulo	if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
377289549Srpaulo	    plen != (int) data_len)
378289549Srpaulo		return -1;
379289549Srpaulo
380289549Srpaulo	len = sizeof(buf);
381289549Srpaulo	if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
382289549Srpaulo		return -1;
383289549Srpaulo	EVP_CIPHER_CTX_cleanup(&ctx);
384289549Srpaulo
385289549Srpaulo	return 0;
386289549Srpaulo}
387289549Srpaulo
388289549Srpaulo
389189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len,
390189251Ssam		   const u8 *power, size_t power_len,
391189251Ssam		   const u8 *modulus, size_t modulus_len,
392189251Ssam		   u8 *result, size_t *result_len)
393189251Ssam{
394189251Ssam	BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
395189251Ssam	int ret = -1;
396189251Ssam	BN_CTX *ctx;
397189251Ssam
398189251Ssam	ctx = BN_CTX_new();
399189251Ssam	if (ctx == NULL)
400189251Ssam		return -1;
401189251Ssam
402189251Ssam	bn_base = BN_bin2bn(base, base_len, NULL);
403189251Ssam	bn_exp = BN_bin2bn(power, power_len, NULL);
404189251Ssam	bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
405189251Ssam	bn_result = BN_new();
406189251Ssam
407189251Ssam	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
408189251Ssam	    bn_result == NULL)
409189251Ssam		goto error;
410189251Ssam
411189251Ssam	if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
412189251Ssam		goto error;
413189251Ssam
414189251Ssam	*result_len = BN_bn2bin(bn_result, result);
415189251Ssam	ret = 0;
416189251Ssam
417189251Ssamerror:
418281806Srpaulo	BN_clear_free(bn_base);
419281806Srpaulo	BN_clear_free(bn_exp);
420281806Srpaulo	BN_clear_free(bn_modulus);
421281806Srpaulo	BN_clear_free(bn_result);
422189251Ssam	BN_CTX_free(ctx);
423189251Ssam	return ret;
424189251Ssam}
425189251Ssam
426189251Ssam
427189251Ssamstruct crypto_cipher {
428189251Ssam	EVP_CIPHER_CTX enc;
429189251Ssam	EVP_CIPHER_CTX dec;
430189251Ssam};
431189251Ssam
432189251Ssam
433189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
434189251Ssam					  const u8 *iv, const u8 *key,
435189251Ssam					  size_t key_len)
436189251Ssam{
437189251Ssam	struct crypto_cipher *ctx;
438189251Ssam	const EVP_CIPHER *cipher;
439189251Ssam
440189251Ssam	ctx = os_zalloc(sizeof(*ctx));
441189251Ssam	if (ctx == NULL)
442189251Ssam		return NULL;
443189251Ssam
444189251Ssam	switch (alg) {
445289549Srpaulo#ifndef CONFIG_NO_RC4
446189251Ssam#ifndef OPENSSL_NO_RC4
447189251Ssam	case CRYPTO_CIPHER_ALG_RC4:
448189251Ssam		cipher = EVP_rc4();
449189251Ssam		break;
450189251Ssam#endif /* OPENSSL_NO_RC4 */
451289549Srpaulo#endif /* CONFIG_NO_RC4 */
452189251Ssam#ifndef OPENSSL_NO_AES
453189251Ssam	case CRYPTO_CIPHER_ALG_AES:
454189251Ssam		switch (key_len) {
455189251Ssam		case 16:
456189251Ssam			cipher = EVP_aes_128_cbc();
457189251Ssam			break;
458281806Srpaulo#ifndef OPENSSL_IS_BORINGSSL
459189251Ssam		case 24:
460189251Ssam			cipher = EVP_aes_192_cbc();
461189251Ssam			break;
462281806Srpaulo#endif /* OPENSSL_IS_BORINGSSL */
463189251Ssam		case 32:
464189251Ssam			cipher = EVP_aes_256_cbc();
465189251Ssam			break;
466189251Ssam		default:
467189251Ssam			os_free(ctx);
468189251Ssam			return NULL;
469189251Ssam		}
470189251Ssam		break;
471189251Ssam#endif /* OPENSSL_NO_AES */
472189251Ssam#ifndef OPENSSL_NO_DES
473189251Ssam	case CRYPTO_CIPHER_ALG_3DES:
474189251Ssam		cipher = EVP_des_ede3_cbc();
475189251Ssam		break;
476189251Ssam	case CRYPTO_CIPHER_ALG_DES:
477189251Ssam		cipher = EVP_des_cbc();
478189251Ssam		break;
479189251Ssam#endif /* OPENSSL_NO_DES */
480189251Ssam#ifndef OPENSSL_NO_RC2
481189251Ssam	case CRYPTO_CIPHER_ALG_RC2:
482189251Ssam		cipher = EVP_rc2_ecb();
483189251Ssam		break;
484189251Ssam#endif /* OPENSSL_NO_RC2 */
485189251Ssam	default:
486189251Ssam		os_free(ctx);
487189251Ssam		return NULL;
488189251Ssam	}
489189251Ssam
490189251Ssam	EVP_CIPHER_CTX_init(&ctx->enc);
491189251Ssam	EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
492189251Ssam	if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
493189251Ssam	    !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
494214734Srpaulo	    !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
495189251Ssam		EVP_CIPHER_CTX_cleanup(&ctx->enc);
496189251Ssam		os_free(ctx);
497189251Ssam		return NULL;
498189251Ssam	}
499189251Ssam
500189251Ssam	EVP_CIPHER_CTX_init(&ctx->dec);
501189251Ssam	EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
502189251Ssam	if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
503189251Ssam	    !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
504214734Srpaulo	    !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
505189251Ssam		EVP_CIPHER_CTX_cleanup(&ctx->enc);
506189251Ssam		EVP_CIPHER_CTX_cleanup(&ctx->dec);
507189251Ssam		os_free(ctx);
508189251Ssam		return NULL;
509189251Ssam	}
510189251Ssam
511189251Ssam	return ctx;
512189251Ssam}
513189251Ssam
514189251Ssam
515189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
516189251Ssam			  u8 *crypt, size_t len)
517189251Ssam{
518189251Ssam	int outl;
519189251Ssam	if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
520189251Ssam		return -1;
521189251Ssam	return 0;
522189251Ssam}
523189251Ssam
524189251Ssam
525189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
526189251Ssam			  u8 *plain, size_t len)
527189251Ssam{
528189251Ssam	int outl;
529189251Ssam	outl = len;
530189251Ssam	if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
531189251Ssam		return -1;
532189251Ssam	return 0;
533189251Ssam}
534189251Ssam
535189251Ssam
536189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
537189251Ssam{
538189251Ssam	EVP_CIPHER_CTX_cleanup(&ctx->enc);
539189251Ssam	EVP_CIPHER_CTX_cleanup(&ctx->dec);
540189251Ssam	os_free(ctx);
541189251Ssam}
542214734Srpaulo
543214734Srpaulo
544214734Srpaulovoid * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
545214734Srpaulo{
546214734Srpaulo	DH *dh;
547214734Srpaulo	struct wpabuf *pubkey = NULL, *privkey = NULL;
548214734Srpaulo	size_t publen, privlen;
549214734Srpaulo
550214734Srpaulo	*priv = NULL;
551214734Srpaulo	*publ = NULL;
552214734Srpaulo
553214734Srpaulo	dh = DH_new();
554214734Srpaulo	if (dh == NULL)
555214734Srpaulo		return NULL;
556214734Srpaulo
557214734Srpaulo	dh->g = BN_new();
558214734Srpaulo	if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
559214734Srpaulo		goto err;
560214734Srpaulo
561214734Srpaulo	dh->p = get_group5_prime();
562214734Srpaulo	if (dh->p == NULL)
563214734Srpaulo		goto err;
564214734Srpaulo
565214734Srpaulo	if (DH_generate_key(dh) != 1)
566214734Srpaulo		goto err;
567214734Srpaulo
568214734Srpaulo	publen = BN_num_bytes(dh->pub_key);
569214734Srpaulo	pubkey = wpabuf_alloc(publen);
570214734Srpaulo	if (pubkey == NULL)
571214734Srpaulo		goto err;
572214734Srpaulo	privlen = BN_num_bytes(dh->priv_key);
573214734Srpaulo	privkey = wpabuf_alloc(privlen);
574214734Srpaulo	if (privkey == NULL)
575214734Srpaulo		goto err;
576214734Srpaulo
577214734Srpaulo	BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen));
578214734Srpaulo	BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen));
579214734Srpaulo
580214734Srpaulo	*priv = privkey;
581214734Srpaulo	*publ = pubkey;
582214734Srpaulo	return dh;
583214734Srpaulo
584214734Srpauloerr:
585281806Srpaulo	wpabuf_clear_free(pubkey);
586281806Srpaulo	wpabuf_clear_free(privkey);
587214734Srpaulo	DH_free(dh);
588214734Srpaulo	return NULL;
589214734Srpaulo}
590214734Srpaulo
591214734Srpaulo
592252726Srpaulovoid * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
593252726Srpaulo{
594252726Srpaulo	DH *dh;
595252726Srpaulo
596252726Srpaulo	dh = DH_new();
597252726Srpaulo	if (dh == NULL)
598252726Srpaulo		return NULL;
599252726Srpaulo
600252726Srpaulo	dh->g = BN_new();
601252726Srpaulo	if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
602252726Srpaulo		goto err;
603252726Srpaulo
604252726Srpaulo	dh->p = get_group5_prime();
605252726Srpaulo	if (dh->p == NULL)
606252726Srpaulo		goto err;
607252726Srpaulo
608252726Srpaulo	dh->priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
609252726Srpaulo	if (dh->priv_key == NULL)
610252726Srpaulo		goto err;
611252726Srpaulo
612252726Srpaulo	dh->pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
613252726Srpaulo	if (dh->pub_key == NULL)
614252726Srpaulo		goto err;
615252726Srpaulo
616252726Srpaulo	if (DH_generate_key(dh) != 1)
617252726Srpaulo		goto err;
618252726Srpaulo
619252726Srpaulo	return dh;
620252726Srpaulo
621252726Srpauloerr:
622252726Srpaulo	DH_free(dh);
623252726Srpaulo	return NULL;
624252726Srpaulo}
625252726Srpaulo
626252726Srpaulo
627214734Srpaulostruct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
628214734Srpaulo				  const struct wpabuf *own_private)
629214734Srpaulo{
630214734Srpaulo	BIGNUM *pub_key;
631214734Srpaulo	struct wpabuf *res = NULL;
632214734Srpaulo	size_t rlen;
633214734Srpaulo	DH *dh = ctx;
634214734Srpaulo	int keylen;
635214734Srpaulo
636214734Srpaulo	if (ctx == NULL)
637214734Srpaulo		return NULL;
638214734Srpaulo
639214734Srpaulo	pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
640214734Srpaulo			    NULL);
641214734Srpaulo	if (pub_key == NULL)
642214734Srpaulo		return NULL;
643214734Srpaulo
644214734Srpaulo	rlen = DH_size(dh);
645214734Srpaulo	res = wpabuf_alloc(rlen);
646214734Srpaulo	if (res == NULL)
647214734Srpaulo		goto err;
648214734Srpaulo
649214734Srpaulo	keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
650214734Srpaulo	if (keylen < 0)
651214734Srpaulo		goto err;
652214734Srpaulo	wpabuf_put(res, keylen);
653281806Srpaulo	BN_clear_free(pub_key);
654214734Srpaulo
655214734Srpaulo	return res;
656214734Srpaulo
657214734Srpauloerr:
658281806Srpaulo	BN_clear_free(pub_key);
659281806Srpaulo	wpabuf_clear_free(res);
660214734Srpaulo	return NULL;
661214734Srpaulo}
662214734Srpaulo
663214734Srpaulo
664214734Srpaulovoid dh5_free(void *ctx)
665214734Srpaulo{
666214734Srpaulo	DH *dh;
667214734Srpaulo	if (ctx == NULL)
668214734Srpaulo		return;
669214734Srpaulo	dh = ctx;
670214734Srpaulo	DH_free(dh);
671214734Srpaulo}
672252726Srpaulo
673252726Srpaulo
674252726Srpaulostruct crypto_hash {
675252726Srpaulo	HMAC_CTX ctx;
676252726Srpaulo};
677252726Srpaulo
678252726Srpaulo
679252726Srpaulostruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
680252726Srpaulo				      size_t key_len)
681252726Srpaulo{
682252726Srpaulo	struct crypto_hash *ctx;
683252726Srpaulo	const EVP_MD *md;
684252726Srpaulo
685252726Srpaulo	switch (alg) {
686252726Srpaulo#ifndef OPENSSL_NO_MD5
687252726Srpaulo	case CRYPTO_HASH_ALG_HMAC_MD5:
688252726Srpaulo		md = EVP_md5();
689252726Srpaulo		break;
690252726Srpaulo#endif /* OPENSSL_NO_MD5 */
691252726Srpaulo#ifndef OPENSSL_NO_SHA
692252726Srpaulo	case CRYPTO_HASH_ALG_HMAC_SHA1:
693252726Srpaulo		md = EVP_sha1();
694252726Srpaulo		break;
695252726Srpaulo#endif /* OPENSSL_NO_SHA */
696252726Srpaulo#ifndef OPENSSL_NO_SHA256
697252726Srpaulo#ifdef CONFIG_SHA256
698252726Srpaulo	case CRYPTO_HASH_ALG_HMAC_SHA256:
699252726Srpaulo		md = EVP_sha256();
700252726Srpaulo		break;
701252726Srpaulo#endif /* CONFIG_SHA256 */
702252726Srpaulo#endif /* OPENSSL_NO_SHA256 */
703252726Srpaulo	default:
704252726Srpaulo		return NULL;
705252726Srpaulo	}
706252726Srpaulo
707252726Srpaulo	ctx = os_zalloc(sizeof(*ctx));
708252726Srpaulo	if (ctx == NULL)
709252726Srpaulo		return NULL;
710252726Srpaulo	HMAC_CTX_init(&ctx->ctx);
711252726Srpaulo
712252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000
713252726Srpaulo	HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
714252726Srpaulo#else /* openssl < 0.9.9 */
715252726Srpaulo	if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
716281806Srpaulo		bin_clear_free(ctx, sizeof(*ctx));
717252726Srpaulo		return NULL;
718252726Srpaulo	}
719252726Srpaulo#endif /* openssl < 0.9.9 */
720252726Srpaulo
721252726Srpaulo	return ctx;
722252726Srpaulo}
723252726Srpaulo
724252726Srpaulo
725252726Srpaulovoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
726252726Srpaulo{
727252726Srpaulo	if (ctx == NULL)
728252726Srpaulo		return;
729252726Srpaulo	HMAC_Update(&ctx->ctx, data, len);
730252726Srpaulo}
731252726Srpaulo
732252726Srpaulo
733252726Srpauloint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
734252726Srpaulo{
735252726Srpaulo	unsigned int mdlen;
736252726Srpaulo	int res;
737252726Srpaulo
738252726Srpaulo	if (ctx == NULL)
739252726Srpaulo		return -2;
740252726Srpaulo
741252726Srpaulo	if (mac == NULL || len == NULL) {
742281806Srpaulo		bin_clear_free(ctx, sizeof(*ctx));
743252726Srpaulo		return 0;
744252726Srpaulo	}
745252726Srpaulo
746252726Srpaulo	mdlen = *len;
747252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000
748252726Srpaulo	HMAC_Final(&ctx->ctx, mac, &mdlen);
749252726Srpaulo	res = 1;
750252726Srpaulo#else /* openssl < 0.9.9 */
751252726Srpaulo	res = HMAC_Final(&ctx->ctx, mac, &mdlen);
752252726Srpaulo#endif /* openssl < 0.9.9 */
753252726Srpaulo	HMAC_CTX_cleanup(&ctx->ctx);
754281806Srpaulo	bin_clear_free(ctx, sizeof(*ctx));
755252726Srpaulo
756252726Srpaulo	if (res == 1) {
757252726Srpaulo		*len = mdlen;
758252726Srpaulo		return 0;
759252726Srpaulo	}
760252726Srpaulo
761252726Srpaulo	return -1;
762252726Srpaulo}
763252726Srpaulo
764252726Srpaulo
765281806Srpaulostatic int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
766281806Srpaulo			       size_t key_len, size_t num_elem,
767281806Srpaulo			       const u8 *addr[], const size_t *len, u8 *mac,
768281806Srpaulo			       unsigned int mdlen)
769252726Srpaulo{
770252726Srpaulo	HMAC_CTX ctx;
771252726Srpaulo	size_t i;
772252726Srpaulo	int res;
773252726Srpaulo
774252726Srpaulo	HMAC_CTX_init(&ctx);
775252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000
776281806Srpaulo	HMAC_Init_ex(&ctx, key, key_len, type, NULL);
777252726Srpaulo#else /* openssl < 0.9.9 */
778281806Srpaulo	if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
779252726Srpaulo		return -1;
780252726Srpaulo#endif /* openssl < 0.9.9 */
781252726Srpaulo
782252726Srpaulo	for (i = 0; i < num_elem; i++)
783252726Srpaulo		HMAC_Update(&ctx, addr[i], len[i]);
784252726Srpaulo
785252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000
786252726Srpaulo	HMAC_Final(&ctx, mac, &mdlen);
787252726Srpaulo	res = 1;
788252726Srpaulo#else /* openssl < 0.9.9 */
789252726Srpaulo	res = HMAC_Final(&ctx, mac, &mdlen);
790252726Srpaulo#endif /* openssl < 0.9.9 */
791252726Srpaulo	HMAC_CTX_cleanup(&ctx);
792252726Srpaulo
793252726Srpaulo	return res == 1 ? 0 : -1;
794252726Srpaulo}
795252726Srpaulo
796252726Srpaulo
797281806Srpaulo#ifndef CONFIG_FIPS
798281806Srpaulo
799281806Srpauloint hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
800281806Srpaulo		    const u8 *addr[], const size_t *len, u8 *mac)
801281806Srpaulo{
802281806Srpaulo	return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
803281806Srpaulo				   mac, 16);
804281806Srpaulo}
805281806Srpaulo
806281806Srpaulo
807281806Srpauloint hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
808281806Srpaulo	     u8 *mac)
809281806Srpaulo{
810281806Srpaulo	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
811281806Srpaulo}
812281806Srpaulo
813281806Srpaulo#endif /* CONFIG_FIPS */
814281806Srpaulo
815281806Srpaulo
816281806Srpauloint pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
817281806Srpaulo		int iterations, u8 *buf, size_t buflen)
818281806Srpaulo{
819281806Srpaulo	if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
820281806Srpaulo				   ssid_len, iterations, buflen, buf) != 1)
821281806Srpaulo		return -1;
822281806Srpaulo	return 0;
823281806Srpaulo}
824281806Srpaulo
825281806Srpaulo
826281806Srpauloint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
827281806Srpaulo		     const u8 *addr[], const size_t *len, u8 *mac)
828281806Srpaulo{
829281806Srpaulo	return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr,
830281806Srpaulo				   len, mac, 20);
831281806Srpaulo}
832281806Srpaulo
833281806Srpaulo
834252726Srpauloint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
835252726Srpaulo	       u8 *mac)
836252726Srpaulo{
837252726Srpaulo	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
838252726Srpaulo}
839252726Srpaulo
840252726Srpaulo
841252726Srpaulo#ifdef CONFIG_SHA256
842252726Srpaulo
843252726Srpauloint hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
844252726Srpaulo		       const u8 *addr[], const size_t *len, u8 *mac)
845252726Srpaulo{
846281806Srpaulo	return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr,
847281806Srpaulo				   len, mac, 32);
848281806Srpaulo}
849252726Srpaulo
850252726Srpaulo
851281806Srpauloint hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
852281806Srpaulo		size_t data_len, u8 *mac)
853281806Srpaulo{
854281806Srpaulo	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
855281806Srpaulo}
856252726Srpaulo
857281806Srpaulo#endif /* CONFIG_SHA256 */
858252726Srpaulo
859281806Srpaulo
860281806Srpaulo#ifdef CONFIG_SHA384
861281806Srpaulo
862281806Srpauloint hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
863281806Srpaulo		       const u8 *addr[], const size_t *len, u8 *mac)
864281806Srpaulo{
865281806Srpaulo	return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
866281806Srpaulo				   len, mac, 32);
867252726Srpaulo}
868252726Srpaulo
869252726Srpaulo
870281806Srpauloint hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
871252726Srpaulo		size_t data_len, u8 *mac)
872252726Srpaulo{
873281806Srpaulo	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
874252726Srpaulo}
875252726Srpaulo
876281806Srpaulo#endif /* CONFIG_SHA384 */
877252726Srpaulo
878252726Srpaulo
879252726Srpauloint crypto_get_random(void *buf, size_t len)
880252726Srpaulo{
881252726Srpaulo	if (RAND_bytes(buf, len) != 1)
882252726Srpaulo		return -1;
883252726Srpaulo	return 0;
884252726Srpaulo}
885252726Srpaulo
886252726Srpaulo
887252726Srpaulo#ifdef CONFIG_OPENSSL_CMAC
888281806Srpauloint omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
889281806Srpaulo		     const u8 *addr[], const size_t *len, u8 *mac)
890252726Srpaulo{
891252726Srpaulo	CMAC_CTX *ctx;
892252726Srpaulo	int ret = -1;
893252726Srpaulo	size_t outlen, i;
894252726Srpaulo
895252726Srpaulo	ctx = CMAC_CTX_new();
896252726Srpaulo	if (ctx == NULL)
897252726Srpaulo		return -1;
898252726Srpaulo
899281806Srpaulo	if (key_len == 32) {
900281806Srpaulo		if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL))
901281806Srpaulo			goto fail;
902281806Srpaulo	} else if (key_len == 16) {
903281806Srpaulo		if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
904281806Srpaulo			goto fail;
905281806Srpaulo	} else {
906252726Srpaulo		goto fail;
907281806Srpaulo	}
908252726Srpaulo	for (i = 0; i < num_elem; i++) {
909252726Srpaulo		if (!CMAC_Update(ctx, addr[i], len[i]))
910252726Srpaulo			goto fail;
911252726Srpaulo	}
912252726Srpaulo	if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16)
913252726Srpaulo		goto fail;
914252726Srpaulo
915252726Srpaulo	ret = 0;
916252726Srpaulofail:
917252726Srpaulo	CMAC_CTX_free(ctx);
918252726Srpaulo	return ret;
919252726Srpaulo}
920252726Srpaulo
921252726Srpaulo
922281806Srpauloint omac1_aes_128_vector(const u8 *key, size_t num_elem,
923281806Srpaulo			 const u8 *addr[], const size_t *len, u8 *mac)
924281806Srpaulo{
925281806Srpaulo	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
926281806Srpaulo}
927281806Srpaulo
928281806Srpaulo
929252726Srpauloint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
930252726Srpaulo{
931252726Srpaulo	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
932252726Srpaulo}
933281806Srpaulo
934281806Srpaulo
935281806Srpauloint omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
936281806Srpaulo{
937281806Srpaulo	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
938281806Srpaulo}
939252726Srpaulo#endif /* CONFIG_OPENSSL_CMAC */
940281806Srpaulo
941281806Srpaulo
942281806Srpaulostruct crypto_bignum * crypto_bignum_init(void)
943281806Srpaulo{
944281806Srpaulo	return (struct crypto_bignum *) BN_new();
945281806Srpaulo}
946281806Srpaulo
947281806Srpaulo
948281806Srpaulostruct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
949281806Srpaulo{
950281806Srpaulo	BIGNUM *bn = BN_bin2bn(buf, len, NULL);
951281806Srpaulo	return (struct crypto_bignum *) bn;
952281806Srpaulo}
953281806Srpaulo
954281806Srpaulo
955281806Srpaulovoid crypto_bignum_deinit(struct crypto_bignum *n, int clear)
956281806Srpaulo{
957281806Srpaulo	if (clear)
958281806Srpaulo		BN_clear_free((BIGNUM *) n);
959281806Srpaulo	else
960281806Srpaulo		BN_free((BIGNUM *) n);
961281806Srpaulo}
962281806Srpaulo
963281806Srpaulo
964281806Srpauloint crypto_bignum_to_bin(const struct crypto_bignum *a,
965281806Srpaulo			 u8 *buf, size_t buflen, size_t padlen)
966281806Srpaulo{
967281806Srpaulo	int num_bytes, offset;
968281806Srpaulo
969281806Srpaulo	if (padlen > buflen)
970281806Srpaulo		return -1;
971281806Srpaulo
972281806Srpaulo	num_bytes = BN_num_bytes((const BIGNUM *) a);
973281806Srpaulo	if ((size_t) num_bytes > buflen)
974281806Srpaulo		return -1;
975281806Srpaulo	if (padlen > (size_t) num_bytes)
976281806Srpaulo		offset = padlen - num_bytes;
977281806Srpaulo	else
978281806Srpaulo		offset = 0;
979281806Srpaulo
980281806Srpaulo	os_memset(buf, 0, offset);
981281806Srpaulo	BN_bn2bin((const BIGNUM *) a, buf + offset);
982281806Srpaulo
983281806Srpaulo	return num_bytes + offset;
984281806Srpaulo}
985281806Srpaulo
986281806Srpaulo
987281806Srpauloint crypto_bignum_add(const struct crypto_bignum *a,
988281806Srpaulo		      const struct crypto_bignum *b,
989281806Srpaulo		      struct crypto_bignum *c)
990281806Srpaulo{
991281806Srpaulo	return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
992281806Srpaulo		0 : -1;
993281806Srpaulo}
994281806Srpaulo
995281806Srpaulo
996281806Srpauloint crypto_bignum_mod(const struct crypto_bignum *a,
997281806Srpaulo		      const struct crypto_bignum *b,
998281806Srpaulo		      struct crypto_bignum *c)
999281806Srpaulo{
1000281806Srpaulo	int res;
1001281806Srpaulo	BN_CTX *bnctx;
1002281806Srpaulo
1003281806Srpaulo	bnctx = BN_CTX_new();
1004281806Srpaulo	if (bnctx == NULL)
1005281806Srpaulo		return -1;
1006281806Srpaulo	res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
1007281806Srpaulo		     bnctx);
1008281806Srpaulo	BN_CTX_free(bnctx);
1009281806Srpaulo
1010281806Srpaulo	return res ? 0 : -1;
1011281806Srpaulo}
1012281806Srpaulo
1013281806Srpaulo
1014281806Srpauloint crypto_bignum_exptmod(const struct crypto_bignum *a,
1015281806Srpaulo			  const struct crypto_bignum *b,
1016281806Srpaulo			  const struct crypto_bignum *c,
1017281806Srpaulo			  struct crypto_bignum *d)
1018281806Srpaulo{
1019281806Srpaulo	int res;
1020281806Srpaulo	BN_CTX *bnctx;
1021281806Srpaulo
1022281806Srpaulo	bnctx = BN_CTX_new();
1023281806Srpaulo	if (bnctx == NULL)
1024281806Srpaulo		return -1;
1025281806Srpaulo	res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
1026281806Srpaulo			 (const BIGNUM *) c, bnctx);
1027281806Srpaulo	BN_CTX_free(bnctx);
1028281806Srpaulo
1029281806Srpaulo	return res ? 0 : -1;
1030281806Srpaulo}
1031281806Srpaulo
1032281806Srpaulo
1033281806Srpauloint crypto_bignum_inverse(const struct crypto_bignum *a,
1034281806Srpaulo			  const struct crypto_bignum *b,
1035281806Srpaulo			  struct crypto_bignum *c)
1036281806Srpaulo{
1037281806Srpaulo	BIGNUM *res;
1038281806Srpaulo	BN_CTX *bnctx;
1039281806Srpaulo
1040281806Srpaulo	bnctx = BN_CTX_new();
1041281806Srpaulo	if (bnctx == NULL)
1042281806Srpaulo		return -1;
1043281806Srpaulo	res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
1044281806Srpaulo			     (const BIGNUM *) b, bnctx);
1045281806Srpaulo	BN_CTX_free(bnctx);
1046281806Srpaulo
1047281806Srpaulo	return res ? 0 : -1;
1048281806Srpaulo}
1049281806Srpaulo
1050281806Srpaulo
1051281806Srpauloint crypto_bignum_sub(const struct crypto_bignum *a,
1052281806Srpaulo		      const struct crypto_bignum *b,
1053281806Srpaulo		      struct crypto_bignum *c)
1054281806Srpaulo{
1055281806Srpaulo	return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
1056281806Srpaulo		0 : -1;
1057281806Srpaulo}
1058281806Srpaulo
1059281806Srpaulo
1060281806Srpauloint crypto_bignum_div(const struct crypto_bignum *a,
1061281806Srpaulo		      const struct crypto_bignum *b,
1062281806Srpaulo		      struct crypto_bignum *c)
1063281806Srpaulo{
1064281806Srpaulo	int res;
1065281806Srpaulo
1066281806Srpaulo	BN_CTX *bnctx;
1067281806Srpaulo
1068281806Srpaulo	bnctx = BN_CTX_new();
1069281806Srpaulo	if (bnctx == NULL)
1070281806Srpaulo		return -1;
1071281806Srpaulo	res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
1072281806Srpaulo		     (const BIGNUM *) b, bnctx);
1073281806Srpaulo	BN_CTX_free(bnctx);
1074281806Srpaulo
1075281806Srpaulo	return res ? 0 : -1;
1076281806Srpaulo}
1077281806Srpaulo
1078281806Srpaulo
1079281806Srpauloint crypto_bignum_mulmod(const struct crypto_bignum *a,
1080281806Srpaulo			 const struct crypto_bignum *b,
1081281806Srpaulo			 const struct crypto_bignum *c,
1082281806Srpaulo			 struct crypto_bignum *d)
1083281806Srpaulo{
1084281806Srpaulo	int res;
1085281806Srpaulo
1086281806Srpaulo	BN_CTX *bnctx;
1087281806Srpaulo
1088281806Srpaulo	bnctx = BN_CTX_new();
1089281806Srpaulo	if (bnctx == NULL)
1090281806Srpaulo		return -1;
1091281806Srpaulo	res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
1092281806Srpaulo			 (const BIGNUM *) c, bnctx);
1093281806Srpaulo	BN_CTX_free(bnctx);
1094281806Srpaulo
1095281806Srpaulo	return res ? 0 : -1;
1096281806Srpaulo}
1097281806Srpaulo
1098281806Srpaulo
1099281806Srpauloint crypto_bignum_cmp(const struct crypto_bignum *a,
1100281806Srpaulo		      const struct crypto_bignum *b)
1101281806Srpaulo{
1102281806Srpaulo	return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b);
1103281806Srpaulo}
1104281806Srpaulo
1105281806Srpaulo
1106281806Srpauloint crypto_bignum_bits(const struct crypto_bignum *a)
1107281806Srpaulo{
1108281806Srpaulo	return BN_num_bits((const BIGNUM *) a);
1109281806Srpaulo}
1110281806Srpaulo
1111281806Srpaulo
1112281806Srpauloint crypto_bignum_is_zero(const struct crypto_bignum *a)
1113281806Srpaulo{
1114281806Srpaulo	return BN_is_zero((const BIGNUM *) a);
1115281806Srpaulo}
1116281806Srpaulo
1117281806Srpaulo
1118281806Srpauloint crypto_bignum_is_one(const struct crypto_bignum *a)
1119281806Srpaulo{
1120281806Srpaulo	return BN_is_one((const BIGNUM *) a);
1121281806Srpaulo}
1122281806Srpaulo
1123281806Srpaulo
1124289549Srpauloint crypto_bignum_legendre(const struct crypto_bignum *a,
1125289549Srpaulo			   const struct crypto_bignum *p)
1126289549Srpaulo{
1127289549Srpaulo	BN_CTX *bnctx;
1128289549Srpaulo	BIGNUM *exp = NULL, *tmp = NULL;
1129289549Srpaulo	int res = -2;
1130289549Srpaulo
1131289549Srpaulo	bnctx = BN_CTX_new();
1132289549Srpaulo	if (bnctx == NULL)
1133289549Srpaulo		return -2;
1134289549Srpaulo
1135289549Srpaulo	exp = BN_new();
1136289549Srpaulo	tmp = BN_new();
1137289549Srpaulo	if (!exp || !tmp ||
1138289549Srpaulo	    /* exp = (p-1) / 2 */
1139289549Srpaulo	    !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
1140289549Srpaulo	    !BN_rshift1(exp, exp) ||
1141289549Srpaulo	    !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
1142289549Srpaulo			bnctx))
1143289549Srpaulo		goto fail;
1144289549Srpaulo
1145289549Srpaulo	if (BN_is_word(tmp, 1))
1146289549Srpaulo		res = 1;
1147289549Srpaulo	else if (BN_is_zero(tmp))
1148289549Srpaulo		res = 0;
1149289549Srpaulo	else
1150289549Srpaulo		res = -1;
1151289549Srpaulo
1152289549Srpaulofail:
1153289549Srpaulo	BN_clear_free(tmp);
1154289549Srpaulo	BN_clear_free(exp);
1155289549Srpaulo	BN_CTX_free(bnctx);
1156289549Srpaulo	return res;
1157289549Srpaulo}
1158289549Srpaulo
1159289549Srpaulo
1160281806Srpaulo#ifdef CONFIG_ECC
1161281806Srpaulo
1162281806Srpaulostruct crypto_ec {
1163281806Srpaulo	EC_GROUP *group;
1164281806Srpaulo	BN_CTX *bnctx;
1165281806Srpaulo	BIGNUM *prime;
1166281806Srpaulo	BIGNUM *order;
1167289549Srpaulo	BIGNUM *a;
1168289549Srpaulo	BIGNUM *b;
1169281806Srpaulo};
1170281806Srpaulo
1171281806Srpaulostruct crypto_ec * crypto_ec_init(int group)
1172281806Srpaulo{
1173281806Srpaulo	struct crypto_ec *e;
1174281806Srpaulo	int nid;
1175281806Srpaulo
1176281806Srpaulo	/* Map from IANA registry for IKE D-H groups to OpenSSL NID */
1177281806Srpaulo	switch (group) {
1178281806Srpaulo	case 19:
1179281806Srpaulo		nid = NID_X9_62_prime256v1;
1180281806Srpaulo		break;
1181281806Srpaulo	case 20:
1182281806Srpaulo		nid = NID_secp384r1;
1183281806Srpaulo		break;
1184281806Srpaulo	case 21:
1185281806Srpaulo		nid = NID_secp521r1;
1186281806Srpaulo		break;
1187281806Srpaulo	case 25:
1188281806Srpaulo		nid = NID_X9_62_prime192v1;
1189281806Srpaulo		break;
1190281806Srpaulo	case 26:
1191281806Srpaulo		nid = NID_secp224r1;
1192281806Srpaulo		break;
1193289549Srpaulo#ifdef NID_brainpoolP224r1
1194289549Srpaulo	case 27:
1195289549Srpaulo		nid = NID_brainpoolP224r1;
1196289549Srpaulo		break;
1197289549Srpaulo#endif /* NID_brainpoolP224r1 */
1198289549Srpaulo#ifdef NID_brainpoolP256r1
1199289549Srpaulo	case 28:
1200289549Srpaulo		nid = NID_brainpoolP256r1;
1201289549Srpaulo		break;
1202289549Srpaulo#endif /* NID_brainpoolP256r1 */
1203289549Srpaulo#ifdef NID_brainpoolP384r1
1204289549Srpaulo	case 29:
1205289549Srpaulo		nid = NID_brainpoolP384r1;
1206289549Srpaulo		break;
1207289549Srpaulo#endif /* NID_brainpoolP384r1 */
1208289549Srpaulo#ifdef NID_brainpoolP512r1
1209289549Srpaulo	case 30:
1210289549Srpaulo		nid = NID_brainpoolP512r1;
1211289549Srpaulo		break;
1212289549Srpaulo#endif /* NID_brainpoolP512r1 */
1213281806Srpaulo	default:
1214281806Srpaulo		return NULL;
1215281806Srpaulo	}
1216281806Srpaulo
1217281806Srpaulo	e = os_zalloc(sizeof(*e));
1218281806Srpaulo	if (e == NULL)
1219281806Srpaulo		return NULL;
1220281806Srpaulo
1221281806Srpaulo	e->bnctx = BN_CTX_new();
1222281806Srpaulo	e->group = EC_GROUP_new_by_curve_name(nid);
1223281806Srpaulo	e->prime = BN_new();
1224281806Srpaulo	e->order = BN_new();
1225289549Srpaulo	e->a = BN_new();
1226289549Srpaulo	e->b = BN_new();
1227281806Srpaulo	if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
1228289549Srpaulo	    e->order == NULL || e->a == NULL || e->b == NULL ||
1229289549Srpaulo	    !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) ||
1230281806Srpaulo	    !EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
1231281806Srpaulo		crypto_ec_deinit(e);
1232281806Srpaulo		e = NULL;
1233281806Srpaulo	}
1234281806Srpaulo
1235281806Srpaulo	return e;
1236281806Srpaulo}
1237281806Srpaulo
1238281806Srpaulo
1239281806Srpaulovoid crypto_ec_deinit(struct crypto_ec *e)
1240281806Srpaulo{
1241281806Srpaulo	if (e == NULL)
1242281806Srpaulo		return;
1243289549Srpaulo	BN_clear_free(e->b);
1244289549Srpaulo	BN_clear_free(e->a);
1245281806Srpaulo	BN_clear_free(e->order);
1246281806Srpaulo	BN_clear_free(e->prime);
1247281806Srpaulo	EC_GROUP_free(e->group);
1248281806Srpaulo	BN_CTX_free(e->bnctx);
1249281806Srpaulo	os_free(e);
1250281806Srpaulo}
1251281806Srpaulo
1252281806Srpaulo
1253281806Srpaulostruct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
1254281806Srpaulo{
1255281806Srpaulo	if (e == NULL)
1256281806Srpaulo		return NULL;
1257281806Srpaulo	return (struct crypto_ec_point *) EC_POINT_new(e->group);
1258281806Srpaulo}
1259281806Srpaulo
1260281806Srpaulo
1261281806Srpaulosize_t crypto_ec_prime_len(struct crypto_ec *e)
1262281806Srpaulo{
1263281806Srpaulo	return BN_num_bytes(e->prime);
1264281806Srpaulo}
1265281806Srpaulo
1266281806Srpaulo
1267281806Srpaulosize_t crypto_ec_prime_len_bits(struct crypto_ec *e)
1268281806Srpaulo{
1269281806Srpaulo	return BN_num_bits(e->prime);
1270281806Srpaulo}
1271281806Srpaulo
1272281806Srpaulo
1273281806Srpauloconst struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
1274281806Srpaulo{
1275281806Srpaulo	return (const struct crypto_bignum *) e->prime;
1276281806Srpaulo}
1277281806Srpaulo
1278281806Srpaulo
1279281806Srpauloconst struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e)
1280281806Srpaulo{
1281281806Srpaulo	return (const struct crypto_bignum *) e->order;
1282281806Srpaulo}
1283281806Srpaulo
1284281806Srpaulo
1285281806Srpaulovoid crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
1286281806Srpaulo{
1287281806Srpaulo	if (clear)
1288281806Srpaulo		EC_POINT_clear_free((EC_POINT *) p);
1289281806Srpaulo	else
1290281806Srpaulo		EC_POINT_free((EC_POINT *) p);
1291281806Srpaulo}
1292281806Srpaulo
1293281806Srpaulo
1294281806Srpauloint crypto_ec_point_to_bin(struct crypto_ec *e,
1295281806Srpaulo			   const struct crypto_ec_point *point, u8 *x, u8 *y)
1296281806Srpaulo{
1297281806Srpaulo	BIGNUM *x_bn, *y_bn;
1298281806Srpaulo	int ret = -1;
1299281806Srpaulo	int len = BN_num_bytes(e->prime);
1300281806Srpaulo
1301281806Srpaulo	x_bn = BN_new();
1302281806Srpaulo	y_bn = BN_new();
1303281806Srpaulo
1304281806Srpaulo	if (x_bn && y_bn &&
1305281806Srpaulo	    EC_POINT_get_affine_coordinates_GFp(e->group, (EC_POINT *) point,
1306281806Srpaulo						x_bn, y_bn, e->bnctx)) {
1307281806Srpaulo		if (x) {
1308281806Srpaulo			crypto_bignum_to_bin((struct crypto_bignum *) x_bn,
1309281806Srpaulo					     x, len, len);
1310281806Srpaulo		}
1311281806Srpaulo		if (y) {
1312281806Srpaulo			crypto_bignum_to_bin((struct crypto_bignum *) y_bn,
1313281806Srpaulo					     y, len, len);
1314281806Srpaulo		}
1315281806Srpaulo		ret = 0;
1316281806Srpaulo	}
1317281806Srpaulo
1318281806Srpaulo	BN_clear_free(x_bn);
1319281806Srpaulo	BN_clear_free(y_bn);
1320281806Srpaulo	return ret;
1321281806Srpaulo}
1322281806Srpaulo
1323281806Srpaulo
1324281806Srpaulostruct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
1325281806Srpaulo						  const u8 *val)
1326281806Srpaulo{
1327281806Srpaulo	BIGNUM *x, *y;
1328281806Srpaulo	EC_POINT *elem;
1329281806Srpaulo	int len = BN_num_bytes(e->prime);
1330281806Srpaulo
1331281806Srpaulo	x = BN_bin2bn(val, len, NULL);
1332281806Srpaulo	y = BN_bin2bn(val + len, len, NULL);
1333281806Srpaulo	elem = EC_POINT_new(e->group);
1334281806Srpaulo	if (x == NULL || y == NULL || elem == NULL) {
1335281806Srpaulo		BN_clear_free(x);
1336281806Srpaulo		BN_clear_free(y);
1337281806Srpaulo		EC_POINT_clear_free(elem);
1338281806Srpaulo		return NULL;
1339281806Srpaulo	}
1340281806Srpaulo
1341281806Srpaulo	if (!EC_POINT_set_affine_coordinates_GFp(e->group, elem, x, y,
1342281806Srpaulo						 e->bnctx)) {
1343281806Srpaulo		EC_POINT_clear_free(elem);
1344281806Srpaulo		elem = NULL;
1345281806Srpaulo	}
1346281806Srpaulo
1347281806Srpaulo	BN_clear_free(x);
1348281806Srpaulo	BN_clear_free(y);
1349281806Srpaulo
1350281806Srpaulo	return (struct crypto_ec_point *) elem;
1351281806Srpaulo}
1352281806Srpaulo
1353281806Srpaulo
1354281806Srpauloint crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
1355281806Srpaulo			const struct crypto_ec_point *b,
1356281806Srpaulo			struct crypto_ec_point *c)
1357281806Srpaulo{
1358281806Srpaulo	return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
1359281806Srpaulo			    (const EC_POINT *) b, e->bnctx) ? 0 : -1;
1360281806Srpaulo}
1361281806Srpaulo
1362281806Srpaulo
1363281806Srpauloint crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
1364281806Srpaulo			const struct crypto_bignum *b,
1365281806Srpaulo			struct crypto_ec_point *res)
1366281806Srpaulo{
1367281806Srpaulo	return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
1368281806Srpaulo			    (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
1369281806Srpaulo		? 0 : -1;
1370281806Srpaulo}
1371281806Srpaulo
1372281806Srpaulo
1373281806Srpauloint crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
1374281806Srpaulo{
1375281806Srpaulo	return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
1376281806Srpaulo}
1377281806Srpaulo
1378281806Srpaulo
1379281806Srpauloint crypto_ec_point_solve_y_coord(struct crypto_ec *e,
1380281806Srpaulo				  struct crypto_ec_point *p,
1381281806Srpaulo				  const struct crypto_bignum *x, int y_bit)
1382281806Srpaulo{
1383281806Srpaulo	if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
1384281806Srpaulo						     (const BIGNUM *) x, y_bit,
1385281806Srpaulo						     e->bnctx) ||
1386281806Srpaulo	    !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx))
1387281806Srpaulo		return -1;
1388281806Srpaulo	return 0;
1389281806Srpaulo}
1390281806Srpaulo
1391281806Srpaulo
1392289549Srpaulostruct crypto_bignum *
1393289549Srpaulocrypto_ec_point_compute_y_sqr(struct crypto_ec *e,
1394289549Srpaulo			      const struct crypto_bignum *x)
1395289549Srpaulo{
1396289549Srpaulo	BIGNUM *tmp, *tmp2, *y_sqr = NULL;
1397289549Srpaulo
1398289549Srpaulo	tmp = BN_new();
1399289549Srpaulo	tmp2 = BN_new();
1400289549Srpaulo
1401289549Srpaulo	/* y^2 = x^3 + ax + b */
1402289549Srpaulo	if (tmp && tmp2 &&
1403289549Srpaulo	    BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
1404289549Srpaulo	    BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
1405289549Srpaulo	    BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
1406289549Srpaulo	    BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
1407289549Srpaulo	    BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
1408289549Srpaulo		y_sqr = tmp2;
1409289549Srpaulo		tmp2 = NULL;
1410289549Srpaulo	}
1411289549Srpaulo
1412289549Srpaulo	BN_clear_free(tmp);
1413289549Srpaulo	BN_clear_free(tmp2);
1414289549Srpaulo
1415289549Srpaulo	return (struct crypto_bignum *) y_sqr;
1416289549Srpaulo}
1417289549Srpaulo
1418289549Srpaulo
1419281806Srpauloint crypto_ec_point_is_at_infinity(struct crypto_ec *e,
1420281806Srpaulo				   const struct crypto_ec_point *p)
1421281806Srpaulo{
1422281806Srpaulo	return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p);
1423281806Srpaulo}
1424281806Srpaulo
1425281806Srpaulo
1426281806Srpauloint crypto_ec_point_is_on_curve(struct crypto_ec *e,
1427281806Srpaulo				const struct crypto_ec_point *p)
1428281806Srpaulo{
1429289549Srpaulo	return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p,
1430289549Srpaulo				    e->bnctx) == 1;
1431281806Srpaulo}
1432281806Srpaulo
1433289549Srpaulo
1434289549Srpauloint crypto_ec_point_cmp(const struct crypto_ec *e,
1435289549Srpaulo			const struct crypto_ec_point *a,
1436289549Srpaulo			const struct crypto_ec_point *b)
1437289549Srpaulo{
1438289549Srpaulo	return EC_POINT_cmp(e->group, (const EC_POINT *) a,
1439289549Srpaulo			    (const EC_POINT *) b, e->bnctx);
1440289549Srpaulo}
1441289549Srpaulo
1442281806Srpaulo#endif /* CONFIG_ECC */
1443