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