1 /*
2 * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
3 * Copyright (c) 2005-2012, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "utils/base64.h"
13 #include "crypto/sha256.h"
14 #include "crypto/crypto.h"
15 #include "crypto/random.h"
16 #include "eap_common/eap_sim_common.h"
17 #include "eap_server/eap_i.h"
18 #include "eap_server/eap_sim_db.h"
19
20
21 struct eap_aka_data {
22 u8 mk[EAP_SIM_MK_LEN];
23 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
24 u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
25 u8 k_encr[EAP_SIM_K_ENCR_LEN];
26 u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
27 u8 msk[EAP_SIM_KEYING_DATA_LEN];
28 u8 emsk[EAP_EMSK_LEN];
29 u8 rand[EAP_AKA_RAND_LEN];
30 u8 autn[EAP_AKA_AUTN_LEN];
31 u8 ck[EAP_AKA_CK_LEN];
32 u8 ik[EAP_AKA_IK_LEN];
33 u8 res[EAP_AKA_RES_MAX_LEN];
34 u8 reauth_mac[EAP_SIM_MAC_LEN];
35 size_t res_len;
36 enum {
37 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
38 } state;
39 char *next_pseudonym;
40 char *next_reauth_id;
41 u16 counter;
42 struct eap_sim_reauth *reauth;
43 int auts_reported; /* whether the current AUTS has been reported to the
44 * eap_sim_db */
45 u16 notification;
46 int use_result_ind;
47
48 struct wpabuf *id_msgs;
49 int pending_id;
50 u8 eap_method;
51 u8 *network_name;
52 size_t network_name_len;
53 u16 kdf;
54 int identity_round;
55 char permanent[20]; /* Permanent username */
56 };
57
58
59 static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
60
61
eap_aka_state_txt(int state)62 static const char * eap_aka_state_txt(int state)
63 {
64 switch (state) {
65 case IDENTITY:
66 return "IDENTITY";
67 case CHALLENGE:
68 return "CHALLENGE";
69 case REAUTH:
70 return "REAUTH";
71 case SUCCESS:
72 return "SUCCESS";
73 case FAILURE:
74 return "FAILURE";
75 case NOTIFICATION:
76 return "NOTIFICATION";
77 default:
78 return "Unknown?!";
79 }
80 }
81
82
eap_aka_state(struct eap_aka_data * data,int state)83 static void eap_aka_state(struct eap_aka_data *data, int state)
84 {
85 wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
86 eap_aka_state_txt(data->state),
87 eap_aka_state_txt(state));
88 data->state = state;
89 }
90
91
eap_aka_check_identity_reauth(struct eap_sm * sm,struct eap_aka_data * data,const char * username)92 static int eap_aka_check_identity_reauth(struct eap_sm *sm,
93 struct eap_aka_data *data,
94 const char *username)
95 {
96 if (data->eap_method == EAP_TYPE_AKA_PRIME &&
97 username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
98 return 0;
99 if (data->eap_method == EAP_TYPE_AKA &&
100 username[0] != EAP_AKA_REAUTH_ID_PREFIX)
101 return 0;
102
103 wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
104 data->reauth = eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv,
105 username);
106 if (data->reauth == NULL) {
107 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
108 "request full auth identity");
109 /* Remain in IDENTITY state for another round */
110 return 0;
111 }
112
113 wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
114 os_strlcpy(data->permanent, data->reauth->permanent,
115 sizeof(data->permanent));
116 data->counter = data->reauth->counter;
117 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
118 os_memcpy(data->k_encr, data->reauth->k_encr,
119 EAP_SIM_K_ENCR_LEN);
120 os_memcpy(data->k_aut, data->reauth->k_aut,
121 EAP_AKA_PRIME_K_AUT_LEN);
122 os_memcpy(data->k_re, data->reauth->k_re,
123 EAP_AKA_PRIME_K_RE_LEN);
124 } else {
125 os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
126 }
127
128 eap_aka_state(data, REAUTH);
129 return 1;
130 }
131
132
eap_aka_check_identity(struct eap_sm * sm,struct eap_aka_data * data)133 static void eap_aka_check_identity(struct eap_sm *sm,
134 struct eap_aka_data *data)
135 {
136 char *username;
137
138 /* Check if we already know the identity from EAP-Response/Identity */
139
140 username = sim_get_username(sm->identity, sm->identity_len);
141 if (username == NULL)
142 return;
143
144 if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
145 os_free(username);
146 /*
147 * Since re-auth username was recognized, skip AKA/Identity
148 * exchange.
149 */
150 return;
151 }
152
153 if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
154 username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
155 (data->eap_method == EAP_TYPE_AKA &&
156 username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
157 const char *permanent;
158 wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
159 username);
160 permanent = eap_sim_db_get_permanent(
161 sm->cfg->eap_sim_db_priv, username);
162 if (permanent == NULL) {
163 os_free(username);
164 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
165 "identity - request permanent identity");
166 /* Remain in IDENTITY state for another round */
167 return;
168 }
169 os_strlcpy(data->permanent, permanent,
170 sizeof(data->permanent));
171 /*
172 * Since pseudonym username was recognized, skip AKA/Identity
173 * exchange.
174 */
175 eap_aka_fullauth(sm, data);
176 }
177
178 os_free(username);
179 }
180
181
eap_aka_init(struct eap_sm * sm)182 static void * eap_aka_init(struct eap_sm *sm)
183 {
184 struct eap_aka_data *data;
185
186 if (!sm->cfg->eap_sim_db_priv) {
187 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
188 return NULL;
189 }
190
191 data = os_zalloc(sizeof(*data));
192 if (data == NULL)
193 return NULL;
194
195 data->eap_method = EAP_TYPE_AKA;
196
197 data->state = IDENTITY;
198 data->pending_id = -1;
199 eap_aka_check_identity(sm, data);
200
201 return data;
202 }
203
204
205 #ifdef EAP_SERVER_AKA_PRIME
eap_aka_prime_init(struct eap_sm * sm)206 static void * eap_aka_prime_init(struct eap_sm *sm)
207 {
208 struct eap_aka_data *data;
209 /* TODO: make ANID configurable; see 3GPP TS 24.302 */
210 char *network_name = "WLAN";
211
212 if (sm->cfg->eap_sim_db_priv == NULL) {
213 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
214 return NULL;
215 }
216
217 data = os_zalloc(sizeof(*data));
218 if (data == NULL)
219 return NULL;
220
221 data->eap_method = EAP_TYPE_AKA_PRIME;
222 data->network_name = (u8 *) os_strdup(network_name);
223 if (data->network_name == NULL) {
224 os_free(data);
225 return NULL;
226 }
227
228 data->network_name_len = os_strlen(network_name);
229
230 data->state = IDENTITY;
231 data->pending_id = -1;
232 eap_aka_check_identity(sm, data);
233
234 return data;
235 }
236 #endif /* EAP_SERVER_AKA_PRIME */
237
238
eap_aka_reset(struct eap_sm * sm,void * priv)239 static void eap_aka_reset(struct eap_sm *sm, void *priv)
240 {
241 struct eap_aka_data *data = priv;
242 os_free(data->next_pseudonym);
243 os_free(data->next_reauth_id);
244 wpabuf_free(data->id_msgs);
245 os_free(data->network_name);
246 bin_clear_free(data, sizeof(*data));
247 }
248
249
eap_aka_add_id_msg(struct eap_aka_data * data,const struct wpabuf * msg)250 static int eap_aka_add_id_msg(struct eap_aka_data *data,
251 const struct wpabuf *msg)
252 {
253 if (msg == NULL)
254 return -1;
255
256 if (data->id_msgs == NULL) {
257 data->id_msgs = wpabuf_dup(msg);
258 return data->id_msgs == NULL ? -1 : 0;
259 }
260
261 if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
262 return -1;
263 wpabuf_put_buf(data->id_msgs, msg);
264
265 return 0;
266 }
267
268
eap_aka_add_checkcode(struct eap_aka_data * data,struct eap_sim_msg * msg)269 static void eap_aka_add_checkcode(struct eap_aka_data *data,
270 struct eap_sim_msg *msg)
271 {
272 const u8 *addr;
273 size_t len;
274 u8 hash[SHA256_MAC_LEN];
275
276 wpa_printf(MSG_DEBUG, " AT_CHECKCODE");
277
278 if (data->id_msgs == NULL) {
279 /*
280 * No EAP-AKA/Identity packets were exchanged - send empty
281 * checkcode.
282 */
283 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
284 return;
285 }
286
287 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
288 addr = wpabuf_head(data->id_msgs);
289 len = wpabuf_len(data->id_msgs);
290 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
291 if (data->eap_method == EAP_TYPE_AKA_PRIME)
292 sha256_vector(1, &addr, &len, hash);
293 else
294 sha1_vector(1, &addr, &len, hash);
295
296 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
297 data->eap_method == EAP_TYPE_AKA_PRIME ?
298 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
299 }
300
301
eap_aka_verify_checkcode(struct eap_aka_data * data,const u8 * checkcode,size_t checkcode_len)302 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
303 const u8 *checkcode, size_t checkcode_len)
304 {
305 const u8 *addr;
306 size_t len;
307 u8 hash[SHA256_MAC_LEN];
308 size_t hash_len;
309
310 if (checkcode == NULL)
311 return -1;
312
313 if (data->id_msgs == NULL) {
314 if (checkcode_len != 0) {
315 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
316 "indicates that AKA/Identity messages were "
317 "used, but they were not");
318 return -1;
319 }
320 return 0;
321 }
322
323 hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
324 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
325
326 if (checkcode_len != hash_len) {
327 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
328 "that AKA/Identity message were not used, but they "
329 "were");
330 return -1;
331 }
332
333 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
334 addr = wpabuf_head(data->id_msgs);
335 len = wpabuf_len(data->id_msgs);
336 if (data->eap_method == EAP_TYPE_AKA_PRIME)
337 sha256_vector(1, &addr, &len, hash);
338 else
339 sha1_vector(1, &addr, &len, hash);
340
341 if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
342 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
343 return -1;
344 }
345
346 return 0;
347 }
348
349
eap_aka_build_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id)350 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
351 struct eap_aka_data *data, u8 id)
352 {
353 struct eap_sim_msg *msg;
354 struct wpabuf *buf;
355
356 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
357 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
358 EAP_AKA_SUBTYPE_IDENTITY);
359 data->identity_round++;
360 if (data->identity_round == 1) {
361 /*
362 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
363 * ignored and the AKA/Identity is used to request the
364 * identity.
365 */
366 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
367 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
368 } else if (data->identity_round > 3) {
369 /* Cannot use more than three rounds of Identity messages */
370 eap_sim_msg_free(msg);
371 return NULL;
372 } else if (sm->identity && sm->identity_len > 0 &&
373 (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
374 sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
375 /* Reauth id may have expired - try fullauth */
376 wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ");
377 eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
378 } else {
379 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
380 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
381 }
382 buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
383 if (eap_aka_add_id_msg(data, buf) < 0) {
384 wpabuf_free(buf);
385 return NULL;
386 }
387 data->pending_id = id;
388 return buf;
389 }
390
391
eap_aka_build_encr(struct eap_sm * sm,struct eap_aka_data * data,struct eap_sim_msg * msg,u16 counter,const u8 * nonce_s)392 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
393 struct eap_sim_msg *msg, u16 counter,
394 const u8 *nonce_s)
395 {
396 os_free(data->next_pseudonym);
397 if (!(sm->cfg->eap_sim_id & 0x01)) {
398 /* Use of pseudonyms disabled in configuration */
399 data->next_pseudonym = NULL;
400 } else if (!nonce_s) {
401 data->next_pseudonym =
402 eap_sim_db_get_next_pseudonym(
403 sm->cfg->eap_sim_db_priv,
404 data->eap_method == EAP_TYPE_AKA_PRIME ?
405 EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
406 } else {
407 /* Do not update pseudonym during re-authentication */
408 data->next_pseudonym = NULL;
409 }
410 os_free(data->next_reauth_id);
411 if (!(sm->cfg->eap_sim_id & 0x02)) {
412 /* Use of fast reauth disabled in configuration */
413 data->next_reauth_id = NULL;
414 } else if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
415 data->next_reauth_id =
416 eap_sim_db_get_next_reauth_id(
417 sm->cfg->eap_sim_db_priv,
418 data->eap_method == EAP_TYPE_AKA_PRIME ?
419 EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
420 } else {
421 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
422 "count exceeded - force full authentication");
423 data->next_reauth_id = NULL;
424 }
425
426 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
427 counter == 0 && nonce_s == NULL)
428 return 0;
429
430 wpa_printf(MSG_DEBUG, " AT_IV");
431 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
432 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
433
434 if (counter > 0) {
435 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
436 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
437 }
438
439 if (nonce_s) {
440 wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
441 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
442 EAP_SIM_NONCE_S_LEN);
443 }
444
445 if (data->next_pseudonym) {
446 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
447 data->next_pseudonym);
448 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
449 os_strlen(data->next_pseudonym),
450 (u8 *) data->next_pseudonym,
451 os_strlen(data->next_pseudonym));
452 }
453
454 if (data->next_reauth_id) {
455 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
456 data->next_reauth_id);
457 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
458 os_strlen(data->next_reauth_id),
459 (u8 *) data->next_reauth_id,
460 os_strlen(data->next_reauth_id));
461 }
462
463 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
464 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
465 "AT_ENCR_DATA");
466 return -1;
467 }
468
469 return 0;
470 }
471
472
eap_aka_build_challenge(struct eap_sm * sm,struct eap_aka_data * data,u8 id)473 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
474 struct eap_aka_data *data,
475 u8 id)
476 {
477 struct eap_sim_msg *msg;
478
479 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
480 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
481 EAP_AKA_SUBTYPE_CHALLENGE);
482 wpa_printf(MSG_DEBUG, " AT_RAND");
483 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
484 wpa_printf(MSG_DEBUG, " AT_AUTN");
485 eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
486 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
487 if (data->kdf) {
488 /* Add the selected KDF into the beginning */
489 wpa_printf(MSG_DEBUG, " AT_KDF");
490 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
491 NULL, 0);
492 }
493 wpa_printf(MSG_DEBUG, " AT_KDF");
494 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
495 NULL, 0);
496 wpa_printf(MSG_DEBUG, " AT_KDF_INPUT");
497 eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
498 data->network_name_len,
499 data->network_name, data->network_name_len);
500 }
501
502 if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
503 eap_sim_msg_free(msg);
504 return NULL;
505 }
506
507 eap_aka_add_checkcode(data, msg);
508
509 if (sm->cfg->eap_sim_aka_result_ind) {
510 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
511 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
512 }
513
514 #ifdef EAP_SERVER_AKA_PRIME
515 if (data->eap_method == EAP_TYPE_AKA) {
516 u16 flags = 0;
517 int i;
518 int aka_prime_preferred = 0;
519
520 i = 0;
521 while (sm->user && i < EAP_MAX_METHODS &&
522 (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
523 sm->user->methods[i].method != EAP_TYPE_NONE)) {
524 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
525 if (sm->user->methods[i].method ==
526 EAP_TYPE_AKA)
527 break;
528 if (sm->user->methods[i].method ==
529 EAP_TYPE_AKA_PRIME) {
530 aka_prime_preferred = 1;
531 break;
532 }
533 }
534 i++;
535 }
536
537 if (aka_prime_preferred)
538 flags |= EAP_AKA_BIDDING_FLAG_D;
539 eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
540 }
541 #endif /* EAP_SERVER_AKA_PRIME */
542
543 wpa_printf(MSG_DEBUG, " AT_MAC");
544 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
545 return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
546 }
547
548
eap_aka_build_reauth(struct eap_sm * sm,struct eap_aka_data * data,u8 id)549 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
550 struct eap_aka_data *data, u8 id)
551 {
552 struct eap_sim_msg *msg;
553 struct wpabuf *buf;
554
555 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
556
557 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
558 return NULL;
559 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
560 data->nonce_s, EAP_SIM_NONCE_S_LEN);
561
562 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
563 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
564 sm->identity,
565 sm->identity_len,
566 data->nonce_s,
567 data->msk, data->emsk);
568 } else {
569 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
570 data->msk, data->emsk);
571 eap_sim_derive_keys_reauth(data->counter, sm->identity,
572 sm->identity_len, data->nonce_s,
573 data->mk, data->msk, data->emsk);
574 }
575
576 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
577 EAP_AKA_SUBTYPE_REAUTHENTICATION);
578
579 if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
580 eap_sim_msg_free(msg);
581 return NULL;
582 }
583
584 eap_aka_add_checkcode(data, msg);
585
586 if (sm->cfg->eap_sim_aka_result_ind) {
587 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
588 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
589 }
590
591 wpa_printf(MSG_DEBUG, " AT_MAC");
592 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
593 buf = eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
594
595 /* Remember this MAC before sending it to the peer. This MAC is used for
596 * Session-Id calculation after receiving response from the peer and
597 * after all other checks pass. */
598 os_memcpy(data->reauth_mac,
599 wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN,
600 EAP_SIM_MAC_LEN);
601
602 return buf;
603 }
604
605
eap_aka_build_notification(struct eap_sm * sm,struct eap_aka_data * data,u8 id)606 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
607 struct eap_aka_data *data,
608 u8 id)
609 {
610 struct eap_sim_msg *msg;
611
612 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
613 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
614 EAP_AKA_SUBTYPE_NOTIFICATION);
615 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification);
616 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
617 NULL, 0);
618 if (data->use_result_ind) {
619 if (data->reauth) {
620 wpa_printf(MSG_DEBUG, " AT_IV");
621 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
622 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
623 EAP_SIM_AT_ENCR_DATA);
624 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)",
625 data->counter);
626 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
627 NULL, 0);
628
629 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
630 EAP_SIM_AT_PADDING)) {
631 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
632 "encrypt AT_ENCR_DATA");
633 eap_sim_msg_free(msg);
634 return NULL;
635 }
636 }
637
638 wpa_printf(MSG_DEBUG, " AT_MAC");
639 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
640 }
641 return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
642 }
643
644
eap_aka_buildReq(struct eap_sm * sm,void * priv,u8 id)645 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
646 {
647 struct eap_aka_data *data = priv;
648
649 data->auts_reported = 0;
650 switch (data->state) {
651 case IDENTITY:
652 return eap_aka_build_identity(sm, data, id);
653 case CHALLENGE:
654 return eap_aka_build_challenge(sm, data, id);
655 case REAUTH:
656 return eap_aka_build_reauth(sm, data, id);
657 case NOTIFICATION:
658 return eap_aka_build_notification(sm, data, id);
659 default:
660 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
661 "buildReq", data->state);
662 break;
663 }
664 return NULL;
665 }
666
667
eap_aka_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)668 static bool eap_aka_check(struct eap_sm *sm, void *priv,
669 struct wpabuf *respData)
670 {
671 struct eap_aka_data *data = priv;
672 const u8 *pos;
673 size_t len;
674
675 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
676 &len);
677 if (pos == NULL || len < 3) {
678 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
679 return true;
680 }
681
682 return false;
683 }
684
685
eap_aka_subtype_ok(struct eap_aka_data * data,u8 subtype)686 static bool eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
687 {
688 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
689 subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
690 return false;
691
692 switch (data->state) {
693 case IDENTITY:
694 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
695 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
696 "subtype %d", subtype);
697 return true;
698 }
699 break;
700 case CHALLENGE:
701 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
702 subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
703 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
704 "subtype %d", subtype);
705 return true;
706 }
707 break;
708 case REAUTH:
709 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
710 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
711 "subtype %d", subtype);
712 return true;
713 }
714 break;
715 case NOTIFICATION:
716 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
717 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
718 "subtype %d", subtype);
719 return true;
720 }
721 break;
722 default:
723 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
724 "processing a response", data->state);
725 return true;
726 }
727
728 return false;
729 }
730
731
eap_aka_determine_identity(struct eap_sm * sm,struct eap_aka_data * data)732 static void eap_aka_determine_identity(struct eap_sm *sm,
733 struct eap_aka_data *data)
734 {
735 char *username;
736
737 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
738 sm->identity, sm->identity_len);
739
740 username = sim_get_username(sm->identity, sm->identity_len);
741 if (!username)
742 goto fail;
743
744 if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
745 os_free(username);
746 return;
747 }
748
749 if (((data->eap_method == EAP_TYPE_AKA_PRIME &&
750 username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
751 (data->eap_method == EAP_TYPE_AKA &&
752 username[0] == EAP_AKA_REAUTH_ID_PREFIX)) &&
753 data->identity_round == 1) {
754 /* Remain in IDENTITY state for another round to request full
755 * auth identity since we did not recognize reauth id */
756 os_free(username);
757 return;
758 }
759
760 if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
761 username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
762 (data->eap_method == EAP_TYPE_AKA &&
763 username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
764 const char *permanent;
765 wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
766 username);
767 permanent = eap_sim_db_get_permanent(
768 sm->cfg->eap_sim_db_priv, username);
769 os_free(username);
770 if (permanent == NULL) {
771 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
772 "identity - request permanent identity");
773 /* Remain in IDENTITY state for another round */
774 return;
775 }
776 os_strlcpy(data->permanent, permanent,
777 sizeof(data->permanent));
778 } else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
779 username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
780 (data->eap_method == EAP_TYPE_AKA &&
781 username[0] == EAP_AKA_PERMANENT_PREFIX)) {
782 wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
783 username);
784 os_strlcpy(data->permanent, username, sizeof(data->permanent));
785 os_free(username);
786 #ifdef CRYPTO_RSA_OAEP_SHA256
787 } else if (sm->identity_len > 1 && sm->identity[0] == '\0') {
788 char *enc_id, *pos, *end;
789 size_t enc_id_len;
790 u8 *decoded_id;
791 size_t decoded_id_len;
792 struct wpabuf *enc, *dec;
793 u8 *new_id;
794
795 os_free(username);
796 if (!sm->cfg->imsi_privacy_key) {
797 wpa_printf(MSG_DEBUG,
798 "EAP-AKA: Received encrypted identity, but no IMSI privacy key configured to decrypt it");
799 goto fail;
800 }
801
802 enc_id = (char *) &sm->identity[1];
803 end = (char *) &sm->identity[sm->identity_len];
804 for (pos = enc_id; pos < end; pos++) {
805 if (*pos == ',')
806 break;
807 }
808 enc_id_len = pos - enc_id;
809
810 wpa_hexdump_ascii(MSG_DEBUG,
811 "EAP-AKA: Encrypted permanent identity",
812 enc_id, enc_id_len);
813 decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len);
814 if (!decoded_id) {
815 wpa_printf(MSG_DEBUG,
816 "EAP-AKA: Could not base64 decode encrypted identity");
817 goto fail;
818 }
819 wpa_hexdump(MSG_DEBUG,
820 "EAP-AKA: Decoded encrypted permanent identity",
821 decoded_id, decoded_id_len);
822 enc = wpabuf_alloc_copy(decoded_id, decoded_id_len);
823 os_free(decoded_id);
824 if (!enc)
825 goto fail;
826 dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key,
827 enc);
828 wpabuf_free(enc);
829 if (!dec) {
830 wpa_printf(MSG_DEBUG,
831 "EAP-AKA: Failed to decrypt encrypted identity");
832 goto fail;
833 }
834 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Decrypted permanent identity",
835 wpabuf_head(dec), wpabuf_len(dec));
836 username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec));
837 if (!username) {
838 wpabuf_free(dec);
839 goto fail;
840 }
841 new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec));
842 if (!new_id) {
843 wpabuf_free(dec);
844 goto fail;
845 }
846 os_free(sm->identity);
847 sm->identity = new_id;
848 sm->identity_len = wpabuf_len(dec);
849 wpabuf_free(dec);
850 os_strlcpy(data->permanent, username, sizeof(data->permanent));
851 os_free(username);
852 #endif /* CRYPTO_RSA_OAEP_SHA256 */
853 } else {
854 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
855 username);
856 os_free(username);
857 goto fail;
858 return;
859 }
860
861 eap_aka_fullauth(sm, data);
862 return;
863
864 fail:
865 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
866 eap_aka_state(data, NOTIFICATION);
867 }
868
869
eap_aka_fullauth(struct eap_sm * sm,struct eap_aka_data * data)870 static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
871 {
872 size_t identity_len;
873 int res;
874
875 res = eap_sim_db_get_aka_auth(sm->cfg->eap_sim_db_priv, data->permanent,
876 data->rand, data->autn, data->ik,
877 data->ck, data->res, &data->res_len, sm);
878 if (res == EAP_SIM_DB_PENDING) {
879 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
880 "not yet available - pending request");
881 sm->method_pending = METHOD_PENDING_WAIT;
882 return;
883 }
884
885 if (data->permanent[0] == EAP_AKA_PERMANENT_PREFIX ||
886 data->permanent[0] == EAP_AKA_PRIME_PERMANENT_PREFIX)
887 os_strlcpy(sm->imsi, &data->permanent[1], sizeof(sm->imsi));
888
889 #ifdef EAP_SERVER_AKA_PRIME
890 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
891 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
892 * needed 6-octet SQN ^AK for CK',IK' derivation */
893 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
894 data->autn,
895 data->network_name,
896 data->network_name_len);
897 }
898 #endif /* EAP_SERVER_AKA_PRIME */
899
900 data->reauth = NULL;
901 data->counter = 0; /* reset re-auth counter since this is full auth */
902
903 if (res != 0) {
904 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
905 "authentication data for the peer");
906 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
907 eap_aka_state(data, NOTIFICATION);
908 return;
909 }
910 if (sm->method_pending == METHOD_PENDING_WAIT) {
911 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
912 "available - abort pending wait");
913 sm->method_pending = METHOD_PENDING_NONE;
914 }
915
916 identity_len = sm->identity_len;
917 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
918 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
919 "character from identity");
920 identity_len--;
921 }
922 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
923 sm->identity, identity_len);
924
925 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
926 eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
927 data->ck, data->k_encr, data->k_aut,
928 data->k_re, data->msk, data->emsk);
929 } else {
930 eap_aka_derive_mk(sm->identity, identity_len, data->ik,
931 data->ck, data->mk);
932 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
933 data->msk, data->emsk);
934 }
935
936 eap_aka_state(data, CHALLENGE);
937 }
938
939
eap_aka_process_identity(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)940 static void eap_aka_process_identity(struct eap_sm *sm,
941 struct eap_aka_data *data,
942 struct wpabuf *respData,
943 struct eap_sim_attrs *attr)
944 {
945 u8 *new_identity;
946
947 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
948
949 if (attr->mac || attr->iv || attr->encr_data) {
950 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
951 "received in EAP-Response/AKA-Identity");
952 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
953 eap_aka_state(data, NOTIFICATION);
954 return;
955 }
956
957 /*
958 * We always request identity with AKA/Identity, so the peer is
959 * required to have replied with one.
960 */
961 if (!attr->identity || attr->identity_len == 0) {
962 wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
963 "identity");
964 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
965 eap_aka_state(data, NOTIFICATION);
966 return;
967 }
968
969 new_identity = os_malloc(attr->identity_len);
970 if (new_identity == NULL) {
971 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
972 eap_aka_state(data, NOTIFICATION);
973 return;
974 }
975 os_free(sm->identity);
976 sm->identity = new_identity;
977 os_memcpy(sm->identity, attr->identity, attr->identity_len);
978 sm->identity_len = attr->identity_len;
979
980 eap_aka_determine_identity(sm, data);
981 if (eap_get_id(respData) == data->pending_id) {
982 data->pending_id = -1;
983 eap_aka_add_id_msg(data, respData);
984 }
985 }
986
987
eap_aka_verify_mac(struct eap_aka_data * data,const struct wpabuf * req,const u8 * mac,const u8 * extra,size_t extra_len)988 static int eap_aka_verify_mac(struct eap_aka_data *data,
989 const struct wpabuf *req,
990 const u8 *mac, const u8 *extra,
991 size_t extra_len)
992 {
993 if (data->eap_method == EAP_TYPE_AKA_PRIME)
994 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
995 extra_len);
996 return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
997 }
998
999
eap_aka_process_challenge(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1000 static void eap_aka_process_challenge(struct eap_sm *sm,
1001 struct eap_aka_data *data,
1002 struct wpabuf *respData,
1003 struct eap_sim_attrs *attr)
1004 {
1005 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
1006
1007 #ifdef EAP_SERVER_AKA_PRIME
1008 #if 0
1009 /* KDF negotiation; to be enabled only after more than one KDF is
1010 * supported */
1011 if (data->eap_method == EAP_TYPE_AKA_PRIME &&
1012 attr->kdf_count == 1 && attr->mac == NULL) {
1013 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
1014 wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
1015 "unknown KDF");
1016 data->notification =
1017 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1018 eap_aka_state(data, NOTIFICATION);
1019 return;
1020 }
1021
1022 data->kdf = attr->kdf[0];
1023
1024 /* Allow negotiation to continue with the selected KDF by
1025 * sending another Challenge message */
1026 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
1027 return;
1028 }
1029 #endif
1030 #endif /* EAP_SERVER_AKA_PRIME */
1031
1032 if (attr->checkcode &&
1033 eap_aka_verify_checkcode(data, attr->checkcode,
1034 attr->checkcode_len)) {
1035 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1036 "message");
1037 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1038 eap_aka_state(data, NOTIFICATION);
1039 return;
1040 }
1041 if (attr->mac == NULL ||
1042 eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
1043 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
1044 "did not include valid AT_MAC");
1045 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1046 eap_aka_state(data, NOTIFICATION);
1047 return;
1048 }
1049
1050 /*
1051 * AT_RES is padded, so verify that there is enough room for RES and
1052 * that the RES length in bits matches with the expected RES.
1053 */
1054 if (attr->res == NULL || attr->res_len < data->res_len ||
1055 attr->res_len_bits != data->res_len * 8 ||
1056 os_memcmp_const(attr->res, data->res, data->res_len) != 0) {
1057 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
1058 "include valid AT_RES (attr len=%lu, res len=%lu "
1059 "bits, expected %lu bits)",
1060 (unsigned long) attr->res_len,
1061 (unsigned long) attr->res_len_bits,
1062 (unsigned long) data->res_len * 8);
1063 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1064 eap_aka_state(data, NOTIFICATION);
1065 return;
1066 }
1067
1068 wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
1069 "correct AT_MAC");
1070 if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
1071 data->use_result_ind = 1;
1072 data->notification = EAP_SIM_SUCCESS;
1073 eap_aka_state(data, NOTIFICATION);
1074 } else
1075 eap_aka_state(data, SUCCESS);
1076
1077 if (data->next_pseudonym) {
1078 eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv,
1079 data->permanent,
1080 data->next_pseudonym);
1081 data->next_pseudonym = NULL;
1082 }
1083 if (data->next_reauth_id) {
1084 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1085 #ifdef EAP_SERVER_AKA_PRIME
1086 eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
1087 data->permanent,
1088 data->next_reauth_id,
1089 data->counter + 1,
1090 data->k_encr, data->k_aut,
1091 data->k_re);
1092 #endif /* EAP_SERVER_AKA_PRIME */
1093 } else {
1094 eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
1095 data->permanent,
1096 data->next_reauth_id,
1097 data->counter + 1,
1098 data->mk);
1099 }
1100 data->next_reauth_id = NULL;
1101 }
1102 }
1103
1104
eap_aka_process_sync_failure(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1105 static void eap_aka_process_sync_failure(struct eap_sm *sm,
1106 struct eap_aka_data *data,
1107 struct wpabuf *respData,
1108 struct eap_sim_attrs *attr)
1109 {
1110 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
1111
1112 if (attr->auts == NULL) {
1113 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
1114 "message did not include valid AT_AUTS");
1115 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1116 eap_aka_state(data, NOTIFICATION);
1117 return;
1118 }
1119
1120 /* Avoid re-reporting AUTS when processing pending EAP packet by
1121 * maintaining a local flag stating whether this AUTS has already been
1122 * reported. */
1123 if (!data->auts_reported &&
1124 eap_sim_db_resynchronize(sm->cfg->eap_sim_db_priv, data->permanent,
1125 attr->auts, data->rand)) {
1126 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
1127 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1128 eap_aka_state(data, NOTIFICATION);
1129 return;
1130 }
1131 data->auts_reported = 1;
1132
1133 /* Remain in CHALLENGE state to re-try after resynchronization */
1134 eap_aka_fullauth(sm, data);
1135 }
1136
1137
eap_aka_process_reauth(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1138 static void eap_aka_process_reauth(struct eap_sm *sm,
1139 struct eap_aka_data *data,
1140 struct wpabuf *respData,
1141 struct eap_sim_attrs *attr)
1142 {
1143 struct eap_sim_attrs eattr;
1144 u8 *decrypted = NULL;
1145
1146 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
1147
1148 if (attr->mac == NULL ||
1149 eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
1150 EAP_SIM_NONCE_S_LEN)) {
1151 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
1152 "did not include valid AT_MAC");
1153 goto fail;
1154 }
1155
1156 if (attr->encr_data == NULL || attr->iv == NULL) {
1157 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1158 "message did not include encrypted data");
1159 goto fail;
1160 }
1161
1162 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1163 attr->encr_data_len, attr->iv, &eattr,
1164 0);
1165 if (decrypted == NULL) {
1166 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1167 "data from reauthentication message");
1168 goto fail;
1169 }
1170
1171 if (eattr.counter != data->counter) {
1172 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
1173 "used incorrect counter %u, expected %u",
1174 eattr.counter, data->counter);
1175 goto fail;
1176 }
1177 os_free(decrypted);
1178 decrypted = NULL;
1179
1180 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
1181 "the correct AT_MAC");
1182
1183 if (eattr.counter_too_small) {
1184 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
1185 "included AT_COUNTER_TOO_SMALL - starting full "
1186 "authentication");
1187 eap_aka_fullauth(sm, data);
1188 return;
1189 }
1190
1191 if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
1192 data->use_result_ind = 1;
1193 data->notification = EAP_SIM_SUCCESS;
1194 eap_aka_state(data, NOTIFICATION);
1195 } else
1196 eap_aka_state(data, SUCCESS);
1197
1198 if (data->next_reauth_id) {
1199 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1200 #ifdef EAP_SERVER_AKA_PRIME
1201 eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
1202 data->permanent,
1203 data->next_reauth_id,
1204 data->counter + 1,
1205 data->k_encr, data->k_aut,
1206 data->k_re);
1207 #endif /* EAP_SERVER_AKA_PRIME */
1208 } else {
1209 eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
1210 data->permanent,
1211 data->next_reauth_id,
1212 data->counter + 1,
1213 data->mk);
1214 }
1215 data->next_reauth_id = NULL;
1216 } else {
1217 eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
1218 data->reauth);
1219 data->reauth = NULL;
1220 }
1221
1222 return;
1223
1224 fail:
1225 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1226 eap_aka_state(data, NOTIFICATION);
1227 eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth);
1228 data->reauth = NULL;
1229 os_free(decrypted);
1230 }
1231
1232
eap_aka_process_client_error(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1233 static void eap_aka_process_client_error(struct eap_sm *sm,
1234 struct eap_aka_data *data,
1235 struct wpabuf *respData,
1236 struct eap_sim_attrs *attr)
1237 {
1238 wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
1239 attr->client_error_code);
1240 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1241 eap_aka_state(data, SUCCESS);
1242 else
1243 eap_aka_state(data, FAILURE);
1244 }
1245
1246
eap_aka_process_authentication_reject(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1247 static void eap_aka_process_authentication_reject(
1248 struct eap_sm *sm, struct eap_aka_data *data,
1249 struct wpabuf *respData, struct eap_sim_attrs *attr)
1250 {
1251 wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
1252 eap_aka_state(data, FAILURE);
1253 }
1254
1255
eap_aka_process_notification(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1256 static void eap_aka_process_notification(struct eap_sm *sm,
1257 struct eap_aka_data *data,
1258 struct wpabuf *respData,
1259 struct eap_sim_attrs *attr)
1260 {
1261 wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
1262 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1263 eap_aka_state(data, SUCCESS);
1264 else
1265 eap_aka_state(data, FAILURE);
1266 }
1267
1268
eap_aka_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)1269 static void eap_aka_process(struct eap_sm *sm, void *priv,
1270 struct wpabuf *respData)
1271 {
1272 struct eap_aka_data *data = priv;
1273 const u8 *pos, *end;
1274 u8 subtype;
1275 size_t len;
1276 struct eap_sim_attrs attr;
1277
1278 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
1279 &len);
1280 if (pos == NULL || len < 3)
1281 return;
1282
1283 end = pos + len;
1284 subtype = *pos;
1285 pos += 3;
1286
1287 if (eap_aka_subtype_ok(data, subtype)) {
1288 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
1289 "EAP-AKA Subtype in EAP Response");
1290 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1291 eap_aka_state(data, NOTIFICATION);
1292 return;
1293 }
1294
1295 if (eap_sim_parse_attr(pos, end, &attr,
1296 data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1297 0)) {
1298 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
1299 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1300 eap_aka_state(data, NOTIFICATION);
1301 return;
1302 }
1303
1304 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
1305 eap_aka_process_client_error(sm, data, respData, &attr);
1306 return;
1307 }
1308
1309 if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
1310 eap_aka_process_authentication_reject(sm, data, respData,
1311 &attr);
1312 return;
1313 }
1314
1315 switch (data->state) {
1316 case IDENTITY:
1317 eap_aka_process_identity(sm, data, respData, &attr);
1318 break;
1319 case CHALLENGE:
1320 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
1321 eap_aka_process_sync_failure(sm, data, respData,
1322 &attr);
1323 } else {
1324 eap_aka_process_challenge(sm, data, respData, &attr);
1325 }
1326 break;
1327 case REAUTH:
1328 eap_aka_process_reauth(sm, data, respData, &attr);
1329 break;
1330 case NOTIFICATION:
1331 eap_aka_process_notification(sm, data, respData, &attr);
1332 break;
1333 default:
1334 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
1335 "process", data->state);
1336 break;
1337 }
1338 }
1339
1340
eap_aka_isDone(struct eap_sm * sm,void * priv)1341 static bool eap_aka_isDone(struct eap_sm *sm, void *priv)
1342 {
1343 struct eap_aka_data *data = priv;
1344 return data->state == SUCCESS || data->state == FAILURE;
1345 }
1346
1347
eap_aka_getKey(struct eap_sm * sm,void * priv,size_t * len)1348 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1349 {
1350 struct eap_aka_data *data = priv;
1351 u8 *key;
1352
1353 if (data->state != SUCCESS)
1354 return NULL;
1355
1356 key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN);
1357 if (key == NULL)
1358 return NULL;
1359 *len = EAP_SIM_KEYING_DATA_LEN;
1360 return key;
1361 }
1362
1363
eap_aka_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1364 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1365 {
1366 struct eap_aka_data *data = priv;
1367 u8 *key;
1368
1369 if (data->state != SUCCESS)
1370 return NULL;
1371
1372 key = os_memdup(data->emsk, EAP_EMSK_LEN);
1373 if (key == NULL)
1374 return NULL;
1375 *len = EAP_EMSK_LEN;
1376 return key;
1377 }
1378
1379
eap_aka_isSuccess(struct eap_sm * sm,void * priv)1380 static bool eap_aka_isSuccess(struct eap_sm *sm, void *priv)
1381 {
1382 struct eap_aka_data *data = priv;
1383 return data->state == SUCCESS;
1384 }
1385
1386
eap_aka_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1387 static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1388 {
1389 struct eap_aka_data *data = priv;
1390 u8 *id;
1391
1392 if (data->state != SUCCESS)
1393 return NULL;
1394
1395 if (!data->reauth)
1396 *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
1397 else
1398 *len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
1399 id = os_malloc(*len);
1400 if (id == NULL)
1401 return NULL;
1402
1403 id[0] = data->eap_method;
1404 if (!data->reauth) {
1405 os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
1406 os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn,
1407 EAP_AKA_AUTN_LEN);
1408 } else {
1409 os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
1410 os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
1411 EAP_SIM_MAC_LEN);
1412 }
1413 wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
1414
1415 return id;
1416 }
1417
1418
eap_server_aka_register(void)1419 int eap_server_aka_register(void)
1420 {
1421 struct eap_method *eap;
1422
1423 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1424 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1425 if (eap == NULL)
1426 return -1;
1427
1428 eap->init = eap_aka_init;
1429 eap->reset = eap_aka_reset;
1430 eap->buildReq = eap_aka_buildReq;
1431 eap->check = eap_aka_check;
1432 eap->process = eap_aka_process;
1433 eap->isDone = eap_aka_isDone;
1434 eap->getKey = eap_aka_getKey;
1435 eap->isSuccess = eap_aka_isSuccess;
1436 eap->get_emsk = eap_aka_get_emsk;
1437 eap->getSessionId = eap_aka_get_session_id;
1438
1439 return eap_server_method_register(eap);
1440 }
1441
1442
1443 #ifdef EAP_SERVER_AKA_PRIME
eap_server_aka_prime_register(void)1444 int eap_server_aka_prime_register(void)
1445 {
1446 struct eap_method *eap;
1447
1448 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1449 EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1450 "AKA'");
1451 if (eap == NULL)
1452 return -1;
1453
1454 eap->init = eap_aka_prime_init;
1455 eap->reset = eap_aka_reset;
1456 eap->buildReq = eap_aka_buildReq;
1457 eap->check = eap_aka_check;
1458 eap->process = eap_aka_process;
1459 eap->isDone = eap_aka_isDone;
1460 eap->getKey = eap_aka_getKey;
1461 eap->isSuccess = eap_aka_isSuccess;
1462 eap->get_emsk = eap_aka_get_emsk;
1463 eap->getSessionId = eap_aka_get_session_id;
1464
1465 return eap_server_method_register(eap);
1466 }
1467 #endif /* EAP_SERVER_AKA_PRIME */
1468