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