00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "wpabuf.h"
00019 #include "crypto/aes_wrap.h"
00020 #include "crypto/crypto.h"
00021 #include "crypto/sha1.h"
00022 #include "crypto/sha256.h"
00023 #include "eap_common/eap_defs.h"
00024 #include "eap_common/eap_sim_common.h"
00025
00026
00027 static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
00028 {
00029 return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
00030 }
00031
00032
00033 void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
00034 const u8 *nonce_mt, u16 selected_version,
00035 const u8 *ver_list, size_t ver_list_len,
00036 int num_chal, const u8 *kc, u8 *mk)
00037 {
00038 u8 sel_ver[2];
00039 const unsigned char *addr[5];
00040 size_t len[5];
00041
00042 addr[0] = identity;
00043 len[0] = identity_len;
00044 addr[1] = kc;
00045 len[1] = num_chal * EAP_SIM_KC_LEN;
00046 addr[2] = nonce_mt;
00047 len[2] = EAP_SIM_NONCE_MT_LEN;
00048 addr[3] = ver_list;
00049 len[3] = ver_list_len;
00050 addr[4] = sel_ver;
00051 len[4] = 2;
00052
00053 WPA_PUT_BE16(sel_ver, selected_version);
00054
00055
00056 sha1_vector(5, addr, len, mk);
00057 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
00058 }
00059
00060
00061 void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
00062 const u8 *ik, const u8 *ck, u8 *mk)
00063 {
00064 const u8 *addr[3];
00065 size_t len[3];
00066
00067 addr[0] = identity;
00068 len[0] = identity_len;
00069 addr[1] = ik;
00070 len[1] = EAP_AKA_IK_LEN;
00071 addr[2] = ck;
00072 len[2] = EAP_AKA_CK_LEN;
00073
00074
00075 sha1_vector(3, addr, len, mk);
00076 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
00077 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
00078 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
00079 }
00080
00081
00082 int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
00083 {
00084 u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
00085 EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
00086 if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
00087 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
00088 return -1;
00089 }
00090 pos = buf;
00091 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
00092 pos += EAP_SIM_K_ENCR_LEN;
00093 os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
00094 pos += EAP_SIM_K_AUT_LEN;
00095 os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
00096 pos += EAP_SIM_KEYING_DATA_LEN;
00097 os_memcpy(emsk, pos, EAP_EMSK_LEN);
00098
00099 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
00100 k_encr, EAP_SIM_K_ENCR_LEN);
00101 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
00102 k_aut, EAP_SIM_K_AUT_LEN);
00103 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
00104 msk, EAP_SIM_KEYING_DATA_LEN);
00105 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
00106 os_memset(buf, 0, sizeof(buf));
00107
00108 return 0;
00109 }
00110
00111
00112 int eap_sim_derive_keys_reauth(u16 _counter,
00113 const u8 *identity, size_t identity_len,
00114 const u8 *nonce_s, const u8 *mk, u8 *msk,
00115 u8 *emsk)
00116 {
00117 u8 xkey[SHA1_MAC_LEN];
00118 u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
00119 u8 counter[2];
00120 const u8 *addr[4];
00121 size_t len[4];
00122
00123 while (identity_len > 0 && identity[identity_len - 1] == 0) {
00124 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null "
00125 "character from the end of identity");
00126 identity_len--;
00127 }
00128 addr[0] = identity;
00129 len[0] = identity_len;
00130 addr[1] = counter;
00131 len[1] = 2;
00132 addr[2] = nonce_s;
00133 len[2] = EAP_SIM_NONCE_S_LEN;
00134 addr[3] = mk;
00135 len[3] = EAP_SIM_MK_LEN;
00136
00137 WPA_PUT_BE16(counter, _counter);
00138
00139 wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
00140 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
00141 identity, identity_len);
00142 wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2);
00143 wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s,
00144 EAP_SIM_NONCE_S_LEN);
00145 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
00146
00147
00148 sha1_vector(4, addr, len, xkey);
00149 wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
00150
00151 if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
00152 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
00153 return -1;
00154 }
00155 if (msk) {
00156 os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
00157 wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
00158 msk, EAP_SIM_KEYING_DATA_LEN);
00159 }
00160 if (emsk) {
00161 os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
00162 wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
00163 }
00164 os_memset(buf, 0, sizeof(buf));
00165
00166 return 0;
00167 }
00168
00169
00170 int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req,
00171 const u8 *mac, const u8 *extra, size_t extra_len)
00172 {
00173 unsigned char hmac[SHA1_MAC_LEN];
00174 const u8 *addr[2];
00175 size_t len[2];
00176 u8 *tmp;
00177
00178 if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN ||
00179 mac < wpabuf_head_u8(req) ||
00180 mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN)
00181 return -1;
00182
00183 tmp = os_malloc(wpabuf_len(req));
00184 if (tmp == NULL)
00185 return -1;
00186
00187 addr[0] = tmp;
00188 len[0] = wpabuf_len(req);
00189 addr[1] = extra;
00190 len[1] = extra_len;
00191
00192
00193 os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req));
00194 os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN);
00195 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg",
00196 tmp, wpabuf_len(req));
00197 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
00198 extra, extra_len);
00199 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
00200 k_aut, EAP_SIM_K_AUT_LEN);
00201 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
00202 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
00203 hmac, EAP_SIM_MAC_LEN);
00204 os_free(tmp);
00205
00206 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
00207 }
00208
00209
00210 void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac,
00211 const u8 *extra, size_t extra_len)
00212 {
00213 unsigned char hmac[SHA1_MAC_LEN];
00214 const u8 *addr[2];
00215 size_t len[2];
00216
00217 addr[0] = msg;
00218 len[0] = msg_len;
00219 addr[1] = extra;
00220 len[1] = extra_len;
00221
00222
00223 os_memset(mac, 0, EAP_SIM_MAC_LEN);
00224 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
00225 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
00226 extra, extra_len);
00227 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
00228 k_aut, EAP_SIM_K_AUT_LEN);
00229 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
00230 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
00231 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
00232 mac, EAP_SIM_MAC_LEN);
00233 }
00234
00235
00236 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
00237 static void prf_prime(const u8 *k, const char *seed1,
00238 const u8 *seed2, size_t seed2_len,
00239 const u8 *seed3, size_t seed3_len,
00240 u8 *res, size_t res_len)
00241 {
00242 const u8 *addr[5];
00243 size_t len[5];
00244 u8 hash[SHA256_MAC_LEN];
00245 u8 iter;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 addr[0] = hash;
00257 len[0] = 0;
00258 addr[1] = (const u8 *) seed1;
00259 len[1] = os_strlen(seed1);
00260 addr[2] = seed2;
00261 len[2] = seed2_len;
00262 addr[3] = seed3;
00263 len[3] = seed3_len;
00264 addr[4] = &iter;
00265 len[4] = 1;
00266
00267 iter = 0;
00268 while (res_len) {
00269 size_t hlen;
00270 iter++;
00271 hmac_sha256_vector(k, 32, 5, addr, len, hash);
00272 len[0] = SHA256_MAC_LEN;
00273 hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len;
00274 os_memcpy(res, hash, hlen);
00275 res += hlen;
00276 res_len -= hlen;
00277 }
00278 }
00279
00280
00281 void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len,
00282 const u8 *ik, const u8 *ck, u8 *k_encr,
00283 u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk)
00284 {
00285 u8 key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN];
00286 u8 keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN +
00287 EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN];
00288 u8 *pos;
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 os_memcpy(key, ik, EAP_AKA_IK_LEN);
00300 os_memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN);
00301
00302 prf_prime(key, "EAP-AKA'", identity, identity_len, NULL, 0,
00303 keys, sizeof(keys));
00304
00305 pos = keys;
00306 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
00307 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_encr",
00308 k_encr, EAP_SIM_K_ENCR_LEN);
00309 pos += EAP_SIM_K_ENCR_LEN;
00310
00311 os_memcpy(k_aut, pos, EAP_AKA_PRIME_K_AUT_LEN);
00312 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_aut",
00313 k_aut, EAP_AKA_PRIME_K_AUT_LEN);
00314 pos += EAP_AKA_PRIME_K_AUT_LEN;
00315
00316 os_memcpy(k_re, pos, EAP_AKA_PRIME_K_RE_LEN);
00317 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_re",
00318 k_re, EAP_AKA_PRIME_K_RE_LEN);
00319 pos += EAP_AKA_PRIME_K_RE_LEN;
00320
00321 os_memcpy(msk, pos, EAP_MSK_LEN);
00322 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN);
00323 pos += EAP_MSK_LEN;
00324
00325 os_memcpy(emsk, pos, EAP_EMSK_LEN);
00326 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN);
00327 }
00328
00329
00330 int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter,
00331 const u8 *identity, size_t identity_len,
00332 const u8 *nonce_s, u8 *msk, u8 *emsk)
00333 {
00334 u8 seed3[2 + EAP_SIM_NONCE_S_LEN];
00335 u8 keys[EAP_MSK_LEN + EAP_EMSK_LEN];
00336 u8 *pos;
00337
00338
00339
00340
00341
00342
00343
00344 WPA_PUT_BE16(seed3, counter);
00345 os_memcpy(seed3 + 2, nonce_s, EAP_SIM_NONCE_S_LEN);
00346
00347 prf_prime(k_re, "EAP-AKA' re-auth", identity, identity_len,
00348 seed3, sizeof(seed3),
00349 keys, sizeof(keys));
00350
00351 pos = keys;
00352 os_memcpy(msk, pos, EAP_MSK_LEN);
00353 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN);
00354 pos += EAP_MSK_LEN;
00355
00356 os_memcpy(emsk, pos, EAP_EMSK_LEN);
00357 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN);
00358
00359 os_memset(keys, 0, sizeof(keys));
00360
00361 return 0;
00362 }
00363
00364
00365 int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req,
00366 const u8 *mac, const u8 *extra, size_t extra_len)
00367 {
00368 unsigned char hmac[SHA256_MAC_LEN];
00369 const u8 *addr[2];
00370 size_t len[2];
00371 u8 *tmp;
00372
00373 if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN ||
00374 mac < wpabuf_head_u8(req) ||
00375 mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN)
00376 return -1;
00377
00378 tmp = os_malloc(wpabuf_len(req));
00379 if (tmp == NULL)
00380 return -1;
00381
00382 addr[0] = tmp;
00383 len[0] = wpabuf_len(req);
00384 addr[1] = extra;
00385 len[1] = extra_len;
00386
00387
00388 os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req));
00389 os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN);
00390 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - msg",
00391 tmp, wpabuf_len(req));
00392 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - extra data",
00393 extra, extra_len);
00394 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Verify MAC - K_aut",
00395 k_aut, EAP_AKA_PRIME_K_AUT_LEN);
00396 hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac);
00397 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC: MAC",
00398 hmac, EAP_SIM_MAC_LEN);
00399 os_free(tmp);
00400
00401 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
00402 }
00403
00404
00405 void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len,
00406 u8 *mac, const u8 *extra, size_t extra_len)
00407 {
00408 unsigned char hmac[SHA256_MAC_LEN];
00409 const u8 *addr[2];
00410 size_t len[2];
00411
00412 addr[0] = msg;
00413 len[0] = msg_len;
00414 addr[1] = extra;
00415 len[1] = extra_len;
00416
00417
00418 os_memset(mac, 0, EAP_SIM_MAC_LEN);
00419 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - msg", msg, msg_len);
00420 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - extra data",
00421 extra, extra_len);
00422 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Add MAC - K_aut",
00423 k_aut, EAP_AKA_PRIME_K_AUT_LEN);
00424 hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac);
00425 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
00426 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC",
00427 mac, EAP_SIM_MAC_LEN);
00428 }
00429
00430
00431 void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
00432 const u8 *network_name,
00433 size_t network_name_len)
00434 {
00435 u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN];
00436 u8 hash[SHA256_MAC_LEN];
00437 const u8 *addr[5];
00438 size_t len[5];
00439 u8 fc;
00440 u8 l0[2], l1[2];
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 fc = 0x20;
00463
00464 wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)");
00465 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN);
00466 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN);
00467 wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc);
00468 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity",
00469 network_name, network_name_len);
00470 wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6);
00471
00472 os_memcpy(key, ck, EAP_AKA_CK_LEN);
00473 os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN);
00474 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK",
00475 key, sizeof(key));
00476
00477 addr[0] = &fc;
00478 len[0] = 1;
00479 addr[1] = network_name;
00480 len[1] = network_name_len;
00481 WPA_PUT_BE16(l0, network_name_len);
00482 addr[2] = l0;
00483 len[2] = 2;
00484 addr[3] = sqn_ak;
00485 len[3] = 6;
00486 WPA_PUT_BE16(l1, 6);
00487 addr[4] = l1;
00488 len[4] = 2;
00489
00490 hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash);
00491 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')",
00492 hash, sizeof(hash));
00493
00494 os_memcpy(ck, hash, EAP_AKA_CK_LEN);
00495 os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN);
00496 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN);
00497 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN);
00498 }
00499 #endif
00500
00501
00502 int eap_sim_parse_attr(const u8 *start, const u8 *end,
00503 struct eap_sim_attrs *attr, int aka, int encr)
00504 {
00505 const u8 *pos = start, *apos;
00506 size_t alen, plen, i, list_len;
00507
00508 os_memset(attr, 0, sizeof(*attr));
00509 attr->id_req = NO_ID_REQ;
00510 attr->notification = -1;
00511 attr->counter = -1;
00512 attr->selected_version = -1;
00513 attr->client_error_code = -1;
00514
00515 while (pos < end) {
00516 if (pos + 2 > end) {
00517 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)");
00518 return -1;
00519 }
00520 wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d",
00521 pos[0], pos[1] * 4);
00522 if (pos + pos[1] * 4 > end) {
00523 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow "
00524 "(pos=%p len=%d end=%p)",
00525 pos, pos[1] * 4, end);
00526 return -1;
00527 }
00528 if (pos[1] == 0) {
00529 wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow");
00530 return -1;
00531 }
00532 apos = pos + 2;
00533 alen = pos[1] * 4 - 2;
00534 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",
00535 apos, alen);
00536
00537 switch (pos[0]) {
00538 case EAP_SIM_AT_RAND:
00539 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND");
00540 apos += 2;
00541 alen -= 2;
00542 if ((!aka && (alen % GSM_RAND_LEN)) ||
00543 (aka && alen != EAP_AKA_RAND_LEN)) {
00544 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
00545 " (len %lu)",
00546 (unsigned long) alen);
00547 return -1;
00548 }
00549 attr->rand = apos;
00550 attr->num_chal = alen / GSM_RAND_LEN;
00551 break;
00552 case EAP_SIM_AT_AUTN:
00553 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN");
00554 if (!aka) {
00555 wpa_printf(MSG_DEBUG, "EAP-SIM: "
00556 "Unexpected AT_AUTN");
00557 return -1;
00558 }
00559 apos += 2;
00560 alen -= 2;
00561 if (alen != EAP_AKA_AUTN_LEN) {
00562 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
00563 " (len %lu)",
00564 (unsigned long) alen);
00565 return -1;
00566 }
00567 attr->autn = apos;
00568 break;
00569 case EAP_SIM_AT_PADDING:
00570 if (!encr) {
00571 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00572 "AT_PADDING");
00573 return -1;
00574 }
00575 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING");
00576 for (i = 2; i < alen; i++) {
00577 if (apos[i] != 0) {
00578 wpa_printf(MSG_INFO, "EAP-SIM: (encr) "
00579 "AT_PADDING used a non-zero"
00580 " padding byte");
00581 wpa_hexdump(MSG_DEBUG, "EAP-SIM: "
00582 "(encr) padding bytes",
00583 apos + 2, alen - 2);
00584 return -1;
00585 }
00586 }
00587 break;
00588 case EAP_SIM_AT_NONCE_MT:
00589 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT");
00590 if (alen != 2 + EAP_SIM_NONCE_MT_LEN) {
00591 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00592 "AT_NONCE_MT length");
00593 return -1;
00594 }
00595 attr->nonce_mt = apos + 2;
00596 break;
00597 case EAP_SIM_AT_PERMANENT_ID_REQ:
00598 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ");
00599 attr->id_req = PERMANENT_ID;
00600 break;
00601 case EAP_SIM_AT_MAC:
00602 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC");
00603 if (alen != 2 + EAP_SIM_MAC_LEN) {
00604 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC "
00605 "length");
00606 return -1;
00607 }
00608 attr->mac = apos + 2;
00609 break;
00610 case EAP_SIM_AT_NOTIFICATION:
00611 if (alen != 2) {
00612 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00613 "AT_NOTIFICATION length %lu",
00614 (unsigned long) alen);
00615 return -1;
00616 }
00617 attr->notification = apos[0] * 256 + apos[1];
00618 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d",
00619 attr->notification);
00620 break;
00621 case EAP_SIM_AT_ANY_ID_REQ:
00622 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ");
00623 attr->id_req = ANY_ID;
00624 break;
00625 case EAP_SIM_AT_IDENTITY:
00626 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY");
00627 plen = WPA_GET_BE16(apos);
00628 apos += 2;
00629 alen -= 2;
00630 if (plen > alen) {
00631 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00632 "AT_IDENTITY (Actual Length %lu, "
00633 "remaining length %lu)",
00634 (unsigned long) plen,
00635 (unsigned long) alen);
00636 return -1;
00637 }
00638
00639 attr->identity = apos;
00640 attr->identity_len = plen;
00641 break;
00642 case EAP_SIM_AT_VERSION_LIST:
00643 if (aka) {
00644 wpa_printf(MSG_DEBUG, "EAP-AKA: "
00645 "Unexpected AT_VERSION_LIST");
00646 return -1;
00647 }
00648 list_len = apos[0] * 256 + apos[1];
00649 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
00650 if (list_len < 2 || list_len > alen - 2) {
00651 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
00652 "AT_VERSION_LIST (list_len=%lu "
00653 "attr_len=%lu)",
00654 (unsigned long) list_len,
00655 (unsigned long) alen);
00656 return -1;
00657 }
00658 attr->version_list = apos + 2;
00659 attr->version_list_len = list_len;
00660 break;
00661 case EAP_SIM_AT_SELECTED_VERSION:
00662 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION");
00663 if (alen != 2) {
00664 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00665 "AT_SELECTED_VERSION length %lu",
00666 (unsigned long) alen);
00667 return -1;
00668 }
00669 attr->selected_version = apos[0] * 256 + apos[1];
00670 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION "
00671 "%d", attr->selected_version);
00672 break;
00673 case EAP_SIM_AT_FULLAUTH_ID_REQ:
00674 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ");
00675 attr->id_req = FULLAUTH_ID;
00676 break;
00677 case EAP_SIM_AT_COUNTER:
00678 if (!encr) {
00679 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00680 "AT_COUNTER");
00681 return -1;
00682 }
00683 if (alen != 2) {
00684 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
00685 "AT_COUNTER (alen=%lu)",
00686 (unsigned long) alen);
00687 return -1;
00688 }
00689 attr->counter = apos[0] * 256 + apos[1];
00690 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
00691 attr->counter);
00692 break;
00693 case EAP_SIM_AT_COUNTER_TOO_SMALL:
00694 if (!encr) {
00695 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00696 "AT_COUNTER_TOO_SMALL");
00697 return -1;
00698 }
00699 if (alen != 2) {
00700 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
00701 "AT_COUNTER_TOO_SMALL (alen=%lu)",
00702 (unsigned long) alen);
00703 return -1;
00704 }
00705 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
00706 "AT_COUNTER_TOO_SMALL");
00707 attr->counter_too_small = 1;
00708 break;
00709 case EAP_SIM_AT_NONCE_S:
00710 if (!encr) {
00711 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00712 "AT_NONCE_S");
00713 return -1;
00714 }
00715 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
00716 "AT_NONCE_S");
00717 if (alen != 2 + EAP_SIM_NONCE_S_LEN) {
00718 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
00719 "AT_NONCE_S (alen=%lu)",
00720 (unsigned long) alen);
00721 return -1;
00722 }
00723 attr->nonce_s = apos + 2;
00724 break;
00725 case EAP_SIM_AT_CLIENT_ERROR_CODE:
00726 if (alen != 2) {
00727 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00728 "AT_CLIENT_ERROR_CODE length %lu",
00729 (unsigned long) alen);
00730 return -1;
00731 }
00732 attr->client_error_code = apos[0] * 256 + apos[1];
00733 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE "
00734 "%d", attr->client_error_code);
00735 break;
00736 case EAP_SIM_AT_IV:
00737 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV");
00738 if (alen != 2 + EAP_SIM_MAC_LEN) {
00739 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV "
00740 "length %lu", (unsigned long) alen);
00741 return -1;
00742 }
00743 attr->iv = apos + 2;
00744 break;
00745 case EAP_SIM_AT_ENCR_DATA:
00746 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA");
00747 attr->encr_data = apos + 2;
00748 attr->encr_data_len = alen - 2;
00749 if (attr->encr_data_len % 16) {
00750 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00751 "AT_ENCR_DATA length %lu",
00752 (unsigned long)
00753 attr->encr_data_len);
00754 return -1;
00755 }
00756 break;
00757 case EAP_SIM_AT_NEXT_PSEUDONYM:
00758 if (!encr) {
00759 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00760 "AT_NEXT_PSEUDONYM");
00761 return -1;
00762 }
00763 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
00764 "AT_NEXT_PSEUDONYM");
00765 plen = apos[0] * 256 + apos[1];
00766 if (plen > alen - 2) {
00767 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
00768 " AT_NEXT_PSEUDONYM (actual"
00769 " len %lu, attr len %lu)",
00770 (unsigned long) plen,
00771 (unsigned long) alen);
00772 return -1;
00773 }
00774 attr->next_pseudonym = pos + 4;
00775 attr->next_pseudonym_len = plen;
00776 break;
00777 case EAP_SIM_AT_NEXT_REAUTH_ID:
00778 if (!encr) {
00779 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
00780 "AT_NEXT_REAUTH_ID");
00781 return -1;
00782 }
00783 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
00784 "AT_NEXT_REAUTH_ID");
00785 plen = apos[0] * 256 + apos[1];
00786 if (plen > alen - 2) {
00787 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
00788 " AT_NEXT_REAUTH_ID (actual"
00789 " len %lu, attr len %lu)",
00790 (unsigned long) plen,
00791 (unsigned long) alen);
00792 return -1;
00793 }
00794 attr->next_reauth_id = pos + 4;
00795 attr->next_reauth_id_len = plen;
00796 break;
00797 case EAP_SIM_AT_RES:
00798 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
00799 attr->res_len_bits = WPA_GET_BE16(apos);
00800 apos += 2;
00801 alen -= 2;
00802 if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
00803 alen > EAP_AKA_MAX_RES_LEN) {
00804 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
00805 "(len %lu)",
00806 (unsigned long) alen);
00807 return -1;
00808 }
00809 attr->res = apos;
00810 attr->res_len = alen;
00811 break;
00812 case EAP_SIM_AT_AUTS:
00813 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
00814 if (!aka) {
00815 wpa_printf(MSG_DEBUG, "EAP-SIM: "
00816 "Unexpected AT_AUTS");
00817 return -1;
00818 }
00819 if (alen != EAP_AKA_AUTS_LEN) {
00820 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
00821 " (len %lu)",
00822 (unsigned long) alen);
00823 return -1;
00824 }
00825 attr->auts = apos;
00826 break;
00827 case EAP_SIM_AT_CHECKCODE:
00828 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_CHECKCODE");
00829 if (!aka) {
00830 wpa_printf(MSG_DEBUG, "EAP-SIM: "
00831 "Unexpected AT_CHECKCODE");
00832 return -1;
00833 }
00834 apos += 2;
00835 alen -= 2;
00836 if (alen != 0 && alen != EAP_AKA_CHECKCODE_LEN &&
00837 alen != EAP_AKA_PRIME_CHECKCODE_LEN) {
00838 wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
00839 "AT_CHECKCODE (len %lu)",
00840 (unsigned long) alen);
00841 return -1;
00842 }
00843 attr->checkcode = apos;
00844 attr->checkcode_len = alen;
00845 break;
00846 case EAP_SIM_AT_RESULT_IND:
00847 if (encr) {
00848 wpa_printf(MSG_ERROR, "EAP-SIM: Encrypted "
00849 "AT_RESULT_IND");
00850 return -1;
00851 }
00852 if (alen != 2) {
00853 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
00854 "AT_RESULT_IND (alen=%lu)",
00855 (unsigned long) alen);
00856 return -1;
00857 }
00858 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND");
00859 attr->result_ind = 1;
00860 break;
00861 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
00862 case EAP_SIM_AT_KDF_INPUT:
00863 if (aka != 2) {
00864 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
00865 "AT_KDF_INPUT");
00866 return -1;
00867 }
00868
00869 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF_INPUT");
00870 plen = WPA_GET_BE16(apos);
00871 apos += 2;
00872 alen -= 2;
00873 if (plen > alen) {
00874 wpa_printf(MSG_INFO, "EAP-AKA': Invalid "
00875 "AT_KDF_INPUT (Actual Length %lu, "
00876 "remaining length %lu)",
00877 (unsigned long) plen,
00878 (unsigned long) alen);
00879 return -1;
00880 }
00881 attr->kdf_input = apos;
00882 attr->kdf_input_len = plen;
00883 break;
00884 case EAP_SIM_AT_KDF:
00885 if (aka != 2) {
00886 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
00887 "AT_KDF");
00888 return -1;
00889 }
00890
00891 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF");
00892 if (alen != 2) {
00893 wpa_printf(MSG_INFO, "EAP-AKA': Invalid "
00894 "AT_KDF (len %lu)",
00895 (unsigned long) alen);
00896 return -1;
00897 }
00898 if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) {
00899 wpa_printf(MSG_DEBUG, "EAP-AKA': Too many "
00900 "AT_KDF attributes - ignore this");
00901 continue;
00902 }
00903 attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
00904 attr->kdf_count++;
00905 break;
00906 case EAP_SIM_AT_BIDDING:
00907 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING");
00908 if (alen != 2) {
00909 wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
00910 "AT_BIDDING (len %lu)",
00911 (unsigned long) alen);
00912 return -1;
00913 }
00914 attr->bidding = apos;
00915 break;
00916 #endif
00917 default:
00918 if (pos[0] < 128) {
00919 wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
00920 "non-skippable attribute %d",
00921 pos[0]);
00922 return -1;
00923 }
00924
00925 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable"
00926 " attribute %d ignored", pos[0]);
00927 break;
00928 }
00929
00930 pos += pos[1] * 4;
00931 }
00932
00933 wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully "
00934 "(aka=%d encr=%d)", aka, encr);
00935
00936 return 0;
00937 }
00938
00939
00940 u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
00941 size_t encr_data_len, const u8 *iv,
00942 struct eap_sim_attrs *attr, int aka)
00943 {
00944 u8 *decrypted;
00945
00946 if (!iv) {
00947 wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
00948 return NULL;
00949 }
00950
00951 decrypted = os_malloc(encr_data_len);
00952 if (decrypted == NULL)
00953 return NULL;
00954 os_memcpy(decrypted, encr_data, encr_data_len);
00955
00956 if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) {
00957 os_free(decrypted);
00958 return NULL;
00959 }
00960 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
00961 decrypted, encr_data_len);
00962
00963 if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
00964 aka, 1)) {
00965 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
00966 "decrypted AT_ENCR_DATA");
00967 os_free(decrypted);
00968 return NULL;
00969 }
00970
00971 return decrypted;
00972 }
00973
00974
00975 #define EAP_SIM_INIT_LEN 128
00976
00977 struct eap_sim_msg {
00978 struct wpabuf *buf;
00979 size_t mac, iv, encr;
00980 int type;
00981 };
00982
00983
00984 struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
00985 {
00986 struct eap_sim_msg *msg;
00987 struct eap_hdr *eap;
00988 u8 *pos;
00989
00990 msg = os_zalloc(sizeof(*msg));
00991 if (msg == NULL)
00992 return NULL;
00993
00994 msg->type = type;
00995 msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN);
00996 if (msg->buf == NULL) {
00997 os_free(msg);
00998 return NULL;
00999 }
01000 eap = wpabuf_put(msg->buf, sizeof(*eap));
01001 eap->code = code;
01002 eap->identifier = id;
01003
01004 pos = wpabuf_put(msg->buf, 4);
01005 *pos++ = type;
01006 *pos++ = subtype;
01007 *pos++ = 0;
01008 *pos++ = 0;
01009
01010 return msg;
01011 }
01012
01013
01014 struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut,
01015 const u8 *extra, size_t extra_len)
01016 {
01017 struct eap_hdr *eap;
01018 struct wpabuf *buf;
01019
01020 if (msg == NULL)
01021 return NULL;
01022
01023 eap = wpabuf_mhead(msg->buf);
01024 eap->length = host_to_be16(wpabuf_len(msg->buf));
01025
01026 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
01027 if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) {
01028 eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf),
01029 wpabuf_len(msg->buf),
01030 (u8 *) wpabuf_mhead(msg->buf) +
01031 msg->mac, extra, extra_len);
01032 } else
01033 #endif
01034 if (k_aut && msg->mac) {
01035 eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf),
01036 wpabuf_len(msg->buf),
01037 (u8 *) wpabuf_mhead(msg->buf) + msg->mac,
01038 extra, extra_len);
01039 }
01040
01041 buf = msg->buf;
01042 os_free(msg);
01043 return buf;
01044 }
01045
01046
01047 void eap_sim_msg_free(struct eap_sim_msg *msg)
01048 {
01049 if (msg) {
01050 wpabuf_free(msg->buf);
01051 os_free(msg);
01052 }
01053 }
01054
01055
01056 u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
01057 const u8 *data, size_t len)
01058 {
01059 int attr_len = 2 + len;
01060 int pad_len;
01061 u8 *start;
01062
01063 if (msg == NULL)
01064 return NULL;
01065
01066 pad_len = (4 - attr_len % 4) % 4;
01067 attr_len += pad_len;
01068 if (wpabuf_resize(&msg->buf, attr_len))
01069 return NULL;
01070 start = wpabuf_put(msg->buf, 0);
01071 wpabuf_put_u8(msg->buf, attr);
01072 wpabuf_put_u8(msg->buf, attr_len / 4);
01073 wpabuf_put_data(msg->buf, data, len);
01074 if (pad_len)
01075 os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len);
01076 return start;
01077 }
01078
01079
01080 u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
01081 const u8 *data, size_t len)
01082 {
01083 int attr_len = 4 + len;
01084 int pad_len;
01085 u8 *start;
01086
01087 if (msg == NULL)
01088 return NULL;
01089
01090 pad_len = (4 - attr_len % 4) % 4;
01091 attr_len += pad_len;
01092 if (wpabuf_resize(&msg->buf, attr_len))
01093 return NULL;
01094 start = wpabuf_put(msg->buf, 0);
01095 wpabuf_put_u8(msg->buf, attr);
01096 wpabuf_put_u8(msg->buf, attr_len / 4);
01097 wpabuf_put_be16(msg->buf, value);
01098 if (data)
01099 wpabuf_put_data(msg->buf, data, len);
01100 else
01101 wpabuf_put(msg->buf, len);
01102 if (pad_len)
01103 os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len);
01104 return start;
01105 }
01106
01107
01108 u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr)
01109 {
01110 u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN);
01111 if (pos)
01112 msg->mac = (pos - wpabuf_head_u8(msg->buf)) + 4;
01113 return pos;
01114 }
01115
01116
01117 int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv,
01118 u8 attr_encr)
01119 {
01120 u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN);
01121 if (pos == NULL)
01122 return -1;
01123 msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4;
01124 if (os_get_random(wpabuf_mhead_u8(msg->buf) + msg->iv,
01125 EAP_SIM_IV_LEN)) {
01126 msg->iv = 0;
01127 return -1;
01128 }
01129
01130 pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0);
01131 if (pos == NULL) {
01132 msg->iv = 0;
01133 return -1;
01134 }
01135 msg->encr = pos - wpabuf_head_u8(msg->buf);
01136
01137 return 0;
01138 }
01139
01140
01141 int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
01142 {
01143 size_t encr_len;
01144
01145 if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
01146 return -1;
01147
01148 encr_len = wpabuf_len(msg->buf) - msg->encr - 4;
01149 if (encr_len % 16) {
01150 u8 *pos;
01151 int pad_len = 16 - (encr_len % 16);
01152 if (pad_len < 4) {
01153 wpa_printf(MSG_WARNING, "EAP-SIM: "
01154 "eap_sim_msg_add_encr_end - invalid pad_len"
01155 " %d", pad_len);
01156 return -1;
01157 }
01158 wpa_printf(MSG_DEBUG, " *AT_PADDING");
01159 pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
01160 if (pos == NULL)
01161 return -1;
01162 os_memset(pos + 4, 0, pad_len - 4);
01163 encr_len += pad_len;
01164 }
01165 wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
01166 (unsigned long) encr_len);
01167 wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1;
01168 return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv,
01169 wpabuf_mhead_u8(msg->buf) + msg->encr + 4,
01170 encr_len);
01171 }
01172
01173
01174 void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
01175 {
01176 #ifndef CONFIG_NO_STDOUT_DEBUG
01177 const char *type = aka ? "AKA" : "SIM";
01178 #endif
01179
01180 switch (notification) {
01181 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
01182 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
01183 "notification (after authentication)", type);
01184 break;
01185 case EAP_SIM_TEMPORARILY_DENIED:
01186 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
01187 "User has been temporarily denied access to the "
01188 "requested service", type);
01189 break;
01190 case EAP_SIM_NOT_SUBSCRIBED:
01191 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
01192 "User has not subscribed to the requested service",
01193 type);
01194 break;
01195 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH:
01196 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
01197 "notification (before authentication)", type);
01198 break;
01199 case EAP_SIM_SUCCESS:
01200 wpa_printf(MSG_INFO, "EAP-%s: Successful authentication "
01201 "notification", type);
01202 break;
01203 default:
01204 if (notification >= 32768) {
01205 wpa_printf(MSG_INFO, "EAP-%s: Unrecognized "
01206 "non-failure notification %d",
01207 type, notification);
01208 } else {
01209 wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized "
01210 "failure notification %d",
01211 type, notification);
01212 }
01213 }
01214 }