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