2 * hostapd / EAP-SIM (RFC 4186)
3 * Copyright (c) 2005-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_server/eap_i.h"
19 #include "eap_common/eap_sim_common.h"
20 #include "eap_server/eap_sim_db.h"
24 u8 mk
[EAP_SIM_MK_LEN
];
25 u8 nonce_mt
[EAP_SIM_NONCE_MT_LEN
];
26 u8 nonce_s
[EAP_SIM_NONCE_S_LEN
];
27 u8 k_aut
[EAP_SIM_K_AUT_LEN
];
28 u8 k_encr
[EAP_SIM_K_ENCR_LEN
];
29 u8 msk
[EAP_SIM_KEYING_DATA_LEN
];
30 u8 emsk
[EAP_EMSK_LEN
];
31 u8 kc
[EAP_SIM_MAX_CHAL
][EAP_SIM_KC_LEN
];
32 u8 sres
[EAP_SIM_MAX_CHAL
][EAP_SIM_SRES_LEN
];
33 u8 rand
[EAP_SIM_MAX_CHAL
][GSM_RAND_LEN
];
36 START
, CHALLENGE
, REAUTH
, NOTIFICATION
, SUCCESS
, FAILURE
41 struct eap_sim_reauth
*reauth
;
47 static const char * eap_sim_state_txt(int state
)
61 return "NOTIFICATION";
68 static void eap_sim_state(struct eap_sim_data
*data
, int state
)
70 wpa_printf(MSG_DEBUG
, "EAP-SIM: %s -> %s",
71 eap_sim_state_txt(data
->state
),
72 eap_sim_state_txt(state
));
77 static void * eap_sim_init(struct eap_sm
*sm
)
79 struct eap_sim_data
*data
;
81 if (sm
->eap_sim_db_priv
== NULL
) {
82 wpa_printf(MSG_WARNING
, "EAP-SIM: eap_sim_db not configured");
86 data
= os_zalloc(sizeof(*data
));
95 static void eap_sim_reset(struct eap_sm
*sm
, void *priv
)
97 struct eap_sim_data
*data
= priv
;
98 os_free(data
->next_pseudonym
);
99 os_free(data
->next_reauth_id
);
104 static struct wpabuf
* eap_sim_build_start(struct eap_sm
*sm
,
105 struct eap_sim_data
*data
, u8 id
)
107 struct eap_sim_msg
*msg
;
110 wpa_printf(MSG_DEBUG
, "EAP-SIM: Generating Start");
111 msg
= eap_sim_msg_init(EAP_CODE_REQUEST
, id
, EAP_TYPE_SIM
,
112 EAP_SIM_SUBTYPE_START
);
113 if (eap_sim_db_identity_known(sm
->eap_sim_db_priv
, sm
->identity
,
115 wpa_printf(MSG_DEBUG
, " AT_PERMANENT_ID_REQ");
116 eap_sim_msg_add(msg
, EAP_SIM_AT_PERMANENT_ID_REQ
, 0, NULL
, 0);
119 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is
120 * ignored and the SIM/Start is used to request the identity.
122 wpa_printf(MSG_DEBUG
, " AT_ANY_ID_REQ");
123 eap_sim_msg_add(msg
, EAP_SIM_AT_ANY_ID_REQ
, 0, NULL
, 0);
125 wpa_printf(MSG_DEBUG
, " AT_VERSION_LIST");
127 ver
[1] = EAP_SIM_VERSION
;
128 eap_sim_msg_add(msg
, EAP_SIM_AT_VERSION_LIST
, sizeof(ver
),
130 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
134 static int eap_sim_build_encr(struct eap_sm
*sm
, struct eap_sim_data
*data
,
135 struct eap_sim_msg
*msg
, u16 counter
,
138 os_free(data
->next_pseudonym
);
139 data
->next_pseudonym
=
140 eap_sim_db_get_next_pseudonym(sm
->eap_sim_db_priv
, 0);
141 os_free(data
->next_reauth_id
);
142 if (data
->counter
<= EAP_SIM_MAX_FAST_REAUTHS
) {
143 data
->next_reauth_id
=
144 eap_sim_db_get_next_reauth_id(sm
->eap_sim_db_priv
, 0);
146 wpa_printf(MSG_DEBUG
, "EAP-SIM: Max fast re-authentication "
147 "count exceeded - force full authentication");
148 data
->next_reauth_id
= NULL
;
151 if (data
->next_pseudonym
== NULL
&& data
->next_reauth_id
== NULL
&&
152 counter
== 0 && nonce_s
== NULL
)
155 wpa_printf(MSG_DEBUG
, " AT_IV");
156 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
157 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
, EAP_SIM_AT_ENCR_DATA
);
160 wpa_printf(MSG_DEBUG
, " *AT_COUNTER (%u)", counter
);
161 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, counter
, NULL
, 0);
165 wpa_printf(MSG_DEBUG
, " *AT_NONCE_S");
166 eap_sim_msg_add(msg
, EAP_SIM_AT_NONCE_S
, 0, nonce_s
,
167 EAP_SIM_NONCE_S_LEN
);
170 if (data
->next_pseudonym
) {
171 wpa_printf(MSG_DEBUG
, " *AT_NEXT_PSEUDONYM (%s)",
172 data
->next_pseudonym
);
173 eap_sim_msg_add(msg
, EAP_SIM_AT_NEXT_PSEUDONYM
,
174 os_strlen(data
->next_pseudonym
),
175 (u8
*) data
->next_pseudonym
,
176 os_strlen(data
->next_pseudonym
));
179 if (data
->next_reauth_id
) {
180 wpa_printf(MSG_DEBUG
, " *AT_NEXT_REAUTH_ID (%s)",
181 data
->next_reauth_id
);
182 eap_sim_msg_add(msg
, EAP_SIM_AT_NEXT_REAUTH_ID
,
183 os_strlen(data
->next_reauth_id
),
184 (u8
*) data
->next_reauth_id
,
185 os_strlen(data
->next_reauth_id
));
188 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
, EAP_SIM_AT_PADDING
)) {
189 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to encrypt "
198 static struct wpabuf
* eap_sim_build_challenge(struct eap_sm
*sm
,
199 struct eap_sim_data
*data
,
202 struct eap_sim_msg
*msg
;
204 wpa_printf(MSG_DEBUG
, "EAP-SIM: Generating Challenge");
205 msg
= eap_sim_msg_init(EAP_CODE_REQUEST
, id
, EAP_TYPE_SIM
,
206 EAP_SIM_SUBTYPE_CHALLENGE
);
207 wpa_printf(MSG_DEBUG
, " AT_RAND");
208 eap_sim_msg_add(msg
, EAP_SIM_AT_RAND
, 0, (u8
*) data
->rand
,
209 data
->num_chal
* GSM_RAND_LEN
);
211 if (eap_sim_build_encr(sm
, data
, msg
, 0, NULL
)) {
212 eap_sim_msg_free(msg
);
216 if (sm
->eap_sim_aka_result_ind
) {
217 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
218 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
221 wpa_printf(MSG_DEBUG
, " AT_MAC");
222 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
223 return eap_sim_msg_finish(msg
, data
->k_aut
, data
->nonce_mt
,
224 EAP_SIM_NONCE_MT_LEN
);
228 static struct wpabuf
* eap_sim_build_reauth(struct eap_sm
*sm
,
229 struct eap_sim_data
*data
, u8 id
)
231 struct eap_sim_msg
*msg
;
233 wpa_printf(MSG_DEBUG
, "EAP-SIM: Generating Re-authentication");
235 if (os_get_random(data
->nonce_s
, EAP_SIM_NONCE_S_LEN
))
237 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-SIM: NONCE_S",
238 data
->nonce_s
, EAP_SIM_NONCE_S_LEN
);
240 eap_sim_derive_keys(data
->mk
, data
->k_encr
, data
->k_aut
, data
->msk
,
242 eap_sim_derive_keys_reauth(data
->counter
, sm
->identity
,
243 sm
->identity_len
, data
->nonce_s
, data
->mk
,
244 data
->msk
, data
->emsk
);
246 msg
= eap_sim_msg_init(EAP_CODE_REQUEST
, id
, EAP_TYPE_SIM
,
247 EAP_SIM_SUBTYPE_REAUTHENTICATION
);
249 if (eap_sim_build_encr(sm
, data
, msg
, data
->counter
, data
->nonce_s
)) {
250 eap_sim_msg_free(msg
);
254 if (sm
->eap_sim_aka_result_ind
) {
255 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
256 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
259 wpa_printf(MSG_DEBUG
, " AT_MAC");
260 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
261 return eap_sim_msg_finish(msg
, data
->k_aut
, NULL
, 0);
265 static struct wpabuf
* eap_sim_build_notification(struct eap_sm
*sm
,
266 struct eap_sim_data
*data
,
269 struct eap_sim_msg
*msg
;
271 wpa_printf(MSG_DEBUG
, "EAP-SIM: Generating Notification");
272 msg
= eap_sim_msg_init(EAP_CODE_REQUEST
, id
, EAP_TYPE_SIM
,
273 EAP_SIM_SUBTYPE_NOTIFICATION
);
274 wpa_printf(MSG_DEBUG
, " AT_NOTIFICATION (%d)", data
->notification
);
275 eap_sim_msg_add(msg
, EAP_SIM_AT_NOTIFICATION
, data
->notification
,
277 if (data
->use_result_ind
) {
279 wpa_printf(MSG_DEBUG
, " AT_IV");
280 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
281 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
,
282 EAP_SIM_AT_ENCR_DATA
);
283 wpa_printf(MSG_DEBUG
, " *AT_COUNTER (%u)",
285 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, data
->counter
,
288 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
,
289 EAP_SIM_AT_PADDING
)) {
290 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to "
291 "encrypt AT_ENCR_DATA");
292 eap_sim_msg_free(msg
);
297 wpa_printf(MSG_DEBUG
, " AT_MAC");
298 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
300 return eap_sim_msg_finish(msg
, data
->k_aut
, NULL
, 0);
304 static struct wpabuf
* eap_sim_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
306 struct eap_sim_data
*data
= priv
;
308 switch (data
->state
) {
310 return eap_sim_build_start(sm
, data
, id
);
312 return eap_sim_build_challenge(sm
, data
, id
);
314 return eap_sim_build_reauth(sm
, data
, id
);
316 return eap_sim_build_notification(sm
, data
, id
);
318 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unknown state %d in "
319 "buildReq", data
->state
);
326 static Boolean
eap_sim_check(struct eap_sm
*sm
, void *priv
,
327 struct wpabuf
*respData
)
329 struct eap_sim_data
*data
= priv
;
334 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_SIM
, respData
, &len
);
335 if (pos
== NULL
|| len
< 3) {
336 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid frame");
341 if (subtype
== EAP_SIM_SUBTYPE_CLIENT_ERROR
)
344 switch (data
->state
) {
346 if (subtype
!= EAP_SIM_SUBTYPE_START
) {
347 wpa_printf(MSG_INFO
, "EAP-SIM: Unexpected response "
348 "subtype %d", subtype
);
353 if (subtype
!= EAP_SIM_SUBTYPE_CHALLENGE
) {
354 wpa_printf(MSG_INFO
, "EAP-SIM: Unexpected response "
355 "subtype %d", subtype
);
360 if (subtype
!= EAP_SIM_SUBTYPE_REAUTHENTICATION
) {
361 wpa_printf(MSG_INFO
, "EAP-SIM: Unexpected response "
362 "subtype %d", subtype
);
367 if (subtype
!= EAP_SIM_SUBTYPE_NOTIFICATION
) {
368 wpa_printf(MSG_INFO
, "EAP-SIM: Unexpected response "
369 "subtype %d", subtype
);
374 wpa_printf(MSG_INFO
, "EAP-SIM: Unexpected state (%d) for "
375 "processing a response", data
->state
);
383 static int eap_sim_supported_ver(struct eap_sim_data
*data
, int version
)
385 return version
== EAP_SIM_VERSION
;
389 static void eap_sim_process_start(struct eap_sm
*sm
,
390 struct eap_sim_data
*data
,
391 struct wpabuf
*respData
,
392 struct eap_sim_attrs
*attr
)
398 wpa_printf(MSG_DEBUG
, "EAP-SIM: Receive start response");
400 if (attr
->identity
) {
401 os_free(sm
->identity
);
402 sm
->identity
= os_malloc(attr
->identity_len
);
404 os_memcpy(sm
->identity
, attr
->identity
,
406 sm
->identity_len
= attr
->identity_len
;
413 if (sm
->identity
&& sm
->identity_len
> 0 &&
414 sm
->identity
[0] == EAP_SIM_PERMANENT_PREFIX
) {
415 identity
= sm
->identity
;
416 identity_len
= sm
->identity_len
;
418 identity
= eap_sim_db_get_permanent(sm
->eap_sim_db_priv
,
422 if (identity
== NULL
) {
423 data
->reauth
= eap_sim_db_get_reauth_entry(
424 sm
->eap_sim_db_priv
, sm
->identity
,
427 wpa_printf(MSG_DEBUG
, "EAP-SIM: Using fast "
428 "re-authentication");
429 identity
= data
->reauth
->identity
;
430 identity_len
= data
->reauth
->identity_len
;
431 data
->counter
= data
->reauth
->counter
;
432 os_memcpy(data
->mk
, data
->reauth
->mk
,
438 if (identity
== NULL
) {
439 wpa_printf(MSG_DEBUG
, "EAP-SIM: Could not get proper permanent"
441 eap_sim_state(data
, FAILURE
);
445 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Identity",
446 identity
, identity_len
);
449 eap_sim_state(data
, REAUTH
);
453 if (attr
->nonce_mt
== NULL
|| attr
->selected_version
< 0) {
454 wpa_printf(MSG_DEBUG
, "EAP-SIM: Start/Response missing "
455 "required attributes");
456 eap_sim_state(data
, FAILURE
);
460 if (!eap_sim_supported_ver(data
, attr
->selected_version
)) {
461 wpa_printf(MSG_DEBUG
, "EAP-SIM: Peer selected unsupported "
462 "version %d", attr
->selected_version
);
463 eap_sim_state(data
, FAILURE
);
467 data
->counter
= 0; /* reset re-auth counter since this is full auth */
470 data
->num_chal
= eap_sim_db_get_gsm_triplets(
471 sm
->eap_sim_db_priv
, identity
, identity_len
,
473 (u8
*) data
->rand
, (u8
*) data
->kc
, (u8
*) data
->sres
, sm
);
474 if (data
->num_chal
== EAP_SIM_DB_PENDING
) {
475 wpa_printf(MSG_DEBUG
, "EAP-SIM: GSM authentication triplets "
476 "not yet available - pending request");
477 sm
->method_pending
= METHOD_PENDING_WAIT
;
480 if (data
->num_chal
< 2) {
481 wpa_printf(MSG_INFO
, "EAP-SIM: Failed to get GSM "
482 "authentication triplets for the peer");
483 eap_sim_state(data
, FAILURE
);
487 identity_len
= sm
->identity_len
;
488 while (identity_len
> 0 && sm
->identity
[identity_len
- 1] == '\0') {
489 wpa_printf(MSG_DEBUG
, "EAP-SIM: Workaround - drop last null "
490 "character from identity");
493 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Identity for MK derivation",
494 sm
->identity
, identity_len
);
496 os_memcpy(data
->nonce_mt
, attr
->nonce_mt
, EAP_SIM_NONCE_MT_LEN
);
497 WPA_PUT_BE16(ver_list
, EAP_SIM_VERSION
);
498 eap_sim_derive_mk(sm
->identity
, identity_len
, attr
->nonce_mt
,
499 attr
->selected_version
, ver_list
, sizeof(ver_list
),
500 data
->num_chal
, (const u8
*) data
->kc
, data
->mk
);
501 eap_sim_derive_keys(data
->mk
, data
->k_encr
, data
->k_aut
, data
->msk
,
504 eap_sim_state(data
, CHALLENGE
);
508 static void eap_sim_process_challenge(struct eap_sm
*sm
,
509 struct eap_sim_data
*data
,
510 struct wpabuf
*respData
,
511 struct eap_sim_attrs
*attr
)
516 if (attr
->mac
== NULL
||
517 eap_sim_verify_mac(data
->k_aut
, respData
, attr
->mac
,
519 data
->num_chal
* EAP_SIM_SRES_LEN
)) {
520 wpa_printf(MSG_WARNING
, "EAP-SIM: Challenge message "
521 "did not include valid AT_MAC");
522 eap_sim_state(data
, FAILURE
);
526 wpa_printf(MSG_DEBUG
, "EAP-SIM: Challenge response includes the "
528 if (sm
->eap_sim_aka_result_ind
&& attr
->result_ind
) {
529 data
->use_result_ind
= 1;
530 data
->notification
= EAP_SIM_SUCCESS
;
531 eap_sim_state(data
, NOTIFICATION
);
533 eap_sim_state(data
, SUCCESS
);
535 identity
= eap_sim_db_get_permanent(sm
->eap_sim_db_priv
, sm
->identity
,
536 sm
->identity_len
, &identity_len
);
537 if (identity
== NULL
) {
538 identity
= sm
->identity
;
539 identity_len
= sm
->identity_len
;
542 if (data
->next_pseudonym
) {
543 eap_sim_db_add_pseudonym(sm
->eap_sim_db_priv
, identity
,
545 data
->next_pseudonym
);
546 data
->next_pseudonym
= NULL
;
548 if (data
->next_reauth_id
) {
549 eap_sim_db_add_reauth(sm
->eap_sim_db_priv
, identity
,
551 data
->next_reauth_id
, data
->counter
+ 1,
553 data
->next_reauth_id
= NULL
;
558 static void eap_sim_process_reauth(struct eap_sm
*sm
,
559 struct eap_sim_data
*data
,
560 struct wpabuf
*respData
,
561 struct eap_sim_attrs
*attr
)
563 struct eap_sim_attrs eattr
;
564 u8
*decrypted
= NULL
;
565 const u8
*identity
, *id2
;
566 size_t identity_len
, id2_len
;
568 if (attr
->mac
== NULL
||
569 eap_sim_verify_mac(data
->k_aut
, respData
, attr
->mac
, data
->nonce_s
,
570 EAP_SIM_NONCE_S_LEN
)) {
571 wpa_printf(MSG_WARNING
, "EAP-SIM: Re-authentication message "
572 "did not include valid AT_MAC");
576 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
577 wpa_printf(MSG_WARNING
, "EAP-SIM: Reauthentication "
578 "message did not include encrypted data");
582 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
583 attr
->encr_data_len
, attr
->iv
, &eattr
,
585 if (decrypted
== NULL
) {
586 wpa_printf(MSG_WARNING
, "EAP-SIM: Failed to parse encrypted "
587 "data from reauthentication message");
591 if (eattr
.counter
!= data
->counter
) {
592 wpa_printf(MSG_WARNING
, "EAP-SIM: Re-authentication message "
593 "used incorrect counter %u, expected %u",
594 eattr
.counter
, data
->counter
);
600 wpa_printf(MSG_DEBUG
, "EAP-SIM: Re-authentication response includes "
601 "the correct AT_MAC");
602 if (sm
->eap_sim_aka_result_ind
&& attr
->result_ind
) {
603 data
->use_result_ind
= 1;
604 data
->notification
= EAP_SIM_SUCCESS
;
605 eap_sim_state(data
, NOTIFICATION
);
607 eap_sim_state(data
, SUCCESS
);
610 identity
= data
->reauth
->identity
;
611 identity_len
= data
->reauth
->identity_len
;
613 identity
= sm
->identity
;
614 identity_len
= sm
->identity_len
;
617 id2
= eap_sim_db_get_permanent(sm
->eap_sim_db_priv
, identity
,
618 identity_len
, &id2_len
);
621 identity_len
= id2_len
;
624 if (data
->next_pseudonym
) {
625 eap_sim_db_add_pseudonym(sm
->eap_sim_db_priv
, identity
,
626 identity_len
, data
->next_pseudonym
);
627 data
->next_pseudonym
= NULL
;
629 if (data
->next_reauth_id
) {
630 eap_sim_db_add_reauth(sm
->eap_sim_db_priv
, identity
,
631 identity_len
, data
->next_reauth_id
,
632 data
->counter
+ 1, data
->mk
);
633 data
->next_reauth_id
= NULL
;
635 eap_sim_db_remove_reauth(sm
->eap_sim_db_priv
, data
->reauth
);
642 eap_sim_state(data
, FAILURE
);
643 eap_sim_db_remove_reauth(sm
->eap_sim_db_priv
, data
->reauth
);
649 static void eap_sim_process_client_error(struct eap_sm
*sm
,
650 struct eap_sim_data
*data
,
651 struct wpabuf
*respData
,
652 struct eap_sim_attrs
*attr
)
654 wpa_printf(MSG_DEBUG
, "EAP-SIM: Client reported error %d",
655 attr
->client_error_code
);
656 if (data
->notification
== EAP_SIM_SUCCESS
&& data
->use_result_ind
)
657 eap_sim_state(data
, SUCCESS
);
659 eap_sim_state(data
, FAILURE
);
663 static void eap_sim_process_notification(struct eap_sm
*sm
,
664 struct eap_sim_data
*data
,
665 struct wpabuf
*respData
,
666 struct eap_sim_attrs
*attr
)
668 wpa_printf(MSG_DEBUG
, "EAP-SIM: Client replied to notification");
669 if (data
->notification
== EAP_SIM_SUCCESS
&& data
->use_result_ind
)
670 eap_sim_state(data
, SUCCESS
);
672 eap_sim_state(data
, FAILURE
);
676 static void eap_sim_process(struct eap_sm
*sm
, void *priv
,
677 struct wpabuf
*respData
)
679 struct eap_sim_data
*data
= priv
;
683 struct eap_sim_attrs attr
;
685 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_SIM
, respData
, &len
);
686 if (pos
== NULL
|| len
< 3)
693 if (eap_sim_parse_attr(pos
, end
, &attr
, 0, 0)) {
694 wpa_printf(MSG_DEBUG
, "EAP-SIM: Failed to parse attributes");
695 eap_sim_state(data
, FAILURE
);
699 if (subtype
== EAP_SIM_SUBTYPE_CLIENT_ERROR
) {
700 eap_sim_process_client_error(sm
, data
, respData
, &attr
);
704 switch (data
->state
) {
706 eap_sim_process_start(sm
, data
, respData
, &attr
);
709 eap_sim_process_challenge(sm
, data
, respData
, &attr
);
712 eap_sim_process_reauth(sm
, data
, respData
, &attr
);
715 eap_sim_process_notification(sm
, data
, respData
, &attr
);
718 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unknown state %d in "
719 "process", data
->state
);
725 static Boolean
eap_sim_isDone(struct eap_sm
*sm
, void *priv
)
727 struct eap_sim_data
*data
= priv
;
728 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
732 static u8
* eap_sim_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
734 struct eap_sim_data
*data
= priv
;
737 if (data
->state
!= SUCCESS
)
740 key
= os_malloc(EAP_SIM_KEYING_DATA_LEN
);
743 os_memcpy(key
, data
->msk
, EAP_SIM_KEYING_DATA_LEN
);
744 *len
= EAP_SIM_KEYING_DATA_LEN
;
749 static u8
* eap_sim_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
751 struct eap_sim_data
*data
= priv
;
754 if (data
->state
!= SUCCESS
)
757 key
= os_malloc(EAP_EMSK_LEN
);
760 os_memcpy(key
, data
->emsk
, EAP_EMSK_LEN
);
766 static Boolean
eap_sim_isSuccess(struct eap_sm
*sm
, void *priv
)
768 struct eap_sim_data
*data
= priv
;
769 return data
->state
== SUCCESS
;
773 int eap_server_sim_register(void)
775 struct eap_method
*eap
;
778 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
779 EAP_VENDOR_IETF
, EAP_TYPE_SIM
, "SIM");
783 eap
->init
= eap_sim_init
;
784 eap
->reset
= eap_sim_reset
;
785 eap
->buildReq
= eap_sim_buildReq
;
786 eap
->check
= eap_sim_check
;
787 eap
->process
= eap_sim_process
;
788 eap
->isDone
= eap_sim_isDone
;
789 eap
->getKey
= eap_sim_getKey
;
790 eap
->isSuccess
= eap_sim_isSuccess
;
791 eap
->get_emsk
= eap_sim_get_emsk
;
793 ret
= eap_server_method_register(eap
);
795 eap_server_method_free(eap
);