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