2 * EAP peer method: EAP-TEAP (RFC 7170)
3 * Copyright (c) 2004-2019, 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/tls.h"
13 #include "eap_common/eap_teap_common.h"
15 #include "eap_tls_common.h"
16 #include "eap_config.h"
17 #include "eap_teap_pac.h"
19 #ifdef EAP_TEAP_DYNAMIC
20 #include "eap_teap_pac.c"
21 #endif /* EAP_TEAP_DYNAMIC */
24 static void eap_teap_deinit(struct eap_sm
*sm
, void *priv
);
27 struct eap_teap_data
{
28 struct eap_ssl_data ssl
;
30 u8 teap_version
; /* Negotiated version */
31 u8 received_version
; /* Version number received during negotiation */
34 const struct eap_method
*phase2_method
;
37 int inner_method_done
;
39 int result_success_done
;
42 struct eap_method_type phase2_type
;
43 struct eap_method_type
*phase2_types
;
44 size_t num_phase2_types
;
45 int resuming
; /* starting a resumed session */
46 #define EAP_TEAP_PROV_UNAUTH 1
47 #define EAP_TEAP_PROV_AUTH 2
48 int provisioning_allowed
; /* Allowed PAC provisioning modes */
49 int provisioning
; /* doing PAC provisioning (not the normal auth) */
50 int anon_provisioning
; /* doing anonymous (unauthenticated)
52 int session_ticket_used
;
55 u8 key_data
[EAP_TEAP_KEY_LEN
];
58 u8 emsk
[EAP_EMSK_LEN
];
61 struct eap_teap_pac
*pac
;
62 struct eap_teap_pac
*current_pac
;
63 size_t max_pac_list_len
;
64 int use_pac_binary_format
;
66 u8 simck_msk
[EAP_TEAP_SIMCK_LEN
];
67 u8 simck_emsk
[EAP_TEAP_SIMCK_LEN
];
69 int cmk_emsk_available
;
71 struct wpabuf
*pending_phase2_req
;
72 struct wpabuf
*pending_resp
;
73 struct wpabuf
*server_outer_tlvs
;
74 struct wpabuf
*peer_outer_tlvs
;
78 static int eap_teap_session_ticket_cb(void *ctx
, const u8
*ticket
, size_t len
,
79 const u8
*client_random
,
80 const u8
*server_random
,
83 struct eap_teap_data
*data
= ctx
;
85 wpa_printf(MSG_DEBUG
, "EAP-TEAP: SessionTicket callback");
89 "EAP-TEAP: SessionTicket failed - fall back to full TLS handshake");
90 data
->session_ticket_used
= 0;
91 if (data
->provisioning_allowed
) {
93 "EAP-TEAP: Try to provision a new PAC-Key");
94 data
->provisioning
= 1;
95 data
->current_pac
= NULL
;
100 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: SessionTicket", ticket
, len
);
102 if (!data
->current_pac
) {
103 wpa_printf(MSG_DEBUG
,
104 "EAP-TEAP: No PAC-Key available for using SessionTicket");
105 data
->session_ticket_used
= 0;
109 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
110 os_memcpy(master_secret
, data
->current_pac
->pac_key
,
111 EAP_TEAP_PAC_KEY_LEN
);
113 data
->session_ticket_used
= 1;
119 static void eap_teap_parse_phase1(struct eap_teap_data
*data
,
124 pos
= os_strstr(phase1
, "teap_provisioning=");
126 data
->provisioning_allowed
= atoi(pos
+ 18);
127 wpa_printf(MSG_DEBUG
,
128 "EAP-TEAP: Automatic PAC provisioning mode: %d",
129 data
->provisioning_allowed
);
132 pos
= os_strstr(phase1
, "teap_max_pac_list_len=");
134 data
->max_pac_list_len
= atoi(pos
+ 22);
135 if (data
->max_pac_list_len
== 0)
136 data
->max_pac_list_len
= 1;
137 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Maximum PAC list length: %lu",
138 (unsigned long) data
->max_pac_list_len
);
141 if (os_strstr(phase1
, "teap_pac_format=binary")) {
142 data
->use_pac_binary_format
= 1;
143 wpa_printf(MSG_DEBUG
,
144 "EAP-TEAP: Using binary format for PAC list");
147 #ifdef CONFIG_TESTING_OPTIONS
148 if (os_strstr(phase1
, "teap_test_outer_tlvs=1"))
149 data
->test_outer_tlvs
= 1;
150 #endif /* CONFIG_TESTING_OPTIONS */
154 static void * eap_teap_init(struct eap_sm
*sm
)
156 struct eap_teap_data
*data
;
157 struct eap_peer_config
*config
= eap_get_config(sm
);
162 data
= os_zalloc(sizeof(*data
));
165 data
->teap_version
= EAP_TEAP_VERSION
;
166 data
->max_pac_list_len
= 10;
169 eap_teap_parse_phase1(data
, config
->phase1
);
171 if ((data
->provisioning_allowed
& EAP_TEAP_PROV_AUTH
) &&
172 !config
->ca_cert
&& !config
->ca_path
) {
173 /* Prevent PAC provisioning without mutual authentication
174 * (either by validating server certificate or by suitable
175 * inner EAP method). */
177 "EAP-TEAP: Disable authenticated provisioning due to no ca_cert/ca_path");
178 data
->provisioning_allowed
&= ~EAP_TEAP_PROV_AUTH
;
181 if (eap_peer_select_phase2_methods(config
, "auth=",
183 &data
->num_phase2_types
) < 0) {
184 eap_teap_deinit(sm
, data
);
188 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
189 data
->phase2_type
.method
= EAP_TYPE_NONE
;
191 config
->teap_anon_dh
= !!(data
->provisioning_allowed
&
192 EAP_TEAP_PROV_UNAUTH
);
193 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
, EAP_TYPE_TEAP
)) {
194 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to initialize SSL");
195 eap_teap_deinit(sm
, data
);
199 if (tls_connection_set_session_ticket_cb(sm
->ssl_ctx
, data
->ssl
.conn
,
200 eap_teap_session_ticket_cb
,
203 "EAP-TEAP: Failed to set SessionTicket callback");
204 eap_teap_deinit(sm
, data
);
208 if (!config
->pac_file
) {
209 wpa_printf(MSG_INFO
, "EAP-TEAP: No PAC file configured");
210 eap_teap_deinit(sm
, data
);
214 if (data
->use_pac_binary_format
&&
215 eap_teap_load_pac_bin(sm
, &data
->pac
, config
->pac_file
) < 0) {
216 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to load PAC file");
217 eap_teap_deinit(sm
, data
);
221 if (!data
->use_pac_binary_format
&&
222 eap_teap_load_pac(sm
, &data
->pac
, config
->pac_file
) < 0) {
223 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to load PAC file");
224 eap_teap_deinit(sm
, data
);
227 eap_teap_pac_list_truncate(data
->pac
, data
->max_pac_list_len
);
233 static void eap_teap_clear(struct eap_teap_data
*data
)
235 forced_memzero(data
->key_data
, EAP_TEAP_KEY_LEN
);
236 forced_memzero(data
->emsk
, EAP_EMSK_LEN
);
237 os_free(data
->session_id
);
238 data
->session_id
= NULL
;
239 wpabuf_free(data
->pending_phase2_req
);
240 data
->pending_phase2_req
= NULL
;
241 wpabuf_free(data
->pending_resp
);
242 data
->pending_resp
= NULL
;
243 wpabuf_free(data
->server_outer_tlvs
);
244 data
->server_outer_tlvs
= NULL
;
245 wpabuf_free(data
->peer_outer_tlvs
);
246 data
->peer_outer_tlvs
= NULL
;
247 forced_memzero(data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
248 forced_memzero(data
->simck_emsk
, EAP_TEAP_SIMCK_LEN
);
252 static void eap_teap_deinit(struct eap_sm
*sm
, void *priv
)
254 struct eap_teap_data
*data
= priv
;
255 struct eap_teap_pac
*pac
, *prev
;
259 if (data
->phase2_priv
&& data
->phase2_method
)
260 data
->phase2_method
->deinit(sm
, data
->phase2_priv
);
261 eap_teap_clear(data
);
262 os_free(data
->phase2_types
);
263 eap_peer_tls_ssl_deinit(sm
, &data
->ssl
);
270 eap_teap_free_pac(prev
);
277 static int eap_teap_derive_msk(struct eap_teap_data
*data
)
279 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
280 * is used in this derivation */
281 if (eap_teap_derive_eap_msk(data
->tls_cs
, data
->simck_msk
,
282 data
->key_data
) < 0 ||
283 eap_teap_derive_eap_emsk(data
->tls_cs
, data
->simck_msk
,
291 static int eap_teap_derive_key_auth(struct eap_sm
*sm
,
292 struct eap_teap_data
*data
)
296 /* RFC 7170, Section 5.1 */
297 res
= tls_connection_export_key(sm
->ssl_ctx
, data
->ssl
.conn
,
298 TEAP_TLS_EXPORTER_LABEL_SKS
, NULL
, 0,
299 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
302 wpa_hexdump_key(MSG_DEBUG
,
303 "EAP-TEAP: session_key_seed (S-IMCK[0])",
304 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
305 os_memcpy(data
->simck_emsk
, data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
311 static int eap_teap_init_phase2_method(struct eap_sm
*sm
,
312 struct eap_teap_data
*data
)
314 data
->inner_method_done
= 0;
315 data
->iresult_verified
= 0;
316 data
->phase2_method
=
317 eap_peer_get_eap_method(data
->phase2_type
.vendor
,
318 data
->phase2_type
.method
);
319 if (!data
->phase2_method
)
323 data
->phase2_priv
= data
->phase2_method
->init(sm
);
326 return data
->phase2_priv
== NULL
? -1 : 0;
330 static int eap_teap_select_phase2_method(struct eap_teap_data
*data
,
331 int vendor
, enum eap_type type
)
335 /* TODO: TNC with anonymous provisioning; need to require both
336 * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
338 if (data
->anon_provisioning
&&
339 !eap_teap_allowed_anon_prov_phase2_method(vendor
, type
)) {
341 "EAP-TEAP: EAP type %u:%u not allowed during unauthenticated provisioning",
347 if (vendor
== EAP_VENDOR_IETF
&& type
== EAP_TYPE_TNC
) {
348 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
349 data
->phase2_type
.method
= EAP_TYPE_TNC
;
350 wpa_printf(MSG_DEBUG
,
351 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
352 data
->phase2_type
.vendor
,
353 data
->phase2_type
.method
);
358 for (i
= 0; i
< data
->num_phase2_types
; i
++) {
359 if (data
->phase2_types
[i
].vendor
!= vendor
||
360 data
->phase2_types
[i
].method
!= type
)
363 data
->phase2_type
.vendor
= data
->phase2_types
[i
].vendor
;
364 data
->phase2_type
.method
= data
->phase2_types
[i
].method
;
365 wpa_printf(MSG_DEBUG
,
366 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
367 data
->phase2_type
.vendor
,
368 data
->phase2_type
.method
);
372 if (vendor
!= data
->phase2_type
.vendor
||
373 type
!= data
->phase2_type
.method
||
374 (vendor
== EAP_VENDOR_IETF
&& type
== EAP_TYPE_NONE
))
381 static int eap_teap_phase2_request(struct eap_sm
*sm
,
382 struct eap_teap_data
*data
,
383 struct eap_method_ret
*ret
,
385 struct wpabuf
**resp
)
387 size_t len
= be_to_host16(hdr
->length
);
389 struct eap_method_ret iret
;
390 struct eap_peer_config
*config
= eap_get_config(sm
);
392 int vendor
= EAP_VENDOR_IETF
;
393 enum eap_type method
;
395 if (len
<= sizeof(struct eap_hdr
)) {
397 "EAP-TEAP: too short Phase 2 request (len=%lu)",
398 (unsigned long) len
);
401 pos
= (u8
*) (hdr
+ 1);
403 if (method
== EAP_TYPE_EXPANDED
) {
404 if (len
< sizeof(struct eap_hdr
) + 8) {
406 "EAP-TEAP: Too short Phase 2 request (expanded header) (len=%lu)",
407 (unsigned long) len
);
410 vendor
= WPA_GET_BE24(pos
+ 1);
411 method
= WPA_GET_BE32(pos
+ 4);
413 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 2 Request: type=%u:%u",
415 if (vendor
== EAP_VENDOR_IETF
&& method
== EAP_TYPE_IDENTITY
) {
416 *resp
= eap_sm_buildIdentity(sm
, hdr
->identifier
, 1);
420 if (data
->phase2_priv
&& data
->phase2_method
&&
421 (vendor
!= data
->phase2_type
.vendor
||
422 method
!= data
->phase2_type
.method
)) {
423 wpa_printf(MSG_DEBUG
,
424 "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
425 data
->phase2_method
->deinit(sm
, data
->phase2_priv
);
426 data
->phase2_method
= NULL
;
427 data
->phase2_priv
= NULL
;
428 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
429 data
->phase2_type
.method
= EAP_TYPE_NONE
;
432 if (data
->phase2_type
.vendor
== EAP_VENDOR_IETF
&&
433 data
->phase2_type
.method
== EAP_TYPE_NONE
&&
434 eap_teap_select_phase2_method(data
, vendor
, method
) < 0) {
435 if (eap_peer_tls_phase2_nak(data
->phase2_types
,
436 data
->num_phase2_types
,
442 if ((!data
->phase2_priv
&& eap_teap_init_phase2_method(sm
, data
) < 0) ||
443 !data
->phase2_method
) {
445 "EAP-TEAP: Failed to initialize Phase 2 EAP method %u:%u",
447 ret
->methodState
= METHOD_DONE
;
448 ret
->decision
= DECISION_FAIL
;
452 os_memset(&iret
, 0, sizeof(iret
));
453 wpabuf_set(&msg
, hdr
, len
);
454 *resp
= data
->phase2_method
->process(sm
, data
->phase2_priv
, &iret
,
456 if (iret
.methodState
== METHOD_DONE
)
457 data
->inner_method_done
= 1;
459 (iret
.methodState
== METHOD_DONE
&&
460 iret
.decision
== DECISION_FAIL
)) {
461 ret
->methodState
= METHOD_DONE
;
462 ret
->decision
= DECISION_FAIL
;
463 } else if ((iret
.methodState
== METHOD_DONE
||
464 iret
.methodState
== METHOD_MAY_CONT
) &&
465 (iret
.decision
== DECISION_UNCOND_SUCC
||
466 iret
.decision
== DECISION_COND_SUCC
)) {
467 data
->phase2_success
= 1;
470 if (!(*resp
) && config
&&
471 (config
->pending_req_identity
|| config
->pending_req_password
||
472 config
->pending_req_otp
|| config
->pending_req_new_password
||
473 config
->pending_req_sim
)) {
474 wpabuf_free(data
->pending_phase2_req
);
475 data
->pending_phase2_req
= wpabuf_alloc_copy(hdr
, len
);
483 static struct wpabuf
* eap_teap_tlv_nak(int vendor_id
, int tlv_type
)
486 struct teap_tlv_nak
*nak
;
488 wpa_printf(MSG_DEBUG
,
489 "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
490 vendor_id
, tlv_type
);
491 buf
= wpabuf_alloc(sizeof(*nak
));
494 nak
= wpabuf_put(buf
, sizeof(*nak
));
495 nak
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
| TEAP_TLV_NAK
);
496 nak
->length
= host_to_be16(6);
497 nak
->vendor_id
= host_to_be32(vendor_id
);
498 nak
->nak_type
= host_to_be16(tlv_type
);
503 static struct wpabuf
* eap_teap_tlv_pac_ack(void)
506 struct teap_tlv_result
*res
;
507 struct teap_tlv_pac_ack
*ack
;
509 buf
= wpabuf_alloc(sizeof(*res
) + sizeof(*ack
));
513 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (ack)");
514 ack
= wpabuf_put(buf
, sizeof(*ack
));
515 ack
->tlv_type
= host_to_be16(TEAP_TLV_PAC
| TEAP_TLV_MANDATORY
);
516 ack
->length
= host_to_be16(sizeof(*ack
) - sizeof(struct teap_tlv_hdr
));
517 ack
->pac_type
= host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT
);
518 ack
->pac_len
= host_to_be16(2);
519 ack
->result
= host_to_be16(TEAP_STATUS_SUCCESS
);
525 static struct wpabuf
* eap_teap_add_identity_type(struct eap_sm
*sm
,
530 tlv
= eap_teap_tlv_identity_type(sm
->use_machine_cred
?
531 TEAP_IDENTITY_TYPE_MACHINE
:
532 TEAP_IDENTITY_TYPE_USER
);
533 return wpabuf_concat(msg
, tlv
);
537 static struct wpabuf
* eap_teap_process_eap_payload_tlv(
538 struct eap_sm
*sm
, struct eap_teap_data
*data
,
539 struct eap_method_ret
*ret
,
540 u8
*eap_payload_tlv
, size_t eap_payload_tlv_len
,
541 enum teap_identity_types req_id_type
)
544 struct wpabuf
*resp
= NULL
;
546 if (eap_payload_tlv_len
< sizeof(*hdr
)) {
547 wpa_printf(MSG_DEBUG
,
548 "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
549 (unsigned long) eap_payload_tlv_len
);
553 hdr
= (struct eap_hdr
*) eap_payload_tlv
;
554 if (be_to_host16(hdr
->length
) > eap_payload_tlv_len
) {
555 wpa_printf(MSG_DEBUG
,
556 "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
560 if (hdr
->code
!= EAP_CODE_REQUEST
) {
562 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
567 if (eap_teap_phase2_request(sm
, data
, ret
, hdr
, &resp
)) {
569 "EAP-TEAP: Phase 2 Request processing failed");
573 resp
= eap_teap_tlv_eap_payload(resp
);
575 resp
= eap_teap_add_identity_type(sm
, resp
);
581 static struct wpabuf
* eap_teap_process_basic_auth_req(
582 struct eap_sm
*sm
, struct eap_teap_data
*data
,
583 u8
*basic_auth_req
, size_t basic_auth_req_len
,
584 enum teap_identity_types req_id_type
)
586 const u8
*identity
, *password
;
587 size_t identity_len
, password_len
, plen
;
590 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Req prompt",
591 basic_auth_req
, basic_auth_req_len
);
592 /* TODO: send over control interface */
594 identity
= eap_get_config_identity(sm
, &identity_len
);
595 password
= eap_get_config_password(sm
, &password_len
);
596 if (!identity
|| !password
||
597 identity_len
> 255 || password_len
> 255) {
598 wpa_printf(MSG_DEBUG
,
599 "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
600 return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ
);
603 plen
= 1 + identity_len
+ 1 + password_len
;
604 resp
= wpabuf_alloc(sizeof(struct teap_tlv_hdr
) + plen
);
607 eap_teap_put_tlv_hdr(resp
, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP
, plen
);
608 wpabuf_put_u8(resp
, identity_len
);
609 wpabuf_put_data(resp
, identity
, identity_len
);
610 wpabuf_put_u8(resp
, password_len
);
611 wpabuf_put_data(resp
, password
, password_len
);
612 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Resp",
615 resp
= eap_teap_add_identity_type(sm
, resp
);
617 /* Assume this succeeds so that Result TLV(Success) from the server can
618 * be used to terminate TEAP. */
619 data
->phase2_success
= 1;
626 eap_teap_validate_crypto_binding(struct eap_teap_data
*data
,
627 const struct teap_tlv_crypto_binding
*cb
)
631 subtype
= cb
->subtype
& 0x0f;
632 flags
= cb
->subtype
>> 4;
634 wpa_printf(MSG_DEBUG
,
635 "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
636 cb
->version
, cb
->received_version
, flags
, subtype
);
637 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
638 cb
->nonce
, sizeof(cb
->nonce
));
639 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
640 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
641 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
642 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
644 if (cb
->version
!= EAP_TEAP_VERSION
||
645 cb
->received_version
!= data
->received_version
||
646 subtype
!= TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST
||
647 flags
< 1 || flags
> 3) {
649 "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
650 cb
->version
, cb
->received_version
, flags
, subtype
);
654 if (cb
->nonce
[EAP_TEAP_NONCE_LEN
- 1] & 0x01) {
656 "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
664 static int eap_teap_write_crypto_binding(
665 struct eap_teap_data
*data
,
666 struct teap_tlv_crypto_binding
*rbind
,
667 const struct teap_tlv_crypto_binding
*cb
,
668 const u8
*cmk_msk
, const u8
*cmk_emsk
)
672 rbind
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
673 TEAP_TLV_CRYPTO_BINDING
);
674 rbind
->length
= host_to_be16(sizeof(*rbind
) -
675 sizeof(struct teap_tlv_hdr
));
676 rbind
->version
= EAP_TEAP_VERSION
;
677 rbind
->received_version
= data
->received_version
;
678 /* FIX: RFC 7170 is not clear on which Flags value to use when
679 * Crypto-Binding TLV is used with Basic-Password-Auth */
680 flags
= cmk_emsk
? TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
:
681 TEAP_CRYPTO_BINDING_MSK_CMAC
;
682 subtype
= TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE
;
683 rbind
->subtype
= (flags
<< 4) | subtype
;
684 os_memcpy(rbind
->nonce
, cb
->nonce
, sizeof(cb
->nonce
));
685 inc_byte_array(rbind
->nonce
, sizeof(rbind
->nonce
));
686 os_memset(rbind
->emsk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
687 os_memset(rbind
->msk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
689 if (eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
690 data
->peer_outer_tlvs
, cmk_msk
,
691 rbind
->msk_compound_mac
) < 0)
694 eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
695 data
->peer_outer_tlvs
, cmk_emsk
,
696 rbind
->emsk_compound_mac
) < 0)
699 wpa_printf(MSG_DEBUG
,
700 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
701 rbind
->version
, rbind
->received_version
, flags
, subtype
);
702 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
703 rbind
->nonce
, sizeof(rbind
->nonce
));
704 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
705 rbind
->emsk_compound_mac
, sizeof(rbind
->emsk_compound_mac
));
706 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
707 rbind
->msk_compound_mac
, sizeof(rbind
->msk_compound_mac
));
713 static int eap_teap_get_cmk(struct eap_sm
*sm
, struct eap_teap_data
*data
,
714 u8
*cmk_msk
, u8
*cmk_emsk
)
716 u8
*msk
= NULL
, *emsk
= NULL
;
717 size_t msk_len
= 0, emsk_len
= 0;
720 wpa_printf(MSG_DEBUG
,
721 "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
722 data
->simck_idx
+ 1);
724 if (!data
->phase2_method
)
725 return eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
729 if (!data
->phase2_method
|| !data
->phase2_priv
) {
730 wpa_printf(MSG_INFO
, "EAP-TEAP: Phase 2 method not available");
734 if (data
->phase2_method
->isKeyAvailable
&&
735 !data
->phase2_method
->isKeyAvailable(sm
, data
->phase2_priv
)) {
737 "EAP-TEAP: Phase 2 key material not available");
741 if (data
->phase2_method
->isKeyAvailable
&&
742 data
->phase2_method
->getKey
) {
743 msk
= data
->phase2_method
->getKey(sm
, data
->phase2_priv
,
747 "EAP-TEAP: Could not fetch Phase 2 MSK");
752 if (data
->phase2_method
->isKeyAvailable
&&
753 data
->phase2_method
->get_emsk
) {
754 emsk
= data
->phase2_method
->get_emsk(sm
, data
->phase2_priv
,
758 res
= eap_teap_derive_imck(data
->tls_cs
,
759 data
->simck_msk
, data
->simck_emsk
,
760 msk
, msk_len
, emsk
, emsk_len
,
761 data
->simck_msk
, cmk_msk
,
762 data
->simck_emsk
, cmk_emsk
);
763 bin_clear_free(msk
, msk_len
);
764 bin_clear_free(emsk
, emsk_len
);
768 data
->cmk_emsk_available
= 1;
774 static int eap_teap_session_id(struct eap_teap_data
*data
)
776 const size_t max_id_len
= 100;
779 os_free(data
->session_id
);
780 data
->session_id
= os_malloc(max_id_len
);
781 if (!data
->session_id
)
784 data
->session_id
[0] = EAP_TYPE_TEAP
;
785 res
= tls_get_tls_unique(data
->ssl
.conn
, data
->session_id
+ 1,
788 os_free(data
->session_id
);
789 data
->session_id
= NULL
;
790 wpa_printf(MSG_ERROR
, "EAP-TEAP: Failed to derive Session-Id");
794 data
->id_len
= 1 + res
;
795 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Derived Session-Id",
796 data
->session_id
, data
->id_len
);
801 static struct wpabuf
* eap_teap_process_crypto_binding(
802 struct eap_sm
*sm
, struct eap_teap_data
*data
,
803 struct eap_method_ret
*ret
,
804 const struct teap_tlv_crypto_binding
*cb
, size_t bind_len
)
808 u8 cmk_msk
[EAP_TEAP_CMK_LEN
];
809 u8 cmk_emsk
[EAP_TEAP_CMK_LEN
];
810 const u8
*cmk_emsk_ptr
= NULL
;
815 if (eap_teap_validate_crypto_binding(data
, cb
) < 0 ||
816 eap_teap_get_cmk(sm
, data
, cmk_msk
, cmk_emsk
) < 0)
819 /* Validate received MSK/EMSK Compound MAC */
820 flags
= cb
->subtype
>> 4;
822 if (flags
== TEAP_CRYPTO_BINDING_MSK_CMAC
||
823 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) {
824 u8 msk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
826 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
827 data
->server_outer_tlvs
,
828 data
->peer_outer_tlvs
, cmk_msk
,
829 msk_compound_mac
) < 0)
831 res
= os_memcmp_const(msk_compound_mac
, cb
->msk_compound_mac
,
832 EAP_TEAP_COMPOUND_MAC_LEN
);
833 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received MSK Compound MAC",
834 cb
->msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
835 wpa_hexdump(MSG_MSGDUMP
,
836 "EAP-TEAP: Calculated MSK Compound MAC",
837 msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
840 "EAP-TEAP: MSK Compound MAC did not match");
845 if ((flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
||
846 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) &&
847 data
->cmk_emsk_available
) {
848 u8 emsk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
850 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
851 data
->server_outer_tlvs
,
852 data
->peer_outer_tlvs
, cmk_emsk
,
853 emsk_compound_mac
) < 0)
855 res
= os_memcmp_const(emsk_compound_mac
, cb
->emsk_compound_mac
,
856 EAP_TEAP_COMPOUND_MAC_LEN
);
857 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received EMSK Compound MAC",
858 cb
->emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
859 wpa_hexdump(MSG_MSGDUMP
,
860 "EAP-TEAP: Calculated EMSK Compound MAC",
861 emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
864 "EAP-TEAP: EMSK Compound MAC did not match");
868 cmk_emsk_ptr
= cmk_emsk
;
871 if (flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
&&
872 !data
->cmk_emsk_available
) {
874 "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
879 * Compound MAC was valid, so authentication succeeded. Reply with
880 * crypto binding to allow server to complete authentication.
883 len
= sizeof(struct teap_tlv_crypto_binding
);
884 resp
= wpabuf_alloc(len
);
888 if (data
->phase2_success
&& eap_teap_derive_msk(data
) < 0) {
889 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to generate MSK");
890 ret
->methodState
= METHOD_DONE
;
891 ret
->decision
= DECISION_FAIL
;
892 data
->phase2_success
= 0;
897 if (data
->phase2_success
&& eap_teap_session_id(data
) < 0) {
902 pos
= wpabuf_put(resp
, sizeof(struct teap_tlv_crypto_binding
));
903 if (eap_teap_write_crypto_binding(
904 data
, (struct teap_tlv_crypto_binding
*) pos
,
905 cb
, cmk_msk
, cmk_emsk_ptr
) < 0) {
914 static void eap_teap_parse_pac_tlv(struct eap_teap_pac
*entry
, int type
,
915 u8
*pos
, size_t len
, int *pac_key_found
)
917 switch (type
& 0x7fff) {
918 case PAC_TYPE_PAC_KEY
:
919 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: PAC-Key", pos
, len
);
920 if (len
!= EAP_TEAP_PAC_KEY_LEN
) {
921 wpa_printf(MSG_DEBUG
,
922 "EAP-TEAP: Invalid PAC-Key length %lu",
923 (unsigned long) len
);
927 os_memcpy(entry
->pac_key
, pos
, len
);
929 case PAC_TYPE_PAC_OPAQUE
:
930 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque", pos
, len
);
931 entry
->pac_opaque
= pos
;
932 entry
->pac_opaque_len
= len
;
934 case PAC_TYPE_PAC_INFO
:
935 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Info", pos
, len
);
936 entry
->pac_info
= pos
;
937 entry
->pac_info_len
= len
;
940 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Ignored unknown PAC type %d",
947 static int eap_teap_process_pac_tlv(struct eap_teap_pac
*entry
,
948 u8
*pac
, size_t pac_len
)
950 struct pac_attr_hdr
*hdr
;
953 int type
, pac_key_found
= 0;
958 while (left
> sizeof(*hdr
)) {
959 hdr
= (struct pac_attr_hdr
*) pos
;
960 type
= be_to_host16(hdr
->type
);
961 len
= be_to_host16(hdr
->len
);
963 left
-= sizeof(*hdr
);
965 wpa_printf(MSG_DEBUG
,
966 "EAP-TEAP: PAC TLV overrun (type=%d len=%lu left=%lu)",
967 type
, (unsigned long) len
,
968 (unsigned long) left
);
972 eap_teap_parse_pac_tlv(entry
, type
, pos
, len
, &pac_key_found
);
978 if (!pac_key_found
|| !entry
->pac_opaque
|| !entry
->pac_info
) {
979 wpa_printf(MSG_DEBUG
,
980 "EAP-TEAP: PAC TLV does not include all the required fields");
988 static int eap_teap_parse_pac_info(struct eap_teap_pac
*entry
, int type
,
995 switch (type
& 0x7fff) {
996 case PAC_TYPE_CRED_LIFETIME
:
998 wpa_hexdump(MSG_DEBUG
,
999 "EAP-TEAP: PAC-Info - Invalid CRED_LIFETIME length - ignored",
1005 * This is not currently saved separately in PAC files since
1006 * the server can automatically initiate PAC update when
1007 * needed. Anyway, the information is available from PAC-Info
1008 * dump if it is needed for something in the future.
1010 lifetime
= WPA_GET_BE32(pos
);
1012 wpa_printf(MSG_DEBUG
,
1013 "EAP-TEAP: PAC-Info - CRED_LIFETIME %d (%d days)",
1014 lifetime
, (lifetime
- (u32
) now
.sec
) / 86400);
1017 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID",
1020 entry
->a_id_len
= len
;
1023 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - I-ID",
1026 entry
->i_id_len
= len
;
1028 case PAC_TYPE_A_ID_INFO
:
1029 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID-Info",
1031 entry
->a_id_info
= pos
;
1032 entry
->a_id_info_len
= len
;
1034 case PAC_TYPE_PAC_TYPE
:
1035 /* RFC 7170, Section 4.2.12.6 - PAC-Type TLV */
1037 wpa_printf(MSG_INFO
,
1038 "EAP-TEAP: Invalid PAC-Type length %lu (expected 2)",
1039 (unsigned long) len
);
1040 wpa_hexdump_ascii(MSG_DEBUG
,
1041 "EAP-TEAP: PAC-Info - PAC-Type",
1045 pac_type
= WPA_GET_BE16(pos
);
1046 if (pac_type
!= PAC_TYPE_TUNNEL_PAC
) {
1047 wpa_printf(MSG_INFO
,
1048 "EAP-TEAP: Unsupported PAC Type %d",
1053 wpa_printf(MSG_DEBUG
, "EAP-TEAP: PAC-Info - PAC-Type %d",
1055 entry
->pac_type
= pac_type
;
1058 wpa_printf(MSG_DEBUG
,
1059 "EAP-TEAP: Ignored unknown PAC-Info type %d", type
);
1067 static int eap_teap_process_pac_info(struct eap_teap_pac
*entry
)
1069 struct pac_attr_hdr
*hdr
;
1074 /* RFC 7170, Section 4.2.12.4 */
1076 /* PAC-Type defaults to Tunnel PAC (Type 1) */
1077 entry
->pac_type
= PAC_TYPE_TUNNEL_PAC
;
1079 pos
= entry
->pac_info
;
1080 left
= entry
->pac_info_len
;
1081 while (left
> sizeof(*hdr
)) {
1082 hdr
= (struct pac_attr_hdr
*) pos
;
1083 type
= be_to_host16(hdr
->type
);
1084 len
= be_to_host16(hdr
->len
);
1085 pos
+= sizeof(*hdr
);
1086 left
-= sizeof(*hdr
);
1088 wpa_printf(MSG_DEBUG
,
1089 "EAP-TEAP: PAC-Info overrun (type=%d len=%lu left=%lu)",
1090 type
, (unsigned long) len
,
1091 (unsigned long) left
);
1095 if (eap_teap_parse_pac_info(entry
, type
, pos
, len
) < 0)
1102 if (!entry
->a_id
|| !entry
->a_id_info
) {
1103 wpa_printf(MSG_DEBUG
,
1104 "EAP-TEAP: PAC-Info does not include all the required fields");
1112 static struct wpabuf
* eap_teap_process_pac(struct eap_sm
*sm
,
1113 struct eap_teap_data
*data
,
1114 struct eap_method_ret
*ret
,
1115 u8
*pac
, size_t pac_len
)
1117 struct eap_peer_config
*config
= eap_get_config(sm
);
1118 struct eap_teap_pac entry
;
1120 os_memset(&entry
, 0, sizeof(entry
));
1121 if (eap_teap_process_pac_tlv(&entry
, pac
, pac_len
) ||
1122 eap_teap_process_pac_info(&entry
))
1125 eap_teap_add_pac(&data
->pac
, &data
->current_pac
, &entry
);
1126 eap_teap_pac_list_truncate(data
->pac
, data
->max_pac_list_len
);
1127 if (data
->use_pac_binary_format
)
1128 eap_teap_save_pac_bin(sm
, data
->pac
, config
->pac_file
);
1130 eap_teap_save_pac(sm
, data
->pac
, config
->pac_file
);
1132 wpa_printf(MSG_DEBUG
,
1133 "EAP-TEAP: Send PAC-Acknowledgement - %s initiated provisioning completed successfully",
1134 data
->provisioning
? "peer" : "server");
1135 return eap_teap_tlv_pac_ack();
1139 static int eap_teap_parse_decrypted(struct wpabuf
*decrypted
,
1140 struct eap_teap_tlv_parse
*tlv
,
1141 struct wpabuf
**resp
)
1148 os_memset(tlv
, 0, sizeof(*tlv
));
1150 /* Parse TLVs from the decrypted Phase 2 data */
1151 pos
= wpabuf_mhead(decrypted
);
1152 end
= pos
+ wpabuf_len(decrypted
);
1153 while (end
- pos
>= 4) {
1154 mandatory
= pos
[0] & 0x80;
1155 tlv_type
= WPA_GET_BE16(pos
) & 0x3fff;
1157 len
= WPA_GET_BE16(pos
);
1159 if (len
> (size_t) (end
- pos
)) {
1160 wpa_printf(MSG_INFO
, "EAP-TEAP: TLV overflow");
1163 wpa_printf(MSG_DEBUG
,
1164 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1165 tlv_type
, eap_teap_tlv_type_str(tlv_type
),
1167 mandatory
? " (mandatory)" : "");
1169 res
= eap_teap_parse_tlv(tlv
, tlv_type
, pos
, len
);
1174 wpa_printf(MSG_DEBUG
,
1175 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1177 *resp
= eap_teap_tlv_nak(0, tlv_type
);
1181 wpa_printf(MSG_DEBUG
,
1182 "EAP-TEAP: Ignore unknown optional TLV type %u",
1193 static struct wpabuf
* eap_teap_pac_request(void)
1196 struct teap_tlv_request_action
*act
;
1197 struct teap_tlv_hdr
*pac
;
1198 struct teap_attr_pac_type
*type
;
1200 req
= wpabuf_alloc(sizeof(*act
) + sizeof(*pac
) + sizeof(*type
));
1204 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add Request Action TLV (Process TLV)");
1205 act
= wpabuf_put(req
, sizeof(*act
));
1206 act
->tlv_type
= host_to_be16(TEAP_TLV_REQUEST_ACTION
);
1207 act
->length
= host_to_be16(2);
1208 act
->status
= TEAP_STATUS_SUCCESS
;
1209 act
->action
= TEAP_REQUEST_ACTION_PROCESS_TLV
;
1211 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (PAC-Type = Tunnel)");
1212 pac
= wpabuf_put(req
, sizeof(*pac
));
1213 pac
->tlv_type
= host_to_be16(TEAP_TLV_PAC
);
1214 pac
->length
= host_to_be16(sizeof(*type
));
1216 type
= wpabuf_put(req
, sizeof(*type
));
1217 type
->type
= host_to_be16(PAC_TYPE_PAC_TYPE
);
1218 type
->length
= host_to_be16(2);
1219 type
->pac_type
= host_to_be16(PAC_TYPE_TUNNEL_PAC
);
1225 static int eap_teap_process_decrypted(struct eap_sm
*sm
,
1226 struct eap_teap_data
*data
,
1227 struct eap_method_ret
*ret
,
1229 struct wpabuf
*decrypted
,
1230 struct wpabuf
**out_data
)
1232 struct wpabuf
*resp
= NULL
, *tmp
;
1233 struct eap_teap_tlv_parse tlv
;
1235 enum teap_error_codes error
= 0;
1236 int iresult_added
= 0;
1238 if (eap_teap_parse_decrypted(decrypted
, &tlv
, &resp
) < 0) {
1239 /* Parsing failed - no response available */
1244 /* Parsing rejected the message - send out an error response */
1248 if (tlv
.result
== TEAP_STATUS_FAILURE
) {
1249 /* Server indicated failure - respond similarly per
1250 * RFC 7170, 3.6.3. This authentication exchange cannot succeed
1251 * and will be terminated with a cleartext EAP Failure. */
1252 wpa_printf(MSG_DEBUG
,
1253 "EAP-TEAP: Server rejected authentication");
1254 resp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1255 ret
->methodState
= METHOD_DONE
;
1256 ret
->decision
= DECISION_FAIL
;
1260 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
&& !tlv
.crypto_binding
) {
1261 /* Intermediate-Result TLV indicating success, but no
1262 * Crypto-Binding TLV */
1263 wpa_printf(MSG_DEBUG
,
1264 "EAP-TEAP: Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
1266 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1270 if (!data
->iresult_verified
&& !data
->result_success_done
&&
1271 tlv
.result
== TEAP_STATUS_SUCCESS
&& !tlv
.crypto_binding
) {
1272 /* Result TLV indicating success, but no Crypto-Binding TLV */
1273 wpa_printf(MSG_DEBUG
,
1274 "EAP-TEAP: Result TLV indicating success, but no Crypto-Binding TLV");
1276 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1280 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1281 tlv
.iresult
!= TEAP_STATUS_FAILURE
&&
1282 data
->inner_method_done
) {
1283 wpa_printf(MSG_DEBUG
,
1284 "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
1286 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1290 if (tlv
.identity_type
== TEAP_IDENTITY_TYPE_MACHINE
) {
1291 struct eap_peer_config
*config
= eap_get_config(sm
);
1293 sm
->use_machine_cred
= config
&& config
->machine_identity
&&
1294 config
->machine_identity_len
;
1295 } else if (tlv
.identity_type
) {
1296 sm
->use_machine_cred
= 0;
1299 if (tlv
.basic_auth_req
) {
1300 tmp
= eap_teap_process_basic_auth_req(sm
, data
,
1302 tlv
.basic_auth_req_len
,
1306 resp
= wpabuf_concat(resp
, tmp
);
1307 } else if (tlv
.eap_payload_tlv
) {
1308 tmp
= eap_teap_process_eap_payload_tlv(sm
, data
, ret
,
1309 tlv
.eap_payload_tlv
,
1310 tlv
.eap_payload_tlv_len
,
1314 resp
= wpabuf_concat(resp
, tmp
);
1316 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1317 tlv
.iresult
== TEAP_STATUS_FAILURE
) {
1318 tmp
= eap_teap_tlv_result(failed
?
1319 TEAP_STATUS_FAILURE
:
1320 TEAP_STATUS_SUCCESS
, 1);
1321 resp
= wpabuf_concat(resp
, tmp
);
1322 if (tlv
.iresult
== TEAP_STATUS_FAILURE
)
1328 if (tlv
.crypto_binding
) {
1329 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1330 tlv
.result
!= TEAP_STATUS_SUCCESS
) {
1331 wpa_printf(MSG_DEBUG
,
1332 "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
1334 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1338 tmp
= eap_teap_process_crypto_binding(sm
, data
, ret
,
1340 tlv
.crypto_binding_len
);
1343 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1345 resp
= wpabuf_concat(resp
, tmp
);
1346 if (tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
)
1347 data
->result_success_done
= 1;
1348 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
&& !failed
) {
1349 data
->inner_method_done
= 0;
1350 data
->iresult_verified
= 1;
1355 if (data
->result_success_done
&& data
->session_ticket_used
&&
1356 eap_teap_derive_msk(data
) == 0) {
1357 /* Assume the server might accept authentication without going
1358 * through inner authentication. */
1359 wpa_printf(MSG_DEBUG
,
1360 "EAP-TEAP: PAC used - server may decide to skip inner authentication");
1361 ret
->methodState
= METHOD_MAY_CONT
;
1362 ret
->decision
= DECISION_COND_SUCC
;
1366 if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1367 tmp
= eap_teap_process_pac(sm
, data
, ret
,
1368 tlv
.pac
, tlv
.pac_len
);
1369 resp
= wpabuf_concat(resp
, tmp
);
1371 wpa_printf(MSG_DEBUG
,
1372 "EAP-TEAP: PAC TLV without Result TLV acknowledging success");
1374 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1378 if (!data
->current_pac
&& data
->provisioning
&& !failed
&& !tlv
.pac
&&
1379 tlv
.crypto_binding
&&
1380 (!data
->anon_provisioning
||
1381 (data
->phase2_success
&& data
->phase2_method
&&
1382 data
->phase2_method
->vendor
== 0 &&
1383 eap_teap_allowed_anon_prov_cipher_suite(data
->tls_cs
) &&
1384 eap_teap_allowed_anon_prov_phase2_method(
1385 data
->phase2_method
->vendor
,
1386 data
->phase2_method
->method
))) &&
1387 (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1388 tlv
.result
== TEAP_STATUS_SUCCESS
)) {
1390 * Need to request Tunnel PAC when using authenticated
1393 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Request Tunnel PAC");
1394 tmp
= eap_teap_pac_request();
1395 resp
= wpabuf_concat(resp
, tmp
);
1400 tmp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1401 resp
= wpabuf_concat(tmp
, resp
);
1404 tmp
= eap_teap_tlv_error(error
);
1405 resp
= wpabuf_concat(tmp
, resp
);
1408 ret
->methodState
= METHOD_DONE
;
1409 ret
->decision
= DECISION_FAIL
;
1410 } else if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1411 tmp
= eap_teap_tlv_result(TEAP_STATUS_SUCCESS
, 0);
1412 resp
= wpabuf_concat(tmp
, resp
);
1414 if ((tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1415 tlv
.iresult
== TEAP_STATUS_FAILURE
) && !iresult_added
) {
1416 tmp
= eap_teap_tlv_result((!failed
&& data
->phase2_success
) ?
1417 TEAP_STATUS_SUCCESS
:
1418 TEAP_STATUS_FAILURE
, 1);
1419 resp
= wpabuf_concat(tmp
, resp
);
1422 if (resp
&& tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
&&
1423 (tlv
.crypto_binding
|| data
->iresult_verified
) &&
1424 data
->phase2_success
) {
1425 /* Successfully completed Phase 2 */
1426 wpa_printf(MSG_DEBUG
,
1427 "EAP-TEAP: Authentication completed successfully");
1428 ret
->methodState
= METHOD_MAY_CONT
;
1429 data
->on_tx_completion
= data
->provisioning
?
1430 METHOD_MAY_CONT
: METHOD_DONE
;
1431 ret
->decision
= DECISION_UNCOND_SUCC
;
1435 wpa_printf(MSG_DEBUG
,
1436 "EAP-TEAP: No recognized TLVs - send empty response packet");
1437 resp
= wpabuf_alloc(1);
1444 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: Encrypting Phase 2 data", resp
);
1445 if (eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1446 data
->teap_version
, identifier
,
1448 wpa_printf(MSG_INFO
,
1449 "EAP-TEAP: Failed to encrypt a Phase 2 frame");
1457 static int eap_teap_decrypt(struct eap_sm
*sm
, struct eap_teap_data
*data
,
1458 struct eap_method_ret
*ret
, u8 identifier
,
1459 const struct wpabuf
*in_data
,
1460 struct wpabuf
**out_data
)
1462 struct wpabuf
*in_decrypted
;
1465 wpa_printf(MSG_DEBUG
,
1466 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1467 (unsigned long) wpabuf_len(in_data
));
1469 if (data
->pending_phase2_req
) {
1470 wpa_printf(MSG_DEBUG
,
1471 "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
1472 /* Clear TLS reassembly state. */
1473 eap_peer_tls_reset_input(&data
->ssl
);
1475 in_decrypted
= data
->pending_phase2_req
;
1476 data
->pending_phase2_req
= NULL
;
1480 if (wpabuf_len(in_data
) == 0) {
1481 /* Received TLS ACK - requesting more fragments */
1482 res
= eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1484 identifier
, NULL
, out_data
);
1485 if (res
== 0 && !data
->ssl
.tls_out
&&
1486 data
->on_tx_completion
) {
1487 wpa_printf(MSG_DEBUG
,
1488 "EAP-TEAP: Mark authentication completed at full TX of fragments");
1489 ret
->methodState
= data
->on_tx_completion
;
1490 data
->on_tx_completion
= 0;
1491 ret
->decision
= DECISION_UNCOND_SUCC
;
1496 res
= eap_peer_tls_decrypt(sm
, &data
->ssl
, in_data
, &in_decrypted
);
1501 wpa_hexdump_buf(MSG_MSGDUMP
, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
1504 if (wpabuf_len(in_decrypted
) < 4) {
1505 wpa_printf(MSG_INFO
,
1506 "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
1507 (unsigned long) wpabuf_len(in_decrypted
));
1508 wpabuf_free(in_decrypted
);
1512 res
= eap_teap_process_decrypted(sm
, data
, ret
, identifier
,
1513 in_decrypted
, out_data
);
1515 wpabuf_free(in_decrypted
);
1521 static void eap_teap_select_pac(struct eap_teap_data
*data
,
1522 const u8
*a_id
, size_t a_id_len
)
1526 data
->current_pac
= eap_teap_get_pac(data
->pac
, a_id
, a_id_len
,
1527 PAC_TYPE_TUNNEL_PAC
);
1528 if (data
->current_pac
) {
1529 wpa_printf(MSG_DEBUG
,
1530 "EAP-TEAP: PAC found for this A-ID (PAC-Type %d)",
1531 data
->current_pac
->pac_type
);
1532 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-TEAP: A-ID-Info",
1533 data
->current_pac
->a_id_info
,
1534 data
->current_pac
->a_id_info_len
);
1539 static int eap_teap_use_pac_opaque(struct eap_sm
*sm
,
1540 struct eap_teap_data
*data
,
1541 struct eap_teap_pac
*pac
)
1544 size_t tlv_len
, olen
;
1545 struct teap_tlv_hdr
*ehdr
;
1547 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC-Opaque TLS extension");
1548 olen
= pac
->pac_opaque_len
;
1549 tlv_len
= sizeof(*ehdr
) + olen
;
1550 tlv
= os_malloc(tlv_len
);
1552 ehdr
= (struct teap_tlv_hdr
*) tlv
;
1553 ehdr
->tlv_type
= host_to_be16(PAC_TYPE_PAC_OPAQUE
);
1554 ehdr
->length
= host_to_be16(olen
);
1555 os_memcpy(ehdr
+ 1, pac
->pac_opaque
, olen
);
1558 tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1560 tlv
, tlv_len
) < 0) {
1561 wpa_printf(MSG_DEBUG
,
1562 "EAP-TEAP: Failed to add PAC-Opaque TLS extension");
1572 static int eap_teap_clear_pac_opaque_ext(struct eap_sm
*sm
,
1573 struct eap_teap_data
*data
)
1575 if (tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1576 TLS_EXT_PAC_OPAQUE
, NULL
, 0) < 0) {
1577 wpa_printf(MSG_DEBUG
,
1578 "EAP-TEAP: Failed to remove PAC-Opaque TLS extension");
1585 static int eap_teap_process_start(struct eap_sm
*sm
,
1586 struct eap_teap_data
*data
, u8 flags
,
1587 const u8
*pos
, size_t left
)
1589 const u8
*a_id
= NULL
;
1590 size_t a_id_len
= 0;
1592 /* TODO: Support (mostly theoretical) case of TEAP/Start request being
1595 /* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
1596 data
->received_version
= flags
& EAP_TLS_VERSION_MASK
;
1597 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
1598 data
->received_version
, data
->teap_version
);
1599 if (data
->received_version
< 1) {
1600 /* Version 1 was the first defined version, so reject 0 */
1601 wpa_printf(MSG_INFO
,
1602 "EAP-TEAP: Server used unknown TEAP version %u",
1603 data
->received_version
);
1606 if (data
->received_version
< data
->teap_version
)
1607 data
->teap_version
= data
->received_version
;
1608 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Using TEAP version %d",
1609 data
->teap_version
);
1610 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message payload", pos
, left
);
1612 /* Parse Authority-ID TLV from Outer TLVs, if present */
1613 if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1614 const u8
*outer_pos
, *outer_end
;
1618 wpa_printf(MSG_INFO
,
1619 "EAP-TEAP: Not enough room for the Outer TLV Length field");
1623 outer_tlv_len
= WPA_GET_BE32(pos
);
1627 if (outer_tlv_len
> left
) {
1628 wpa_printf(MSG_INFO
,
1629 "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
1630 outer_tlv_len
, (unsigned int) left
);
1634 outer_pos
= pos
+ left
- outer_tlv_len
;
1635 outer_end
= outer_pos
+ outer_tlv_len
;
1636 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message Outer TLVs",
1637 outer_pos
, outer_tlv_len
);
1638 wpabuf_free(data
->server_outer_tlvs
);
1639 data
->server_outer_tlvs
= wpabuf_alloc_copy(outer_pos
,
1641 if (!data
->server_outer_tlvs
)
1643 left
-= outer_tlv_len
;
1645 wpa_hexdump(MSG_INFO
,
1646 "EAP-TEAP: Unexpected TLS Data in Start message",
1651 while (outer_pos
< outer_end
) {
1652 u16 tlv_type
, tlv_len
;
1654 if (outer_end
- outer_pos
< 4) {
1655 wpa_printf(MSG_INFO
,
1656 "EAP-TEAP: Truncated Outer TLV header");
1659 tlv_type
= WPA_GET_BE16(outer_pos
);
1661 tlv_len
= WPA_GET_BE16(outer_pos
);
1663 /* Outer TLVs are required to be optional, so no need to
1664 * check the M flag */
1665 tlv_type
&= TEAP_TLV_TYPE_MASK
;
1666 wpa_printf(MSG_DEBUG
,
1667 "EAP-TEAP: Outer TLV: Type=%u Length=%u",
1669 if (outer_end
- outer_pos
< tlv_len
) {
1670 wpa_printf(MSG_INFO
,
1671 "EAP-TEAP: Truncated Outer TLV (Type %u)",
1675 if (tlv_type
== TEAP_TLV_AUTHORITY_ID
) {
1676 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Authority-ID",
1677 outer_pos
, tlv_len
);
1679 wpa_printf(MSG_INFO
,
1680 "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
1686 wpa_printf(MSG_DEBUG
,
1687 "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
1690 outer_pos
+= tlv_len
;
1692 } else if (left
> 0) {
1693 wpa_hexdump(MSG_INFO
,
1694 "EAP-TEAP: Unexpected TLS Data in Start message",
1699 eap_teap_select_pac(data
, a_id
, a_id_len
);
1701 if (data
->resuming
&& data
->current_pac
) {
1702 wpa_printf(MSG_DEBUG
,
1703 "EAP-TEAP: Trying to resume session - do not add PAC-Opaque to TLS ClientHello");
1704 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1706 } else if (data
->current_pac
) {
1708 * PAC found for the A-ID and we are not resuming an old
1709 * session, so add PAC-Opaque extension to ClientHello.
1711 if (eap_teap_use_pac_opaque(sm
, data
, data
->current_pac
) < 0)
1713 } else if (data
->provisioning_allowed
) {
1714 wpa_printf(MSG_DEBUG
,
1715 "EAP-TEAP: No PAC found - starting provisioning");
1716 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1718 data
->provisioning
= 1;
1725 #ifdef CONFIG_TESTING_OPTIONS
1726 static struct wpabuf
* eap_teap_add_dummy_outer_tlvs(struct eap_teap_data
*data
,
1727 struct wpabuf
*resp
)
1729 struct wpabuf
*resp2
;
1734 wpabuf_free(data
->peer_outer_tlvs
);
1735 data
->peer_outer_tlvs
= wpabuf_alloc(4 + 4);
1736 if (!data
->peer_outer_tlvs
) {
1741 /* Outer TLVs (dummy Vendor-Specific TLV for testing) */
1742 wpabuf_put_be16(data
->peer_outer_tlvs
, TEAP_TLV_VENDOR_SPECIFIC
);
1743 wpabuf_put_be16(data
->peer_outer_tlvs
, 4);
1744 wpabuf_put_be32(data
->peer_outer_tlvs
, EAP_VENDOR_HOSTAP
);
1745 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
1746 data
->peer_outer_tlvs
);
1748 wpa_hexdump_buf(MSG_DEBUG
,
1749 "EAP-TEAP: TEAP/Start response before modification",
1751 resp2
= wpabuf_alloc(wpabuf_len(resp
) + 4 +
1752 wpabuf_len(data
->peer_outer_tlvs
));
1758 pos
= wpabuf_head(resp
);
1759 wpabuf_put_u8(resp2
, *pos
++); /* Code */
1760 wpabuf_put_u8(resp2
, *pos
++); /* Identifier */
1761 len
= WPA_GET_BE16(pos
);
1763 wpabuf_put_be16(resp2
, len
+ 4 + wpabuf_len(data
->peer_outer_tlvs
));
1764 wpabuf_put_u8(resp2
, *pos
++); /* Type */
1765 /* Flags | Ver (with Outer TLV length included flag set to 1) */
1767 if (flags
& (EAP_TEAP_FLAGS_OUTER_TLV_LEN
|
1768 EAP_TLS_FLAGS_LENGTH_INCLUDED
)) {
1769 wpa_printf(MSG_INFO
,
1770 "EAP-TEAP: Cannot add Outer TLVs for testing");
1775 flags
|= EAP_TEAP_FLAGS_OUTER_TLV_LEN
;
1776 wpabuf_put_u8(resp2
, flags
);
1777 /* Outer TLV Length */
1778 wpabuf_put_be32(resp2
, wpabuf_len(data
->peer_outer_tlvs
));
1780 wpabuf_put_data(resp2
, pos
, wpabuf_len(resp
) - 6);
1781 wpabuf_put_buf(resp2
, data
->peer_outer_tlvs
); /* Outer TLVs */
1784 wpa_hexdump_buf(MSG_DEBUG
,
1785 "EAP-TEAP: TEAP/Start response after modification",
1789 #endif /* CONFIG_TESTING_OPTIONS */
1792 static struct wpabuf
* eap_teap_process(struct eap_sm
*sm
, void *priv
,
1793 struct eap_method_ret
*ret
,
1794 const struct wpabuf
*reqData
)
1796 const struct eap_hdr
*req
;
1800 struct wpabuf
*resp
;
1802 struct eap_teap_data
*data
= priv
;
1805 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TEAP
, ret
,
1806 reqData
, &left
, &flags
);
1810 req
= wpabuf_head(reqData
);
1811 id
= req
->identifier
;
1813 if (flags
& EAP_TLS_FLAGS_START
) {
1814 if (eap_teap_process_start(sm
, data
, flags
, pos
, left
) < 0)
1817 /* Outer TLVs are not used in further packet processing and
1818 * there cannot be TLS Data in this TEAP/Start message, so
1819 * enforce that by ignoring whatever data might remain in the
1822 } else if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1823 /* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
1824 * Outer TLVs MUST be ignored instead of ignoring the full
1826 wpa_printf(MSG_INFO
,
1827 "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
1831 wpabuf_set(&msg
, pos
, left
);
1834 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
) &&
1836 /* Process tunneled (encrypted) phase 2 data. */
1837 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1839 ret
->methodState
= METHOD_DONE
;
1840 ret
->decision
= DECISION_FAIL
;
1842 * Ack possible Alert that may have caused failure in
1848 if (sm
->waiting_ext_cert_check
&& data
->pending_resp
) {
1849 struct eap_peer_config
*config
= eap_get_config(sm
);
1851 if (config
->pending_ext_cert_check
==
1852 EXT_CERT_CHECK_GOOD
) {
1853 wpa_printf(MSG_DEBUG
,
1854 "EAP-TEAP: External certificate check succeeded - continue handshake");
1855 resp
= data
->pending_resp
;
1856 data
->pending_resp
= NULL
;
1857 sm
->waiting_ext_cert_check
= 0;
1861 if (config
->pending_ext_cert_check
==
1862 EXT_CERT_CHECK_BAD
) {
1863 wpa_printf(MSG_DEBUG
,
1864 "EAP-TEAP: External certificate check failed - force authentication failure");
1865 ret
->methodState
= METHOD_DONE
;
1866 ret
->decision
= DECISION_FAIL
;
1867 sm
->waiting_ext_cert_check
= 0;
1871 wpa_printf(MSG_DEBUG
,
1872 "EAP-TEAP: Continuing to wait external server certificate validation");
1876 /* Continue processing TLS handshake (phase 1). */
1877 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
,
1879 data
->teap_version
, id
, &msg
,
1882 wpa_printf(MSG_DEBUG
,
1883 "EAP-TEAP: TLS processing failed");
1884 ret
->methodState
= METHOD_DONE
;
1885 ret
->decision
= DECISION_FAIL
;
1889 if (sm
->waiting_ext_cert_check
) {
1890 wpa_printf(MSG_DEBUG
,
1891 "EAP-TEAP: Waiting external server certificate validation");
1892 wpabuf_free(data
->pending_resp
);
1893 data
->pending_resp
= resp
;
1897 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1900 wpa_printf(MSG_DEBUG
,
1901 "EAP-TEAP: TLS done, proceed to Phase 2");
1903 tls_connection_get_cipher_suite(data
->ssl
.conn
);
1904 wpa_printf(MSG_DEBUG
,
1905 "EAP-TEAP: TLS cipher suite 0x%04x",
1908 if (data
->provisioning
&&
1909 (!(data
->provisioning_allowed
&
1910 EAP_TEAP_PROV_AUTH
) ||
1911 tls_get_cipher(sm
->ssl_ctx
, data
->ssl
.conn
,
1912 cipher
, sizeof(cipher
)) < 0 ||
1913 os_strstr(cipher
, "ADH-") ||
1914 os_strstr(cipher
, "anon"))) {
1915 wpa_printf(MSG_DEBUG
,
1916 "EAP-TEAP: Using anonymous (unauthenticated) provisioning");
1917 data
->anon_provisioning
= 1;
1919 data
->anon_provisioning
= 0;
1922 if (eap_teap_derive_key_auth(sm
, data
) < 0) {
1923 wpa_printf(MSG_DEBUG
,
1924 "EAP-TEAP: Could not derive keys");
1925 ret
->methodState
= METHOD_DONE
;
1926 ret
->decision
= DECISION_FAIL
;
1934 * Application data included in the handshake message.
1936 wpabuf_free(data
->pending_phase2_req
);
1937 data
->pending_phase2_req
= resp
;
1939 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1945 return eap_peer_tls_build_ack(id
, EAP_TYPE_TEAP
,
1946 data
->teap_version
);
1949 #ifdef CONFIG_TESTING_OPTIONS
1950 if (data
->test_outer_tlvs
&& res
== 0 && resp
&&
1951 (flags
& EAP_TLS_FLAGS_START
) && wpabuf_len(resp
) >= 6)
1952 resp
= eap_teap_add_dummy_outer_tlvs(data
, resp
);
1953 #endif /* CONFIG_TESTING_OPTIONS */
1960 static Boolean
eap_teap_has_reauth_data(struct eap_sm
*sm
, void *priv
)
1962 struct eap_teap_data
*data
= priv
;
1964 return tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
);
1968 static void eap_teap_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
1970 struct eap_teap_data
*data
= priv
;
1972 if (data
->phase2_priv
&& data
->phase2_method
&&
1973 data
->phase2_method
->deinit_for_reauth
)
1974 data
->phase2_method
->deinit_for_reauth(sm
, data
->phase2_priv
);
1975 eap_teap_clear(data
);
1979 static void * eap_teap_init_for_reauth(struct eap_sm
*sm
, void *priv
)
1981 struct eap_teap_data
*data
= priv
;
1983 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
1984 eap_teap_deinit(sm
, data
);
1987 if (data
->phase2_priv
&& data
->phase2_method
&&
1988 data
->phase2_method
->init_for_reauth
)
1989 data
->phase2_method
->init_for_reauth(sm
, data
->phase2_priv
);
1990 data
->phase2_success
= 0;
1991 data
->inner_method_done
= 0;
1992 data
->result_success_done
= 0;
1993 data
->iresult_verified
= 0;
1994 data
->done_on_tx_completion
= 0;
1996 data
->provisioning
= 0;
1997 data
->anon_provisioning
= 0;
1998 data
->simck_idx
= 0;
2004 static int eap_teap_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
2005 size_t buflen
, int verbose
)
2007 struct eap_teap_data
*data
= priv
;
2010 len
= eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
2011 if (data
->phase2_method
) {
2012 ret
= os_snprintf(buf
+ len
, buflen
- len
,
2013 "EAP-TEAP Phase 2 method=%s\n",
2014 data
->phase2_method
->name
);
2015 if (os_snprintf_error(buflen
- len
, ret
))
2023 static Boolean
eap_teap_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
2025 struct eap_teap_data
*data
= priv
;
2027 return data
->success
;
2031 static u8
* eap_teap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
2033 struct eap_teap_data
*data
= priv
;
2039 key
= os_memdup(data
->key_data
, EAP_TEAP_KEY_LEN
);
2043 *len
= EAP_TEAP_KEY_LEN
;
2049 static u8
* eap_teap_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
2051 struct eap_teap_data
*data
= priv
;
2054 if (!data
->success
|| !data
->session_id
)
2057 id
= os_memdup(data
->session_id
, data
->id_len
);
2061 *len
= data
->id_len
;
2067 static u8
* eap_teap_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
2069 struct eap_teap_data
*data
= priv
;
2075 key
= os_memdup(data
->emsk
, EAP_EMSK_LEN
);
2079 *len
= EAP_EMSK_LEN
;
2085 int eap_peer_teap_register(void)
2087 struct eap_method
*eap
;
2089 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
2090 EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, "TEAP");
2094 eap
->init
= eap_teap_init
;
2095 eap
->deinit
= eap_teap_deinit
;
2096 eap
->process
= eap_teap_process
;
2097 eap
->isKeyAvailable
= eap_teap_isKeyAvailable
;
2098 eap
->getKey
= eap_teap_getKey
;
2099 eap
->getSessionId
= eap_teap_get_session_id
;
2100 eap
->get_status
= eap_teap_get_status
;
2102 eap
->has_reauth_data
= eap_teap_has_reauth_data
;
2103 eap
->deinit_for_reauth
= eap_teap_deinit_for_reauth
;
2104 eap
->init_for_reauth
= eap_teap_init_for_reauth
;
2106 eap
->get_emsk
= eap_teap_get_emsk
;
2108 return eap_peer_method_register(eap
);