1*5b9c547cSRui Paulo /* 2*5b9c547cSRui Paulo * EAP server/peer: EAP-EKE shared routines 3*5b9c547cSRui Paulo * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi> 4*5b9c547cSRui Paulo * 5*5b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license. 6*5b9c547cSRui Paulo * See README for more details. 7*5b9c547cSRui Paulo */ 8*5b9c547cSRui Paulo 9*5b9c547cSRui Paulo #include "includes.h" 10*5b9c547cSRui Paulo 11*5b9c547cSRui Paulo #include "common.h" 12*5b9c547cSRui Paulo #include "crypto/aes.h" 13*5b9c547cSRui Paulo #include "crypto/aes_wrap.h" 14*5b9c547cSRui Paulo #include "crypto/crypto.h" 15*5b9c547cSRui Paulo #include "crypto/dh_groups.h" 16*5b9c547cSRui Paulo #include "crypto/random.h" 17*5b9c547cSRui Paulo #include "crypto/sha1.h" 18*5b9c547cSRui Paulo #include "crypto/sha256.h" 19*5b9c547cSRui Paulo #include "eap_common/eap_defs.h" 20*5b9c547cSRui Paulo #include "eap_eke_common.h" 21*5b9c547cSRui Paulo 22*5b9c547cSRui Paulo 23*5b9c547cSRui Paulo static int eap_eke_dh_len(u8 group) 24*5b9c547cSRui Paulo { 25*5b9c547cSRui Paulo switch (group) { 26*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_2: 27*5b9c547cSRui Paulo return 128; 28*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_5: 29*5b9c547cSRui Paulo return 192; 30*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_14: 31*5b9c547cSRui Paulo return 256; 32*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_15: 33*5b9c547cSRui Paulo return 384; 34*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_16: 35*5b9c547cSRui Paulo return 512; 36*5b9c547cSRui Paulo } 37*5b9c547cSRui Paulo 38*5b9c547cSRui Paulo return -1; 39*5b9c547cSRui Paulo } 40*5b9c547cSRui Paulo 41*5b9c547cSRui Paulo 42*5b9c547cSRui Paulo static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr) 43*5b9c547cSRui Paulo { 44*5b9c547cSRui Paulo int dhlen; 45*5b9c547cSRui Paulo 46*5b9c547cSRui Paulo dhlen = eap_eke_dh_len(dhgroup); 47*5b9c547cSRui Paulo if (dhlen < 0) 48*5b9c547cSRui Paulo return -1; 49*5b9c547cSRui Paulo if (encr != EAP_EKE_ENCR_AES128_CBC) 50*5b9c547cSRui Paulo return -1; 51*5b9c547cSRui Paulo return AES_BLOCK_SIZE + dhlen; 52*5b9c547cSRui Paulo } 53*5b9c547cSRui Paulo 54*5b9c547cSRui Paulo 55*5b9c547cSRui Paulo static const struct dh_group * eap_eke_dh_group(u8 group) 56*5b9c547cSRui Paulo { 57*5b9c547cSRui Paulo switch (group) { 58*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_2: 59*5b9c547cSRui Paulo return dh_groups_get(2); 60*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_5: 61*5b9c547cSRui Paulo return dh_groups_get(5); 62*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_14: 63*5b9c547cSRui Paulo return dh_groups_get(14); 64*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_15: 65*5b9c547cSRui Paulo return dh_groups_get(15); 66*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_16: 67*5b9c547cSRui Paulo return dh_groups_get(16); 68*5b9c547cSRui Paulo } 69*5b9c547cSRui Paulo 70*5b9c547cSRui Paulo return NULL; 71*5b9c547cSRui Paulo } 72*5b9c547cSRui Paulo 73*5b9c547cSRui Paulo 74*5b9c547cSRui Paulo static int eap_eke_dh_generator(u8 group) 75*5b9c547cSRui Paulo { 76*5b9c547cSRui Paulo switch (group) { 77*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_2: 78*5b9c547cSRui Paulo return 5; 79*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_5: 80*5b9c547cSRui Paulo return 31; 81*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_14: 82*5b9c547cSRui Paulo return 11; 83*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_15: 84*5b9c547cSRui Paulo return 5; 85*5b9c547cSRui Paulo case EAP_EKE_DHGROUP_EKE_16: 86*5b9c547cSRui Paulo return 5; 87*5b9c547cSRui Paulo } 88*5b9c547cSRui Paulo 89*5b9c547cSRui Paulo return -1; 90*5b9c547cSRui Paulo } 91*5b9c547cSRui Paulo 92*5b9c547cSRui Paulo 93*5b9c547cSRui Paulo static int eap_eke_pnonce_len(u8 mac) 94*5b9c547cSRui Paulo { 95*5b9c547cSRui Paulo int mac_len; 96*5b9c547cSRui Paulo 97*5b9c547cSRui Paulo if (mac == EAP_EKE_MAC_HMAC_SHA1) 98*5b9c547cSRui Paulo mac_len = SHA1_MAC_LEN; 99*5b9c547cSRui Paulo else if (mac == EAP_EKE_MAC_HMAC_SHA2_256) 100*5b9c547cSRui Paulo mac_len = SHA256_MAC_LEN; 101*5b9c547cSRui Paulo else 102*5b9c547cSRui Paulo return -1; 103*5b9c547cSRui Paulo 104*5b9c547cSRui Paulo return AES_BLOCK_SIZE + 16 + mac_len; 105*5b9c547cSRui Paulo } 106*5b9c547cSRui Paulo 107*5b9c547cSRui Paulo 108*5b9c547cSRui Paulo static int eap_eke_pnonce_ps_len(u8 mac) 109*5b9c547cSRui Paulo { 110*5b9c547cSRui Paulo int mac_len; 111*5b9c547cSRui Paulo 112*5b9c547cSRui Paulo if (mac == EAP_EKE_MAC_HMAC_SHA1) 113*5b9c547cSRui Paulo mac_len = SHA1_MAC_LEN; 114*5b9c547cSRui Paulo else if (mac == EAP_EKE_MAC_HMAC_SHA2_256) 115*5b9c547cSRui Paulo mac_len = SHA256_MAC_LEN; 116*5b9c547cSRui Paulo else 117*5b9c547cSRui Paulo return -1; 118*5b9c547cSRui Paulo 119*5b9c547cSRui Paulo return AES_BLOCK_SIZE + 2 * 16 + mac_len; 120*5b9c547cSRui Paulo } 121*5b9c547cSRui Paulo 122*5b9c547cSRui Paulo 123*5b9c547cSRui Paulo static int eap_eke_prf_len(u8 prf) 124*5b9c547cSRui Paulo { 125*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA1) 126*5b9c547cSRui Paulo return 20; 127*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA2_256) 128*5b9c547cSRui Paulo return 32; 129*5b9c547cSRui Paulo return -1; 130*5b9c547cSRui Paulo } 131*5b9c547cSRui Paulo 132*5b9c547cSRui Paulo 133*5b9c547cSRui Paulo static int eap_eke_nonce_len(u8 prf) 134*5b9c547cSRui Paulo { 135*5b9c547cSRui Paulo int prf_len; 136*5b9c547cSRui Paulo 137*5b9c547cSRui Paulo prf_len = eap_eke_prf_len(prf); 138*5b9c547cSRui Paulo if (prf_len < 0) 139*5b9c547cSRui Paulo return -1; 140*5b9c547cSRui Paulo 141*5b9c547cSRui Paulo if (prf_len > 2 * 16) 142*5b9c547cSRui Paulo return (prf_len + 1) / 2; 143*5b9c547cSRui Paulo 144*5b9c547cSRui Paulo return 16; 145*5b9c547cSRui Paulo } 146*5b9c547cSRui Paulo 147*5b9c547cSRui Paulo 148*5b9c547cSRui Paulo static int eap_eke_auth_len(u8 prf) 149*5b9c547cSRui Paulo { 150*5b9c547cSRui Paulo switch (prf) { 151*5b9c547cSRui Paulo case EAP_EKE_PRF_HMAC_SHA1: 152*5b9c547cSRui Paulo return SHA1_MAC_LEN; 153*5b9c547cSRui Paulo case EAP_EKE_PRF_HMAC_SHA2_256: 154*5b9c547cSRui Paulo return SHA256_MAC_LEN; 155*5b9c547cSRui Paulo } 156*5b9c547cSRui Paulo 157*5b9c547cSRui Paulo return -1; 158*5b9c547cSRui Paulo } 159*5b9c547cSRui Paulo 160*5b9c547cSRui Paulo 161*5b9c547cSRui Paulo int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub) 162*5b9c547cSRui Paulo { 163*5b9c547cSRui Paulo int generator; 164*5b9c547cSRui Paulo u8 gen; 165*5b9c547cSRui Paulo const struct dh_group *dh; 166*5b9c547cSRui Paulo size_t pub_len, i; 167*5b9c547cSRui Paulo 168*5b9c547cSRui Paulo generator = eap_eke_dh_generator(group); 169*5b9c547cSRui Paulo if (generator < 0 || generator > 255) 170*5b9c547cSRui Paulo return -1; 171*5b9c547cSRui Paulo gen = generator; 172*5b9c547cSRui Paulo 173*5b9c547cSRui Paulo dh = eap_eke_dh_group(group); 174*5b9c547cSRui Paulo if (dh == NULL) 175*5b9c547cSRui Paulo return -1; 176*5b9c547cSRui Paulo 177*5b9c547cSRui Paulo /* x = random number 2 .. p-1 */ 178*5b9c547cSRui Paulo if (random_get_bytes(ret_priv, dh->prime_len)) 179*5b9c547cSRui Paulo return -1; 180*5b9c547cSRui Paulo if (os_memcmp(ret_priv, dh->prime, dh->prime_len) > 0) { 181*5b9c547cSRui Paulo /* Make sure private value is smaller than prime */ 182*5b9c547cSRui Paulo ret_priv[0] = 0; 183*5b9c547cSRui Paulo } 184*5b9c547cSRui Paulo for (i = 0; i < dh->prime_len - 1; i++) { 185*5b9c547cSRui Paulo if (ret_priv[i]) 186*5b9c547cSRui Paulo break; 187*5b9c547cSRui Paulo } 188*5b9c547cSRui Paulo if (i == dh->prime_len - 1 && (ret_priv[i] == 0 || ret_priv[i] == 1)) 189*5b9c547cSRui Paulo return -1; 190*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value", 191*5b9c547cSRui Paulo ret_priv, dh->prime_len); 192*5b9c547cSRui Paulo 193*5b9c547cSRui Paulo /* y = g ^ x (mod p) */ 194*5b9c547cSRui Paulo pub_len = dh->prime_len; 195*5b9c547cSRui Paulo if (crypto_mod_exp(&gen, 1, ret_priv, dh->prime_len, 196*5b9c547cSRui Paulo dh->prime, dh->prime_len, ret_pub, &pub_len) < 0) 197*5b9c547cSRui Paulo return -1; 198*5b9c547cSRui Paulo if (pub_len < dh->prime_len) { 199*5b9c547cSRui Paulo size_t pad = dh->prime_len - pub_len; 200*5b9c547cSRui Paulo os_memmove(ret_pub + pad, ret_pub, pub_len); 201*5b9c547cSRui Paulo os_memset(ret_pub, 0, pad); 202*5b9c547cSRui Paulo } 203*5b9c547cSRui Paulo 204*5b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value", 205*5b9c547cSRui Paulo ret_pub, dh->prime_len); 206*5b9c547cSRui Paulo 207*5b9c547cSRui Paulo return 0; 208*5b9c547cSRui Paulo } 209*5b9c547cSRui Paulo 210*5b9c547cSRui Paulo 211*5b9c547cSRui Paulo static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data, 212*5b9c547cSRui Paulo size_t data_len, const u8 *data2, size_t data2_len, 213*5b9c547cSRui Paulo u8 *res) 214*5b9c547cSRui Paulo { 215*5b9c547cSRui Paulo const u8 *addr[2]; 216*5b9c547cSRui Paulo size_t len[2]; 217*5b9c547cSRui Paulo size_t num_elem = 1; 218*5b9c547cSRui Paulo 219*5b9c547cSRui Paulo addr[0] = data; 220*5b9c547cSRui Paulo len[0] = data_len; 221*5b9c547cSRui Paulo if (data2) { 222*5b9c547cSRui Paulo num_elem++; 223*5b9c547cSRui Paulo addr[1] = data2; 224*5b9c547cSRui Paulo len[1] = data2_len; 225*5b9c547cSRui Paulo } 226*5b9c547cSRui Paulo 227*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA1) 228*5b9c547cSRui Paulo return hmac_sha1_vector(key, key_len, num_elem, addr, len, res); 229*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA2_256) 230*5b9c547cSRui Paulo return hmac_sha256_vector(key, key_len, num_elem, addr, len, 231*5b9c547cSRui Paulo res); 232*5b9c547cSRui Paulo return -1; 233*5b9c547cSRui Paulo } 234*5b9c547cSRui Paulo 235*5b9c547cSRui Paulo 236*5b9c547cSRui Paulo static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data, 237*5b9c547cSRui Paulo size_t data_len, u8 *res, size_t len) 238*5b9c547cSRui Paulo { 239*5b9c547cSRui Paulo u8 hash[SHA1_MAC_LEN]; 240*5b9c547cSRui Paulo u8 idx; 241*5b9c547cSRui Paulo const u8 *addr[3]; 242*5b9c547cSRui Paulo size_t vlen[3]; 243*5b9c547cSRui Paulo int ret; 244*5b9c547cSRui Paulo 245*5b9c547cSRui Paulo idx = 0; 246*5b9c547cSRui Paulo addr[0] = hash; 247*5b9c547cSRui Paulo vlen[0] = SHA1_MAC_LEN; 248*5b9c547cSRui Paulo addr[1] = data; 249*5b9c547cSRui Paulo vlen[1] = data_len; 250*5b9c547cSRui Paulo addr[2] = &idx; 251*5b9c547cSRui Paulo vlen[2] = 1; 252*5b9c547cSRui Paulo 253*5b9c547cSRui Paulo while (len > 0) { 254*5b9c547cSRui Paulo idx++; 255*5b9c547cSRui Paulo if (idx == 1) 256*5b9c547cSRui Paulo ret = hmac_sha1_vector(key, key_len, 2, &addr[1], 257*5b9c547cSRui Paulo &vlen[1], hash); 258*5b9c547cSRui Paulo else 259*5b9c547cSRui Paulo ret = hmac_sha1_vector(key, key_len, 3, addr, vlen, 260*5b9c547cSRui Paulo hash); 261*5b9c547cSRui Paulo if (ret < 0) 262*5b9c547cSRui Paulo return -1; 263*5b9c547cSRui Paulo if (len > SHA1_MAC_LEN) { 264*5b9c547cSRui Paulo os_memcpy(res, hash, SHA1_MAC_LEN); 265*5b9c547cSRui Paulo res += SHA1_MAC_LEN; 266*5b9c547cSRui Paulo len -= SHA1_MAC_LEN; 267*5b9c547cSRui Paulo } else { 268*5b9c547cSRui Paulo os_memcpy(res, hash, len); 269*5b9c547cSRui Paulo len = 0; 270*5b9c547cSRui Paulo } 271*5b9c547cSRui Paulo } 272*5b9c547cSRui Paulo 273*5b9c547cSRui Paulo return 0; 274*5b9c547cSRui Paulo } 275*5b9c547cSRui Paulo 276*5b9c547cSRui Paulo 277*5b9c547cSRui Paulo static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data, 278*5b9c547cSRui Paulo size_t data_len, u8 *res, size_t len) 279*5b9c547cSRui Paulo { 280*5b9c547cSRui Paulo u8 hash[SHA256_MAC_LEN]; 281*5b9c547cSRui Paulo u8 idx; 282*5b9c547cSRui Paulo const u8 *addr[3]; 283*5b9c547cSRui Paulo size_t vlen[3]; 284*5b9c547cSRui Paulo int ret; 285*5b9c547cSRui Paulo 286*5b9c547cSRui Paulo idx = 0; 287*5b9c547cSRui Paulo addr[0] = hash; 288*5b9c547cSRui Paulo vlen[0] = SHA256_MAC_LEN; 289*5b9c547cSRui Paulo addr[1] = data; 290*5b9c547cSRui Paulo vlen[1] = data_len; 291*5b9c547cSRui Paulo addr[2] = &idx; 292*5b9c547cSRui Paulo vlen[2] = 1; 293*5b9c547cSRui Paulo 294*5b9c547cSRui Paulo while (len > 0) { 295*5b9c547cSRui Paulo idx++; 296*5b9c547cSRui Paulo if (idx == 1) 297*5b9c547cSRui Paulo ret = hmac_sha256_vector(key, key_len, 2, &addr[1], 298*5b9c547cSRui Paulo &vlen[1], hash); 299*5b9c547cSRui Paulo else 300*5b9c547cSRui Paulo ret = hmac_sha256_vector(key, key_len, 3, addr, vlen, 301*5b9c547cSRui Paulo hash); 302*5b9c547cSRui Paulo if (ret < 0) 303*5b9c547cSRui Paulo return -1; 304*5b9c547cSRui Paulo if (len > SHA256_MAC_LEN) { 305*5b9c547cSRui Paulo os_memcpy(res, hash, SHA256_MAC_LEN); 306*5b9c547cSRui Paulo res += SHA256_MAC_LEN; 307*5b9c547cSRui Paulo len -= SHA256_MAC_LEN; 308*5b9c547cSRui Paulo } else { 309*5b9c547cSRui Paulo os_memcpy(res, hash, len); 310*5b9c547cSRui Paulo len = 0; 311*5b9c547cSRui Paulo } 312*5b9c547cSRui Paulo } 313*5b9c547cSRui Paulo 314*5b9c547cSRui Paulo return 0; 315*5b9c547cSRui Paulo } 316*5b9c547cSRui Paulo 317*5b9c547cSRui Paulo 318*5b9c547cSRui Paulo static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len, 319*5b9c547cSRui Paulo const u8 *data, size_t data_len, u8 *res, size_t len) 320*5b9c547cSRui Paulo { 321*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA1) 322*5b9c547cSRui Paulo return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res, 323*5b9c547cSRui Paulo len); 324*5b9c547cSRui Paulo if (prf == EAP_EKE_PRF_HMAC_SHA2_256) 325*5b9c547cSRui Paulo return eap_eke_prf_hmac_sha256(key, key_len, data, data_len, 326*5b9c547cSRui Paulo res, len); 327*5b9c547cSRui Paulo return -1; 328*5b9c547cSRui Paulo } 329*5b9c547cSRui Paulo 330*5b9c547cSRui Paulo 331*5b9c547cSRui Paulo int eap_eke_derive_key(struct eap_eke_session *sess, 332*5b9c547cSRui Paulo const u8 *password, size_t password_len, 333*5b9c547cSRui Paulo const u8 *id_s, size_t id_s_len, const u8 *id_p, 334*5b9c547cSRui Paulo size_t id_p_len, u8 *key) 335*5b9c547cSRui Paulo { 336*5b9c547cSRui Paulo u8 zeros[EAP_EKE_MAX_HASH_LEN]; 337*5b9c547cSRui Paulo u8 temp[EAP_EKE_MAX_HASH_LEN]; 338*5b9c547cSRui Paulo size_t key_len = 16; /* Only AES-128-CBC is used here */ 339*5b9c547cSRui Paulo u8 *id; 340*5b9c547cSRui Paulo 341*5b9c547cSRui Paulo /* temp = prf(0+, password) */ 342*5b9c547cSRui Paulo os_memset(zeros, 0, sess->prf_len); 343*5b9c547cSRui Paulo if (eap_eke_prf(sess->prf, zeros, sess->prf_len, 344*5b9c547cSRui Paulo password, password_len, NULL, 0, temp) < 0) 345*5b9c547cSRui Paulo return -1; 346*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)", 347*5b9c547cSRui Paulo temp, sess->prf_len); 348*5b9c547cSRui Paulo 349*5b9c547cSRui Paulo /* key = prf+(temp, ID_S | ID_P) */ 350*5b9c547cSRui Paulo id = os_malloc(id_s_len + id_p_len); 351*5b9c547cSRui Paulo if (id == NULL) 352*5b9c547cSRui Paulo return -1; 353*5b9c547cSRui Paulo os_memcpy(id, id_s, id_s_len); 354*5b9c547cSRui Paulo os_memcpy(id + id_s_len, id_p, id_p_len); 355*5b9c547cSRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P", 356*5b9c547cSRui Paulo id, id_s_len + id_p_len); 357*5b9c547cSRui Paulo if (eap_eke_prfplus(sess->prf, temp, sess->prf_len, 358*5b9c547cSRui Paulo id, id_s_len + id_p_len, key, key_len) < 0) { 359*5b9c547cSRui Paulo os_free(id); 360*5b9c547cSRui Paulo return -1; 361*5b9c547cSRui Paulo } 362*5b9c547cSRui Paulo os_free(id); 363*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)", 364*5b9c547cSRui Paulo key, key_len); 365*5b9c547cSRui Paulo 366*5b9c547cSRui Paulo return 0; 367*5b9c547cSRui Paulo } 368*5b9c547cSRui Paulo 369*5b9c547cSRui Paulo 370*5b9c547cSRui Paulo int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub, 371*5b9c547cSRui Paulo u8 *ret_dhcomp) 372*5b9c547cSRui Paulo { 373*5b9c547cSRui Paulo u8 pub[EAP_EKE_MAX_DH_LEN]; 374*5b9c547cSRui Paulo int dh_len; 375*5b9c547cSRui Paulo u8 iv[AES_BLOCK_SIZE]; 376*5b9c547cSRui Paulo 377*5b9c547cSRui Paulo dh_len = eap_eke_dh_len(sess->dhgroup); 378*5b9c547cSRui Paulo if (dh_len < 0) 379*5b9c547cSRui Paulo return -1; 380*5b9c547cSRui Paulo 381*5b9c547cSRui Paulo /* 382*5b9c547cSRui Paulo * DHComponent = Encr(key, y) 383*5b9c547cSRui Paulo * 384*5b9c547cSRui Paulo * All defined DH groups use primes that have length devisible by 16, so 385*5b9c547cSRui Paulo * no need to do extra padding for y (= pub). 386*5b9c547cSRui Paulo */ 387*5b9c547cSRui Paulo if (sess->encr != EAP_EKE_ENCR_AES128_CBC) 388*5b9c547cSRui Paulo return -1; 389*5b9c547cSRui Paulo if (random_get_bytes(iv, AES_BLOCK_SIZE)) 390*5b9c547cSRui Paulo return -1; 391*5b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)", 392*5b9c547cSRui Paulo iv, AES_BLOCK_SIZE); 393*5b9c547cSRui Paulo os_memcpy(pub, dhpub, dh_len); 394*5b9c547cSRui Paulo if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0) 395*5b9c547cSRui Paulo return -1; 396*5b9c547cSRui Paulo os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE); 397*5b9c547cSRui Paulo os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len); 398*5b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)", 399*5b9c547cSRui Paulo ret_dhcomp, AES_BLOCK_SIZE + dh_len); 400*5b9c547cSRui Paulo 401*5b9c547cSRui Paulo return 0; 402*5b9c547cSRui Paulo } 403*5b9c547cSRui Paulo 404*5b9c547cSRui Paulo 405*5b9c547cSRui Paulo int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key, 406*5b9c547cSRui Paulo const u8 *dhpriv, const u8 *peer_dhcomp) 407*5b9c547cSRui Paulo { 408*5b9c547cSRui Paulo u8 zeros[EAP_EKE_MAX_HASH_LEN]; 409*5b9c547cSRui Paulo u8 peer_pub[EAP_EKE_MAX_DH_LEN]; 410*5b9c547cSRui Paulo u8 modexp[EAP_EKE_MAX_DH_LEN]; 411*5b9c547cSRui Paulo size_t len; 412*5b9c547cSRui Paulo const struct dh_group *dh; 413*5b9c547cSRui Paulo 414*5b9c547cSRui Paulo if (sess->encr != EAP_EKE_ENCR_AES128_CBC) 415*5b9c547cSRui Paulo return -1; 416*5b9c547cSRui Paulo 417*5b9c547cSRui Paulo dh = eap_eke_dh_group(sess->dhgroup); 418*5b9c547cSRui Paulo if (dh == NULL) 419*5b9c547cSRui Paulo return -1; 420*5b9c547cSRui Paulo 421*5b9c547cSRui Paulo /* Decrypt peer DHComponent */ 422*5b9c547cSRui Paulo os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len); 423*5b9c547cSRui Paulo if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) { 424*5b9c547cSRui Paulo wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent"); 425*5b9c547cSRui Paulo return -1; 426*5b9c547cSRui Paulo } 427*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey", 428*5b9c547cSRui Paulo peer_pub, dh->prime_len); 429*5b9c547cSRui Paulo 430*5b9c547cSRui Paulo /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */ 431*5b9c547cSRui Paulo len = dh->prime_len; 432*5b9c547cSRui Paulo if (crypto_mod_exp(peer_pub, dh->prime_len, dhpriv, dh->prime_len, 433*5b9c547cSRui Paulo dh->prime, dh->prime_len, modexp, &len) < 0) 434*5b9c547cSRui Paulo return -1; 435*5b9c547cSRui Paulo if (len < dh->prime_len) { 436*5b9c547cSRui Paulo size_t pad = dh->prime_len - len; 437*5b9c547cSRui Paulo os_memmove(modexp + pad, modexp, len); 438*5b9c547cSRui Paulo os_memset(modexp, 0, pad); 439*5b9c547cSRui Paulo } 440*5b9c547cSRui Paulo 441*5b9c547cSRui Paulo os_memset(zeros, 0, sess->auth_len); 442*5b9c547cSRui Paulo if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len, 443*5b9c547cSRui Paulo NULL, 0, sess->shared_secret) < 0) 444*5b9c547cSRui Paulo return -1; 445*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret", 446*5b9c547cSRui Paulo sess->shared_secret, sess->auth_len); 447*5b9c547cSRui Paulo 448*5b9c547cSRui Paulo return 0; 449*5b9c547cSRui Paulo } 450*5b9c547cSRui Paulo 451*5b9c547cSRui Paulo 452*5b9c547cSRui Paulo int eap_eke_derive_ke_ki(struct eap_eke_session *sess, 453*5b9c547cSRui Paulo const u8 *id_s, size_t id_s_len, 454*5b9c547cSRui Paulo const u8 *id_p, size_t id_p_len) 455*5b9c547cSRui Paulo { 456*5b9c547cSRui Paulo u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN]; 457*5b9c547cSRui Paulo size_t ke_len, ki_len; 458*5b9c547cSRui Paulo u8 *data; 459*5b9c547cSRui Paulo size_t data_len; 460*5b9c547cSRui Paulo const char *label = "EAP-EKE Keys"; 461*5b9c547cSRui Paulo size_t label_len; 462*5b9c547cSRui Paulo 463*5b9c547cSRui Paulo /* 464*5b9c547cSRui Paulo * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P) 465*5b9c547cSRui Paulo * Ke = encryption key 466*5b9c547cSRui Paulo * Ki = integrity protection key 467*5b9c547cSRui Paulo * Length of each key depends on the selected algorithms. 468*5b9c547cSRui Paulo */ 469*5b9c547cSRui Paulo 470*5b9c547cSRui Paulo if (sess->encr == EAP_EKE_ENCR_AES128_CBC) 471*5b9c547cSRui Paulo ke_len = 16; 472*5b9c547cSRui Paulo else 473*5b9c547cSRui Paulo return -1; 474*5b9c547cSRui Paulo 475*5b9c547cSRui Paulo if (sess->mac == EAP_EKE_PRF_HMAC_SHA1) 476*5b9c547cSRui Paulo ki_len = 20; 477*5b9c547cSRui Paulo else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256) 478*5b9c547cSRui Paulo ki_len = 32; 479*5b9c547cSRui Paulo else 480*5b9c547cSRui Paulo return -1; 481*5b9c547cSRui Paulo 482*5b9c547cSRui Paulo label_len = os_strlen(label); 483*5b9c547cSRui Paulo data_len = label_len + id_s_len + id_p_len; 484*5b9c547cSRui Paulo data = os_malloc(data_len); 485*5b9c547cSRui Paulo if (data == NULL) 486*5b9c547cSRui Paulo return -1; 487*5b9c547cSRui Paulo os_memcpy(data, label, label_len); 488*5b9c547cSRui Paulo os_memcpy(data + label_len, id_s, id_s_len); 489*5b9c547cSRui Paulo os_memcpy(data + label_len + id_s_len, id_p, id_p_len); 490*5b9c547cSRui Paulo if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len, 491*5b9c547cSRui Paulo data, data_len, buf, ke_len + ki_len) < 0) { 492*5b9c547cSRui Paulo os_free(data); 493*5b9c547cSRui Paulo return -1; 494*5b9c547cSRui Paulo } 495*5b9c547cSRui Paulo 496*5b9c547cSRui Paulo os_memcpy(sess->ke, buf, ke_len); 497*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len); 498*5b9c547cSRui Paulo os_memcpy(sess->ki, buf + ke_len, ki_len); 499*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len); 500*5b9c547cSRui Paulo 501*5b9c547cSRui Paulo os_free(data); 502*5b9c547cSRui Paulo return 0; 503*5b9c547cSRui Paulo } 504*5b9c547cSRui Paulo 505*5b9c547cSRui Paulo 506*5b9c547cSRui Paulo int eap_eke_derive_ka(struct eap_eke_session *sess, 507*5b9c547cSRui Paulo const u8 *id_s, size_t id_s_len, 508*5b9c547cSRui Paulo const u8 *id_p, size_t id_p_len, 509*5b9c547cSRui Paulo const u8 *nonce_p, const u8 *nonce_s) 510*5b9c547cSRui Paulo { 511*5b9c547cSRui Paulo u8 *data, *pos; 512*5b9c547cSRui Paulo size_t data_len; 513*5b9c547cSRui Paulo const char *label = "EAP-EKE Ka"; 514*5b9c547cSRui Paulo size_t label_len; 515*5b9c547cSRui Paulo 516*5b9c547cSRui Paulo /* 517*5b9c547cSRui Paulo * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P | 518*5b9c547cSRui Paulo * Nonce_S) 519*5b9c547cSRui Paulo * Ka = authentication key 520*5b9c547cSRui Paulo * Length of the key depends on the selected algorithms. 521*5b9c547cSRui Paulo */ 522*5b9c547cSRui Paulo 523*5b9c547cSRui Paulo label_len = os_strlen(label); 524*5b9c547cSRui Paulo data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len; 525*5b9c547cSRui Paulo data = os_malloc(data_len); 526*5b9c547cSRui Paulo if (data == NULL) 527*5b9c547cSRui Paulo return -1; 528*5b9c547cSRui Paulo pos = data; 529*5b9c547cSRui Paulo os_memcpy(pos, label, label_len); 530*5b9c547cSRui Paulo pos += label_len; 531*5b9c547cSRui Paulo os_memcpy(pos, id_s, id_s_len); 532*5b9c547cSRui Paulo pos += id_s_len; 533*5b9c547cSRui Paulo os_memcpy(pos, id_p, id_p_len); 534*5b9c547cSRui Paulo pos += id_p_len; 535*5b9c547cSRui Paulo os_memcpy(pos, nonce_p, sess->nonce_len); 536*5b9c547cSRui Paulo pos += sess->nonce_len; 537*5b9c547cSRui Paulo os_memcpy(pos, nonce_s, sess->nonce_len); 538*5b9c547cSRui Paulo if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len, 539*5b9c547cSRui Paulo data, data_len, sess->ka, sess->prf_len) < 0) { 540*5b9c547cSRui Paulo os_free(data); 541*5b9c547cSRui Paulo return -1; 542*5b9c547cSRui Paulo } 543*5b9c547cSRui Paulo os_free(data); 544*5b9c547cSRui Paulo 545*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len); 546*5b9c547cSRui Paulo 547*5b9c547cSRui Paulo return 0; 548*5b9c547cSRui Paulo } 549*5b9c547cSRui Paulo 550*5b9c547cSRui Paulo 551*5b9c547cSRui Paulo int eap_eke_derive_msk(struct eap_eke_session *sess, 552*5b9c547cSRui Paulo const u8 *id_s, size_t id_s_len, 553*5b9c547cSRui Paulo const u8 *id_p, size_t id_p_len, 554*5b9c547cSRui Paulo const u8 *nonce_p, const u8 *nonce_s, 555*5b9c547cSRui Paulo u8 *msk, u8 *emsk) 556*5b9c547cSRui Paulo { 557*5b9c547cSRui Paulo u8 *data, *pos; 558*5b9c547cSRui Paulo size_t data_len; 559*5b9c547cSRui Paulo const char *label = "EAP-EKE Exported Keys"; 560*5b9c547cSRui Paulo size_t label_len; 561*5b9c547cSRui Paulo u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN]; 562*5b9c547cSRui Paulo 563*5b9c547cSRui Paulo /* 564*5b9c547cSRui Paulo * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S | 565*5b9c547cSRui Paulo * ID_P | Nonce_P | Nonce_S) 566*5b9c547cSRui Paulo */ 567*5b9c547cSRui Paulo 568*5b9c547cSRui Paulo label_len = os_strlen(label); 569*5b9c547cSRui Paulo data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len; 570*5b9c547cSRui Paulo data = os_malloc(data_len); 571*5b9c547cSRui Paulo if (data == NULL) 572*5b9c547cSRui Paulo return -1; 573*5b9c547cSRui Paulo pos = data; 574*5b9c547cSRui Paulo os_memcpy(pos, label, label_len); 575*5b9c547cSRui Paulo pos += label_len; 576*5b9c547cSRui Paulo os_memcpy(pos, id_s, id_s_len); 577*5b9c547cSRui Paulo pos += id_s_len; 578*5b9c547cSRui Paulo os_memcpy(pos, id_p, id_p_len); 579*5b9c547cSRui Paulo pos += id_p_len; 580*5b9c547cSRui Paulo os_memcpy(pos, nonce_p, sess->nonce_len); 581*5b9c547cSRui Paulo pos += sess->nonce_len; 582*5b9c547cSRui Paulo os_memcpy(pos, nonce_s, sess->nonce_len); 583*5b9c547cSRui Paulo if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len, 584*5b9c547cSRui Paulo data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) < 585*5b9c547cSRui Paulo 0) { 586*5b9c547cSRui Paulo os_free(data); 587*5b9c547cSRui Paulo return -1; 588*5b9c547cSRui Paulo } 589*5b9c547cSRui Paulo os_free(data); 590*5b9c547cSRui Paulo 591*5b9c547cSRui Paulo os_memcpy(msk, buf, EAP_MSK_LEN); 592*5b9c547cSRui Paulo os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN); 593*5b9c547cSRui Paulo os_memset(buf, 0, sizeof(buf)); 594*5b9c547cSRui Paulo 595*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN); 596*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN); 597*5b9c547cSRui Paulo 598*5b9c547cSRui Paulo return 0; 599*5b9c547cSRui Paulo } 600*5b9c547cSRui Paulo 601*5b9c547cSRui Paulo 602*5b9c547cSRui Paulo static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len, 603*5b9c547cSRui Paulo u8 *res) 604*5b9c547cSRui Paulo { 605*5b9c547cSRui Paulo if (mac == EAP_EKE_MAC_HMAC_SHA1) 606*5b9c547cSRui Paulo return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res); 607*5b9c547cSRui Paulo if (mac == EAP_EKE_MAC_HMAC_SHA2_256) 608*5b9c547cSRui Paulo return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res); 609*5b9c547cSRui Paulo return -1; 610*5b9c547cSRui Paulo } 611*5b9c547cSRui Paulo 612*5b9c547cSRui Paulo 613*5b9c547cSRui Paulo int eap_eke_prot(struct eap_eke_session *sess, 614*5b9c547cSRui Paulo const u8 *data, size_t data_len, 615*5b9c547cSRui Paulo u8 *prot, size_t *prot_len) 616*5b9c547cSRui Paulo { 617*5b9c547cSRui Paulo size_t block_size, icv_len, pad; 618*5b9c547cSRui Paulo u8 *pos, *iv, *e; 619*5b9c547cSRui Paulo 620*5b9c547cSRui Paulo if (sess->encr == EAP_EKE_ENCR_AES128_CBC) 621*5b9c547cSRui Paulo block_size = AES_BLOCK_SIZE; 622*5b9c547cSRui Paulo else 623*5b9c547cSRui Paulo return -1; 624*5b9c547cSRui Paulo 625*5b9c547cSRui Paulo if (sess->mac == EAP_EKE_PRF_HMAC_SHA1) 626*5b9c547cSRui Paulo icv_len = SHA1_MAC_LEN; 627*5b9c547cSRui Paulo else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256) 628*5b9c547cSRui Paulo icv_len = SHA256_MAC_LEN; 629*5b9c547cSRui Paulo else 630*5b9c547cSRui Paulo return -1; 631*5b9c547cSRui Paulo 632*5b9c547cSRui Paulo pad = data_len % block_size; 633*5b9c547cSRui Paulo if (pad) 634*5b9c547cSRui Paulo pad = block_size - pad; 635*5b9c547cSRui Paulo 636*5b9c547cSRui Paulo if (*prot_len < block_size + data_len + pad + icv_len) { 637*5b9c547cSRui Paulo wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data"); 638*5b9c547cSRui Paulo } 639*5b9c547cSRui Paulo pos = prot; 640*5b9c547cSRui Paulo 641*5b9c547cSRui Paulo if (random_get_bytes(pos, block_size)) 642*5b9c547cSRui Paulo return -1; 643*5b9c547cSRui Paulo iv = pos; 644*5b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size); 645*5b9c547cSRui Paulo pos += block_size; 646*5b9c547cSRui Paulo 647*5b9c547cSRui Paulo e = pos; 648*5b9c547cSRui Paulo os_memcpy(pos, data, data_len); 649*5b9c547cSRui Paulo pos += data_len; 650*5b9c547cSRui Paulo if (pad) { 651*5b9c547cSRui Paulo if (random_get_bytes(pos, pad)) 652*5b9c547cSRui Paulo return -1; 653*5b9c547cSRui Paulo pos += pad; 654*5b9c547cSRui Paulo } 655*5b9c547cSRui Paulo 656*5b9c547cSRui Paulo if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0) 657*5b9c547cSRui Paulo return -1; 658*5b9c547cSRui Paulo 659*5b9c547cSRui Paulo if (eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0) 660*5b9c547cSRui Paulo return -1; 661*5b9c547cSRui Paulo pos += icv_len; 662*5b9c547cSRui Paulo 663*5b9c547cSRui Paulo *prot_len = pos - prot; 664*5b9c547cSRui Paulo return 0; 665*5b9c547cSRui Paulo } 666*5b9c547cSRui Paulo 667*5b9c547cSRui Paulo 668*5b9c547cSRui Paulo int eap_eke_decrypt_prot(struct eap_eke_session *sess, 669*5b9c547cSRui Paulo const u8 *prot, size_t prot_len, 670*5b9c547cSRui Paulo u8 *data, size_t *data_len) 671*5b9c547cSRui Paulo { 672*5b9c547cSRui Paulo size_t block_size, icv_len; 673*5b9c547cSRui Paulo u8 icv[EAP_EKE_MAX_HASH_LEN]; 674*5b9c547cSRui Paulo 675*5b9c547cSRui Paulo if (sess->encr == EAP_EKE_ENCR_AES128_CBC) 676*5b9c547cSRui Paulo block_size = AES_BLOCK_SIZE; 677*5b9c547cSRui Paulo else 678*5b9c547cSRui Paulo return -1; 679*5b9c547cSRui Paulo 680*5b9c547cSRui Paulo if (sess->mac == EAP_EKE_PRF_HMAC_SHA1) 681*5b9c547cSRui Paulo icv_len = SHA1_MAC_LEN; 682*5b9c547cSRui Paulo else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256) 683*5b9c547cSRui Paulo icv_len = SHA256_MAC_LEN; 684*5b9c547cSRui Paulo else 685*5b9c547cSRui Paulo return -1; 686*5b9c547cSRui Paulo 687*5b9c547cSRui Paulo if (prot_len < 2 * block_size + icv_len) 688*5b9c547cSRui Paulo return -1; 689*5b9c547cSRui Paulo if ((prot_len - icv_len) % block_size) 690*5b9c547cSRui Paulo return -1; 691*5b9c547cSRui Paulo 692*5b9c547cSRui Paulo if (eap_eke_mac(sess->mac, sess->ki, prot + block_size, 693*5b9c547cSRui Paulo prot_len - block_size - icv_len, icv) < 0) 694*5b9c547cSRui Paulo return -1; 695*5b9c547cSRui Paulo if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) { 696*5b9c547cSRui Paulo wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data"); 697*5b9c547cSRui Paulo return -1; 698*5b9c547cSRui Paulo } 699*5b9c547cSRui Paulo 700*5b9c547cSRui Paulo if (*data_len < prot_len - block_size - icv_len) { 701*5b9c547cSRui Paulo wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data"); 702*5b9c547cSRui Paulo return -1; 703*5b9c547cSRui Paulo } 704*5b9c547cSRui Paulo 705*5b9c547cSRui Paulo *data_len = prot_len - block_size - icv_len; 706*5b9c547cSRui Paulo os_memcpy(data, prot + block_size, *data_len); 707*5b9c547cSRui Paulo if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) { 708*5b9c547cSRui Paulo wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data"); 709*5b9c547cSRui Paulo return -1; 710*5b9c547cSRui Paulo } 711*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data", 712*5b9c547cSRui Paulo data, *data_len); 713*5b9c547cSRui Paulo 714*5b9c547cSRui Paulo return 0; 715*5b9c547cSRui Paulo } 716*5b9c547cSRui Paulo 717*5b9c547cSRui Paulo 718*5b9c547cSRui Paulo int eap_eke_auth(struct eap_eke_session *sess, const char *label, 719*5b9c547cSRui Paulo const struct wpabuf *msgs, u8 *auth) 720*5b9c547cSRui Paulo { 721*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label); 722*5b9c547cSRui Paulo wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth", 723*5b9c547cSRui Paulo sess->ka, sess->auth_len); 724*5b9c547cSRui Paulo wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs); 725*5b9c547cSRui Paulo return eap_eke_prf(sess->prf, sess->ka, sess->auth_len, 726*5b9c547cSRui Paulo (const u8 *) label, os_strlen(label), 727*5b9c547cSRui Paulo wpabuf_head(msgs), wpabuf_len(msgs), auth); 728*5b9c547cSRui Paulo } 729*5b9c547cSRui Paulo 730*5b9c547cSRui Paulo 731*5b9c547cSRui Paulo int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr, 732*5b9c547cSRui Paulo u8 prf, u8 mac) 733*5b9c547cSRui Paulo { 734*5b9c547cSRui Paulo sess->dhgroup = dhgroup; 735*5b9c547cSRui Paulo sess->encr = encr; 736*5b9c547cSRui Paulo sess->prf = prf; 737*5b9c547cSRui Paulo sess->mac = mac; 738*5b9c547cSRui Paulo 739*5b9c547cSRui Paulo sess->prf_len = eap_eke_prf_len(prf); 740*5b9c547cSRui Paulo if (sess->prf_len < 0) 741*5b9c547cSRui Paulo return -1; 742*5b9c547cSRui Paulo sess->nonce_len = eap_eke_nonce_len(prf); 743*5b9c547cSRui Paulo if (sess->nonce_len < 0) 744*5b9c547cSRui Paulo return -1; 745*5b9c547cSRui Paulo sess->auth_len = eap_eke_auth_len(prf); 746*5b9c547cSRui Paulo if (sess->auth_len < 0) 747*5b9c547cSRui Paulo return -1; 748*5b9c547cSRui Paulo sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr); 749*5b9c547cSRui Paulo if (sess->dhcomp_len < 0) 750*5b9c547cSRui Paulo return -1; 751*5b9c547cSRui Paulo sess->pnonce_len = eap_eke_pnonce_len(sess->mac); 752*5b9c547cSRui Paulo if (sess->pnonce_len < 0) 753*5b9c547cSRui Paulo return -1; 754*5b9c547cSRui Paulo sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac); 755*5b9c547cSRui Paulo if (sess->pnonce_ps_len < 0) 756*5b9c547cSRui Paulo return -1; 757*5b9c547cSRui Paulo 758*5b9c547cSRui Paulo return 0; 759*5b9c547cSRui Paulo } 760*5b9c547cSRui Paulo 761*5b9c547cSRui Paulo 762*5b9c547cSRui Paulo void eap_eke_session_clean(struct eap_eke_session *sess) 763*5b9c547cSRui Paulo { 764*5b9c547cSRui Paulo os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN); 765*5b9c547cSRui Paulo os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN); 766*5b9c547cSRui Paulo os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN); 767*5b9c547cSRui Paulo os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN); 768*5b9c547cSRui Paulo } 769