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
;
38 int result_success_done
;
41 struct eap_method_type phase2_type
;
42 struct eap_method_type
*phase2_types
;
43 size_t num_phase2_types
;
44 int resuming
; /* starting a resumed session */
45 #define EAP_TEAP_PROV_UNAUTH 1
46 #define EAP_TEAP_PROV_AUTH 2
47 int provisioning_allowed
; /* Allowed PAC provisioning modes */
48 int provisioning
; /* doing PAC provisioning (not the normal auth) */
49 int anon_provisioning
; /* doing anonymous (unauthenticated)
51 int session_ticket_used
;
54 u8 key_data
[EAP_TEAP_KEY_LEN
];
57 u8 emsk
[EAP_EMSK_LEN
];
60 struct eap_teap_pac
*pac
;
61 struct eap_teap_pac
*current_pac
;
62 size_t max_pac_list_len
;
63 int use_pac_binary_format
;
65 u8 simck_msk
[EAP_TEAP_SIMCK_LEN
];
66 u8 simck_emsk
[EAP_TEAP_SIMCK_LEN
];
68 int cmk_emsk_available
;
70 struct wpabuf
*pending_phase2_req
;
71 struct wpabuf
*pending_resp
;
72 struct wpabuf
*server_outer_tlvs
;
73 struct wpabuf
*peer_outer_tlvs
;
77 static int eap_teap_session_ticket_cb(void *ctx
, const u8
*ticket
, size_t len
,
78 const u8
*client_random
,
79 const u8
*server_random
,
82 struct eap_teap_data
*data
= ctx
;
84 wpa_printf(MSG_DEBUG
, "EAP-TEAP: SessionTicket callback");
88 "EAP-TEAP: SessionTicket failed - fall back to full TLS handshake");
89 data
->session_ticket_used
= 0;
90 if (data
->provisioning_allowed
) {
92 "EAP-TEAP: Try to provision a new PAC-Key");
93 data
->provisioning
= 1;
94 data
->current_pac
= NULL
;
99 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: SessionTicket", ticket
, len
);
101 if (!data
->current_pac
) {
102 wpa_printf(MSG_DEBUG
,
103 "EAP-TEAP: No PAC-Key available for using SessionTicket");
104 data
->session_ticket_used
= 0;
108 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
109 os_memcpy(master_secret
, data
->current_pac
->pac_key
,
110 EAP_TEAP_PAC_KEY_LEN
);
112 data
->session_ticket_used
= 1;
118 static void eap_teap_parse_phase1(struct eap_teap_data
*data
,
123 pos
= os_strstr(phase1
, "teap_provisioning=");
125 data
->provisioning_allowed
= atoi(pos
+ 18);
126 wpa_printf(MSG_DEBUG
,
127 "EAP-TEAP: Automatic PAC provisioning mode: %d",
128 data
->provisioning_allowed
);
131 pos
= os_strstr(phase1
, "teap_max_pac_list_len=");
133 data
->max_pac_list_len
= atoi(pos
+ 22);
134 if (data
->max_pac_list_len
== 0)
135 data
->max_pac_list_len
= 1;
136 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Maximum PAC list length: %lu",
137 (unsigned long) data
->max_pac_list_len
);
140 if (os_strstr(phase1
, "teap_pac_format=binary")) {
141 data
->use_pac_binary_format
= 1;
142 wpa_printf(MSG_DEBUG
,
143 "EAP-TEAP: Using binary format for PAC list");
146 #ifdef CONFIG_TESTING_OPTIONS
147 if (os_strstr(phase1
, "teap_test_outer_tlvs=1"))
148 data
->test_outer_tlvs
= 1;
149 #endif /* CONFIG_TESTING_OPTIONS */
153 static void * eap_teap_init(struct eap_sm
*sm
)
155 struct eap_teap_data
*data
;
156 struct eap_peer_config
*config
= eap_get_config(sm
);
161 data
= os_zalloc(sizeof(*data
));
164 data
->teap_version
= EAP_TEAP_VERSION
;
165 data
->max_pac_list_len
= 10;
168 eap_teap_parse_phase1(data
, config
->phase1
);
170 if ((data
->provisioning_allowed
& EAP_TEAP_PROV_AUTH
) &&
171 !config
->ca_cert
&& !config
->ca_path
) {
172 /* Prevent PAC provisioning without mutual authentication
173 * (either by validating server certificate or by suitable
174 * inner EAP method). */
176 "EAP-TEAP: Disable authenticated provisioning due to no ca_cert/ca_path");
177 data
->provisioning_allowed
&= ~EAP_TEAP_PROV_AUTH
;
180 if (eap_peer_select_phase2_methods(config
, "auth=",
182 &data
->num_phase2_types
) < 0) {
183 eap_teap_deinit(sm
, data
);
187 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
188 data
->phase2_type
.method
= EAP_TYPE_NONE
;
190 config
->teap_anon_dh
= !!(data
->provisioning_allowed
&
191 EAP_TEAP_PROV_UNAUTH
);
192 if (eap_peer_tls_ssl_init(sm
, &data
->ssl
, config
, EAP_TYPE_TEAP
)) {
193 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to initialize SSL");
194 eap_teap_deinit(sm
, data
);
198 if (tls_connection_set_session_ticket_cb(sm
->ssl_ctx
, data
->ssl
.conn
,
199 eap_teap_session_ticket_cb
,
202 "EAP-TEAP: Failed to set SessionTicket callback");
203 eap_teap_deinit(sm
, data
);
207 if (!config
->pac_file
) {
208 wpa_printf(MSG_INFO
, "EAP-TEAP: No PAC file configured");
209 eap_teap_deinit(sm
, data
);
213 if (data
->use_pac_binary_format
&&
214 eap_teap_load_pac_bin(sm
, &data
->pac
, config
->pac_file
) < 0) {
215 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to load PAC file");
216 eap_teap_deinit(sm
, data
);
220 if (!data
->use_pac_binary_format
&&
221 eap_teap_load_pac(sm
, &data
->pac
, config
->pac_file
) < 0) {
222 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to load PAC file");
223 eap_teap_deinit(sm
, data
);
226 eap_teap_pac_list_truncate(data
->pac
, data
->max_pac_list_len
);
232 static void eap_teap_clear(struct eap_teap_data
*data
)
234 forced_memzero(data
->key_data
, EAP_TEAP_KEY_LEN
);
235 forced_memzero(data
->emsk
, EAP_EMSK_LEN
);
236 os_free(data
->session_id
);
237 data
->session_id
= NULL
;
238 wpabuf_free(data
->pending_phase2_req
);
239 data
->pending_phase2_req
= NULL
;
240 wpabuf_free(data
->pending_resp
);
241 data
->pending_resp
= NULL
;
242 wpabuf_free(data
->server_outer_tlvs
);
243 data
->server_outer_tlvs
= NULL
;
244 wpabuf_free(data
->peer_outer_tlvs
);
245 data
->peer_outer_tlvs
= NULL
;
246 forced_memzero(data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
247 forced_memzero(data
->simck_emsk
, EAP_TEAP_SIMCK_LEN
);
251 static void eap_teap_deinit(struct eap_sm
*sm
, void *priv
)
253 struct eap_teap_data
*data
= priv
;
254 struct eap_teap_pac
*pac
, *prev
;
258 if (data
->phase2_priv
&& data
->phase2_method
)
259 data
->phase2_method
->deinit(sm
, data
->phase2_priv
);
260 eap_teap_clear(data
);
261 os_free(data
->phase2_types
);
262 eap_peer_tls_ssl_deinit(sm
, &data
->ssl
);
269 eap_teap_free_pac(prev
);
276 static int eap_teap_derive_msk(struct eap_teap_data
*data
)
278 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
279 * is used in this derivation */
280 if (eap_teap_derive_eap_msk(data
->tls_cs
, data
->simck_msk
,
281 data
->key_data
) < 0 ||
282 eap_teap_derive_eap_emsk(data
->tls_cs
, data
->simck_msk
,
290 static int eap_teap_derive_key_auth(struct eap_sm
*sm
,
291 struct eap_teap_data
*data
)
295 /* RFC 7170, Section 5.1 */
296 res
= tls_connection_export_key(sm
->ssl_ctx
, data
->ssl
.conn
,
297 TEAP_TLS_EXPORTER_LABEL_SKS
, NULL
, 0,
298 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
301 wpa_hexdump_key(MSG_DEBUG
,
302 "EAP-TEAP: session_key_seed (S-IMCK[0])",
303 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
304 os_memcpy(data
->simck_emsk
, data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
310 static int eap_teap_init_phase2_method(struct eap_sm
*sm
,
311 struct eap_teap_data
*data
)
313 data
->inner_method_done
= 0;
314 data
->phase2_method
=
315 eap_peer_get_eap_method(data
->phase2_type
.vendor
,
316 data
->phase2_type
.method
);
317 if (!data
->phase2_method
)
321 data
->phase2_priv
= data
->phase2_method
->init(sm
);
324 return data
->phase2_priv
== NULL
? -1 : 0;
328 static int eap_teap_select_phase2_method(struct eap_teap_data
*data
, u8 type
)
332 /* TODO: TNC with anonymous provisioning; need to require both
333 * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
335 if (data
->anon_provisioning
&&
336 !eap_teap_allowed_anon_prov_phase2_method(type
)) {
338 "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
344 if (type
== EAP_TYPE_TNC
) {
345 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
346 data
->phase2_type
.method
= EAP_TYPE_TNC
;
347 wpa_printf(MSG_DEBUG
,
348 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
349 data
->phase2_type
.vendor
,
350 data
->phase2_type
.method
);
355 for (i
= 0; i
< data
->num_phase2_types
; i
++) {
356 if (data
->phase2_types
[i
].vendor
!= EAP_VENDOR_IETF
||
357 data
->phase2_types
[i
].method
!= type
)
360 data
->phase2_type
.vendor
= data
->phase2_types
[i
].vendor
;
361 data
->phase2_type
.method
= data
->phase2_types
[i
].method
;
362 wpa_printf(MSG_DEBUG
,
363 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
364 data
->phase2_type
.vendor
,
365 data
->phase2_type
.method
);
369 if (type
!= data
->phase2_type
.method
|| type
== EAP_TYPE_NONE
)
376 static int eap_teap_phase2_request(struct eap_sm
*sm
,
377 struct eap_teap_data
*data
,
378 struct eap_method_ret
*ret
,
380 struct wpabuf
**resp
)
382 size_t len
= be_to_host16(hdr
->length
);
384 struct eap_method_ret iret
;
385 struct eap_peer_config
*config
= eap_get_config(sm
);
388 if (len
<= sizeof(struct eap_hdr
)) {
390 "EAP-TEAP: too short Phase 2 request (len=%lu)",
391 (unsigned long) len
);
394 pos
= (u8
*) (hdr
+ 1);
395 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 2 Request: type=%d", *pos
);
396 if (*pos
== EAP_TYPE_IDENTITY
) {
397 *resp
= eap_sm_buildIdentity(sm
, hdr
->identifier
, 1);
401 if (data
->phase2_priv
&& data
->phase2_method
&&
402 *pos
!= data
->phase2_type
.method
) {
403 wpa_printf(MSG_DEBUG
,
404 "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
405 data
->phase2_method
->deinit(sm
, data
->phase2_priv
);
406 data
->phase2_method
= NULL
;
407 data
->phase2_priv
= NULL
;
408 data
->phase2_type
.vendor
= EAP_VENDOR_IETF
;
409 data
->phase2_type
.method
= EAP_TYPE_NONE
;
412 if (data
->phase2_type
.vendor
== EAP_VENDOR_IETF
&&
413 data
->phase2_type
.method
== EAP_TYPE_NONE
&&
414 eap_teap_select_phase2_method(data
, *pos
) < 0) {
415 if (eap_peer_tls_phase2_nak(data
->phase2_types
,
416 data
->num_phase2_types
,
422 if ((!data
->phase2_priv
&& eap_teap_init_phase2_method(sm
, data
) < 0) ||
423 !data
->phase2_method
) {
425 "EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
427 ret
->methodState
= METHOD_DONE
;
428 ret
->decision
= DECISION_FAIL
;
432 os_memset(&iret
, 0, sizeof(iret
));
433 wpabuf_set(&msg
, hdr
, len
);
434 *resp
= data
->phase2_method
->process(sm
, data
->phase2_priv
, &iret
,
436 if (iret
.methodState
== METHOD_DONE
)
437 data
->inner_method_done
= 1;
439 (iret
.methodState
== METHOD_DONE
&&
440 iret
.decision
== DECISION_FAIL
)) {
441 ret
->methodState
= METHOD_DONE
;
442 ret
->decision
= DECISION_FAIL
;
443 } else if ((iret
.methodState
== METHOD_DONE
||
444 iret
.methodState
== METHOD_MAY_CONT
) &&
445 (iret
.decision
== DECISION_UNCOND_SUCC
||
446 iret
.decision
== DECISION_COND_SUCC
)) {
447 data
->phase2_success
= 1;
450 if (!(*resp
) && config
&&
451 (config
->pending_req_identity
|| config
->pending_req_password
||
452 config
->pending_req_otp
|| config
->pending_req_new_password
||
453 config
->pending_req_sim
)) {
454 wpabuf_free(data
->pending_phase2_req
);
455 data
->pending_phase2_req
= wpabuf_alloc_copy(hdr
, len
);
463 static struct wpabuf
* eap_teap_tlv_nak(int vendor_id
, int tlv_type
)
466 struct teap_tlv_nak
*nak
;
468 wpa_printf(MSG_DEBUG
,
469 "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
470 vendor_id
, tlv_type
);
471 buf
= wpabuf_alloc(sizeof(*nak
));
474 nak
= wpabuf_put(buf
, sizeof(*nak
));
475 nak
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
| TEAP_TLV_NAK
);
476 nak
->length
= host_to_be16(6);
477 nak
->vendor_id
= host_to_be32(vendor_id
);
478 nak
->nak_type
= host_to_be16(tlv_type
);
483 static struct wpabuf
* eap_teap_tlv_pac_ack(void)
486 struct teap_tlv_result
*res
;
487 struct teap_tlv_pac_ack
*ack
;
489 buf
= wpabuf_alloc(sizeof(*res
) + sizeof(*ack
));
493 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (ack)");
494 ack
= wpabuf_put(buf
, sizeof(*ack
));
495 ack
->tlv_type
= host_to_be16(TEAP_TLV_PAC
| TEAP_TLV_MANDATORY
);
496 ack
->length
= host_to_be16(sizeof(*ack
) - sizeof(struct teap_tlv_hdr
));
497 ack
->pac_type
= host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT
);
498 ack
->pac_len
= host_to_be16(2);
499 ack
->result
= host_to_be16(TEAP_STATUS_SUCCESS
);
505 static struct wpabuf
* eap_teap_process_eap_payload_tlv(
506 struct eap_sm
*sm
, struct eap_teap_data
*data
,
507 struct eap_method_ret
*ret
,
508 u8
*eap_payload_tlv
, size_t eap_payload_tlv_len
)
511 struct wpabuf
*resp
= NULL
;
513 if (eap_payload_tlv_len
< sizeof(*hdr
)) {
514 wpa_printf(MSG_DEBUG
,
515 "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
516 (unsigned long) eap_payload_tlv_len
);
520 hdr
= (struct eap_hdr
*) eap_payload_tlv
;
521 if (be_to_host16(hdr
->length
) > eap_payload_tlv_len
) {
522 wpa_printf(MSG_DEBUG
,
523 "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
527 if (hdr
->code
!= EAP_CODE_REQUEST
) {
529 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
534 if (eap_teap_phase2_request(sm
, data
, ret
, hdr
, &resp
)) {
536 "EAP-TEAP: Phase 2 Request processing failed");
540 return eap_teap_tlv_eap_payload(resp
);
544 static struct wpabuf
* eap_teap_process_basic_auth_req(
545 struct eap_sm
*sm
, struct eap_teap_data
*data
,
546 u8
*basic_auth_req
, size_t basic_auth_req_len
)
548 const u8
*identity
, *password
;
549 size_t identity_len
, password_len
, plen
;
552 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Req prompt",
553 basic_auth_req
, basic_auth_req_len
);
554 /* TODO: send over control interface */
556 identity
= eap_get_config_identity(sm
, &identity_len
);
557 password
= eap_get_config_password(sm
, &password_len
);
558 if (!identity
|| !password
||
559 identity_len
> 255 || password_len
> 255) {
560 wpa_printf(MSG_DEBUG
,
561 "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
562 return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ
);
565 plen
= 1 + identity_len
+ 1 + password_len
;
566 resp
= wpabuf_alloc(sizeof(struct teap_tlv_hdr
) + plen
);
569 eap_teap_put_tlv_hdr(resp
, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP
, plen
);
570 wpabuf_put_u8(resp
, identity_len
);
571 wpabuf_put_data(resp
, identity
, identity_len
);
572 wpabuf_put_u8(resp
, password_len
);
573 wpabuf_put_data(resp
, password
, password_len
);
574 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Basic-Password-Auth-Resp",
577 /* Assume this succeeds so that Result TLV(Success) from the server can
578 * be used to terminate TEAP. */
579 data
->phase2_success
= 1;
586 eap_teap_validate_crypto_binding(struct eap_teap_data
*data
,
587 const struct teap_tlv_crypto_binding
*cb
)
591 subtype
= cb
->subtype
& 0x0f;
592 flags
= cb
->subtype
>> 4;
594 wpa_printf(MSG_DEBUG
,
595 "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
596 cb
->version
, cb
->received_version
, flags
, subtype
);
597 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
598 cb
->nonce
, sizeof(cb
->nonce
));
599 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
600 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
601 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
602 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
604 if (cb
->version
!= EAP_TEAP_VERSION
||
605 cb
->received_version
!= data
->received_version
||
606 subtype
!= TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST
||
607 flags
< 1 || flags
> 3) {
609 "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
610 cb
->version
, cb
->received_version
, flags
, subtype
);
614 if (cb
->nonce
[EAP_TEAP_NONCE_LEN
- 1] & 0x01) {
616 "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
624 static int eap_teap_write_crypto_binding(
625 struct eap_teap_data
*data
,
626 struct teap_tlv_crypto_binding
*rbind
,
627 const struct teap_tlv_crypto_binding
*cb
,
628 const u8
*cmk_msk
, const u8
*cmk_emsk
)
632 rbind
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
633 TEAP_TLV_CRYPTO_BINDING
);
634 rbind
->length
= host_to_be16(sizeof(*rbind
) -
635 sizeof(struct teap_tlv_hdr
));
636 rbind
->version
= EAP_TEAP_VERSION
;
637 rbind
->received_version
= data
->received_version
;
638 /* FIX: RFC 7170 is not clear on which Flags value to use when
639 * Crypto-Binding TLV is used with Basic-Password-Auth */
640 flags
= cmk_emsk
? TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
:
641 TEAP_CRYPTO_BINDING_MSK_CMAC
;
642 subtype
= TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE
;
643 rbind
->subtype
= (flags
<< 4) | subtype
;
644 os_memcpy(rbind
->nonce
, cb
->nonce
, sizeof(cb
->nonce
));
645 inc_byte_array(rbind
->nonce
, sizeof(rbind
->nonce
));
646 os_memset(rbind
->emsk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
647 os_memset(rbind
->msk_compound_mac
, 0, EAP_TEAP_COMPOUND_MAC_LEN
);
649 if (eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
650 data
->peer_outer_tlvs
, cmk_msk
,
651 rbind
->msk_compound_mac
) < 0)
654 eap_teap_compound_mac(data
->tls_cs
, rbind
, data
->server_outer_tlvs
,
655 data
->peer_outer_tlvs
, cmk_emsk
,
656 rbind
->emsk_compound_mac
) < 0)
659 wpa_printf(MSG_DEBUG
,
660 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
661 rbind
->version
, rbind
->received_version
, flags
, subtype
);
662 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
663 rbind
->nonce
, sizeof(rbind
->nonce
));
664 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
665 rbind
->emsk_compound_mac
, sizeof(rbind
->emsk_compound_mac
));
666 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
667 rbind
->msk_compound_mac
, sizeof(rbind
->msk_compound_mac
));
673 static int eap_teap_get_cmk(struct eap_sm
*sm
, struct eap_teap_data
*data
,
674 u8
*cmk_msk
, u8
*cmk_emsk
)
676 u8
*msk
= NULL
, *emsk
= NULL
;
677 size_t msk_len
= 0, emsk_len
= 0;
680 wpa_printf(MSG_DEBUG
,
681 "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
682 data
->simck_idx
+ 1);
684 if (!data
->phase2_method
)
685 return eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
689 if (!data
->phase2_method
|| !data
->phase2_priv
) {
690 wpa_printf(MSG_INFO
, "EAP-TEAP: Phase 2 method not available");
694 if (data
->phase2_method
->isKeyAvailable
&&
695 !data
->phase2_method
->isKeyAvailable(sm
, data
->phase2_priv
)) {
697 "EAP-TEAP: Phase 2 key material not available");
701 if (data
->phase2_method
->isKeyAvailable
&&
702 data
->phase2_method
->getKey
) {
703 msk
= data
->phase2_method
->getKey(sm
, data
->phase2_priv
,
707 "EAP-TEAP: Could not fetch Phase 2 MSK");
712 if (data
->phase2_method
->isKeyAvailable
&&
713 data
->phase2_method
->get_emsk
) {
714 emsk
= data
->phase2_method
->get_emsk(sm
, data
->phase2_priv
,
718 res
= eap_teap_derive_imck(data
->tls_cs
,
719 data
->simck_msk
, data
->simck_emsk
,
720 msk
, msk_len
, emsk
, emsk_len
,
721 data
->simck_msk
, cmk_msk
,
722 data
->simck_emsk
, cmk_emsk
);
723 bin_clear_free(msk
, msk_len
);
724 bin_clear_free(emsk
, emsk_len
);
728 data
->cmk_emsk_available
= 1;
734 static int eap_teap_session_id(struct eap_teap_data
*data
)
736 const size_t max_id_len
= 100;
739 os_free(data
->session_id
);
740 data
->session_id
= os_malloc(max_id_len
);
741 if (!data
->session_id
)
744 data
->session_id
[0] = EAP_TYPE_TEAP
;
745 res
= tls_get_tls_unique(data
->ssl
.conn
, data
->session_id
+ 1,
748 os_free(data
->session_id
);
749 data
->session_id
= NULL
;
750 wpa_printf(MSG_ERROR
, "EAP-TEAP: Failed to derive Session-Id");
754 data
->id_len
= 1 + res
;
755 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Derived Session-Id",
756 data
->session_id
, data
->id_len
);
761 static struct wpabuf
* eap_teap_process_crypto_binding(
762 struct eap_sm
*sm
, struct eap_teap_data
*data
,
763 struct eap_method_ret
*ret
,
764 const struct teap_tlv_crypto_binding
*cb
, size_t bind_len
)
768 u8 cmk_msk
[EAP_TEAP_CMK_LEN
];
769 u8 cmk_emsk
[EAP_TEAP_CMK_LEN
];
770 const u8
*cmk_emsk_ptr
= NULL
;
775 if (eap_teap_validate_crypto_binding(data
, cb
) < 0 ||
776 eap_teap_get_cmk(sm
, data
, cmk_msk
, cmk_emsk
) < 0)
779 /* Validate received MSK/EMSK Compound MAC */
780 flags
= cb
->subtype
>> 4;
782 if (flags
== TEAP_CRYPTO_BINDING_MSK_CMAC
||
783 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) {
784 u8 msk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
786 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
787 data
->server_outer_tlvs
,
788 data
->peer_outer_tlvs
, cmk_msk
,
789 msk_compound_mac
) < 0)
791 res
= os_memcmp_const(msk_compound_mac
, cb
->msk_compound_mac
,
792 EAP_TEAP_COMPOUND_MAC_LEN
);
793 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received MSK Compound MAC",
794 cb
->msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
795 wpa_hexdump(MSG_MSGDUMP
,
796 "EAP-TEAP: Calculated MSK Compound MAC",
797 msk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
800 "EAP-TEAP: MSK Compound MAC did not match");
805 if ((flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
||
806 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) &&
807 data
->cmk_emsk_available
) {
808 u8 emsk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
810 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
811 data
->server_outer_tlvs
,
812 data
->peer_outer_tlvs
, cmk_emsk
,
813 emsk_compound_mac
) < 0)
815 res
= os_memcmp_const(emsk_compound_mac
, cb
->emsk_compound_mac
,
816 EAP_TEAP_COMPOUND_MAC_LEN
);
817 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Received EMSK Compound MAC",
818 cb
->emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
819 wpa_hexdump(MSG_MSGDUMP
,
820 "EAP-TEAP: Calculated EMSK Compound MAC",
821 emsk_compound_mac
, EAP_TEAP_COMPOUND_MAC_LEN
);
824 "EAP-TEAP: EMSK Compound MAC did not match");
828 cmk_emsk_ptr
= cmk_emsk
;
831 if (flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
&&
832 !data
->cmk_emsk_available
) {
834 "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
839 * Compound MAC was valid, so authentication succeeded. Reply with
840 * crypto binding to allow server to complete authentication.
843 len
= sizeof(struct teap_tlv_crypto_binding
);
844 resp
= wpabuf_alloc(len
);
848 if (data
->phase2_success
&& eap_teap_derive_msk(data
) < 0) {
849 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to generate MSK");
850 ret
->methodState
= METHOD_DONE
;
851 ret
->decision
= DECISION_FAIL
;
852 data
->phase2_success
= 0;
857 if (data
->phase2_success
&& eap_teap_session_id(data
) < 0) {
862 pos
= wpabuf_put(resp
, sizeof(struct teap_tlv_crypto_binding
));
863 if (eap_teap_write_crypto_binding(
864 data
, (struct teap_tlv_crypto_binding
*) pos
,
865 cb
, cmk_msk
, cmk_emsk_ptr
) < 0) {
874 static void eap_teap_parse_pac_tlv(struct eap_teap_pac
*entry
, int type
,
875 u8
*pos
, size_t len
, int *pac_key_found
)
877 switch (type
& 0x7fff) {
878 case PAC_TYPE_PAC_KEY
:
879 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: PAC-Key", pos
, len
);
880 if (len
!= EAP_TEAP_PAC_KEY_LEN
) {
881 wpa_printf(MSG_DEBUG
,
882 "EAP-TEAP: Invalid PAC-Key length %lu",
883 (unsigned long) len
);
887 os_memcpy(entry
->pac_key
, pos
, len
);
889 case PAC_TYPE_PAC_OPAQUE
:
890 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque", pos
, len
);
891 entry
->pac_opaque
= pos
;
892 entry
->pac_opaque_len
= len
;
894 case PAC_TYPE_PAC_INFO
:
895 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Info", pos
, len
);
896 entry
->pac_info
= pos
;
897 entry
->pac_info_len
= len
;
900 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Ignored unknown PAC type %d",
907 static int eap_teap_process_pac_tlv(struct eap_teap_pac
*entry
,
908 u8
*pac
, size_t pac_len
)
910 struct pac_attr_hdr
*hdr
;
913 int type
, pac_key_found
= 0;
918 while (left
> sizeof(*hdr
)) {
919 hdr
= (struct pac_attr_hdr
*) pos
;
920 type
= be_to_host16(hdr
->type
);
921 len
= be_to_host16(hdr
->len
);
923 left
-= sizeof(*hdr
);
925 wpa_printf(MSG_DEBUG
,
926 "EAP-TEAP: PAC TLV overrun (type=%d len=%lu left=%lu)",
927 type
, (unsigned long) len
,
928 (unsigned long) left
);
932 eap_teap_parse_pac_tlv(entry
, type
, pos
, len
, &pac_key_found
);
938 if (!pac_key_found
|| !entry
->pac_opaque
|| !entry
->pac_info
) {
939 wpa_printf(MSG_DEBUG
,
940 "EAP-TEAP: PAC TLV does not include all the required fields");
948 static int eap_teap_parse_pac_info(struct eap_teap_pac
*entry
, int type
,
955 switch (type
& 0x7fff) {
956 case PAC_TYPE_CRED_LIFETIME
:
958 wpa_hexdump(MSG_DEBUG
,
959 "EAP-TEAP: PAC-Info - Invalid CRED_LIFETIME length - ignored",
965 * This is not currently saved separately in PAC files since
966 * the server can automatically initiate PAC update when
967 * needed. Anyway, the information is available from PAC-Info
968 * dump if it is needed for something in the future.
970 lifetime
= WPA_GET_BE32(pos
);
972 wpa_printf(MSG_DEBUG
,
973 "EAP-TEAP: PAC-Info - CRED_LIFETIME %d (%d days)",
974 lifetime
, (lifetime
- (u32
) now
.sec
) / 86400);
977 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID",
980 entry
->a_id_len
= len
;
983 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - I-ID",
986 entry
->i_id_len
= len
;
988 case PAC_TYPE_A_ID_INFO
:
989 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Info - A-ID-Info",
991 entry
->a_id_info
= pos
;
992 entry
->a_id_info_len
= len
;
994 case PAC_TYPE_PAC_TYPE
:
995 /* RFC 7170, Section 4.2.12.6 - PAC-Type TLV */
998 "EAP-TEAP: Invalid PAC-Type length %lu (expected 2)",
999 (unsigned long) len
);
1000 wpa_hexdump_ascii(MSG_DEBUG
,
1001 "EAP-TEAP: PAC-Info - PAC-Type",
1005 pac_type
= WPA_GET_BE16(pos
);
1006 if (pac_type
!= PAC_TYPE_TUNNEL_PAC
) {
1007 wpa_printf(MSG_INFO
,
1008 "EAP-TEAP: Unsupported PAC Type %d",
1013 wpa_printf(MSG_DEBUG
, "EAP-TEAP: PAC-Info - PAC-Type %d",
1015 entry
->pac_type
= pac_type
;
1018 wpa_printf(MSG_DEBUG
,
1019 "EAP-TEAP: Ignored unknown PAC-Info type %d", type
);
1027 static int eap_teap_process_pac_info(struct eap_teap_pac
*entry
)
1029 struct pac_attr_hdr
*hdr
;
1034 /* RFC 7170, Section 4.2.12.4 */
1036 /* PAC-Type defaults to Tunnel PAC (Type 1) */
1037 entry
->pac_type
= PAC_TYPE_TUNNEL_PAC
;
1039 pos
= entry
->pac_info
;
1040 left
= entry
->pac_info_len
;
1041 while (left
> sizeof(*hdr
)) {
1042 hdr
= (struct pac_attr_hdr
*) pos
;
1043 type
= be_to_host16(hdr
->type
);
1044 len
= be_to_host16(hdr
->len
);
1045 pos
+= sizeof(*hdr
);
1046 left
-= sizeof(*hdr
);
1048 wpa_printf(MSG_DEBUG
,
1049 "EAP-TEAP: PAC-Info overrun (type=%d len=%lu left=%lu)",
1050 type
, (unsigned long) len
,
1051 (unsigned long) left
);
1055 if (eap_teap_parse_pac_info(entry
, type
, pos
, len
) < 0)
1062 if (!entry
->a_id
|| !entry
->a_id_info
) {
1063 wpa_printf(MSG_DEBUG
,
1064 "EAP-TEAP: PAC-Info does not include all the required fields");
1072 static struct wpabuf
* eap_teap_process_pac(struct eap_sm
*sm
,
1073 struct eap_teap_data
*data
,
1074 struct eap_method_ret
*ret
,
1075 u8
*pac
, size_t pac_len
)
1077 struct eap_peer_config
*config
= eap_get_config(sm
);
1078 struct eap_teap_pac entry
;
1080 os_memset(&entry
, 0, sizeof(entry
));
1081 if (eap_teap_process_pac_tlv(&entry
, pac
, pac_len
) ||
1082 eap_teap_process_pac_info(&entry
))
1085 eap_teap_add_pac(&data
->pac
, &data
->current_pac
, &entry
);
1086 eap_teap_pac_list_truncate(data
->pac
, data
->max_pac_list_len
);
1087 if (data
->use_pac_binary_format
)
1088 eap_teap_save_pac_bin(sm
, data
->pac
, config
->pac_file
);
1090 eap_teap_save_pac(sm
, data
->pac
, config
->pac_file
);
1092 wpa_printf(MSG_DEBUG
,
1093 "EAP-TEAP: Send PAC-Acknowledgement - %s initiated provisioning completed successfully",
1094 data
->provisioning
? "peer" : "server");
1095 return eap_teap_tlv_pac_ack();
1099 static int eap_teap_parse_decrypted(struct wpabuf
*decrypted
,
1100 struct eap_teap_tlv_parse
*tlv
,
1101 struct wpabuf
**resp
)
1108 os_memset(tlv
, 0, sizeof(*tlv
));
1110 /* Parse TLVs from the decrypted Phase 2 data */
1111 pos
= wpabuf_mhead(decrypted
);
1112 end
= pos
+ wpabuf_len(decrypted
);
1113 while (end
- pos
>= 4) {
1114 mandatory
= pos
[0] & 0x80;
1115 tlv_type
= WPA_GET_BE16(pos
) & 0x3fff;
1117 len
= WPA_GET_BE16(pos
);
1119 if (len
> (size_t) (end
- pos
)) {
1120 wpa_printf(MSG_INFO
, "EAP-TEAP: TLV overflow");
1123 wpa_printf(MSG_DEBUG
,
1124 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1125 tlv_type
, eap_teap_tlv_type_str(tlv_type
),
1127 mandatory
? " (mandatory)" : "");
1129 res
= eap_teap_parse_tlv(tlv
, tlv_type
, pos
, len
);
1134 wpa_printf(MSG_DEBUG
,
1135 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1137 *resp
= eap_teap_tlv_nak(0, tlv_type
);
1141 wpa_printf(MSG_DEBUG
,
1142 "EAP-TEAP: Ignore unknown optional TLV type %u",
1153 static struct wpabuf
* eap_teap_pac_request(void)
1156 struct teap_tlv_request_action
*act
;
1157 struct teap_tlv_hdr
*pac
;
1158 struct teap_attr_pac_type
*type
;
1160 req
= wpabuf_alloc(sizeof(*act
) + sizeof(*pac
) + sizeof(*type
));
1164 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add Request Action TLV (Process TLV)");
1165 act
= wpabuf_put(req
, sizeof(*act
));
1166 act
->tlv_type
= host_to_be16(TEAP_TLV_REQUEST_ACTION
);
1167 act
->length
= host_to_be16(2);
1168 act
->status
= TEAP_STATUS_SUCCESS
;
1169 act
->action
= TEAP_REQUEST_ACTION_PROCESS_TLV
;
1171 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV (PAC-Type = Tunnel)");
1172 pac
= wpabuf_put(req
, sizeof(*pac
));
1173 pac
->tlv_type
= host_to_be16(TEAP_TLV_PAC
);
1174 pac
->length
= host_to_be16(sizeof(*type
));
1176 type
= wpabuf_put(req
, sizeof(*type
));
1177 type
->type
= host_to_be16(PAC_TYPE_PAC_TYPE
);
1178 type
->length
= host_to_be16(2);
1179 type
->pac_type
= host_to_be16(PAC_TYPE_TUNNEL_PAC
);
1185 static int eap_teap_process_decrypted(struct eap_sm
*sm
,
1186 struct eap_teap_data
*data
,
1187 struct eap_method_ret
*ret
,
1189 struct wpabuf
*decrypted
,
1190 struct wpabuf
**out_data
)
1192 struct wpabuf
*resp
= NULL
, *tmp
;
1193 struct eap_teap_tlv_parse tlv
;
1195 enum teap_error_codes error
= 0;
1196 int iresult_added
= 0;
1198 if (eap_teap_parse_decrypted(decrypted
, &tlv
, &resp
) < 0) {
1199 /* Parsing failed - no response available */
1204 /* Parsing rejected the message - send out an error response */
1208 if (tlv
.result
== TEAP_STATUS_FAILURE
) {
1209 /* Server indicated failure - respond similarly per
1210 * RFC 7170, 3.6.3. This authentication exchange cannot succeed
1211 * and will be terminated with a cleartext EAP Failure. */
1212 wpa_printf(MSG_DEBUG
,
1213 "EAP-TEAP: Server rejected authentication");
1214 resp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1215 ret
->methodState
= METHOD_DONE
;
1216 ret
->decision
= DECISION_FAIL
;
1220 if ((tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1221 (!data
->result_success_done
&&
1222 tlv
.result
== TEAP_STATUS_SUCCESS
)) &&
1223 !tlv
.crypto_binding
) {
1224 /* Result TLV or Intermediate-Result TLV indicating success,
1225 * but no Crypto-Binding TLV */
1226 wpa_printf(MSG_DEBUG
,
1227 "EAP-TEAP: Result TLV or Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
1229 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1233 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1234 tlv
.iresult
!= TEAP_STATUS_FAILURE
&&
1235 data
->inner_method_done
) {
1236 wpa_printf(MSG_DEBUG
,
1237 "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
1239 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1243 if (tlv
.basic_auth_req
) {
1244 tmp
= eap_teap_process_basic_auth_req(sm
, data
,
1246 tlv
.basic_auth_req_len
);
1249 resp
= wpabuf_concat(resp
, tmp
);
1250 } else if (tlv
.eap_payload_tlv
) {
1251 tmp
= eap_teap_process_eap_payload_tlv(sm
, data
, ret
,
1252 tlv
.eap_payload_tlv
,
1253 tlv
.eap_payload_tlv_len
);
1256 resp
= wpabuf_concat(resp
, tmp
);
1258 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1259 tlv
.iresult
== TEAP_STATUS_FAILURE
) {
1260 tmp
= eap_teap_tlv_result(failed
?
1261 TEAP_STATUS_FAILURE
:
1262 TEAP_STATUS_SUCCESS
, 1);
1263 resp
= wpabuf_concat(resp
, tmp
);
1264 if (tlv
.iresult
== TEAP_STATUS_FAILURE
)
1270 if (tlv
.crypto_binding
) {
1271 if (tlv
.iresult
!= TEAP_STATUS_SUCCESS
&&
1272 tlv
.result
!= TEAP_STATUS_SUCCESS
) {
1273 wpa_printf(MSG_DEBUG
,
1274 "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
1276 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1280 tmp
= eap_teap_process_crypto_binding(sm
, data
, ret
,
1282 tlv
.crypto_binding_len
);
1285 error
= TEAP_ERROR_TUNNEL_COMPROMISE_ERROR
;
1287 resp
= wpabuf_concat(resp
, tmp
);
1288 if (tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
)
1289 data
->result_success_done
= 1;
1290 if (tlv
.iresult
== TEAP_STATUS_SUCCESS
&& !failed
)
1291 data
->inner_method_done
= 0;
1295 if (data
->result_success_done
&& data
->session_ticket_used
&&
1296 eap_teap_derive_msk(data
) == 0) {
1297 /* Assume the server might accept authentication without going
1298 * through inner authentication. */
1299 wpa_printf(MSG_DEBUG
,
1300 "EAP-TEAP: PAC used - server may decide to skip inner authentication");
1301 ret
->methodState
= METHOD_MAY_CONT
;
1302 ret
->decision
= DECISION_COND_SUCC
;
1306 if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1307 tmp
= eap_teap_process_pac(sm
, data
, ret
,
1308 tlv
.pac
, tlv
.pac_len
);
1309 resp
= wpabuf_concat(resp
, tmp
);
1311 wpa_printf(MSG_DEBUG
,
1312 "EAP-TEAP: PAC TLV without Result TLV acknowledging success");
1314 error
= TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED
;
1318 if (!data
->current_pac
&& data
->provisioning
&& !failed
&& !tlv
.pac
&&
1319 tlv
.crypto_binding
&&
1320 (!data
->anon_provisioning
||
1321 (data
->phase2_success
&& data
->phase2_method
&&
1322 data
->phase2_method
->vendor
== 0 &&
1323 eap_teap_allowed_anon_prov_cipher_suite(data
->tls_cs
) &&
1324 eap_teap_allowed_anon_prov_phase2_method(
1325 data
->phase2_method
->method
))) &&
1326 (tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1327 tlv
.result
== TEAP_STATUS_SUCCESS
)) {
1329 * Need to request Tunnel PAC when using authenticated
1332 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Request Tunnel PAC");
1333 tmp
= eap_teap_pac_request();
1334 resp
= wpabuf_concat(resp
, tmp
);
1339 tmp
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
1340 resp
= wpabuf_concat(tmp
, resp
);
1343 tmp
= eap_teap_tlv_error(error
);
1344 resp
= wpabuf_concat(tmp
, resp
);
1347 ret
->methodState
= METHOD_DONE
;
1348 ret
->decision
= DECISION_FAIL
;
1349 } else if (tlv
.result
== TEAP_STATUS_SUCCESS
) {
1350 tmp
= eap_teap_tlv_result(TEAP_STATUS_SUCCESS
, 0);
1351 resp
= wpabuf_concat(tmp
, resp
);
1353 if ((tlv
.iresult
== TEAP_STATUS_SUCCESS
||
1354 tlv
.iresult
== TEAP_STATUS_FAILURE
) && !iresult_added
) {
1355 tmp
= eap_teap_tlv_result((!failed
&& data
->phase2_success
) ?
1356 TEAP_STATUS_SUCCESS
:
1357 TEAP_STATUS_FAILURE
, 1);
1358 resp
= wpabuf_concat(tmp
, resp
);
1361 if (resp
&& tlv
.result
== TEAP_STATUS_SUCCESS
&& !failed
&&
1362 tlv
.crypto_binding
&& data
->phase2_success
) {
1363 /* Successfully completed Phase 2 */
1364 wpa_printf(MSG_DEBUG
,
1365 "EAP-TEAP: Authentication completed successfully");
1366 ret
->methodState
= METHOD_MAY_CONT
;
1367 data
->on_tx_completion
= data
->provisioning
?
1368 METHOD_MAY_CONT
: METHOD_DONE
;
1369 ret
->decision
= DECISION_UNCOND_SUCC
;
1373 wpa_printf(MSG_DEBUG
,
1374 "EAP-TEAP: No recognized TLVs - send empty response packet");
1375 resp
= wpabuf_alloc(1);
1382 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: Encrypting Phase 2 data", resp
);
1383 if (eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1384 data
->teap_version
, identifier
,
1386 wpa_printf(MSG_INFO
,
1387 "EAP-TEAP: Failed to encrypt a Phase 2 frame");
1395 static int eap_teap_decrypt(struct eap_sm
*sm
, struct eap_teap_data
*data
,
1396 struct eap_method_ret
*ret
, u8 identifier
,
1397 const struct wpabuf
*in_data
,
1398 struct wpabuf
**out_data
)
1400 struct wpabuf
*in_decrypted
;
1403 wpa_printf(MSG_DEBUG
,
1404 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1405 (unsigned long) wpabuf_len(in_data
));
1407 if (data
->pending_phase2_req
) {
1408 wpa_printf(MSG_DEBUG
,
1409 "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
1410 /* Clear TLS reassembly state. */
1411 eap_peer_tls_reset_input(&data
->ssl
);
1413 in_decrypted
= data
->pending_phase2_req
;
1414 data
->pending_phase2_req
= NULL
;
1418 if (wpabuf_len(in_data
) == 0) {
1419 /* Received TLS ACK - requesting more fragments */
1420 res
= eap_peer_tls_encrypt(sm
, &data
->ssl
, EAP_TYPE_TEAP
,
1422 identifier
, NULL
, out_data
);
1423 if (res
== 0 && !data
->ssl
.tls_out
&&
1424 data
->on_tx_completion
) {
1425 wpa_printf(MSG_DEBUG
,
1426 "EAP-TEAP: Mark authentication completed at full TX of fragments");
1427 ret
->methodState
= data
->on_tx_completion
;
1428 data
->on_tx_completion
= 0;
1429 ret
->decision
= DECISION_UNCOND_SUCC
;
1434 res
= eap_peer_tls_decrypt(sm
, &data
->ssl
, in_data
, &in_decrypted
);
1439 wpa_hexdump_buf(MSG_MSGDUMP
, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
1442 if (wpabuf_len(in_decrypted
) < 4) {
1443 wpa_printf(MSG_INFO
,
1444 "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
1445 (unsigned long) wpabuf_len(in_decrypted
));
1446 wpabuf_free(in_decrypted
);
1450 res
= eap_teap_process_decrypted(sm
, data
, ret
, identifier
,
1451 in_decrypted
, out_data
);
1453 wpabuf_free(in_decrypted
);
1459 static void eap_teap_select_pac(struct eap_teap_data
*data
,
1460 const u8
*a_id
, size_t a_id_len
)
1464 data
->current_pac
= eap_teap_get_pac(data
->pac
, a_id
, a_id_len
,
1465 PAC_TYPE_TUNNEL_PAC
);
1466 if (data
->current_pac
) {
1467 wpa_printf(MSG_DEBUG
,
1468 "EAP-TEAP: PAC found for this A-ID (PAC-Type %d)",
1469 data
->current_pac
->pac_type
);
1470 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-TEAP: A-ID-Info",
1471 data
->current_pac
->a_id_info
,
1472 data
->current_pac
->a_id_info_len
);
1477 static int eap_teap_use_pac_opaque(struct eap_sm
*sm
,
1478 struct eap_teap_data
*data
,
1479 struct eap_teap_pac
*pac
)
1482 size_t tlv_len
, olen
;
1483 struct teap_tlv_hdr
*ehdr
;
1485 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC-Opaque TLS extension");
1486 olen
= pac
->pac_opaque_len
;
1487 tlv_len
= sizeof(*ehdr
) + olen
;
1488 tlv
= os_malloc(tlv_len
);
1490 ehdr
= (struct teap_tlv_hdr
*) tlv
;
1491 ehdr
->tlv_type
= host_to_be16(PAC_TYPE_PAC_OPAQUE
);
1492 ehdr
->length
= host_to_be16(olen
);
1493 os_memcpy(ehdr
+ 1, pac
->pac_opaque
, olen
);
1496 tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1498 tlv
, tlv_len
) < 0) {
1499 wpa_printf(MSG_DEBUG
,
1500 "EAP-TEAP: Failed to add PAC-Opaque TLS extension");
1510 static int eap_teap_clear_pac_opaque_ext(struct eap_sm
*sm
,
1511 struct eap_teap_data
*data
)
1513 if (tls_connection_client_hello_ext(sm
->ssl_ctx
, data
->ssl
.conn
,
1514 TLS_EXT_PAC_OPAQUE
, NULL
, 0) < 0) {
1515 wpa_printf(MSG_DEBUG
,
1516 "EAP-TEAP: Failed to remove PAC-Opaque TLS extension");
1523 static int eap_teap_process_start(struct eap_sm
*sm
,
1524 struct eap_teap_data
*data
, u8 flags
,
1525 const u8
*pos
, size_t left
)
1527 const u8
*a_id
= NULL
;
1528 size_t a_id_len
= 0;
1530 /* TODO: Support (mostly theoretical) case of TEAP/Start request being
1533 /* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
1534 data
->received_version
= flags
& EAP_TLS_VERSION_MASK
;
1535 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
1536 data
->received_version
, data
->teap_version
);
1537 if (data
->received_version
< 1) {
1538 /* Version 1 was the first defined version, so reject 0 */
1539 wpa_printf(MSG_INFO
,
1540 "EAP-TEAP: Server used unknown TEAP version %u",
1541 data
->received_version
);
1544 if (data
->received_version
< data
->teap_version
)
1545 data
->teap_version
= data
->received_version
;
1546 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Using TEAP version %d",
1547 data
->teap_version
);
1548 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message payload", pos
, left
);
1550 /* Parse Authority-ID TLV from Outer TLVs, if present */
1551 if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1552 const u8
*outer_pos
, *outer_end
;
1556 wpa_printf(MSG_INFO
,
1557 "EAP-TEAP: Not enough room for the Outer TLV Length field");
1561 outer_tlv_len
= WPA_GET_BE32(pos
);
1565 if (outer_tlv_len
> left
) {
1566 wpa_printf(MSG_INFO
,
1567 "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
1568 outer_tlv_len
, (unsigned int) left
);
1572 outer_pos
= pos
+ left
- outer_tlv_len
;
1573 outer_end
= outer_pos
+ outer_tlv_len
;
1574 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Start message Outer TLVs",
1575 outer_pos
, outer_tlv_len
);
1576 wpabuf_free(data
->server_outer_tlvs
);
1577 data
->server_outer_tlvs
= wpabuf_alloc_copy(outer_pos
,
1579 if (!data
->server_outer_tlvs
)
1581 left
-= outer_tlv_len
;
1583 wpa_hexdump(MSG_INFO
,
1584 "EAP-TEAP: Unexpected TLS Data in Start message",
1589 while (outer_pos
< outer_end
) {
1590 u16 tlv_type
, tlv_len
;
1592 if (outer_end
- outer_pos
< 4) {
1593 wpa_printf(MSG_INFO
,
1594 "EAP-TEAP: Truncated Outer TLV header");
1597 tlv_type
= WPA_GET_BE16(outer_pos
);
1599 tlv_len
= WPA_GET_BE16(outer_pos
);
1601 /* Outer TLVs are required to be optional, so no need to
1602 * check the M flag */
1603 tlv_type
&= TEAP_TLV_TYPE_MASK
;
1604 wpa_printf(MSG_DEBUG
,
1605 "EAP-TEAP: Outer TLV: Type=%u Length=%u",
1607 if (outer_end
- outer_pos
< tlv_len
) {
1608 wpa_printf(MSG_INFO
,
1609 "EAP-TEAP: Truncated Outer TLV (Type %u)",
1613 if (tlv_type
== TEAP_TLV_AUTHORITY_ID
) {
1614 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Authority-ID",
1615 outer_pos
, tlv_len
);
1617 wpa_printf(MSG_INFO
,
1618 "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
1624 wpa_printf(MSG_DEBUG
,
1625 "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
1628 outer_pos
+= tlv_len
;
1630 } else if (left
> 0) {
1631 wpa_hexdump(MSG_INFO
,
1632 "EAP-TEAP: Unexpected TLS Data in Start message",
1637 eap_teap_select_pac(data
, a_id
, a_id_len
);
1639 if (data
->resuming
&& data
->current_pac
) {
1640 wpa_printf(MSG_DEBUG
,
1641 "EAP-TEAP: Trying to resume session - do not add PAC-Opaque to TLS ClientHello");
1642 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1644 } else if (data
->current_pac
) {
1646 * PAC found for the A-ID and we are not resuming an old
1647 * session, so add PAC-Opaque extension to ClientHello.
1649 if (eap_teap_use_pac_opaque(sm
, data
, data
->current_pac
) < 0)
1651 } else if (data
->provisioning_allowed
) {
1652 wpa_printf(MSG_DEBUG
,
1653 "EAP-TEAP: No PAC found - starting provisioning");
1654 if (eap_teap_clear_pac_opaque_ext(sm
, data
) < 0)
1656 data
->provisioning
= 1;
1663 #ifdef CONFIG_TESTING_OPTIONS
1664 static struct wpabuf
* eap_teap_add_dummy_outer_tlvs(struct eap_teap_data
*data
,
1665 struct wpabuf
*resp
)
1667 struct wpabuf
*resp2
;
1672 wpabuf_free(data
->peer_outer_tlvs
);
1673 data
->peer_outer_tlvs
= wpabuf_alloc(4 + 4);
1674 if (!data
->peer_outer_tlvs
) {
1679 /* Outer TLVs (dummy Vendor-Specific TLV for testing) */
1680 wpabuf_put_be16(data
->peer_outer_tlvs
, TEAP_TLV_VENDOR_SPECIFIC
);
1681 wpabuf_put_be16(data
->peer_outer_tlvs
, 4);
1682 wpabuf_put_be32(data
->peer_outer_tlvs
, EAP_VENDOR_HOSTAP
);
1683 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
1684 data
->peer_outer_tlvs
);
1686 wpa_hexdump_buf(MSG_DEBUG
,
1687 "EAP-TEAP: TEAP/Start response before modification",
1689 resp2
= wpabuf_alloc(wpabuf_len(resp
) + 4 +
1690 wpabuf_len(data
->peer_outer_tlvs
));
1696 pos
= wpabuf_head(resp
);
1697 wpabuf_put_u8(resp2
, *pos
++); /* Code */
1698 wpabuf_put_u8(resp2
, *pos
++); /* Identifier */
1699 len
= WPA_GET_BE16(pos
);
1701 wpabuf_put_be16(resp2
, len
+ 4 + wpabuf_len(data
->peer_outer_tlvs
));
1702 wpabuf_put_u8(resp2
, *pos
++); /* Type */
1703 /* Flags | Ver (with Outer TLV length included flag set to 1) */
1705 if (flags
& (EAP_TEAP_FLAGS_OUTER_TLV_LEN
|
1706 EAP_TLS_FLAGS_LENGTH_INCLUDED
)) {
1707 wpa_printf(MSG_INFO
,
1708 "EAP-TEAP: Cannot add Outer TLVs for testing");
1713 flags
|= EAP_TEAP_FLAGS_OUTER_TLV_LEN
;
1714 wpabuf_put_u8(resp2
, flags
);
1715 /* Outer TLV Length */
1716 wpabuf_put_be32(resp2
, wpabuf_len(data
->peer_outer_tlvs
));
1718 wpabuf_put_data(resp2
, pos
, wpabuf_len(resp
) - 6);
1719 wpabuf_put_buf(resp2
, data
->peer_outer_tlvs
); /* Outer TLVs */
1722 wpa_hexdump_buf(MSG_DEBUG
,
1723 "EAP-TEAP: TEAP/Start response after modification",
1727 #endif /* CONFIG_TESTING_OPTIONS */
1730 static struct wpabuf
* eap_teap_process(struct eap_sm
*sm
, void *priv
,
1731 struct eap_method_ret
*ret
,
1732 const struct wpabuf
*reqData
)
1734 const struct eap_hdr
*req
;
1738 struct wpabuf
*resp
;
1740 struct eap_teap_data
*data
= priv
;
1743 pos
= eap_peer_tls_process_init(sm
, &data
->ssl
, EAP_TYPE_TEAP
, ret
,
1744 reqData
, &left
, &flags
);
1748 req
= wpabuf_head(reqData
);
1749 id
= req
->identifier
;
1751 if (flags
& EAP_TLS_FLAGS_START
) {
1752 if (eap_teap_process_start(sm
, data
, flags
, pos
, left
) < 0)
1755 /* Outer TLVs are not used in further packet processing and
1756 * there cannot be TLS Data in this TEAP/Start message, so
1757 * enforce that by ignoring whatever data might remain in the
1760 } else if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1761 /* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
1762 * Outer TLVs MUST be ignored instead of ignoring the full
1764 wpa_printf(MSG_INFO
,
1765 "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
1769 wpabuf_set(&msg
, pos
, left
);
1772 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
) &&
1774 /* Process tunneled (encrypted) phase 2 data. */
1775 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1777 ret
->methodState
= METHOD_DONE
;
1778 ret
->decision
= DECISION_FAIL
;
1780 * Ack possible Alert that may have caused failure in
1786 if (sm
->waiting_ext_cert_check
&& data
->pending_resp
) {
1787 struct eap_peer_config
*config
= eap_get_config(sm
);
1789 if (config
->pending_ext_cert_check
==
1790 EXT_CERT_CHECK_GOOD
) {
1791 wpa_printf(MSG_DEBUG
,
1792 "EAP-TEAP: External certificate check succeeded - continue handshake");
1793 resp
= data
->pending_resp
;
1794 data
->pending_resp
= NULL
;
1795 sm
->waiting_ext_cert_check
= 0;
1799 if (config
->pending_ext_cert_check
==
1800 EXT_CERT_CHECK_BAD
) {
1801 wpa_printf(MSG_DEBUG
,
1802 "EAP-TEAP: External certificate check failed - force authentication failure");
1803 ret
->methodState
= METHOD_DONE
;
1804 ret
->decision
= DECISION_FAIL
;
1805 sm
->waiting_ext_cert_check
= 0;
1809 wpa_printf(MSG_DEBUG
,
1810 "EAP-TEAP: Continuing to wait external server certificate validation");
1814 /* Continue processing TLS handshake (phase 1). */
1815 res
= eap_peer_tls_process_helper(sm
, &data
->ssl
,
1817 data
->teap_version
, id
, &msg
,
1820 wpa_printf(MSG_DEBUG
,
1821 "EAP-TEAP: TLS processing failed");
1822 ret
->methodState
= METHOD_DONE
;
1823 ret
->decision
= DECISION_FAIL
;
1827 if (sm
->waiting_ext_cert_check
) {
1828 wpa_printf(MSG_DEBUG
,
1829 "EAP-TEAP: Waiting external server certificate validation");
1830 wpabuf_free(data
->pending_resp
);
1831 data
->pending_resp
= resp
;
1835 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
1838 wpa_printf(MSG_DEBUG
,
1839 "EAP-TEAP: TLS done, proceed to Phase 2");
1841 tls_connection_get_cipher_suite(data
->ssl
.conn
);
1842 wpa_printf(MSG_DEBUG
,
1843 "EAP-TEAP: TLS cipher suite 0x%04x",
1846 if (data
->provisioning
&&
1847 (!(data
->provisioning_allowed
&
1848 EAP_TEAP_PROV_AUTH
) ||
1849 tls_get_cipher(sm
->ssl_ctx
, data
->ssl
.conn
,
1850 cipher
, sizeof(cipher
)) < 0 ||
1851 os_strstr(cipher
, "ADH-") ||
1852 os_strstr(cipher
, "anon"))) {
1853 wpa_printf(MSG_DEBUG
,
1854 "EAP-TEAP: Using anonymous (unauthenticated) provisioning");
1855 data
->anon_provisioning
= 1;
1857 data
->anon_provisioning
= 0;
1860 if (eap_teap_derive_key_auth(sm
, data
) < 0) {
1861 wpa_printf(MSG_DEBUG
,
1862 "EAP-TEAP: Could not derive keys");
1863 ret
->methodState
= METHOD_DONE
;
1864 ret
->decision
= DECISION_FAIL
;
1872 * Application data included in the handshake message.
1874 wpabuf_free(data
->pending_phase2_req
);
1875 data
->pending_phase2_req
= resp
;
1877 res
= eap_teap_decrypt(sm
, data
, ret
, id
, &msg
, &resp
);
1883 return eap_peer_tls_build_ack(id
, EAP_TYPE_TEAP
,
1884 data
->teap_version
);
1887 #ifdef CONFIG_TESTING_OPTIONS
1888 if (data
->test_outer_tlvs
&& res
== 0 && resp
&&
1889 (flags
& EAP_TLS_FLAGS_START
) && wpabuf_len(resp
) >= 6)
1890 resp
= eap_teap_add_dummy_outer_tlvs(data
, resp
);
1891 #endif /* CONFIG_TESTING_OPTIONS */
1898 static Boolean
eap_teap_has_reauth_data(struct eap_sm
*sm
, void *priv
)
1900 struct eap_teap_data
*data
= priv
;
1902 return tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
);
1906 static void eap_teap_deinit_for_reauth(struct eap_sm
*sm
, void *priv
)
1908 struct eap_teap_data
*data
= priv
;
1910 if (data
->phase2_priv
&& data
->phase2_method
&&
1911 data
->phase2_method
->deinit_for_reauth
)
1912 data
->phase2_method
->deinit_for_reauth(sm
, data
->phase2_priv
);
1913 eap_teap_clear(data
);
1917 static void * eap_teap_init_for_reauth(struct eap_sm
*sm
, void *priv
)
1919 struct eap_teap_data
*data
= priv
;
1921 if (eap_peer_tls_reauth_init(sm
, &data
->ssl
)) {
1922 eap_teap_deinit(sm
, data
);
1925 if (data
->phase2_priv
&& data
->phase2_method
&&
1926 data
->phase2_method
->init_for_reauth
)
1927 data
->phase2_method
->init_for_reauth(sm
, data
->phase2_priv
);
1928 data
->phase2_success
= 0;
1929 data
->inner_method_done
= 0;
1930 data
->result_success_done
= 0;
1931 data
->done_on_tx_completion
= 0;
1933 data
->provisioning
= 0;
1934 data
->anon_provisioning
= 0;
1935 data
->simck_idx
= 0;
1941 static int eap_teap_get_status(struct eap_sm
*sm
, void *priv
, char *buf
,
1942 size_t buflen
, int verbose
)
1944 struct eap_teap_data
*data
= priv
;
1947 len
= eap_peer_tls_status(sm
, &data
->ssl
, buf
, buflen
, verbose
);
1948 if (data
->phase2_method
) {
1949 ret
= os_snprintf(buf
+ len
, buflen
- len
,
1950 "EAP-TEAP Phase 2 method=%s\n",
1951 data
->phase2_method
->name
);
1952 if (os_snprintf_error(buflen
- len
, ret
))
1960 static Boolean
eap_teap_isKeyAvailable(struct eap_sm
*sm
, void *priv
)
1962 struct eap_teap_data
*data
= priv
;
1964 return data
->success
;
1968 static u8
* eap_teap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1970 struct eap_teap_data
*data
= priv
;
1976 key
= os_memdup(data
->key_data
, EAP_TEAP_KEY_LEN
);
1980 *len
= EAP_TEAP_KEY_LEN
;
1986 static u8
* eap_teap_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
1988 struct eap_teap_data
*data
= priv
;
1991 if (!data
->success
|| !data
->session_id
)
1994 id
= os_memdup(data
->session_id
, data
->id_len
);
1998 *len
= data
->id_len
;
2004 static u8
* eap_teap_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
2006 struct eap_teap_data
*data
= priv
;
2012 key
= os_memdup(data
->emsk
, EAP_EMSK_LEN
);
2016 *len
= EAP_EMSK_LEN
;
2022 int eap_peer_teap_register(void)
2024 struct eap_method
*eap
;
2026 eap
= eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION
,
2027 EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, "TEAP");
2031 eap
->init
= eap_teap_init
;
2032 eap
->deinit
= eap_teap_deinit
;
2033 eap
->process
= eap_teap_process
;
2034 eap
->isKeyAvailable
= eap_teap_isKeyAvailable
;
2035 eap
->getKey
= eap_teap_getKey
;
2036 eap
->getSessionId
= eap_teap_get_session_id
;
2037 eap
->get_status
= eap_teap_get_status
;
2039 eap
->has_reauth_data
= eap_teap_has_reauth_data
;
2040 eap
->deinit_for_reauth
= eap_teap_deinit_for_reauth
;
2041 eap
->init_for_reauth
= eap_teap_init_for_reauth
;
2043 eap
->get_emsk
= eap_teap_get_emsk
;
2045 return eap_peer_method_register(eap
);