1 /* 2 * EAP peer/server: EAP-SIM/AKA/AKA' shared routines 3 * Copyright (c) 2004-2008, Jouni Malinen <j (at) 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 "wpabuf.h" 19 #include "crypto/aes_wrap.h" 20 #include "crypto/crypto.h" 21 #include "crypto/sha1.h" 22 #include "crypto/sha256.h" 23 #include "crypto/random.h" 24 #include "eap_common/eap_defs.h" 25 #include "eap_common/eap_sim_common.h" 26 27 28 static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen) 29 { 30 return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen); 31 } 32 33 34 void eap_sim_derive_mk(const u8 *identity, size_t identity_len, 35 const u8 *nonce_mt, u16 selected_version, 36 const u8 *ver_list, size_t ver_list_len, 37 int num_chal, const u8 *kc, u8 *mk) 38 { 39 u8 sel_ver[2]; 40 const unsigned char *addr[5]; 41 size_t len[5]; 42 43 addr[0] = identity; 44 len[0] = identity_len; 45 addr[1] = kc; 46 len[1] = num_chal * EAP_SIM_KC_LEN; 47 addr[2] = nonce_mt; 48 len[2] = EAP_SIM_NONCE_MT_LEN; 49 addr[3] = ver_list; 50 len[3] = ver_list_len; 51 addr[4] = sel_ver; 52 len[4] = 2; 53 54 WPA_PUT_BE16(sel_ver, selected_version); 55 56 /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ 57 sha1_vector(5, addr, len, mk); 58 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); 59 } 60 61 62 void eap_aka_derive_mk(const u8 *identity, size_t identity_len, 63 const u8 *ik, const u8 *ck, u8 *mk) 64 { 65 const u8 *addr[3]; 66 size_t len[3]; 67 68 addr[0] = identity; 69 len[0] = identity_len; 70 addr[1] = ik; 71 len[1] = EAP_AKA_IK_LEN; 72 addr[2] = ck; 73 len[2] = EAP_AKA_CK_LEN; 74 75 /* MK = SHA1(Identity|IK|CK) */ 76 sha1_vector(3, addr, len, mk); 77 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN); 78 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN); 79 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN); 80 } 81 82 83 int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk) 84 { 85 u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN + 86 EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos; 87 if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) { 88 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); 89 return -1; 90 } 91 pos = buf; 92 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); 93 pos += EAP_SIM_K_ENCR_LEN; 94 os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN); 95 pos += EAP_SIM_K_AUT_LEN; 96 os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN); 97 pos += EAP_SIM_KEYING_DATA_LEN; 98 os_memcpy(emsk, pos, EAP_EMSK_LEN); 99 100 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr", 101 k_encr, EAP_SIM_K_ENCR_LEN); 102 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut", 103 k_aut, EAP_SIM_K_AUT_LEN); 104 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)", 105 msk, EAP_SIM_KEYING_DATA_LEN); 106 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); 107 os_memset(buf, 0, sizeof(buf)); 108 109 return 0; 110 } 111 112 113 int eap_sim_derive_keys_reauth(u16 _counter, 114 const u8 *identity, size_t identity_len, 115 const u8 *nonce_s, const u8 *mk, u8 *msk, 116 u8 *emsk) 117 { 118 u8 xkey[SHA1_MAC_LEN]; 119 u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32]; 120 u8 counter[2]; 121 const u8 *addr[4]; 122 size_t len[4]; 123 124 while (identity_len > 0 && identity[identity_len - 1] == 0) { 125 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null " 126 "character from the end of identity"); 127 identity_len--; 128 } 129 addr[0] = identity; 130 len[0] = identity_len; 131 addr[1] = counter; 132 len[1] = 2; 133 addr[2] = nonce_s; 134 len[2] = EAP_SIM_NONCE_S_LEN; 135 addr[3] = mk; 136 len[3] = EAP_SIM_MK_LEN; 137 138 WPA_PUT_BE16(counter, _counter); 139 140 wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth"); 141 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 142 identity, identity_len); 143 wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2); 144 wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s, 145 EAP_SIM_NONCE_S_LEN); 146 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); 147 148 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */ 149 sha1_vector(4, addr, len, xkey); 150 wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN); 151 152 if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) { 153 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); 154 return -1; 155 } 156 if (msk) { 157 os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN); 158 wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)", 159 msk, EAP_SIM_KEYING_DATA_LEN); 160 } 161 if (emsk) { 162 os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN); 163 wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); 164 } 165 os_memset(buf, 0, sizeof(buf)); 166 167 return 0; 168 } 169 170 171 int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req, 172 const u8 *mac, const u8 *extra, size_t extra_len) 173 { 174 unsigned char hmac[SHA1_MAC_LEN]; 175 const u8 *addr[2]; 176 size_t len[2]; 177 u8 *tmp; 178 179 if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || 180 mac < wpabuf_head_u8(req) || 181 mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) 182 return -1; 183 184 tmp = os_malloc(wpabuf_len(req)); 185 if (tmp == NULL) 186 return -1; 187 188 addr[0] = tmp; 189 len[0] = wpabuf_len(req); 190 addr[1] = extra; 191 len[1] = extra_len; 192 193 /* HMAC-SHA1-128 */ 194 os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); 195 os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); 196 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", 197 tmp, wpabuf_len(req)); 198 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data", 199 extra, extra_len); 200 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut", 201 k_aut, EAP_SIM_K_AUT_LEN); 202 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); 203 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC", 204 hmac, EAP_SIM_MAC_LEN); 205 os_free(tmp); 206 207 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; 208 } 209 210 211 void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, 212 const u8 *extra, size_t extra_len) 213 { 214 unsigned char hmac[SHA1_MAC_LEN]; 215 const u8 *addr[2]; 216 size_t len[2]; 217 218 addr[0] = msg; 219 len[0] = msg_len; 220 addr[1] = extra; 221 len[1] = extra_len; 222 223 /* HMAC-SHA1-128 */ 224 os_memset(mac, 0, EAP_SIM_MAC_LEN); 225 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len); 226 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data", 227 extra, extra_len); 228 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut", 229 k_aut, EAP_SIM_K_AUT_LEN); 230 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); 231 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); 232 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC", 233 mac, EAP_SIM_MAC_LEN); 234 } 235 236 237 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) 238 static void prf_prime(const u8 *k, const char *seed1, 239 const u8 *seed2, size_t seed2_len, 240 const u8 *seed3, size_t seed3_len, 241 u8 *res, size_t res_len) 242 { 243 const u8 *addr[5]; 244 size_t len[5]; 245 u8 hash[SHA256_MAC_LEN]; 246 u8 iter; 247 248 /* 249 * PRF'(K,S) = T1 | T2 | T3 | T4 | ... 250 * T1 = HMAC-SHA-256 (K, S | 0x01) 251 * T2 = HMAC-SHA-256 (K, T1 | S | 0x02) 252 * T3 = HMAC-SHA-256 (K, T2 | S | 0x03) 253 * T4 = HMAC-SHA-256 (K, T3 | S | 0x04) 254 * ... 255 */ 256 257 addr[0] = hash; 258 len[0] = 0; 259 addr[1] = (const u8 *) seed1; 260 len[1] = os_strlen(seed1); 261 addr[2] = seed2; 262 len[2] = seed2_len; 263 addr[3] = seed3; 264 len[3] = seed3_len; 265 addr[4] = &iter; 266 len[4] = 1; 267 268 iter = 0; 269 while (res_len) { 270 size_t hlen; 271 iter++; 272 hmac_sha256_vector(k, 32, 5, addr, len, hash); 273 len[0] = SHA256_MAC_LEN; 274 hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len; 275 os_memcpy(res, hash, hlen); 276 res += hlen; 277 res_len -= hlen; 278 } 279 } 280 281 282 void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len, 283 const u8 *ik, const u8 *ck, u8 *k_encr, 284 u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk) 285 { 286 u8 key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN]; 287 u8 keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN + 288 EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN]; 289 u8 *pos; 290 291 /* 292 * MK = PRF'(IK'|CK',"EAP-AKA'"|Identity) 293 * K_encr = MK[0..127] 294 * K_aut = MK[128..383] 295 * K_re = MK[384..639] 296 * MSK = MK[640..1151] 297 * EMSK = MK[1152..1663] 298 */ 299 300 os_memcpy(key, ik, EAP_AKA_IK_LEN); 301 os_memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN); 302 303 prf_prime(key, "EAP-AKA'", identity, identity_len, NULL, 0, 304 keys, sizeof(keys)); 305 306 pos = keys; 307 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); 308 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_encr", 309 k_encr, EAP_SIM_K_ENCR_LEN); 310 pos += EAP_SIM_K_ENCR_LEN; 311 312 os_memcpy(k_aut, pos, EAP_AKA_PRIME_K_AUT_LEN); 313 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_aut", 314 k_aut, EAP_AKA_PRIME_K_AUT_LEN); 315 pos += EAP_AKA_PRIME_K_AUT_LEN; 316 317 os_memcpy(k_re, pos, EAP_AKA_PRIME_K_RE_LEN); 318 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_re", 319 k_re, EAP_AKA_PRIME_K_RE_LEN); 320 pos += EAP_AKA_PRIME_K_RE_LEN; 321 322 os_memcpy(msk, pos, EAP_MSK_LEN); 323 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); 324 pos += EAP_MSK_LEN; 325 326 os_memcpy(emsk, pos, EAP_EMSK_LEN); 327 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); 328 } 329 330 331 int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, 332 const u8 *identity, size_t identity_len, 333 const u8 *nonce_s, u8 *msk, u8 *emsk) 334 { 335 u8 seed3[2 + EAP_SIM_NONCE_S_LEN]; 336 u8 keys[EAP_MSK_LEN + EAP_EMSK_LEN]; 337 u8 *pos; 338 339 /* 340 * MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S) 341 * MSK = MK[0..511] 342 * EMSK = MK[512..1023] 343 */ 344 345 WPA_PUT_BE16(seed3, counter); 346 os_memcpy(seed3 + 2, nonce_s, EAP_SIM_NONCE_S_LEN); 347 348 prf_prime(k_re, "EAP-AKA' re-auth", identity, identity_len, 349 seed3, sizeof(seed3), 350 keys, sizeof(keys)); 351 352 pos = keys; 353 os_memcpy(msk, pos, EAP_MSK_LEN); 354 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); 355 pos += EAP_MSK_LEN; 356 357 os_memcpy(emsk, pos, EAP_EMSK_LEN); 358 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); 359 360 os_memset(keys, 0, sizeof(keys)); 361 362 return 0; 363 } 364 365 366 int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, 367 const u8 *mac, const u8 *extra, size_t extra_len) 368 { 369 unsigned char hmac[SHA256_MAC_LEN]; 370 const u8 *addr[2]; 371 size_t len[2]; 372 u8 *tmp; 373 374 if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || 375 mac < wpabuf_head_u8(req) || 376 mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) 377 return -1; 378 379 tmp = os_malloc(wpabuf_len(req)); 380 if (tmp == NULL) 381 return -1; 382 383 addr[0] = tmp; 384 len[0] = wpabuf_len(req); 385 addr[1] = extra; 386 len[1] = extra_len; 387 388 /* HMAC-SHA-256-128 */ 389 os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); 390 os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); 391 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - msg", 392 tmp, wpabuf_len(req)); 393 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - extra data", 394 extra, extra_len); 395 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Verify MAC - K_aut", 396 k_aut, EAP_AKA_PRIME_K_AUT_LEN); 397 hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); 398 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC: MAC", 399 hmac, EAP_SIM_MAC_LEN); 400 os_free(tmp); 401 402 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; 403 } 404 405 406 void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, 407 u8 *mac, const u8 *extra, size_t extra_len) 408 { 409 unsigned char hmac[SHA256_MAC_LEN]; 410 const u8 *addr[2]; 411 size_t len[2]; 412 413 addr[0] = msg; 414 len[0] = msg_len; 415 addr[1] = extra; 416 len[1] = extra_len; 417 418 /* HMAC-SHA-256-128 */ 419 os_memset(mac, 0, EAP_SIM_MAC_LEN); 420 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - msg", msg, msg_len); 421 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - extra data", 422 extra, extra_len); 423 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Add MAC - K_aut", 424 k_aut, EAP_AKA_PRIME_K_AUT_LEN); 425 hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); 426 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); 427 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC", 428 mac, EAP_SIM_MAC_LEN); 429 } 430 431 432 void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, 433 const u8 *network_name, 434 size_t network_name_len) 435 { 436 u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN]; 437 u8 hash[SHA256_MAC_LEN]; 438 const u8 *addr[5]; 439 size_t len[5]; 440 u8 fc; 441 u8 l0[2], l1[2]; 442 443 /* 3GPP TS 33.402 V8.0.0 444 * (CK', IK') = F(CK, IK, <access network identity>) 445 */ 446 /* TODO: CK', IK' generation should really be moved into the actual 447 * AKA procedure with network name passed in there and option to use 448 * AMF separation bit = 1 (3GPP TS 33.401). */ 449 450 /* Change Request 33.402 CR 0033 to version 8.1.1 from 451 * 3GPP TSG-SA WG3 Meeting #53 in September 2008: 452 * 453 * CK' || IK' = HMAC-SHA-256(Key, S) 454 * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln 455 * Key = CK || IK 456 * FC = 0x20 457 * P0 = access network identity (3GPP TS 24.302) 458 * L0 = length of acceess network identity (2 octets, big endian) 459 * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0 460 * L1 = 0x00 0x06 461 */ 462 463 fc = 0x20; 464 465 wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)"); 466 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN); 467 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN); 468 wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc); 469 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity", 470 network_name, network_name_len); 471 wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6); 472 473 os_memcpy(key, ck, EAP_AKA_CK_LEN); 474 os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN); 475 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK", 476 key, sizeof(key)); 477 478 addr[0] = &fc; 479 len[0] = 1; 480 addr[1] = network_name; 481 len[1] = network_name_len; 482 WPA_PUT_BE16(l0, network_name_len); 483 addr[2] = l0; 484 len[2] = 2; 485 addr[3] = sqn_ak; 486 len[3] = 6; 487 WPA_PUT_BE16(l1, 6); 488 addr[4] = l1; 489 len[4] = 2; 490 491 hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash); 492 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')", 493 hash, sizeof(hash)); 494 495 os_memcpy(ck, hash, EAP_AKA_CK_LEN); 496 os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN); 497 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN); 498 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN); 499 } 500 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ 501 502 503 int eap_sim_parse_attr(const u8 *start, const u8 *end, 504 struct eap_sim_attrs *attr, int aka, int encr) 505 { 506 const u8 *pos = start, *apos; 507 size_t alen, plen, i, list_len; 508 509 os_memset(attr, 0, sizeof(*attr)); 510 attr->id_req = NO_ID_REQ; 511 attr->notification = -1; 512 attr->counter = -1; 513 attr->selected_version = -1; 514 attr->client_error_code = -1; 515 516 while (pos < end) { 517 if (pos + 2 > end) { 518 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)"); 519 return -1; 520 } 521 wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d", 522 pos[0], pos[1] * 4); 523 if (pos + pos[1] * 4 > end) { 524 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow " 525 "(pos=%p len=%d end=%p)", 526 pos, pos[1] * 4, end); 527 return -1; 528 } 529 if (pos[1] == 0) { 530 wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow"); 531 return -1; 532 } 533 apos = pos + 2; 534 alen = pos[1] * 4 - 2; 535 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", 536 apos, alen); 537 538 switch (pos[0]) { 539 case EAP_SIM_AT_RAND: 540 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND"); 541 apos += 2; 542 alen -= 2; 543 if ((!aka && (alen % GSM_RAND_LEN)) || 544 (aka && alen != EAP_AKA_RAND_LEN)) { 545 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND" 546 " (len %lu)", 547 (unsigned long) alen); 548 return -1; 549 } 550 attr->rand = apos; 551 attr->num_chal = alen / GSM_RAND_LEN; 552 break; 553 case EAP_SIM_AT_AUTN: 554 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN"); 555 if (!aka) { 556 wpa_printf(MSG_DEBUG, "EAP-SIM: " 557 "Unexpected AT_AUTN"); 558 return -1; 559 } 560 apos += 2; 561 alen -= 2; 562 if (alen != EAP_AKA_AUTN_LEN) { 563 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN" 564 " (len %lu)", 565 (unsigned long) alen); 566 return -1; 567 } 568 attr->autn = apos; 569 break; 570 case EAP_SIM_AT_PADDING: 571 if (!encr) { 572 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 573 "AT_PADDING"); 574 return -1; 575 } 576 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING"); 577 for (i = 2; i < alen; i++) { 578 if (apos[i] != 0) { 579 wpa_printf(MSG_INFO, "EAP-SIM: (encr) " 580 "AT_PADDING used a non-zero" 581 " padding byte"); 582 wpa_hexdump(MSG_DEBUG, "EAP-SIM: " 583 "(encr) padding bytes", 584 apos + 2, alen - 2); 585 return -1; 586 } 587 } 588 break; 589 case EAP_SIM_AT_NONCE_MT: 590 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT"); 591 if (alen != 2 + EAP_SIM_NONCE_MT_LEN) { 592 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 593 "AT_NONCE_MT length"); 594 return -1; 595 } 596 attr->nonce_mt = apos + 2; 597 break; 598 case EAP_SIM_AT_PERMANENT_ID_REQ: 599 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ"); 600 attr->id_req = PERMANENT_ID; 601 break; 602 case EAP_SIM_AT_MAC: 603 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC"); 604 if (alen != 2 + EAP_SIM_MAC_LEN) { 605 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC " 606 "length"); 607 return -1; 608 } 609 attr->mac = apos + 2; 610 break; 611 case EAP_SIM_AT_NOTIFICATION: 612 if (alen != 2) { 613 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 614 "AT_NOTIFICATION length %lu", 615 (unsigned long) alen); 616 return -1; 617 } 618 attr->notification = apos[0] * 256 + apos[1]; 619 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d", 620 attr->notification); 621 break; 622 case EAP_SIM_AT_ANY_ID_REQ: 623 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ"); 624 attr->id_req = ANY_ID; 625 break; 626 case EAP_SIM_AT_IDENTITY: 627 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY"); 628 plen = WPA_GET_BE16(apos); 629 apos += 2; 630 alen -= 2; 631 if (plen > alen) { 632 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 633 "AT_IDENTITY (Actual Length %lu, " 634 "remaining length %lu)", 635 (unsigned long) plen, 636 (unsigned long) alen); 637 return -1; 638 } 639 640 attr->identity = apos; 641 attr->identity_len = plen; 642 break; 643 case EAP_SIM_AT_VERSION_LIST: 644 if (aka) { 645 wpa_printf(MSG_DEBUG, "EAP-AKA: " 646 "Unexpected AT_VERSION_LIST"); 647 return -1; 648 } 649 list_len = apos[0] * 256 + apos[1]; 650 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST"); 651 if (list_len < 2 || list_len > alen - 2) { 652 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " 653 "AT_VERSION_LIST (list_len=%lu " 654 "attr_len=%lu)", 655 (unsigned long) list_len, 656 (unsigned long) alen); 657 return -1; 658 } 659 attr->version_list = apos + 2; 660 attr->version_list_len = list_len; 661 break; 662 case EAP_SIM_AT_SELECTED_VERSION: 663 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION"); 664 if (alen != 2) { 665 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 666 "AT_SELECTED_VERSION length %lu", 667 (unsigned long) alen); 668 return -1; 669 } 670 attr->selected_version = apos[0] * 256 + apos[1]; 671 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION " 672 "%d", attr->selected_version); 673 break; 674 case EAP_SIM_AT_FULLAUTH_ID_REQ: 675 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ"); 676 attr->id_req = FULLAUTH_ID; 677 break; 678 case EAP_SIM_AT_COUNTER: 679 if (!encr) { 680 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 681 "AT_COUNTER"); 682 return -1; 683 } 684 if (alen != 2) { 685 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 686 "AT_COUNTER (alen=%lu)", 687 (unsigned long) alen); 688 return -1; 689 } 690 attr->counter = apos[0] * 256 + apos[1]; 691 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d", 692 attr->counter); 693 break; 694 case EAP_SIM_AT_COUNTER_TOO_SMALL: 695 if (!encr) { 696 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 697 "AT_COUNTER_TOO_SMALL"); 698 return -1; 699 } 700 if (alen != 2) { 701 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 702 "AT_COUNTER_TOO_SMALL (alen=%lu)", 703 (unsigned long) alen); 704 return -1; 705 } 706 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 707 "AT_COUNTER_TOO_SMALL"); 708 attr->counter_too_small = 1; 709 break; 710 case EAP_SIM_AT_NONCE_S: 711 if (!encr) { 712 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 713 "AT_NONCE_S"); 714 return -1; 715 } 716 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 717 "AT_NONCE_S"); 718 if (alen != 2 + EAP_SIM_NONCE_S_LEN) { 719 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " 720 "AT_NONCE_S (alen=%lu)", 721 (unsigned long) alen); 722 return -1; 723 } 724 attr->nonce_s = apos + 2; 725 break; 726 case EAP_SIM_AT_CLIENT_ERROR_CODE: 727 if (alen != 2) { 728 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 729 "AT_CLIENT_ERROR_CODE length %lu", 730 (unsigned long) alen); 731 return -1; 732 } 733 attr->client_error_code = apos[0] * 256 + apos[1]; 734 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE " 735 "%d", attr->client_error_code); 736 break; 737 case EAP_SIM_AT_IV: 738 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV"); 739 if (alen != 2 + EAP_SIM_MAC_LEN) { 740 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV " 741 "length %lu", (unsigned long) alen); 742 return -1; 743 } 744 attr->iv = apos + 2; 745 break; 746 case EAP_SIM_AT_ENCR_DATA: 747 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA"); 748 attr->encr_data = apos + 2; 749 attr->encr_data_len = alen - 2; 750 if (attr->encr_data_len % 16) { 751 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 752 "AT_ENCR_DATA length %lu", 753 (unsigned long) 754 attr->encr_data_len); 755 return -1; 756 } 757 break; 758 case EAP_SIM_AT_NEXT_PSEUDONYM: 759 if (!encr) { 760 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 761 "AT_NEXT_PSEUDONYM"); 762 return -1; 763 } 764 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 765 "AT_NEXT_PSEUDONYM"); 766 plen = apos[0] * 256 + apos[1]; 767 if (plen > alen - 2) { 768 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" 769 " AT_NEXT_PSEUDONYM (actual" 770 " len %lu, attr len %lu)", 771 (unsigned long) plen, 772 (unsigned long) alen); 773 return -1; 774 } 775 attr->next_pseudonym = pos + 4; 776 attr->next_pseudonym_len = plen; 777 break; 778 case EAP_SIM_AT_NEXT_REAUTH_ID: 779 if (!encr) { 780 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " 781 "AT_NEXT_REAUTH_ID"); 782 return -1; 783 } 784 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " 785 "AT_NEXT_REAUTH_ID"); 786 plen = apos[0] * 256 + apos[1]; 787 if (plen > alen - 2) { 788 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" 789 " AT_NEXT_REAUTH_ID (actual" 790 " len %lu, attr len %lu)", 791 (unsigned long) plen, 792 (unsigned long) alen); 793 return -1; 794 } 795 attr->next_reauth_id = pos + 4; 796 attr->next_reauth_id_len = plen; 797 break; 798 case EAP_SIM_AT_RES: 799 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES"); 800 attr->res_len_bits = WPA_GET_BE16(apos); 801 apos += 2; 802 alen -= 2; 803 if (!aka || alen < EAP_AKA_MIN_RES_LEN || 804 alen > EAP_AKA_MAX_RES_LEN) { 805 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES " 806 "(len %lu)", 807 (unsigned long) alen); 808 return -1; 809 } 810 attr->res = apos; 811 attr->res_len = alen; 812 break; 813 case EAP_SIM_AT_AUTS: 814 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS"); 815 if (!aka) { 816 wpa_printf(MSG_DEBUG, "EAP-SIM: " 817 "Unexpected AT_AUTS"); 818 return -1; 819 } 820 if (alen != EAP_AKA_AUTS_LEN) { 821 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS" 822 " (len %lu)", 823 (unsigned long) alen); 824 return -1; 825 } 826 attr->auts = apos; 827 break; 828 case EAP_SIM_AT_CHECKCODE: 829 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_CHECKCODE"); 830 if (!aka) { 831 wpa_printf(MSG_DEBUG, "EAP-SIM: " 832 "Unexpected AT_CHECKCODE"); 833 return -1; 834 } 835 apos += 2; 836 alen -= 2; 837 if (alen != 0 && alen != EAP_AKA_CHECKCODE_LEN && 838 alen != EAP_AKA_PRIME_CHECKCODE_LEN) { 839 wpa_printf(MSG_INFO, "EAP-AKA: Invalid " 840 "AT_CHECKCODE (len %lu)", 841 (unsigned long) alen); 842 return -1; 843 } 844 attr->checkcode = apos; 845 attr->checkcode_len = alen; 846 break; 847 case EAP_SIM_AT_RESULT_IND: 848 if (encr) { 849 wpa_printf(MSG_ERROR, "EAP-SIM: Encrypted " 850 "AT_RESULT_IND"); 851 return -1; 852 } 853 if (alen != 2) { 854 wpa_printf(MSG_INFO, "EAP-SIM: Invalid " 855 "AT_RESULT_IND (alen=%lu)", 856 (unsigned long) alen); 857 return -1; 858 } 859 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND"); 860 attr->result_ind = 1; 861 break; 862 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) 863 case EAP_SIM_AT_KDF_INPUT: 864 if (aka != 2) { 865 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " 866 "AT_KDF_INPUT"); 867 return -1; 868 } 869 870 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF_INPUT"); 871 plen = WPA_GET_BE16(apos); 872 apos += 2; 873 alen -= 2; 874 if (plen > alen) { 875 wpa_printf(MSG_INFO, "EAP-AKA': Invalid " 876 "AT_KDF_INPUT (Actual Length %lu, " 877 "remaining length %lu)", 878 (unsigned long) plen, 879 (unsigned long) alen); 880 return -1; 881 } 882 attr->kdf_input = apos; 883 attr->kdf_input_len = plen; 884 break; 885 case EAP_SIM_AT_KDF: 886 if (aka != 2) { 887 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " 888 "AT_KDF"); 889 return -1; 890 } 891 892 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF"); 893 if (alen != 2) { 894 wpa_printf(MSG_INFO, "EAP-AKA': Invalid " 895 "AT_KDF (len %lu)", 896 (unsigned long) alen); 897 return -1; 898 } 899 if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) { 900 wpa_printf(MSG_DEBUG, "EAP-AKA': Too many " 901 "AT_KDF attributes - ignore this"); 902 continue; 903 } 904 attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos); 905 attr->kdf_count++; 906 break; 907 case EAP_SIM_AT_BIDDING: 908 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING"); 909 if (alen != 2) { 910 wpa_printf(MSG_INFO, "EAP-AKA: Invalid " 911 "AT_BIDDING (len %lu)", 912 (unsigned long) alen); 913 return -1; 914 } 915 attr->bidding = apos; 916 break; 917 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ 918 default: 919 if (pos[0] < 128) { 920 wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized " 921 "non-skippable attribute %d", 922 pos[0]); 923 return -1; 924 } 925 926 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable" 927 " attribute %d ignored", pos[0]); 928 break; 929 } 930 931 pos += pos[1] * 4; 932 } 933 934 wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully " 935 "(aka=%d encr=%d)", aka, encr); 936 937 return 0; 938 } 939 940 941 u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, 942 size_t encr_data_len, const u8 *iv, 943 struct eap_sim_attrs *attr, int aka) 944 { 945 u8 *decrypted; 946 947 if (!iv) { 948 wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); 949 return NULL; 950 } 951 952 decrypted = os_malloc(encr_data_len); 953 if (decrypted == NULL) 954 return NULL; 955 os_memcpy(decrypted, encr_data, encr_data_len); 956 957 if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) { 958 os_free(decrypted); 959 return NULL; 960 } 961 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", 962 decrypted, encr_data_len); 963 964 if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr, 965 aka, 1)) { 966 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " 967 "decrypted AT_ENCR_DATA"); 968 os_free(decrypted); 969 return NULL; 970 } 971 972 return decrypted; 973 } 974 975 976 #define EAP_SIM_INIT_LEN 128 977 978 struct eap_sim_msg { 979 struct wpabuf *buf; 980 size_t mac, iv, encr; /* index from buf */ 981 int type; 982 }; 983 984 985 struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype) 986 { 987 struct eap_sim_msg *msg; 988 struct eap_hdr *eap; 989 u8 *pos; 990 991 msg = os_zalloc(sizeof(*msg)); 992 if (msg == NULL) 993 return NULL; 994 995 msg->type = type; 996 msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN); 997 if (msg->buf == NULL) { 998 os_free(msg); 999 return NULL; 1000 } 1001 eap = wpabuf_put(msg->buf, sizeof(*eap)); 1002 eap->code = code; 1003 eap->identifier = id; 1004 1005 pos = wpabuf_put(msg->buf, 4); 1006 *pos++ = type; 1007 *pos++ = subtype; 1008 *pos++ = 0; /* Reserved */ 1009 *pos++ = 0; /* Reserved */ 1010 1011 return msg; 1012 } 1013 1014 1015 struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, 1016 const u8 *extra, size_t extra_len) 1017 { 1018 struct eap_hdr *eap; 1019 struct wpabuf *buf; 1020 1021 if (msg == NULL) 1022 return NULL; 1023 1024 eap = wpabuf_mhead(msg->buf); 1025 eap->length = host_to_be16(wpabuf_len(msg->buf)); 1026 1027 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) 1028 if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) { 1029 eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf), 1030 wpabuf_len(msg->buf), 1031 (u8 *) wpabuf_mhead(msg->buf) + 1032 msg->mac, extra, extra_len); 1033 } else 1034 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ 1035 if (k_aut && msg->mac) { 1036 eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf), 1037 wpabuf_len(msg->buf), 1038 (u8 *) wpabuf_mhead(msg->buf) + msg->mac, 1039 extra, extra_len); 1040 } 1041 1042 buf = msg->buf; 1043 os_free(msg); 1044 return buf; 1045 } 1046 1047 1048 void eap_sim_msg_free(struct eap_sim_msg *msg) 1049 { 1050 if (msg) { 1051 wpabuf_free(msg->buf); 1052 os_free(msg); 1053 } 1054 } 1055 1056 1057 u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, 1058 const u8 *data, size_t len) 1059 { 1060 int attr_len = 2 + len; 1061 int pad_len; 1062 u8 *start; 1063 1064 if (msg == NULL) 1065 return NULL; 1066 1067 pad_len = (4 - attr_len % 4) % 4; 1068 attr_len += pad_len; 1069 if (wpabuf_resize(&msg->buf, attr_len)) 1070 return NULL; 1071 start = wpabuf_put(msg->buf, 0); 1072 wpabuf_put_u8(msg->buf, attr); 1073 wpabuf_put_u8(msg->buf, attr_len / 4); 1074 wpabuf_put_data(msg->buf, data, len); 1075 if (pad_len) 1076 os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); 1077 return start; 1078 } 1079 1080 1081 u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value, 1082 const u8 *data, size_t len) 1083 { 1084 int attr_len = 4 + len; 1085 int pad_len; 1086 u8 *start; 1087 1088 if (msg == NULL) 1089 return NULL; 1090 1091 pad_len = (4 - attr_len % 4) % 4; 1092 attr_len += pad_len; 1093 if (wpabuf_resize(&msg->buf, attr_len)) 1094 return NULL; 1095 start = wpabuf_put(msg->buf, 0); 1096 wpabuf_put_u8(msg->buf, attr); 1097 wpabuf_put_u8(msg->buf, attr_len / 4); 1098 wpabuf_put_be16(msg->buf, value); 1099 if (data) 1100 wpabuf_put_data(msg->buf, data, len); 1101 else 1102 wpabuf_put(msg->buf, len); 1103 if (pad_len) 1104 os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); 1105 return start; 1106 } 1107 1108 1109 u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr) 1110 { 1111 u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN); 1112 if (pos) 1113 msg->mac = (pos - wpabuf_head_u8(msg->buf)) + 4; 1114 return pos; 1115 } 1116 1117 1118 int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, 1119 u8 attr_encr) 1120 { 1121 u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); 1122 if (pos == NULL) 1123 return -1; 1124 msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4; 1125 if (random_get_bytes(wpabuf_mhead_u8(msg->buf) + msg->iv, 1126 EAP_SIM_IV_LEN)) { 1127 msg->iv = 0; 1128 return -1; 1129 } 1130 1131 pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); 1132 if (pos == NULL) { 1133 msg->iv = 0; 1134 return -1; 1135 } 1136 msg->encr = pos - wpabuf_head_u8(msg->buf); 1137 1138 return 0; 1139 } 1140 1141 1142 int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) 1143 { 1144 size_t encr_len; 1145 1146 if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0) 1147 return -1; 1148 1149 encr_len = wpabuf_len(msg->buf) - msg->encr - 4; 1150 if (encr_len % 16) { 1151 u8 *pos; 1152 int pad_len = 16 - (encr_len % 16); 1153 if (pad_len < 4) { 1154 wpa_printf(MSG_WARNING, "EAP-SIM: " 1155 "eap_sim_msg_add_encr_end - invalid pad_len" 1156 " %d", pad_len); 1157 return -1; 1158 } 1159 wpa_printf(MSG_DEBUG, " *AT_PADDING"); 1160 pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); 1161 if (pos == NULL) 1162 return -1; 1163 os_memset(pos + 4, 0, pad_len - 4); 1164 encr_len += pad_len; 1165 } 1166 wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", 1167 (unsigned long) encr_len); 1168 wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1; 1169 return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv, 1170 wpabuf_mhead_u8(msg->buf) + msg->encr + 4, 1171 encr_len); 1172 } 1173 1174 1175 void eap_sim_report_notification(void *msg_ctx, int notification, int aka) 1176 { 1177 #ifndef CONFIG_NO_STDOUT_DEBUG 1178 const char *type = aka ? "AKA" : "SIM"; 1179 #endif /* CONFIG_NO_STDOUT_DEBUG */ 1180 1181 switch (notification) { 1182 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH: 1183 wpa_printf(MSG_WARNING, "EAP-%s: General failure " 1184 "notification (after authentication)", type); 1185 break; 1186 case EAP_SIM_TEMPORARILY_DENIED: 1187 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " 1188 "User has been temporarily denied access to the " 1189 "requested service", type); 1190 break; 1191 case EAP_SIM_NOT_SUBSCRIBED: 1192 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " 1193 "User has not subscribed to the requested service", 1194 type); 1195 break; 1196 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH: 1197 wpa_printf(MSG_WARNING, "EAP-%s: General failure " 1198 "notification (before authentication)", type); 1199 break; 1200 case EAP_SIM_SUCCESS: 1201 wpa_printf(MSG_INFO, "EAP-%s: Successful authentication " 1202 "notification", type); 1203 break; 1204 default: 1205 if (notification >= 32768) { 1206 wpa_printf(MSG_INFO, "EAP-%s: Unrecognized " 1207 "non-failure notification %d", 1208 type, notification); 1209 } else { 1210 wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized " 1211 "failure notification %d", 1212 type, notification); 1213 } 1214 } 1215 } 1216