eap_server_aka.c 34 KB

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