eap_aka_prime.c 32 KB

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