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