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