2 * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "pcsc_funcs.h"
13 #include "crypto/crypto.h"
14 #include "crypto/sha1.h"
15 #include "crypto/sha256.h"
16 #include "crypto/milenage.h"
17 #include "eap_common/eap_sim_common.h"
18 #include "eap_config.h"
23 u8 ik
[EAP_AKA_IK_LEN
], ck
[EAP_AKA_CK_LEN
], res
[EAP_AKA_RES_MAX_LEN
];
25 u8 nonce_s
[EAP_SIM_NONCE_S_LEN
];
26 u8 mk
[EAP_SIM_MK_LEN
];
27 u8 k_aut
[EAP_AKA_PRIME_K_AUT_LEN
];
28 u8 k_encr
[EAP_SIM_K_ENCR_LEN
];
29 u8 k_re
[EAP_AKA_PRIME_K_RE_LEN
]; /* EAP-AKA' only */
30 u8 msk
[EAP_SIM_KEYING_DATA_LEN
];
31 u8 emsk
[EAP_EMSK_LEN
];
32 u8 rand
[EAP_AKA_RAND_LEN
], autn
[EAP_AKA_AUTN_LEN
];
33 u8 auts
[EAP_AKA_AUTS_LEN
];
35 int num_id_req
, num_notification
;
41 unsigned int counter
, counter_too_small
;
42 u8
*last_eap_identity
;
43 size_t last_eap_identity_len
;
45 CONTINUE
, RESULT_SUCCESS
, RESULT_FAILURE
, SUCCESS
, FAILURE
48 struct wpabuf
*id_msgs
;
50 int result_ind
, use_result_ind
;
53 size_t network_name_len
;
59 #ifndef CONFIG_NO_STDOUT_DEBUG
60 static const char * eap_aka_state_txt(int state
)
66 return "RESULT_SUCCESS";
68 return "RESULT_FAILURE";
77 #endif /* CONFIG_NO_STDOUT_DEBUG */
80 static void eap_aka_state(struct eap_aka_data
*data
, int state
)
82 wpa_printf(MSG_DEBUG
, "EAP-AKA: %s -> %s",
83 eap_aka_state_txt(data
->state
),
84 eap_aka_state_txt(state
));
89 static void * eap_aka_init(struct eap_sm
*sm
)
91 struct eap_aka_data
*data
;
92 const char *phase1
= eap_get_config_phase1(sm
);
94 data
= os_zalloc(sizeof(*data
));
98 data
->eap_method
= EAP_TYPE_AKA
;
100 eap_aka_state(data
, CONTINUE
);
103 data
->result_ind
= phase1
&& os_strstr(phase1
, "result_ind=1") != NULL
;
110 static void * eap_aka_prime_init(struct eap_sm
*sm
)
112 struct eap_aka_data
*data
= eap_aka_init(sm
);
115 data
->eap_method
= EAP_TYPE_AKA_PRIME
;
118 #endif /* EAP_AKA_PRIME */
121 static void eap_aka_deinit(struct eap_sm
*sm
, void *priv
)
123 struct eap_aka_data
*data
= priv
;
125 os_free(data
->pseudonym
);
126 os_free(data
->reauth_id
);
127 os_free(data
->last_eap_identity
);
128 wpabuf_free(data
->id_msgs
);
129 os_free(data
->network_name
);
135 static int eap_aka_umts_auth(struct eap_sm
*sm
, struct eap_aka_data
*data
)
137 struct eap_peer_config
*conf
;
139 wpa_printf(MSG_DEBUG
, "EAP-AKA: UMTS authentication algorithm");
141 conf
= eap_get_config(sm
);
145 return scard_umts_auth(sm
->scard_ctx
, data
->rand
,
146 data
->autn
, data
->res
, &data
->res_len
,
147 data
->ik
, data
->ck
, data
->auts
);
150 #ifdef CONFIG_USIM_SIMULATOR
151 if (conf
->password
) {
152 u8 opc
[16], k
[16], sqn
[6];
154 wpa_printf(MSG_DEBUG
, "EAP-AKA: Use internal Milenage "
155 "implementation for UMTS authentication");
156 if (conf
->password_len
< 78) {
157 wpa_printf(MSG_DEBUG
, "EAP-AKA: invalid Milenage "
161 pos
= (const char *) conf
->password
;
162 if (hexstr2bin(pos
, k
, 16))
169 if (hexstr2bin(pos
, opc
, 16))
176 if (hexstr2bin(pos
, sqn
, 6))
179 return milenage_check(opc
, k
, sqn
, data
->rand
, data
->autn
,
181 data
->res
, &data
->res_len
, data
->auts
);
183 #endif /* CONFIG_USIM_SIMULATOR */
185 #ifdef CONFIG_USIM_HARDCODED
186 wpa_printf(MSG_DEBUG
, "EAP-AKA: Use hardcoded Kc and SRES values for "
189 /* These hardcoded Kc and SRES values are used for testing.
190 * Could consider making them configurable. */
191 os_memset(data
->res
, '2', EAP_AKA_RES_MAX_LEN
);
192 data
->res_len
= EAP_AKA_RES_MAX_LEN
;
193 os_memset(data
->ik
, '3', EAP_AKA_IK_LEN
);
194 os_memset(data
->ck
, '4', EAP_AKA_CK_LEN
);
196 u8 autn
[EAP_AKA_AUTN_LEN
];
197 os_memset(autn
, '1', EAP_AKA_AUTN_LEN
);
198 if (os_memcmp(autn
, data
->autn
, EAP_AKA_AUTN_LEN
) != 0) {
199 wpa_printf(MSG_WARNING
, "EAP-AKA: AUTN did not match "
200 "with expected value");
206 static int test_resync
= 1;
208 /* Test Resynchronization */
216 #else /* CONFIG_USIM_HARDCODED */
218 wpa_printf(MSG_DEBUG
, "EAP-AKA: No UMTS authentication algorith "
222 #endif /* CONFIG_USIM_HARDCODED */
226 #define CLEAR_PSEUDONYM 0x01
227 #define CLEAR_REAUTH_ID 0x02
228 #define CLEAR_EAP_ID 0x04
230 static void eap_aka_clear_identities(struct eap_aka_data
*data
, int id
)
232 if ((id
& CLEAR_PSEUDONYM
) && data
->pseudonym
) {
233 wpa_printf(MSG_DEBUG
, "EAP-AKA: forgetting old pseudonym");
234 os_free(data
->pseudonym
);
235 data
->pseudonym
= NULL
;
236 data
->pseudonym_len
= 0;
238 if ((id
& CLEAR_REAUTH_ID
) && data
->reauth_id
) {
239 wpa_printf(MSG_DEBUG
, "EAP-AKA: forgetting old reauth_id");
240 os_free(data
->reauth_id
);
241 data
->reauth_id
= NULL
;
242 data
->reauth_id_len
= 0;
244 if ((id
& CLEAR_EAP_ID
) && data
->last_eap_identity
) {
245 wpa_printf(MSG_DEBUG
, "EAP-AKA: forgetting old eap_id");
246 os_free(data
->last_eap_identity
);
247 data
->last_eap_identity
= NULL
;
248 data
->last_eap_identity_len
= 0;
253 static int eap_aka_learn_ids(struct eap_sm
*sm
, struct eap_aka_data
*data
,
254 struct eap_sim_attrs
*attr
)
256 if (attr
->next_pseudonym
) {
257 const u8
*identity
= NULL
;
258 size_t identity_len
= 0;
259 const u8
*realm
= NULL
;
260 size_t realm_len
= 0;
262 wpa_hexdump_ascii(MSG_DEBUG
,
263 "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
264 attr
->next_pseudonym
,
265 attr
->next_pseudonym_len
);
266 os_free(data
->pseudonym
);
267 /* Look for the realm of the permanent identity */
268 identity
= eap_get_config_identity(sm
, &identity_len
);
270 for (realm
= identity
, realm_len
= identity_len
;
271 realm_len
> 0; realm_len
--, realm
++) {
276 data
->pseudonym
= os_malloc(attr
->next_pseudonym_len
+
278 if (data
->pseudonym
== NULL
) {
279 wpa_printf(MSG_INFO
, "EAP-AKA: (encr) No memory for "
281 data
->pseudonym_len
= 0;
284 os_memcpy(data
->pseudonym
, attr
->next_pseudonym
,
285 attr
->next_pseudonym_len
);
287 os_memcpy(data
->pseudonym
+ attr
->next_pseudonym_len
,
290 data
->pseudonym_len
= attr
->next_pseudonym_len
+ realm_len
;
293 if (attr
->next_reauth_id
) {
294 os_free(data
->reauth_id
);
295 data
->reauth_id
= os_malloc(attr
->next_reauth_id_len
);
296 if (data
->reauth_id
== NULL
) {
297 wpa_printf(MSG_INFO
, "EAP-AKA: (encr) No memory for "
299 data
->reauth_id_len
= 0;
302 os_memcpy(data
->reauth_id
, attr
->next_reauth_id
,
303 attr
->next_reauth_id_len
);
304 data
->reauth_id_len
= attr
->next_reauth_id_len
;
305 wpa_hexdump_ascii(MSG_DEBUG
,
306 "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
308 data
->reauth_id_len
);
315 static int eap_aka_add_id_msg(struct eap_aka_data
*data
,
316 const struct wpabuf
*msg
)
321 if (data
->id_msgs
== NULL
) {
322 data
->id_msgs
= wpabuf_dup(msg
);
323 return data
->id_msgs
== NULL
? -1 : 0;
326 if (wpabuf_resize(&data
->id_msgs
, wpabuf_len(msg
)) < 0)
328 wpabuf_put_buf(data
->id_msgs
, msg
);
334 static void eap_aka_add_checkcode(struct eap_aka_data
*data
,
335 struct eap_sim_msg
*msg
)
339 u8 hash
[SHA256_MAC_LEN
];
341 wpa_printf(MSG_DEBUG
, " AT_CHECKCODE");
343 if (data
->id_msgs
== NULL
) {
345 * No EAP-AKA/Identity packets were exchanged - send empty
348 eap_sim_msg_add(msg
, EAP_SIM_AT_CHECKCODE
, 0, NULL
, 0);
352 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
353 addr
= wpabuf_head(data
->id_msgs
);
354 len
= wpabuf_len(data
->id_msgs
);
355 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA: AT_CHECKCODE data", addr
, len
);
357 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
)
358 sha256_vector(1, &addr
, &len
, hash
);
360 #endif /* EAP_AKA_PRIME */
361 sha1_vector(1, &addr
, &len
, hash
);
363 eap_sim_msg_add(msg
, EAP_SIM_AT_CHECKCODE
, 0, hash
,
364 data
->eap_method
== EAP_TYPE_AKA_PRIME
?
365 EAP_AKA_PRIME_CHECKCODE_LEN
: EAP_AKA_CHECKCODE_LEN
);
369 static int eap_aka_verify_checkcode(struct eap_aka_data
*data
,
370 const u8
*checkcode
, size_t checkcode_len
)
374 u8 hash
[SHA256_MAC_LEN
];
377 if (checkcode
== NULL
)
380 if (data
->id_msgs
== NULL
) {
381 if (checkcode_len
!= 0) {
382 wpa_printf(MSG_DEBUG
, "EAP-AKA: Checkcode from server "
383 "indicates that AKA/Identity messages were "
384 "used, but they were not");
390 hash_len
= data
->eap_method
== EAP_TYPE_AKA_PRIME
?
391 EAP_AKA_PRIME_CHECKCODE_LEN
: EAP_AKA_CHECKCODE_LEN
;
393 if (checkcode_len
!= hash_len
) {
394 wpa_printf(MSG_DEBUG
, "EAP-AKA: Checkcode from server "
395 "indicates that AKA/Identity message were not "
396 "used, but they were");
400 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
401 addr
= wpabuf_head(data
->id_msgs
);
402 len
= wpabuf_len(data
->id_msgs
);
404 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
)
405 sha256_vector(1, &addr
, &len
, hash
);
407 #endif /* EAP_AKA_PRIME */
408 sha1_vector(1, &addr
, &len
, hash
);
410 if (os_memcmp(hash
, checkcode
, hash_len
) != 0) {
411 wpa_printf(MSG_DEBUG
, "EAP-AKA: Mismatch in AT_CHECKCODE");
419 static struct wpabuf
* eap_aka_client_error(struct eap_aka_data
*data
, u8 id
,
422 struct eap_sim_msg
*msg
;
424 eap_aka_state(data
, FAILURE
);
425 data
->num_id_req
= 0;
426 data
->num_notification
= 0;
428 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
429 EAP_AKA_SUBTYPE_CLIENT_ERROR
);
430 eap_sim_msg_add(msg
, EAP_SIM_AT_CLIENT_ERROR_CODE
, err
, NULL
, 0);
431 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
435 static struct wpabuf
* eap_aka_authentication_reject(struct eap_aka_data
*data
,
438 struct eap_sim_msg
*msg
;
440 eap_aka_state(data
, FAILURE
);
441 data
->num_id_req
= 0;
442 data
->num_notification
= 0;
444 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Authentication-Reject "
446 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
447 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT
);
448 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
452 static struct wpabuf
* eap_aka_synchronization_failure(
453 struct eap_aka_data
*data
, u8 id
)
455 struct eap_sim_msg
*msg
;
457 data
->num_id_req
= 0;
458 data
->num_notification
= 0;
460 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Synchronization-Failure "
462 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
463 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE
);
464 wpa_printf(MSG_DEBUG
, " AT_AUTS");
465 eap_sim_msg_add_full(msg
, EAP_SIM_AT_AUTS
, data
->auts
,
467 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
471 static struct wpabuf
* eap_aka_response_identity(struct eap_sm
*sm
,
472 struct eap_aka_data
*data
,
474 enum eap_sim_id_req id_req
)
476 const u8
*identity
= NULL
;
477 size_t identity_len
= 0;
478 struct eap_sim_msg
*msg
;
481 if (id_req
== ANY_ID
&& data
->reauth_id
) {
482 identity
= data
->reauth_id
;
483 identity_len
= data
->reauth_id_len
;
485 } else if ((id_req
== ANY_ID
|| id_req
== FULLAUTH_ID
) &&
487 identity
= data
->pseudonym
;
488 identity_len
= data
->pseudonym_len
;
489 eap_aka_clear_identities(data
, CLEAR_REAUTH_ID
);
490 } else if (id_req
!= NO_ID_REQ
) {
491 identity
= eap_get_config_identity(sm
, &identity_len
);
493 eap_aka_clear_identities(data
, CLEAR_PSEUDONYM
|
497 if (id_req
!= NO_ID_REQ
)
498 eap_aka_clear_identities(data
, CLEAR_EAP_ID
);
500 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Identity (id=%d)", id
);
501 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
502 EAP_AKA_SUBTYPE_IDENTITY
);
505 wpa_hexdump_ascii(MSG_DEBUG
, " AT_IDENTITY",
506 identity
, identity_len
);
507 eap_sim_msg_add(msg
, EAP_SIM_AT_IDENTITY
, identity_len
,
508 identity
, identity_len
);
511 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
515 static struct wpabuf
* eap_aka_response_challenge(struct eap_aka_data
*data
,
518 struct eap_sim_msg
*msg
;
520 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Challenge (id=%d)", id
);
521 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
522 EAP_AKA_SUBTYPE_CHALLENGE
);
523 wpa_printf(MSG_DEBUG
, " AT_RES");
524 eap_sim_msg_add(msg
, EAP_SIM_AT_RES
, data
->res_len
* 8,
525 data
->res
, data
->res_len
);
526 eap_aka_add_checkcode(data
, msg
);
527 if (data
->use_result_ind
) {
528 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
529 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
531 wpa_printf(MSG_DEBUG
, " AT_MAC");
532 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
533 return eap_sim_msg_finish(msg
, data
->k_aut
, (u8
*) "", 0);
537 static struct wpabuf
* eap_aka_response_reauth(struct eap_aka_data
*data
,
538 u8 id
, int counter_too_small
,
541 struct eap_sim_msg
*msg
;
542 unsigned int counter
;
544 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Reauthentication (id=%d)",
546 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
547 EAP_AKA_SUBTYPE_REAUTHENTICATION
);
548 wpa_printf(MSG_DEBUG
, " AT_IV");
549 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
550 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
, EAP_SIM_AT_ENCR_DATA
);
552 if (counter_too_small
) {
553 wpa_printf(MSG_DEBUG
, " *AT_COUNTER_TOO_SMALL");
554 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER_TOO_SMALL
, 0, NULL
, 0);
555 counter
= data
->counter_too_small
;
557 counter
= data
->counter
;
559 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", counter
);
560 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, counter
, NULL
, 0);
562 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
, EAP_SIM_AT_PADDING
)) {
563 wpa_printf(MSG_WARNING
, "EAP-AKA: Failed to encrypt "
565 eap_sim_msg_free(msg
);
568 eap_aka_add_checkcode(data
, msg
);
569 if (data
->use_result_ind
) {
570 wpa_printf(MSG_DEBUG
, " AT_RESULT_IND");
571 eap_sim_msg_add(msg
, EAP_SIM_AT_RESULT_IND
, 0, NULL
, 0);
573 wpa_printf(MSG_DEBUG
, " AT_MAC");
574 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
575 return eap_sim_msg_finish(msg
, data
->k_aut
, nonce_s
,
576 EAP_SIM_NONCE_S_LEN
);
580 static struct wpabuf
* eap_aka_response_notification(struct eap_aka_data
*data
,
581 u8 id
, u16 notification
)
583 struct eap_sim_msg
*msg
;
584 u8
*k_aut
= (notification
& 0x4000) == 0 ? data
->k_aut
: NULL
;
586 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Notification (id=%d)", id
);
587 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
588 EAP_AKA_SUBTYPE_NOTIFICATION
);
589 if (k_aut
&& data
->reauth
) {
590 wpa_printf(MSG_DEBUG
, " AT_IV");
591 wpa_printf(MSG_DEBUG
, " AT_ENCR_DATA");
592 eap_sim_msg_add_encr_start(msg
, EAP_SIM_AT_IV
,
593 EAP_SIM_AT_ENCR_DATA
);
594 wpa_printf(MSG_DEBUG
, " *AT_COUNTER %d", data
->counter
);
595 eap_sim_msg_add(msg
, EAP_SIM_AT_COUNTER
, data
->counter
,
597 if (eap_sim_msg_add_encr_end(msg
, data
->k_encr
,
598 EAP_SIM_AT_PADDING
)) {
599 wpa_printf(MSG_WARNING
, "EAP-AKA: Failed to encrypt "
601 eap_sim_msg_free(msg
);
606 wpa_printf(MSG_DEBUG
, " AT_MAC");
607 eap_sim_msg_add_mac(msg
, EAP_SIM_AT_MAC
);
609 return eap_sim_msg_finish(msg
, k_aut
, (u8
*) "", 0);
613 static struct wpabuf
* eap_aka_process_identity(struct eap_sm
*sm
,
614 struct eap_aka_data
*data
,
616 const struct wpabuf
*reqData
,
617 struct eap_sim_attrs
*attr
)
622 wpa_printf(MSG_DEBUG
, "EAP-AKA: subtype Identity");
625 switch (attr
->id_req
) {
629 if (data
->num_id_req
> 0)
634 if (data
->num_id_req
> 1)
639 if (data
->num_id_req
> 2)
645 wpa_printf(MSG_INFO
, "EAP-AKA: Too many ID requests "
646 "used within one authentication");
647 return eap_aka_client_error(data
, id
,
648 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
651 buf
= eap_aka_response_identity(sm
, data
, id
, attr
->id_req
);
653 if (data
->prev_id
!= id
) {
654 eap_aka_add_id_msg(data
, reqData
);
655 eap_aka_add_id_msg(data
, buf
);
663 static int eap_aka_verify_mac(struct eap_aka_data
*data
,
664 const struct wpabuf
*req
,
665 const u8
*mac
, const u8
*extra
,
668 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
)
669 return eap_sim_verify_mac_sha256(data
->k_aut
, req
, mac
, extra
,
671 return eap_sim_verify_mac(data
->k_aut
, req
, mac
, extra
, extra_len
);
676 static struct wpabuf
* eap_aka_prime_kdf_select(struct eap_aka_data
*data
,
679 struct eap_sim_msg
*msg
;
681 data
->kdf_negotiation
= 1;
683 wpa_printf(MSG_DEBUG
, "Generating EAP-AKA Challenge (id=%d) (KDF "
685 msg
= eap_sim_msg_init(EAP_CODE_RESPONSE
, id
, data
->eap_method
,
686 EAP_AKA_SUBTYPE_CHALLENGE
);
687 wpa_printf(MSG_DEBUG
, " AT_KDF");
688 eap_sim_msg_add(msg
, EAP_SIM_AT_KDF
, kdf
, NULL
, 0);
689 return eap_sim_msg_finish(msg
, NULL
, NULL
, 0);
693 static struct wpabuf
* eap_aka_prime_kdf_neg(struct eap_aka_data
*data
,
694 u8 id
, struct eap_sim_attrs
*attr
)
698 for (i
= 0; i
< attr
->kdf_count
; i
++) {
699 if (attr
->kdf
[i
] == EAP_AKA_PRIME_KDF
)
700 return eap_aka_prime_kdf_select(data
, id
,
704 /* No matching KDF found - fail authentication as if AUTN had been
706 return eap_aka_authentication_reject(data
, id
);
710 static int eap_aka_prime_kdf_valid(struct eap_aka_data
*data
,
711 struct eap_sim_attrs
*attr
)
715 if (attr
->kdf_count
== 0)
718 /* The only allowed (and required) duplication of a KDF is the addition
719 * of the selected KDF into the beginning of the list. */
721 if (data
->kdf_negotiation
) {
722 if (attr
->kdf
[0] != data
->kdf
) {
723 wpa_printf(MSG_WARNING
, "EAP-AKA': The server did not "
724 "accept the selected KDF");
728 for (i
= 1; i
< attr
->kdf_count
; i
++) {
729 if (attr
->kdf
[i
] == data
->kdf
)
732 if (i
== attr
->kdf_count
&&
733 attr
->kdf_count
< EAP_AKA_PRIME_KDF_MAX
) {
734 wpa_printf(MSG_WARNING
, "EAP-AKA': The server did not "
735 "duplicate the selected KDF");
739 /* TODO: should check that the list is identical to the one
740 * used in the previous Challenge message apart from the added
741 * entry in the beginning. */
744 for (i
= data
->kdf
? 1 : 0; i
< attr
->kdf_count
; i
++) {
745 for (j
= i
+ 1; j
< attr
->kdf_count
; j
++) {
746 if (attr
->kdf
[i
] == attr
->kdf
[j
]) {
747 wpa_printf(MSG_WARNING
, "EAP-AKA': The server "
748 "included a duplicated KDF");
756 #endif /* EAP_AKA_PRIME */
759 static struct wpabuf
* eap_aka_process_challenge(struct eap_sm
*sm
,
760 struct eap_aka_data
*data
,
762 const struct wpabuf
*reqData
,
763 struct eap_sim_attrs
*attr
)
768 struct eap_sim_attrs eattr
;
770 wpa_printf(MSG_DEBUG
, "EAP-AKA: subtype Challenge");
772 if (attr
->checkcode
&&
773 eap_aka_verify_checkcode(data
, attr
->checkcode
,
774 attr
->checkcode_len
)) {
775 wpa_printf(MSG_WARNING
, "EAP-AKA: Invalid AT_CHECKCODE in the "
777 return eap_aka_client_error(data
, id
,
778 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
782 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
) {
783 if (!attr
->kdf_input
|| attr
->kdf_input_len
== 0) {
784 wpa_printf(MSG_WARNING
, "EAP-AKA': Challenge message "
785 "did not include non-empty AT_KDF_INPUT");
786 /* Fail authentication as if AUTN had been incorrect */
787 return eap_aka_authentication_reject(data
, id
);
789 os_free(data
->network_name
);
790 data
->network_name
= os_malloc(attr
->kdf_input_len
);
791 if (data
->network_name
== NULL
) {
792 wpa_printf(MSG_WARNING
, "EAP-AKA': No memory for "
793 "storing Network Name");
794 return eap_aka_authentication_reject(data
, id
);
796 os_memcpy(data
->network_name
, attr
->kdf_input
,
797 attr
->kdf_input_len
);
798 data
->network_name_len
= attr
->kdf_input_len
;
799 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-AKA': Network Name "
801 data
->network_name
, data
->network_name_len
);
802 /* TODO: check Network Name per 3GPP.33.402 */
804 if (!eap_aka_prime_kdf_valid(data
, attr
))
805 return eap_aka_authentication_reject(data
, id
);
807 if (attr
->kdf
[0] != EAP_AKA_PRIME_KDF
)
808 return eap_aka_prime_kdf_neg(data
, id
, attr
);
810 data
->kdf
= EAP_AKA_PRIME_KDF
;
811 wpa_printf(MSG_DEBUG
, "EAP-AKA': KDF %d selected", data
->kdf
);
814 if (data
->eap_method
== EAP_TYPE_AKA
&& attr
->bidding
) {
815 u16 flags
= WPA_GET_BE16(attr
->bidding
);
816 if ((flags
& EAP_AKA_BIDDING_FLAG_D
) &&
817 eap_allowed_method(sm
, EAP_VENDOR_IETF
,
818 EAP_TYPE_AKA_PRIME
)) {
819 wpa_printf(MSG_WARNING
, "EAP-AKA: Bidding down from "
820 "AKA' to AKA detected");
821 /* Fail authentication as if AUTN had been incorrect */
822 return eap_aka_authentication_reject(data
, id
);
825 #endif /* EAP_AKA_PRIME */
828 if (!attr
->mac
|| !attr
->rand
|| !attr
->autn
) {
829 wpa_printf(MSG_WARNING
, "EAP-AKA: Challenge message "
830 "did not include%s%s%s",
831 !attr
->mac
? " AT_MAC" : "",
832 !attr
->rand
? " AT_RAND" : "",
833 !attr
->autn
? " AT_AUTN" : "");
834 return eap_aka_client_error(data
, id
,
835 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
837 os_memcpy(data
->rand
, attr
->rand
, EAP_AKA_RAND_LEN
);
838 os_memcpy(data
->autn
, attr
->autn
, EAP_AKA_AUTN_LEN
);
840 res
= eap_aka_umts_auth(sm
, data
);
842 wpa_printf(MSG_WARNING
, "EAP-AKA: UMTS authentication "
844 return eap_aka_authentication_reject(data
, id
);
845 } else if (res
== -2) {
846 wpa_printf(MSG_WARNING
, "EAP-AKA: UMTS authentication "
847 "failed (AUTN seq# -> AUTS)");
848 return eap_aka_synchronization_failure(data
, id
);
850 wpa_printf(MSG_WARNING
, "EAP-AKA: UMTS authentication failed");
851 return eap_aka_client_error(data
, id
,
852 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
855 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
) {
856 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
857 * needed 6-octet SQN ^ AK for CK',IK' derivation */
858 u16 amf
= WPA_GET_BE16(data
->autn
+ 6);
859 if (!(amf
& 0x8000)) {
860 wpa_printf(MSG_WARNING
, "EAP-AKA': AMF separation bit "
861 "not set (AMF=0x%4x)", amf
);
862 return eap_aka_authentication_reject(data
, id
);
864 eap_aka_prime_derive_ck_ik_prime(data
->ck
, data
->ik
,
867 data
->network_name_len
);
869 #endif /* EAP_AKA_PRIME */
870 if (data
->last_eap_identity
) {
871 identity
= data
->last_eap_identity
;
872 identity_len
= data
->last_eap_identity_len
;
873 } else if (data
->pseudonym
) {
874 identity
= data
->pseudonym
;
875 identity_len
= data
->pseudonym_len
;
877 identity
= eap_get_config_identity(sm
, &identity_len
);
878 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-AKA: Selected identity for MK "
879 "derivation", identity
, identity_len
);
880 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
) {
881 eap_aka_prime_derive_keys(identity
, identity_len
, data
->ik
,
882 data
->ck
, data
->k_encr
, data
->k_aut
,
883 data
->k_re
, data
->msk
, data
->emsk
);
885 eap_aka_derive_mk(identity
, identity_len
, data
->ik
, data
->ck
,
887 eap_sim_derive_keys(data
->mk
, data
->k_encr
, data
->k_aut
,
888 data
->msk
, data
->emsk
);
890 if (eap_aka_verify_mac(data
, reqData
, attr
->mac
, (u8
*) "", 0)) {
891 wpa_printf(MSG_WARNING
, "EAP-AKA: Challenge message "
892 "used invalid AT_MAC");
893 return eap_aka_client_error(data
, id
,
894 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
897 /* Old reauthentication identity must not be used anymore. In
898 * other words, if no new identities are received, full
899 * authentication will be used on next reauthentication (using
900 * pseudonym identity or permanent identity). */
901 eap_aka_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
903 if (attr
->encr_data
) {
905 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
906 attr
->encr_data_len
, attr
->iv
,
908 if (decrypted
== NULL
) {
909 return eap_aka_client_error(
910 data
, id
, EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
912 eap_aka_learn_ids(sm
, data
, &eattr
);
916 if (data
->result_ind
&& attr
->result_ind
)
917 data
->use_result_ind
= 1;
919 if (data
->state
!= FAILURE
&& data
->state
!= RESULT_FAILURE
) {
920 eap_aka_state(data
, data
->use_result_ind
?
921 RESULT_SUCCESS
: SUCCESS
);
924 data
->num_id_req
= 0;
925 data
->num_notification
= 0;
926 /* RFC 4187 specifies that counter is initialized to one after
927 * fullauth, but initializing it to zero makes it easier to implement
928 * reauth verification. */
930 return eap_aka_response_challenge(data
, id
);
934 static int eap_aka_process_notification_reauth(struct eap_aka_data
*data
,
935 struct eap_sim_attrs
*attr
)
937 struct eap_sim_attrs eattr
;
940 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
941 wpa_printf(MSG_WARNING
, "EAP-AKA: Notification message after "
942 "reauth did not include encrypted data");
946 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
947 attr
->encr_data_len
, attr
->iv
, &eattr
,
949 if (decrypted
== NULL
) {
950 wpa_printf(MSG_WARNING
, "EAP-AKA: Failed to parse encrypted "
951 "data from notification message");
955 if (eattr
.counter
< 0 || (size_t) eattr
.counter
!= data
->counter
) {
956 wpa_printf(MSG_WARNING
, "EAP-AKA: Counter in notification "
957 "message does not match with counter in reauth "
968 static int eap_aka_process_notification_auth(struct eap_aka_data
*data
,
969 const struct wpabuf
*reqData
,
970 struct eap_sim_attrs
*attr
)
972 if (attr
->mac
== NULL
) {
973 wpa_printf(MSG_INFO
, "EAP-AKA: no AT_MAC in after_auth "
974 "Notification message");
978 if (eap_aka_verify_mac(data
, reqData
, attr
->mac
, (u8
*) "", 0)) {
979 wpa_printf(MSG_WARNING
, "EAP-AKA: Notification message "
980 "used invalid AT_MAC");
985 eap_aka_process_notification_reauth(data
, attr
)) {
986 wpa_printf(MSG_WARNING
, "EAP-AKA: Invalid notification "
987 "message after reauth");
995 static struct wpabuf
* eap_aka_process_notification(
996 struct eap_sm
*sm
, struct eap_aka_data
*data
, u8 id
,
997 const struct wpabuf
*reqData
, struct eap_sim_attrs
*attr
)
999 wpa_printf(MSG_DEBUG
, "EAP-AKA: subtype Notification");
1000 if (data
->num_notification
> 0) {
1001 wpa_printf(MSG_INFO
, "EAP-AKA: too many notification "
1002 "rounds (only one allowed)");
1003 return eap_aka_client_error(data
, id
,
1004 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1006 data
->num_notification
++;
1007 if (attr
->notification
== -1) {
1008 wpa_printf(MSG_INFO
, "EAP-AKA: no AT_NOTIFICATION in "
1009 "Notification message");
1010 return eap_aka_client_error(data
, id
,
1011 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1014 if ((attr
->notification
& 0x4000) == 0 &&
1015 eap_aka_process_notification_auth(data
, reqData
, attr
)) {
1016 return eap_aka_client_error(data
, id
,
1017 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1020 eap_sim_report_notification(sm
->msg_ctx
, attr
->notification
, 1);
1021 if (attr
->notification
>= 0 && attr
->notification
< 32768) {
1022 eap_aka_state(data
, FAILURE
);
1023 } else if (attr
->notification
== EAP_SIM_SUCCESS
&&
1024 data
->state
== RESULT_SUCCESS
)
1025 eap_aka_state(data
, SUCCESS
);
1026 return eap_aka_response_notification(data
, id
, attr
->notification
);
1030 static struct wpabuf
* eap_aka_process_reauthentication(
1031 struct eap_sm
*sm
, struct eap_aka_data
*data
, u8 id
,
1032 const struct wpabuf
*reqData
, struct eap_sim_attrs
*attr
)
1034 struct eap_sim_attrs eattr
;
1037 wpa_printf(MSG_DEBUG
, "EAP-AKA: subtype Reauthentication");
1039 if (attr
->checkcode
&&
1040 eap_aka_verify_checkcode(data
, attr
->checkcode
,
1041 attr
->checkcode_len
)) {
1042 wpa_printf(MSG_WARNING
, "EAP-AKA: Invalid AT_CHECKCODE in the "
1044 return eap_aka_client_error(data
, id
,
1045 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1048 if (data
->reauth_id
== NULL
) {
1049 wpa_printf(MSG_WARNING
, "EAP-AKA: Server is trying "
1050 "reauthentication, but no reauth_id available");
1051 return eap_aka_client_error(data
, id
,
1052 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1056 if (eap_aka_verify_mac(data
, reqData
, attr
->mac
, (u8
*) "", 0)) {
1057 wpa_printf(MSG_WARNING
, "EAP-AKA: Reauthentication "
1058 "did not have valid AT_MAC");
1059 return eap_aka_client_error(data
, id
,
1060 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1063 if (attr
->encr_data
== NULL
|| attr
->iv
== NULL
) {
1064 wpa_printf(MSG_WARNING
, "EAP-AKA: Reauthentication "
1065 "message did not include encrypted data");
1066 return eap_aka_client_error(data
, id
,
1067 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1070 decrypted
= eap_sim_parse_encr(data
->k_encr
, attr
->encr_data
,
1071 attr
->encr_data_len
, attr
->iv
, &eattr
,
1073 if (decrypted
== NULL
) {
1074 wpa_printf(MSG_WARNING
, "EAP-AKA: Failed to parse encrypted "
1075 "data from reauthentication message");
1076 return eap_aka_client_error(data
, id
,
1077 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1080 if (eattr
.nonce_s
== NULL
|| eattr
.counter
< 0) {
1081 wpa_printf(MSG_INFO
, "EAP-AKA: (encr) No%s%s in reauth packet",
1082 !eattr
.nonce_s
? " AT_NONCE_S" : "",
1083 eattr
.counter
< 0 ? " AT_COUNTER" : "");
1085 return eap_aka_client_error(data
, id
,
1086 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1089 if (eattr
.counter
< 0 || (size_t) eattr
.counter
<= data
->counter
) {
1091 wpa_printf(MSG_INFO
, "EAP-AKA: (encr) Invalid counter "
1092 "(%d <= %d)", eattr
.counter
, data
->counter
);
1093 data
->counter_too_small
= eattr
.counter
;
1095 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1096 * reauth_id must not be used to start a new reauthentication.
1097 * However, since it was used in the last EAP-Response-Identity
1098 * packet, it has to saved for the following fullauth to be
1099 * used in MK derivation. */
1100 os_free(data
->last_eap_identity
);
1101 data
->last_eap_identity
= data
->reauth_id
;
1102 data
->last_eap_identity_len
= data
->reauth_id_len
;
1103 data
->reauth_id
= NULL
;
1104 data
->reauth_id_len
= 0;
1106 res
= eap_aka_response_reauth(data
, id
, 1, eattr
.nonce_s
);
1111 data
->counter
= eattr
.counter
;
1113 os_memcpy(data
->nonce_s
, eattr
.nonce_s
, EAP_SIM_NONCE_S_LEN
);
1114 wpa_hexdump(MSG_DEBUG
, "EAP-AKA: (encr) AT_NONCE_S",
1115 data
->nonce_s
, EAP_SIM_NONCE_S_LEN
);
1117 if (data
->eap_method
== EAP_TYPE_AKA_PRIME
) {
1118 eap_aka_prime_derive_keys_reauth(data
->k_re
, data
->counter
,
1120 data
->reauth_id_len
,
1122 data
->msk
, data
->emsk
);
1124 eap_sim_derive_keys_reauth(data
->counter
, data
->reauth_id
,
1125 data
->reauth_id_len
,
1126 data
->nonce_s
, data
->mk
,
1127 data
->msk
, data
->emsk
);
1129 eap_aka_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
1130 eap_aka_learn_ids(sm
, data
, &eattr
);
1132 if (data
->result_ind
&& attr
->result_ind
)
1133 data
->use_result_ind
= 1;
1135 if (data
->state
!= FAILURE
&& data
->state
!= RESULT_FAILURE
) {
1136 eap_aka_state(data
, data
->use_result_ind
?
1137 RESULT_SUCCESS
: SUCCESS
);
1140 data
->num_id_req
= 0;
1141 data
->num_notification
= 0;
1142 if (data
->counter
> EAP_AKA_MAX_FAST_REAUTHS
) {
1143 wpa_printf(MSG_DEBUG
, "EAP-AKA: Maximum number of "
1144 "fast reauths performed - force fullauth");
1145 eap_aka_clear_identities(data
, CLEAR_REAUTH_ID
| CLEAR_EAP_ID
);
1148 return eap_aka_response_reauth(data
, id
, 0, data
->nonce_s
);
1152 static struct wpabuf
* eap_aka_process(struct eap_sm
*sm
, void *priv
,
1153 struct eap_method_ret
*ret
,
1154 const struct wpabuf
*reqData
)
1156 struct eap_aka_data
*data
= priv
;
1157 const struct eap_hdr
*req
;
1161 struct eap_sim_attrs attr
;
1164 wpa_hexdump_buf(MSG_DEBUG
, "EAP-AKA: EAP data", reqData
);
1165 if (eap_get_config_identity(sm
, &len
) == NULL
) {
1166 wpa_printf(MSG_INFO
, "EAP-AKA: Identity not configured");
1167 eap_sm_request_identity(sm
);
1172 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, data
->eap_method
, reqData
,
1174 if (pos
== NULL
|| len
< 1) {
1178 req
= wpabuf_head(reqData
);
1179 id
= req
->identifier
;
1180 len
= be_to_host16(req
->length
);
1182 ret
->ignore
= FALSE
;
1183 ret
->methodState
= METHOD_MAY_CONT
;
1184 ret
->decision
= DECISION_FAIL
;
1185 ret
->allowNotifications
= TRUE
;
1188 wpa_printf(MSG_DEBUG
, "EAP-AKA: Subtype=%d", subtype
);
1189 pos
+= 2; /* Reserved */
1191 if (eap_sim_parse_attr(pos
, wpabuf_head_u8(reqData
) + len
, &attr
,
1192 data
->eap_method
== EAP_TYPE_AKA_PRIME
? 2 : 1,
1194 res
= eap_aka_client_error(data
, id
,
1195 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1200 case EAP_AKA_SUBTYPE_IDENTITY
:
1201 res
= eap_aka_process_identity(sm
, data
, id
, reqData
, &attr
);
1203 case EAP_AKA_SUBTYPE_CHALLENGE
:
1204 res
= eap_aka_process_challenge(sm
, data
, id
, reqData
, &attr
);
1206 case EAP_AKA_SUBTYPE_NOTIFICATION
:
1207 res
= eap_aka_process_notification(sm
, data
, id
, reqData
,
1210 case EAP_AKA_SUBTYPE_REAUTHENTICATION
:
1211 res
= eap_aka_process_reauthentication(sm
, data
, id
, reqData
,
1214 case EAP_AKA_SUBTYPE_CLIENT_ERROR
:
1215 wpa_printf(MSG_DEBUG
, "EAP-AKA: subtype Client-Error");
1216 res
= eap_aka_client_error(data
, id
,
1217 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1220 wpa_printf(MSG_DEBUG
, "EAP-AKA: Unknown subtype=%d", subtype
);
1221 res
= eap_aka_client_error(data
, id
,
1222 EAP_AKA_UNABLE_TO_PROCESS_PACKET
);
1227 if (data
->state
== FAILURE
) {
1228 ret
->decision
= DECISION_FAIL
;
1229 ret
->methodState
= METHOD_DONE
;
1230 } else if (data
->state
== SUCCESS
) {
1231 ret
->decision
= data
->use_result_ind
?
1232 DECISION_UNCOND_SUCC
: DECISION_COND_SUCC
;
1234 * It is possible for the server to reply with AKA
1235 * Notification, so we must allow the method to continue and
1236 * not only accept EAP-Success at this point.
1238 ret
->methodState
= data
->use_result_ind
?
1239 METHOD_DONE
: METHOD_MAY_CONT
;
1240 } else if (data
->state
== RESULT_FAILURE
)
1241 ret
->methodState
= METHOD_CONT
;
1242 else if (data
->state
== RESULT_SUCCESS
)
1243 ret
->methodState
= METHOD_CONT
;
1245 if (ret
->methodState
== METHOD_DONE
) {
1246 ret
->allowNotifications
= FALSE
;
1253 static Boolean
eap_aka_has_reauth_data(struct eap_sm
*sm
, void *priv
)
1255 struct eap_aka_data
*data
= priv
;
1256 return data
->pseudonym
|| data
->reauth_id
;
1260 static void eap_aka_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
1262 struct eap_aka_data
*data
= priv
;
1263 eap_aka_clear_identities(data
, CLEAR_EAP_ID
);
1265 wpabuf_free(data
->id_msgs
);
1266 data
->id_msgs
= NULL
;
1267 data
->use_result_ind
= 0;
1268 data
->kdf_negotiation
= 0;
1272 static void * eap_aka_init_for_reauth(struct eap_sm
*sm
, void *priv
)
1274 struct eap_aka_data
*data
= priv
;
1275 data
->num_id_req
= 0;
1276 data
->num_notification
= 0;
1277 eap_aka_state(data
, CONTINUE
);
1282 static const u8
* eap_aka_get_identity(struct eap_sm
*sm
, void *priv
,
1285 struct eap_aka_data
*data
= priv
;
1287 if (data
->reauth_id
) {
1288 *len
= data
->reauth_id_len
;
1289 return data
->reauth_id
;
1292 if (data
->pseudonym
) {
1293 *len
= data
->pseudonym_len
;
1294 return data
->pseudonym
;
1301 static Boolean
eap_aka_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
1303 struct eap_aka_data
*data
= priv
;
1304 return data
->state
== SUCCESS
;
1308 static u8
* eap_aka_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1310 struct eap_aka_data
*data
= priv
;
1313 if (data
->state
!= SUCCESS
)
1316 key
= os_malloc(EAP_SIM_KEYING_DATA_LEN
);
1320 *len
= EAP_SIM_KEYING_DATA_LEN
;
1321 os_memcpy(key
, data
->msk
, EAP_SIM_KEYING_DATA_LEN
);
1327 static u8
* eap_aka_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
1329 struct eap_aka_data
*data
= priv
;
1332 if (data
->state
!= SUCCESS
)
1335 key
= os_malloc(EAP_EMSK_LEN
);
1339 *len
= EAP_EMSK_LEN
;
1340 os_memcpy(key
, data
->emsk
, EAP_EMSK_LEN
);
1346 int eap_peer_aka_register(void)
1348 struct eap_method
*eap
;
1351 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
1352 EAP_VENDOR_IETF
, EAP_TYPE_AKA
, "AKA");
1356 eap
->init
= eap_aka_init
;
1357 eap
->deinit
= eap_aka_deinit
;
1358 eap
->process
= eap_aka_process
;
1359 eap
->isKeyAvailable
= eap_aka_isKeyAvailable
;
1360 eap
->getKey
= eap_aka_getKey
;
1361 eap
->has_reauth_data
= eap_aka_has_reauth_data
;
1362 eap
->deinit_for_reauth
= eap_aka_deinit_for_reauth
;
1363 eap
->init_for_reauth
= eap_aka_init_for_reauth
;
1364 eap
->get_identity
= eap_aka_get_identity
;
1365 eap
->get_emsk
= eap_aka_get_emsk
;
1367 ret
= eap_peer_method_register(eap
);
1369 eap_peer_method_free(eap
);
1374 #ifdef EAP_AKA_PRIME
1375 int eap_peer_aka_prime_register(void)
1377 struct eap_method
*eap
;
1380 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
1381 EAP_VENDOR_IETF
, EAP_TYPE_AKA_PRIME
,
1386 eap
->init
= eap_aka_prime_init
;
1387 eap
->deinit
= eap_aka_deinit
;
1388 eap
->process
= eap_aka_process
;
1389 eap
->isKeyAvailable
= eap_aka_isKeyAvailable
;
1390 eap
->getKey
= eap_aka_getKey
;
1391 eap
->has_reauth_data
= eap_aka_has_reauth_data
;
1392 eap
->deinit_for_reauth
= eap_aka_deinit_for_reauth
;
1393 eap
->init_for_reauth
= eap_aka_init_for_reauth
;
1394 eap
->get_identity
= eap_aka_get_identity
;
1395 eap
->get_emsk
= eap_aka_get_emsk
;
1397 ret
= eap_peer_method_register(eap
);
1399 eap_peer_method_free(eap
);
1403 #endif /* EAP_AKA_PRIME */