Don't include unused calls to SHA256 functions if EAP-AKA' is not enabled
[libeap.git] / src / eap_peer / eap_aka.c
1 /*
2  * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
3  * Copyright (c) 2004-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
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_peer/eap_i.h"
19 #include "pcsc_funcs.h"
20 #include "eap_common/eap_sim_common.h"
21 #include "sha1.h"
22 #include "sha256.h"
23 #include "crypto.h"
24 #include "eap_peer/eap_config.h"
25 #ifdef CONFIG_USIM_SIMULATOR
26 #include "hlr_auc_gw/milenage.h"
27 #endif /* CONFIG_USIM_SIMULATOR */
28
29
30 struct eap_aka_data {
31         u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
32         size_t res_len;
33         u8 nonce_s[EAP_SIM_NONCE_S_LEN];
34         u8 mk[EAP_SIM_MK_LEN];
35         u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
36         u8 k_encr[EAP_SIM_K_ENCR_LEN];
37         u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
38         u8 msk[EAP_SIM_KEYING_DATA_LEN];
39         u8 emsk[EAP_EMSK_LEN];
40         u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
41         u8 auts[EAP_AKA_AUTS_LEN];
42
43         int num_id_req, num_notification;
44         u8 *pseudonym;
45         size_t pseudonym_len;
46         u8 *reauth_id;
47         size_t reauth_id_len;
48         int reauth;
49         unsigned int counter, counter_too_small;
50         u8 *last_eap_identity;
51         size_t last_eap_identity_len;
52         enum {
53                 CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
54         } state;
55
56         struct wpabuf *id_msgs;
57         int prev_id;
58         int result_ind, use_result_ind;
59         u8 eap_method;
60         u8 *network_name;
61         size_t network_name_len;
62         u16 kdf;
63 };
64
65
66 #ifndef CONFIG_NO_STDOUT_DEBUG
67 static const char * eap_aka_state_txt(int state)
68 {
69         switch (state) {
70         case CONTINUE:
71                 return "CONTINUE";
72         case RESULT_SUCCESS:
73                 return "RESULT_SUCCESS";
74         case RESULT_FAILURE:
75                 return "RESULT_FAILURE";
76         case SUCCESS:
77                 return "SUCCESS";
78         case FAILURE:
79                 return "FAILURE";
80         default:
81                 return "?";
82         }
83 }
84 #endif /* CONFIG_NO_STDOUT_DEBUG */
85
86
87 static void eap_aka_state(struct eap_aka_data *data, int state)
88 {
89         wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
90                    eap_aka_state_txt(data->state),
91                    eap_aka_state_txt(state));
92         data->state = state;
93 }
94
95
96 static void * eap_aka_init(struct eap_sm *sm)
97 {
98         struct eap_aka_data *data;
99         const char *phase1 = eap_get_config_phase1(sm);
100
101         data = os_zalloc(sizeof(*data));
102         if (data == NULL)
103                 return NULL;
104
105         data->eap_method = EAP_TYPE_AKA;
106
107         eap_aka_state(data, CONTINUE);
108         data->prev_id = -1;
109
110         data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
111
112         return data;
113 }
114
115
116 #ifdef EAP_AKA_PRIME
117 static void * eap_aka_prime_init(struct eap_sm *sm)
118 {
119         struct eap_aka_data *data = eap_aka_init(sm);
120         if (data == NULL)
121                 return NULL;
122         data->eap_method = EAP_TYPE_AKA_PRIME;
123         return data;
124 }
125 #endif /* EAP_AKA_PRIME */
126
127
128 static void eap_aka_deinit(struct eap_sm *sm, void *priv)
129 {
130         struct eap_aka_data *data = priv;
131         if (data) {
132                 os_free(data->pseudonym);
133                 os_free(data->reauth_id);
134                 os_free(data->last_eap_identity);
135                 wpabuf_free(data->id_msgs);
136                 os_free(data->network_name);
137                 os_free(data);
138         }
139 }
140
141
142 static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
143 {
144         struct eap_peer_config *conf;
145
146         wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
147
148         conf = eap_get_config(sm);
149         if (conf == NULL)
150                 return -1;
151         if (conf->pcsc) {
152                 return scard_umts_auth(sm->scard_ctx, data->rand,
153                                        data->autn, data->res, &data->res_len,
154                                        data->ik, data->ck, data->auts);
155         }
156
157 #ifdef CONFIG_USIM_SIMULATOR
158         if (conf->password) {
159                 u8 opc[16], k[16], sqn[6];
160                 const char *pos;
161                 wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage "
162                            "implementation for UMTS authentication");
163                 if (conf->password_len < 78) {
164                         wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage "
165                                    "password");
166                         return -1;
167                 }
168                 pos = (const char *) conf->password;
169                 if (hexstr2bin(pos, k, 16))
170                         return -1;
171                 pos += 32;
172                 if (*pos != ':')
173                         return -1;
174                 pos++;
175
176                 if (hexstr2bin(pos, opc, 16))
177                         return -1;
178                 pos += 32;
179                 if (*pos != ':')
180                         return -1;
181                 pos++;
182
183                 if (hexstr2bin(pos, sqn, 6))
184                         return -1;
185
186                 return milenage_check(opc, k, sqn, data->rand, data->autn,
187                                       data->ik, data->ck,
188                                       data->res, &data->res_len, data->auts);
189         }
190 #endif /* CONFIG_USIM_SIMULATOR */
191
192 #ifdef CONFIG_USIM_HARDCODED
193         wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for "
194                    "testing");
195
196         /* These hardcoded Kc and SRES values are used for testing.
197          * Could consider making them configurable. */
198         os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
199         data->res_len = EAP_AKA_RES_MAX_LEN;
200         os_memset(data->ik, '3', EAP_AKA_IK_LEN);
201         os_memset(data->ck, '4', EAP_AKA_CK_LEN);
202         {
203                 u8 autn[EAP_AKA_AUTN_LEN];
204                 os_memset(autn, '1', EAP_AKA_AUTN_LEN);
205                 if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
206                         wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
207                                    "with expected value");
208                         return -1;
209                 }
210         }
211 #if 0
212         {
213                 static int test_resync = 1;
214                 if (test_resync) {
215                         /* Test Resynchronization */
216                         test_resync = 0;
217                         return -2;
218                 }
219         }
220 #endif
221         return 0;
222
223 #else /* CONFIG_USIM_HARDCODED */
224
225         wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith "
226                    "enabled");
227         return -1;
228
229 #endif /* CONFIG_USIM_HARDCODED */
230 }
231
232
233 #define CLEAR_PSEUDONYM 0x01
234 #define CLEAR_REAUTH_ID 0x02
235 #define CLEAR_EAP_ID    0x04
236
237 static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
238 {
239         wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s",
240                    id & CLEAR_PSEUDONYM ? " pseudonym" : "",
241                    id & CLEAR_REAUTH_ID ? " reauth_id" : "",
242                    id & CLEAR_EAP_ID ? " eap_id" : "");
243         if (id & CLEAR_PSEUDONYM) {
244                 os_free(data->pseudonym);
245                 data->pseudonym = NULL;
246                 data->pseudonym_len = 0;
247         }
248         if (id & CLEAR_REAUTH_ID) {
249                 os_free(data->reauth_id);
250                 data->reauth_id = NULL;
251                 data->reauth_id_len = 0;
252         }
253         if (id & CLEAR_EAP_ID) {
254                 os_free(data->last_eap_identity);
255                 data->last_eap_identity = NULL;
256                 data->last_eap_identity_len = 0;
257         }
258 }
259
260
261 static int eap_aka_learn_ids(struct eap_aka_data *data,
262                              struct eap_sim_attrs *attr)
263 {
264         if (attr->next_pseudonym) {
265                 os_free(data->pseudonym);
266                 data->pseudonym = os_malloc(attr->next_pseudonym_len);
267                 if (data->pseudonym == NULL) {
268                         wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
269                                    "next pseudonym");
270                         return -1;
271                 }
272                 os_memcpy(data->pseudonym, attr->next_pseudonym,
273                           attr->next_pseudonym_len);
274                 data->pseudonym_len = attr->next_pseudonym_len;
275                 wpa_hexdump_ascii(MSG_DEBUG,
276                                   "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
277                                   data->pseudonym,
278                                   data->pseudonym_len);
279         }
280
281         if (attr->next_reauth_id) {
282                 os_free(data->reauth_id);
283                 data->reauth_id = os_malloc(attr->next_reauth_id_len);
284                 if (data->reauth_id == NULL) {
285                         wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
286                                    "next reauth_id");
287                         return -1;
288                 }
289                 os_memcpy(data->reauth_id, attr->next_reauth_id,
290                           attr->next_reauth_id_len);
291                 data->reauth_id_len = attr->next_reauth_id_len;
292                 wpa_hexdump_ascii(MSG_DEBUG,
293                                   "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
294                                   data->reauth_id,
295                                   data->reauth_id_len);
296         }
297
298         return 0;
299 }
300
301
302 static int eap_aka_add_id_msg(struct eap_aka_data *data,
303                               const struct wpabuf *msg)
304 {
305         if (msg == NULL)
306                 return -1;
307
308         if (data->id_msgs == NULL) {
309                 data->id_msgs = wpabuf_dup(msg);
310                 return data->id_msgs == NULL ? -1 : 0;
311         }
312
313         if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
314                 return -1;
315         wpabuf_put_buf(data->id_msgs, msg);
316
317         return 0;
318 }
319
320
321 static void eap_aka_add_checkcode(struct eap_aka_data *data,
322                                   struct eap_sim_msg *msg)
323 {
324         const u8 *addr;
325         size_t len;
326         u8 hash[SHA256_MAC_LEN];
327
328         wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
329
330         if (data->id_msgs == NULL) {
331                 /*
332                  * No EAP-AKA/Identity packets were exchanged - send empty
333                  * checkcode.
334                  */
335                 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
336                 return;
337         }
338
339         /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
340         addr = wpabuf_head(data->id_msgs);
341         len = wpabuf_len(data->id_msgs);
342         wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
343 #ifdef EAP_AKA_PRIME
344         if (data->eap_method == EAP_TYPE_AKA_PRIME)
345                 sha256_vector(1, &addr, &len, hash);
346         else
347 #endif /* EAP_AKA_PRIME */
348                 sha1_vector(1, &addr, &len, hash);
349
350         eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
351                         data->eap_method == EAP_TYPE_AKA_PRIME ?
352                         EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
353 }
354
355
356 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
357                                     const u8 *checkcode, size_t checkcode_len)
358 {
359         const u8 *addr;
360         size_t len;
361         u8 hash[SHA256_MAC_LEN];
362         size_t hash_len;
363
364         if (checkcode == NULL)
365                 return -1;
366
367         if (data->id_msgs == NULL) {
368                 if (checkcode_len != 0) {
369                         wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
370                                    "indicates that AKA/Identity messages were "
371                                    "used, but they were not");
372                         return -1;
373                 }
374                 return 0;
375         }
376
377         hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
378                 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
379
380         if (checkcode_len != hash_len) {
381                 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
382                            "indicates that AKA/Identity message were not "
383                            "used, but they were");
384                 return -1;
385         }
386
387         /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
388         addr = wpabuf_head(data->id_msgs);
389         len = wpabuf_len(data->id_msgs);
390 #ifdef EAP_AKA_PRIME
391         if (data->eap_method == EAP_TYPE_AKA_PRIME)
392                 sha256_vector(1, &addr, &len, hash);
393         else
394 #endif /* EAP_AKA_PRIME */
395                 sha1_vector(1, &addr, &len, hash);
396
397         if (os_memcmp(hash, checkcode, hash_len) != 0) {
398                 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
399                 return -1;
400         }
401
402         return 0;
403 }
404
405
406 static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id,
407                                             int err)
408 {
409         struct eap_sim_msg *msg;
410
411         eap_aka_state(data, FAILURE);
412         data->num_id_req = 0;
413         data->num_notification = 0;
414
415         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
416                                EAP_AKA_SUBTYPE_CLIENT_ERROR);
417         eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
418         return eap_sim_msg_finish(msg, NULL, NULL, 0);
419 }
420
421
422 static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data,
423                                                      u8 id)
424 {
425         struct eap_sim_msg *msg;
426
427         eap_aka_state(data, FAILURE);
428         data->num_id_req = 0;
429         data->num_notification = 0;
430
431         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject "
432                    "(id=%d)", id);
433         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
434                                EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
435         return eap_sim_msg_finish(msg, NULL, NULL, 0);
436 }
437
438
439 static struct wpabuf * eap_aka_synchronization_failure(
440         struct eap_aka_data *data, u8 id)
441 {
442         struct eap_sim_msg *msg;
443
444         data->num_id_req = 0;
445         data->num_notification = 0;
446
447         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure "
448                    "(id=%d)", id);
449         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
450                                EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
451         wpa_printf(MSG_DEBUG, "   AT_AUTS");
452         eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
453                              EAP_AKA_AUTS_LEN);
454         return eap_sim_msg_finish(msg, NULL, NULL, 0);
455 }
456
457
458 static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
459                                                  struct eap_aka_data *data,
460                                                  u8 id,
461                                                  enum eap_sim_id_req id_req)
462 {
463         const u8 *identity = NULL;
464         size_t identity_len = 0;
465         struct eap_sim_msg *msg;
466
467         data->reauth = 0;
468         if (id_req == ANY_ID && data->reauth_id) {
469                 identity = data->reauth_id;
470                 identity_len = data->reauth_id_len;
471                 data->reauth = 1;
472         } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
473                    data->pseudonym) {
474                 identity = data->pseudonym;
475                 identity_len = data->pseudonym_len;
476                 eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
477         } else if (id_req != NO_ID_REQ) {
478                 identity = eap_get_config_identity(sm, &identity_len);
479                 if (identity) {
480                         eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
481                                                  CLEAR_REAUTH_ID);
482                 }
483         }
484         if (id_req != NO_ID_REQ)
485                 eap_aka_clear_identities(data, CLEAR_EAP_ID);
486
487         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
488         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
489                                EAP_AKA_SUBTYPE_IDENTITY);
490
491         if (identity) {
492                 wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
493                                   identity, identity_len);
494                 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
495                                 identity, identity_len);
496         }
497
498         return eap_sim_msg_finish(msg, NULL, NULL, 0);
499 }
500
501
502 static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data,
503                                                   u8 id)
504 {
505         struct eap_sim_msg *msg;
506
507         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id);
508         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
509                                EAP_AKA_SUBTYPE_CHALLENGE);
510         wpa_printf(MSG_DEBUG, "   AT_RES");
511         eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8,
512                         data->res, data->res_len);
513         eap_aka_add_checkcode(data, msg);
514         if (data->use_result_ind) {
515                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
516                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
517         }
518         wpa_printf(MSG_DEBUG, "   AT_MAC");
519         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
520         return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0);
521 }
522
523
524 static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data,
525                                                u8 id, int counter_too_small,
526                                                const u8 *nonce_s)
527 {
528         struct eap_sim_msg *msg;
529         unsigned int counter;
530
531         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
532                    id);
533         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
534                                EAP_AKA_SUBTYPE_REAUTHENTICATION);
535         wpa_printf(MSG_DEBUG, "   AT_IV");
536         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
537         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
538
539         if (counter_too_small) {
540                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
541                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
542                 counter = data->counter_too_small;
543         } else
544                 counter = data->counter;
545
546         wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
547         eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
548
549         if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
550                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
551                            "AT_ENCR_DATA");
552                 eap_sim_msg_free(msg);
553                 return NULL;
554         }
555         eap_aka_add_checkcode(data, msg);
556         if (data->use_result_ind) {
557                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
558                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
559         }
560         wpa_printf(MSG_DEBUG, "   AT_MAC");
561         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
562         return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
563                                   EAP_SIM_NONCE_S_LEN);
564 }
565
566
567 static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data,
568                                                      u8 id, u16 notification)
569 {
570         struct eap_sim_msg *msg;
571         u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
572
573         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id);
574         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
575                                EAP_AKA_SUBTYPE_NOTIFICATION);
576         if (k_aut && data->reauth) {
577                 wpa_printf(MSG_DEBUG, "   AT_IV");
578                 wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
579                 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
580                                            EAP_SIM_AT_ENCR_DATA);
581                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
582                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
583                                 NULL, 0);
584                 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
585                                              EAP_SIM_AT_PADDING)) {
586                         wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
587                                    "AT_ENCR_DATA");
588                         eap_sim_msg_free(msg);
589                         return NULL;
590                 }
591         }
592         if (k_aut) {
593                 wpa_printf(MSG_DEBUG, "   AT_MAC");
594                 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
595         }
596         return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
597 }
598
599
600 static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm,
601                                                 struct eap_aka_data *data,
602                                                 u8 id,
603                                                 const struct wpabuf *reqData,
604                                                 struct eap_sim_attrs *attr)
605 {
606         int id_error;
607         struct wpabuf *buf;
608
609         wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
610
611         id_error = 0;
612         switch (attr->id_req) {
613         case NO_ID_REQ:
614                 break;
615         case ANY_ID:
616                 if (data->num_id_req > 0)
617                         id_error++;
618                 data->num_id_req++;
619                 break;
620         case FULLAUTH_ID:
621                 if (data->num_id_req > 1)
622                         id_error++;
623                 data->num_id_req++;
624                 break;
625         case PERMANENT_ID:
626                 if (data->num_id_req > 2)
627                         id_error++;
628                 data->num_id_req++;
629                 break;
630         }
631         if (id_error) {
632                 wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
633                            "used within one authentication");
634                 return eap_aka_client_error(data, id,
635                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
636         }
637
638         buf = eap_aka_response_identity(sm, data, id, attr->id_req);
639
640         if (data->prev_id != id) {
641                 eap_aka_add_id_msg(data, reqData);
642                 eap_aka_add_id_msg(data, buf);
643                 data->prev_id = id;
644         }
645
646         return buf;
647 }
648
649
650 static int eap_aka_verify_mac(struct eap_aka_data *data,
651                               const struct wpabuf *req,
652                               const u8 *mac, const u8 *extra,
653                               size_t extra_len)
654 {
655         if (data->eap_method == EAP_TYPE_AKA_PRIME)
656                 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
657                                                  extra_len);
658         return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
659 }
660
661
662 #ifdef EAP_AKA_PRIME
663 static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data,
664                                                 u8 id, u16 kdf)
665 {
666         struct eap_sim_msg *msg;
667
668         data->kdf = kdf;
669         wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF "
670                    "select)", id);
671         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
672                                EAP_AKA_SUBTYPE_CHALLENGE);
673         wpa_printf(MSG_DEBUG, "   AT_KDF");
674         eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0);
675         return eap_sim_msg_finish(msg, NULL, NULL, 0);
676 }
677
678
679 static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data,
680                                              u8 id, struct eap_sim_attrs *attr)
681 {
682         size_t i;
683
684         for (i = 0; i < attr->kdf_count; i++) {
685                 if (attr->kdf[i] == EAP_AKA_PRIME_KDF)
686                         return eap_aka_prime_kdf_select(data, id,
687                                                         EAP_AKA_PRIME_KDF);
688         }
689
690         /* No matching KDF found - fail authentication as if AUTN had been
691          * incorrect */
692         return eap_aka_authentication_reject(data, id);
693 }
694
695
696 static int eap_aka_prime_kdf_valid(struct eap_aka_data *data,
697                                    struct eap_sim_attrs *attr)
698 {
699         size_t i, j;
700
701         if (attr->kdf_count == 0)
702                 return 0;
703
704         /* The only allowed (and required) duplication of a KDF is the addition
705          * of the selected KDF into the beginning of the list. */
706
707         if (data->kdf) {
708                 if (attr->kdf[0] != data->kdf) {
709                         wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
710                                    "accept the selected KDF");
711                         return 0;
712                 }
713
714                 for (i = 1; i < attr->kdf_count; i++) {
715                         if (attr->kdf[i] == data->kdf)
716                                 break;
717                 }
718                 if (i == attr->kdf_count &&
719                     attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) {
720                         wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
721                                    "duplicate the selected KDF");
722                         return 0;
723                 }
724
725                 /* TODO: should check that the list is identical to the one
726                  * used in the previous Challenge message apart from the added
727                  * entry in the beginning. */
728         }
729
730         for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) {
731                 for (j = i + 1; j < attr->kdf_count; j++) {
732                         if (attr->kdf[i] == attr->kdf[j]) {
733                                 wpa_printf(MSG_WARNING, "EAP-AKA': The server "
734                                            "included a duplicated KDF");
735                                 return 0;
736                         }
737                 }
738         }
739
740         return 1;
741 }
742 #endif /* EAP_AKA_PRIME */
743
744
745 static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
746                                                  struct eap_aka_data *data,
747                                                  u8 id,
748                                                  const struct wpabuf *reqData,
749                                                  struct eap_sim_attrs *attr)
750 {
751         const u8 *identity;
752         size_t identity_len;
753         int res;
754         struct eap_sim_attrs eattr;
755
756         wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
757
758         if (attr->checkcode &&
759             eap_aka_verify_checkcode(data, attr->checkcode,
760                                      attr->checkcode_len)) {
761                 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
762                            "message");
763                 return eap_aka_client_error(data, id,
764                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
765         }
766
767 #ifdef EAP_AKA_PRIME
768         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
769                 if (!attr->kdf_input || attr->kdf_input_len == 0) {
770                         wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message "
771                                    "did not include non-empty AT_KDF_INPUT");
772                         /* Fail authentication as if AUTN had been incorrect */
773                         return eap_aka_authentication_reject(data, id);
774                 }
775                 os_free(data->network_name);
776                 data->network_name = os_malloc(attr->kdf_input_len);
777                 if (data->network_name == NULL) {
778                         wpa_printf(MSG_WARNING, "EAP-AKA': No memory for "
779                                    "storing Network Name");
780                         return eap_aka_authentication_reject(data, id);
781                 }
782                 os_memcpy(data->network_name, attr->kdf_input,
783                           attr->kdf_input_len);
784                 data->network_name_len = attr->kdf_input_len;
785                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name "
786                                   "(AT_KDF_INPUT)",
787                                   data->network_name, data->network_name_len);
788                 /* TODO: check Network Name per 3GPP.33.402 */
789
790                 if (!eap_aka_prime_kdf_valid(data, attr))
791                         return eap_aka_authentication_reject(data, id);
792
793                 if (attr->kdf[0] != EAP_AKA_PRIME_KDF)
794                         return eap_aka_prime_kdf_neg(data, id, attr);
795
796                 data->kdf = EAP_AKA_PRIME_KDF;
797                 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
798         }
799
800         if (data->eap_method == EAP_TYPE_AKA && attr->bidding) {
801                 u16 flags = WPA_GET_BE16(attr->bidding);
802                 if ((flags & EAP_AKA_BIDDING_FLAG_D) &&
803                     eap_allowed_method(sm, EAP_VENDOR_IETF,
804                                        EAP_TYPE_AKA_PRIME)) {
805                         wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from "
806                                    "AKA' to AKA detected");
807                         /* Fail authentication as if AUTN had been incorrect */
808                         return eap_aka_authentication_reject(data, id);
809                 }
810         }
811 #endif /* EAP_AKA_PRIME */
812
813         data->reauth = 0;
814         if (!attr->mac || !attr->rand || !attr->autn) {
815                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
816                            "did not include%s%s%s",
817                            !attr->mac ? " AT_MAC" : "",
818                            !attr->rand ? " AT_RAND" : "",
819                            !attr->autn ? " AT_AUTN" : "");
820                 return eap_aka_client_error(data, id,
821                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
822         }
823         os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
824         os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
825
826         res = eap_aka_umts_auth(sm, data);
827         if (res == -1) {
828                 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
829                            "failed (AUTN)");
830                 return eap_aka_authentication_reject(data, id);
831         } else if (res == -2) {
832                 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
833                            "failed (AUTN seq# -> AUTS)");
834                 return eap_aka_synchronization_failure(data, id);
835         } else if (res) {
836                 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
837                 return eap_aka_client_error(data, id,
838                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
839         }
840 #ifdef EAP_AKA_PRIME
841         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
842                 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
843                  * needed 6-octet SQN ^AK for CK',IK' derivation */
844                 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
845                                                  data->autn,
846                                                  data->network_name,
847                                                  data->network_name_len);
848         }
849 #endif /* EAP_AKA_PRIME */
850         if (data->last_eap_identity) {
851                 identity = data->last_eap_identity;
852                 identity_len = data->last_eap_identity_len;
853         } else if (data->pseudonym) {
854                 identity = data->pseudonym;
855                 identity_len = data->pseudonym_len;
856         } else
857                 identity = eap_get_config_identity(sm, &identity_len);
858         wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
859                           "derivation", identity, identity_len);
860         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
861                 eap_aka_prime_derive_keys(identity, identity_len, data->ik,
862                                           data->ck, data->k_encr, data->k_aut,
863                                           data->k_re, data->msk, data->emsk);
864         } else {
865                 eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
866                                   data->mk);
867                 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
868                                     data->msk, data->emsk);
869         }
870         if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
871                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
872                            "used invalid AT_MAC");
873                 return eap_aka_client_error(data, id,
874                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
875         }
876
877         /* Old reauthentication and pseudonym identities must not be used
878          * anymore. In other words, if no new identities are received, full
879          * authentication will be used on next reauthentication. */
880         eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
881                                  CLEAR_EAP_ID);
882
883         if (attr->encr_data) {
884                 u8 *decrypted;
885                 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
886                                                attr->encr_data_len, attr->iv,
887                                                &eattr, 0);
888                 if (decrypted == NULL) {
889                         return eap_aka_client_error(
890                                 data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
891                 }
892                 eap_aka_learn_ids(data, &eattr);
893                 os_free(decrypted);
894         }
895
896         if (data->result_ind && attr->result_ind)
897                 data->use_result_ind = 1;
898
899         if (data->state != FAILURE && data->state != RESULT_FAILURE) {
900                 eap_aka_state(data, data->use_result_ind ?
901                               RESULT_SUCCESS : SUCCESS);
902         }
903
904         data->num_id_req = 0;
905         data->num_notification = 0;
906         /* RFC 4187 specifies that counter is initialized to one after
907          * fullauth, but initializing it to zero makes it easier to implement
908          * reauth verification. */
909         data->counter = 0;
910         return eap_aka_response_challenge(data, id);
911 }
912
913
914 static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
915                                                struct eap_sim_attrs *attr)
916 {
917         struct eap_sim_attrs eattr;
918         u8 *decrypted;
919
920         if (attr->encr_data == NULL || attr->iv == NULL) {
921                 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
922                            "reauth did not include encrypted data");
923                 return -1;
924         }
925
926         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
927                                        attr->encr_data_len, attr->iv, &eattr,
928                                        0);
929         if (decrypted == NULL) {
930                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
931                            "data from notification message");
932                 return -1;
933         }
934
935         if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
936                 wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
937                            "message does not match with counter in reauth "
938                            "message");
939                 os_free(decrypted);
940                 return -1;
941         }
942
943         os_free(decrypted);
944         return 0;
945 }
946
947
948 static int eap_aka_process_notification_auth(struct eap_aka_data *data,
949                                              const struct wpabuf *reqData,
950                                              struct eap_sim_attrs *attr)
951 {
952         if (attr->mac == NULL) {
953                 wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
954                            "Notification message");
955                 return -1;
956         }
957
958         if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
959                 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
960                            "used invalid AT_MAC");
961                 return -1;
962         }
963
964         if (data->reauth &&
965             eap_aka_process_notification_reauth(data, attr)) {
966                 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
967                            "message after reauth");
968                 return -1;
969         }
970
971         return 0;
972 }
973
974
975 static struct wpabuf * eap_aka_process_notification(
976         struct eap_sm *sm, struct eap_aka_data *data, u8 id,
977         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
978 {
979         wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
980         if (data->num_notification > 0) {
981                 wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
982                            "rounds (only one allowed)");
983                 return eap_aka_client_error(data, id,
984                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
985         }
986         data->num_notification++;
987         if (attr->notification == -1) {
988                 wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
989                            "Notification message");
990                 return eap_aka_client_error(data, id,
991                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
992         }
993
994         if ((attr->notification & 0x4000) == 0 &&
995             eap_aka_process_notification_auth(data, reqData, attr)) {
996                 return eap_aka_client_error(data, id,
997                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
998         }
999
1000         eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
1001         if (attr->notification >= 0 && attr->notification < 32768) {
1002                 eap_aka_state(data, FAILURE);
1003         } else if (attr->notification == EAP_SIM_SUCCESS &&
1004                    data->state == RESULT_SUCCESS)
1005                 eap_aka_state(data, SUCCESS);
1006         return eap_aka_response_notification(data, id, attr->notification);
1007 }
1008
1009
1010 static struct wpabuf * eap_aka_process_reauthentication(
1011         struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1012         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1013 {
1014         struct eap_sim_attrs eattr;
1015         u8 *decrypted;
1016
1017         wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
1018
1019         if (attr->checkcode &&
1020             eap_aka_verify_checkcode(data, attr->checkcode,
1021                                      attr->checkcode_len)) {
1022                 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1023                            "message");
1024                 return eap_aka_client_error(data, id,
1025                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1026         }
1027
1028         if (data->reauth_id == NULL) {
1029                 wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
1030                            "reauthentication, but no reauth_id available");
1031                 return eap_aka_client_error(data, id,
1032                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1033         }
1034
1035         data->reauth = 1;
1036         if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1037                 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1038                            "did not have valid AT_MAC");
1039                 return eap_aka_client_error(data, id,
1040                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1041         }
1042
1043         if (attr->encr_data == NULL || attr->iv == NULL) {
1044                 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1045                            "message did not include encrypted data");
1046                 return eap_aka_client_error(data, id,
1047                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1048         }
1049
1050         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1051                                        attr->encr_data_len, attr->iv, &eattr,
1052                                        0);
1053         if (decrypted == NULL) {
1054                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1055                            "data from reauthentication message");
1056                 return eap_aka_client_error(data, id,
1057                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1058         }
1059
1060         if (eattr.nonce_s == NULL || eattr.counter < 0) {
1061                 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
1062                            !eattr.nonce_s ? " AT_NONCE_S" : "",
1063                            eattr.counter < 0 ? " AT_COUNTER" : "");
1064                 os_free(decrypted);
1065                 return eap_aka_client_error(data, id,
1066                                             EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1067         }
1068
1069         if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
1070                 struct wpabuf *res;
1071                 wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
1072                            "(%d <= %d)", eattr.counter, data->counter);
1073                 data->counter_too_small = eattr.counter;
1074
1075                 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1076                  * reauth_id must not be used to start a new reauthentication.
1077                  * However, since it was used in the last EAP-Response-Identity
1078                  * packet, it has to saved for the following fullauth to be
1079                  * used in MK derivation. */
1080                 os_free(data->last_eap_identity);
1081                 data->last_eap_identity = data->reauth_id;
1082                 data->last_eap_identity_len = data->reauth_id_len;
1083                 data->reauth_id = NULL;
1084                 data->reauth_id_len = 0;
1085
1086                 res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s);
1087                 os_free(decrypted);
1088
1089                 return res;
1090         }
1091         data->counter = eattr.counter;
1092
1093         os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
1094         wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
1095                     data->nonce_s, EAP_SIM_NONCE_S_LEN);
1096
1097         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1098                 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
1099                                                  data->reauth_id,
1100                                                  data->reauth_id_len,
1101                                                  data->nonce_s,
1102                                                  data->msk, data->emsk);
1103         } else {
1104                 eap_sim_derive_keys_reauth(data->counter, data->reauth_id,
1105                                            data->reauth_id_len,
1106                                            data->nonce_s, data->mk,
1107                                            data->msk, data->emsk);
1108         }
1109         eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1110         eap_aka_learn_ids(data, &eattr);
1111
1112         if (data->result_ind && attr->result_ind)
1113                 data->use_result_ind = 1;
1114
1115         if (data->state != FAILURE && data->state != RESULT_FAILURE) {
1116                 eap_aka_state(data, data->use_result_ind ?
1117                               RESULT_SUCCESS : SUCCESS);
1118         }
1119
1120         data->num_id_req = 0;
1121         data->num_notification = 0;
1122         if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
1123                 wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
1124                            "fast reauths performed - force fullauth");
1125                 eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1126         }
1127         os_free(decrypted);
1128         return eap_aka_response_reauth(data, id, 0, data->nonce_s);
1129 }
1130
1131
1132 static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv,
1133                                        struct eap_method_ret *ret,
1134                                        const struct wpabuf *reqData)
1135 {
1136         struct eap_aka_data *data = priv;
1137         const struct eap_hdr *req;
1138         u8 subtype, id;
1139         struct wpabuf *res;
1140         const u8 *pos;
1141         struct eap_sim_attrs attr;
1142         size_t len;
1143
1144         wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData);
1145         if (eap_get_config_identity(sm, &len) == NULL) {
1146                 wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
1147                 eap_sm_request_identity(sm);
1148                 ret->ignore = TRUE;
1149                 return NULL;
1150         }
1151
1152         pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData,
1153                                &len);
1154         if (pos == NULL || len < 1) {
1155                 ret->ignore = TRUE;
1156                 return NULL;
1157         }
1158         req = wpabuf_head(reqData);
1159         id = req->identifier;
1160         len = be_to_host16(req->length);
1161
1162         ret->ignore = FALSE;
1163         ret->methodState = METHOD_MAY_CONT;
1164         ret->decision = DECISION_FAIL;
1165         ret->allowNotifications = TRUE;
1166
1167         subtype = *pos++;
1168         wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
1169         pos += 2; /* Reserved */
1170
1171         if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr,
1172                                data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1173                                0)) {
1174                 res = eap_aka_client_error(data, id,
1175                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1176                 goto done;
1177         }
1178
1179         switch (subtype) {
1180         case EAP_AKA_SUBTYPE_IDENTITY:
1181                 res = eap_aka_process_identity(sm, data, id, reqData, &attr);
1182                 break;
1183         case EAP_AKA_SUBTYPE_CHALLENGE:
1184                 res = eap_aka_process_challenge(sm, data, id, reqData, &attr);
1185                 break;
1186         case EAP_AKA_SUBTYPE_NOTIFICATION:
1187                 res = eap_aka_process_notification(sm, data, id, reqData,
1188                                                    &attr);
1189                 break;
1190         case EAP_AKA_SUBTYPE_REAUTHENTICATION:
1191                 res = eap_aka_process_reauthentication(sm, data, id, reqData,
1192                                                        &attr);
1193                 break;
1194         case EAP_AKA_SUBTYPE_CLIENT_ERROR:
1195                 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
1196                 res = eap_aka_client_error(data, id,
1197                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1198                 break;
1199         default:
1200                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
1201                 res = eap_aka_client_error(data, id,
1202                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1203                 break;
1204         }
1205
1206 done:
1207         if (data->state == FAILURE) {
1208                 ret->decision = DECISION_FAIL;
1209                 ret->methodState = METHOD_DONE;
1210         } else if (data->state == SUCCESS) {
1211                 ret->decision = data->use_result_ind ?
1212                         DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
1213                 /*
1214                  * It is possible for the server to reply with AKA
1215                  * Notification, so we must allow the method to continue and
1216                  * not only accept EAP-Success at this point.
1217                  */
1218                 ret->methodState = data->use_result_ind ?
1219                         METHOD_DONE : METHOD_MAY_CONT;
1220         } else if (data->state == RESULT_FAILURE)
1221                 ret->methodState = METHOD_CONT;
1222         else if (data->state == RESULT_SUCCESS)
1223                 ret->methodState = METHOD_CONT;
1224
1225         if (ret->methodState == METHOD_DONE) {
1226                 ret->allowNotifications = FALSE;
1227         }
1228
1229         return res;
1230 }
1231
1232
1233 static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
1234 {
1235         struct eap_aka_data *data = priv;
1236         return data->pseudonym || data->reauth_id;
1237 }
1238
1239
1240 static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
1241 {
1242         struct eap_aka_data *data = priv;
1243         eap_aka_clear_identities(data, CLEAR_EAP_ID);
1244         data->prev_id = -1;
1245         wpabuf_free(data->id_msgs);
1246         data->id_msgs = NULL;
1247         data->use_result_ind = 0;
1248 }
1249
1250
1251 static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
1252 {
1253         struct eap_aka_data *data = priv;
1254         data->num_id_req = 0;
1255         data->num_notification = 0;
1256         eap_aka_state(data, CONTINUE);
1257         return priv;
1258 }
1259
1260
1261 static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
1262                                        size_t *len)
1263 {
1264         struct eap_aka_data *data = priv;
1265
1266         if (data->reauth_id) {
1267                 *len = data->reauth_id_len;
1268                 return data->reauth_id;
1269         }
1270
1271         if (data->pseudonym) {
1272                 *len = data->pseudonym_len;
1273                 return data->pseudonym;
1274         }
1275
1276         return NULL;
1277 }
1278
1279
1280 static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
1281 {
1282         struct eap_aka_data *data = priv;
1283         return data->state == SUCCESS;
1284 }
1285
1286
1287 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1288 {
1289         struct eap_aka_data *data = priv;
1290         u8 *key;
1291
1292         if (data->state != SUCCESS)
1293                 return NULL;
1294
1295         key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1296         if (key == NULL)
1297                 return NULL;
1298
1299         *len = EAP_SIM_KEYING_DATA_LEN;
1300         os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1301
1302         return key;
1303 }
1304
1305
1306 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1307 {
1308         struct eap_aka_data *data = priv;
1309         u8 *key;
1310
1311         if (data->state != SUCCESS)
1312                 return NULL;
1313
1314         key = os_malloc(EAP_EMSK_LEN);
1315         if (key == NULL)
1316                 return NULL;
1317
1318         *len = EAP_EMSK_LEN;
1319         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1320
1321         return key;
1322 }
1323
1324
1325 int eap_peer_aka_register(void)
1326 {
1327         struct eap_method *eap;
1328         int ret;
1329
1330         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1331                                     EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1332         if (eap == NULL)
1333                 return -1;
1334
1335         eap->init = eap_aka_init;
1336         eap->deinit = eap_aka_deinit;
1337         eap->process = eap_aka_process;
1338         eap->isKeyAvailable = eap_aka_isKeyAvailable;
1339         eap->getKey = eap_aka_getKey;
1340         eap->has_reauth_data = eap_aka_has_reauth_data;
1341         eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1342         eap->init_for_reauth = eap_aka_init_for_reauth;
1343         eap->get_identity = eap_aka_get_identity;
1344         eap->get_emsk = eap_aka_get_emsk;
1345
1346         ret = eap_peer_method_register(eap);
1347         if (ret)
1348                 eap_peer_method_free(eap);
1349         return ret;
1350 }
1351
1352
1353 #ifdef EAP_AKA_PRIME
1354 int eap_peer_aka_prime_register(void)
1355 {
1356         struct eap_method *eap;
1357         int ret;
1358
1359         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1360                                     EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1361                                     "AKA'");
1362         if (eap == NULL)
1363                 return -1;
1364
1365         eap->init = eap_aka_prime_init;
1366         eap->deinit = eap_aka_deinit;
1367         eap->process = eap_aka_process;
1368         eap->isKeyAvailable = eap_aka_isKeyAvailable;
1369         eap->getKey = eap_aka_getKey;
1370         eap->has_reauth_data = eap_aka_has_reauth_data;
1371         eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1372         eap->init_for_reauth = eap_aka_init_for_reauth;
1373         eap->get_identity = eap_aka_get_identity;
1374         eap->get_emsk = eap_aka_get_emsk;
1375
1376         ret = eap_peer_method_register(eap);
1377         if (ret)
1378                 eap_peer_method_free(eap);
1379
1380         return ret;
1381 }
1382 #endif /* EAP_AKA_PRIME */