12
12
* See README and COPYING for more details.
19
17
#include "common.h"
21
19
#include "wpa_supplicant.h"
22
#include "config_ssid.h"
24
21
#include "pcsc_funcs.h"
25
22
#include "eap_sim_common.h"
27
/* EAP-AKA Subtypes */
28
#define EAP_AKA_SUBTYPE_CHALLENGE 1
29
#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
30
#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
31
#define EAP_AKA_SUBTYPE_IDENTITY 5
32
#define EAP_AKA_SUBTYPE_NOTIFICATION 12
33
#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13
34
#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14
36
/* AT_CLIENT_ERROR_CODE error codes */
37
#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0
39
#define AKA_AUTS_LEN 14
40
#define RES_MAX_LEN 16
43
#define EAP_AKA_MAX_FAST_REAUTHS 1000
45
25
struct eap_aka_data {
46
u8 ik[IK_LEN], ck[CK_LEN], res[RES_MAX_LEN];
26
u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
48
28
u8 nonce_s[EAP_SIM_NONCE_S_LEN];
49
29
u8 mk[EAP_SIM_MK_LEN];
50
30
u8 k_aut[EAP_SIM_K_AUT_LEN];
51
31
u8 k_encr[EAP_SIM_K_ENCR_LEN];
52
32
u8 msk[EAP_SIM_KEYING_DATA_LEN];
53
u8 rand[AKA_RAND_LEN], autn[AKA_AUTN_LEN];
54
u8 auts[AKA_AUTS_LEN];
33
u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
34
u8 auts[EAP_AKA_AUTS_LEN];
56
36
int num_id_req, num_notification;
102
81
#else /* PCSC_FUNCS */
103
82
/* These hardcoded Kc and SRES values are used for testing.
104
83
* Could consider making them configurable. */
105
memset(data->res, '2', RES_MAX_LEN);
107
memset(data->ik, '3', IK_LEN);
108
memset(data->ck, '4', CK_LEN);
84
memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
85
data->res_len = EAP_AKA_RES_MAX_LEN;
86
memset(data->ik, '3', EAP_AKA_IK_LEN);
87
memset(data->ck, '4', EAP_AKA_CK_LEN);
110
u8 autn[AKA_AUTN_LEN];
111
memset(autn, '1', AKA_AUTN_LEN);
112
if (memcmp(autn, data->autn, AKA_AUTN_LEN) != 0) {
89
u8 autn[EAP_AKA_AUTN_LEN];
90
memset(autn, '1', EAP_AKA_AUTN_LEN);
91
if (memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
113
92
wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
114
93
"with expected value");
99
static int test_resync = 1;
101
/* Test Resynchronization */
119
108
#endif /* PCSC_FUNCS */
123
static void eap_aka_derive_mk(struct eap_aka_data *data,
124
const u8 *identity, size_t identity_len)
130
len[0] = identity_len;
136
/* MK = SHA1(Identity|IK|CK) */
137
sha1_vector(3, addr, len, data->mk);
138
wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, IK_LEN);
139
wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, CK_LEN);
140
wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", data->mk, EAP_SIM_MK_LEN);
144
112
#define CLEAR_PSEUDONYM 0x01
145
113
#define CLEAR_REAUTH_ID 0x02
146
114
#define CLEAR_EAP_ID 0x04
265
230
EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
266
231
wpa_printf(MSG_DEBUG, " AT_AUTS");
267
eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, AKA_AUTS_LEN);
232
eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
268
234
return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
272
238
static u8 * eap_aka_response_identity(struct eap_sm *sm,
273
239
struct eap_aka_data *data,
240
const struct eap_hdr *req,
275
241
size_t *respDataLen,
276
242
enum eap_sim_id_req id_req)
278
struct wpa_ssid *config = eap_get_config(sm);
244
const u8 *identity = NULL;
280
245
size_t identity_len = 0;
281
246
struct eap_sim_msg *msg;
290
255
identity = data->pseudonym;
291
256
identity_len = data->pseudonym_len;
292
257
eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
293
} else if (id_req != NO_ID_REQ && config && config->identity) {
294
identity = config->identity;
295
identity_len = config->identity_len;
296
eap_aka_clear_identities(data,
297
CLEAR_PSEUDONYM | CLEAR_REAUTH_ID);
258
} else if (id_req != NO_ID_REQ) {
259
identity = eap_get_config_identity(sm, &identity_len);
261
eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
299
265
if (id_req != NO_ID_REQ)
300
266
eap_aka_clear_identities(data, CLEAR_EAP_ID);
302
268
wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)",
304
270
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
305
271
EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY);
318
static u8 * eap_aka_response_challenge(struct eap_sm *sm,
319
struct eap_aka_data *data,
284
static u8 * eap_aka_response_challenge(struct eap_aka_data *data,
285
const struct eap_hdr *req,
321
286
size_t *respDataLen)
323
288
struct eap_sim_msg *msg;
325
290
wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)",
327
292
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
328
293
EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE);
329
294
wpa_printf(MSG_DEBUG, " AT_RES");
476
439
!attr->mac ? " AT_MAC" : "",
477
440
!attr->rand ? " AT_RAND" : "",
478
441
!attr->autn ? " AT_AUTN" : "");
479
return eap_aka_client_error(sm, data, req, respDataLen,
442
return eap_aka_client_error(data, req, respDataLen,
480
443
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
482
memcpy(data->rand, attr->rand, AKA_RAND_LEN);
483
memcpy(data->autn, attr->autn, AKA_AUTN_LEN);
445
memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
446
memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
485
448
res = eap_aka_umts_auth(sm, data);
487
450
wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
488
451
"failed (AUTN)");
489
return eap_aka_authentication_reject(sm, data, req,
452
return eap_aka_authentication_reject(data, req, respDataLen);
491
453
} else if (res == -2) {
492
454
wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
493
455
"failed (AUTN seq# -> AUTS)");
494
return eap_aka_synchronization_failure(sm, data, req,
456
return eap_aka_synchronization_failure(data, req, respDataLen);
496
457
} else if (res) {
497
458
wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
498
return eap_aka_client_error(sm, data, req, respDataLen,
459
return eap_aka_client_error(data, req, respDataLen,
499
460
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
501
462
if (data->last_eap_identity) {
504
465
} else if (data->pseudonym) {
505
466
identity = data->pseudonym;
506
467
identity_len = data->pseudonym_len;
508
identity = config->identity;
509
identity_len = config->identity_len;
469
identity = eap_get_config_identity(sm, &identity_len);
511
470
wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
512
471
"derivation", identity, identity_len);
513
eap_aka_derive_mk(data, identity, identity_len);
472
eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
514
474
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
515
if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
475
if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
476
attr->mac, (u8 *) "", 0)) {
517
477
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
518
478
"used invalid AT_MAC");
519
return eap_aka_client_error(sm, data, req, respDataLen,
479
return eap_aka_client_error(data, req, respDataLen,
520
480
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
529
489
if (attr->encr_data) {
530
if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
531
attr->encr_data_len, attr->iv, &eattr,
491
decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
492
attr->encr_data_len, attr->iv,
494
if (decrypted == NULL) {
533
495
return eap_aka_client_error(
534
sm, data, req, respDataLen,
496
data, req, respDataLen,
535
497
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
537
499
eap_aka_learn_ids(data, &eattr);
540
503
if (data->state != FAILURE)
543
506
data->num_id_req = 0;
544
507
data->num_notification = 0;
545
/* draft-arkko-pppext-eap-aka-12.txt specifies that counter
546
* is initialized to one after fullauth, but initializing it to
547
* zero makes it easier to implement reauth verification. */
508
/* RFC 4187 specifies that counter is initialized to one after
509
* fullauth, but initializing it to zero makes it easier to implement
510
* reauth verification. */
548
511
data->counter = 0;
549
return eap_aka_response_challenge(sm, data, req, respDataLen);
512
return eap_aka_response_challenge(data, req, respDataLen);
553
516
static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
556
517
struct eap_sim_attrs *attr)
558
519
struct eap_sim_attrs eattr;
560
522
if (attr->encr_data == NULL || attr->iv == NULL) {
561
523
wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
566
if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
567
attr->encr_data_len, attr->iv, &eattr, 0)) {
528
decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
529
attr->encr_data_len, attr->iv, &eattr,
531
if (decrypted == NULL) {
568
532
wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
569
533
"data from notification message");
573
if (eattr.counter != data->counter) {
537
if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
574
538
wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
575
539
"message does not match with counter in reauth "
584
550
static int eap_aka_process_notification_auth(struct eap_aka_data *data,
551
const struct eap_hdr *req,
586
552
size_t reqDataLen,
587
553
struct eap_sim_attrs *attr)
595
if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
561
if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
562
attr->mac, (u8 *) "", 0)) {
597
563
wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
598
564
"used invalid AT_MAC");
602
568
if (data->reauth &&
603
eap_aka_process_notification_reauth(data, req, reqDataLen, attr)) {
569
eap_aka_process_notification_reauth(data, attr)) {
604
570
wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
605
571
"message after reauth");
621
587
if (data->num_notification > 0) {
622
588
wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
623
589
"rounds (only one allowed)");
624
return eap_aka_client_error(sm, data, req, respDataLen,
590
return eap_aka_client_error(data, req, respDataLen,
625
591
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
627
593
data->num_notification++;
628
594
if (attr->notification == -1) {
629
595
wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
630
596
"Notification message");
631
return eap_aka_client_error(sm, data, req, respDataLen,
597
return eap_aka_client_error(data, req, respDataLen,
632
598
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
635
601
if ((attr->notification & 0x4000) == 0 &&
636
602
eap_aka_process_notification_auth(data, req, reqDataLen, attr)) {
637
return eap_aka_client_error(sm, data, req, respDataLen,
603
return eap_aka_client_error(data, req, respDataLen,
638
604
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
642
608
if (attr->notification >= 0 && attr->notification < 32768) {
643
609
data->state = FAILURE;
645
return eap_aka_response_notification(sm, data, req, respDataLen,
611
return eap_aka_response_notification(data, req, respDataLen,
646
612
attr->notification);
650
616
static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
651
617
struct eap_aka_data *data,
618
const struct eap_hdr *req,
653
619
size_t reqDataLen,
654
620
size_t *respDataLen,
655
621
struct eap_sim_attrs *attr)
657
623
struct eap_sim_attrs eattr;
659
626
wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
661
628
if (data->reauth_id == NULL) {
662
629
wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
663
630
"reauthentication, but no reauth_id available");
664
return eap_aka_client_error(sm, data, req, respDataLen,
631
return eap_aka_client_error(data, req, respDataLen,
665
632
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
668
635
data->reauth = 1;
669
if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen,
636
if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
670
637
attr->mac, (u8 *) "", 0)) {
671
638
wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
672
639
"did not have valid AT_MAC");
673
return eap_aka_client_error(sm, data, req, respDataLen,
640
return eap_aka_client_error(data, req, respDataLen,
674
641
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
677
644
if (attr->encr_data == NULL || attr->iv == NULL) {
678
645
wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
679
646
"message did not include encrypted data");
680
return eap_aka_client_error(sm, data, req, respDataLen,
647
return eap_aka_client_error(data, req, respDataLen,
681
648
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
684
if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
685
attr->encr_data_len, attr->iv, &eattr, 0)) {
651
decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
652
attr->encr_data_len, attr->iv, &eattr,
654
if (decrypted == NULL) {
686
655
wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
687
656
"data from reauthentication message");
688
return eap_aka_client_error(sm, data, req, respDataLen,
657
return eap_aka_client_error(data, req, respDataLen,
689
658
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
693
662
wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
694
663
!eattr.nonce_s ? " AT_NONCE_S" : "",
695
664
eattr.counter < 0 ? " AT_COUNTER" : "");
696
return eap_aka_client_error(sm, data, req, respDataLen,
666
return eap_aka_client_error(data, req, respDataLen,
697
667
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
700
if (eattr.counter <= data->counter) {
670
if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
701
671
wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
702
672
"(%d <= %d)", eattr.counter, data->counter);
703
673
data->counter_too_small = eattr.counter;
735
706
"fast reauths performed - force fullauth");
736
707
eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
738
return eap_aka_response_reauth(sm, data, req, respDataLen, 0);
710
return eap_aka_response_reauth(data, req, respDataLen, 0);
742
714
static u8 * eap_aka_process(struct eap_sm *sm, void *priv,
743
715
struct eap_method_ret *ret,
744
u8 *reqData, size_t reqDataLen,
716
const u8 *reqData, size_t reqDataLen,
745
717
size_t *respDataLen)
747
719
struct eap_aka_data *data = priv;
748
struct wpa_ssid *config = eap_get_config(sm);
750
u8 *pos, subtype, *res;
720
const struct eap_hdr *req;
751
723
struct eap_sim_attrs attr;
754
726
wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen);
755
if (config == NULL || config->identity == NULL) {
727
if (eap_get_config_identity(sm, &len) == NULL) {
756
728
wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
757
eap_sm_request_identity(sm, config);
729
eap_sm_request_identity(sm);
758
730
ret->ignore = TRUE;
762
req = (struct eap_hdr *) reqData;
763
pos = (u8 *) (req + 1);
764
if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_AKA ||
765
(len = be_to_host16(req->length)) > reqDataLen) {
766
wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
734
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA,
735
reqData, reqDataLen, &len);
736
if (pos == NULL || len < 1) {
767
737
ret->ignore = TRUE;
740
req = (const struct eap_hdr *) reqData;
741
len = be_to_host16(req->length);
771
743
ret->ignore = FALSE;
772
ret->methodState = METHOD_CONT;
744
ret->methodState = METHOD_MAY_CONT;
773
745
ret->decision = DECISION_FAIL;
774
746
ret->allowNotifications = TRUE;
777
748
subtype = *pos++;
778
749
wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
779
750
pos += 2; /* Reserved */
781
752
if (eap_sim_parse_attr(pos, reqData + len, &attr, 1, 0)) {
782
res = eap_aka_client_error(sm, data, req, respDataLen,
753
res = eap_aka_client_error(data, req, respDataLen,
783
754
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
787
758
switch (subtype) {
788
759
case EAP_AKA_SUBTYPE_IDENTITY:
789
res = eap_aka_process_identity(sm, data, req, len,
760
res = eap_aka_process_identity(sm, data, req,
790
761
respDataLen, &attr);
792
763
case EAP_AKA_SUBTYPE_CHALLENGE:
804
775
case EAP_AKA_SUBTYPE_CLIENT_ERROR:
805
776
wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
806
res = eap_aka_client_error(sm, data, req, respDataLen,
777
res = eap_aka_client_error(data, req, respDataLen,
807
778
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
810
781
wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
811
res = eap_aka_client_error(sm, data, req, respDataLen,
782
res = eap_aka_client_error(data, req, respDataLen,
812
783
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
902
const struct eap_method eap_method_aka =
873
int eap_peer_aka_register(void)
904
.method = EAP_TYPE_AKA,
906
.init = eap_aka_init,
907
.deinit = eap_aka_deinit,
908
.process = eap_aka_process,
909
.isKeyAvailable = eap_aka_isKeyAvailable,
910
.getKey = eap_aka_getKey,
911
.has_reauth_data = eap_aka_has_reauth_data,
912
.deinit_for_reauth = eap_aka_deinit_for_reauth,
913
.init_for_reauth = eap_aka_init_for_reauth,
914
.get_identity = eap_aka_get_identity,
875
struct eap_method *eap;
878
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
879
EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
883
eap->init = eap_aka_init;
884
eap->deinit = eap_aka_deinit;
885
eap->process = eap_aka_process;
886
eap->isKeyAvailable = eap_aka_isKeyAvailable;
887
eap->getKey = eap_aka_getKey;
888
eap->has_reauth_data = eap_aka_has_reauth_data;
889
eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
890
eap->init_for_reauth = eap_aka_init_for_reauth;
891
eap->get_identity = eap_aka_get_identity;
893
ret = eap_peer_method_register(eap);
895
eap_peer_method_free(eap);