2 * EAP peer method: EAP-SIM (RFC 4186)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "eap_peer/eap_i.h"
19 #include "eap_config.h"
20 #include "pcsc_funcs.h"
21 #include "eap_common/eap_sim_common.h"
28 size_t min_num_chal
, num_chal
;
30 u8 kc
[3][EAP_SIM_KC_LEN
];
31 u8 sres
[3][EAP_SIM_SRES_LEN
];
32 u8 nonce_mt
[EAP_SIM_NONCE_MT_LEN
], nonce_s
[EAP_SIM_NONCE_S_LEN
];
33 u8 mk
[EAP_SIM_MK_LEN
];
34 u8 k_aut
[EAP_SIM_K_AUT_LEN
];
35 u8 k_encr
[EAP_SIM_K_ENCR_LEN
];
36 u8 msk
[EAP_SIM_KEYING_DATA_LEN
];
37 u8 emsk
[EAP_EMSK_LEN
];
38 u8 rand
[3][GSM_RAND_LEN
];
40 int num_id_req
, num_notification
;
46 unsigned int counter
, counter_too_small
;
47 u8
*last_eap_identity
;
48 size_t last_eap_identity_len
;
50 CONTINUE
, RESULT_SUCCESS
, RESULT_FAILURE
, SUCCESS
, FAILURE
52 int result_ind
, use_result_ind
;
56 #ifndef CONFIG_NO_STDOUT_DEBUG
57 static const char * eap_sim_state_txt(int state
)
63 return "RESULT_SUCCESS";
65 return "RESULT_FAILURE";
74 #endif /* CONFIG_NO_STDOUT_DEBUG */
77 static void eap_sim_state(struct eap_sim_data
*data
, int state
)
79 wpa_printf(MSG_DEBUG
, "EAP-SIM: %s -> %s",
80 eap_sim_state_txt(data
->state
),
81 eap_sim_state_txt(state
));
86 static void * eap_sim_init(struct eap_sm
*sm
)
88 struct eap_sim_data
*data
;
89 struct eap_peer_config
*config
= eap_get_config(sm
);
91 data
= os_zalloc(sizeof(*data
));
95 if (os_get_random(data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
)) {
96 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to get random data "
102 data
->min_num_chal
= 2;
103 if (config
&& config
->phase1
) {
104 char *pos
= os_strstr(config
->phase1
, "sim_min_num_chal=");
106 data
->min_num_chal
= atoi(pos
+ 17);
107 if (data
->min_num_chal
< 2 || data
->min_num_chal
> 3) {
108 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid "
109 "sim_min_num_chal configuration "
110 "(%lu, expected 2 or 3)",
111 (unsigned long) data
->min_num_chal
);
115 wpa_printf(MSG_DEBUG
, "EAP-SIM: Set minimum number of "
117 (unsigned long) data
->min_num_chal
);
120 data
->result_ind
= os_strstr(config
->phase1
, "result_ind=1") !=
124 eap_sim_state(data
, CONTINUE
);
130 static void eap_sim_deinit(struct eap_sm
*sm
, void *priv
)
132 struct eap_sim_data
*data
= priv
;
134 os_free(data
->ver_list
);
135 os_free(data
->pseudonym
);
136 os_free(data
->reauth_id
);
137 os_free(data
->last_eap_identity
);
143 static int eap_sim_gsm_auth(struct eap_sm
*sm
, struct eap_sim_data
*data
)
145 wpa_printf(MSG_DEBUG
, "EAP-SIM: GSM authentication algorithm");
147 if (scard_gsm_auth(sm
->scard_ctx
, data
->rand
[0],
148 data
->sres
[0], data
->kc
[0]) ||
149 scard_gsm_auth(sm
->scard_ctx
, data
->rand
[1],
150 data
->sres
[1], data
->kc
[1]) ||
151 (data
->num_chal
> 2 &&
152 scard_gsm_auth(sm
->scard_ctx
, data
->rand
[2],
153 data
->sres
[2], data
->kc
[2]))) {
154 wpa_printf(MSG_DEBUG
, "EAP-SIM: GSM SIM authentication could "
158 #else /* PCSC_FUNCS */
159 /* These hardcoded Kc and SRES values are used for testing. RAND to
160 * KC/SREC mapping is very bogus as far as real authentication is
161 * concerned, but it is quite useful for cases where the AS is rotating
162 * the order of pre-configured values. */
165 for (i
= 0; i
< data
->num_chal
; i
++) {
166 if (data
->rand
[i
][0] == 0xaa) {
167 os_memcpy(data
->kc
[i
],
168 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
170 os_memcpy(data
->sres
[i
], "\xd1\xd2\xd3\xd4",
172 } else if (data
->rand
[i
][0] == 0xbb) {
173 os_memcpy(data
->kc
[i
],
174 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
176 os_memcpy(data
->sres
[i
], "\xe1\xe2\xe3\xe4",
179 os_memcpy(data
->kc
[i
],
180 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
182 os_memcpy(data
->sres
[i
], "\xf1\xf2\xf3\xf4",
187 #endif /* PCSC_FUNCS */
192 static int eap_sim_supported_ver(int version
)
194 return version
== EAP_SIM_VERSION
;
198 #define CLEAR_PSEUDONYM 0x01
199 #define CLEAR_REAUTH_ID 0x02
200 #define CLEAR_EAP_ID 0x04
202 static void eap_sim_clear_identities(struct eap_sim_data
*data
, int id
)
204 wpa_printf(MSG_DEBUG
, "EAP-SIM: forgetting old%s%s%s",
205 id
& CLEAR_PSEUDONYM
? " pseudonym" : "",
206 id
& CLEAR_REAUTH_ID
? " reauth_id" : "",
207 id
& CLEAR_EAP_ID
? " eap_id" : "");
208 if (id
& CLEAR_PSEUDONYM
) {
209 os_free(data
->pseudonym
);
210 data
->pseudonym
= NULL
;
211 data
->pseudonym_len
= 0;
213 if (id
& CLEAR_REAUTH_ID
) {
214 os_free(data
->reauth_id
);
215 data
->reauth_id
= NULL
;
216 data
->reauth_id_len
= 0;
218 if (id
& CLEAR_EAP_ID
) {
219 os_free(data
->last_eap_identity
);
220 data
->last_eap_identity
= NULL
;
221 data
->last_eap_identity_len
= 0;
226 static int eap_sim_learn_ids(struct eap_sim_data
*data
,
227 struct eap_sim_attrs
*attr
)
229 if (attr
->next_pseudonym
) {
230 os_free(data
->pseudonym
);
231 data
->pseudonym
= os_malloc(attr
->next_pseudonym_len
);
232 if (data
->pseudonym
== NULL
) {
233 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No memory for "
237 os_memcpy(data
->pseudonym
, attr
->next_pseudonym
,
238 attr
->next_pseudonym_len
);
239 data
->pseudonym_len
= attr
->next_pseudonym_len
;
240 wpa_hexdump_ascii(MSG_DEBUG
,
241 "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
243 data
->pseudonym_len
);
246 if (attr
->next_reauth_id
) {
247 os_free(data
->reauth_id
);
248 data
->reauth_id
= os_malloc(attr
->next_reauth_id_len
);
249 if (data
->reauth_id
== NULL
) {
250 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No memory for "
254 os_memcpy(data
->reauth_id
, attr
->next_reauth_id
,
255 attr
->next_reauth_id_len
);
256 data
->reauth_id_len
= attr
->next_reauth_id_len
;
257 wpa_hexdump_ascii(MSG_DEBUG
,
258 "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
260 data
->reauth_id_len
);
267 static struct wpabuf
* eap_sim_client_error(struct eap_sim_data
*data
, u8 id
,
270 struct eap_sim_msg
*msg
;
272 eap_sim_state(data
, FAILURE
);
273 data
->num_id_req
= 0;
274 data
->num_notification
= 0;
276 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, EAP_TYPE_SIM
,
277 EAP_SIM_SUBTYPE_CLIENT_ERROR
);
278 eap_sim_msg_add(msg
, EAP_SIM_AT_CLIENT_ERROR_CODE
, err
, NULL
, 0);
279 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
283 static struct wpabuf
* eap_sim_response_start(struct eap_sm
*sm
,
284 struct eap_sim_data
*data
, u8 id
,
285 enum eap_sim_id_req id_req
)
287 const u8
*identity
= NULL
;
288 size_t identity_len
= 0;
289 struct eap_sim_msg
*msg
;
292 if (id_req
== ANY_ID
&& data
->reauth_id
) {
293 identity
= data
->reauth_id
;
294 identity_len
= data
->reauth_id_len
;
296 } else if ((id_req
== ANY_ID
|| id_req
== FULLAUTH_ID
) &&
298 identity
= data
->pseudonym
;
299 identity_len
= data
->pseudonym_len
;
300 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
);
301 } else if (id_req
!= NO_ID_REQ
) {
302 identity
= eap_get_config_identity(sm
, &identity_len
);
304 eap_sim_clear_identities(data
, CLEAR_PSEUDONYM
|
308 if (id_req
!= NO_ID_REQ
)
309 eap_sim_clear_identities(data
, CLEAR_EAP_ID
);
311 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Start (id=%d)", id
);
312 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
,
313 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_START
);
315 wpa_hexdump(MSG_DEBUG
, " AT_NONCE_MT",
316 data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
);
317 eap_sim_msg_add(msg
, EAP_SIM_AT_NONCE_MT
, 0,
318 data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
);
319 wpa_printf(MSG_DEBUG
, " AT_SELECTED_VERSION %d",
320 data
->selected_version
);
321 eap_sim_msg_add(msg
, EAP_SIM_AT_SELECTED_VERSION
,
322 data
->selected_version
, NULL
, 0);
326 wpa_hexdump_ascii(MSG_DEBUG
, " AT_IDENTITY",
327 identity
, identity_len
);
328 eap_sim_msg_add(msg
, EAP_SIM_AT_IDENTITY
, identity_len
,
329 identity
, identity_len
);
332 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
336 static struct wpabuf
* eap_sim_response_challenge(struct eap_sim_data
*data
,
339 struct eap_sim_msg
*msg
;
341 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Challenge (id=%d)", id
);
342 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, EAP_TYPE_SIM
,
343 EAP_SIM_SUBTYPE_CHALLENGE
);
344 if (data
->use_result_ind
) {
345 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
346 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
348 wpa_printf(MSG_DEBUG
, " AT_MAC");
349 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
350 return eap_sim_msg_finish(msg
, data
->k_aut
, (u8
*) data
->sres
,
351 data
->num_chal
* EAP_SIM_SRES_LEN
);
355 static struct wpabuf
* eap_sim_response_reauth(struct eap_sim_data
*data
,
356 u8 id
, int counter_too_small
)
358 struct eap_sim_msg
*msg
;
359 unsigned int counter
;
361 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Reauthentication (id=%d)",
363 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, EAP_TYPE_SIM
,
364 EAP_SIM_SUBTYPE_REAUTHENTICATION
);
365 wpa_printf(MSG_DEBUG
, " AT_IV");
366 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
367 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
, EAP_SIM_AT_ENCR_DATA
);
369 if (counter_too_small
) {
370 wpa_printf(MSG_DEBUG
, " *AT_COUNTER_TOO_SMALL");
371 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER_TOO_SMALL
, 0, NULL
, 0);
372 counter
= data
->counter_too_small
;
374 counter
= data
->counter
;
376 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", counter
);
377 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, counter
, NULL
, 0);
379 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
, EAP_SIM_AT_PADDING
)) {
380 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to encrypt "
382 eap_sim_msg_free(msg
);
385 if (data
->use_result_ind
) {
386 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
387 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
389 wpa_printf(MSG_DEBUG
, " AT_MAC");
390 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
391 return eap_sim_msg_finish(msg
, data
->k_aut
, data
->nonce_s
,
392 EAP_SIM_NONCE_S_LEN
);
396 static struct wpabuf
* eap_sim_response_notification(struct eap_sim_data
*data
,
397 u8 id
, u16 notification
)
399 struct eap_sim_msg
*msg
;
400 u8
*k_aut
= (notification
& 0x4000) == 0 ? data
->k_aut
: NULL
;
402 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Notification (id=%d)", id
);
403 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
,
404 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_NOTIFICATION
);
405 wpa_printf(MSG_DEBUG
, " AT_NOTIFICATION");
406 eap_sim_msg_add(msg
, EAP_SIM_AT_NOTIFICATION
, notification
, NULL
, 0);
407 if (k_aut
&& data
->reauth
) {
408 wpa_printf(MSG_DEBUG
, " AT_IV");
409 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
410 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
,
411 EAP_SIM_AT_ENCR_DATA
);
412 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", data
->counter
);
413 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, data
->counter
,
415 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
,
416 EAP_SIM_AT_PADDING
)) {
417 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to encrypt "
419 eap_sim_msg_free(msg
);
424 wpa_printf(MSG_DEBUG
, " AT_MAC");
425 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
427 return eap_sim_msg_finish(msg
, k_aut
, (u8
*) "", 0);
431 static struct wpabuf
* eap_sim_process_start(struct eap_sm
*sm
,
432 struct eap_sim_data
*data
, u8 id
,
433 struct eap_sim_attrs
*attr
)
435 int selected_version
= -1, id_error
;
439 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Start");
440 if (attr
->version_list
== NULL
) {
441 wpa_printf(MSG_INFO
, "EAP-SIM: No AT_VERSION_LIST in "
443 return eap_sim_client_error(data
, id
,
444 EAP_SIM_UNSUPPORTED_VERSION
);
447 os_free(data
->ver_list
);
448 data
->ver_list
= os_malloc(attr
->version_list_len
);
449 if (data
->ver_list
== NULL
) {
450 wpa_printf(MSG_DEBUG
, "EAP-SIM: Failed to allocate "
451 "memory for version list");
452 return eap_sim_client_error(data
, id
,
453 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
455 os_memcpy(data
->ver_list
, attr
->version_list
, attr
->version_list_len
);
456 data
->ver_list_len
= attr
->version_list_len
;
457 pos
= data
->ver_list
;
458 for (i
= 0; i
< data
->ver_list_len
/ 2; i
++) {
459 int ver
= pos
[0] * 256 + pos
[1];
461 if (eap_sim_supported_ver(ver
)) {
462 selected_version
= ver
;
466 if (selected_version
< 0) {
467 wpa_printf(MSG_INFO
, "EAP-SIM: Could not find a supported "
469 return eap_sim_client_error(data
, id
,
470 EAP_SIM_UNSUPPORTED_VERSION
);
472 wpa_printf(MSG_DEBUG
, "EAP-SIM: Selected Version %d",
474 data
->selected_version
= selected_version
;
477 switch (attr
->id_req
) {
481 if (data
->num_id_req
> 0)
486 if (data
->num_id_req
> 1)
491 if (data
->num_id_req
> 2)
497 wpa_printf(MSG_INFO
, "EAP-SIM: Too many ID requests "
498 "used within one authentication");
499 return eap_sim_client_error(data
, id
,
500 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
503 return eap_sim_response_start(sm
, data
, id
, attr
->id_req
);
507 static struct wpabuf
* eap_sim_process_challenge(struct eap_sm
*sm
,
508 struct eap_sim_data
*data
,
510 const struct wpabuf
*reqData
,
511 struct eap_sim_attrs
*attr
)
515 struct eap_sim_attrs eattr
;
517 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Challenge");
519 if (!attr
->mac
|| !attr
->rand
) {
520 wpa_printf(MSG_WARNING
, "EAP-SIM: Challenge message "
521 "did not include%s%s",
522 !attr
->mac
? " AT_MAC" : "",
523 !attr
->rand
? " AT_RAND" : "");
524 return eap_sim_client_error(data
, id
,
525 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
528 wpa_printf(MSG_DEBUG
, "EAP-SIM: %lu challenges",
529 (unsigned long) attr
->num_chal
);
530 if (attr
->num_chal
< data
->min_num_chal
) {
531 wpa_printf(MSG_INFO
, "EAP-SIM: Insufficient number of "
532 "challenges (%lu)", (unsigned long) attr
->num_chal
);
533 return eap_sim_client_error(data
, id
,
534 EAP_SIM_INSUFFICIENT_NUM_OF_CHAL
);
536 if (attr
->num_chal
> 3) {
537 wpa_printf(MSG_INFO
, "EAP-SIM: Too many challenges "
538 "(%lu)", (unsigned long) attr
->num_chal
);
539 return eap_sim_client_error(data
, id
,
540 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
543 /* Verify that RANDs are different */
544 if (os_memcmp(attr
->rand
, attr
->rand
+ GSM_RAND_LEN
,
545 GSM_RAND_LEN
) == 0 ||
546 (attr
->num_chal
> 2 &&
547 (os_memcmp(attr
->rand
, attr
->rand
+ 2 * GSM_RAND_LEN
,
548 GSM_RAND_LEN
) == 0 ||
549 os_memcmp(attr
->rand
+ GSM_RAND_LEN
,
550 attr
->rand
+ 2 * GSM_RAND_LEN
,
551 GSM_RAND_LEN
) == 0))) {
552 wpa_printf(MSG_INFO
, "EAP-SIM: Same RAND used multiple times");
553 return eap_sim_client_error(data
, id
,
554 EAP_SIM_RAND_NOT_FRESH
);
557 os_memcpy(data
->rand
, attr
->rand
, attr
->num_chal
* GSM_RAND_LEN
);
558 data
->num_chal
= attr
->num_chal
;
560 if (eap_sim_gsm_auth(sm
, data
)) {
561 wpa_printf(MSG_WARNING
, "EAP-SIM: GSM authentication failed");
562 return eap_sim_client_error(data
, id
,
563 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
565 if (data
->last_eap_identity
) {
566 identity
= data
->last_eap_identity
;
567 identity_len
= data
->last_eap_identity_len
;
568 } else if (data
->pseudonym
) {
569 identity
= data
->pseudonym
;
570 identity_len
= data
->pseudonym_len
;
572 identity
= eap_get_config_identity(sm
, &identity_len
);
573 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Selected identity for MK "
574 "derivation", identity
, identity_len
);
575 eap_sim_derive_mk(identity
, identity_len
, data
->nonce_mt
,
576 data
->selected_version
, data
->ver_list
,
577 data
->ver_list_len
, data
->num_chal
,
578 (const u8
*) data
->kc
, data
->mk
);
579 eap_sim_derive_keys(data
->mk
, data
->k_encr
, data
->k_aut
, data
->msk
,
581 if (eap_sim_verify_mac(data
->k_aut
, reqData
, attr
->mac
, data
->nonce_mt
,
582 EAP_SIM_NONCE_MT_LEN
)) {
583 wpa_printf(MSG_WARNING
, "EAP-SIM: Challenge message "
584 "used invalid AT_MAC");
585 return eap_sim_client_error(data
, id
,
586 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
589 /* Old reauthentication and pseudonym identities must not be used
590 * anymore. In other words, if no new identities are received, full
591 * authentication will be used on next reauthentication. */
592 eap_sim_clear_identities(data
, CLEAR_PSEUDONYM
| CLEAR_REAUTH_ID
|
595 if (attr
->encr_data
) {
597 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
598 attr
->encr_data_len
, attr
->iv
,
600 if (decrypted
== NULL
) {
601 return eap_sim_client_error(
602 data
, id
, EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
604 eap_sim_learn_ids(data
, &eattr
);
608 if (data
->result_ind
&& attr
->result_ind
)
609 data
->use_result_ind
= 1;
611 if (data
->state
!= FAILURE
&& data
->state
!= RESULT_FAILURE
) {
612 eap_sim_state(data
, data
->use_result_ind
?
613 RESULT_SUCCESS
: SUCCESS
);
616 data
->num_id_req
= 0;
617 data
->num_notification
= 0;
618 /* RFC 4186 specifies that counter is initialized to one after
619 * fullauth, but initializing it to zero makes it easier to implement
620 * reauth verification. */
622 return eap_sim_response_challenge(data
, id
);
626 static int eap_sim_process_notification_reauth(struct eap_sim_data
*data
,
627 struct eap_sim_attrs
*attr
)
629 struct eap_sim_attrs eattr
;
632 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
633 wpa_printf(MSG_WARNING
, "EAP-SIM: Notification message after "
634 "reauth did not include encrypted data");
638 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
639 attr
->encr_data_len
, attr
->iv
, &eattr
,
641 if (decrypted
== NULL
) {
642 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to parse encrypted "
643 "data from notification message");
647 if (eattr
.counter
< 0 || (size_t) eattr
.counter
!= data
->counter
) {
648 wpa_printf(MSG_WARNING
, "EAP-SIM: Counter in notification "
649 "message does not match with counter in reauth "
660 static int eap_sim_process_notification_auth(struct eap_sim_data
*data
,
661 const struct wpabuf
*reqData
,
662 struct eap_sim_attrs
*attr
)
664 if (attr
->mac
== NULL
) {
665 wpa_printf(MSG_INFO
, "EAP-SIM: no AT_MAC in after_auth "
666 "Notification message");
670 if (eap_sim_verify_mac(data
->k_aut
, reqData
, attr
->mac
, (u8
*) "", 0))
672 wpa_printf(MSG_WARNING
, "EAP-SIM: Notification message "
673 "used invalid AT_MAC");
678 eap_sim_process_notification_reauth(data
, attr
)) {
679 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid notification "
680 "message after reauth");
688 static struct wpabuf
* eap_sim_process_notification(
689 struct eap_sm
*sm
, struct eap_sim_data
*data
, u8 id
,
690 const struct wpabuf
*reqData
, struct eap_sim_attrs
*attr
)
692 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Notification");
693 if (data
->num_notification
> 0) {
694 wpa_printf(MSG_INFO
, "EAP-SIM: too many notification "
695 "rounds (only one allowed)");
696 return eap_sim_client_error(data
, id
,
697 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
699 data
->num_notification
++;
700 if (attr
->notification
== -1) {
701 wpa_printf(MSG_INFO
, "EAP-SIM: no AT_NOTIFICATION in "
702 "Notification message");
703 return eap_sim_client_error(data
, id
,
704 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
707 if ((attr
->notification
& 0x4000) == 0 &&
708 eap_sim_process_notification_auth(data
, reqData
, attr
)) {
709 return eap_sim_client_error(data
, id
,
710 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
713 eap_sim_report_notification(sm
->msg_ctx
, attr
->notification
, 0);
714 if (attr
->notification
>= 0 && attr
->notification
< 32768) {
715 eap_sim_state(data
, FAILURE
);
716 } else if (attr
->notification
== EAP_SIM_SUCCESS
&&
717 data
->state
== RESULT_SUCCESS
)
718 eap_sim_state(data
, SUCCESS
);
719 return eap_sim_response_notification(data
, id
, attr
->notification
);
723 static struct wpabuf
* eap_sim_process_reauthentication(
724 struct eap_sm
*sm
, struct eap_sim_data
*data
, u8 id
,
725 const struct wpabuf
*reqData
, struct eap_sim_attrs
*attr
)
727 struct eap_sim_attrs eattr
;
730 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Reauthentication");
732 if (data
->reauth_id
== NULL
) {
733 wpa_printf(MSG_WARNING
, "EAP-SIM: Server is trying "
734 "reauthentication, but no reauth_id available");
735 return eap_sim_client_error(data
, id
,
736 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
740 if (eap_sim_verify_mac(data
->k_aut
, reqData
, attr
->mac
, (u8
*) "", 0))
742 wpa_printf(MSG_WARNING
, "EAP-SIM: Reauthentication "
743 "did not have valid AT_MAC");
744 return eap_sim_client_error(data
, id
,
745 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
748 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
749 wpa_printf(MSG_WARNING
, "EAP-SIM: Reauthentication "
750 "message did not include encrypted data");
751 return eap_sim_client_error(data
, id
,
752 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
755 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
756 attr
->encr_data_len
, attr
->iv
, &eattr
,
758 if (decrypted
== NULL
) {
759 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to parse encrypted "
760 "data from reauthentication message");
761 return eap_sim_client_error(data
, id
,
762 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
765 if (eattr
.nonce_s
== NULL
|| eattr
.counter
< 0) {
766 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No%s%s in reauth packet",
767 !eattr
.nonce_s
? " AT_NONCE_S" : "",
768 eattr
.counter
< 0 ? " AT_COUNTER" : "");
770 return eap_sim_client_error(data
, id
,
771 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
774 if (eattr
.counter
< 0 || (size_t) eattr
.counter
<= data
->counter
) {
775 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid counter "
776 "(%d <= %d)", eattr
.counter
, data
->counter
);
777 data
->counter_too_small
= eattr
.counter
;
778 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
779 * reauth_id must not be used to start a new reauthentication.
780 * However, since it was used in the last EAP-Response-Identity
781 * packet, it has to saved for the following fullauth to be
782 * used in MK derivation. */
783 os_free(data
->last_eap_identity
);
784 data
->last_eap_identity
= data
->reauth_id
;
785 data
->last_eap_identity_len
= data
->reauth_id_len
;
786 data
->reauth_id
= NULL
;
787 data
->reauth_id_len
= 0;
789 return eap_sim_response_reauth(data
, id
, 1);
791 data
->counter
= eattr
.counter
;
793 os_memcpy(data
->nonce_s
, eattr
.nonce_s
, EAP_SIM_NONCE_S_LEN
);
794 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: (encr) AT_NONCE_S",
795 data
->nonce_s
, EAP_SIM_NONCE_S_LEN
);
797 eap_sim_derive_keys_reauth(data
->counter
,
798 data
->reauth_id
, data
->reauth_id_len
,
799 data
->nonce_s
, data
->mk
, data
->msk
,
801 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
802 eap_sim_learn_ids(data
, &eattr
);
804 if (data
->result_ind
&& attr
->result_ind
)
805 data
->use_result_ind
= 1;
807 if (data
->state
!= FAILURE
&& data
->state
!= RESULT_FAILURE
) {
808 eap_sim_state(data
, data
->use_result_ind
?
809 RESULT_SUCCESS
: SUCCESS
);
812 data
->num_id_req
= 0;
813 data
->num_notification
= 0;
814 if (data
->counter
> EAP_SIM_MAX_FAST_REAUTHS
) {
815 wpa_printf(MSG_DEBUG
, "EAP-SIM: Maximum number of "
816 "fast reauths performed - force fullauth");
817 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
820 return eap_sim_response_reauth(data
, id
, 0);
824 static struct wpabuf
* eap_sim_process(struct eap_sm
*sm
, void *priv
,
825 struct eap_method_ret
*ret
,
826 const struct wpabuf
*reqData
)
828 struct eap_sim_data
*data
= priv
;
829 const struct eap_hdr
*req
;
833 struct eap_sim_attrs attr
;
836 wpa_hexdump_buf(MSG_DEBUG
, "EAP-SIM: EAP data", reqData
);
837 if (eap_get_config_identity(sm
, &len
) == NULL
) {
838 wpa_printf(MSG_INFO
, "EAP-SIM: Identity not configured");
839 eap_sm_request_identity(sm
);
844 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_SIM
, reqData
, &len
);
845 if (pos
== NULL
|| len
< 1) {
849 req
= wpabuf_head(reqData
);
850 id
= req
->identifier
;
851 len
= be_to_host16(req
->length
);
854 ret
->methodState
= METHOD_MAY_CONT
;
855 ret
->decision
= DECISION_FAIL
;
856 ret
->allowNotifications
= TRUE
;
859 wpa_printf(MSG_DEBUG
, "EAP-SIM: Subtype=%d", subtype
);
860 pos
+= 2; /* Reserved */
862 if (eap_sim_parse_attr(pos
, wpabuf_head_u8(reqData
) + len
, &attr
, 0,
864 res
= eap_sim_client_error(data
, id
,
865 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
870 case EAP_SIM_SUBTYPE_START
:
871 res
= eap_sim_process_start(sm
, data
, id
, &attr
);
873 case EAP_SIM_SUBTYPE_CHALLENGE
:
874 res
= eap_sim_process_challenge(sm
, data
, id
, reqData
, &attr
);
876 case EAP_SIM_SUBTYPE_NOTIFICATION
:
877 res
= eap_sim_process_notification(sm
, data
, id
, reqData
,
880 case EAP_SIM_SUBTYPE_REAUTHENTICATION
:
881 res
= eap_sim_process_reauthentication(sm
, data
, id
, reqData
,
884 case EAP_SIM_SUBTYPE_CLIENT_ERROR
:
885 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Client-Error");
886 res
= eap_sim_client_error(data
, id
,
887 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
890 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unknown subtype=%d", subtype
);
891 res
= eap_sim_client_error(data
, id
,
892 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
897 if (data
->state
== FAILURE
) {
898 ret
->decision
= DECISION_FAIL
;
899 ret
->methodState
= METHOD_DONE
;
900 } else if (data
->state
== SUCCESS
) {
901 ret
->decision
= data
->use_result_ind
?
902 DECISION_UNCOND_SUCC
: DECISION_COND_SUCC
;
903 ret
->methodState
= data
->use_result_ind
?
904 METHOD_DONE
: METHOD_MAY_CONT
;
905 } else if (data
->state
== RESULT_FAILURE
)
906 ret
->methodState
= METHOD_CONT
;
907 else if (data
->state
== RESULT_SUCCESS
)
908 ret
->methodState
= METHOD_CONT
;
910 if (ret
->methodState
== METHOD_DONE
) {
911 ret
->allowNotifications
= FALSE
;
918 static Boolean
eap_sim_has_reauth_data(struct eap_sm
*sm
, void *priv
)
920 struct eap_sim_data
*data
= priv
;
921 return data
->pseudonym
|| data
->reauth_id
;
925 static void eap_sim_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
927 struct eap_sim_data
*data
= priv
;
928 eap_sim_clear_identities(data
, CLEAR_EAP_ID
);
929 data
->use_result_ind
= 0;
933 static void * eap_sim_init_for_reauth(struct eap_sm
*sm
, void *priv
)
935 struct eap_sim_data
*data
= priv
;
936 if (os_get_random(data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
)) {
937 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to get random data "
942 data
->num_id_req
= 0;
943 data
->num_notification
= 0;
944 eap_sim_state(data
, CONTINUE
);
949 static const u8
* eap_sim_get_identity(struct eap_sm
*sm
, void *priv
,
952 struct eap_sim_data
*data
= priv
;
954 if (data
->reauth_id
) {
955 *len
= data
->reauth_id_len
;
956 return data
->reauth_id
;
959 if (data
->pseudonym
) {
960 *len
= data
->pseudonym_len
;
961 return data
->pseudonym
;
968 static Boolean
eap_sim_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
970 struct eap_sim_data
*data
= priv
;
971 return data
->state
== SUCCESS
;
975 static u8
* eap_sim_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
977 struct eap_sim_data
*data
= priv
;
980 if (data
->state
!= SUCCESS
)
983 key
= os_malloc(EAP_SIM_KEYING_DATA_LEN
);
987 *len
= EAP_SIM_KEYING_DATA_LEN
;
988 os_memcpy(key
, data
->msk
, EAP_SIM_KEYING_DATA_LEN
);
994 static u8
* eap_sim_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
996 struct eap_sim_data
*data
= priv
;
999 if (data
->state
!= SUCCESS
)
1002 key
= os_malloc(EAP_EMSK_LEN
);
1006 *len
= EAP_EMSK_LEN
;
1007 os_memcpy(key
, data
->emsk
, EAP_EMSK_LEN
);
1013 int eap_peer_sim_register(void)
1015 struct eap_method
*eap
;
1018 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
1019 EAP_VENDOR_IETF
, EAP_TYPE_SIM
, "SIM");
1023 eap
->init
= eap_sim_init
;
1024 eap
->deinit
= eap_sim_deinit
;
1025 eap
->process
= eap_sim_process
;
1026 eap
->isKeyAvailable
= eap_sim_isKeyAvailable
;
1027 eap
->getKey
= eap_sim_getKey
;
1028 eap
->has_reauth_data
= eap_sim_has_reauth_data
;
1029 eap
->deinit_for_reauth
= eap_sim_deinit_for_reauth
;
1030 eap
->init_for_reauth
= eap_sim_init_for_reauth
;
1031 eap
->get_identity
= eap_sim_get_identity
;
1032 eap
->get_emsk
= eap_sim_get_emsk
;
1034 ret
= eap_peer_method_register(eap
);
1036 eap_peer_method_free(eap
);