PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/external/bsd/wpa/dist/src/eap_server/eap_server_aka.c

https://github.com/rumpkernel/netbsd-userspace-src
C | 1351 lines | 1095 code | 200 blank | 56 comment | 258 complexity | 16c785ed332c24258e721d2982718b2e MD5 | raw file
  1. /*
  2. * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
  3. * Copyright (c) 2005-2012, 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. #include "includes.h"
  9. #include "common.h"
  10. #include "crypto/sha256.h"
  11. #include "crypto/crypto.h"
  12. #include "crypto/random.h"
  13. #include "eap_common/eap_sim_common.h"
  14. #include "eap_server/eap_i.h"
  15. #include "eap_server/eap_sim_db.h"
  16. struct eap_aka_data {
  17. u8 mk[EAP_SIM_MK_LEN];
  18. u8 nonce_s[EAP_SIM_NONCE_S_LEN];
  19. u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
  20. u8 k_encr[EAP_SIM_K_ENCR_LEN];
  21. u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
  22. u8 msk[EAP_SIM_KEYING_DATA_LEN];
  23. u8 emsk[EAP_EMSK_LEN];
  24. u8 rand[EAP_AKA_RAND_LEN];
  25. u8 autn[EAP_AKA_AUTN_LEN];
  26. u8 ck[EAP_AKA_CK_LEN];
  27. u8 ik[EAP_AKA_IK_LEN];
  28. u8 res[EAP_AKA_RES_MAX_LEN];
  29. size_t res_len;
  30. enum {
  31. IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
  32. } state;
  33. char *next_pseudonym;
  34. char *next_reauth_id;
  35. u16 counter;
  36. struct eap_sim_reauth *reauth;
  37. int auts_reported; /* whether the current AUTS has been reported to the
  38. * eap_sim_db */
  39. u16 notification;
  40. int use_result_ind;
  41. struct wpabuf *id_msgs;
  42. int pending_id;
  43. u8 eap_method;
  44. u8 *network_name;
  45. size_t network_name_len;
  46. u16 kdf;
  47. int identity_round;
  48. char permanent[20]; /* Permanent username */
  49. };
  50. static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
  51. static const char * eap_aka_state_txt(int state)
  52. {
  53. switch (state) {
  54. case IDENTITY:
  55. return "IDENTITY";
  56. case CHALLENGE:
  57. return "CHALLENGE";
  58. case REAUTH:
  59. return "REAUTH";
  60. case SUCCESS:
  61. return "SUCCESS";
  62. case FAILURE:
  63. return "FAILURE";
  64. case NOTIFICATION:
  65. return "NOTIFICATION";
  66. default:
  67. return "Unknown?!";
  68. }
  69. }
  70. static void eap_aka_state(struct eap_aka_data *data, int state)
  71. {
  72. wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
  73. eap_aka_state_txt(data->state),
  74. eap_aka_state_txt(state));
  75. data->state = state;
  76. }
  77. static int eap_aka_check_identity_reauth(struct eap_sm *sm,
  78. struct eap_aka_data *data,
  79. const char *username)
  80. {
  81. if (data->eap_method == EAP_TYPE_AKA_PRIME &&
  82. username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
  83. return 0;
  84. if (data->eap_method == EAP_TYPE_AKA &&
  85. username[0] != EAP_AKA_REAUTH_ID_PREFIX)
  86. return 0;
  87. wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
  88. data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv,
  89. username);
  90. if (data->reauth == NULL) {
  91. wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
  92. "request full auth identity");
  93. /* Remain in IDENTITY state for another round */
  94. return 0;
  95. }
  96. wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
  97. os_strlcpy(data->permanent, data->reauth->permanent,
  98. sizeof(data->permanent));
  99. data->counter = data->reauth->counter;
  100. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  101. os_memcpy(data->k_encr, data->reauth->k_encr,
  102. EAP_SIM_K_ENCR_LEN);
  103. os_memcpy(data->k_aut, data->reauth->k_aut,
  104. EAP_AKA_PRIME_K_AUT_LEN);
  105. os_memcpy(data->k_re, data->reauth->k_re,
  106. EAP_AKA_PRIME_K_RE_LEN);
  107. } else {
  108. os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
  109. }
  110. eap_aka_state(data, REAUTH);
  111. return 1;
  112. }
  113. static void eap_aka_check_identity(struct eap_sm *sm,
  114. struct eap_aka_data *data)
  115. {
  116. char *username;
  117. /* Check if we already know the identity from EAP-Response/Identity */
  118. username = sim_get_username(sm->identity, sm->identity_len);
  119. if (username == NULL)
  120. return;
  121. if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
  122. os_free(username);
  123. /*
  124. * Since re-auth username was recognized, skip AKA/Identity
  125. * exchange.
  126. */
  127. return;
  128. }
  129. if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
  130. username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
  131. (data->eap_method == EAP_TYPE_AKA &&
  132. username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
  133. const char *permanent;
  134. wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
  135. username);
  136. permanent = eap_sim_db_get_permanent(
  137. sm->eap_sim_db_priv, username);
  138. if (permanent == NULL) {
  139. os_free(username);
  140. wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
  141. "identity - request permanent identity");
  142. /* Remain in IDENTITY state for another round */
  143. return;
  144. }
  145. os_strlcpy(data->permanent, permanent,
  146. sizeof(data->permanent));
  147. /*
  148. * Since pseudonym username was recognized, skip AKA/Identity
  149. * exchange.
  150. */
  151. eap_aka_fullauth(sm, data);
  152. }
  153. os_free(username);
  154. }
  155. static void * eap_aka_init(struct eap_sm *sm)
  156. {
  157. struct eap_aka_data *data;
  158. if (sm->eap_sim_db_priv == NULL) {
  159. wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
  160. return NULL;
  161. }
  162. data = os_zalloc(sizeof(*data));
  163. if (data == NULL)
  164. return NULL;
  165. data->eap_method = EAP_TYPE_AKA;
  166. data->state = IDENTITY;
  167. data->pending_id = -1;
  168. eap_aka_check_identity(sm, data);
  169. return data;
  170. }
  171. #ifdef EAP_SERVER_AKA_PRIME
  172. static void * eap_aka_prime_init(struct eap_sm *sm)
  173. {
  174. struct eap_aka_data *data;
  175. /* TODO: make ANID configurable; see 3GPP TS 24.302 */
  176. char *network_name = "WLAN";
  177. if (sm->eap_sim_db_priv == NULL) {
  178. wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
  179. return NULL;
  180. }
  181. data = os_zalloc(sizeof(*data));
  182. if (data == NULL)
  183. return NULL;
  184. data->eap_method = EAP_TYPE_AKA_PRIME;
  185. data->network_name = (u8 *) os_strdup(network_name);
  186. if (data->network_name == NULL) {
  187. os_free(data);
  188. return NULL;
  189. }
  190. data->network_name_len = os_strlen(network_name);
  191. data->state = IDENTITY;
  192. data->pending_id = -1;
  193. eap_aka_check_identity(sm, data);
  194. return data;
  195. }
  196. #endif /* EAP_SERVER_AKA_PRIME */
  197. static void eap_aka_reset(struct eap_sm *sm, void *priv)
  198. {
  199. struct eap_aka_data *data = priv;
  200. os_free(data->next_pseudonym);
  201. os_free(data->next_reauth_id);
  202. wpabuf_free(data->id_msgs);
  203. os_free(data->network_name);
  204. os_free(data);
  205. }
  206. static int eap_aka_add_id_msg(struct eap_aka_data *data,
  207. const struct wpabuf *msg)
  208. {
  209. if (msg == NULL)
  210. return -1;
  211. if (data->id_msgs == NULL) {
  212. data->id_msgs = wpabuf_dup(msg);
  213. return data->id_msgs == NULL ? -1 : 0;
  214. }
  215. if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
  216. return -1;
  217. wpabuf_put_buf(data->id_msgs, msg);
  218. return 0;
  219. }
  220. static void eap_aka_add_checkcode(struct eap_aka_data *data,
  221. struct eap_sim_msg *msg)
  222. {
  223. const u8 *addr;
  224. size_t len;
  225. u8 hash[SHA256_MAC_LEN];
  226. wpa_printf(MSG_DEBUG, " AT_CHECKCODE");
  227. if (data->id_msgs == NULL) {
  228. /*
  229. * No EAP-AKA/Identity packets were exchanged - send empty
  230. * checkcode.
  231. */
  232. eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
  233. return;
  234. }
  235. /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
  236. addr = wpabuf_head(data->id_msgs);
  237. len = wpabuf_len(data->id_msgs);
  238. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
  239. if (data->eap_method == EAP_TYPE_AKA_PRIME)
  240. sha256_vector(1, &addr, &len, hash);
  241. else
  242. sha1_vector(1, &addr, &len, hash);
  243. eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
  244. data->eap_method == EAP_TYPE_AKA_PRIME ?
  245. EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
  246. }
  247. static int eap_aka_verify_checkcode(struct eap_aka_data *data,
  248. const u8 *checkcode, size_t checkcode_len)
  249. {
  250. const u8 *addr;
  251. size_t len;
  252. u8 hash[SHA256_MAC_LEN];
  253. size_t hash_len;
  254. if (checkcode == NULL)
  255. return -1;
  256. if (data->id_msgs == NULL) {
  257. if (checkcode_len != 0) {
  258. wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
  259. "indicates that AKA/Identity messages were "
  260. "used, but they were not");
  261. return -1;
  262. }
  263. return 0;
  264. }
  265. hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
  266. EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
  267. if (checkcode_len != hash_len) {
  268. wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
  269. "that AKA/Identity message were not used, but they "
  270. "were");
  271. return -1;
  272. }
  273. /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
  274. addr = wpabuf_head(data->id_msgs);
  275. len = wpabuf_len(data->id_msgs);
  276. if (data->eap_method == EAP_TYPE_AKA_PRIME)
  277. sha256_vector(1, &addr, &len, hash);
  278. else
  279. sha1_vector(1, &addr, &len, hash);
  280. if (os_memcmp(hash, checkcode, hash_len) != 0) {
  281. wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
  282. return -1;
  283. }
  284. return 0;
  285. }
  286. static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
  287. struct eap_aka_data *data, u8 id)
  288. {
  289. struct eap_sim_msg *msg;
  290. struct wpabuf *buf;
  291. wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
  292. msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
  293. EAP_AKA_SUBTYPE_IDENTITY);
  294. data->identity_round++;
  295. if (data->identity_round == 1) {
  296. /*
  297. * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
  298. * ignored and the AKA/Identity is used to request the
  299. * identity.
  300. */
  301. wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
  302. eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
  303. } else if (data->identity_round > 3) {
  304. /* Cannot use more than three rounds of Identity messages */
  305. eap_sim_msg_free(msg);
  306. return NULL;
  307. } else if (sm->identity && sm->identity_len > 0 &&
  308. (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
  309. sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
  310. /* Reauth id may have expired - try fullauth */
  311. wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ");
  312. eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
  313. } else {
  314. wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
  315. eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
  316. }
  317. buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
  318. if (eap_aka_add_id_msg(data, buf) < 0) {
  319. wpabuf_free(buf);
  320. return NULL;
  321. }
  322. data->pending_id = id;
  323. return buf;
  324. }
  325. static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
  326. struct eap_sim_msg *msg, u16 counter,
  327. const u8 *nonce_s)
  328. {
  329. os_free(data->next_pseudonym);
  330. if (nonce_s == NULL) {
  331. data->next_pseudonym =
  332. eap_sim_db_get_next_pseudonym(
  333. sm->eap_sim_db_priv,
  334. data->eap_method == EAP_TYPE_AKA_PRIME ?
  335. EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
  336. } else {
  337. /* Do not update pseudonym during re-authentication */
  338. data->next_pseudonym = NULL;
  339. }
  340. os_free(data->next_reauth_id);
  341. if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
  342. data->next_reauth_id =
  343. eap_sim_db_get_next_reauth_id(
  344. sm->eap_sim_db_priv,
  345. data->eap_method == EAP_TYPE_AKA_PRIME ?
  346. EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
  347. } else {
  348. wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
  349. "count exceeded - force full authentication");
  350. data->next_reauth_id = NULL;
  351. }
  352. if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
  353. counter == 0 && nonce_s == NULL)
  354. return 0;
  355. wpa_printf(MSG_DEBUG, " AT_IV");
  356. wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
  357. eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
  358. if (counter > 0) {
  359. wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
  360. eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
  361. }
  362. if (nonce_s) {
  363. wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
  364. eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
  365. EAP_SIM_NONCE_S_LEN);
  366. }
  367. if (data->next_pseudonym) {
  368. wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
  369. data->next_pseudonym);
  370. eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
  371. os_strlen(data->next_pseudonym),
  372. (u8 *) data->next_pseudonym,
  373. os_strlen(data->next_pseudonym));
  374. }
  375. if (data->next_reauth_id) {
  376. wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
  377. data->next_reauth_id);
  378. eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
  379. os_strlen(data->next_reauth_id),
  380. (u8 *) data->next_reauth_id,
  381. os_strlen(data->next_reauth_id));
  382. }
  383. if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
  384. wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
  385. "AT_ENCR_DATA");
  386. return -1;
  387. }
  388. return 0;
  389. }
  390. static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
  391. struct eap_aka_data *data,
  392. u8 id)
  393. {
  394. struct eap_sim_msg *msg;
  395. wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
  396. msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
  397. EAP_AKA_SUBTYPE_CHALLENGE);
  398. wpa_printf(MSG_DEBUG, " AT_RAND");
  399. eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
  400. wpa_printf(MSG_DEBUG, " AT_AUTN");
  401. eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
  402. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  403. if (data->kdf) {
  404. /* Add the selected KDF into the beginning */
  405. wpa_printf(MSG_DEBUG, " AT_KDF");
  406. eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
  407. NULL, 0);
  408. }
  409. wpa_printf(MSG_DEBUG, " AT_KDF");
  410. eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
  411. NULL, 0);
  412. wpa_printf(MSG_DEBUG, " AT_KDF_INPUT");
  413. eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
  414. data->network_name_len,
  415. data->network_name, data->network_name_len);
  416. }
  417. if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
  418. eap_sim_msg_free(msg);
  419. return NULL;
  420. }
  421. eap_aka_add_checkcode(data, msg);
  422. if (sm->eap_sim_aka_result_ind) {
  423. wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
  424. eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
  425. }
  426. #ifdef EAP_SERVER_AKA_PRIME
  427. if (data->eap_method == EAP_TYPE_AKA) {
  428. u16 flags = 0;
  429. int i;
  430. int aka_prime_preferred = 0;
  431. i = 0;
  432. while (sm->user && i < EAP_MAX_METHODS &&
  433. (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
  434. sm->user->methods[i].method != EAP_TYPE_NONE)) {
  435. if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
  436. if (sm->user->methods[i].method ==
  437. EAP_TYPE_AKA)
  438. break;
  439. if (sm->user->methods[i].method ==
  440. EAP_TYPE_AKA_PRIME) {
  441. aka_prime_preferred = 1;
  442. break;
  443. }
  444. }
  445. i++;
  446. }
  447. if (aka_prime_preferred)
  448. flags |= EAP_AKA_BIDDING_FLAG_D;
  449. eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
  450. }
  451. #endif /* EAP_SERVER_AKA_PRIME */
  452. wpa_printf(MSG_DEBUG, " AT_MAC");
  453. eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
  454. return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
  455. }
  456. static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
  457. struct eap_aka_data *data, u8 id)
  458. {
  459. struct eap_sim_msg *msg;
  460. wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
  461. if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
  462. return NULL;
  463. wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
  464. data->nonce_s, EAP_SIM_NONCE_S_LEN);
  465. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  466. eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
  467. sm->identity,
  468. sm->identity_len,
  469. data->nonce_s,
  470. data->msk, data->emsk);
  471. } else {
  472. eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
  473. data->msk, data->emsk);
  474. eap_sim_derive_keys_reauth(data->counter, sm->identity,
  475. sm->identity_len, data->nonce_s,
  476. data->mk, data->msk, data->emsk);
  477. }
  478. msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
  479. EAP_AKA_SUBTYPE_REAUTHENTICATION);
  480. if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
  481. eap_sim_msg_free(msg);
  482. return NULL;
  483. }
  484. eap_aka_add_checkcode(data, msg);
  485. if (sm->eap_sim_aka_result_ind) {
  486. wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
  487. eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
  488. }
  489. wpa_printf(MSG_DEBUG, " AT_MAC");
  490. eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
  491. return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
  492. }
  493. static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
  494. struct eap_aka_data *data,
  495. u8 id)
  496. {
  497. struct eap_sim_msg *msg;
  498. wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
  499. msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
  500. EAP_AKA_SUBTYPE_NOTIFICATION);
  501. wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification);
  502. eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
  503. NULL, 0);
  504. if (data->use_result_ind) {
  505. if (data->reauth) {
  506. wpa_printf(MSG_DEBUG, " AT_IV");
  507. wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
  508. eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
  509. EAP_SIM_AT_ENCR_DATA);
  510. wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)",
  511. data->counter);
  512. eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
  513. NULL, 0);
  514. if (eap_sim_msg_add_encr_end(msg, data->k_encr,
  515. EAP_SIM_AT_PADDING)) {
  516. wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
  517. "encrypt AT_ENCR_DATA");
  518. eap_sim_msg_free(msg);
  519. return NULL;
  520. }
  521. }
  522. wpa_printf(MSG_DEBUG, " AT_MAC");
  523. eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
  524. }
  525. return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
  526. }
  527. static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
  528. {
  529. struct eap_aka_data *data = priv;
  530. data->auts_reported = 0;
  531. switch (data->state) {
  532. case IDENTITY:
  533. return eap_aka_build_identity(sm, data, id);
  534. case CHALLENGE:
  535. return eap_aka_build_challenge(sm, data, id);
  536. case REAUTH:
  537. return eap_aka_build_reauth(sm, data, id);
  538. case NOTIFICATION:
  539. return eap_aka_build_notification(sm, data, id);
  540. default:
  541. wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
  542. "buildReq", data->state);
  543. break;
  544. }
  545. return NULL;
  546. }
  547. static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
  548. struct wpabuf *respData)
  549. {
  550. struct eap_aka_data *data = priv;
  551. const u8 *pos;
  552. size_t len;
  553. pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
  554. &len);
  555. if (pos == NULL || len < 3) {
  556. wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
  557. return TRUE;
  558. }
  559. return FALSE;
  560. }
  561. static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
  562. {
  563. if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
  564. subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
  565. return FALSE;
  566. switch (data->state) {
  567. case IDENTITY:
  568. if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
  569. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
  570. "subtype %d", subtype);
  571. return TRUE;
  572. }
  573. break;
  574. case CHALLENGE:
  575. if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
  576. subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
  577. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
  578. "subtype %d", subtype);
  579. return TRUE;
  580. }
  581. break;
  582. case REAUTH:
  583. if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
  584. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
  585. "subtype %d", subtype);
  586. return TRUE;
  587. }
  588. break;
  589. case NOTIFICATION:
  590. if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
  591. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
  592. "subtype %d", subtype);
  593. return TRUE;
  594. }
  595. break;
  596. default:
  597. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
  598. "processing a response", data->state);
  599. return TRUE;
  600. }
  601. return FALSE;
  602. }
  603. static void eap_aka_determine_identity(struct eap_sm *sm,
  604. struct eap_aka_data *data)
  605. {
  606. char *username;
  607. wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
  608. sm->identity, sm->identity_len);
  609. username = sim_get_username(sm->identity, sm->identity_len);
  610. if (username == NULL) {
  611. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  612. eap_aka_state(data, NOTIFICATION);
  613. return;
  614. }
  615. if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
  616. os_free(username);
  617. return;
  618. }
  619. if (((data->eap_method == EAP_TYPE_AKA_PRIME &&
  620. username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
  621. (data->eap_method == EAP_TYPE_AKA &&
  622. username[0] == EAP_AKA_REAUTH_ID_PREFIX)) &&
  623. data->identity_round == 1) {
  624. /* Remain in IDENTITY state for another round to request full
  625. * auth identity since we did not recognize reauth id */
  626. os_free(username);
  627. return;
  628. }
  629. if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
  630. username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
  631. (data->eap_method == EAP_TYPE_AKA &&
  632. username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
  633. const char *permanent;
  634. wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
  635. username);
  636. permanent = eap_sim_db_get_permanent(
  637. sm->eap_sim_db_priv, username);
  638. os_free(username);
  639. if (permanent == NULL) {
  640. wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
  641. "identity - request permanent identity");
  642. /* Remain in IDENTITY state for another round */
  643. return;
  644. }
  645. os_strlcpy(data->permanent, permanent,
  646. sizeof(data->permanent));
  647. } else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
  648. username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
  649. (data->eap_method == EAP_TYPE_AKA &&
  650. username[0] == EAP_AKA_PERMANENT_PREFIX)) {
  651. wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
  652. username);
  653. os_strlcpy(data->permanent, username, sizeof(data->permanent));
  654. os_free(username);
  655. } else {
  656. wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
  657. username);
  658. os_free(username);
  659. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  660. eap_aka_state(data, NOTIFICATION);
  661. return;
  662. }
  663. eap_aka_fullauth(sm, data);
  664. }
  665. static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
  666. {
  667. size_t identity_len;
  668. int res;
  669. res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent,
  670. data->rand, data->autn, data->ik,
  671. data->ck, data->res, &data->res_len, sm);
  672. if (res == EAP_SIM_DB_PENDING) {
  673. wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
  674. "not yet available - pending request");
  675. sm->method_pending = METHOD_PENDING_WAIT;
  676. return;
  677. }
  678. #ifdef EAP_SERVER_AKA_PRIME
  679. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  680. /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
  681. * needed 6-octet SQN ^AK for CK',IK' derivation */
  682. eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
  683. data->autn,
  684. data->network_name,
  685. data->network_name_len);
  686. }
  687. #endif /* EAP_SERVER_AKA_PRIME */
  688. data->reauth = NULL;
  689. data->counter = 0; /* reset re-auth counter since this is full auth */
  690. if (res != 0) {
  691. wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
  692. "authentication data for the peer");
  693. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  694. eap_aka_state(data, NOTIFICATION);
  695. return;
  696. }
  697. if (sm->method_pending == METHOD_PENDING_WAIT) {
  698. wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
  699. "available - abort pending wait");
  700. sm->method_pending = METHOD_PENDING_NONE;
  701. }
  702. identity_len = sm->identity_len;
  703. while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
  704. wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
  705. "character from identity");
  706. identity_len--;
  707. }
  708. wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
  709. sm->identity, identity_len);
  710. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  711. eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
  712. data->ck, data->k_encr, data->k_aut,
  713. data->k_re, data->msk, data->emsk);
  714. } else {
  715. eap_aka_derive_mk(sm->identity, identity_len, data->ik,
  716. data->ck, data->mk);
  717. eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
  718. data->msk, data->emsk);
  719. }
  720. eap_aka_state(data, CHALLENGE);
  721. }
  722. static void eap_aka_process_identity(struct eap_sm *sm,
  723. struct eap_aka_data *data,
  724. struct wpabuf *respData,
  725. struct eap_sim_attrs *attr)
  726. {
  727. u8 *new_identity;
  728. wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
  729. if (attr->mac || attr->iv || attr->encr_data) {
  730. wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
  731. "received in EAP-Response/AKA-Identity");
  732. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  733. eap_aka_state(data, NOTIFICATION);
  734. return;
  735. }
  736. /*
  737. * We always request identity with AKA/Identity, so the peer is
  738. * required to have replied with one.
  739. */
  740. if (!attr->identity || attr->identity_len == 0) {
  741. wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
  742. "identity");
  743. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  744. eap_aka_state(data, NOTIFICATION);
  745. return;
  746. }
  747. new_identity = os_malloc(attr->identity_len);
  748. if (new_identity == NULL) {
  749. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  750. eap_aka_state(data, NOTIFICATION);
  751. return;
  752. }
  753. os_free(sm->identity);
  754. sm->identity = new_identity;
  755. os_memcpy(sm->identity, attr->identity, attr->identity_len);
  756. sm->identity_len = attr->identity_len;
  757. eap_aka_determine_identity(sm, data);
  758. if (eap_get_id(respData) == data->pending_id) {
  759. data->pending_id = -1;
  760. eap_aka_add_id_msg(data, respData);
  761. }
  762. }
  763. static int eap_aka_verify_mac(struct eap_aka_data *data,
  764. const struct wpabuf *req,
  765. const u8 *mac, const u8 *extra,
  766. size_t extra_len)
  767. {
  768. if (data->eap_method == EAP_TYPE_AKA_PRIME)
  769. return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
  770. extra_len);
  771. return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
  772. }
  773. static void eap_aka_process_challenge(struct eap_sm *sm,
  774. struct eap_aka_data *data,
  775. struct wpabuf *respData,
  776. struct eap_sim_attrs *attr)
  777. {
  778. wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
  779. #ifdef EAP_SERVER_AKA_PRIME
  780. #if 0
  781. /* KDF negotiation; to be enabled only after more than one KDF is
  782. * supported */
  783. if (data->eap_method == EAP_TYPE_AKA_PRIME &&
  784. attr->kdf_count == 1 && attr->mac == NULL) {
  785. if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
  786. wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
  787. "unknown KDF");
  788. data->notification =
  789. EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  790. eap_aka_state(data, NOTIFICATION);
  791. return;
  792. }
  793. data->kdf = attr->kdf[0];
  794. /* Allow negotiation to continue with the selected KDF by
  795. * sending another Challenge message */
  796. wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
  797. return;
  798. }
  799. #endif
  800. #endif /* EAP_SERVER_AKA_PRIME */
  801. if (attr->checkcode &&
  802. eap_aka_verify_checkcode(data, attr->checkcode,
  803. attr->checkcode_len)) {
  804. wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
  805. "message");
  806. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  807. eap_aka_state(data, NOTIFICATION);
  808. return;
  809. }
  810. if (attr->mac == NULL ||
  811. eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
  812. wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
  813. "did not include valid AT_MAC");
  814. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  815. eap_aka_state(data, NOTIFICATION);
  816. return;
  817. }
  818. /*
  819. * AT_RES is padded, so verify that there is enough room for RES and
  820. * that the RES length in bits matches with the expected RES.
  821. */
  822. if (attr->res == NULL || attr->res_len < data->res_len ||
  823. attr->res_len_bits != data->res_len * 8 ||
  824. os_memcmp(attr->res, data->res, data->res_len) != 0) {
  825. wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
  826. "include valid AT_RES (attr len=%lu, res len=%lu "
  827. "bits, expected %lu bits)",
  828. (unsigned long) attr->res_len,
  829. (unsigned long) attr->res_len_bits,
  830. (unsigned long) data->res_len * 8);
  831. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  832. eap_aka_state(data, NOTIFICATION);
  833. return;
  834. }
  835. wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
  836. "correct AT_MAC");
  837. if (sm->eap_sim_aka_result_ind && attr->result_ind) {
  838. data->use_result_ind = 1;
  839. data->notification = EAP_SIM_SUCCESS;
  840. eap_aka_state(data, NOTIFICATION);
  841. } else
  842. eap_aka_state(data, SUCCESS);
  843. if (data->next_pseudonym) {
  844. eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
  845. data->next_pseudonym);
  846. data->next_pseudonym = NULL;
  847. }
  848. if (data->next_reauth_id) {
  849. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  850. #ifdef EAP_SERVER_AKA_PRIME
  851. eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
  852. data->permanent,
  853. data->next_reauth_id,
  854. data->counter + 1,
  855. data->k_encr, data->k_aut,
  856. data->k_re);
  857. #endif /* EAP_SERVER_AKA_PRIME */
  858. } else {
  859. eap_sim_db_add_reauth(sm->eap_sim_db_priv,
  860. data->permanent,
  861. data->next_reauth_id,
  862. data->counter + 1,
  863. data->mk);
  864. }
  865. data->next_reauth_id = NULL;
  866. }
  867. }
  868. static void eap_aka_process_sync_failure(struct eap_sm *sm,
  869. struct eap_aka_data *data,
  870. struct wpabuf *respData,
  871. struct eap_sim_attrs *attr)
  872. {
  873. wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
  874. if (attr->auts == NULL) {
  875. wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
  876. "message did not include valid AT_AUTS");
  877. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  878. eap_aka_state(data, NOTIFICATION);
  879. return;
  880. }
  881. /* Avoid re-reporting AUTS when processing pending EAP packet by
  882. * maintaining a local flag stating whether this AUTS has already been
  883. * reported. */
  884. if (!data->auts_reported &&
  885. eap_sim_db_resynchronize(sm->eap_sim_db_priv, data->permanent,
  886. attr->auts, data->rand)) {
  887. wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
  888. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  889. eap_aka_state(data, NOTIFICATION);
  890. return;
  891. }
  892. data->auts_reported = 1;
  893. /* Remain in CHALLENGE state to re-try after resynchronization */
  894. }
  895. static void eap_aka_process_reauth(struct eap_sm *sm,
  896. struct eap_aka_data *data,
  897. struct wpabuf *respData,
  898. struct eap_sim_attrs *attr)
  899. {
  900. struct eap_sim_attrs eattr;
  901. u8 *decrypted = NULL;
  902. wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
  903. if (attr->mac == NULL ||
  904. eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
  905. EAP_SIM_NONCE_S_LEN)) {
  906. wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
  907. "did not include valid AT_MAC");
  908. goto fail;
  909. }
  910. if (attr->encr_data == NULL || attr->iv == NULL) {
  911. wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
  912. "message did not include encrypted data");
  913. goto fail;
  914. }
  915. decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
  916. attr->encr_data_len, attr->iv, &eattr,
  917. 0);
  918. if (decrypted == NULL) {
  919. wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
  920. "data from reauthentication message");
  921. goto fail;
  922. }
  923. if (eattr.counter != data->counter) {
  924. wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
  925. "used incorrect counter %u, expected %u",
  926. eattr.counter, data->counter);
  927. goto fail;
  928. }
  929. os_free(decrypted);
  930. decrypted = NULL;
  931. wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
  932. "the correct AT_MAC");
  933. if (eattr.counter_too_small) {
  934. wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
  935. "included AT_COUNTER_TOO_SMALL - starting full "
  936. "authentication");
  937. eap_aka_fullauth(sm, data);
  938. return;
  939. }
  940. if (sm->eap_sim_aka_result_ind && attr->result_ind) {
  941. data->use_result_ind = 1;
  942. data->notification = EAP_SIM_SUCCESS;
  943. eap_aka_state(data, NOTIFICATION);
  944. } else
  945. eap_aka_state(data, SUCCESS);
  946. if (data->next_reauth_id) {
  947. if (data->eap_method == EAP_TYPE_AKA_PRIME) {
  948. #ifdef EAP_SERVER_AKA_PRIME
  949. eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
  950. data->permanent,
  951. data->next_reauth_id,
  952. data->counter + 1,
  953. data->k_encr, data->k_aut,
  954. data->k_re);
  955. #endif /* EAP_SERVER_AKA_PRIME */
  956. } else {
  957. eap_sim_db_add_reauth(sm->eap_sim_db_priv,
  958. data->permanent,
  959. data->next_reauth_id,
  960. data->counter + 1,
  961. data->mk);
  962. }
  963. data->next_reauth_id = NULL;
  964. } else {
  965. eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
  966. data->reauth = NULL;
  967. }
  968. return;
  969. fail:
  970. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  971. eap_aka_state(data, NOTIFICATION);
  972. eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
  973. data->reauth = NULL;
  974. os_free(decrypted);
  975. }
  976. static void eap_aka_process_client_error(struct eap_sm *sm,
  977. struct eap_aka_data *data,
  978. struct wpabuf *respData,
  979. struct eap_sim_attrs *attr)
  980. {
  981. wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
  982. attr->client_error_code);
  983. if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
  984. eap_aka_state(data, SUCCESS);
  985. else
  986. eap_aka_state(data, FAILURE);
  987. }
  988. static void eap_aka_process_authentication_reject(
  989. struct eap_sm *sm, struct eap_aka_data *data,
  990. struct wpabuf *respData, struct eap_sim_attrs *attr)
  991. {
  992. wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
  993. eap_aka_state(data, FAILURE);
  994. }
  995. static void eap_aka_process_notification(struct eap_sm *sm,
  996. struct eap_aka_data *data,
  997. struct wpabuf *respData,
  998. struct eap_sim_attrs *attr)
  999. {
  1000. wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
  1001. if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
  1002. eap_aka_state(data, SUCCESS);
  1003. else
  1004. eap_aka_state(data, FAILURE);
  1005. }
  1006. static void eap_aka_process(struct eap_sm *sm, void *priv,
  1007. struct wpabuf *respData)
  1008. {
  1009. struct eap_aka_data *data = priv;
  1010. const u8 *pos, *end;
  1011. u8 subtype;
  1012. size_t len;
  1013. struct eap_sim_attrs attr;
  1014. pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
  1015. &len);
  1016. if (pos == NULL || len < 3)
  1017. return;
  1018. end = pos + len;
  1019. subtype = *pos;
  1020. pos += 3;
  1021. if (eap_aka_subtype_ok(data, subtype)) {
  1022. wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
  1023. "EAP-AKA Subtype in EAP Response");
  1024. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  1025. eap_aka_state(data, NOTIFICATION);
  1026. return;
  1027. }
  1028. if (eap_sim_parse_attr(pos, end, &attr,
  1029. data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
  1030. 0)) {
  1031. wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
  1032. data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
  1033. eap_aka_state(data, NOTIFICATION);
  1034. return;
  1035. }
  1036. if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
  1037. eap_aka_process_client_error(sm, data, respData, &attr);
  1038. return;
  1039. }
  1040. if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
  1041. eap_aka_process_authentication_reject(sm, data, respData,
  1042. &attr);
  1043. return;
  1044. }
  1045. switch (data->state) {
  1046. case IDENTITY:
  1047. eap_aka_process_identity(sm, data, respData, &attr);
  1048. break;
  1049. case CHALLENGE:
  1050. if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
  1051. eap_aka_process_sync_failure(sm, data, respData,
  1052. &attr);
  1053. } else {
  1054. eap_aka_process_challenge(sm, data, respData, &attr);
  1055. }
  1056. break;
  1057. case REAUTH:
  1058. eap_aka_process_reauth(sm, data, respData, &attr);
  1059. break;
  1060. case NOTIFICATION:
  1061. eap_aka_process_notification(sm, data, respData, &attr);
  1062. break;
  1063. default:
  1064. wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
  1065. "process", data->state);
  1066. break;
  1067. }
  1068. }
  1069. static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
  1070. {
  1071. struct eap_aka_data *data = priv;
  1072. return data->state == SUCCESS || data->state == FAILURE;
  1073. }
  1074. static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
  1075. {
  1076. struct eap_aka_data *data = priv;
  1077. u8 *key;
  1078. if (data->state != SUCCESS)
  1079. return NULL;
  1080. key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
  1081. if (key == NULL)
  1082. return NULL;
  1083. os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
  1084. *len = EAP_SIM_KEYING_DATA_LEN;
  1085. return key;
  1086. }
  1087. static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
  1088. {
  1089. struct eap_aka_data *data = priv;
  1090. u8 *key;
  1091. if (data->state != SUCCESS)
  1092. return NULL;
  1093. key = os_malloc(EAP_EMSK_LEN);
  1094. if (key == NULL)
  1095. return NULL;
  1096. os_memcpy(key, data->emsk, EAP_EMSK_LEN);
  1097. *len = EAP_EMSK_LEN;
  1098. return key;
  1099. }
  1100. static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
  1101. {
  1102. struct eap_aka_data *data = priv;
  1103. return data->state == SUCCESS;
  1104. }
  1105. int eap_server_aka_register(void)
  1106. {
  1107. struct eap_method *eap;
  1108. int ret;
  1109. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  1110. EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
  1111. if (eap == NULL)
  1112. return -1;
  1113. eap->init = eap_aka_init;
  1114. eap->reset = eap_aka_reset;
  1115. eap->buildReq = eap_aka_buildReq;
  1116. eap->check = eap_aka_check;
  1117. eap->process = eap_aka_process;
  1118. eap->isDone = eap_aka_isDone;
  1119. eap->getKey = eap_aka_getKey;
  1120. eap->isSuccess = eap_aka_isSuccess;
  1121. eap->get_emsk = eap_aka_get_emsk;
  1122. ret = eap_server_method_register(eap);
  1123. if (ret)
  1124. eap_server_method_free(eap);
  1125. return ret;
  1126. }
  1127. #ifdef EAP_SERVER_AKA_PRIME
  1128. int eap_server_aka_prime_register(void)
  1129. {
  1130. struct eap_method *eap;
  1131. int ret;
  1132. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  1133. EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
  1134. "AKA'");
  1135. if (eap == NULL)
  1136. return -1;
  1137. eap->init = eap_aka_prime_init;
  1138. eap->reset = eap_aka_reset;
  1139. eap->buildReq = eap_aka_buildReq;
  1140. eap->check = eap_aka_check;
  1141. eap->process = eap_aka_process;
  1142. eap->isDone = eap_aka_isDone;
  1143. eap->getKey = eap_aka_getKey;
  1144. eap->isSuccess = eap_aka_isSuccess;
  1145. eap->get_emsk = eap_aka_get_emsk;
  1146. ret = eap_server_method_register(eap);
  1147. if (ret)
  1148. eap_server_method_free(eap);
  1149. return ret;
  1150. }
  1151. #endif /* EAP_SERVER_AKA_PRIME */