18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / wrapper functions for libcrypto
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/opensslv.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/err.h>
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/des.h>
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/aes.h>
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/bn.h>
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/evp.h>
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <openssl/dh.h>
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpabuf.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dh_group5.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x00907000
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define DES_key_schedule des_key_schedule
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define DES_cblock des_cblock
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define DES_set_key(key, schedule) des_set_key((key), *(schedule))
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define DES_ecb_encrypt(input, output, ks, enc) \
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_ecb_encrypt((input), (output), *(ks), (enc))
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* openssl < 0.9.7 */
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic BIGNUM * get_group5_prime(void)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x00908000
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const unsigned char RFC3526_PRIME_1536[] = {
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* openssl < 0.9.8 */
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return get_rfc3526_prime_1536(NULL);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* openssl < 0.9.8 */
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x00908000
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_SHA256
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_FIPS
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NO_SHA256_WRAPPER
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* openssl < 0.9.8 */
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_SHA256
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NO_SHA256_WRAPPER
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int openssl_digest_vector(const EVP_MD *type, int non_fips,
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t num_elem, const u8 *addr[],
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const size_t *len, u8 *mac)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_MD_CTX ctx;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int mac_len;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_MD_CTX_init(&ctx);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_FIPS
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (non_fips)
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_FIPS */
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++) {
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %s",
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ERR_error_string(ERR_get_error(), NULL));
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   ERR_error_string(ERR_get_error(), NULL));
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pkey[8], next, tmp;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DES_key_schedule ks;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Add parity bits to the key */
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	next = 0;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 7; i++) {
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = key[i];
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pkey[i] = (tmp >> i) | next | 1;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = tmp << (7 - i);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pkey[i] = next | 1;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DES_set_key(&pkey, &ks);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			DES_ENCRYPT);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rc4_skip(const u8 *key, size_t keylen, size_t skip,
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     u8 *data, size_t data_len)
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef OPENSSL_NO_RC4
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* OPENSSL_NO_RC4 */
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX ctx;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int outl;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = -1;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char skip_buf[16];
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_init(&ctx);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (skip >= sizeof(skip_buf)) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len = skip;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > sizeof(skip_buf))
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(skip_buf);
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		skip -= len;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = 0;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_cleanup(&ctx);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_RC4 */
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const size_t *len, u8 *mac)
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef NO_SHA256_WRAPPER
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  u8 *mac)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len,
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     mac);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NO_SHA256_WRAPPER */
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_encrypt_init(const u8 *key, size_t len)
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	AES_KEY *ak;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ak = os_malloc(sizeof(*ak));
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ak == NULL)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (AES_set_encrypt_key(key, 8 * len, ak) < 0) {
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ak);
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ak;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	AES_encrypt(plain, crypt, ctx);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt_deinit(void *ctx)
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_decrypt_init(const u8 *key, size_t len)
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	AES_KEY *ak;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ak = os_malloc(sizeof(*ak));
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ak == NULL)
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (AES_set_decrypt_key(key, 8 * len, ak) < 0) {
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ak);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ak;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	AES_decrypt(crypt, plain, ctx);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt_deinit(void *ctx)
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *power, size_t power_len,
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *modulus, size_t modulus_len,
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   u8 *result, size_t *result_len)
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_CTX *ctx;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = BN_CTX_new();
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bn_base = BN_bin2bn(base, base_len, NULL);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bn_exp = BN_bin2bn(power, power_len, NULL);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bn_result = BN_new();
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    bn_result == NULL)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto error;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto error;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*result_len = BN_bn2bin(bn_result, result);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror:
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(bn_base);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(bn_exp);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(bn_modulus);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(bn_result);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_CTX_free(ctx);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher {
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX enc;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX dec;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *iv, const u8 *key,
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t key_len)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_cipher *ctx;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const EVP_CIPHER *cipher;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_RC4
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cipher = EVP_rc4();
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_RC4 */
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_AES
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (key_len) {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 16:
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cipher = EVP_aes_128_cbc();
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 24:
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cipher = EVP_aes_192_cbc();
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 32:
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cipher = EVP_aes_256_cbc();
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_AES */
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_DES
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cipher = EVP_des_ede3_cbc();
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_DES:
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cipher = EVP_des_cbc();
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_DES */
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OPENSSL_NO_RC2
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC2:
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cipher = EVP_rc2_ecb();
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OPENSSL_NO_RC2 */
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_init(&ctx->enc);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->enc);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_init(&ctx->dec);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->enc);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->dec);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *crypt, size_t len)
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int outl;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *plain, size_t len)
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int outl;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outl = len;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_cleanup(&ctx->enc);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EVP_CIPHER_CTX_cleanup(&ctx->dec);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *pubkey = NULL, *privkey = NULL;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t publen, privlen;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*priv = NULL;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*publ = NULL;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = DH_new();
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh == NULL)
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh->g = BN_new();
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh->p = get_group5_prime();
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh->p == NULL)
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (DH_generate_key(dh) != 1)
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	publen = BN_num_bytes(dh->pub_key);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pubkey = wpabuf_alloc(publen);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pubkey == NULL)
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	privlen = BN_num_bytes(dh->priv_key);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	privkey = wpabuf_alloc(privlen);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (privkey == NULL)
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen));
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen));
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*priv = privkey;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*publ = pubkey;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dh;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(pubkey);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(privkey);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const struct wpabuf *own_private)
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BIGNUM *pub_key;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *res = NULL;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh = ctx;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int keylen;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    NULL);
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pub_key == NULL)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rlen = DH_size(dh);
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpabuf_alloc(rlen);
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == NULL)
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keylen < 0)
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto err;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put(res, keylen);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(pub_key);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr:
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BN_free(pub_key);
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(res);
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid dh5_free(void *ctx)
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH *dh;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh = ctx;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DH_free(dh);
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
500