1189251Ssam/* 2189251Ssam * WPA Supplicant / wrapper functions for libcrypto 3214734Srpaulo * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam#include <openssl/opensslv.h> 17214734Srpaulo#include <openssl/err.h> 18189251Ssam#include <openssl/des.h> 19189251Ssam#include <openssl/aes.h> 20189251Ssam#include <openssl/bn.h> 21189251Ssam#include <openssl/evp.h> 22214734Srpaulo#include <openssl/dh.h> 23189251Ssam 24189251Ssam#include "common.h" 25214734Srpaulo#include "wpabuf.h" 26214734Srpaulo#include "dh_group5.h" 27189251Ssam#include "crypto.h" 28189251Ssam 29189251Ssam#if OPENSSL_VERSION_NUMBER < 0x00907000 30189251Ssam#define DES_key_schedule des_key_schedule 31189251Ssam#define DES_cblock des_cblock 32189251Ssam#define DES_set_key(key, schedule) des_set_key((key), *(schedule)) 33189251Ssam#define DES_ecb_encrypt(input, output, ks, enc) \ 34189251Ssam des_ecb_encrypt((input), (output), *(ks), (enc)) 35189251Ssam#endif /* openssl < 0.9.7 */ 36189251Ssam 37214734Srpaulostatic BIGNUM * get_group5_prime(void) 38214734Srpaulo{ 39214734Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00908000 40214734Srpaulo static const unsigned char RFC3526_PRIME_1536[] = { 41214734Srpaulo 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 42214734Srpaulo 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, 43214734Srpaulo 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, 44214734Srpaulo 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, 45214734Srpaulo 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, 46214734Srpaulo 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, 47214734Srpaulo 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, 48214734Srpaulo 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, 49214734Srpaulo 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, 50214734Srpaulo 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, 51214734Srpaulo 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, 52214734Srpaulo 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, 53214734Srpaulo 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, 54214734Srpaulo 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, 55214734Srpaulo 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, 56214734Srpaulo 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 57214734Srpaulo }; 58214734Srpaulo return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); 59214734Srpaulo#else /* openssl < 0.9.8 */ 60214734Srpaulo return get_rfc3526_prime_1536(NULL); 61214734Srpaulo#endif /* openssl < 0.9.8 */ 62214734Srpaulo} 63189251Ssam 64214734Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00908000 65214734Srpaulo#ifndef OPENSSL_NO_SHA256 66214734Srpaulo#ifndef OPENSSL_FIPS 67214734Srpaulo#define NO_SHA256_WRAPPER 68214734Srpaulo#endif 69214734Srpaulo#endif 70214734Srpaulo 71214734Srpaulo#endif /* openssl < 0.9.8 */ 72214734Srpaulo 73214734Srpaulo#ifdef OPENSSL_NO_SHA256 74214734Srpaulo#define NO_SHA256_WRAPPER 75214734Srpaulo#endif 76214734Srpaulo 77214734Srpaulostatic int openssl_digest_vector(const EVP_MD *type, int non_fips, 78214734Srpaulo size_t num_elem, const u8 *addr[], 79214734Srpaulo const size_t *len, u8 *mac) 80189251Ssam{ 81214734Srpaulo EVP_MD_CTX ctx; 82189251Ssam size_t i; 83214734Srpaulo unsigned int mac_len; 84189251Ssam 85214734Srpaulo EVP_MD_CTX_init(&ctx); 86214734Srpaulo#ifdef CONFIG_FIPS 87214734Srpaulo#ifdef OPENSSL_FIPS 88214734Srpaulo if (non_fips) 89214734Srpaulo EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 90214734Srpaulo#endif /* OPENSSL_FIPS */ 91214734Srpaulo#endif /* CONFIG_FIPS */ 92214734Srpaulo if (!EVP_DigestInit_ex(&ctx, type, NULL)) { 93214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", 94214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 95214734Srpaulo return -1; 96214734Srpaulo } 97214734Srpaulo for (i = 0; i < num_elem; i++) { 98214734Srpaulo if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { 99214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " 100214734Srpaulo "failed: %s", 101214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 102214734Srpaulo return -1; 103214734Srpaulo } 104214734Srpaulo } 105214734Srpaulo if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { 106214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", 107214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 108214734Srpaulo return -1; 109214734Srpaulo } 110214734Srpaulo 111214734Srpaulo return 0; 112189251Ssam} 113189251Ssam 114189251Ssam 115214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 116214734Srpaulo{ 117214734Srpaulo return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac); 118214734Srpaulo} 119214734Srpaulo 120214734Srpaulo 121189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 122189251Ssam{ 123189251Ssam u8 pkey[8], next, tmp; 124189251Ssam int i; 125189251Ssam DES_key_schedule ks; 126189251Ssam 127189251Ssam /* Add parity bits to the key */ 128189251Ssam next = 0; 129189251Ssam for (i = 0; i < 7; i++) { 130189251Ssam tmp = key[i]; 131189251Ssam pkey[i] = (tmp >> i) | next | 1; 132189251Ssam next = tmp << (7 - i); 133189251Ssam } 134189251Ssam pkey[i] = next | 1; 135189251Ssam 136189251Ssam DES_set_key(&pkey, &ks); 137189251Ssam DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, 138189251Ssam DES_ENCRYPT); 139189251Ssam} 140189251Ssam 141189251Ssam 142214734Srpauloint rc4_skip(const u8 *key, size_t keylen, size_t skip, 143214734Srpaulo u8 *data, size_t data_len) 144189251Ssam{ 145214734Srpaulo#ifdef OPENSSL_NO_RC4 146214734Srpaulo return -1; 147214734Srpaulo#else /* OPENSSL_NO_RC4 */ 148214734Srpaulo EVP_CIPHER_CTX ctx; 149214734Srpaulo int outl; 150214734Srpaulo int res = -1; 151214734Srpaulo unsigned char skip_buf[16]; 152189251Ssam 153214734Srpaulo EVP_CIPHER_CTX_init(&ctx); 154214734Srpaulo if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || 155214734Srpaulo !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || 156214734Srpaulo !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || 157214734Srpaulo !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) 158214734Srpaulo goto out; 159189251Ssam 160214734Srpaulo while (skip >= sizeof(skip_buf)) { 161214734Srpaulo size_t len = skip; 162214734Srpaulo if (len > sizeof(skip_buf)) 163214734Srpaulo len = sizeof(skip_buf); 164214734Srpaulo if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) 165214734Srpaulo goto out; 166214734Srpaulo skip -= len; 167214734Srpaulo } 168189251Ssam 169214734Srpaulo if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) 170214734Srpaulo res = 0; 171189251Ssam 172214734Srpauloout: 173214734Srpaulo EVP_CIPHER_CTX_cleanup(&ctx); 174214734Srpaulo return res; 175214734Srpaulo#endif /* OPENSSL_NO_RC4 */ 176189251Ssam} 177189251Ssam 178189251Ssam 179214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 180189251Ssam{ 181214734Srpaulo return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac); 182189251Ssam} 183189251Ssam 184189251Ssam 185214734Srpaulo#ifdef CONFIG_FIPS 186214734Srpauloint md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], 187214734Srpaulo const size_t *len, u8 *mac) 188189251Ssam{ 189214734Srpaulo return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac); 190214734Srpaulo} 191214734Srpaulo#endif /* CONFIG_FIPS */ 192189251Ssam 193189251Ssam 194214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 195214734Srpaulo{ 196214734Srpaulo return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac); 197214734Srpaulo} 198189251Ssam 199189251Ssam 200214734Srpaulo#ifndef NO_SHA256_WRAPPER 201214734Srpauloint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, 202214734Srpaulo u8 *mac) 203214734Srpaulo{ 204214734Srpaulo return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len, 205214734Srpaulo mac); 206189251Ssam} 207214734Srpaulo#endif /* NO_SHA256_WRAPPER */ 208189251Ssam 209189251Ssam 210189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 211189251Ssam{ 212189251Ssam AES_KEY *ak; 213189251Ssam ak = os_malloc(sizeof(*ak)); 214189251Ssam if (ak == NULL) 215189251Ssam return NULL; 216189251Ssam if (AES_set_encrypt_key(key, 8 * len, ak) < 0) { 217189251Ssam os_free(ak); 218189251Ssam return NULL; 219189251Ssam } 220189251Ssam return ak; 221189251Ssam} 222189251Ssam 223189251Ssam 224189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 225189251Ssam{ 226189251Ssam AES_encrypt(plain, crypt, ctx); 227189251Ssam} 228189251Ssam 229189251Ssam 230189251Ssamvoid aes_encrypt_deinit(void *ctx) 231189251Ssam{ 232189251Ssam os_free(ctx); 233189251Ssam} 234189251Ssam 235189251Ssam 236189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 237189251Ssam{ 238189251Ssam AES_KEY *ak; 239189251Ssam ak = os_malloc(sizeof(*ak)); 240189251Ssam if (ak == NULL) 241189251Ssam return NULL; 242189251Ssam if (AES_set_decrypt_key(key, 8 * len, ak) < 0) { 243189251Ssam os_free(ak); 244189251Ssam return NULL; 245189251Ssam } 246189251Ssam return ak; 247189251Ssam} 248189251Ssam 249189251Ssam 250189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 251189251Ssam{ 252189251Ssam AES_decrypt(crypt, plain, ctx); 253189251Ssam} 254189251Ssam 255189251Ssam 256189251Ssamvoid aes_decrypt_deinit(void *ctx) 257189251Ssam{ 258189251Ssam os_free(ctx); 259189251Ssam} 260189251Ssam 261189251Ssam 262189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len, 263189251Ssam const u8 *power, size_t power_len, 264189251Ssam const u8 *modulus, size_t modulus_len, 265189251Ssam u8 *result, size_t *result_len) 266189251Ssam{ 267189251Ssam BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; 268189251Ssam int ret = -1; 269189251Ssam BN_CTX *ctx; 270189251Ssam 271189251Ssam ctx = BN_CTX_new(); 272189251Ssam if (ctx == NULL) 273189251Ssam return -1; 274189251Ssam 275189251Ssam bn_base = BN_bin2bn(base, base_len, NULL); 276189251Ssam bn_exp = BN_bin2bn(power, power_len, NULL); 277189251Ssam bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); 278189251Ssam bn_result = BN_new(); 279189251Ssam 280189251Ssam if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || 281189251Ssam bn_result == NULL) 282189251Ssam goto error; 283189251Ssam 284189251Ssam if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) 285189251Ssam goto error; 286189251Ssam 287189251Ssam *result_len = BN_bn2bin(bn_result, result); 288189251Ssam ret = 0; 289189251Ssam 290189251Ssamerror: 291189251Ssam BN_free(bn_base); 292189251Ssam BN_free(bn_exp); 293189251Ssam BN_free(bn_modulus); 294189251Ssam BN_free(bn_result); 295189251Ssam BN_CTX_free(ctx); 296189251Ssam return ret; 297189251Ssam} 298189251Ssam 299189251Ssam 300189251Ssamstruct crypto_cipher { 301189251Ssam EVP_CIPHER_CTX enc; 302189251Ssam EVP_CIPHER_CTX dec; 303189251Ssam}; 304189251Ssam 305189251Ssam 306189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 307189251Ssam const u8 *iv, const u8 *key, 308189251Ssam size_t key_len) 309189251Ssam{ 310189251Ssam struct crypto_cipher *ctx; 311189251Ssam const EVP_CIPHER *cipher; 312189251Ssam 313189251Ssam ctx = os_zalloc(sizeof(*ctx)); 314189251Ssam if (ctx == NULL) 315189251Ssam return NULL; 316189251Ssam 317189251Ssam switch (alg) { 318189251Ssam#ifndef OPENSSL_NO_RC4 319189251Ssam case CRYPTO_CIPHER_ALG_RC4: 320189251Ssam cipher = EVP_rc4(); 321189251Ssam break; 322189251Ssam#endif /* OPENSSL_NO_RC4 */ 323189251Ssam#ifndef OPENSSL_NO_AES 324189251Ssam case CRYPTO_CIPHER_ALG_AES: 325189251Ssam switch (key_len) { 326189251Ssam case 16: 327189251Ssam cipher = EVP_aes_128_cbc(); 328189251Ssam break; 329189251Ssam case 24: 330189251Ssam cipher = EVP_aes_192_cbc(); 331189251Ssam break; 332189251Ssam case 32: 333189251Ssam cipher = EVP_aes_256_cbc(); 334189251Ssam break; 335189251Ssam default: 336189251Ssam os_free(ctx); 337189251Ssam return NULL; 338189251Ssam } 339189251Ssam break; 340189251Ssam#endif /* OPENSSL_NO_AES */ 341189251Ssam#ifndef OPENSSL_NO_DES 342189251Ssam case CRYPTO_CIPHER_ALG_3DES: 343189251Ssam cipher = EVP_des_ede3_cbc(); 344189251Ssam break; 345189251Ssam case CRYPTO_CIPHER_ALG_DES: 346189251Ssam cipher = EVP_des_cbc(); 347189251Ssam break; 348189251Ssam#endif /* OPENSSL_NO_DES */ 349189251Ssam#ifndef OPENSSL_NO_RC2 350189251Ssam case CRYPTO_CIPHER_ALG_RC2: 351189251Ssam cipher = EVP_rc2_ecb(); 352189251Ssam break; 353189251Ssam#endif /* OPENSSL_NO_RC2 */ 354189251Ssam default: 355189251Ssam os_free(ctx); 356189251Ssam return NULL; 357189251Ssam } 358189251Ssam 359189251Ssam EVP_CIPHER_CTX_init(&ctx->enc); 360189251Ssam EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); 361189251Ssam if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || 362189251Ssam !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || 363214734Srpaulo !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { 364189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 365189251Ssam os_free(ctx); 366189251Ssam return NULL; 367189251Ssam } 368189251Ssam 369189251Ssam EVP_CIPHER_CTX_init(&ctx->dec); 370189251Ssam EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); 371189251Ssam if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || 372189251Ssam !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || 373214734Srpaulo !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { 374189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 375189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->dec); 376189251Ssam os_free(ctx); 377189251Ssam return NULL; 378189251Ssam } 379189251Ssam 380189251Ssam return ctx; 381189251Ssam} 382189251Ssam 383189251Ssam 384189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 385189251Ssam u8 *crypt, size_t len) 386189251Ssam{ 387189251Ssam int outl; 388189251Ssam if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) 389189251Ssam return -1; 390189251Ssam return 0; 391189251Ssam} 392189251Ssam 393189251Ssam 394189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 395189251Ssam u8 *plain, size_t len) 396189251Ssam{ 397189251Ssam int outl; 398189251Ssam outl = len; 399189251Ssam if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) 400189251Ssam return -1; 401189251Ssam return 0; 402189251Ssam} 403189251Ssam 404189251Ssam 405189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 406189251Ssam{ 407189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 408189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->dec); 409189251Ssam os_free(ctx); 410189251Ssam} 411214734Srpaulo 412214734Srpaulo 413214734Srpaulovoid * dh5_init(struct wpabuf **priv, struct wpabuf **publ) 414214734Srpaulo{ 415214734Srpaulo DH *dh; 416214734Srpaulo struct wpabuf *pubkey = NULL, *privkey = NULL; 417214734Srpaulo size_t publen, privlen; 418214734Srpaulo 419214734Srpaulo *priv = NULL; 420214734Srpaulo *publ = NULL; 421214734Srpaulo 422214734Srpaulo dh = DH_new(); 423214734Srpaulo if (dh == NULL) 424214734Srpaulo return NULL; 425214734Srpaulo 426214734Srpaulo dh->g = BN_new(); 427214734Srpaulo if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) 428214734Srpaulo goto err; 429214734Srpaulo 430214734Srpaulo dh->p = get_group5_prime(); 431214734Srpaulo if (dh->p == NULL) 432214734Srpaulo goto err; 433214734Srpaulo 434214734Srpaulo if (DH_generate_key(dh) != 1) 435214734Srpaulo goto err; 436214734Srpaulo 437214734Srpaulo publen = BN_num_bytes(dh->pub_key); 438214734Srpaulo pubkey = wpabuf_alloc(publen); 439214734Srpaulo if (pubkey == NULL) 440214734Srpaulo goto err; 441214734Srpaulo privlen = BN_num_bytes(dh->priv_key); 442214734Srpaulo privkey = wpabuf_alloc(privlen); 443214734Srpaulo if (privkey == NULL) 444214734Srpaulo goto err; 445214734Srpaulo 446214734Srpaulo BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); 447214734Srpaulo BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); 448214734Srpaulo 449214734Srpaulo *priv = privkey; 450214734Srpaulo *publ = pubkey; 451214734Srpaulo return dh; 452214734Srpaulo 453214734Srpauloerr: 454214734Srpaulo wpabuf_free(pubkey); 455214734Srpaulo wpabuf_free(privkey); 456214734Srpaulo DH_free(dh); 457214734Srpaulo return NULL; 458214734Srpaulo} 459214734Srpaulo 460214734Srpaulo 461214734Srpaulostruct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, 462214734Srpaulo const struct wpabuf *own_private) 463214734Srpaulo{ 464214734Srpaulo BIGNUM *pub_key; 465214734Srpaulo struct wpabuf *res = NULL; 466214734Srpaulo size_t rlen; 467214734Srpaulo DH *dh = ctx; 468214734Srpaulo int keylen; 469214734Srpaulo 470214734Srpaulo if (ctx == NULL) 471214734Srpaulo return NULL; 472214734Srpaulo 473214734Srpaulo pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), 474214734Srpaulo NULL); 475214734Srpaulo if (pub_key == NULL) 476214734Srpaulo return NULL; 477214734Srpaulo 478214734Srpaulo rlen = DH_size(dh); 479214734Srpaulo res = wpabuf_alloc(rlen); 480214734Srpaulo if (res == NULL) 481214734Srpaulo goto err; 482214734Srpaulo 483214734Srpaulo keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); 484214734Srpaulo if (keylen < 0) 485214734Srpaulo goto err; 486214734Srpaulo wpabuf_put(res, keylen); 487214734Srpaulo BN_free(pub_key); 488214734Srpaulo 489214734Srpaulo return res; 490214734Srpaulo 491214734Srpauloerr: 492214734Srpaulo BN_free(pub_key); 493214734Srpaulo wpabuf_free(res); 494214734Srpaulo return NULL; 495214734Srpaulo} 496214734Srpaulo 497214734Srpaulo 498214734Srpaulovoid dh5_free(void *ctx) 499214734Srpaulo{ 500214734Srpaulo DH *dh; 501214734Srpaulo if (ctx == NULL) 502214734Srpaulo return; 503214734Srpaulo dh = ctx; 504214734Srpaulo DH_free(dh); 505214734Srpaulo} 506