1/* 2 * EAP peer: EAP-SIM/AKA shared routines 3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "eap_i.h" 19#include "sha1.h" 20#include "crypto.h" 21#include "aes_wrap.h" 22#include "eap_sim_common.h" 23 24 25static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen) 26{ 27 return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen); 28} 29 30 31void eap_sim_derive_mk(const u8 *identity, size_t identity_len, 32 const u8 *nonce_mt, u16 selected_version, 33 const u8 *ver_list, size_t ver_list_len, 34 int num_chal, const u8 *kc, u8 *mk) 35{ 36 u8 sel_ver[2]; 37 const unsigned char *addr[5]; 38 size_t len[5]; 39 40 addr[0] = identity; 41 len[0] = identity_len; 42 addr[1] = kc; 43 len[1] = num_chal * EAP_SIM_KC_LEN; 44 addr[2] = nonce_mt; 45 len[2] = EAP_SIM_NONCE_MT_LEN; 46 addr[3] = ver_list; 47 len[3] = ver_list_len; 48 addr[4] = sel_ver; 49 len[4] = 2; 50 51 WPA_PUT_BE16(sel_ver, selected_version); 52 53 /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ 54 sha1_vector(5, addr, len, mk); 55 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); 56} 57 58 59void eap_aka_derive_mk(const u8 *identity, size_t identity_len, 60 const u8 *ik, const u8 *ck, u8 *mk) 61{ 62 const u8 *addr[3]; 63 size_t len[3]; 64 65 addr[0] = identity; 66 len[0] = identity_len; 67 addr[1] = ik; 68 len[1] = EAP_AKA_IK_LEN; 69 addr[2] = ck; 70 len[2] = EAP_AKA_CK_LEN; 71 72 /* MK = SHA1(Identity|IK|CK) */ 73 sha1_vector(3, addr, len, mk); 74 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN); 75 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN); 76 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN); 77} 78 79 80int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk) 81{ 82 u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN + 83 EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos; 84 if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) { 85 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); 86 return -1; 87 } 88 pos = buf; 89 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); 90 pos += EAP_SIM_K_ENCR_LEN; 91 os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN); 92 pos += EAP_SIM_K_AUT_LEN; 93 os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN); 94 pos += EAP_SIM_KEYING_DATA_LEN; 95 os_memcpy(emsk, pos, EAP_EMSK_LEN); 96 97 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr", 98 k_encr, EAP_SIM_K_ENCR_LEN); 99 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut", 100 k_aut, EAP_SIM_K_AUT_LEN); 101 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)", 102 msk, EAP_SIM_KEYING_DATA_LEN); 103 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); 104 os_memset(buf, 0, sizeof(buf)); 105 106 return 0; 107} 108 109 110int eap_sim_derive_keys_reauth(u16 _counter, 111 const u8 *identity, size_t identity_len, 112 const u8 *nonce_s, const u8 *mk, u8 *msk, 113 u8 *emsk) 114{ 115 u8 xkey[SHA1_MAC_LEN]; 116 u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32]; 117 u8 counter[2]; 118 const u8 *addr[4]; 119 size_t len[4]; 120 121 while (identity_len > 0 && identity[identity_len - 1] == 0) { 122 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null " 123 "character from the end of identity"); 124 identity_len--; 125 } 126 addr[0] = identity; 127 len[0] = identity_len; 128 addr[1] = counter; 129 len[1] = 2; 130 addr[2] = nonce_s; 131 len[2] = EAP_SIM_NONCE_S_LEN; 132 addr[3] = mk; 133 len[3] = EAP_SIM_MK_LEN; 134 135 WPA_PUT_BE16(counter, _counter); 136 137 wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth"); 138 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 139 identity, identity_len); 140 wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2); 141 wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s, 142 EAP_SIM_NONCE_S_LEN); 143 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); 144 145 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */ 146 sha1_vector(4, addr, len, xkey); 147 wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN); 148 149 if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) { 150 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); 151 return -1; 152 } 153 if (msk) { 154 os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN); 155 wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)", 156 msk, EAP_SIM_KEYING_DATA_LEN); 157 } 158 if (emsk) { 159 os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN); 160 wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); 161 } 162 os_memset(buf, 0, sizeof(buf)); 163 164 return 0; 165} 166 167 168int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len, 169 const u8 *mac, const u8 *extra, size_t extra_len) 170{ 171 unsigned char hmac[SHA1_MAC_LEN]; 172 const u8 *addr[2]; 173 size_t len[2]; 174 u8 *tmp; 175 176 if (mac == NULL || req_len < EAP_SIM_MAC_LEN || mac < req || 177 mac > req + req_len - EAP_SIM_MAC_LEN) 178 return -1; 179 180 tmp = os_malloc(req_len); 181 if (tmp == NULL) 182 return -1; 183 184 addr[0] = tmp; 185 len[0] = req_len; 186 addr[1] = extra; 187 len[1] = extra_len; 188 189 /* HMAC-SHA1-128 */ 190 os_memcpy(tmp, req, req_len); 191 os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN); 192 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len); 193 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data", 194 extra, extra_len); 195 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut", 196 k_aut, EAP_SIM_K_AUT_LEN); 197 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); 198 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC", 199 hmac, EAP_SIM_MAC_LEN); 200 os_free(tmp); 201 202 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; 203} 204 205 206void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac, 207 const u8 *extra, size_t extra_len) 208{ 209 unsigned char hmac[SHA1_MAC_LEN]; 210 const u8 *addr[2]; 211 size_t len[2]; 212 213 addr[0] = msg; 214 len[0] = msg_len; 215 addr[1] = extra; 216 len[1] = extra_len; 217 218 /* HMAC-SHA1-128 */ 219 os_memset(mac, 0, EAP_SIM_MAC_LEN); 220 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len); 221 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data", 222 extra, extra_len); 223 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut", 224 k_aut, EAP_SIM_K_AUT_LEN); 225 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); 226 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); 227 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC", 228 mac, EAP_SIM_MAC_LEN); 229} 230 231 232int eap_sim_parse_attr(const u8 *start, const u8 *end, 233 struct eap_sim_attrs *attr, int aka, int encr) 234{ 235 const u8 *pos = start, *apos; 236 size_t alen, plen, i, list_len; 237 238 os_memset(attr, 0, sizeof(*attr)); 239 attr->id_req = NO_ID_REQ; 240 attr->notification = -1; 241 attr->counter = -1; 242 attr->selected_version = -1; 243 attr->client_error_code = -1; 244 245 while (pos < end) { 246 if (pos + 2 > end) { 247 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)"); 248 return -1; 249 } 250 wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d", 251 pos[0], pos[1] * 4); 252 if (pos + pos[1] * 4 > end) { 253 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow " 254 "(pos=%p len=%d end=%p)", 255 pos, pos[1] * 4, end); 256 return -1; 257 } 258 if (pos[1] == 0) { 259 wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow"); 260 return -1; 261 } 262 apos = pos + 2; 263 alen = pos[1] * 4 - 2; 264 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", 265 apos, alen); 266 267 switch (pos[0]) { 268 case EAP_SIM_AT_RAND: 269 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND"); 270 apos += 2; 271 alen -= 2; 272 if ((!aka && (alen % GSM_RAND_LEN)) || 273 (aka && alen != EAP_AKA_RAND_LEN)) { 274 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND" 275 " (len %lu)", 276 (unsigned long) alen); 277 return -1; 278 } 279 attr->rand = apos; 280 attr->num_chal = alen / GSM_RAND_LEN; 281 break; 282 case EAP_SIM_AT_AUTN: 283 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN"); 284 if (!aka) { 285 wpa_printf(MSG_DEBUG, "EAP-SIM: " 286 "Unexpected AT_AUTN"); 287 return -1; 288 } 289 apos += 2; 290 alen -= 2; 291 if (alen != EAP_AKA_AUTN_LEN) { 292 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN" 293 " (len %lu)", 294 (unsigned long) alen); 295 return -1; 296 } 297 attr->autn = apos; 298 break; 299 case EAP_SIM_AT_PADDING: 300 if (!encr) { 301 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 302 "AT_PADDING"); 303 return -1; 304 } 305 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING"); 306 for (i = 2; i < alen; i++) { 307 if (apos[i] != 0) { 308 wpa_printf(MSG_INFO, "EAP-SIM: (encr) " 309 "AT_PADDING used a non-zero" 310 " padding byte"); 311 wpa_hexdump(MSG_DEBUG, "EAP-SIM: " 312 "(encr) padding bytes", 313 apos + 2, alen - 2); 314 return -1; 315 } 316 } 317 break; 318 case EAP_SIM_AT_NONCE_MT: 319 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT"); 320 if (alen != 2 + EAP_SIM_NONCE_MT_LEN) { 321 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 322 "AT_NONCE_MT length"); 323 return -1; 324 } 325 attr->nonce_mt = apos + 2; 326 break; 327 case EAP_SIM_AT_PERMANENT_ID_REQ: 328 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ"); 329 attr->id_req = PERMANENT_ID; 330 break; 331 case EAP_SIM_AT_MAC: 332 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC"); 333 if (alen != 2 + EAP_SIM_MAC_LEN) { 334 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC " 335 "length"); 336 return -1; 337 } 338 attr->mac = apos + 2; 339 break; 340 case EAP_SIM_AT_NOTIFICATION: 341 if (alen != 2) { 342 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 343 "AT_NOTIFICATION length %lu", 344 (unsigned long) alen); 345 return -1; 346 } 347 attr->notification = apos[0] * 256 + apos[1]; 348 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d", 349 attr->notification); 350 break; 351 case EAP_SIM_AT_ANY_ID_REQ: 352 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ"); 353 attr->id_req = ANY_ID; 354 break; 355 case EAP_SIM_AT_IDENTITY: 356 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY"); 357 attr->identity = apos + 2; 358 attr->identity_len = alen - 2; 359 break; 360 case EAP_SIM_AT_VERSION_LIST: 361 if (aka) { 362 wpa_printf(MSG_DEBUG, "EAP-AKA: " 363 "Unexpected AT_VERSION_LIST"); 364 return -1; 365 } 366 list_len = apos[0] * 256 + apos[1]; 367 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST"); 368 if (list_len < 2 || list_len > alen - 2) { 369 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " 370 "AT_VERSION_LIST (list_len=%lu " 371 "attr_len=%lu)", 372 (unsigned long) list_len, 373 (unsigned long) alen); 374 return -1; 375 } 376 attr->version_list = apos + 2; 377 attr->version_list_len = list_len; 378 break; 379 case EAP_SIM_AT_SELECTED_VERSION: 380 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION"); 381 if (alen != 2) { 382 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 383 "AT_SELECTED_VERSION length %lu", 384 (unsigned long) alen); 385 return -1; 386 } 387 attr->selected_version = apos[0] * 256 + apos[1]; 388 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION " 389 "%d", attr->selected_version); 390 break; 391 case EAP_SIM_AT_FULLAUTH_ID_REQ: 392 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ"); 393 attr->id_req = FULLAUTH_ID; 394 break; 395 case EAP_SIM_AT_COUNTER: 396 if (!encr) { 397 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 398 "AT_COUNTER"); 399 return -1; 400 } 401 if (alen != 2) { 402 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 403 "AT_COUNTER (alen=%lu)", 404 (unsigned long) alen); 405 return -1; 406 } 407 attr->counter = apos[0] * 256 + apos[1]; 408 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d", 409 attr->counter); 410 break; 411 case EAP_SIM_AT_COUNTER_TOO_SMALL: 412 if (!encr) { 413 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 414 "AT_COUNTER_TOO_SMALL"); 415 return -1; 416 } 417 if (alen != 2) { 418 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 419 "AT_COUNTER_TOO_SMALL (alen=%lu)", 420 (unsigned long) alen); 421 return -1; 422 } 423 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 424 "AT_COUNTER_TOO_SMALL"); 425 attr->counter_too_small = 1; 426 break; 427 case EAP_SIM_AT_NONCE_S: 428 if (!encr) { 429 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 430 "AT_NONCE_S"); 431 return -1; 432 } 433 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 434 "AT_NONCE_S"); 435 if (alen != 2 + EAP_SIM_NONCE_S_LEN) { 436 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 437 "AT_NONCE_S (alen=%lu)", 438 (unsigned long) alen); 439 return -1; 440 } 441 attr->nonce_s = apos + 2; 442 break; 443 case EAP_SIM_AT_CLIENT_ERROR_CODE: 444 if (alen != 2) { 445 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 446 "AT_CLIENT_ERROR_CODE length %lu", 447 (unsigned long) alen); 448 return -1; 449 } 450 attr->client_error_code = apos[0] * 256 + apos[1]; 451 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE " 452 "%d", attr->client_error_code); 453 break; 454 case EAP_SIM_AT_IV: 455 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV"); 456 if (alen != 2 + EAP_SIM_MAC_LEN) { 457 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV " 458 "length %lu", (unsigned long) alen); 459 return -1; 460 } 461 attr->iv = apos + 2; 462 break; 463 case EAP_SIM_AT_ENCR_DATA: 464 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA"); 465 attr->encr_data = apos + 2; 466 attr->encr_data_len = alen - 2; 467 if (attr->encr_data_len % 16) { 468 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 469 "AT_ENCR_DATA length %lu", 470 (unsigned long) 471 attr->encr_data_len); 472 return -1; 473 } 474 break; 475 case EAP_SIM_AT_NEXT_PSEUDONYM: 476 if (!encr) { 477 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 478 "AT_NEXT_PSEUDONYM"); 479 return -1; 480 } 481 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 482 "AT_NEXT_PSEUDONYM"); 483 plen = apos[0] * 256 + apos[1]; 484 if (plen > alen - 2) { 485 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" 486 " AT_NEXT_PSEUDONYM (actual" 487 " len %lu, attr len %lu)", 488 (unsigned long) plen, 489 (unsigned long) alen); 490 return -1; 491 } 492 attr->next_pseudonym = pos + 4; 493 attr->next_pseudonym_len = plen; 494 break; 495 case EAP_SIM_AT_NEXT_REAUTH_ID: 496 if (!encr) { 497 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 498 "AT_NEXT_REAUTH_ID"); 499 return -1; 500 } 501 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 502 "AT_NEXT_REAUTH_ID"); 503 plen = apos[0] * 256 + apos[1]; 504 if (plen > alen - 2) { 505 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" 506 " AT_NEXT_REAUTH_ID (actual" 507 " len %lu, attr len %lu)", 508 (unsigned long) plen, 509 (unsigned long) alen); 510 return -1; 511 } 512 attr->next_reauth_id = pos + 4; 513 attr->next_reauth_id_len = plen; 514 break; 515 case EAP_SIM_AT_RES: 516 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES"); 517 apos += 2; 518 alen -= 2; 519 if (!aka || alen < EAP_AKA_MIN_RES_LEN || 520 alen > EAP_AKA_MAX_RES_LEN) { 521 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES " 522 "(len %lu)", 523 (unsigned long) alen); 524 return -1; 525 } 526 attr->res = apos; 527 attr->res_len = alen; 528 break; 529 case EAP_SIM_AT_AUTS: 530 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS"); 531 if (!aka) { 532 wpa_printf(MSG_DEBUG, "EAP-SIM: " 533 "Unexpected AT_AUTS"); 534 return -1; 535 } 536 if (alen != EAP_AKA_AUTS_LEN) { 537 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS" 538 " (len %lu)", 539 (unsigned long) alen); 540 return -1; 541 } 542 attr->auts = apos; 543 break; 544 default: 545 if (pos[0] < 128) { 546 wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized " 547 "non-skippable attribute %d", 548 pos[0]); 549 return -1; 550 } 551 552 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable" 553 " attribute %d ignored", pos[0]); 554 break; 555 } 556 557 pos += pos[1] * 4; 558 } 559 560 wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully " 561 "(aka=%d encr=%d)", aka, encr); 562 563 return 0; 564} 565 566 567u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, 568 size_t encr_data_len, const u8 *iv, 569 struct eap_sim_attrs *attr, int aka) 570{ 571 u8 *decrypted; 572 573 if (!iv) { 574 wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); 575 return NULL; 576 } 577 578 decrypted = os_malloc(encr_data_len); 579 if (decrypted == NULL) 580 return NULL; 581 os_memcpy(decrypted, encr_data, encr_data_len); 582 583 aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len); 584 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", 585 decrypted, encr_data_len); 586 587 if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr, 588 aka, 1)) { 589 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " 590 "decrypted AT_ENCR_DATA"); 591 os_free(decrypted); 592 return NULL; 593 } 594 595 return decrypted; 596} 597 598 599#define EAP_SIM_INIT_LEN 128 600 601struct eap_sim_msg { 602 u8 *buf; 603 size_t buf_len, used; 604 size_t mac, iv, encr; /* index from buf */ 605}; 606 607 608struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype) 609{ 610 struct eap_sim_msg *msg; 611 struct eap_hdr *eap; 612 u8 *pos; 613 614 msg = os_zalloc(sizeof(*msg)); 615 if (msg == NULL) 616 return NULL; 617 618 msg->buf = os_zalloc(EAP_SIM_INIT_LEN); 619 if (msg->buf == NULL) { 620 os_free(msg); 621 return NULL; 622 } 623 msg->buf_len = EAP_SIM_INIT_LEN; 624 eap = (struct eap_hdr *) msg->buf; 625 eap->code = code; 626 eap->identifier = id; 627 msg->used = sizeof(*eap); 628 629 pos = (u8 *) (eap + 1); 630 *pos++ = type; 631 *pos++ = subtype; 632 *pos++ = 0; /* Reserved */ 633 *pos++ = 0; /* Reserved */ 634 msg->used += 4; 635 636 return msg; 637} 638 639 640u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut, 641 const u8 *extra, size_t extra_len) 642{ 643 struct eap_hdr *eap; 644 u8 *buf; 645 646 if (msg == NULL) 647 return NULL; 648 649 eap = (struct eap_hdr *) msg->buf; 650 eap->length = host_to_be16(msg->used); 651 652 if (k_aut && msg->mac) { 653 eap_sim_add_mac(k_aut, msg->buf, msg->used, 654 msg->buf + msg->mac, extra, extra_len); 655 } 656 657 *len = msg->used; 658 buf = msg->buf; 659 os_free(msg); 660 return buf; 661} 662 663 664void eap_sim_msg_free(struct eap_sim_msg *msg) 665{ 666 if (msg) { 667 os_free(msg->buf); 668 os_free(msg); 669 } 670} 671 672 673static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len) 674{ 675 if (msg->used + add_len > msg->buf_len) { 676 u8 *nbuf = os_realloc(msg->buf, msg->used + add_len); 677 if (nbuf == NULL) 678 return -1; 679 msg->buf = nbuf; 680 msg->buf_len = msg->used + add_len; 681 } 682 return 0; 683} 684 685 686u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, 687 const u8 *data, size_t len) 688{ 689 int attr_len = 2 + len; 690 int pad_len; 691 u8 *start, *pos; 692 693 if (msg == NULL) 694 return NULL; 695 696 pad_len = (4 - attr_len % 4) % 4; 697 attr_len += pad_len; 698 if (eap_sim_msg_resize(msg, attr_len)) 699 return NULL; 700 start = pos = msg->buf + msg->used; 701 *pos++ = attr; 702 *pos++ = attr_len / 4; 703 os_memcpy(pos, data, len); 704 if (pad_len) { 705 pos += len; 706 os_memset(pos, 0, pad_len); 707 } 708 msg->used += attr_len; 709 return start; 710} 711 712 713u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value, 714 const u8 *data, size_t len) 715{ 716 int attr_len = 4 + len; 717 int pad_len; 718 u8 *start, *pos; 719 720 if (msg == NULL) 721 return NULL; 722 723 pad_len = (4 - attr_len % 4) % 4; 724 attr_len += pad_len; 725 if (eap_sim_msg_resize(msg, attr_len)) 726 return NULL; 727 start = pos = msg->buf + msg->used; 728 *pos++ = attr; 729 *pos++ = attr_len / 4; 730 WPA_PUT_BE16(pos, value); 731 pos += 2; 732 if (data) 733 os_memcpy(pos, data, len); 734 if (pad_len) { 735 pos += len; 736 os_memset(pos, 0, pad_len); 737 } 738 msg->used += attr_len; 739 return start; 740} 741 742 743u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr) 744{ 745 u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN); 746 if (pos) 747 msg->mac = (pos - msg->buf) + 4; 748 return pos; 749} 750 751 752int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, 753 u8 attr_encr) 754{ 755 u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); 756 if (pos == NULL) 757 return -1; 758 msg->iv = (pos - msg->buf) + 4; 759 if (hostapd_get_rand(msg->buf + msg->iv, EAP_SIM_IV_LEN)) { 760 msg->iv = 0; 761 return -1; 762 } 763 764 pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); 765 if (pos == NULL) { 766 msg->iv = 0; 767 return -1; 768 } 769 msg->encr = pos - msg->buf; 770 771 return 0; 772} 773 774 775int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) 776{ 777 size_t encr_len; 778 779 if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0) 780 return -1; 781 782 encr_len = msg->used - msg->encr - 4; 783 if (encr_len % 16) { 784 u8 *pos; 785 int pad_len = 16 - (encr_len % 16); 786 if (pad_len < 4) { 787 wpa_printf(MSG_WARNING, "EAP-SIM: " 788 "eap_sim_msg_add_encr_end - invalid pad_len" 789 " %d", pad_len); 790 return -1; 791 } 792 wpa_printf(MSG_DEBUG, " *AT_PADDING"); 793 pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); 794 if (pos == NULL) 795 return -1; 796 os_memset(pos + 4, 0, pad_len - 4); 797 encr_len += pad_len; 798 } 799 wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", 800 (unsigned long) encr_len); 801 msg->buf[msg->encr + 1] = encr_len / 4 + 1; 802 aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv, 803 msg->buf + msg->encr + 4, encr_len); 804 805 return 0; 806} 807 808 809void eap_sim_report_notification(void *msg_ctx, int notification, int aka) 810{ 811#ifndef CONFIG_NO_STDOUT_DEBUG 812 const char *type = aka ? "AKA" : "SIM"; 813#endif /* CONFIG_NO_STDOUT_DEBUG */ 814 815 switch (notification) { 816 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH: 817 wpa_printf(MSG_WARNING, "EAP-%s: General failure " 818 "notification (after authentication)", type); 819 break; 820 case EAP_SIM_TEMPORARILY_DENIED: 821 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " 822 "User has been temporarily denied access to the " 823 "requested service", type); 824 break; 825 case EAP_SIM_NOT_SUBSCRIBED: 826 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " 827 "User has not subscribed to the requested service", 828 type); 829 break; 830 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH: 831 wpa_printf(MSG_WARNING, "EAP-%s: General failure " 832 "notification (before authentication)", type); 833 break; 834 case EAP_SIM_SUCCESS: 835 wpa_printf(MSG_INFO, "EAP-%s: Successful authentication " 836 "notification", type); 837 break; 838 default: 839 if (notification >= 32768) { 840 wpa_printf(MSG_INFO, "EAP-%s: Unrecognized " 841 "non-failure notification %d", 842 type, notification); 843 } else { 844 wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized " 845 "failure notification %d", 846 type, notification); 847 } 848 } 849} 850