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
, u8 type
)
334 /* TODO: TNC with anonymous provisioning; need to require both
335 * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
337 if (data
->anon_provisioning
&&
338 !eap_teap_allowed_anon_prov_phase2_method(type
)) {
340 "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
346 if (type
== EAP_TYPE_TNC
) {
347 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
348 data
->phase2_type
.method
= EAP_TYPE_TNC
;
349 wpa_printf(MSG_DEBUG
,
350 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
351 data
->phase2_type
.vendor
,
352 data
->phase2_type
.method
);
357 for (i
= 0; i
< data
->num_phase2_types
; i
++) {
358 if (data
->phase2_types
[i
].vendor
!= EAP_VENDOR_IETF
||
359 data
->phase2_types
[i
].method
!= type
)
362 data
->phase2_type
.vendor
= data
->phase2_types
[i
].vendor
;
363 data
->phase2_type
.method
= data
->phase2_types
[i
].method
;
364 wpa_printf(MSG_DEBUG
,
365 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
366 data
->phase2_type
.vendor
,
367 data
->phase2_type
.method
);
371 if (type
!= data
->phase2_type
.method
|| type
== EAP_TYPE_NONE
)
378 static int eap_teap_phase2_request(struct eap_sm
*sm
,
379 struct eap_teap_data
*data
,
380 struct eap_method_ret
*ret
,
382 struct wpabuf
**resp
)
384 size_t len
= be_to_host16(hdr
->length
);
386 struct eap_method_ret iret
;
387 struct eap_peer_config
*config
= eap_get_config(sm
);
390 if (len
<= sizeof(struct eap_hdr
)) {
392 "EAP-TEAP: too short Phase 2 request (len=%lu)",
393 (unsigned long) len
);
396 pos
= (u8
*) (hdr
+ 1);
397 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 2 Request: type=%d", *pos
);
398 if (*pos
== EAP_TYPE_IDENTITY
) {
399 *resp
= eap_sm_buildIdentity(sm
, hdr
->identifier
, 1);
403 if (data
->phase2_priv
&& data
->phase2_method
&&
404 *pos
!= data
->phase2_type
.method
) {
405 wpa_printf(MSG_DEBUG
,
406 "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
407 data
->phase2_method
->deinit(sm
, data
->phase2_priv
);
408 data
->phase2_method
= NULL
;
409 data
->phase2_priv
= NULL
;
410 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
411 data
->phase2_type
.method
= EAP_TYPE_NONE
;
414 if (data
->phase2_type
.vendor
== EAP_VENDOR_IETF
&&
415 data
->phase2_type
.method
== EAP_TYPE_NONE
&&
416 eap_teap_select_phase2_method(data
, *pos
) < 0) {
417 if (eap_peer_tls_phase2_nak(data
->phase2_types
,
418 data
->num_phase2_types
,
424 if ((!data
->phase2_priv
&& eap_teap_init_phase2_method(sm
, data
) < 0) ||
425 !data
->phase2_method
) {
427 "EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
429 ret
->methodState
= METHOD_DONE
;
430 ret
->decision
= DECISION_FAIL
;
434 os_memset(&iret
, 0, sizeof(iret
));
435 wpabuf_set(&msg
, hdr
, len
);
436 *resp
= data
->phase2_method
->process(sm
, data
->phase2_priv
, &iret
,
438 if (iret
.methodState
== METHOD_DONE
)
439 data
->inner_method_done
= 1;
441 (iret
.methodState
== METHOD_DONE
&&
442 iret
.decision
== DECISION_FAIL
)) {
443 ret
->methodState
= METHOD_DONE
;
444 ret
->decision
= DECISION_FAIL
;
445 } else if ((iret
.methodState
== METHOD_DONE
||
446 iret
.methodState
== METHOD_MAY_CONT
) &&
447 (iret
.decision
== DECISION_UNCOND_SUCC
||
448 iret
.decision
== DECISION_COND_SUCC
)) {
449 data
->phase2_success
= 1;
452 if (!(*resp
) && config
&&
453 (config
->pending_req_identity
|| config
->pending_req_password
||
454 config
->pending_req_otp
|| config
->pending_req_new_password
||
455 config
->pending_req_sim
)) {
456 wpabuf_free(data
->pending_phase2_req
);
457 data
->pending_phase2_req
= wpabuf_alloc_copy(hdr
, len
);
465 static struct wpabuf
* eap_teap_tlv_nak(int vendor_id
, int tlv_type
)
468 struct teap_tlv_nak
*nak
;
470 wpa_printf(MSG_DEBUG
,
471 "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
472 vendor_id
, tlv_type
);
473 buf
= wpabuf_alloc(sizeof(*nak
));
476 nak
= wpabuf_put(buf
, sizeof(*nak
));
477 nak
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
| TEAP_TLV_NAK
);
478 nak
->length
= host_to_be16(6);
479 nak
->vendor_id
= host_to_be32(vendor_id
);
480 nak
->nak_type
= host_to_be16(tlv_type
);
485 static struct wpabuf
* eap_teap_tlv_pac_ack(void)
488 struct teap_tlv_result
*res
;
489 struct teap_tlv_pac_ack
*ack
;
491 buf
= wpabuf_alloc(sizeof(*res
) + sizeof(*ack
));
495 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (ack)");
496 ack
= wpabuf_put(buf
, sizeof(*ack
));
497 ack
->tlv_type
= host_to_be16(TEAP_TLV_PAC
| TEAP_TLV_MANDATORY
);
498 ack
->length
= host_to_be16(sizeof(*ack
) - sizeof(struct teap_tlv_hdr
));
499 ack
->pac_type
= host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT
);
500 ack
->pac_len
= host_to_be16(2);
501 ack
->result
= host_to_be16(TEAP_STATUS_SUCCESS
);
507 static struct wpabuf
* eap_teap_process_eap_payload_tlv(
508 struct eap_sm
*sm
, struct eap_teap_data
*data
,
509 struct eap_method_ret
*ret
,
510 u8
*eap_payload_tlv
, size_t eap_payload_tlv_len
)
513 struct wpabuf
*resp
= NULL
;
515 if (eap_payload_tlv_len
< sizeof(*hdr
)) {
516 wpa_printf(MSG_DEBUG
,
517 "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
518 (unsigned long) eap_payload_tlv_len
);
522 hdr
= (struct eap_hdr
*) eap_payload_tlv
;
523 if (be_to_host16(hdr
->length
) > eap_payload_tlv_len
) {
524 wpa_printf(MSG_DEBUG
,
525 "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
529 if (hdr
->code
!= EAP_CODE_REQUEST
) {
531 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
536 if (eap_teap_phase2_request(sm
, data
, ret
, hdr
, &resp
)) {
538 "EAP-TEAP: Phase 2 Request processing failed");
542 return eap_teap_tlv_eap_payload(resp
);
546 static struct wpabuf
* eap_teap_process_basic_auth_req(
547 struct eap_sm
*sm
, struct eap_teap_data
*data
,
548 u8
*basic_auth_req
, size_t basic_auth_req_len
)
550 const u8
*identity
, *password
;
551 size_t identity_len
, password_len
, plen
;
554 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Req prompt",
555 basic_auth_req
, basic_auth_req_len
);
556 /* TODO: send over control interface */
558 identity
= eap_get_config_identity(sm
, &identity_len
);
559 password
= eap_get_config_password(sm
, &password_len
);
560 if (!identity
|| !password
||
561 identity_len
> 255 || password_len
> 255) {
562 wpa_printf(MSG_DEBUG
,
563 "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
564 return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ
);
567 plen
= 1 + identity_len
+ 1 + password_len
;
568 resp
= wpabuf_alloc(sizeof(struct teap_tlv_hdr
) + plen
);
571 eap_teap_put_tlv_hdr(resp
, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP
, plen
);
572 wpabuf_put_u8(resp
, identity_len
);
573 wpabuf_put_data(resp
, identity
, identity_len
);
574 wpabuf_put_u8(resp
, password_len
);
575 wpabuf_put_data(resp
, password
, password_len
);
576 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Resp",
579 /* Assume this succeeds so that Result TLV(Success) from the server can
580 * be used to terminate TEAP. */
581 data
->phase2_success
= 1;
588 eap_teap_validate_crypto_binding(struct eap_teap_data
*data
,
589 const struct teap_tlv_crypto_binding
*cb
)
593 subtype
= cb
->subtype
& 0x0f;
594 flags
= cb
->subtype
>> 4;
596 wpa_printf(MSG_DEBUG
,
597 "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
598 cb
->version
, cb
->received_version
, flags
, subtype
);
599 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
600 cb
->nonce
, sizeof(cb
->nonce
));
601 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
602 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
603 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
604 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
606 if (cb
->version
!= EAP_TEAP_VERSION
||
607 cb
->received_version
!= data
->received_version
||
608 subtype
!= TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST
||
609 flags
< 1 || flags
> 3) {
611 "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
612 cb
->version
, cb
->received_version
, flags
, subtype
);
616 if (cb
->nonce
[EAP_TEAP_NONCE_LEN
- 1] & 0x01) {
618 "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
626 static int eap_teap_write_crypto_binding(
627 struct eap_teap_data
*data
,
628 struct teap_tlv_crypto_binding
*rbind
,
629 const struct teap_tlv_crypto_binding
*cb
,
630 const u8
*cmk_msk
, const u8
*cmk_emsk
)
634 rbind
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
635 TEAP_TLV_CRYPTO_BINDING
);
636 rbind
->length
= host_to_be16(sizeof(*rbind
) -
637 sizeof(struct teap_tlv_hdr
));
638 rbind
->version
= EAP_TEAP_VERSION
;
639 rbind
->received_version
= data
->received_version
;
640 /* FIX: RFC 7170 is not clear on which Flags value to use when
641 * Crypto-Binding TLV is used with Basic-Password-Auth */
642 flags
= cmk_emsk
? TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
:
643 TEAP_CRYPTO_BINDING_MSK_CMAC
;
644 subtype
= TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE
;
645 rbind
->subtype
= (flags
<< 4) | subtype
;
646 os_memcpy(rbind
->nonce
, cb
->nonce
, sizeof(cb
->nonce
));
647 inc_byte_array(rbind
->nonce
, sizeof(rbind
->nonce
));
648 os_memset(rbind
->emsk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
649 os_memset(rbind
->msk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
651 if (eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
652 data
->peer_outer_tlvs
, cmk_msk
,
653 rbind
->msk_compound_mac
) < 0)
656 eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
657 data
->peer_outer_tlvs
, cmk_emsk
,
658 rbind
->emsk_compound_mac
) < 0)
661 wpa_printf(MSG_DEBUG
,
662 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
663 rbind
->version
, rbind
->received_version
, flags
, subtype
);
664 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
665 rbind
->nonce
, sizeof(rbind
->nonce
));
666 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
667 rbind
->emsk_compound_mac
, sizeof(rbind
->emsk_compound_mac
));
668 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
669 rbind
->msk_compound_mac
, sizeof(rbind
->msk_compound_mac
));
675 static int eap_teap_get_cmk(struct eap_sm
*sm
, struct eap_teap_data
*data
,
676 u8
*cmk_msk
, u8
*cmk_emsk
)
678 u8
*msk
= NULL
, *emsk
= NULL
;
679 size_t msk_len
= 0, emsk_len
= 0;
682 wpa_printf(MSG_DEBUG
,
683 "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
684 data
->simck_idx
+ 1);
686 if (!data
->phase2_method
)
687 return eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
691 if (!data
->phase2_method
|| !data
->phase2_priv
) {
692 wpa_printf(MSG_INFO
, "EAP-TEAP: Phase 2 method not available");
696 if (data
->phase2_method
->isKeyAvailable
&&
697 !data
->phase2_method
->isKeyAvailable(sm
, data
->phase2_priv
)) {
699 "EAP-TEAP: Phase 2 key material not available");
703 if (data
->phase2_method
->isKeyAvailable
&&
704 data
->phase2_method
->getKey
) {
705 msk
= data
->phase2_method
->getKey(sm
, data
->phase2_priv
,
709 "EAP-TEAP: Could not fetch Phase 2 MSK");
714 if (data
->phase2_method
->isKeyAvailable
&&
715 data
->phase2_method
->get_emsk
) {
716 emsk
= data
->phase2_method
->get_emsk(sm
, data
->phase2_priv
,
720 res
= eap_teap_derive_imck(data
->tls_cs
,
721 data
->simck_msk
, data
->simck_emsk
,
722 msk
, msk_len
, emsk
, emsk_len
,
723 data
->simck_msk
, cmk_msk
,
724 data
->simck_emsk
, cmk_emsk
);
725 bin_clear_free(msk
, msk_len
);
726 bin_clear_free(emsk
, emsk_len
);
730 data
->cmk_emsk_available
= 1;
736 static int eap_teap_session_id(struct eap_teap_data
*data
)
738 const size_t max_id_len
= 100;
741 os_free(data
->session_id
);
742 data
->session_id
= os_malloc(max_id_len
);
743 if (!data
->session_id
)
746 data
->session_id
[0] = EAP_TYPE_TEAP
;
747 res
= tls_get_tls_unique(data
->ssl
.conn
, data
->session_id
+ 1,
750 os_free(data
->session_id
);
751 data
->session_id
= NULL
;
752 wpa_printf(MSG_ERROR
, "EAP-TEAP: Failed to derive Session-Id");
756 data
->id_len
= 1 + res
;
757 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Derived Session-Id",
758 data
->session_id
, data
->id_len
);
763 static struct wpabuf
* eap_teap_process_crypto_binding(
764 struct eap_sm
*sm
, struct eap_teap_data
*data
,
765 struct eap_method_ret
*ret
,
766 const struct teap_tlv_crypto_binding
*cb
, size_t bind_len
)
770 u8 cmk_msk
[EAP_TEAP_CMK_LEN
];
771 u8 cmk_emsk
[EAP_TEAP_CMK_LEN
];
772 const u8
*cmk_emsk_ptr
= NULL
;
777 if (eap_teap_validate_crypto_binding(data
, cb
) < 0 ||
778 eap_teap_get_cmk(sm
, data
, cmk_msk
, cmk_emsk
) < 0)
781 /* Validate received MSK/EMSK Compound MAC */
782 flags
= cb
->subtype
>> 4;
784 if (flags
== TEAP_CRYPTO_BINDING_MSK_CMAC
||
785 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) {
786 u8 msk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
788 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
789 data
->server_outer_tlvs
,
790 data
->peer_outer_tlvs
, cmk_msk
,
791 msk_compound_mac
) < 0)
793 res
= os_memcmp_const(msk_compound_mac
, cb
->msk_compound_mac
,
794 EAP_TEAP_COMPOUND_MAC_LEN
);
795 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received MSK Compound MAC",
796 cb
->msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
797 wpa_hexdump(MSG_MSGDUMP
,
798 "EAP-TEAP: Calculated MSK Compound MAC",
799 msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
802 "EAP-TEAP: MSK Compound MAC did not match");
807 if ((flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
||
808 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) &&
809 data
->cmk_emsk_available
) {
810 u8 emsk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
812 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
813 data
->server_outer_tlvs
,
814 data
->peer_outer_tlvs
, cmk_emsk
,
815 emsk_compound_mac
) < 0)
817 res
= os_memcmp_const(emsk_compound_mac
, cb
->emsk_compound_mac
,
818 EAP_TEAP_COMPOUND_MAC_LEN
);
819 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received EMSK Compound MAC",
820 cb
->emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
821 wpa_hexdump(MSG_MSGDUMP
,
822 "EAP-TEAP: Calculated EMSK Compound MAC",
823 emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
826 "EAP-TEAP: EMSK Compound MAC did not match");
830 cmk_emsk_ptr
= cmk_emsk
;
833 if (flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
&&
834 !data
->cmk_emsk_available
) {
836 "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
841 * Compound MAC was valid, so authentication succeeded. Reply with
842 * crypto binding to allow server to complete authentication.
845 len
= sizeof(struct teap_tlv_crypto_binding
);
846 resp
= wpabuf_alloc(len
);
850 if (data
->phase2_success
&& eap_teap_derive_msk(data
) < 0) {
851 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to generate MSK");
852 ret
->methodState
= METHOD_DONE
;
853 ret
->decision
= DECISION_FAIL
;
854 data
->phase2_success
= 0;
859 if (data
->phase2_success
&& eap_teap_session_id(data
) < 0) {
864 pos
= wpabuf_put(resp
, sizeof(struct teap_tlv_crypto_binding
));
865 if (eap_teap_write_crypto_binding(
866 data
, (struct teap_tlv_crypto_binding
*) pos
,
867 cb
, cmk_msk
, cmk_emsk_ptr
) < 0) {
876 static void eap_teap_parse_pac_tlv(struct eap_teap_pac
*entry
, int type
,
877 u8
*pos
, size_t len
, int *pac_key_found
)
879 switch (type
& 0x7fff) {
880 case PAC_TYPE_PAC_KEY
:
881 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: PAC-Key", pos
, len
);
882 if (len
!= EAP_TEAP_PAC_KEY_LEN
) {
883 wpa_printf(MSG_DEBUG
,
884 "EAP-TEAP: Invalid PAC-Key length %lu",
885 (unsigned long) len
);
889 os_memcpy(entry
->pac_key
, pos
, len
);
891 case PAC_TYPE_PAC_OPAQUE
:
892 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque", pos
, len
);
893 entry
->pac_opaque
= pos
;
894 entry
->pac_opaque_len
= len
;
896 case PAC_TYPE_PAC_INFO
:
897 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Info", pos
, len
);
898 entry
->pac_info
= pos
;
899 entry
->pac_info_len
= len
;
902 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Ignored unknown PAC type %d",
909 static int eap_teap_process_pac_tlv(struct eap_teap_pac
*entry
,
910 u8
*pac
, size_t pac_len
)
912 struct pac_attr_hdr
*hdr
;
915 int type
, pac_key_found
= 0;
920 while (left
> sizeof(*hdr
)) {
921 hdr
= (struct pac_attr_hdr
*) pos
;
922 type
= be_to_host16(hdr
->type
);
923 len
= be_to_host16(hdr
->len
);
925 left
-= sizeof(*hdr
);
927 wpa_printf(MSG_DEBUG
,
928 "EAP-TEAP: PAC TLV overrun (type=%d len=%lu left=%lu)",
929 type
, (unsigned long) len
,
930 (unsigned long) left
);
934 eap_teap_parse_pac_tlv(entry
, type
, pos
, len
, &pac_key_found
);
940 if (!pac_key_found
|| !entry
->pac_opaque
|| !entry
->pac_info
) {
941 wpa_printf(MSG_DEBUG
,
942 "EAP-TEAP: PAC TLV does not include all the required fields");
950 static int eap_teap_parse_pac_info(struct eap_teap_pac
*entry
, int type
,
957 switch (type
& 0x7fff) {
958 case PAC_TYPE_CRED_LIFETIME
:
960 wpa_hexdump(MSG_DEBUG
,
961 "EAP-TEAP: PAC-Info - Invalid CRED_LIFETIME length - ignored",
967 * This is not currently saved separately in PAC files since
968 * the server can automatically initiate PAC update when
969 * needed. Anyway, the information is available from PAC-Info
970 * dump if it is needed for something in the future.
972 lifetime
= WPA_GET_BE32(pos
);
974 wpa_printf(MSG_DEBUG
,
975 "EAP-TEAP: PAC-Info - CRED_LIFETIME %d (%d days)",
976 lifetime
, (lifetime
- (u32
) now
.sec
) / 86400);
979 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID",
982 entry
->a_id_len
= len
;
985 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - I-ID",
988 entry
->i_id_len
= len
;
990 case PAC_TYPE_A_ID_INFO
:
991 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID-Info",
993 entry
->a_id_info
= pos
;
994 entry
->a_id_info_len
= len
;
996 case PAC_TYPE_PAC_TYPE
:
997 /* RFC 7170, Section 4.2.12.6 - PAC-Type TLV */
1000 "EAP-TEAP: Invalid PAC-Type length %lu (expected 2)",
1001 (unsigned long) len
);
1002 wpa_hexdump_ascii(MSG_DEBUG
,
1003 "EAP-TEAP: PAC-Info - PAC-Type",
1007 pac_type
= WPA_GET_BE16(pos
);
1008 if (pac_type
!= PAC_TYPE_TUNNEL_PAC
) {
1009 wpa_printf(MSG_INFO
,
1010 "EAP-TEAP: Unsupported PAC Type %d",
1015 wpa_printf(MSG_DEBUG
, "EAP-TEAP: PAC-Info - PAC-Type %d",
1017 entry
->pac_type
= pac_type
;
1020 wpa_printf(MSG_DEBUG
,
1021 "EAP-TEAP: Ignored unknown PAC-Info type %d", type
);
1029 static int eap_teap_process_pac_info(struct eap_teap_pac
*entry
)
1031 struct pac_attr_hdr
*hdr
;
1036 /* RFC 7170, Section 4.2.12.4 */
1038 /* PAC-Type defaults to Tunnel PAC (Type 1) */
1039 entry
->pac_type
= PAC_TYPE_TUNNEL_PAC
;
1041 pos
= entry
->pac_info
;
1042 left
= entry
->pac_info_len
;
1043 while (left
> sizeof(*hdr
)) {
1044 hdr
= (struct pac_attr_hdr
*) pos
;
1045 type
= be_to_host16(hdr
->type
);
1046 len
= be_to_host16(hdr
->len
);
1047 pos
+= sizeof(*hdr
);
1048 left
-= sizeof(*hdr
);
1050 wpa_printf(MSG_DEBUG
,
1051 "EAP-TEAP: PAC-Info overrun (type=%d len=%lu left=%lu)",
1052 type
, (unsigned long) len
,
1053 (unsigned long) left
);
1057 if (eap_teap_parse_pac_info(entry
, type
, pos
, len
) < 0)
1064 if (!entry
->a_id
|| !entry
->a_id_info
) {
1065 wpa_printf(MSG_DEBUG
,
1066 "EAP-TEAP: PAC-Info does not include all the required fields");
1074 static struct wpabuf
* eap_teap_process_pac(struct eap_sm
*sm
,
1075 struct eap_teap_data
*data
,
1076 struct eap_method_ret
*ret
,
1077 u8
*pac
, size_t pac_len
)
1079 struct eap_peer_config
*config
= eap_get_config(sm
);
1080 struct eap_teap_pac entry
;
1082 os_memset(&entry
, 0, sizeof(entry
));
1083 if (eap_teap_process_pac_tlv(&entry
, pac
, pac_len
) ||
1084 eap_teap_process_pac_info(&entry
))
1087 eap_teap_add_pac(&data
->pac
, &data
->current_pac
, &entry
);
1088 eap_teap_pac_list_truncate(data
->pac
, data
->max_pac_list_len
);
1089 if (data
->use_pac_binary_format
)
1090 eap_teap_save_pac_bin(sm
, data
->pac
, config
->pac_file
);
1092 eap_teap_save_pac(sm
, data
->pac
, config
->pac_file
);
1094 wpa_printf(MSG_DEBUG
,
1095 "EAP-TEAP: Send PAC-Acknowledgement - %s initiated provisioning completed successfully",
1096 data
->provisioning
? "peer" : "server");
1097 return eap_teap_tlv_pac_ack();
1101 static int eap_teap_parse_decrypted(struct wpabuf
*decrypted
,
1102 struct eap_teap_tlv_parse
*tlv
,
1103 struct wpabuf
**resp
)
1110 os_memset(tlv
, 0, sizeof(*tlv
));
1112 /* Parse TLVs from the decrypted Phase 2 data */
1113 pos
= wpabuf_mhead(decrypted
);
1114 end
= pos
+ wpabuf_len(decrypted
);
1115 while (end
- pos
>= 4) {
1116 mandatory
= pos
[0] & 0x80;
1117 tlv_type
= WPA_GET_BE16(pos
) & 0x3fff;
1119 len
= WPA_GET_BE16(pos
);
1121 if (len
> (size_t) (end
- pos
)) {
1122 wpa_printf(MSG_INFO
, "EAP-TEAP: TLV overflow");
1125 wpa_printf(MSG_DEBUG
,
1126 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1127 tlv_type
, eap_teap_tlv_type_str(tlv_type
),
1129 mandatory
? " (mandatory)" : "");
1131 res
= eap_teap_parse_tlv(tlv
, tlv_type
, pos
, len
);
1136 wpa_printf(MSG_DEBUG
,
1137 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1139 *resp
= eap_teap_tlv_nak(0, tlv_type
);
1143 wpa_printf(MSG_DEBUG
,
1144 "EAP-TEAP: Ignore unknown optional TLV type %u",
1155 static struct wpabuf
* eap_teap_pac_request(void)
1158 struct teap_tlv_request_action
*act
;
1159 struct teap_tlv_hdr
*pac
;
1160 struct teap_attr_pac_type
*type
;
1162 req
= wpabuf_alloc(sizeof(*act
) + sizeof(*pac
) + sizeof(*type
));
1166 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add Request Action TLV (Process TLV)");
1167 act
= wpabuf_put(req
, sizeof(*act
));
1168 act
->tlv_type
= host_to_be16(TEAP_TLV_REQUEST_ACTION
);
1169 act
->length
= host_to_be16(2);
1170 act
->status
= TEAP_STATUS_SUCCESS
;
1171 act
->action
= TEAP_REQUEST_ACTION_PROCESS_TLV
;
1173 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (PAC-Type = Tunnel)");
1174 pac
= wpabuf_put(req
, sizeof(*pac
));
1175 pac
->tlv_type
= host_to_be16(TEAP_TLV_PAC
);
1176 pac
->length
= host_to_be16(sizeof(*type
));
1178 type
= wpabuf_put(req
, sizeof(*type
));
1179 type
->type
= host_to_be16(PAC_TYPE_PAC_TYPE
);
1180 type
->length
= host_to_be16(2);
1181 type
->pac_type
= host_to_be16(PAC_TYPE_TUNNEL_PAC
);
1187 static int eap_teap_process_decrypted(struct eap_sm
*sm
,
1188 struct eap_teap_data
*data
,
1189 struct eap_method_ret
*ret
,
1191 struct wpabuf
*decrypted
,
1192 struct wpabuf
**out_data
)
1194 struct wpabuf
*resp
= NULL
, *tmp
;
1195 struct eap_teap_tlv_parse tlv
;
1197 enum teap_error_codes error
= 0;
1198 int iresult_added
= 0;
1200 if (eap_teap_parse_decrypted(decrypted
, &tlv
, &resp
) < 0) {
1201 /* Parsing failed - no response available */
1206 /* Parsing rejected the message - send out an error response */
1210 if (tlv
.result
== TEAP_STATUS_FAILURE
) {
1211 /* Server indicated failure - respond similarly per
1212 * RFC 7170, 3.6.3. This authentication exchange cannot succeed
1213 * and will be terminated with a cleartext EAP Failure. */
1214 wpa_printf(MSG_DEBUG
,
1215 "EAP-TEAP: Server rejected authentication");
1216 resp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1217 ret
->methodState
= METHOD_DONE
;
1218 ret
->decision
= DECISION_FAIL
;
1222 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
&& !tlv
.crypto_binding
) {
1223 /* Intermediate-Result TLV indicating success, but no
1224 * Crypto-Binding TLV */
1225 wpa_printf(MSG_DEBUG
,
1226 "EAP-TEAP: Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
1228 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1232 if (!data
->iresult_verified
&& !data
->result_success_done
&&
1233 tlv
.result
== TEAP_STATUS_SUCCESS
&& !tlv
.crypto_binding
) {
1234 /* Result TLV indicating success, but no Crypto-Binding TLV */
1235 wpa_printf(MSG_DEBUG
,
1236 "EAP-TEAP: Result TLV indicating success, but no Crypto-Binding TLV");
1238 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1242 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1243 tlv
.iresult
!= TEAP_STATUS_FAILURE
&&
1244 data
->inner_method_done
) {
1245 wpa_printf(MSG_DEBUG
,
1246 "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
1248 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1252 if (tlv
.basic_auth_req
) {
1253 tmp
= eap_teap_process_basic_auth_req(sm
, data
,
1255 tlv
.basic_auth_req_len
);
1258 resp
= wpabuf_concat(resp
, tmp
);
1259 } else if (tlv
.eap_payload_tlv
) {
1260 tmp
= eap_teap_process_eap_payload_tlv(sm
, data
, ret
,
1261 tlv
.eap_payload_tlv
,
1262 tlv
.eap_payload_tlv_len
);
1265 resp
= wpabuf_concat(resp
, tmp
);
1267 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1268 tlv
.iresult
== TEAP_STATUS_FAILURE
) {
1269 tmp
= eap_teap_tlv_result(failed
?
1270 TEAP_STATUS_FAILURE
:
1271 TEAP_STATUS_SUCCESS
, 1);
1272 resp
= wpabuf_concat(resp
, tmp
);
1273 if (tlv
.iresult
== TEAP_STATUS_FAILURE
)
1279 if (tlv
.crypto_binding
) {
1280 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1281 tlv
.result
!= TEAP_STATUS_SUCCESS
) {
1282 wpa_printf(MSG_DEBUG
,
1283 "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
1285 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1289 tmp
= eap_teap_process_crypto_binding(sm
, data
, ret
,
1291 tlv
.crypto_binding_len
);
1294 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1296 resp
= wpabuf_concat(resp
, tmp
);
1297 if (tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
)
1298 data
->result_success_done
= 1;
1299 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
&& !failed
) {
1300 data
->inner_method_done
= 0;
1301 data
->iresult_verified
= 1;
1306 if (data
->result_success_done
&& data
->session_ticket_used
&&
1307 eap_teap_derive_msk(data
) == 0) {
1308 /* Assume the server might accept authentication without going
1309 * through inner authentication. */
1310 wpa_printf(MSG_DEBUG
,
1311 "EAP-TEAP: PAC used - server may decide to skip inner authentication");
1312 ret
->methodState
= METHOD_MAY_CONT
;
1313 ret
->decision
= DECISION_COND_SUCC
;
1317 if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1318 tmp
= eap_teap_process_pac(sm
, data
, ret
,
1319 tlv
.pac
, tlv
.pac_len
);
1320 resp
= wpabuf_concat(resp
, tmp
);
1322 wpa_printf(MSG_DEBUG
,
1323 "EAP-TEAP: PAC TLV without Result TLV acknowledging success");
1325 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1329 if (!data
->current_pac
&& data
->provisioning
&& !failed
&& !tlv
.pac
&&
1330 tlv
.crypto_binding
&&
1331 (!data
->anon_provisioning
||
1332 (data
->phase2_success
&& data
->phase2_method
&&
1333 data
->phase2_method
->vendor
== 0 &&
1334 eap_teap_allowed_anon_prov_cipher_suite(data
->tls_cs
) &&
1335 eap_teap_allowed_anon_prov_phase2_method(
1336 data
->phase2_method
->method
))) &&
1337 (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1338 tlv
.result
== TEAP_STATUS_SUCCESS
)) {
1340 * Need to request Tunnel PAC when using authenticated
1343 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Request Tunnel PAC");
1344 tmp
= eap_teap_pac_request();
1345 resp
= wpabuf_concat(resp
, tmp
);
1350 tmp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1351 resp
= wpabuf_concat(tmp
, resp
);
1354 tmp
= eap_teap_tlv_error(error
);
1355 resp
= wpabuf_concat(tmp
, resp
);
1358 ret
->methodState
= METHOD_DONE
;
1359 ret
->decision
= DECISION_FAIL
;
1360 } else if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1361 tmp
= eap_teap_tlv_result(TEAP_STATUS_SUCCESS
, 0);
1362 resp
= wpabuf_concat(tmp
, resp
);
1364 if ((tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1365 tlv
.iresult
== TEAP_STATUS_FAILURE
) && !iresult_added
) {
1366 tmp
= eap_teap_tlv_result((!failed
&& data
->phase2_success
) ?
1367 TEAP_STATUS_SUCCESS
:
1368 TEAP_STATUS_FAILURE
, 1);
1369 resp
= wpabuf_concat(tmp
, resp
);
1372 if (resp
&& tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
&&
1373 (tlv
.crypto_binding
|| data
->iresult_verified
) &&
1374 data
->phase2_success
) {
1375 /* Successfully completed Phase 2 */
1376 wpa_printf(MSG_DEBUG
,
1377 "EAP-TEAP: Authentication completed successfully");
1378 ret
->methodState
= METHOD_MAY_CONT
;
1379 data
->on_tx_completion
= data
->provisioning
?
1380 METHOD_MAY_CONT
: METHOD_DONE
;
1381 ret
->decision
= DECISION_UNCOND_SUCC
;
1385 wpa_printf(MSG_DEBUG
,
1386 "EAP-TEAP: No recognized TLVs - send empty response packet");
1387 resp
= wpabuf_alloc(1);
1394 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: Encrypting Phase 2 data", resp
);
1395 if (eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1396 data
->teap_version
, identifier
,
1398 wpa_printf(MSG_INFO
,
1399 "EAP-TEAP: Failed to encrypt a Phase 2 frame");
1407 static int eap_teap_decrypt(struct eap_sm
*sm
, struct eap_teap_data
*data
,
1408 struct eap_method_ret
*ret
, u8 identifier
,
1409 const struct wpabuf
*in_data
,
1410 struct wpabuf
**out_data
)
1412 struct wpabuf
*in_decrypted
;
1415 wpa_printf(MSG_DEBUG
,
1416 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1417 (unsigned long) wpabuf_len(in_data
));
1419 if (data
->pending_phase2_req
) {
1420 wpa_printf(MSG_DEBUG
,
1421 "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
1422 /* Clear TLS reassembly state. */
1423 eap_peer_tls_reset_input(&data
->ssl
);
1425 in_decrypted
= data
->pending_phase2_req
;
1426 data
->pending_phase2_req
= NULL
;
1430 if (wpabuf_len(in_data
) == 0) {
1431 /* Received TLS ACK - requesting more fragments */
1432 res
= eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1434 identifier
, NULL
, out_data
);
1435 if (res
== 0 && !data
->ssl
.tls_out
&&
1436 data
->on_tx_completion
) {
1437 wpa_printf(MSG_DEBUG
,
1438 "EAP-TEAP: Mark authentication completed at full TX of fragments");
1439 ret
->methodState
= data
->on_tx_completion
;
1440 data
->on_tx_completion
= 0;
1441 ret
->decision
= DECISION_UNCOND_SUCC
;
1446 res
= eap_peer_tls_decrypt(sm
, &data
->ssl
, in_data
, &in_decrypted
);
1451 wpa_hexdump_buf(MSG_MSGDUMP
, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
1454 if (wpabuf_len(in_decrypted
) < 4) {
1455 wpa_printf(MSG_INFO
,
1456 "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
1457 (unsigned long) wpabuf_len(in_decrypted
));
1458 wpabuf_free(in_decrypted
);
1462 res
= eap_teap_process_decrypted(sm
, data
, ret
, identifier
,
1463 in_decrypted
, out_data
);
1465 wpabuf_free(in_decrypted
);
1471 static void eap_teap_select_pac(struct eap_teap_data
*data
,
1472 const u8
*a_id
, size_t a_id_len
)
1476 data
->current_pac
= eap_teap_get_pac(data
->pac
, a_id
, a_id_len
,
1477 PAC_TYPE_TUNNEL_PAC
);
1478 if (data
->current_pac
) {
1479 wpa_printf(MSG_DEBUG
,
1480 "EAP-TEAP: PAC found for this A-ID (PAC-Type %d)",
1481 data
->current_pac
->pac_type
);
1482 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-TEAP: A-ID-Info",
1483 data
->current_pac
->a_id_info
,
1484 data
->current_pac
->a_id_info_len
);
1489 static int eap_teap_use_pac_opaque(struct eap_sm
*sm
,
1490 struct eap_teap_data
*data
,
1491 struct eap_teap_pac
*pac
)
1494 size_t tlv_len
, olen
;
1495 struct teap_tlv_hdr
*ehdr
;
1497 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC-Opaque TLS extension");
1498 olen
= pac
->pac_opaque_len
;
1499 tlv_len
= sizeof(*ehdr
) + olen
;
1500 tlv
= os_malloc(tlv_len
);
1502 ehdr
= (struct teap_tlv_hdr
*) tlv
;
1503 ehdr
->tlv_type
= host_to_be16(PAC_TYPE_PAC_OPAQUE
);
1504 ehdr
->length
= host_to_be16(olen
);
1505 os_memcpy(ehdr
+ 1, pac
->pac_opaque
, olen
);
1508 tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1510 tlv
, tlv_len
) < 0) {
1511 wpa_printf(MSG_DEBUG
,
1512 "EAP-TEAP: Failed to add PAC-Opaque TLS extension");
1522 static int eap_teap_clear_pac_opaque_ext(struct eap_sm
*sm
,
1523 struct eap_teap_data
*data
)
1525 if (tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1526 TLS_EXT_PAC_OPAQUE
, NULL
, 0) < 0) {
1527 wpa_printf(MSG_DEBUG
,
1528 "EAP-TEAP: Failed to remove PAC-Opaque TLS extension");
1535 static int eap_teap_process_start(struct eap_sm
*sm
,
1536 struct eap_teap_data
*data
, u8 flags
,
1537 const u8
*pos
, size_t left
)
1539 const u8
*a_id
= NULL
;
1540 size_t a_id_len
= 0;
1542 /* TODO: Support (mostly theoretical) case of TEAP/Start request being
1545 /* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
1546 data
->received_version
= flags
& EAP_TLS_VERSION_MASK
;
1547 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
1548 data
->received_version
, data
->teap_version
);
1549 if (data
->received_version
< 1) {
1550 /* Version 1 was the first defined version, so reject 0 */
1551 wpa_printf(MSG_INFO
,
1552 "EAP-TEAP: Server used unknown TEAP version %u",
1553 data
->received_version
);
1556 if (data
->received_version
< data
->teap_version
)
1557 data
->teap_version
= data
->received_version
;
1558 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Using TEAP version %d",
1559 data
->teap_version
);
1560 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message payload", pos
, left
);
1562 /* Parse Authority-ID TLV from Outer TLVs, if present */
1563 if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1564 const u8
*outer_pos
, *outer_end
;
1568 wpa_printf(MSG_INFO
,
1569 "EAP-TEAP: Not enough room for the Outer TLV Length field");
1573 outer_tlv_len
= WPA_GET_BE32(pos
);
1577 if (outer_tlv_len
> left
) {
1578 wpa_printf(MSG_INFO
,
1579 "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
1580 outer_tlv_len
, (unsigned int) left
);
1584 outer_pos
= pos
+ left
- outer_tlv_len
;
1585 outer_end
= outer_pos
+ outer_tlv_len
;
1586 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message Outer TLVs",
1587 outer_pos
, outer_tlv_len
);
1588 wpabuf_free(data
->server_outer_tlvs
);
1589 data
->server_outer_tlvs
= wpabuf_alloc_copy(outer_pos
,
1591 if (!data
->server_outer_tlvs
)
1593 left
-= outer_tlv_len
;
1595 wpa_hexdump(MSG_INFO
,
1596 "EAP-TEAP: Unexpected TLS Data in Start message",
1601 while (outer_pos
< outer_end
) {
1602 u16 tlv_type
, tlv_len
;
1604 if (outer_end
- outer_pos
< 4) {
1605 wpa_printf(MSG_INFO
,
1606 "EAP-TEAP: Truncated Outer TLV header");
1609 tlv_type
= WPA_GET_BE16(outer_pos
);
1611 tlv_len
= WPA_GET_BE16(outer_pos
);
1613 /* Outer TLVs are required to be optional, so no need to
1614 * check the M flag */
1615 tlv_type
&= TEAP_TLV_TYPE_MASK
;
1616 wpa_printf(MSG_DEBUG
,
1617 "EAP-TEAP: Outer TLV: Type=%u Length=%u",
1619 if (outer_end
- outer_pos
< tlv_len
) {
1620 wpa_printf(MSG_INFO
,
1621 "EAP-TEAP: Truncated Outer TLV (Type %u)",
1625 if (tlv_type
== TEAP_TLV_AUTHORITY_ID
) {
1626 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Authority-ID",
1627 outer_pos
, tlv_len
);
1629 wpa_printf(MSG_INFO
,
1630 "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
1636 wpa_printf(MSG_DEBUG
,
1637 "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
1640 outer_pos
+= tlv_len
;
1642 } else if (left
> 0) {
1643 wpa_hexdump(MSG_INFO
,
1644 "EAP-TEAP: Unexpected TLS Data in Start message",
1649 eap_teap_select_pac(data
, a_id
, a_id_len
);
1651 if (data
->resuming
&& data
->current_pac
) {
1652 wpa_printf(MSG_DEBUG
,
1653 "EAP-TEAP: Trying to resume session - do not add PAC-Opaque to TLS ClientHello");
1654 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1656 } else if (data
->current_pac
) {
1658 * PAC found for the A-ID and we are not resuming an old
1659 * session, so add PAC-Opaque extension to ClientHello.
1661 if (eap_teap_use_pac_opaque(sm
, data
, data
->current_pac
) < 0)
1663 } else if (data
->provisioning_allowed
) {
1664 wpa_printf(MSG_DEBUG
,
1665 "EAP-TEAP: No PAC found - starting provisioning");
1666 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1668 data
->provisioning
= 1;
1675 #ifdef CONFIG_TESTING_OPTIONS
1676 static struct wpabuf
* eap_teap_add_dummy_outer_tlvs(struct eap_teap_data
*data
,
1677 struct wpabuf
*resp
)
1679 struct wpabuf
*resp2
;
1684 wpabuf_free(data
->peer_outer_tlvs
);
1685 data
->peer_outer_tlvs
= wpabuf_alloc(4 + 4);
1686 if (!data
->peer_outer_tlvs
) {
1691 /* Outer TLVs (dummy Vendor-Specific TLV for testing) */
1692 wpabuf_put_be16(data
->peer_outer_tlvs
, TEAP_TLV_VENDOR_SPECIFIC
);
1693 wpabuf_put_be16(data
->peer_outer_tlvs
, 4);
1694 wpabuf_put_be32(data
->peer_outer_tlvs
, EAP_VENDOR_HOSTAP
);
1695 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
1696 data
->peer_outer_tlvs
);
1698 wpa_hexdump_buf(MSG_DEBUG
,
1699 "EAP-TEAP: TEAP/Start response before modification",
1701 resp2
= wpabuf_alloc(wpabuf_len(resp
) + 4 +
1702 wpabuf_len(data
->peer_outer_tlvs
));
1708 pos
= wpabuf_head(resp
);
1709 wpabuf_put_u8(resp2
, *pos
++); /* Code */
1710 wpabuf_put_u8(resp2
, *pos
++); /* Identifier */
1711 len
= WPA_GET_BE16(pos
);
1713 wpabuf_put_be16(resp2
, len
+ 4 + wpabuf_len(data
->peer_outer_tlvs
));
1714 wpabuf_put_u8(resp2
, *pos
++); /* Type */
1715 /* Flags | Ver (with Outer TLV length included flag set to 1) */
1717 if (flags
& (EAP_TEAP_FLAGS_OUTER_TLV_LEN
|
1718 EAP_TLS_FLAGS_LENGTH_INCLUDED
)) {
1719 wpa_printf(MSG_INFO
,
1720 "EAP-TEAP: Cannot add Outer TLVs for testing");
1725 flags
|= EAP_TEAP_FLAGS_OUTER_TLV_LEN
;
1726 wpabuf_put_u8(resp2
, flags
);
1727 /* Outer TLV Length */
1728 wpabuf_put_be32(resp2
, wpabuf_len(data
->peer_outer_tlvs
));
1730 wpabuf_put_data(resp2
, pos
, wpabuf_len(resp
) - 6);
1731 wpabuf_put_buf(resp2
, data
->peer_outer_tlvs
); /* Outer TLVs */
1734 wpa_hexdump_buf(MSG_DEBUG
,
1735 "EAP-TEAP: TEAP/Start response after modification",
1739 #endif /* CONFIG_TESTING_OPTIONS */
1742 static struct wpabuf
* eap_teap_process(struct eap_sm
*sm
, void *priv
,
1743 struct eap_method_ret
*ret
,
1744 const struct wpabuf
*reqData
)
1746 const struct eap_hdr
*req
;
1750 struct wpabuf
*resp
;
1752 struct eap_teap_data
*data
= priv
;
1755 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TEAP
, ret
,
1756 reqData
, &left
, &flags
);
1760 req
= wpabuf_head(reqData
);
1761 id
= req
->identifier
;
1763 if (flags
& EAP_TLS_FLAGS_START
) {
1764 if (eap_teap_process_start(sm
, data
, flags
, pos
, left
) < 0)
1767 /* Outer TLVs are not used in further packet processing and
1768 * there cannot be TLS Data in this TEAP/Start message, so
1769 * enforce that by ignoring whatever data might remain in the
1772 } else if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1773 /* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
1774 * Outer TLVs MUST be ignored instead of ignoring the full
1776 wpa_printf(MSG_INFO
,
1777 "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
1781 wpabuf_set(&msg
, pos
, left
);
1784 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
) &&
1786 /* Process tunneled (encrypted) phase 2 data. */
1787 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1789 ret
->methodState
= METHOD_DONE
;
1790 ret
->decision
= DECISION_FAIL
;
1792 * Ack possible Alert that may have caused failure in
1798 if (sm
->waiting_ext_cert_check
&& data
->pending_resp
) {
1799 struct eap_peer_config
*config
= eap_get_config(sm
);
1801 if (config
->pending_ext_cert_check
==
1802 EXT_CERT_CHECK_GOOD
) {
1803 wpa_printf(MSG_DEBUG
,
1804 "EAP-TEAP: External certificate check succeeded - continue handshake");
1805 resp
= data
->pending_resp
;
1806 data
->pending_resp
= NULL
;
1807 sm
->waiting_ext_cert_check
= 0;
1811 if (config
->pending_ext_cert_check
==
1812 EXT_CERT_CHECK_BAD
) {
1813 wpa_printf(MSG_DEBUG
,
1814 "EAP-TEAP: External certificate check failed - force authentication failure");
1815 ret
->methodState
= METHOD_DONE
;
1816 ret
->decision
= DECISION_FAIL
;
1817 sm
->waiting_ext_cert_check
= 0;
1821 wpa_printf(MSG_DEBUG
,
1822 "EAP-TEAP: Continuing to wait external server certificate validation");
1826 /* Continue processing TLS handshake (phase 1). */
1827 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
,
1829 data
->teap_version
, id
, &msg
,
1832 wpa_printf(MSG_DEBUG
,
1833 "EAP-TEAP: TLS processing failed");
1834 ret
->methodState
= METHOD_DONE
;
1835 ret
->decision
= DECISION_FAIL
;
1839 if (sm
->waiting_ext_cert_check
) {
1840 wpa_printf(MSG_DEBUG
,
1841 "EAP-TEAP: Waiting external server certificate validation");
1842 wpabuf_free(data
->pending_resp
);
1843 data
->pending_resp
= resp
;
1847 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1850 wpa_printf(MSG_DEBUG
,
1851 "EAP-TEAP: TLS done, proceed to Phase 2");
1853 tls_connection_get_cipher_suite(data
->ssl
.conn
);
1854 wpa_printf(MSG_DEBUG
,
1855 "EAP-TEAP: TLS cipher suite 0x%04x",
1858 if (data
->provisioning
&&
1859 (!(data
->provisioning_allowed
&
1860 EAP_TEAP_PROV_AUTH
) ||
1861 tls_get_cipher(sm
->ssl_ctx
, data
->ssl
.conn
,
1862 cipher
, sizeof(cipher
)) < 0 ||
1863 os_strstr(cipher
, "ADH-") ||
1864 os_strstr(cipher
, "anon"))) {
1865 wpa_printf(MSG_DEBUG
,
1866 "EAP-TEAP: Using anonymous (unauthenticated) provisioning");
1867 data
->anon_provisioning
= 1;
1869 data
->anon_provisioning
= 0;
1872 if (eap_teap_derive_key_auth(sm
, data
) < 0) {
1873 wpa_printf(MSG_DEBUG
,
1874 "EAP-TEAP: Could not derive keys");
1875 ret
->methodState
= METHOD_DONE
;
1876 ret
->decision
= DECISION_FAIL
;
1884 * Application data included in the handshake message.
1886 wpabuf_free(data
->pending_phase2_req
);
1887 data
->pending_phase2_req
= resp
;
1889 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1895 return eap_peer_tls_build_ack(id
, EAP_TYPE_TEAP
,
1896 data
->teap_version
);
1899 #ifdef CONFIG_TESTING_OPTIONS
1900 if (data
->test_outer_tlvs
&& res
== 0 && resp
&&
1901 (flags
& EAP_TLS_FLAGS_START
) && wpabuf_len(resp
) >= 6)
1902 resp
= eap_teap_add_dummy_outer_tlvs(data
, resp
);
1903 #endif /* CONFIG_TESTING_OPTIONS */
1910 static Boolean
eap_teap_has_reauth_data(struct eap_sm
*sm
, void *priv
)
1912 struct eap_teap_data
*data
= priv
;
1914 return tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
);
1918 static void eap_teap_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
1920 struct eap_teap_data
*data
= priv
;
1922 if (data
->phase2_priv
&& data
->phase2_method
&&
1923 data
->phase2_method
->deinit_for_reauth
)
1924 data
->phase2_method
->deinit_for_reauth(sm
, data
->phase2_priv
);
1925 eap_teap_clear(data
);
1929 static void * eap_teap_init_for_reauth(struct eap_sm
*sm
, void *priv
)
1931 struct eap_teap_data
*data
= priv
;
1933 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
1934 eap_teap_deinit(sm
, data
);
1937 if (data
->phase2_priv
&& data
->phase2_method
&&
1938 data
->phase2_method
->init_for_reauth
)
1939 data
->phase2_method
->init_for_reauth(sm
, data
->phase2_priv
);
1940 data
->phase2_success
= 0;
1941 data
->inner_method_done
= 0;
1942 data
->result_success_done
= 0;
1943 data
->iresult_verified
= 0;
1944 data
->done_on_tx_completion
= 0;
1946 data
->provisioning
= 0;
1947 data
->anon_provisioning
= 0;
1948 data
->simck_idx
= 0;
1954 static int eap_teap_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
1955 size_t buflen
, int verbose
)
1957 struct eap_teap_data
*data
= priv
;
1960 len
= eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
1961 if (data
->phase2_method
) {
1962 ret
= os_snprintf(buf
+ len
, buflen
- len
,
1963 "EAP-TEAP Phase 2 method=%s\n",
1964 data
->phase2_method
->name
);
1965 if (os_snprintf_error(buflen
- len
, ret
))
1973 static Boolean
eap_teap_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
1975 struct eap_teap_data
*data
= priv
;
1977 return data
->success
;
1981 static u8
* eap_teap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1983 struct eap_teap_data
*data
= priv
;
1989 key
= os_memdup(data
->key_data
, EAP_TEAP_KEY_LEN
);
1993 *len
= EAP_TEAP_KEY_LEN
;
1999 static u8
* eap_teap_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
2001 struct eap_teap_data
*data
= priv
;
2004 if (!data
->success
|| !data
->session_id
)
2007 id
= os_memdup(data
->session_id
, data
->id_len
);
2011 *len
= data
->id_len
;
2017 static u8
* eap_teap_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
2019 struct eap_teap_data
*data
= priv
;
2025 key
= os_memdup(data
->emsk
, EAP_EMSK_LEN
);
2029 *len
= EAP_EMSK_LEN
;
2035 int eap_peer_teap_register(void)
2037 struct eap_method
*eap
;
2039 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
2040 EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, "TEAP");
2044 eap
->init
= eap_teap_init
;
2045 eap
->deinit
= eap_teap_deinit
;
2046 eap
->process
= eap_teap_process
;
2047 eap
->isKeyAvailable
= eap_teap_isKeyAvailable
;
2048 eap
->getKey
= eap_teap_getKey
;
2049 eap
->getSessionId
= eap_teap_get_session_id
;
2050 eap
->get_status
= eap_teap_get_status
;
2052 eap
->has_reauth_data
= eap_teap_has_reauth_data
;
2053 eap
->deinit_for_reauth
= eap_teap_deinit_for_reauth
;
2054 eap
->init_for_reauth
= eap_teap_init_for_reauth
;
2056 eap
->get_emsk
= eap_teap_get_emsk
;
2058 return eap_peer_method_register(eap
);