2 * EAP peer method: EAP-SIM (RFC 4186)
3 * Copyright (c) 2004-2006, 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.
19 #include "config_ssid.h"
21 #include "pcsc_funcs.h"
22 #include "eap_sim_common.h"
29 size_t min_num_chal
, num_chal
;
31 u8 kc
[3][EAP_SIM_KC_LEN
];
32 u8 sres
[3][EAP_SIM_SRES_LEN
];
33 u8 nonce_mt
[EAP_SIM_NONCE_MT_LEN
], nonce_s
[EAP_SIM_NONCE_S_LEN
];
34 u8 mk
[EAP_SIM_MK_LEN
];
35 u8 k_aut
[EAP_SIM_K_AUT_LEN
];
36 u8 k_encr
[EAP_SIM_K_ENCR_LEN
];
37 u8 msk
[EAP_SIM_KEYING_DATA_LEN
];
38 u8 emsk
[EAP_EMSK_LEN
];
39 u8 rand
[3][GSM_RAND_LEN
];
41 int num_id_req
, num_notification
;
47 unsigned int counter
, counter_too_small
;
48 u8
*last_eap_identity
;
49 size_t last_eap_identity_len
;
50 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
54 static void * eap_sim_init(struct eap_sm
*sm
)
56 struct eap_sim_data
*data
;
57 struct wpa_ssid
*config
= eap_get_config(sm
);
59 data
= os_zalloc(sizeof(*data
));
63 if (hostapd_get_rand(data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
)) {
64 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to get random data "
70 data
->min_num_chal
= 2;
71 if (config
&& config
->phase1
) {
72 char *pos
= os_strstr(config
->phase1
, "sim_min_num_chal=");
74 data
->min_num_chal
= atoi(pos
+ 17);
75 if (data
->min_num_chal
< 2 || data
->min_num_chal
> 3) {
76 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid "
77 "sim_min_num_chal configuration "
78 "(%lu, expected 2 or 3)",
79 (unsigned long) data
->min_num_chal
);
83 wpa_printf(MSG_DEBUG
, "EAP-SIM: Set minimum number of "
85 (unsigned long) data
->min_num_chal
);
89 data
->state
= CONTINUE
;
95 static void eap_sim_deinit(struct eap_sm
*sm
, void *priv
)
97 struct eap_sim_data
*data
= priv
;
99 os_free(data
->ver_list
);
100 os_free(data
->pseudonym
);
101 os_free(data
->reauth_id
);
102 os_free(data
->last_eap_identity
);
108 static int eap_sim_gsm_auth(struct eap_sm
*sm
, struct eap_sim_data
*data
)
110 wpa_printf(MSG_DEBUG
, "EAP-SIM: GSM authentication algorithm");
112 if (scard_gsm_auth(sm
->scard_ctx
, data
->rand
[0],
113 data
->sres
[0], data
->kc
[0]) ||
114 scard_gsm_auth(sm
->scard_ctx
, data
->rand
[1],
115 data
->sres
[1], data
->kc
[1]) ||
116 (data
->num_chal
> 2 &&
117 scard_gsm_auth(sm
->scard_ctx
, data
->rand
[2],
118 data
->sres
[2], data
->kc
[2]))) {
119 wpa_printf(MSG_DEBUG
, "EAP-SIM: GSM SIM authentication could "
123 #else /* PCSC_FUNCS */
124 /* These hardcoded Kc and SRES values are used for testing. RAND to
125 * KC/SREC mapping is very bogus as far as real authentication is
126 * concerned, but it is quite useful for cases where the AS is rotating
127 * the order of pre-configured values. */
130 for (i
= 0; i
< data
->num_chal
; i
++) {
131 if (data
->rand
[i
][0] == 0xaa) {
132 os_memcpy(data
->kc
[i
],
133 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
135 os_memcpy(data
->sres
[i
], "\xd1\xd2\xd3\xd4",
137 } else if (data
->rand
[i
][0] == 0xbb) {
138 os_memcpy(data
->kc
[i
],
139 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
141 os_memcpy(data
->sres
[i
], "\xe1\xe2\xe3\xe4",
144 os_memcpy(data
->kc
[i
],
145 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
147 os_memcpy(data
->sres
[i
], "\xf1\xf2\xf3\xf4",
152 #endif /* PCSC_FUNCS */
157 static int eap_sim_supported_ver(int version
)
159 return version
== EAP_SIM_VERSION
;
163 #define CLEAR_PSEUDONYM 0x01
164 #define CLEAR_REAUTH_ID 0x02
165 #define CLEAR_EAP_ID 0x04
167 static void eap_sim_clear_identities(struct eap_sim_data
*data
, int id
)
169 wpa_printf(MSG_DEBUG
, "EAP-SIM: forgetting old%s%s%s",
170 id
& CLEAR_PSEUDONYM
? " pseudonym" : "",
171 id
& CLEAR_REAUTH_ID
? " reauth_id" : "",
172 id
& CLEAR_EAP_ID
? " eap_id" : "");
173 if (id
& CLEAR_PSEUDONYM
) {
174 os_free(data
->pseudonym
);
175 data
->pseudonym
= NULL
;
176 data
->pseudonym_len
= 0;
178 if (id
& CLEAR_REAUTH_ID
) {
179 os_free(data
->reauth_id
);
180 data
->reauth_id
= NULL
;
181 data
->reauth_id_len
= 0;
183 if (id
& CLEAR_EAP_ID
) {
184 os_free(data
->last_eap_identity
);
185 data
->last_eap_identity
= NULL
;
186 data
->last_eap_identity_len
= 0;
191 static int eap_sim_learn_ids(struct eap_sim_data
*data
,
192 struct eap_sim_attrs
*attr
)
194 if (attr
->next_pseudonym
) {
195 os_free(data
->pseudonym
);
196 data
->pseudonym
= os_malloc(attr
->next_pseudonym_len
);
197 if (data
->pseudonym
== NULL
) {
198 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No memory for "
202 os_memcpy(data
->pseudonym
, attr
->next_pseudonym
,
203 attr
->next_pseudonym_len
);
204 data
->pseudonym_len
= attr
->next_pseudonym_len
;
205 wpa_hexdump_ascii(MSG_DEBUG
,
206 "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
208 data
->pseudonym_len
);
211 if (attr
->next_reauth_id
) {
212 os_free(data
->reauth_id
);
213 data
->reauth_id
= os_malloc(attr
->next_reauth_id_len
);
214 if (data
->reauth_id
== NULL
) {
215 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No memory for "
219 os_memcpy(data
->reauth_id
, attr
->next_reauth_id
,
220 attr
->next_reauth_id_len
);
221 data
->reauth_id_len
= attr
->next_reauth_id_len
;
222 wpa_hexdump_ascii(MSG_DEBUG
,
223 "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
225 data
->reauth_id_len
);
232 static u8
* eap_sim_client_error(struct eap_sim_data
*data
,
233 const struct eap_hdr
*req
,
234 size_t *respDataLen
, int err
)
236 struct eap_sim_msg
*msg
;
238 data
->state
= FAILURE
;
239 data
->num_id_req
= 0;
240 data
->num_notification
= 0;
242 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, req
->identifier
,
243 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_CLIENT_ERROR
);
244 eap_sim_msg_add(msg
, EAP_SIM_AT_CLIENT_ERROR_CODE
, err
, NULL
, 0);
245 return eap_sim_msg_finish(msg
, respDataLen
, NULL
, NULL
, 0);
249 static u8
* eap_sim_response_start(struct eap_sm
*sm
,
250 struct eap_sim_data
*data
,
251 const struct eap_hdr
*req
,
253 enum eap_sim_id_req id_req
)
255 const u8
*identity
= NULL
;
256 size_t identity_len
= 0;
257 struct eap_sim_msg
*msg
;
260 if (id_req
== ANY_ID
&& data
->reauth_id
) {
261 identity
= data
->reauth_id
;
262 identity_len
= data
->reauth_id_len
;
264 } else if ((id_req
== ANY_ID
|| id_req
== FULLAUTH_ID
) &&
266 identity
= data
->pseudonym
;
267 identity_len
= data
->pseudonym_len
;
268 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
);
269 } else if (id_req
!= NO_ID_REQ
) {
270 identity
= eap_get_config_identity(sm
, &identity_len
);
272 eap_sim_clear_identities(data
, CLEAR_PSEUDONYM
|
276 if (id_req
!= NO_ID_REQ
)
277 eap_sim_clear_identities(data
, CLEAR_EAP_ID
);
279 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Start (id=%d)",
281 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, req
->identifier
,
282 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_START
);
283 wpa_hexdump(MSG_DEBUG
, " AT_NONCE_MT",
284 data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
);
285 eap_sim_msg_add(msg
, EAP_SIM_AT_NONCE_MT
, 0,
286 data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
);
287 wpa_printf(MSG_DEBUG
, " AT_SELECTED_VERSION %d",
288 data
->selected_version
);
289 eap_sim_msg_add(msg
, EAP_SIM_AT_SELECTED_VERSION
,
290 data
->selected_version
, NULL
, 0);
293 wpa_hexdump_ascii(MSG_DEBUG
, " AT_IDENTITY",
294 identity
, identity_len
);
295 eap_sim_msg_add(msg
, EAP_SIM_AT_IDENTITY
, identity_len
,
296 identity
, identity_len
);
299 return eap_sim_msg_finish(msg
, respDataLen
, NULL
, NULL
, 0);
303 static u8
* eap_sim_response_challenge(struct eap_sim_data
*data
,
304 const struct eap_hdr
*req
,
307 struct eap_sim_msg
*msg
;
309 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Challenge (id=%d)",
311 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, req
->identifier
,
312 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_CHALLENGE
);
313 wpa_printf(MSG_DEBUG
, " AT_MAC");
314 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
315 return eap_sim_msg_finish(msg
, respDataLen
, data
->k_aut
,
317 data
->num_chal
* EAP_SIM_SRES_LEN
);
321 static u8
* eap_sim_response_reauth(struct eap_sim_data
*data
,
322 const struct eap_hdr
*req
,
323 size_t *respDataLen
, int counter_too_small
)
325 struct eap_sim_msg
*msg
;
326 unsigned int counter
;
328 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Reauthentication (id=%d)",
330 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, req
->identifier
,
332 EAP_SIM_SUBTYPE_REAUTHENTICATION
);
333 wpa_printf(MSG_DEBUG
, " AT_IV");
334 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
335 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
, EAP_SIM_AT_ENCR_DATA
);
337 if (counter_too_small
) {
338 wpa_printf(MSG_DEBUG
, " *AT_COUNTER_TOO_SMALL");
339 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER_TOO_SMALL
, 0, NULL
, 0);
340 counter
= data
->counter_too_small
;
342 counter
= data
->counter
;
344 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", counter
);
345 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, counter
, NULL
, 0);
347 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
, EAP_SIM_AT_PADDING
)) {
348 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to encrypt "
350 eap_sim_msg_free(msg
);
353 wpa_printf(MSG_DEBUG
, " AT_MAC");
354 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
355 return eap_sim_msg_finish(msg
, respDataLen
, data
->k_aut
, data
->nonce_s
,
356 EAP_SIM_NONCE_S_LEN
);
360 static u8
* eap_sim_response_notification(struct eap_sim_data
*data
,
361 const struct eap_hdr
*req
,
365 struct eap_sim_msg
*msg
;
366 u8
*k_aut
= (notification
& 0x4000) == 0 ? data
->k_aut
: NULL
;
368 wpa_printf(MSG_DEBUG
, "Generating EAP-SIM Notification (id=%d)",
370 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, req
->identifier
,
371 EAP_TYPE_SIM
, EAP_SIM_SUBTYPE_NOTIFICATION
);
372 wpa_printf(MSG_DEBUG
, " AT_NOTIFICATION");
373 eap_sim_msg_add(msg
, EAP_SIM_AT_NOTIFICATION
, notification
, NULL
, 0);
374 if (k_aut
&& data
->reauth
) {
375 wpa_printf(MSG_DEBUG
, " AT_IV");
376 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
377 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
,
378 EAP_SIM_AT_ENCR_DATA
);
379 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", data
->counter
);
380 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, data
->counter
,
382 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
,
383 EAP_SIM_AT_PADDING
)) {
384 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to encrypt "
386 eap_sim_msg_free(msg
);
391 wpa_printf(MSG_DEBUG
, " AT_MAC");
392 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
394 return eap_sim_msg_finish(msg
, respDataLen
, k_aut
, (u8
*) "", 0);
398 static u8
* eap_sim_process_start(struct eap_sm
*sm
, struct eap_sim_data
*data
,
399 const struct eap_hdr
*req
,
401 struct eap_sim_attrs
*attr
)
403 int selected_version
= -1, id_error
;
407 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Start");
408 if (attr
->version_list
== NULL
) {
409 wpa_printf(MSG_INFO
, "EAP-SIM: No AT_VERSION_LIST in "
411 return eap_sim_client_error(data
, req
, respDataLen
,
412 EAP_SIM_UNSUPPORTED_VERSION
);
415 os_free(data
->ver_list
);
416 data
->ver_list
= os_malloc(attr
->version_list_len
);
417 if (data
->ver_list
== NULL
) {
418 wpa_printf(MSG_DEBUG
, "EAP-SIM: Failed to allocate "
419 "memory for version list");
420 return eap_sim_client_error(data
, req
, respDataLen
,
421 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
423 os_memcpy(data
->ver_list
, attr
->version_list
, attr
->version_list_len
);
424 data
->ver_list_len
= attr
->version_list_len
;
425 pos
= data
->ver_list
;
426 for (i
= 0; i
< data
->ver_list_len
/ 2; i
++) {
427 int ver
= pos
[0] * 256 + pos
[1];
429 if (eap_sim_supported_ver(ver
)) {
430 selected_version
= ver
;
434 if (selected_version
< 0) {
435 wpa_printf(MSG_INFO
, "EAP-SIM: Could not find a supported "
437 return eap_sim_client_error(data
, req
, respDataLen
,
438 EAP_SIM_UNSUPPORTED_VERSION
);
440 wpa_printf(MSG_DEBUG
, "EAP-SIM: Selected Version %d",
442 data
->selected_version
= selected_version
;
445 switch (attr
->id_req
) {
449 if (data
->num_id_req
> 0)
454 if (data
->num_id_req
> 1)
459 if (data
->num_id_req
> 2)
465 wpa_printf(MSG_INFO
, "EAP-SIM: Too many ID requests "
466 "used within one authentication");
467 return eap_sim_client_error(data
, req
, respDataLen
,
468 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
471 return eap_sim_response_start(sm
, data
, req
, respDataLen
,
476 static u8
* eap_sim_process_challenge(struct eap_sm
*sm
,
477 struct eap_sim_data
*data
,
478 const struct eap_hdr
*req
,
481 struct eap_sim_attrs
*attr
)
485 struct eap_sim_attrs eattr
;
487 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Challenge");
489 if (!attr
->mac
|| !attr
->rand
) {
490 wpa_printf(MSG_WARNING
, "EAP-SIM: Challenge message "
491 "did not include%s%s",
492 !attr
->mac
? " AT_MAC" : "",
493 !attr
->rand
? " AT_RAND" : "");
494 return eap_sim_client_error(data
, req
, respDataLen
,
495 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
498 wpa_printf(MSG_DEBUG
, "EAP-SIM: %lu challenges",
499 (unsigned long) attr
->num_chal
);
500 if (attr
->num_chal
< data
->min_num_chal
) {
501 wpa_printf(MSG_INFO
, "EAP-SIM: Insufficient number of "
502 "challenges (%lu)", (unsigned long) attr
->num_chal
);
503 return eap_sim_client_error(data
, req
, respDataLen
,
504 EAP_SIM_INSUFFICIENT_NUM_OF_CHAL
);
506 if (attr
->num_chal
> 3) {
507 wpa_printf(MSG_INFO
, "EAP-SIM: Too many challenges "
508 "(%lu)", (unsigned long) attr
->num_chal
);
509 return eap_sim_client_error(data
, req
, respDataLen
,
510 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
513 /* Verify that RANDs are different */
514 if (os_memcmp(attr
->rand
, attr
->rand
+ GSM_RAND_LEN
,
515 GSM_RAND_LEN
) == 0 ||
516 (attr
->num_chal
> 2 &&
517 (os_memcmp(attr
->rand
, attr
->rand
+ 2 * GSM_RAND_LEN
,
518 GSM_RAND_LEN
) == 0 ||
519 os_memcmp(attr
->rand
+ GSM_RAND_LEN
,
520 attr
->rand
+ 2 * GSM_RAND_LEN
,
521 GSM_RAND_LEN
) == 0))) {
522 wpa_printf(MSG_INFO
, "EAP-SIM: Same RAND used multiple times");
523 return eap_sim_client_error(data
, req
, respDataLen
,
524 EAP_SIM_RAND_NOT_FRESH
);
527 os_memcpy(data
->rand
, attr
->rand
, attr
->num_chal
* GSM_RAND_LEN
);
528 data
->num_chal
= attr
->num_chal
;
530 if (eap_sim_gsm_auth(sm
, data
)) {
531 wpa_printf(MSG_WARNING
, "EAP-SIM: GSM authentication failed");
532 return eap_sim_client_error(data
, req
, respDataLen
,
533 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
535 if (data
->last_eap_identity
) {
536 identity
= data
->last_eap_identity
;
537 identity_len
= data
->last_eap_identity_len
;
538 } else if (data
->pseudonym
) {
539 identity
= data
->pseudonym
;
540 identity_len
= data
->pseudonym_len
;
542 identity
= eap_get_config_identity(sm
, &identity_len
);
543 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Selected identity for MK "
544 "derivation", identity
, identity_len
);
545 eap_sim_derive_mk(identity
, identity_len
, data
->nonce_mt
,
546 data
->selected_version
, data
->ver_list
,
547 data
->ver_list_len
, data
->num_chal
,
548 (const u8
*) data
->kc
, data
->mk
);
549 eap_sim_derive_keys(data
->mk
, data
->k_encr
, data
->k_aut
, data
->msk
,
551 if (eap_sim_verify_mac(data
->k_aut
, (const u8
*) req
, reqDataLen
,
552 attr
->mac
, data
->nonce_mt
,
553 EAP_SIM_NONCE_MT_LEN
)) {
554 wpa_printf(MSG_WARNING
, "EAP-SIM: Challenge message "
555 "used invalid AT_MAC");
556 return eap_sim_client_error(data
, req
, respDataLen
,
557 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
560 /* Old reauthentication and pseudonym identities must not be used
561 * anymore. In other words, if no new identities are received, full
562 * authentication will be used on next reauthentication. */
563 eap_sim_clear_identities(data
, CLEAR_PSEUDONYM
| CLEAR_REAUTH_ID
|
566 if (attr
->encr_data
) {
568 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
569 attr
->encr_data_len
, attr
->iv
,
571 if (decrypted
== NULL
) {
572 return eap_sim_client_error(
573 data
, req
, respDataLen
,
574 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
576 eap_sim_learn_ids(data
, &eattr
);
580 if (data
->state
!= FAILURE
)
581 data
->state
= SUCCESS
;
583 data
->num_id_req
= 0;
584 data
->num_notification
= 0;
585 /* RFC 4186 specifies that counter is initialized to one after
586 * fullauth, but initializing it to zero makes it easier to implement
587 * reauth verification. */
589 return eap_sim_response_challenge(data
, req
, respDataLen
);
593 static int eap_sim_process_notification_reauth(struct eap_sim_data
*data
,
594 struct eap_sim_attrs
*attr
)
596 struct eap_sim_attrs eattr
;
599 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
600 wpa_printf(MSG_WARNING
, "EAP-SIM: Notification message after "
601 "reauth did not include encrypted data");
605 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
606 attr
->encr_data_len
, attr
->iv
, &eattr
,
608 if (decrypted
== NULL
) {
609 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to parse encrypted "
610 "data from notification message");
614 if (eattr
.counter
< 0 || (size_t) eattr
.counter
!= data
->counter
) {
615 wpa_printf(MSG_WARNING
, "EAP-SIM: Counter in notification "
616 "message does not match with counter in reauth "
627 static int eap_sim_process_notification_auth(struct eap_sim_data
*data
,
628 const struct eap_hdr
*req
,
630 struct eap_sim_attrs
*attr
)
632 if (attr
->mac
== NULL
) {
633 wpa_printf(MSG_INFO
, "EAP-SIM: no AT_MAC in after_auth "
634 "Notification message");
638 if (eap_sim_verify_mac(data
->k_aut
, (u8
*) req
, reqDataLen
, attr
->mac
,
640 wpa_printf(MSG_WARNING
, "EAP-SIM: Notification message "
641 "used invalid AT_MAC");
646 eap_sim_process_notification_reauth(data
, attr
)) {
647 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid notification "
648 "message after reauth");
656 static u8
* eap_sim_process_notification(struct eap_sm
*sm
,
657 struct eap_sim_data
*data
,
658 const struct eap_hdr
*req
,
661 struct eap_sim_attrs
*attr
)
663 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Notification");
664 if (data
->num_notification
> 0) {
665 wpa_printf(MSG_INFO
, "EAP-SIM: too many notification "
666 "rounds (only one allowed)");
667 return eap_sim_client_error(data
, req
, respDataLen
,
668 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
670 data
->num_notification
++;
671 if (attr
->notification
== -1) {
672 wpa_printf(MSG_INFO
, "EAP-SIM: no AT_NOTIFICATION in "
673 "Notification message");
674 return eap_sim_client_error(data
, req
, respDataLen
,
675 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
678 if ((attr
->notification
& 0x4000) == 0 &&
679 eap_sim_process_notification_auth(data
, req
, reqDataLen
, attr
)) {
680 return eap_sim_client_error(data
, req
, respDataLen
,
681 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
684 eap_sim_report_notification(sm
->msg_ctx
, attr
->notification
, 0);
685 if (attr
->notification
>= 0 && attr
->notification
< 32768) {
686 data
->state
= FAILURE
;
688 return eap_sim_response_notification(data
, req
, respDataLen
,
693 static u8
* eap_sim_process_reauthentication(struct eap_sm
*sm
,
694 struct eap_sim_data
*data
,
695 const struct eap_hdr
*req
,
698 struct eap_sim_attrs
*attr
)
700 struct eap_sim_attrs eattr
;
703 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Reauthentication");
705 if (data
->reauth_id
== NULL
) {
706 wpa_printf(MSG_WARNING
, "EAP-SIM: Server is trying "
707 "reauthentication, but no reauth_id available");
708 return eap_sim_client_error(data
, req
, respDataLen
,
709 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
713 if (eap_sim_verify_mac(data
->k_aut
, (const u8
*) req
, reqDataLen
,
714 attr
->mac
, (u8
*) "", 0)) {
715 wpa_printf(MSG_WARNING
, "EAP-SIM: Reauthentication "
716 "did not have valid AT_MAC");
717 return eap_sim_client_error(data
, req
, respDataLen
,
718 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
721 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
722 wpa_printf(MSG_WARNING
, "EAP-SIM: Reauthentication "
723 "message did not include encrypted data");
724 return eap_sim_client_error(data
, req
, respDataLen
,
725 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
728 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
729 attr
->encr_data_len
, attr
->iv
, &eattr
,
731 if (decrypted
== NULL
) {
732 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to parse encrypted "
733 "data from reauthentication message");
734 return eap_sim_client_error(data
, req
, respDataLen
,
735 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
738 if (eattr
.nonce_s
== NULL
|| eattr
.counter
< 0) {
739 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) No%s%s in reauth packet",
740 !eattr
.nonce_s
? " AT_NONCE_S" : "",
741 eattr
.counter
< 0 ? " AT_COUNTER" : "");
743 return eap_sim_client_error(data
, req
, respDataLen
,
744 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
747 if (eattr
.counter
< 0 || (size_t) eattr
.counter
<= data
->counter
) {
748 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid counter "
749 "(%d <= %d)", eattr
.counter
, data
->counter
);
750 data
->counter_too_small
= eattr
.counter
;
751 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
752 * reauth_id must not be used to start a new reauthentication.
753 * However, since it was used in the last EAP-Response-Identity
754 * packet, it has to saved for the following fullauth to be
755 * used in MK derivation. */
756 os_free(data
->last_eap_identity
);
757 data
->last_eap_identity
= data
->reauth_id
;
758 data
->last_eap_identity_len
= data
->reauth_id_len
;
759 data
->reauth_id
= NULL
;
760 data
->reauth_id_len
= 0;
762 return eap_sim_response_reauth(data
, req
, respDataLen
, 1);
764 data
->counter
= eattr
.counter
;
766 os_memcpy(data
->nonce_s
, eattr
.nonce_s
, EAP_SIM_NONCE_S_LEN
);
767 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: (encr) AT_NONCE_S",
768 data
->nonce_s
, EAP_SIM_NONCE_S_LEN
);
770 eap_sim_derive_keys_reauth(data
->counter
,
771 data
->reauth_id
, data
->reauth_id_len
,
772 data
->nonce_s
, data
->mk
, data
->msk
,
774 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
775 eap_sim_learn_ids(data
, &eattr
);
777 if (data
->state
!= FAILURE
)
778 data
->state
= SUCCESS
;
780 data
->num_id_req
= 0;
781 data
->num_notification
= 0;
782 if (data
->counter
> EAP_SIM_MAX_FAST_REAUTHS
) {
783 wpa_printf(MSG_DEBUG
, "EAP-SIM: Maximum number of "
784 "fast reauths performed - force fullauth");
785 eap_sim_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
788 return eap_sim_response_reauth(data
, req
, respDataLen
, 0);
792 static u8
* eap_sim_process(struct eap_sm
*sm
, void *priv
,
793 struct eap_method_ret
*ret
,
794 const u8
*reqData
, size_t reqDataLen
,
797 struct eap_sim_data
*data
= priv
;
798 const struct eap_hdr
*req
;
801 struct eap_sim_attrs attr
;
804 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: EAP data", reqData
, reqDataLen
);
805 if (eap_get_config_identity(sm
, &len
) == NULL
) {
806 wpa_printf(MSG_INFO
, "EAP-SIM: Identity not configured");
807 eap_sm_request_identity(sm
);
812 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_SIM
,
813 reqData
, reqDataLen
, &len
);
814 if (pos
== NULL
|| len
< 1) {
818 req
= (const struct eap_hdr
*) reqData
;
819 len
= be_to_host16(req
->length
);
822 ret
->methodState
= METHOD_MAY_CONT
;
823 ret
->decision
= DECISION_FAIL
;
824 ret
->allowNotifications
= TRUE
;
827 wpa_printf(MSG_DEBUG
, "EAP-SIM: Subtype=%d", subtype
);
828 pos
+= 2; /* Reserved */
830 if (eap_sim_parse_attr(pos
, reqData
+ len
, &attr
, 0, 0)) {
831 res
= eap_sim_client_error(data
, req
, respDataLen
,
832 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
837 case EAP_SIM_SUBTYPE_START
:
838 res
= eap_sim_process_start(sm
, data
, req
,
841 case EAP_SIM_SUBTYPE_CHALLENGE
:
842 res
= eap_sim_process_challenge(sm
, data
, req
, len
,
845 case EAP_SIM_SUBTYPE_NOTIFICATION
:
846 res
= eap_sim_process_notification(sm
, data
, req
, len
,
849 case EAP_SIM_SUBTYPE_REAUTHENTICATION
:
850 res
= eap_sim_process_reauthentication(sm
, data
, req
, len
,
853 case EAP_SIM_SUBTYPE_CLIENT_ERROR
:
854 wpa_printf(MSG_DEBUG
, "EAP-SIM: subtype Client-Error");
855 res
= eap_sim_client_error(data
, req
, respDataLen
,
856 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
859 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unknown subtype=%d", subtype
);
860 res
= eap_sim_client_error(data
, req
, respDataLen
,
861 EAP_SIM_UNABLE_TO_PROCESS_PACKET
);
866 if (data
->state
== FAILURE
) {
867 ret
->decision
= DECISION_FAIL
;
868 ret
->methodState
= METHOD_DONE
;
869 } else if (data
->state
== SUCCESS
) {
870 ret
->decision
= DECISION_COND_SUCC
;
871 ret
->methodState
= METHOD_DONE
;
874 if (ret
->methodState
== METHOD_DONE
) {
875 ret
->allowNotifications
= FALSE
;
882 static Boolean
eap_sim_has_reauth_data(struct eap_sm
*sm
, void *priv
)
884 struct eap_sim_data
*data
= priv
;
885 return data
->pseudonym
|| data
->reauth_id
;
889 static void eap_sim_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
891 struct eap_sim_data
*data
= priv
;
892 eap_sim_clear_identities(data
, CLEAR_EAP_ID
);
896 static void * eap_sim_init_for_reauth(struct eap_sm
*sm
, void *priv
)
898 struct eap_sim_data
*data
= priv
;
899 if (hostapd_get_rand(data
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
)) {
900 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to get random data "
905 data
->num_id_req
= 0;
906 data
->num_notification
= 0;
907 data
->state
= CONTINUE
;
912 static const u8
* eap_sim_get_identity(struct eap_sm
*sm
, void *priv
,
915 struct eap_sim_data
*data
= priv
;
917 if (data
->reauth_id
) {
918 *len
= data
->reauth_id_len
;
919 return data
->reauth_id
;
922 if (data
->pseudonym
) {
923 *len
= data
->pseudonym_len
;
924 return data
->pseudonym
;
931 static Boolean
eap_sim_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
933 struct eap_sim_data
*data
= priv
;
934 return data
->state
== SUCCESS
;
938 static u8
* eap_sim_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
940 struct eap_sim_data
*data
= priv
;
943 if (data
->state
!= SUCCESS
)
946 key
= os_malloc(EAP_SIM_KEYING_DATA_LEN
);
950 *len
= EAP_SIM_KEYING_DATA_LEN
;
951 os_memcpy(key
, data
->msk
, EAP_SIM_KEYING_DATA_LEN
);
957 static u8
* eap_sim_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
959 struct eap_sim_data
*data
= priv
;
962 if (data
->state
!= SUCCESS
)
965 key
= os_malloc(EAP_EMSK_LEN
);
970 os_memcpy(key
, data
->emsk
, EAP_EMSK_LEN
);
976 int eap_peer_sim_register(void)
978 struct eap_method
*eap
;
981 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
982 EAP_VENDOR_IETF
, EAP_TYPE_SIM
, "SIM");
986 eap
->init
= eap_sim_init
;
987 eap
->deinit
= eap_sim_deinit
;
988 eap
->process
= eap_sim_process
;
989 eap
->isKeyAvailable
= eap_sim_isKeyAvailable
;
990 eap
->getKey
= eap_sim_getKey
;
991 eap
->has_reauth_data
= eap_sim_has_reauth_data
;
992 eap
->deinit_for_reauth
= eap_sim_deinit_for_reauth
;
993 eap
->init_for_reauth
= eap_sim_init_for_reauth
;
994 eap
->get_identity
= eap_sim_get_identity
;
995 eap
->get_emsk
= eap_sim_get_emsk
;
997 ret
= eap_peer_method_register(eap
);
999 eap_peer_method_free(eap
);