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