1189251Ssam/* 2189251Ssam * WPA Supplicant / wrapper functions for libcrypto 3252726Srpaulo * Copyright (c) 2004-2012, 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 */ 22189251Ssam 23189251Ssam#include "common.h" 24214734Srpaulo#include "wpabuf.h" 25214734Srpaulo#include "dh_group5.h" 26189251Ssam#include "crypto.h" 27189251Ssam 28189251Ssam#if OPENSSL_VERSION_NUMBER < 0x00907000 29189251Ssam#define DES_key_schedule des_key_schedule 30189251Ssam#define DES_cblock des_cblock 31189251Ssam#define DES_set_key(key, schedule) des_set_key((key), *(schedule)) 32189251Ssam#define DES_ecb_encrypt(input, output, ks, enc) \ 33189251Ssam des_ecb_encrypt((input), (output), *(ks), (enc)) 34189251Ssam#endif /* openssl < 0.9.7 */ 35189251Ssam 36214734Srpaulostatic BIGNUM * get_group5_prime(void) 37214734Srpaulo{ 38214734Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00908000 39214734Srpaulo static const unsigned char RFC3526_PRIME_1536[] = { 40214734Srpaulo 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 41214734Srpaulo 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, 42214734Srpaulo 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, 43214734Srpaulo 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, 44214734Srpaulo 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, 45214734Srpaulo 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, 46214734Srpaulo 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, 47214734Srpaulo 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, 48214734Srpaulo 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, 49214734Srpaulo 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, 50214734Srpaulo 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, 51214734Srpaulo 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, 52214734Srpaulo 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, 53214734Srpaulo 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, 54214734Srpaulo 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, 55214734Srpaulo 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 56214734Srpaulo }; 57214734Srpaulo return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); 58214734Srpaulo#else /* openssl < 0.9.8 */ 59214734Srpaulo return get_rfc3526_prime_1536(NULL); 60214734Srpaulo#endif /* openssl < 0.9.8 */ 61214734Srpaulo} 62189251Ssam 63214734Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00908000 64214734Srpaulo#ifndef OPENSSL_NO_SHA256 65214734Srpaulo#ifndef OPENSSL_FIPS 66214734Srpaulo#define NO_SHA256_WRAPPER 67214734Srpaulo#endif 68214734Srpaulo#endif 69214734Srpaulo 70214734Srpaulo#endif /* openssl < 0.9.8 */ 71214734Srpaulo 72214734Srpaulo#ifdef OPENSSL_NO_SHA256 73214734Srpaulo#define NO_SHA256_WRAPPER 74214734Srpaulo#endif 75214734Srpaulo 76252726Srpaulostatic int openssl_digest_vector(const EVP_MD *type, size_t num_elem, 77252726Srpaulo const u8 *addr[], const size_t *len, u8 *mac) 78189251Ssam{ 79214734Srpaulo EVP_MD_CTX ctx; 80189251Ssam size_t i; 81214734Srpaulo unsigned int mac_len; 82189251Ssam 83214734Srpaulo EVP_MD_CTX_init(&ctx); 84214734Srpaulo if (!EVP_DigestInit_ex(&ctx, type, NULL)) { 85214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", 86214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 87214734Srpaulo return -1; 88214734Srpaulo } 89214734Srpaulo for (i = 0; i < num_elem; i++) { 90214734Srpaulo if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { 91214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " 92214734Srpaulo "failed: %s", 93214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 94214734Srpaulo return -1; 95214734Srpaulo } 96214734Srpaulo } 97214734Srpaulo if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { 98214734Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", 99214734Srpaulo ERR_error_string(ERR_get_error(), NULL)); 100214734Srpaulo return -1; 101214734Srpaulo } 102214734Srpaulo 103214734Srpaulo return 0; 104189251Ssam} 105189251Ssam 106189251Ssam 107214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 108214734Srpaulo{ 109252726Srpaulo return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac); 110214734Srpaulo} 111214734Srpaulo 112214734Srpaulo 113189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 114189251Ssam{ 115189251Ssam u8 pkey[8], next, tmp; 116189251Ssam int i; 117189251Ssam DES_key_schedule ks; 118189251Ssam 119189251Ssam /* Add parity bits to the key */ 120189251Ssam next = 0; 121189251Ssam for (i = 0; i < 7; i++) { 122189251Ssam tmp = key[i]; 123189251Ssam pkey[i] = (tmp >> i) | next | 1; 124189251Ssam next = tmp << (7 - i); 125189251Ssam } 126189251Ssam pkey[i] = next | 1; 127189251Ssam 128189251Ssam DES_set_key(&pkey, &ks); 129189251Ssam DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, 130189251Ssam DES_ENCRYPT); 131189251Ssam} 132189251Ssam 133189251Ssam 134214734Srpauloint rc4_skip(const u8 *key, size_t keylen, size_t skip, 135214734Srpaulo u8 *data, size_t data_len) 136189251Ssam{ 137214734Srpaulo#ifdef OPENSSL_NO_RC4 138214734Srpaulo return -1; 139214734Srpaulo#else /* OPENSSL_NO_RC4 */ 140214734Srpaulo EVP_CIPHER_CTX ctx; 141214734Srpaulo int outl; 142214734Srpaulo int res = -1; 143214734Srpaulo unsigned char skip_buf[16]; 144189251Ssam 145214734Srpaulo EVP_CIPHER_CTX_init(&ctx); 146214734Srpaulo if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || 147214734Srpaulo !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || 148214734Srpaulo !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || 149214734Srpaulo !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) 150214734Srpaulo goto out; 151189251Ssam 152214734Srpaulo while (skip >= sizeof(skip_buf)) { 153214734Srpaulo size_t len = skip; 154214734Srpaulo if (len > sizeof(skip_buf)) 155214734Srpaulo len = sizeof(skip_buf); 156214734Srpaulo if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) 157214734Srpaulo goto out; 158214734Srpaulo skip -= len; 159214734Srpaulo } 160189251Ssam 161214734Srpaulo if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) 162214734Srpaulo res = 0; 163189251Ssam 164214734Srpauloout: 165214734Srpaulo EVP_CIPHER_CTX_cleanup(&ctx); 166214734Srpaulo return res; 167214734Srpaulo#endif /* OPENSSL_NO_RC4 */ 168189251Ssam} 169189251Ssam 170189251Ssam 171214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 172189251Ssam{ 173252726Srpaulo return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac); 174189251Ssam} 175189251Ssam 176189251Ssam 177214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 178214734Srpaulo{ 179252726Srpaulo return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac); 180214734Srpaulo} 181189251Ssam 182189251Ssam 183214734Srpaulo#ifndef NO_SHA256_WRAPPER 184214734Srpauloint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, 185214734Srpaulo u8 *mac) 186214734Srpaulo{ 187252726Srpaulo return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac); 188189251Ssam} 189214734Srpaulo#endif /* NO_SHA256_WRAPPER */ 190189251Ssam 191189251Ssam 192252726Srpaulostatic const EVP_CIPHER * aes_get_evp_cipher(size_t keylen) 193252726Srpaulo{ 194252726Srpaulo switch (keylen) { 195252726Srpaulo case 16: 196252726Srpaulo return EVP_aes_128_ecb(); 197252726Srpaulo case 24: 198252726Srpaulo return EVP_aes_192_ecb(); 199252726Srpaulo case 32: 200252726Srpaulo return EVP_aes_256_ecb(); 201252726Srpaulo } 202252726Srpaulo 203252726Srpaulo return NULL; 204252726Srpaulo} 205252726Srpaulo 206252726Srpaulo 207189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 208189251Ssam{ 209252726Srpaulo EVP_CIPHER_CTX *ctx; 210252726Srpaulo const EVP_CIPHER *type; 211252726Srpaulo 212252726Srpaulo type = aes_get_evp_cipher(len); 213252726Srpaulo if (type == NULL) 214189251Ssam return NULL; 215252726Srpaulo 216252726Srpaulo ctx = os_malloc(sizeof(*ctx)); 217252726Srpaulo if (ctx == NULL) 218189251Ssam return NULL; 219252726Srpaulo EVP_CIPHER_CTX_init(ctx); 220252726Srpaulo if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) { 221252726Srpaulo os_free(ctx); 222252726Srpaulo return NULL; 223189251Ssam } 224252726Srpaulo EVP_CIPHER_CTX_set_padding(ctx, 0); 225252726Srpaulo return ctx; 226189251Ssam} 227189251Ssam 228189251Ssam 229189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 230189251Ssam{ 231252726Srpaulo EVP_CIPHER_CTX *c = ctx; 232252726Srpaulo int clen = 16; 233252726Srpaulo if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) { 234252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s", 235252726Srpaulo ERR_error_string(ERR_get_error(), NULL)); 236252726Srpaulo } 237189251Ssam} 238189251Ssam 239189251Ssam 240189251Ssamvoid aes_encrypt_deinit(void *ctx) 241189251Ssam{ 242252726Srpaulo EVP_CIPHER_CTX *c = ctx; 243252726Srpaulo u8 buf[16]; 244252726Srpaulo int len = sizeof(buf); 245252726Srpaulo if (EVP_EncryptFinal_ex(c, buf, &len) != 1) { 246252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: " 247252726Srpaulo "%s", ERR_error_string(ERR_get_error(), NULL)); 248252726Srpaulo } 249252726Srpaulo if (len != 0) { 250252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " 251252726Srpaulo "in AES encrypt", len); 252252726Srpaulo } 253252726Srpaulo EVP_CIPHER_CTX_cleanup(c); 254252726Srpaulo os_free(c); 255189251Ssam} 256189251Ssam 257189251Ssam 258189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 259189251Ssam{ 260252726Srpaulo EVP_CIPHER_CTX *ctx; 261252726Srpaulo const EVP_CIPHER *type; 262252726Srpaulo 263252726Srpaulo type = aes_get_evp_cipher(len); 264252726Srpaulo if (type == NULL) 265189251Ssam return NULL; 266252726Srpaulo 267252726Srpaulo ctx = os_malloc(sizeof(*ctx)); 268252726Srpaulo if (ctx == NULL) 269189251Ssam return NULL; 270252726Srpaulo EVP_CIPHER_CTX_init(ctx); 271252726Srpaulo if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) { 272252726Srpaulo os_free(ctx); 273252726Srpaulo return NULL; 274189251Ssam } 275252726Srpaulo EVP_CIPHER_CTX_set_padding(ctx, 0); 276252726Srpaulo return ctx; 277189251Ssam} 278189251Ssam 279189251Ssam 280189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 281189251Ssam{ 282252726Srpaulo EVP_CIPHER_CTX *c = ctx; 283252726Srpaulo int plen = 16; 284252726Srpaulo if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) { 285252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s", 286252726Srpaulo ERR_error_string(ERR_get_error(), NULL)); 287252726Srpaulo } 288189251Ssam} 289189251Ssam 290189251Ssam 291189251Ssamvoid aes_decrypt_deinit(void *ctx) 292189251Ssam{ 293252726Srpaulo EVP_CIPHER_CTX *c = ctx; 294252726Srpaulo u8 buf[16]; 295252726Srpaulo int len = sizeof(buf); 296252726Srpaulo if (EVP_DecryptFinal_ex(c, buf, &len) != 1) { 297252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: " 298252726Srpaulo "%s", ERR_error_string(ERR_get_error(), NULL)); 299252726Srpaulo } 300252726Srpaulo if (len != 0) { 301252726Srpaulo wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " 302252726Srpaulo "in AES decrypt", len); 303252726Srpaulo } 304252726Srpaulo EVP_CIPHER_CTX_cleanup(c); 305189251Ssam os_free(ctx); 306189251Ssam} 307189251Ssam 308189251Ssam 309189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len, 310189251Ssam const u8 *power, size_t power_len, 311189251Ssam const u8 *modulus, size_t modulus_len, 312189251Ssam u8 *result, size_t *result_len) 313189251Ssam{ 314189251Ssam BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; 315189251Ssam int ret = -1; 316189251Ssam BN_CTX *ctx; 317189251Ssam 318189251Ssam ctx = BN_CTX_new(); 319189251Ssam if (ctx == NULL) 320189251Ssam return -1; 321189251Ssam 322189251Ssam bn_base = BN_bin2bn(base, base_len, NULL); 323189251Ssam bn_exp = BN_bin2bn(power, power_len, NULL); 324189251Ssam bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); 325189251Ssam bn_result = BN_new(); 326189251Ssam 327189251Ssam if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || 328189251Ssam bn_result == NULL) 329189251Ssam goto error; 330189251Ssam 331189251Ssam if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) 332189251Ssam goto error; 333189251Ssam 334189251Ssam *result_len = BN_bn2bin(bn_result, result); 335189251Ssam ret = 0; 336189251Ssam 337189251Ssamerror: 338189251Ssam BN_free(bn_base); 339189251Ssam BN_free(bn_exp); 340189251Ssam BN_free(bn_modulus); 341189251Ssam BN_free(bn_result); 342189251Ssam BN_CTX_free(ctx); 343189251Ssam return ret; 344189251Ssam} 345189251Ssam 346189251Ssam 347189251Ssamstruct crypto_cipher { 348189251Ssam EVP_CIPHER_CTX enc; 349189251Ssam EVP_CIPHER_CTX dec; 350189251Ssam}; 351189251Ssam 352189251Ssam 353189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 354189251Ssam const u8 *iv, const u8 *key, 355189251Ssam size_t key_len) 356189251Ssam{ 357189251Ssam struct crypto_cipher *ctx; 358189251Ssam const EVP_CIPHER *cipher; 359189251Ssam 360189251Ssam ctx = os_zalloc(sizeof(*ctx)); 361189251Ssam if (ctx == NULL) 362189251Ssam return NULL; 363189251Ssam 364189251Ssam switch (alg) { 365189251Ssam#ifndef OPENSSL_NO_RC4 366189251Ssam case CRYPTO_CIPHER_ALG_RC4: 367189251Ssam cipher = EVP_rc4(); 368189251Ssam break; 369189251Ssam#endif /* OPENSSL_NO_RC4 */ 370189251Ssam#ifndef OPENSSL_NO_AES 371189251Ssam case CRYPTO_CIPHER_ALG_AES: 372189251Ssam switch (key_len) { 373189251Ssam case 16: 374189251Ssam cipher = EVP_aes_128_cbc(); 375189251Ssam break; 376189251Ssam case 24: 377189251Ssam cipher = EVP_aes_192_cbc(); 378189251Ssam break; 379189251Ssam case 32: 380189251Ssam cipher = EVP_aes_256_cbc(); 381189251Ssam break; 382189251Ssam default: 383189251Ssam os_free(ctx); 384189251Ssam return NULL; 385189251Ssam } 386189251Ssam break; 387189251Ssam#endif /* OPENSSL_NO_AES */ 388189251Ssam#ifndef OPENSSL_NO_DES 389189251Ssam case CRYPTO_CIPHER_ALG_3DES: 390189251Ssam cipher = EVP_des_ede3_cbc(); 391189251Ssam break; 392189251Ssam case CRYPTO_CIPHER_ALG_DES: 393189251Ssam cipher = EVP_des_cbc(); 394189251Ssam break; 395189251Ssam#endif /* OPENSSL_NO_DES */ 396189251Ssam#ifndef OPENSSL_NO_RC2 397189251Ssam case CRYPTO_CIPHER_ALG_RC2: 398189251Ssam cipher = EVP_rc2_ecb(); 399189251Ssam break; 400189251Ssam#endif /* OPENSSL_NO_RC2 */ 401189251Ssam default: 402189251Ssam os_free(ctx); 403189251Ssam return NULL; 404189251Ssam } 405189251Ssam 406189251Ssam EVP_CIPHER_CTX_init(&ctx->enc); 407189251Ssam EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); 408189251Ssam if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || 409189251Ssam !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || 410214734Srpaulo !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { 411189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 412189251Ssam os_free(ctx); 413189251Ssam return NULL; 414189251Ssam } 415189251Ssam 416189251Ssam EVP_CIPHER_CTX_init(&ctx->dec); 417189251Ssam EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); 418189251Ssam if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || 419189251Ssam !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || 420214734Srpaulo !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { 421189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 422189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->dec); 423189251Ssam os_free(ctx); 424189251Ssam return NULL; 425189251Ssam } 426189251Ssam 427189251Ssam return ctx; 428189251Ssam} 429189251Ssam 430189251Ssam 431189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 432189251Ssam u8 *crypt, size_t len) 433189251Ssam{ 434189251Ssam int outl; 435189251Ssam if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) 436189251Ssam return -1; 437189251Ssam return 0; 438189251Ssam} 439189251Ssam 440189251Ssam 441189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 442189251Ssam u8 *plain, size_t len) 443189251Ssam{ 444189251Ssam int outl; 445189251Ssam outl = len; 446189251Ssam if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) 447189251Ssam return -1; 448189251Ssam return 0; 449189251Ssam} 450189251Ssam 451189251Ssam 452189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 453189251Ssam{ 454189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->enc); 455189251Ssam EVP_CIPHER_CTX_cleanup(&ctx->dec); 456189251Ssam os_free(ctx); 457189251Ssam} 458214734Srpaulo 459214734Srpaulo 460214734Srpaulovoid * dh5_init(struct wpabuf **priv, struct wpabuf **publ) 461214734Srpaulo{ 462214734Srpaulo DH *dh; 463214734Srpaulo struct wpabuf *pubkey = NULL, *privkey = NULL; 464214734Srpaulo size_t publen, privlen; 465214734Srpaulo 466214734Srpaulo *priv = NULL; 467214734Srpaulo *publ = NULL; 468214734Srpaulo 469214734Srpaulo dh = DH_new(); 470214734Srpaulo if (dh == NULL) 471214734Srpaulo return NULL; 472214734Srpaulo 473214734Srpaulo dh->g = BN_new(); 474214734Srpaulo if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) 475214734Srpaulo goto err; 476214734Srpaulo 477214734Srpaulo dh->p = get_group5_prime(); 478214734Srpaulo if (dh->p == NULL) 479214734Srpaulo goto err; 480214734Srpaulo 481214734Srpaulo if (DH_generate_key(dh) != 1) 482214734Srpaulo goto err; 483214734Srpaulo 484214734Srpaulo publen = BN_num_bytes(dh->pub_key); 485214734Srpaulo pubkey = wpabuf_alloc(publen); 486214734Srpaulo if (pubkey == NULL) 487214734Srpaulo goto err; 488214734Srpaulo privlen = BN_num_bytes(dh->priv_key); 489214734Srpaulo privkey = wpabuf_alloc(privlen); 490214734Srpaulo if (privkey == NULL) 491214734Srpaulo goto err; 492214734Srpaulo 493214734Srpaulo BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); 494214734Srpaulo BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); 495214734Srpaulo 496214734Srpaulo *priv = privkey; 497214734Srpaulo *publ = pubkey; 498214734Srpaulo return dh; 499214734Srpaulo 500214734Srpauloerr: 501214734Srpaulo wpabuf_free(pubkey); 502214734Srpaulo wpabuf_free(privkey); 503214734Srpaulo DH_free(dh); 504214734Srpaulo return NULL; 505214734Srpaulo} 506214734Srpaulo 507214734Srpaulo 508252726Srpaulovoid * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) 509252726Srpaulo{ 510252726Srpaulo DH *dh; 511252726Srpaulo 512252726Srpaulo dh = DH_new(); 513252726Srpaulo if (dh == NULL) 514252726Srpaulo return NULL; 515252726Srpaulo 516252726Srpaulo dh->g = BN_new(); 517252726Srpaulo if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) 518252726Srpaulo goto err; 519252726Srpaulo 520252726Srpaulo dh->p = get_group5_prime(); 521252726Srpaulo if (dh->p == NULL) 522252726Srpaulo goto err; 523252726Srpaulo 524252726Srpaulo dh->priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); 525252726Srpaulo if (dh->priv_key == NULL) 526252726Srpaulo goto err; 527252726Srpaulo 528252726Srpaulo dh->pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); 529252726Srpaulo if (dh->pub_key == NULL) 530252726Srpaulo goto err; 531252726Srpaulo 532252726Srpaulo if (DH_generate_key(dh) != 1) 533252726Srpaulo goto err; 534252726Srpaulo 535252726Srpaulo return dh; 536252726Srpaulo 537252726Srpauloerr: 538252726Srpaulo DH_free(dh); 539252726Srpaulo return NULL; 540252726Srpaulo} 541252726Srpaulo 542252726Srpaulo 543214734Srpaulostruct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, 544214734Srpaulo const struct wpabuf *own_private) 545214734Srpaulo{ 546214734Srpaulo BIGNUM *pub_key; 547214734Srpaulo struct wpabuf *res = NULL; 548214734Srpaulo size_t rlen; 549214734Srpaulo DH *dh = ctx; 550214734Srpaulo int keylen; 551214734Srpaulo 552214734Srpaulo if (ctx == NULL) 553214734Srpaulo return NULL; 554214734Srpaulo 555214734Srpaulo pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), 556214734Srpaulo NULL); 557214734Srpaulo if (pub_key == NULL) 558214734Srpaulo return NULL; 559214734Srpaulo 560214734Srpaulo rlen = DH_size(dh); 561214734Srpaulo res = wpabuf_alloc(rlen); 562214734Srpaulo if (res == NULL) 563214734Srpaulo goto err; 564214734Srpaulo 565214734Srpaulo keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); 566214734Srpaulo if (keylen < 0) 567214734Srpaulo goto err; 568214734Srpaulo wpabuf_put(res, keylen); 569214734Srpaulo BN_free(pub_key); 570214734Srpaulo 571214734Srpaulo return res; 572214734Srpaulo 573214734Srpauloerr: 574214734Srpaulo BN_free(pub_key); 575214734Srpaulo wpabuf_free(res); 576214734Srpaulo return NULL; 577214734Srpaulo} 578214734Srpaulo 579214734Srpaulo 580214734Srpaulovoid dh5_free(void *ctx) 581214734Srpaulo{ 582214734Srpaulo DH *dh; 583214734Srpaulo if (ctx == NULL) 584214734Srpaulo return; 585214734Srpaulo dh = ctx; 586214734Srpaulo DH_free(dh); 587214734Srpaulo} 588252726Srpaulo 589252726Srpaulo 590252726Srpaulostruct crypto_hash { 591252726Srpaulo HMAC_CTX ctx; 592252726Srpaulo}; 593252726Srpaulo 594252726Srpaulo 595252726Srpaulostruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 596252726Srpaulo size_t key_len) 597252726Srpaulo{ 598252726Srpaulo struct crypto_hash *ctx; 599252726Srpaulo const EVP_MD *md; 600252726Srpaulo 601252726Srpaulo switch (alg) { 602252726Srpaulo#ifndef OPENSSL_NO_MD5 603252726Srpaulo case CRYPTO_HASH_ALG_HMAC_MD5: 604252726Srpaulo md = EVP_md5(); 605252726Srpaulo break; 606252726Srpaulo#endif /* OPENSSL_NO_MD5 */ 607252726Srpaulo#ifndef OPENSSL_NO_SHA 608252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA1: 609252726Srpaulo md = EVP_sha1(); 610252726Srpaulo break; 611252726Srpaulo#endif /* OPENSSL_NO_SHA */ 612252726Srpaulo#ifndef OPENSSL_NO_SHA256 613252726Srpaulo#ifdef CONFIG_SHA256 614252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 615252726Srpaulo md = EVP_sha256(); 616252726Srpaulo break; 617252726Srpaulo#endif /* CONFIG_SHA256 */ 618252726Srpaulo#endif /* OPENSSL_NO_SHA256 */ 619252726Srpaulo default: 620252726Srpaulo return NULL; 621252726Srpaulo } 622252726Srpaulo 623252726Srpaulo ctx = os_zalloc(sizeof(*ctx)); 624252726Srpaulo if (ctx == NULL) 625252726Srpaulo return NULL; 626252726Srpaulo HMAC_CTX_init(&ctx->ctx); 627252726Srpaulo 628252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 629252726Srpaulo HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL); 630252726Srpaulo#else /* openssl < 0.9.9 */ 631252726Srpaulo if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) { 632252726Srpaulo os_free(ctx); 633252726Srpaulo return NULL; 634252726Srpaulo } 635252726Srpaulo#endif /* openssl < 0.9.9 */ 636252726Srpaulo 637252726Srpaulo return ctx; 638252726Srpaulo} 639252726Srpaulo 640252726Srpaulo 641252726Srpaulovoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 642252726Srpaulo{ 643252726Srpaulo if (ctx == NULL) 644252726Srpaulo return; 645252726Srpaulo HMAC_Update(&ctx->ctx, data, len); 646252726Srpaulo} 647252726Srpaulo 648252726Srpaulo 649252726Srpauloint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 650252726Srpaulo{ 651252726Srpaulo unsigned int mdlen; 652252726Srpaulo int res; 653252726Srpaulo 654252726Srpaulo if (ctx == NULL) 655252726Srpaulo return -2; 656252726Srpaulo 657252726Srpaulo if (mac == NULL || len == NULL) { 658252726Srpaulo os_free(ctx); 659252726Srpaulo return 0; 660252726Srpaulo } 661252726Srpaulo 662252726Srpaulo mdlen = *len; 663252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 664252726Srpaulo HMAC_Final(&ctx->ctx, mac, &mdlen); 665252726Srpaulo res = 1; 666252726Srpaulo#else /* openssl < 0.9.9 */ 667252726Srpaulo res = HMAC_Final(&ctx->ctx, mac, &mdlen); 668252726Srpaulo#endif /* openssl < 0.9.9 */ 669252726Srpaulo HMAC_CTX_cleanup(&ctx->ctx); 670252726Srpaulo os_free(ctx); 671252726Srpaulo 672252726Srpaulo if (res == 1) { 673252726Srpaulo *len = mdlen; 674252726Srpaulo return 0; 675252726Srpaulo } 676252726Srpaulo 677252726Srpaulo return -1; 678252726Srpaulo} 679252726Srpaulo 680252726Srpaulo 681252726Srpauloint pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, 682252726Srpaulo int iterations, u8 *buf, size_t buflen) 683252726Srpaulo{ 684252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00908000 685252726Srpaulo if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), 686252726Srpaulo (unsigned char *) ssid, 687252726Srpaulo ssid_len, 4096, buflen, buf) != 1) 688252726Srpaulo return -1; 689252726Srpaulo#else /* openssl < 0.9.8 */ 690252726Srpaulo if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid, 691252726Srpaulo ssid_len, 4096, buflen, buf) != 1) 692252726Srpaulo return -1; 693252726Srpaulo#endif /* openssl < 0.9.8 */ 694252726Srpaulo return 0; 695252726Srpaulo} 696252726Srpaulo 697252726Srpaulo 698252726Srpauloint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, 699252726Srpaulo const u8 *addr[], const size_t *len, u8 *mac) 700252726Srpaulo{ 701252726Srpaulo HMAC_CTX ctx; 702252726Srpaulo size_t i; 703252726Srpaulo unsigned int mdlen; 704252726Srpaulo int res; 705252726Srpaulo 706252726Srpaulo HMAC_CTX_init(&ctx); 707252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 708252726Srpaulo HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL); 709252726Srpaulo#else /* openssl < 0.9.9 */ 710252726Srpaulo if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL) != 1) 711252726Srpaulo return -1; 712252726Srpaulo#endif /* openssl < 0.9.9 */ 713252726Srpaulo 714252726Srpaulo for (i = 0; i < num_elem; i++) 715252726Srpaulo HMAC_Update(&ctx, addr[i], len[i]); 716252726Srpaulo 717252726Srpaulo mdlen = 20; 718252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 719252726Srpaulo HMAC_Final(&ctx, mac, &mdlen); 720252726Srpaulo res = 1; 721252726Srpaulo#else /* openssl < 0.9.9 */ 722252726Srpaulo res = HMAC_Final(&ctx, mac, &mdlen); 723252726Srpaulo#endif /* openssl < 0.9.9 */ 724252726Srpaulo HMAC_CTX_cleanup(&ctx); 725252726Srpaulo 726252726Srpaulo return res == 1 ? 0 : -1; 727252726Srpaulo} 728252726Srpaulo 729252726Srpaulo 730252726Srpauloint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, 731252726Srpaulo u8 *mac) 732252726Srpaulo{ 733252726Srpaulo return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); 734252726Srpaulo} 735252726Srpaulo 736252726Srpaulo 737252726Srpaulo#ifdef CONFIG_SHA256 738252726Srpaulo 739252726Srpauloint hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, 740252726Srpaulo const u8 *addr[], const size_t *len, u8 *mac) 741252726Srpaulo{ 742252726Srpaulo HMAC_CTX ctx; 743252726Srpaulo size_t i; 744252726Srpaulo unsigned int mdlen; 745252726Srpaulo int res; 746252726Srpaulo 747252726Srpaulo HMAC_CTX_init(&ctx); 748252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 749252726Srpaulo HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL); 750252726Srpaulo#else /* openssl < 0.9.9 */ 751252726Srpaulo if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL) != 1) 752252726Srpaulo return -1; 753252726Srpaulo#endif /* openssl < 0.9.9 */ 754252726Srpaulo 755252726Srpaulo for (i = 0; i < num_elem; i++) 756252726Srpaulo HMAC_Update(&ctx, addr[i], len[i]); 757252726Srpaulo 758252726Srpaulo mdlen = 32; 759252726Srpaulo#if OPENSSL_VERSION_NUMBER < 0x00909000 760252726Srpaulo HMAC_Final(&ctx, mac, &mdlen); 761252726Srpaulo res = 1; 762252726Srpaulo#else /* openssl < 0.9.9 */ 763252726Srpaulo res = HMAC_Final(&ctx, mac, &mdlen); 764252726Srpaulo#endif /* openssl < 0.9.9 */ 765252726Srpaulo HMAC_CTX_cleanup(&ctx); 766252726Srpaulo 767252726Srpaulo return res == 1 ? 0 : -1; 768252726Srpaulo} 769252726Srpaulo 770252726Srpaulo 771252726Srpauloint hmac_sha256(const u8 *key, size_t key_len, const u8 *data, 772252726Srpaulo size_t data_len, u8 *mac) 773252726Srpaulo{ 774252726Srpaulo return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); 775252726Srpaulo} 776252726Srpaulo 777252726Srpaulo#endif /* CONFIG_SHA256 */ 778252726Srpaulo 779252726Srpaulo 780252726Srpauloint crypto_get_random(void *buf, size_t len) 781252726Srpaulo{ 782252726Srpaulo if (RAND_bytes(buf, len) != 1) 783252726Srpaulo return -1; 784252726Srpaulo return 0; 785252726Srpaulo} 786252726Srpaulo 787252726Srpaulo 788252726Srpaulo#ifdef CONFIG_OPENSSL_CMAC 789252726Srpauloint omac1_aes_128_vector(const u8 *key, size_t num_elem, 790252726Srpaulo const u8 *addr[], const size_t *len, u8 *mac) 791252726Srpaulo{ 792252726Srpaulo CMAC_CTX *ctx; 793252726Srpaulo int ret = -1; 794252726Srpaulo size_t outlen, i; 795252726Srpaulo 796252726Srpaulo ctx = CMAC_CTX_new(); 797252726Srpaulo if (ctx == NULL) 798252726Srpaulo return -1; 799252726Srpaulo 800252726Srpaulo if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL)) 801252726Srpaulo goto fail; 802252726Srpaulo for (i = 0; i < num_elem; i++) { 803252726Srpaulo if (!CMAC_Update(ctx, addr[i], len[i])) 804252726Srpaulo goto fail; 805252726Srpaulo } 806252726Srpaulo if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16) 807252726Srpaulo goto fail; 808252726Srpaulo 809252726Srpaulo ret = 0; 810252726Srpaulofail: 811252726Srpaulo CMAC_CTX_free(ctx); 812252726Srpaulo return ret; 813252726Srpaulo} 814252726Srpaulo 815252726Srpaulo 816252726Srpauloint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 817252726Srpaulo{ 818252726Srpaulo return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 819252726Srpaulo} 820252726Srpaulo#endif /* CONFIG_OPENSSL_CMAC */ 821