2 * EAP peer method: EAP-EKE (RFC 6124)
3 * Copyright (c) 2013, 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 "crypto/random.h"
13 #include "eap_peer/eap_i.h"
14 #include "eap_common/eap_eke_common.h"
18 IDENTITY
, COMMIT
, CONFIRM
, SUCCESS
, FAILURE
21 u8 emsk
[EAP_EMSK_LEN
];
26 u8 dh_priv
[EAP_EKE_MAX_DH_LEN
];
27 struct eap_eke_session sess
;
28 u8 nonce_p
[EAP_EKE_MAX_NONCE_LEN
];
29 u8 nonce_s
[EAP_EKE_MAX_NONCE_LEN
];
31 u8 dhgroup
; /* forced DH group or 0 to allow all supported */
32 u8 encr
; /* forced encryption algorithm or 0 to allow all supported */
33 u8 prf
; /* forced PRF or 0 to allow all supported */
34 u8 mac
; /* forced MAC or 0 to allow all supported */
38 static const char * eap_eke_state_txt(int state
)
57 static void eap_eke_state(struct eap_eke_data
*data
, int state
)
59 wpa_printf(MSG_DEBUG
, "EAP-EKE: %s -> %s",
60 eap_eke_state_txt(data
->state
), eap_eke_state_txt(state
));
65 static void eap_eke_deinit(struct eap_sm
*sm
, void *priv
);
68 static void * eap_eke_init(struct eap_sm
*sm
)
70 struct eap_eke_data
*data
;
71 const u8
*identity
, *password
;
72 size_t identity_len
, password_len
;
75 password
= eap_get_config_password(sm
, &password_len
);
77 wpa_printf(MSG_INFO
, "EAP-EKE: No password configured");
81 data
= os_zalloc(sizeof(*data
));
84 eap_eke_state(data
, IDENTITY
);
86 identity
= eap_get_config_identity(sm
, &identity_len
);
88 data
->peerid
= os_memdup(identity
, identity_len
);
89 if (data
->peerid
== NULL
) {
90 eap_eke_deinit(sm
, data
);
93 data
->peerid_len
= identity_len
;
96 phase1
= eap_get_config_phase1(sm
);
100 pos
= os_strstr(phase1
, "dhgroup=");
102 data
->dhgroup
= atoi(pos
+ 8);
103 wpa_printf(MSG_DEBUG
, "EAP-EKE: Forced dhgroup %u",
107 pos
= os_strstr(phase1
, "encr=");
109 data
->encr
= atoi(pos
+ 5);
110 wpa_printf(MSG_DEBUG
, "EAP-EKE: Forced encr %u",
114 pos
= os_strstr(phase1
, "prf=");
116 data
->prf
= atoi(pos
+ 4);
117 wpa_printf(MSG_DEBUG
, "EAP-EKE: Forced prf %u",
121 pos
= os_strstr(phase1
, "mac=");
123 data
->mac
= atoi(pos
+ 4);
124 wpa_printf(MSG_DEBUG
, "EAP-EKE: Forced mac %u",
133 static void eap_eke_deinit(struct eap_sm
*sm
, void *priv
)
135 struct eap_eke_data
*data
= priv
;
136 eap_eke_session_clean(&data
->sess
);
137 os_free(data
->serverid
);
138 os_free(data
->peerid
);
139 wpabuf_free(data
->msgs
);
140 bin_clear_free(data
, sizeof(*data
));
144 static struct wpabuf
* eap_eke_build_msg(struct eap_eke_data
*data
, int id
,
145 size_t length
, u8 eke_exch
)
152 msg
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_EKE
, plen
,
153 EAP_CODE_RESPONSE
, id
);
155 wpa_printf(MSG_ERROR
, "EAP-EKE: Failed to allocate memory");
159 wpabuf_put_u8(msg
, eke_exch
);
165 static int eap_eke_supp_dhgroup(u8 dhgroup
)
167 return dhgroup
== EAP_EKE_DHGROUP_EKE_2
||
168 dhgroup
== EAP_EKE_DHGROUP_EKE_5
||
169 dhgroup
== EAP_EKE_DHGROUP_EKE_14
||
170 dhgroup
== EAP_EKE_DHGROUP_EKE_15
||
171 dhgroup
== EAP_EKE_DHGROUP_EKE_16
;
175 static int eap_eke_supp_encr(u8 encr
)
177 return encr
== EAP_EKE_ENCR_AES128_CBC
;
181 static int eap_eke_supp_prf(u8 prf
)
183 return prf
== EAP_EKE_PRF_HMAC_SHA1
||
184 prf
== EAP_EKE_PRF_HMAC_SHA2_256
;
188 static int eap_eke_supp_mac(u8 mac
)
190 return mac
== EAP_EKE_MAC_HMAC_SHA1
||
191 mac
== EAP_EKE_MAC_HMAC_SHA2_256
;
195 static struct wpabuf
* eap_eke_build_fail(struct eap_eke_data
*data
,
196 struct eap_method_ret
*ret
,
197 u8 id
, u32 failure_code
)
201 wpa_printf(MSG_DEBUG
, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x",
204 resp
= eap_eke_build_msg(data
, id
, 4, EAP_EKE_FAILURE
);
206 wpabuf_put_be32(resp
, failure_code
);
208 os_memset(data
->dh_priv
, 0, sizeof(data
->dh_priv
));
209 eap_eke_session_clean(&data
->sess
);
211 eap_eke_state(data
, FAILURE
);
212 ret
->methodState
= METHOD_DONE
;
213 ret
->decision
= DECISION_FAIL
;
214 ret
->allowNotifications
= FALSE
;
220 static struct wpabuf
* eap_eke_process_id(struct eap_eke_data
*data
,
221 struct eap_method_ret
*ret
,
222 const struct wpabuf
*reqData
,
227 unsigned num_prop
, i
;
229 const u8
*prop
= NULL
;
231 u8 id
= eap_get_id(reqData
);
233 if (data
->state
!= IDENTITY
) {
234 return eap_eke_build_fail(data
, ret
, id
,
235 EAP_EKE_FAIL_PROTO_ERROR
);
238 wpa_printf(MSG_DEBUG
, "EAP-EKE: Received EAP-EKE-ID/Request");
240 if (payload_len
< 2 + 4) {
241 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short ID/Request Data");
242 return eap_eke_build_fail(data
, ret
, id
,
243 EAP_EKE_FAIL_PROTO_ERROR
);
247 end
= payload
+ payload_len
;
250 pos
++; /* Ignore Reserved field */
252 if (pos
+ num_prop
* 4 > end
) {
253 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short ID/Request Data (num_prop=%u)",
255 return eap_eke_build_fail(data
, ret
, id
,
256 EAP_EKE_FAIL_PROTO_ERROR
);
259 for (i
= 0; i
< num_prop
; i
++) {
262 wpa_printf(MSG_DEBUG
, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u",
263 i
, pos
[0], pos
[1], pos
[2], pos
[3]);
266 if ((data
->dhgroup
&& data
->dhgroup
!= *tmp
) ||
267 !eap_eke_supp_dhgroup(*tmp
))
270 if ((data
->encr
&& data
->encr
!= *tmp
) ||
271 !eap_eke_supp_encr(*tmp
))
274 if ((data
->prf
&& data
->prf
!= *tmp
) ||
275 !eap_eke_supp_prf(*tmp
))
278 if ((data
->mac
&& data
->mac
!= *tmp
) ||
279 !eap_eke_supp_mac(*tmp
))
283 if (eap_eke_session_init(&data
->sess
, prop
[0], prop
[1], prop
[2],
289 wpa_printf(MSG_DEBUG
, "EAP-EKE: Selected proposal");
294 wpa_printf(MSG_DEBUG
, "EAP-EKE: No acceptable proposal found");
295 return eap_eke_build_fail(data
, ret
, id
,
296 EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN
);
299 pos
+= (num_prop
- i
- 1) * 4;
302 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short ID/Request Data to include IDType/Identity");
303 return eap_eke_build_fail(data
, ret
, id
,
304 EAP_EKE_FAIL_PROTO_ERROR
);
308 wpa_printf(MSG_DEBUG
, "EAP-EKE: Server IDType %u", idtype
);
309 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-EKE: Server Identity",
311 os_free(data
->serverid
);
312 data
->serverid
= os_memdup(pos
, end
- pos
);
313 if (data
->serverid
== NULL
) {
314 return eap_eke_build_fail(data
, ret
, id
,
315 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
317 data
->serverid_len
= end
- pos
;
319 wpa_printf(MSG_DEBUG
, "EAP-EKE: Sending EAP-EKE-ID/Response");
321 resp
= eap_eke_build_msg(data
, id
,
322 2 + 4 + 1 + data
->peerid_len
,
325 return eap_eke_build_fail(data
, ret
, id
,
326 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
329 wpabuf_put_u8(resp
, 1); /* NumProposals */
330 wpabuf_put_u8(resp
, 0); /* Reserved */
331 wpabuf_put_data(resp
, prop
, 4); /* Selected Proposal */
332 wpabuf_put_u8(resp
, EAP_EKE_ID_NAI
);
334 wpabuf_put_data(resp
, data
->peerid
, data
->peerid_len
);
336 wpabuf_free(data
->msgs
);
337 data
->msgs
= wpabuf_alloc(wpabuf_len(reqData
) + wpabuf_len(resp
));
338 if (data
->msgs
== NULL
) {
340 return eap_eke_build_fail(data
, ret
, id
,
341 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
343 wpabuf_put_buf(data
->msgs
, reqData
);
344 wpabuf_put_buf(data
->msgs
, resp
);
346 eap_eke_state(data
, COMMIT
);
352 static struct wpabuf
* eap_eke_process_commit(struct eap_sm
*sm
,
353 struct eap_eke_data
*data
,
354 struct eap_method_ret
*ret
,
355 const struct wpabuf
*reqData
,
360 const u8
*pos
, *end
, *dhcomp
;
363 u8 key
[EAP_EKE_MAX_KEY_LEN
];
364 u8 pub
[EAP_EKE_MAX_DH_LEN
];
367 u8 id
= eap_get_id(reqData
);
369 if (data
->state
!= COMMIT
) {
370 wpa_printf(MSG_DEBUG
, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data
->state
);
371 return eap_eke_build_fail(data
, ret
, id
,
372 EAP_EKE_FAIL_PROTO_ERROR
);
375 wpa_printf(MSG_DEBUG
, "EAP-EKE: Received EAP-EKE-Commit/Request");
377 password
= eap_get_config_password(sm
, &password_len
);
378 if (password
== NULL
) {
379 wpa_printf(MSG_INFO
, "EAP-EKE: No password configured!");
380 return eap_eke_build_fail(data
, ret
, id
,
381 EAP_EKE_FAIL_PASSWD_NOT_FOUND
);
385 end
= payload
+ payload_len
;
387 if (pos
+ data
->sess
.dhcomp_len
> end
) {
388 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short EAP-EKE-Commit");
389 return eap_eke_build_fail(data
, ret
, id
,
390 EAP_EKE_FAIL_PROTO_ERROR
);
393 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: DHComponent_S",
394 pos
, data
->sess
.dhcomp_len
);
396 pos
+= data
->sess
.dhcomp_len
;
397 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: CBValue", pos
, end
- pos
);
400 * temp = prf(0+, password)
401 * key = prf+(temp, ID_S | ID_P)
403 if (eap_eke_derive_key(&data
->sess
, password
, password_len
,
404 data
->serverid
, data
->serverid_len
,
405 data
->peerid
, data
->peerid_len
, key
) < 0) {
406 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to derive key");
407 return eap_eke_build_fail(data
, ret
, id
,
408 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
412 * y_p = g ^ x_p (mod p)
413 * x_p = random number 2 .. p-1
415 if (eap_eke_dh_init(data
->sess
.dhgroup
, data
->dh_priv
, pub
) < 0) {
416 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to initialize DH");
417 os_memset(key
, 0, sizeof(key
));
418 return eap_eke_build_fail(data
, ret
, id
,
419 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
422 if (eap_eke_shared_secret(&data
->sess
, key
, data
->dh_priv
, dhcomp
) < 0)
424 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to derive shared secret");
425 os_memset(key
, 0, sizeof(key
));
426 return eap_eke_build_fail(data
, ret
, id
,
427 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
430 if (eap_eke_derive_ke_ki(&data
->sess
,
431 data
->serverid
, data
->serverid_len
,
432 data
->peerid
, data
->peerid_len
) < 0) {
433 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to derive Ke/Ki");
434 os_memset(key
, 0, sizeof(key
));
435 return eap_eke_build_fail(data
, ret
, id
,
436 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
439 wpa_printf(MSG_DEBUG
, "EAP-EKE: Sending EAP-EKE-Commit/Response");
441 resp
= eap_eke_build_msg(data
, id
,
442 data
->sess
.dhcomp_len
+ data
->sess
.pnonce_len
,
445 os_memset(key
, 0, sizeof(key
));
446 return eap_eke_build_fail(data
, ret
, id
,
447 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
450 /* DHComponent_P = Encr(key, y_p) */
451 rpos
= wpabuf_put(resp
, data
->sess
.dhcomp_len
);
452 if (eap_eke_dhcomp(&data
->sess
, key
, pub
, rpos
) < 0) {
454 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to build DHComponent_P");
455 os_memset(key
, 0, sizeof(key
));
456 return eap_eke_build_fail(data
, ret
, id
,
457 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
459 os_memset(key
, 0, sizeof(key
));
461 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: DHComponent_P",
462 rpos
, data
->sess
.dhcomp_len
);
464 if (random_get_bytes(data
->nonce_p
, data
->sess
.nonce_len
)) {
466 return eap_eke_build_fail(data
, ret
, id
,
467 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
469 wpa_hexdump_key(MSG_DEBUG
, "EAP-EKE: Nonce_P",
470 data
->nonce_p
, data
->sess
.nonce_len
);
471 prot_len
= wpabuf_tailroom(resp
);
472 if (eap_eke_prot(&data
->sess
, data
->nonce_p
, data
->sess
.nonce_len
,
473 wpabuf_put(resp
, 0), &prot_len
) < 0) {
475 return eap_eke_build_fail(data
, ret
, id
,
476 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
478 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: PNonce_P",
479 wpabuf_put(resp
, 0), prot_len
);
480 wpabuf_put(resp
, prot_len
);
484 if (wpabuf_resize(&data
->msgs
, wpabuf_len(reqData
) + wpabuf_len(resp
))
487 return eap_eke_build_fail(data
, ret
, id
,
488 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
490 wpabuf_put_buf(data
->msgs
, reqData
);
491 wpabuf_put_buf(data
->msgs
, resp
);
493 eap_eke_state(data
, CONFIRM
);
499 static struct wpabuf
* eap_eke_process_confirm(struct eap_eke_data
*data
,
500 struct eap_method_ret
*ret
,
501 const struct wpabuf
*reqData
,
508 u8 nonces
[2 * EAP_EKE_MAX_NONCE_LEN
];
509 u8 auth_s
[EAP_EKE_MAX_HASH_LEN
];
512 u8 id
= eap_get_id(reqData
);
514 if (data
->state
!= CONFIRM
) {
515 wpa_printf(MSG_DEBUG
, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)",
517 return eap_eke_build_fail(data
, ret
, id
,
518 EAP_EKE_FAIL_PROTO_ERROR
);
521 wpa_printf(MSG_DEBUG
, "EAP-EKE: Received EAP-EKE-Confirm/Request");
524 end
= payload
+ payload_len
;
526 if (pos
+ data
->sess
.pnonce_ps_len
+ data
->sess
.prf_len
> end
) {
527 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short EAP-EKE-Confirm");
528 return eap_eke_build_fail(data
, ret
, id
,
529 EAP_EKE_FAIL_PROTO_ERROR
);
532 decrypt_len
= sizeof(nonces
);
533 if (eap_eke_decrypt_prot(&data
->sess
, pos
, data
->sess
.pnonce_ps_len
,
534 nonces
, &decrypt_len
) < 0) {
535 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to decrypt PNonce_PS");
536 return eap_eke_build_fail(data
, ret
, id
,
537 EAP_EKE_FAIL_AUTHENTICATION_FAIL
);
539 if (decrypt_len
!= (size_t) 2 * data
->sess
.nonce_len
) {
540 wpa_printf(MSG_INFO
, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S");
541 return eap_eke_build_fail(data
, ret
, id
,
542 EAP_EKE_FAIL_AUTHENTICATION_FAIL
);
544 wpa_hexdump_key(MSG_DEBUG
, "EAP-EKE: Received Nonce_P | Nonce_S",
545 nonces
, 2 * data
->sess
.nonce_len
);
546 if (os_memcmp(data
->nonce_p
, nonces
, data
->sess
.nonce_len
) != 0) {
547 wpa_printf(MSG_INFO
, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P");
548 return eap_eke_build_fail(data
, ret
, id
,
549 EAP_EKE_FAIL_AUTHENTICATION_FAIL
);
552 os_memcpy(data
->nonce_s
, nonces
+ data
->sess
.nonce_len
,
553 data
->sess
.nonce_len
);
554 wpa_hexdump_key(MSG_DEBUG
, "EAP-EKE: Nonce_S",
555 data
->nonce_s
, data
->sess
.nonce_len
);
557 if (eap_eke_derive_ka(&data
->sess
, data
->serverid
, data
->serverid_len
,
558 data
->peerid
, data
->peerid_len
,
559 data
->nonce_p
, data
->nonce_s
) < 0) {
560 return eap_eke_build_fail(data
, ret
, id
,
561 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
564 if (eap_eke_auth(&data
->sess
, "EAP-EKE server", data
->msgs
, auth_s
) < 0)
566 return eap_eke_build_fail(data
, ret
, id
,
567 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
569 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: Auth_S", auth_s
, data
->sess
.prf_len
);
570 if (os_memcmp_const(auth_s
, pos
+ data
->sess
.pnonce_ps_len
,
571 data
->sess
.prf_len
) != 0) {
572 wpa_printf(MSG_INFO
, "EAP-EKE: Auth_S does not match");
573 return eap_eke_build_fail(data
, ret
, id
,
574 EAP_EKE_FAIL_AUTHENTICATION_FAIL
);
577 wpa_printf(MSG_DEBUG
, "EAP-EKE: Sending EAP-EKE-Confirm/Response");
579 resp
= eap_eke_build_msg(data
, id
,
580 data
->sess
.pnonce_len
+ data
->sess
.prf_len
,
583 return eap_eke_build_fail(data
, ret
, id
,
584 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
587 prot_len
= wpabuf_tailroom(resp
);
588 if (eap_eke_prot(&data
->sess
, data
->nonce_s
, data
->sess
.nonce_len
,
589 wpabuf_put(resp
, 0), &prot_len
) < 0) {
591 return eap_eke_build_fail(data
, ret
, id
,
592 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
594 wpabuf_put(resp
, prot_len
);
596 auth
= wpabuf_put(resp
, data
->sess
.prf_len
);
597 if (eap_eke_auth(&data
->sess
, "EAP-EKE peer", data
->msgs
, auth
) < 0) {
599 return eap_eke_build_fail(data
, ret
, id
,
600 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
602 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: Auth_P", auth
, data
->sess
.prf_len
);
604 if (eap_eke_derive_msk(&data
->sess
, data
->serverid
, data
->serverid_len
,
605 data
->peerid
, data
->peerid_len
,
606 data
->nonce_s
, data
->nonce_p
,
607 data
->msk
, data
->emsk
) < 0) {
608 wpa_printf(MSG_INFO
, "EAP-EKE: Failed to derive MSK/EMSK");
610 return eap_eke_build_fail(data
, ret
, id
,
611 EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR
);
614 os_memset(data
->dh_priv
, 0, sizeof(data
->dh_priv
));
615 eap_eke_session_clean(&data
->sess
);
617 eap_eke_state(data
, SUCCESS
);
618 ret
->methodState
= METHOD_MAY_CONT
;
619 ret
->decision
= DECISION_COND_SUCC
;
620 ret
->allowNotifications
= FALSE
;
626 static struct wpabuf
* eap_eke_process_failure(struct eap_eke_data
*data
,
627 struct eap_method_ret
*ret
,
628 const struct wpabuf
*reqData
,
632 wpa_printf(MSG_DEBUG
, "EAP-EKE: Received EAP-EKE-Failure/Request");
634 if (payload_len
< 4) {
635 wpa_printf(MSG_DEBUG
, "EAP-EKE: Too short EAP-EKE-Failure");
638 code
= WPA_GET_BE32(payload
);
639 wpa_printf(MSG_INFO
, "EAP-EKE: Failure-Code 0x%x", code
);
642 return eap_eke_build_fail(data
, ret
, eap_get_id(reqData
),
643 EAP_EKE_FAIL_NO_ERROR
);
647 static struct wpabuf
* eap_eke_process(struct eap_sm
*sm
, void *priv
,
648 struct eap_method_ret
*ret
,
649 const struct wpabuf
*reqData
)
651 struct eap_eke_data
*data
= priv
;
657 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_EKE
, reqData
, &len
);
658 if (pos
== NULL
|| len
< 1) {
666 wpa_printf(MSG_DEBUG
, "EAP-EKE: Received frame: exch %d", eke_exch
);
667 wpa_hexdump(MSG_DEBUG
, "EAP-EKE: Received Data", pos
, end
- pos
);
670 ret
->methodState
= METHOD_MAY_CONT
;
671 ret
->decision
= DECISION_FAIL
;
672 ret
->allowNotifications
= TRUE
;
676 resp
= eap_eke_process_id(data
, ret
, reqData
, pos
, end
- pos
);
679 resp
= eap_eke_process_commit(sm
, data
, ret
, reqData
,
682 case EAP_EKE_CONFIRM
:
683 resp
= eap_eke_process_confirm(data
, ret
, reqData
,
686 case EAP_EKE_FAILURE
:
687 resp
= eap_eke_process_failure(data
, ret
, reqData
,
691 wpa_printf(MSG_DEBUG
, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch
);
696 if (ret
->methodState
== METHOD_DONE
)
697 ret
->allowNotifications
= FALSE
;
703 static Boolean
eap_eke_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
705 struct eap_eke_data
*data
= priv
;
706 return data
->state
== SUCCESS
;
710 static u8
* eap_eke_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
712 struct eap_eke_data
*data
= priv
;
715 if (data
->state
!= SUCCESS
)
718 key
= os_memdup(data
->msk
, EAP_MSK_LEN
);
727 static u8
* eap_eke_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
729 struct eap_eke_data
*data
= priv
;
732 if (data
->state
!= SUCCESS
)
735 key
= os_memdup(data
->emsk
, EAP_EMSK_LEN
);
744 static u8
* eap_eke_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
746 struct eap_eke_data
*data
= priv
;
750 if (data
->state
!= SUCCESS
)
753 sid_len
= 1 + 2 * data
->sess
.nonce_len
;
754 sid
= os_malloc(sid_len
);
757 sid
[0] = EAP_TYPE_EKE
;
758 os_memcpy(sid
+ 1, data
->nonce_p
, data
->sess
.nonce_len
);
759 os_memcpy(sid
+ 1 + data
->sess
.nonce_len
, data
->nonce_s
,
760 data
->sess
.nonce_len
);
767 int eap_peer_eke_register(void)
769 struct eap_method
*eap
;
771 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
772 EAP_VENDOR_IETF
, EAP_TYPE_EKE
, "EKE");
776 eap
->init
= eap_eke_init
;
777 eap
->deinit
= eap_eke_deinit
;
778 eap
->process
= eap_eke_process
;
779 eap
->isKeyAvailable
= eap_eke_isKeyAvailable
;
780 eap
->getKey
= eap_eke_getKey
;
781 eap
->get_emsk
= eap_eke_get_emsk
;
782 eap
->getSessionId
= eap_eke_get_session_id
;
784 return eap_peer_method_register(eap
);