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