2 * EAP-TEAP server (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/aes_wrap.h"
13 #include "crypto/tls.h"
14 #include "crypto/random.h"
15 #include "eap_common/eap_teap_common.h"
17 #include "eap_tls_common.h"
20 static void eap_teap_reset(struct eap_sm
*sm
, void *priv
);
23 /* Private PAC-Opaque TLV types */
24 #define PAC_OPAQUE_TYPE_PAD 0
25 #define PAC_OPAQUE_TYPE_KEY 1
26 #define PAC_OPAQUE_TYPE_LIFETIME 2
27 #define PAC_OPAQUE_TYPE_IDENTITY 3
29 struct eap_teap_data
{
30 struct eap_ssl_data ssl
;
32 START
, PHASE1
, PHASE1B
, PHASE2_START
, PHASE2_ID
,
33 PHASE2_BASIC_AUTH
, PHASE2_METHOD
, CRYPTO_BINDING
, REQUEST_PAC
,
34 FAILURE_SEND_RESULT
, SUCCESS
, FAILURE
41 const struct eap_method
*phase2_method
;
44 u8 crypto_binding_nonce
[32];
47 u8 simck_msk
[EAP_TEAP_SIMCK_LEN
];
48 u8 cmk_msk
[EAP_TEAP_CMK_LEN
];
49 u8 simck_emsk
[EAP_TEAP_SIMCK_LEN
];
50 u8 cmk_emsk
[EAP_TEAP_CMK_LEN
];
52 int cmk_emsk_available
;
54 u8 pac_opaque_encr
[16];
59 int anon_provisioning
;
60 int send_new_pac
; /* server triggered re-keying of Tunnel PAC */
61 struct wpabuf
*pending_phase2_resp
;
62 struct wpabuf
*server_outer_tlvs
;
63 struct wpabuf
*peer_outer_tlvs
;
64 u8
*identity
; /* from PAC-Opaque */
70 int pac_key_refresh_time
;
72 enum teap_error_codes error_code
;
76 static int eap_teap_process_phase2_start(struct eap_sm
*sm
,
77 struct eap_teap_data
*data
);
80 static const char * eap_teap_state_txt(int state
)
90 return "PHASE2_START";
93 case PHASE2_BASIC_AUTH
:
94 return "PHASE2_BASIC_AUTH";
96 return "PHASE2_METHOD";
98 return "CRYPTO_BINDING";
100 return "REQUEST_PAC";
101 case FAILURE_SEND_RESULT
:
102 return "FAILURE_SEND_RESULT";
113 static void eap_teap_state(struct eap_teap_data
*data
, int state
)
115 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s -> %s",
116 eap_teap_state_txt(data
->state
),
117 eap_teap_state_txt(state
));
122 static EapType
eap_teap_req_failure(struct eap_teap_data
*data
,
123 enum teap_error_codes error
)
125 eap_teap_state(data
, FAILURE_SEND_RESULT
);
126 return EAP_TYPE_NONE
;
130 static int eap_teap_session_ticket_cb(void *ctx
, const u8
*ticket
, size_t len
,
131 const u8
*client_random
,
132 const u8
*server_random
,
135 struct eap_teap_data
*data
= ctx
;
136 const u8
*pac_opaque
;
137 size_t pac_opaque_len
;
138 u8
*buf
, *pos
, *end
, *pac_key
= NULL
;
139 os_time_t lifetime
= 0;
142 size_t identity_len
= 0;
144 wpa_printf(MSG_DEBUG
, "EAP-TEAP: SessionTicket callback");
145 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: SessionTicket (PAC-Opaque)",
148 if (len
< 4 || WPA_GET_BE16(ticket
) != PAC_TYPE_PAC_OPAQUE
) {
149 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Ignore invalid SessionTicket");
153 pac_opaque_len
= WPA_GET_BE16(ticket
+ 2);
154 pac_opaque
= ticket
+ 4;
155 if (pac_opaque_len
< 8 || pac_opaque_len
% 8 ||
156 pac_opaque_len
> len
- 4) {
157 wpa_printf(MSG_DEBUG
,
158 "EAP-TEAP: Ignore invalid PAC-Opaque (len=%lu left=%lu)",
159 (unsigned long) pac_opaque_len
,
160 (unsigned long) len
);
163 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Received PAC-Opaque",
164 pac_opaque
, pac_opaque_len
);
166 buf
= os_malloc(pac_opaque_len
- 8);
168 wpa_printf(MSG_DEBUG
,
169 "EAP-TEAP: Failed to allocate memory for decrypting PAC-Opaque");
173 if (aes_unwrap(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
),
174 (pac_opaque_len
- 8) / 8, pac_opaque
, buf
) < 0) {
175 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Failed to decrypt PAC-Opaque");
178 * This may have been caused by server changing the PAC-Opaque
179 * encryption key, so just ignore this PAC-Opaque instead of
180 * failing the authentication completely. Provisioning can now
181 * be used to provision a new PAC.
186 end
= buf
+ pac_opaque_len
- 8;
187 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: Decrypted PAC-Opaque",
191 while (end
- pos
> 1) {
196 if (elen
> end
- pos
)
200 case PAC_OPAQUE_TYPE_PAD
:
202 case PAC_OPAQUE_TYPE_KEY
:
203 if (elen
!= EAP_TEAP_PAC_KEY_LEN
) {
204 wpa_printf(MSG_DEBUG
,
205 "EAP-TEAP: Invalid PAC-Key length %d",
211 wpa_hexdump_key(MSG_DEBUG
,
212 "EAP-TEAP: PAC-Key from decrypted PAC-Opaque",
213 pac_key
, EAP_TEAP_PAC_KEY_LEN
);
215 case PAC_OPAQUE_TYPE_LIFETIME
:
217 wpa_printf(MSG_DEBUG
,
218 "EAP-TEAP: Invalid PAC-Key lifetime length %d",
223 lifetime
= WPA_GET_BE32(pos
);
225 case PAC_OPAQUE_TYPE_IDENTITY
:
236 wpa_printf(MSG_DEBUG
,
237 "EAP-TEAP: No PAC-Key included in PAC-Opaque");
243 wpa_hexdump_ascii(MSG_DEBUG
,
244 "EAP-TEAP: Identity from PAC-Opaque",
245 identity
, identity_len
);
246 os_free(data
->identity
);
247 data
->identity
= os_malloc(identity_len
);
248 if (data
->identity
) {
249 os_memcpy(data
->identity
, identity
, identity_len
);
250 data
->identity_len
= identity_len
;
254 if (os_get_time(&now
) < 0 || lifetime
<= 0 || now
.sec
> lifetime
) {
255 wpa_printf(MSG_DEBUG
,
256 "EAP-TEAP: PAC-Key not valid anymore (lifetime=%ld now=%ld)",
258 data
->send_new_pac
= 2;
260 * Allow PAC to be used to allow a PAC update with some level
261 * of server authentication (i.e., do not fall back to full TLS
262 * handshake since we cannot be sure that the peer would be
263 * able to validate server certificate now). However, reject
264 * the authentication since the PAC was not valid anymore. Peer
265 * can connect again with the newly provisioned PAC after this.
267 } else if (lifetime
- now
.sec
< data
->pac_key_refresh_time
) {
268 wpa_printf(MSG_DEBUG
,
269 "EAP-TEAP: PAC-Key soft timeout; send an update if authentication succeeds");
270 data
->send_new_pac
= 1;
273 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
274 os_memcpy(master_secret
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
282 static int eap_teap_derive_key_auth(struct eap_sm
*sm
,
283 struct eap_teap_data
*data
)
287 /* RFC 7170, Section 5.1 */
288 res
= tls_connection_export_key(sm
->ssl_ctx
, data
->ssl
.conn
,
289 TEAP_TLS_EXPORTER_LABEL_SKS
, NULL
, 0,
290 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
293 wpa_hexdump_key(MSG_DEBUG
,
294 "EAP-TEAP: session_key_seed (S-IMCK[0])",
295 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
296 os_memcpy(data
->simck_emsk
, data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
302 static int eap_teap_update_icmk(struct eap_sm
*sm
, struct eap_teap_data
*data
)
304 u8
*msk
= NULL
, *emsk
= NULL
;
305 size_t msk_len
= 0, emsk_len
= 0;
308 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Deriving ICMK[%d] (S-IMCK and CMK)",
309 data
->simck_idx
+ 1);
311 if (sm
->eap_teap_auth
== 1)
312 return eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
316 if (!data
->phase2_method
|| !data
->phase2_priv
) {
317 wpa_printf(MSG_INFO
, "EAP-TEAP: Phase 2 method not available");
321 if (data
->phase2_method
->getKey
) {
322 msk
= data
->phase2_method
->getKey(sm
, data
->phase2_priv
,
326 "EAP-TEAP: Could not fetch Phase 2 MSK");
331 if (data
->phase2_method
->get_emsk
) {
332 emsk
= data
->phase2_method
->get_emsk(sm
, data
->phase2_priv
,
336 res
= eap_teap_derive_imck(data
->tls_cs
,
337 data
->simck_msk
, data
->simck_emsk
,
338 msk
, msk_len
, emsk
, emsk_len
,
339 data
->simck_msk
, data
->cmk_msk
,
340 data
->simck_emsk
, data
->cmk_emsk
);
341 bin_clear_free(msk
, msk_len
);
342 bin_clear_free(emsk
, emsk_len
);
346 data
->cmk_emsk_available
= 1;
352 static void * eap_teap_init(struct eap_sm
*sm
)
354 struct eap_teap_data
*data
;
356 data
= os_zalloc(sizeof(*data
));
359 data
->teap_version
= EAP_TEAP_VERSION
;
362 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0, EAP_TYPE_TEAP
)) {
363 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to initialize SSL.");
364 eap_teap_reset(sm
, data
);
368 /* TODO: Add anon-DH TLS cipher suites (and if one is negotiated,
369 * enforce inner EAP with mutual authentication to be used) */
371 if (tls_connection_set_session_ticket_cb(sm
->ssl_ctx
, data
->ssl
.conn
,
372 eap_teap_session_ticket_cb
,
375 "EAP-TEAP: Failed to set SessionTicket callback");
376 eap_teap_reset(sm
, data
);
380 if (!sm
->pac_opaque_encr_key
) {
382 "EAP-TEAP: No PAC-Opaque encryption key configured");
383 eap_teap_reset(sm
, data
);
386 os_memcpy(data
->pac_opaque_encr
, sm
->pac_opaque_encr_key
,
387 sizeof(data
->pac_opaque_encr
));
389 if (!sm
->eap_fast_a_id
) {
390 wpa_printf(MSG_INFO
, "EAP-TEAP: No A-ID configured");
391 eap_teap_reset(sm
, data
);
394 data
->srv_id
= os_malloc(sm
->eap_fast_a_id_len
);
396 eap_teap_reset(sm
, data
);
399 os_memcpy(data
->srv_id
, sm
->eap_fast_a_id
, sm
->eap_fast_a_id_len
);
400 data
->srv_id_len
= sm
->eap_fast_a_id_len
;
402 if (!sm
->eap_fast_a_id_info
) {
403 wpa_printf(MSG_INFO
, "EAP-TEAP: No A-ID-Info configured");
404 eap_teap_reset(sm
, data
);
407 data
->srv_id_info
= os_strdup(sm
->eap_fast_a_id_info
);
408 if (!data
->srv_id_info
) {
409 eap_teap_reset(sm
, data
);
413 /* PAC-Key lifetime in seconds (hard limit) */
414 data
->pac_key_lifetime
= sm
->pac_key_lifetime
;
417 * PAC-Key refresh time in seconds (soft limit on remaining hard
418 * limit). The server will generate a new PAC-Key when this number of
419 * seconds (or fewer) of the lifetime remains.
421 data
->pac_key_refresh_time
= sm
->pac_key_refresh_time
;
427 static void eap_teap_reset(struct eap_sm
*sm
, void *priv
)
429 struct eap_teap_data
*data
= priv
;
433 if (data
->phase2_priv
&& data
->phase2_method
)
434 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
435 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
436 os_free(data
->srv_id
);
437 os_free(data
->srv_id_info
);
438 wpabuf_free(data
->pending_phase2_resp
);
439 wpabuf_free(data
->server_outer_tlvs
);
440 wpabuf_free(data
->peer_outer_tlvs
);
441 os_free(data
->identity
);
442 forced_memzero(data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
443 forced_memzero(data
->simck_emsk
, EAP_TEAP_SIMCK_LEN
);
444 forced_memzero(data
->cmk_msk
, EAP_TEAP_CMK_LEN
);
445 forced_memzero(data
->cmk_emsk
, EAP_TEAP_CMK_LEN
);
446 forced_memzero(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
));
447 bin_clear_free(data
, sizeof(*data
));
451 static struct wpabuf
* eap_teap_build_start(struct eap_sm
*sm
,
452 struct eap_teap_data
*data
, u8 id
)
455 size_t outer_tlv_len
= sizeof(struct teap_tlv_hdr
) + data
->srv_id_len
;
456 const u8
*start
, *end
;
458 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
,
459 1 + 4 + outer_tlv_len
, EAP_CODE_REQUEST
, id
);
461 wpa_printf(MSG_ERROR
,
462 "EAP-TEAP: Failed to allocate memory for request");
463 eap_teap_state(data
, FAILURE
);
467 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
| EAP_TEAP_FLAGS_OUTER_TLV_LEN
|
469 wpabuf_put_be32(req
, outer_tlv_len
);
471 start
= wpabuf_put(req
, 0);
473 /* RFC 7170, Section 4.2.2: Authority-ID TLV */
474 eap_teap_put_tlv(req
, TEAP_TLV_AUTHORITY_ID
,
475 data
->srv_id
, data
->srv_id_len
);
477 end
= wpabuf_put(req
, 0);
478 wpabuf_free(data
->server_outer_tlvs
);
479 data
->server_outer_tlvs
= wpabuf_alloc_copy(start
, end
- start
);
480 if (!data
->server_outer_tlvs
) {
481 eap_teap_state(data
, FAILURE
);
485 eap_teap_state(data
, PHASE1
);
491 static int eap_teap_phase1_done(struct eap_sm
*sm
, struct eap_teap_data
*data
)
495 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 1 done, starting Phase 2");
497 data
->tls_cs
= tls_connection_get_cipher_suite(data
->ssl
.conn
);
498 wpa_printf(MSG_DEBUG
, "EAP-TEAP: TLS cipher suite 0x%04x",
501 if (tls_get_cipher(sm
->ssl_ctx
, data
->ssl
.conn
, cipher
, sizeof(cipher
))
503 wpa_printf(MSG_DEBUG
,
504 "EAP-TEAP: Failed to get cipher information");
505 eap_teap_state(data
, FAILURE
);
508 data
->anon_provisioning
= os_strstr(cipher
, "ADH") != NULL
;
510 if (data
->anon_provisioning
)
511 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Anonymous provisioning");
513 if (eap_teap_derive_key_auth(sm
, data
) < 0) {
514 eap_teap_state(data
, FAILURE
);
518 eap_teap_state(data
, PHASE2_START
);
524 static struct wpabuf
* eap_teap_build_phase2_req(struct eap_sm
*sm
,
525 struct eap_teap_data
*data
,
530 if (sm
->eap_teap_auth
== 1) {
531 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initiate Basic-Password-Auth");
532 req
= wpabuf_alloc(sizeof(struct teap_tlv_hdr
));
535 eap_teap_put_tlv_hdr(req
, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ
, 0);
539 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initiate inner EAP method");
540 if (!data
->phase2_priv
) {
541 wpa_printf(MSG_DEBUG
,
542 "EAP-TEAP: Phase 2 method not initialized");
546 req
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, id
);
550 wpa_hexdump_buf_key(MSG_MSGDUMP
, "EAP-TEAP: Phase 2 EAP-Request", req
);
551 return eap_teap_tlv_eap_payload(req
);
555 static struct wpabuf
* eap_teap_build_crypto_binding(
556 struct eap_sm
*sm
, struct eap_teap_data
*data
)
559 struct teap_tlv_result
*result
;
560 struct teap_tlv_crypto_binding
*cb
;
563 buf
= wpabuf_alloc(2 * sizeof(*result
) + sizeof(*cb
));
567 if (data
->send_new_pac
|| data
->anon_provisioning
||
569 data
->final_result
= 0;
571 data
->final_result
= 1;
573 if (!data
->final_result
|| data
->eap_seq
> 0) {
574 /* Intermediate-Result */
575 wpa_printf(MSG_DEBUG
,
576 "EAP-TEAP: Add Intermediate-Result TLV (status=SUCCESS)");
577 result
= wpabuf_put(buf
, sizeof(*result
));
578 result
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
579 TEAP_TLV_INTERMEDIATE_RESULT
);
580 result
->length
= host_to_be16(2);
581 result
->status
= host_to_be16(TEAP_STATUS_SUCCESS
);
584 if (data
->final_result
) {
586 wpa_printf(MSG_DEBUG
,
587 "EAP-TEAP: Add Result TLV (status=SUCCESS)");
588 result
= wpabuf_put(buf
, sizeof(*result
));
589 result
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
591 result
->length
= host_to_be16(2);
592 result
->status
= host_to_be16(TEAP_STATUS_SUCCESS
);
595 /* Crypto-Binding TLV */
596 cb
= wpabuf_put(buf
, sizeof(*cb
));
597 cb
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
598 TEAP_TLV_CRYPTO_BINDING
);
599 cb
->length
= host_to_be16(sizeof(*cb
) - sizeof(struct teap_tlv_hdr
));
600 cb
->version
= EAP_TEAP_VERSION
;
601 cb
->received_version
= data
->peer_version
;
602 /* FIX: RFC 7170 is not clear on which Flags value to use when
603 * Crypto-Binding TLV is used with Basic-Password-Auth */
604 flags
= data
->cmk_emsk_available
?
605 TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
:
606 TEAP_CRYPTO_BINDING_MSK_CMAC
;
607 subtype
= TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST
;
608 cb
->subtype
= (flags
<< 4) | subtype
;
609 if (random_get_bytes(cb
->nonce
, sizeof(cb
->nonce
)) < 0) {
615 * RFC 7170, Section 4.2.13:
616 * The nonce in a request MUST have its least significant bit set to 0.
618 cb
->nonce
[sizeof(cb
->nonce
) - 1] &= ~0x01;
620 os_memcpy(data
->crypto_binding_nonce
, cb
->nonce
, sizeof(cb
->nonce
));
622 if (eap_teap_compound_mac(data
->tls_cs
, cb
, data
->server_outer_tlvs
,
623 data
->peer_outer_tlvs
, data
->cmk_msk
,
624 cb
->msk_compound_mac
) < 0) {
629 if (data
->cmk_emsk_available
&&
630 eap_teap_compound_mac(data
->tls_cs
, cb
, data
->server_outer_tlvs
,
631 data
->peer_outer_tlvs
, data
->cmk_emsk
,
632 cb
->emsk_compound_mac
) < 0) {
637 wpa_printf(MSG_DEBUG
,
638 "EAP-TEAP: Add Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
639 cb
->version
, cb
->received_version
, flags
, subtype
);
640 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
641 cb
->nonce
, sizeof(cb
->nonce
));
642 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
643 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
644 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
645 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
651 static struct wpabuf
* eap_teap_build_pac(struct eap_sm
*sm
,
652 struct eap_teap_data
*data
)
654 u8 pac_key
[EAP_TEAP_PAC_KEY_LEN
];
655 u8
*pac_buf
, *pac_opaque
;
658 size_t buf_len
, srv_id_info_len
, pac_len
;
659 struct teap_tlv_hdr
*pac_tlv
;
660 struct pac_attr_hdr
*pac_info
;
661 struct teap_tlv_result
*result
;
664 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Build a new PAC");
666 if (random_get_bytes(pac_key
, EAP_TEAP_PAC_KEY_LEN
) < 0 ||
667 os_get_time(&now
) < 0)
669 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: Generated PAC-Key",
670 pac_key
, EAP_TEAP_PAC_KEY_LEN
);
672 pac_len
= (2 + EAP_TEAP_PAC_KEY_LEN
) + (2 + 4) +
673 (2 + sm
->identity_len
) + 8;
674 pac_buf
= os_malloc(pac_len
);
678 srv_id_info_len
= os_strlen(data
->srv_id_info
);
681 *pos
++ = PAC_OPAQUE_TYPE_KEY
;
682 *pos
++ = EAP_TEAP_PAC_KEY_LEN
;
683 os_memcpy(pos
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
684 pos
+= EAP_TEAP_PAC_KEY_LEN
;
686 wpa_printf(MSG_DEBUG
, "EAP-TEAP: PAC-Key lifetime: %u seconds",
687 data
->pac_key_lifetime
);
688 *pos
++ = PAC_OPAQUE_TYPE_LIFETIME
;
690 WPA_PUT_BE32(pos
, now
.sec
+ data
->pac_key_lifetime
);
694 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque Identity",
695 sm
->identity
, sm
->identity_len
);
696 *pos
++ = PAC_OPAQUE_TYPE_IDENTITY
;
697 *pos
++ = sm
->identity_len
;
698 os_memcpy(pos
, sm
->identity
, sm
->identity_len
);
699 pos
+= sm
->identity_len
;
702 pac_len
= pos
- pac_buf
;
703 while (pac_len
% 8) {
704 *pos
++ = PAC_OPAQUE_TYPE_PAD
;
708 pac_opaque
= os_malloc(pac_len
+ 8);
713 if (aes_wrap(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
),
714 pac_len
/ 8, pac_buf
, pac_opaque
) < 0) {
722 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque", pac_opaque
, pac_len
);
724 buf_len
= sizeof(*pac_tlv
) +
725 sizeof(struct pac_attr_hdr
) + EAP_TEAP_PAC_KEY_LEN
+
726 sizeof(struct pac_attr_hdr
) + pac_len
+
727 data
->srv_id_len
+ srv_id_info_len
+ 100 + sizeof(*result
);
728 buf
= wpabuf_alloc(buf_len
);
735 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add Result TLV (status=SUCCESS)");
736 result
= wpabuf_put(buf
, sizeof(*result
));
737 WPA_PUT_BE16((u8
*) &result
->tlv_type
,
738 TEAP_TLV_MANDATORY
| TEAP_TLV_RESULT
);
739 WPA_PUT_BE16((u8
*) &result
->length
, 2);
740 WPA_PUT_BE16((u8
*) &result
->status
, TEAP_STATUS_SUCCESS
);
743 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV");
744 pac_tlv
= wpabuf_put(buf
, sizeof(*pac_tlv
));
745 pac_tlv
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
| TEAP_TLV_PAC
);
748 eap_teap_put_tlv(buf
, PAC_TYPE_PAC_KEY
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
751 eap_teap_put_tlv(buf
, PAC_TYPE_PAC_OPAQUE
, pac_opaque
, pac_len
);
755 pac_info
= wpabuf_put(buf
, sizeof(*pac_info
));
756 pac_info
->type
= host_to_be16(PAC_TYPE_PAC_INFO
);
758 /* PAC-Lifetime (inside PAC-Info) */
759 eap_teap_put_tlv_hdr(buf
, PAC_TYPE_CRED_LIFETIME
, 4);
760 wpabuf_put_be32(buf
, now
.sec
+ data
->pac_key_lifetime
);
762 /* A-ID (inside PAC-Info) */
763 eap_teap_put_tlv(buf
, PAC_TYPE_A_ID
, data
->srv_id
, data
->srv_id_len
);
765 /* Note: headers may be misaligned after A-ID */
768 eap_teap_put_tlv(buf
, PAC_TYPE_I_ID
, sm
->identity
,
772 /* A-ID-Info (inside PAC-Info) */
773 eap_teap_put_tlv(buf
, PAC_TYPE_A_ID_INFO
, data
->srv_id_info
,
776 /* PAC-Type (inside PAC-Info) */
777 eap_teap_put_tlv_hdr(buf
, PAC_TYPE_PAC_TYPE
, 2);
778 wpabuf_put_be16(buf
, PAC_TYPE_TUNNEL_PAC
);
780 /* Update PAC-Info and PAC TLV Length fields */
781 pos
= wpabuf_put(buf
, 0);
782 pac_info
->len
= host_to_be16(pos
- (u8
*) (pac_info
+ 1));
783 pac_tlv
->length
= host_to_be16(pos
- (u8
*) (pac_tlv
+ 1));
789 static int eap_teap_encrypt_phase2(struct eap_sm
*sm
,
790 struct eap_teap_data
*data
,
791 struct wpabuf
*plain
, int piggyback
)
795 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Encrypting Phase 2 TLVs",
797 encr
= eap_server_tls_encrypt(sm
, &data
->ssl
, plain
);
803 if (data
->ssl
.tls_out
&& piggyback
) {
804 wpa_printf(MSG_DEBUG
,
805 "EAP-TEAP: Piggyback Phase 2 data (len=%d) with last Phase 1 Message (len=%d used=%d)",
806 (int) wpabuf_len(encr
),
807 (int) wpabuf_len(data
->ssl
.tls_out
),
808 (int) data
->ssl
.tls_out_pos
);
809 if (wpabuf_resize(&data
->ssl
.tls_out
, wpabuf_len(encr
)) < 0) {
810 wpa_printf(MSG_WARNING
,
811 "EAP-TEAP: Failed to resize output buffer");
815 wpabuf_put_buf(data
->ssl
.tls_out
, encr
);
818 wpabuf_free(data
->ssl
.tls_out
);
819 data
->ssl
.tls_out_pos
= 0;
820 data
->ssl
.tls_out
= encr
;
827 static struct wpabuf
* eap_teap_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
829 struct eap_teap_data
*data
= priv
;
830 struct wpabuf
*req
= NULL
;
833 if (data
->ssl
.state
== FRAG_ACK
) {
834 return eap_server_tls_build_ack(id
, EAP_TYPE_TEAP
,
838 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
839 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TEAP
,
840 data
->teap_version
, id
);
843 switch (data
->state
) {
845 return eap_teap_build_start(sm
, data
, id
);
847 if (tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
)) {
848 if (eap_teap_phase1_done(sm
, data
) < 0)
850 if (data
->state
== PHASE2_START
) {
854 * Try to generate Phase 2 data to piggyback
855 * with the end of Phase 1 to avoid extra
858 wpa_printf(MSG_DEBUG
,
859 "EAP-TEAP: Try to start Phase 2");
860 res
= eap_teap_process_phase2_start(sm
, data
);
862 req
= eap_teap_build_crypto_binding(
870 req
= eap_teap_build_phase2_req(sm
, data
, id
);
876 case PHASE2_BASIC_AUTH
:
878 req
= eap_teap_build_phase2_req(sm
, data
, id
);
881 req
= eap_teap_build_crypto_binding(sm
, data
);
882 if (data
->phase2_method
) {
884 * Include the start of the next EAP method in the
885 * sequence in the same message with Crypto-Binding to
890 eap
= eap_teap_build_phase2_req(sm
, data
, id
);
891 req
= wpabuf_concat(req
, eap
);
892 eap_teap_state(data
, PHASE2_METHOD
);
896 req
= eap_teap_build_pac(sm
, data
);
898 case FAILURE_SEND_RESULT
:
899 req
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
900 if (data
->error_code
)
902 req
, eap_teap_tlv_error(data
->error_code
));
905 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s - unexpected state %d",
906 __func__
, data
->state
);
910 if (req
&& eap_teap_encrypt_phase2(sm
, data
, req
, piggyback
) < 0)
913 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TEAP
,
914 data
->teap_version
, id
);
918 static Boolean
eap_teap_check(struct eap_sm
*sm
, void *priv
,
919 struct wpabuf
*respData
)
924 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, respData
, &len
);
925 if (!pos
|| len
< 1) {
926 wpa_printf(MSG_INFO
, "EAP-TEAP: Invalid frame");
934 static int eap_teap_phase2_init(struct eap_sm
*sm
, struct eap_teap_data
*data
,
937 if (data
->phase2_priv
&& data
->phase2_method
) {
938 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
939 data
->phase2_method
= NULL
;
940 data
->phase2_priv
= NULL
;
942 data
->phase2_method
= eap_server_get_eap_method(EAP_VENDOR_IETF
,
944 if (!data
->phase2_method
)
948 data
->phase2_priv
= data
->phase2_method
->init(sm
);
951 return data
->phase2_priv
? 0 : -1;
955 static void eap_teap_process_phase2_response(struct eap_sm
*sm
,
956 struct eap_teap_data
*data
,
957 u8
*in_data
, size_t in_len
)
959 u8 next_type
= EAP_TYPE_NONE
;
964 const struct eap_method
*m
= data
->phase2_method
;
965 void *priv
= data
->phase2_priv
;
968 wpa_printf(MSG_DEBUG
,
969 "EAP-TEAP: %s - Phase 2 not initialized?!",
974 hdr
= (struct eap_hdr
*) in_data
;
975 pos
= (u8
*) (hdr
+ 1);
977 if (in_len
> sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
978 left
= in_len
- sizeof(*hdr
);
979 wpa_hexdump(MSG_DEBUG
,
980 "EAP-TEAP: Phase 2 type Nak'ed; allowed types",
982 #ifdef EAP_SERVER_TNC
983 if (m
&& m
->vendor
== EAP_VENDOR_IETF
&&
984 m
->method
== EAP_TYPE_TNC
) {
985 wpa_printf(MSG_DEBUG
,
986 "EAP-TEAP: Peer Nak'ed required TNC negotiation");
987 next_type
= eap_teap_req_failure(data
, 0);
988 eap_teap_phase2_init(sm
, data
, next_type
);
991 #endif /* EAP_SERVER_TNC */
992 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
993 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
994 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
996 next_type
= sm
->user
->methods
[
997 sm
->user_eap_method_index
++].method
;
998 wpa_printf(MSG_DEBUG
, "EAP-TEAP: try EAP type %d",
1001 next_type
= eap_teap_req_failure(data
, 0);
1003 eap_teap_phase2_init(sm
, data
, next_type
);
1007 wpabuf_set(&buf
, in_data
, in_len
);
1009 if (m
->check(sm
, priv
, &buf
)) {
1010 wpa_printf(MSG_DEBUG
,
1011 "EAP-TEAP: Phase 2 check() asked to ignore the packet");
1012 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1016 m
->process(sm
, priv
, &buf
);
1018 if (!m
->isDone(sm
, priv
))
1021 if (!m
->isSuccess(sm
, priv
)) {
1022 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 2 method failed");
1023 next_type
= eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1024 eap_teap_phase2_init(sm
, data
, next_type
);
1028 switch (data
->state
) {
1030 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1031 wpa_hexdump_ascii(MSG_DEBUG
,
1032 "EAP-TEAP: Phase 2 Identity not found in the user database",
1033 sm
->identity
, sm
->identity_len
);
1034 next_type
= eap_teap_req_failure(
1035 data
, TEAP_ERROR_INNER_METHOD
);
1039 eap_teap_state(data
, PHASE2_METHOD
);
1040 if (data
->anon_provisioning
) {
1041 /* TODO: Allow any inner EAP method that provides
1042 * mutual authentication and EMSK derivation (i.e.,
1043 * EAP-pwd or EAP-EKE). */
1044 next_type
= EAP_TYPE_PWD
;
1045 sm
->user_eap_method_index
= 0;
1047 next_type
= sm
->user
->methods
[0].method
;
1048 sm
->user_eap_method_index
= 1;
1050 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Try EAP type %d", next_type
);
1053 case CRYPTO_BINDING
:
1054 eap_teap_update_icmk(sm
, data
);
1055 eap_teap_state(data
, CRYPTO_BINDING
);
1057 next_type
= EAP_TYPE_NONE
;
1058 #ifdef EAP_SERVER_TNC
1059 if (sm
->tnc
&& !data
->tnc_started
) {
1060 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initialize TNC");
1061 next_type
= EAP_TYPE_TNC
;
1062 data
->tnc_started
= 1;
1064 #endif /* EAP_SERVER_TNC */
1069 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s - unexpected state %d",
1070 __func__
, data
->state
);
1074 eap_teap_phase2_init(sm
, data
, next_type
);
1078 static void eap_teap_process_phase2_eap(struct eap_sm
*sm
,
1079 struct eap_teap_data
*data
,
1080 u8
*in_data
, size_t in_len
)
1082 struct eap_hdr
*hdr
;
1085 hdr
= (struct eap_hdr
*) in_data
;
1086 if (in_len
< (int) sizeof(*hdr
)) {
1087 wpa_printf(MSG_INFO
,
1088 "EAP-TEAP: Too short Phase 2 EAP frame (len=%lu)",
1089 (unsigned long) in_len
);
1090 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1093 len
= be_to_host16(hdr
->length
);
1095 wpa_printf(MSG_INFO
,
1096 "EAP-TEAP: Length mismatch in Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1097 (unsigned long) in_len
, (unsigned long) len
);
1098 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1101 wpa_printf(MSG_DEBUG
,
1102 "EAP-TEAP: Received Phase 2: code=%d identifier=%d length=%lu",
1103 hdr
->code
, hdr
->identifier
,
1104 (unsigned long) len
);
1105 switch (hdr
->code
) {
1106 case EAP_CODE_RESPONSE
:
1107 eap_teap_process_phase2_response(sm
, data
, (u8
*) hdr
, len
);
1110 wpa_printf(MSG_INFO
,
1111 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
1118 static void eap_teap_process_basic_auth_resp(struct eap_sm
*sm
,
1119 struct eap_teap_data
*data
,
1120 u8
*in_data
, size_t in_len
)
1122 u8
*pos
, *end
, *username
, *password
, *new_id
;
1123 u8 userlen
, passlen
;
1128 if (end
- pos
< 1) {
1129 wpa_printf(MSG_DEBUG
,
1130 "EAP-TEAP: No room for Basic-Password-Auth-Resp Userlen field");
1131 eap_teap_req_failure(data
, 0);
1135 if (end
- pos
< userlen
) {
1136 wpa_printf(MSG_DEBUG
,
1137 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Username field");
1138 eap_teap_req_failure(data
, 0);
1143 wpa_hexdump_ascii(MSG_DEBUG
,
1144 "EAP-TEAP: Basic-Password-Auth-Resp Username",
1147 if (end
- pos
< 1) {
1148 wpa_printf(MSG_DEBUG
,
1149 "EAP-TEAP: No room for Basic-Password-Auth-Resp Passlen field");
1150 eap_teap_req_failure(data
, 0);
1154 if (end
- pos
< passlen
) {
1155 wpa_printf(MSG_DEBUG
,
1156 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Password field");
1157 eap_teap_req_failure(data
, 0);
1162 wpa_hexdump_ascii_key(MSG_DEBUG
,
1163 "EAP-TEAP: Basic-Password-Auth-Resp Password",
1167 wpa_printf(MSG_DEBUG
,
1168 "EAP-TEAP: Unexpected %d extra octet(s) at the end of Basic-Password-Auth-Resp TLV",
1170 eap_teap_req_failure(data
, 0);
1174 if (eap_user_get(sm
, username
, userlen
, 1) != 0) {
1175 wpa_printf(MSG_DEBUG
,
1176 "EAP-TEAP: Username not found in the user database");
1177 eap_teap_req_failure(data
, 0);
1181 if (!sm
->user
|| !sm
->user
->password
|| sm
->user
->password_hash
) {
1182 wpa_printf(MSG_DEBUG
,
1183 "EAP-TEAP: No plaintext user password configured");
1184 eap_teap_req_failure(data
, 0);
1188 if (sm
->user
->password_len
!= passlen
||
1189 os_memcmp_const(sm
->user
->password
, password
, passlen
) != 0) {
1190 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Invalid password");
1191 eap_teap_req_failure(data
, 0);
1195 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Correct password");
1196 new_id
= os_memdup(username
, userlen
);
1198 os_free(sm
->identity
);
1199 sm
->identity
= new_id
;
1200 sm
->identity_len
= userlen
;
1202 eap_teap_state(data
, CRYPTO_BINDING
);
1203 eap_teap_update_icmk(sm
, data
);
1207 static int eap_teap_parse_tlvs(struct wpabuf
*data
,
1208 struct eap_teap_tlv_parse
*tlv
)
1215 os_memset(tlv
, 0, sizeof(*tlv
));
1217 pos
= wpabuf_mhead(data
);
1218 end
= pos
+ wpabuf_len(data
);
1219 while (end
- pos
> 4) {
1220 mandatory
= pos
[0] & 0x80;
1221 tlv_type
= WPA_GET_BE16(pos
) & 0x3fff;
1223 len
= WPA_GET_BE16(pos
);
1225 if (len
> (size_t) (end
- pos
)) {
1226 wpa_printf(MSG_INFO
, "EAP-TEAP: TLV overflow");
1229 wpa_printf(MSG_DEBUG
,
1230 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1231 tlv_type
, eap_teap_tlv_type_str(tlv_type
),
1233 mandatory
? " (mandatory)" : "");
1235 res
= eap_teap_parse_tlv(tlv
, tlv_type
, pos
, len
);
1240 wpa_printf(MSG_DEBUG
,
1241 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1243 /* TODO: generate NAK TLV */
1247 wpa_printf(MSG_DEBUG
,
1248 "EAP-TEAP: Ignore unknown optional TLV type %u",
1259 static int eap_teap_validate_crypto_binding(
1260 struct eap_teap_data
*data
, const struct teap_tlv_crypto_binding
*cb
,
1265 subtype
= cb
->subtype
& 0x0f;
1266 flags
= cb
->subtype
>> 4;
1268 wpa_printf(MSG_DEBUG
,
1269 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
1270 cb
->version
, cb
->received_version
, flags
, subtype
);
1271 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
1272 cb
->nonce
, sizeof(cb
->nonce
));
1273 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
1274 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
1275 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
1276 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
1278 if (cb
->version
!= EAP_TEAP_VERSION
||
1279 cb
->received_version
!= data
->peer_version
) {
1280 wpa_printf(MSG_DEBUG
,
1281 "EAP-TEAP: Unexpected version in Crypto-Binding: Version %u Received Version %u",
1282 cb
->version
, cb
->received_version
);
1286 if (flags
< 1 || flags
> 3) {
1287 wpa_printf(MSG_DEBUG
,
1288 "EAP-TEAP: Unexpected Flags in Crypto-Binding: %u",
1293 if (subtype
!= TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE
) {
1294 wpa_printf(MSG_DEBUG
,
1295 "EAP-TEAP: Unexpected Sub-Type in Crypto-Binding: %u",
1300 if (os_memcmp_const(data
->crypto_binding_nonce
, cb
->nonce
,
1301 EAP_TEAP_NONCE_LEN
- 1) != 0 ||
1302 (data
->crypto_binding_nonce
[EAP_TEAP_NONCE_LEN
- 1] | 1) !=
1303 cb
->nonce
[EAP_TEAP_NONCE_LEN
- 1]) {
1304 wpa_printf(MSG_DEBUG
,
1305 "EAP-TEAP: Invalid Nonce in Crypto-Binding");
1309 if (flags
== TEAP_CRYPTO_BINDING_MSK_CMAC
||
1310 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) {
1311 u8 msk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
1313 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
1314 data
->server_outer_tlvs
,
1315 data
->peer_outer_tlvs
, data
->cmk_msk
,
1316 msk_compound_mac
) < 0)
1318 if (os_memcmp_const(msk_compound_mac
, cb
->msk_compound_mac
,
1319 EAP_TEAP_COMPOUND_MAC_LEN
) != 0) {
1320 wpa_hexdump(MSG_DEBUG
,
1321 "EAP-TEAP: Calculated MSK Compound MAC",
1323 EAP_TEAP_COMPOUND_MAC_LEN
);
1324 wpa_printf(MSG_INFO
,
1325 "EAP-TEAP: MSK Compound MAC did not match");
1330 if ((flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
||
1331 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) &&
1332 data
->cmk_emsk_available
) {
1333 u8 emsk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
1335 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
1336 data
->server_outer_tlvs
,
1337 data
->peer_outer_tlvs
, data
->cmk_emsk
,
1338 emsk_compound_mac
) < 0)
1340 if (os_memcmp_const(emsk_compound_mac
, cb
->emsk_compound_mac
,
1341 EAP_TEAP_COMPOUND_MAC_LEN
) != 0) {
1342 wpa_hexdump(MSG_DEBUG
,
1343 "EAP-TEAP: Calculated EMSK Compound MAC",
1345 EAP_TEAP_COMPOUND_MAC_LEN
);
1346 wpa_printf(MSG_INFO
,
1347 "EAP-TEAP: EMSK Compound MAC did not match");
1352 if (flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
&&
1353 !data
->cmk_emsk_available
) {
1354 wpa_printf(MSG_INFO
,
1355 "EAP-TEAP: Peer included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
1363 static int eap_teap_pac_type(u8
*pac
, size_t len
, u16 type
)
1365 struct teap_attr_pac_type
*tlv
;
1367 if (!pac
|| len
!= sizeof(*tlv
))
1370 tlv
= (struct teap_attr_pac_type
*) pac
;
1372 return be_to_host16(tlv
->type
) == PAC_TYPE_PAC_TYPE
&&
1373 be_to_host16(tlv
->length
) == 2 &&
1374 be_to_host16(tlv
->pac_type
) == type
;
1378 static void eap_teap_process_phase2_tlvs(struct eap_sm
*sm
,
1379 struct eap_teap_data
*data
,
1380 struct wpabuf
*in_data
)
1382 struct eap_teap_tlv_parse tlv
;
1383 int check_crypto_binding
= data
->state
== CRYPTO_BINDING
;
1385 if (eap_teap_parse_tlvs(in_data
, &tlv
) < 0) {
1386 wpa_printf(MSG_DEBUG
,
1387 "EAP-TEAP: Failed to parse received Phase 2 TLVs");
1391 if (tlv
.result
== TEAP_STATUS_FAILURE
) {
1392 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Result TLV indicated failure");
1393 eap_teap_state(data
, FAILURE
);
1398 wpa_printf(MSG_DEBUG
,
1399 "EAP-TEAP: Peer NAK'ed Vendor-Id %u NAK-Type %u",
1400 WPA_GET_BE32(tlv
.nak
), WPA_GET_BE16(tlv
.nak
+ 4));
1401 eap_teap_state(data
, FAILURE_SEND_RESULT
);
1405 if (data
->state
== REQUEST_PAC
) {
1408 if (!tlv
.pac
|| tlv
.pac_len
< 6) {
1409 wpa_printf(MSG_DEBUG
,
1410 "EAP-TEAP: No PAC Acknowledgement received");
1411 eap_teap_state(data
, FAILURE
);
1415 type
= WPA_GET_BE16(tlv
.pac
);
1416 len
= WPA_GET_BE16(tlv
.pac
+ 2);
1417 res
= WPA_GET_BE16(tlv
.pac
+ 4);
1419 if (type
!= PAC_TYPE_PAC_ACKNOWLEDGEMENT
|| len
!= 2 ||
1420 res
!= TEAP_STATUS_SUCCESS
) {
1421 wpa_printf(MSG_DEBUG
,
1422 "EAP-TEAP: PAC TLV did not contain acknowledgement");
1423 eap_teap_state(data
, FAILURE
);
1427 wpa_printf(MSG_DEBUG
,
1428 "EAP-TEAP: PAC-Acknowledgement received - PAC provisioning succeeded");
1429 eap_teap_state(data
, SUCCESS
);
1433 if (check_crypto_binding
) {
1434 if (!tlv
.crypto_binding
) {
1435 wpa_printf(MSG_DEBUG
,
1436 "EAP-TEAP: No Crypto-Binding TLV received");
1437 eap_teap_state(data
, FAILURE
);
1441 if (data
->final_result
&&
1442 tlv
.result
!= TEAP_STATUS_SUCCESS
) {
1443 wpa_printf(MSG_DEBUG
,
1444 "EAP-TEAP: Crypto-Binding TLV without Success Result");
1445 eap_teap_state(data
, FAILURE
);
1449 if (sm
->eap_teap_auth
!= 1 &&
1450 tlv
.iresult
!= TEAP_STATUS_SUCCESS
) {
1451 wpa_printf(MSG_DEBUG
,
1452 "EAP-TEAP: Crypto-Binding TLV without intermediate Success Result");
1453 eap_teap_state(data
, FAILURE
);
1457 if (eap_teap_validate_crypto_binding(data
, tlv
.crypto_binding
,
1458 tlv
.crypto_binding_len
)) {
1459 eap_teap_state(data
, FAILURE
);
1463 wpa_printf(MSG_DEBUG
,
1464 "EAP-TEAP: Valid Crypto-Binding TLV received");
1465 if (data
->final_result
) {
1466 wpa_printf(MSG_DEBUG
,
1467 "EAP-TEAP: Authentication completed successfully");
1470 if (data
->anon_provisioning
&&
1471 sm
->eap_fast_prov
!= ANON_PROV
&&
1472 sm
->eap_fast_prov
!= BOTH_PROV
) {
1473 wpa_printf(MSG_DEBUG
,
1474 "EAP-TEAP: Client is trying to use unauthenticated provisioning which is disabled");
1475 eap_teap_state(data
, FAILURE
);
1479 if (sm
->eap_fast_prov
!= AUTH_PROV
&&
1480 sm
->eap_fast_prov
!= BOTH_PROV
&&
1481 tlv
.request_action
== TEAP_REQUEST_ACTION_PROCESS_TLV
&&
1482 eap_teap_pac_type(tlv
.pac
, tlv
.pac_len
,
1483 PAC_TYPE_TUNNEL_PAC
)) {
1484 wpa_printf(MSG_DEBUG
,
1485 "EAP-TEAP: Client is trying to use authenticated provisioning which is disabled");
1486 eap_teap_state(data
, FAILURE
);
1490 if (data
->anon_provisioning
||
1491 (tlv
.request_action
== TEAP_REQUEST_ACTION_PROCESS_TLV
&&
1492 eap_teap_pac_type(tlv
.pac
, tlv
.pac_len
,
1493 PAC_TYPE_TUNNEL_PAC
))) {
1494 wpa_printf(MSG_DEBUG
,
1495 "EAP-TEAP: Requested a new Tunnel PAC");
1496 eap_teap_state(data
, REQUEST_PAC
);
1497 } else if (data
->send_new_pac
) {
1498 wpa_printf(MSG_DEBUG
,
1499 "EAP-TEAP: Server triggered re-keying of Tunnel PAC");
1500 eap_teap_state(data
, REQUEST_PAC
);
1501 } else if (data
->final_result
)
1502 eap_teap_state(data
, SUCCESS
);
1505 if (tlv
.basic_auth_resp
) {
1506 if (sm
->eap_teap_auth
!= 1) {
1507 wpa_printf(MSG_DEBUG
,
1508 "EAP-TEAP: Unexpected Basic-Password-Auth-Resp when trying to use inner EAP");
1509 eap_teap_state(data
, FAILURE
);
1512 eap_teap_process_basic_auth_resp(sm
, data
, tlv
.basic_auth_resp
,
1513 tlv
.basic_auth_resp_len
);
1516 if (tlv
.eap_payload_tlv
) {
1517 if (sm
->eap_teap_auth
== 1) {
1518 wpa_printf(MSG_DEBUG
,
1519 "EAP-TEAP: Unexpected EAP Payload TLV when trying to use Basic-Password-Auth");
1520 eap_teap_state(data
, FAILURE
);
1523 eap_teap_process_phase2_eap(sm
, data
, tlv
.eap_payload_tlv
,
1524 tlv
.eap_payload_tlv_len
);
1529 static void eap_teap_process_phase2(struct eap_sm
*sm
,
1530 struct eap_teap_data
*data
,
1531 struct wpabuf
*in_buf
)
1533 struct wpabuf
*in_decrypted
;
1535 wpa_printf(MSG_DEBUG
,
1536 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1537 (unsigned long) wpabuf_len(in_buf
));
1539 if (data
->pending_phase2_resp
) {
1540 wpa_printf(MSG_DEBUG
,
1541 "EAP-TEAP: Pending Phase 2 response - skip decryption and use old data");
1542 eap_teap_process_phase2_tlvs(sm
, data
,
1543 data
->pending_phase2_resp
);
1544 wpabuf_free(data
->pending_phase2_resp
);
1545 data
->pending_phase2_resp
= NULL
;
1549 in_decrypted
= tls_connection_decrypt(sm
->ssl_ctx
, data
->ssl
.conn
,
1551 if (!in_decrypted
) {
1552 wpa_printf(MSG_INFO
,
1553 "EAP-TEAP: Failed to decrypt Phase 2 data");
1554 eap_teap_state(data
, FAILURE
);
1558 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Decrypted Phase 2 TLVs",
1561 eap_teap_process_phase2_tlvs(sm
, data
, in_decrypted
);
1563 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
1564 wpa_printf(MSG_DEBUG
,
1565 "EAP-TEAP: Phase 2 method is in pending wait state - save decrypted response");
1566 wpabuf_free(data
->pending_phase2_resp
);
1567 data
->pending_phase2_resp
= in_decrypted
;
1571 wpabuf_free(in_decrypted
);
1575 static int eap_teap_process_version(struct eap_sm
*sm
, void *priv
,
1578 struct eap_teap_data
*data
= priv
;
1580 if (peer_version
< 1) {
1581 /* Version 1 was the first defined version, so reject 0 */
1582 wpa_printf(MSG_INFO
,
1583 "EAP-TEAP: Peer used unknown TEAP version %u",
1588 if (peer_version
< data
->teap_version
) {
1589 wpa_printf(MSG_DEBUG
, "EAP-TEAP: peer ver=%u, own ver=%u; "
1591 peer_version
, data
->teap_version
, peer_version
);
1592 data
->teap_version
= peer_version
;
1595 data
->peer_version
= peer_version
;
1601 static int eap_teap_process_phase1(struct eap_sm
*sm
,
1602 struct eap_teap_data
*data
)
1604 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0) {
1605 wpa_printf(MSG_INFO
, "EAP-TEAP: TLS processing failed");
1606 eap_teap_state(data
, FAILURE
);
1610 if (!tls_connection_established(sm
->ssl_ctx
, data
->ssl
.conn
) ||
1611 wpabuf_len(data
->ssl
.tls_out
) > 0)
1615 * Phase 1 was completed with the received message (e.g., when using
1616 * abbreviated handshake), so Phase 2 can be started immediately
1617 * without having to send through an empty message to the peer.
1620 return eap_teap_phase1_done(sm
, data
);
1624 static int eap_teap_process_phase2_start(struct eap_sm
*sm
,
1625 struct eap_teap_data
*data
)
1629 if (data
->identity
) {
1630 /* Used PAC and identity is from PAC-Opaque */
1631 os_free(sm
->identity
);
1632 sm
->identity
= data
->identity
;
1633 data
->identity
= NULL
;
1634 sm
->identity_len
= data
->identity_len
;
1635 data
->identity_len
= 0;
1636 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1637 wpa_hexdump_ascii(MSG_DEBUG
,
1638 "EAP-TEAP: Phase 2 Identity not found in the user database",
1639 sm
->identity
, sm
->identity_len
);
1640 next_type
= EAP_TYPE_NONE
;
1641 eap_teap_state(data
, PHASE2_METHOD
);
1642 } else if (sm
->eap_teap_pac_no_inner
) {
1643 wpa_printf(MSG_DEBUG
,
1644 "EAP-TEAP: Used PAC and identity already known - skip inner auth");
1645 /* FIX: Need to derive CMK here. However, how is that
1646 * supposed to be done? RFC 7170 does not tell that for
1647 * the no-inner-auth case. */
1648 eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
1651 eap_teap_state(data
, CRYPTO_BINDING
);
1653 } else if (sm
->eap_teap_auth
== 1) {
1654 eap_teap_state(data
, PHASE2_BASIC_AUTH
);
1657 wpa_printf(MSG_DEBUG
,
1658 "EAP-TEAP: Identity already known - skip Phase 2 Identity Request");
1659 next_type
= sm
->user
->methods
[0].method
;
1660 sm
->user_eap_method_index
= 1;
1661 eap_teap_state(data
, PHASE2_METHOD
);
1664 } else if (sm
->eap_teap_auth
== 1) {
1665 eap_teap_state(data
, PHASE2_BASIC_AUTH
);
1668 eap_teap_state(data
, PHASE2_ID
);
1669 next_type
= EAP_TYPE_IDENTITY
;
1672 return eap_teap_phase2_init(sm
, data
, next_type
);
1676 static void eap_teap_process_msg(struct eap_sm
*sm
, void *priv
,
1677 const struct wpabuf
*respData
)
1679 struct eap_teap_data
*data
= priv
;
1681 switch (data
->state
) {
1684 if (eap_teap_process_phase1(sm
, data
))
1689 eap_teap_process_phase2_start(sm
, data
);
1692 case PHASE2_BASIC_AUTH
:
1694 case CRYPTO_BINDING
:
1696 eap_teap_process_phase2(sm
, data
, data
->ssl
.tls_in
);
1698 case FAILURE_SEND_RESULT
:
1699 /* Protected failure result indication completed. Ignore the
1700 * received message (which is supposed to include Result TLV
1701 * indicating failure) and terminate exchange with cleartext
1703 eap_teap_state(data
, FAILURE
);
1706 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Unexpected state %d in %s",
1707 data
->state
, __func__
);
1713 static void eap_teap_process(struct eap_sm
*sm
, void *priv
,
1714 struct wpabuf
*respData
)
1716 struct eap_teap_data
*data
= priv
;
1719 struct wpabuf
*resp
= respData
;
1722 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, respData
, &len
);
1723 if (!pos
|| len
< 1)
1729 if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1730 /* Extract Outer TLVs from the message before common TLS
1732 u32 message_len
= 0, outer_tlv_len
;
1735 if (data
->state
!= PHASE1
) {
1736 wpa_printf(MSG_INFO
,
1737 "EAP-TEAP: Unexpected Outer TLVs in a message that is not the first message from the peer");
1741 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
1743 wpa_printf(MSG_INFO
,
1744 "EAP-TEAP: Too short message to include Message Length field");
1748 message_len
= WPA_GET_BE32(pos
);
1751 if (message_len
< 4) {
1752 wpa_printf(MSG_INFO
,
1753 "EAP-TEAP: Message Length field has too msall value to include Outer TLV Length field");
1759 wpa_printf(MSG_INFO
,
1760 "EAP-TEAP: Too short message to include Outer TLVs Length field");
1764 outer_tlv_len
= WPA_GET_BE32(pos
);
1768 wpa_printf(MSG_DEBUG
,
1769 "EAP-TEAP: Message Length %u Outer TLV Length %u",
1770 message_len
, outer_tlv_len
);
1771 if (len
< outer_tlv_len
) {
1772 wpa_printf(MSG_INFO
,
1773 "EAP-TEAP: Too short message to include Outer TLVs field");
1778 (message_len
< outer_tlv_len
||
1779 message_len
< 4 + outer_tlv_len
)) {
1780 wpa_printf(MSG_INFO
,
1781 "EAP-TEAP: Message Length field has too small value to include Outer TLVs");
1785 if (wpabuf_len(respData
) < 4 + outer_tlv_len
||
1786 len
< outer_tlv_len
)
1788 resp
= wpabuf_alloc(wpabuf_len(respData
) - 4 - outer_tlv_len
);
1791 hdr
= wpabuf_head(respData
);
1792 wpabuf_put_u8(resp
, *hdr
++); /* Code */
1793 wpabuf_put_u8(resp
, *hdr
++); /* Identifier */
1794 wpabuf_put_be16(resp
, WPA_GET_BE16(hdr
) - 4 - outer_tlv_len
);
1796 wpabuf_put_u8(resp
, *hdr
++); /* Type */
1798 wpabuf_put_u8(resp
, flags
& ~EAP_TEAP_FLAGS_OUTER_TLV_LEN
);
1800 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
)
1801 wpabuf_put_be32(resp
, message_len
- 4 - outer_tlv_len
);
1803 wpabuf_put_data(resp
, pos
, len
- outer_tlv_len
);
1804 pos
+= len
- outer_tlv_len
;
1805 wpabuf_free(data
->peer_outer_tlvs
);
1806 data
->peer_outer_tlvs
= wpabuf_alloc_copy(pos
, outer_tlv_len
);
1807 if (!data
->peer_outer_tlvs
)
1809 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: Outer TLVs",
1810 data
->peer_outer_tlvs
);
1812 wpa_hexdump_buf(MSG_DEBUG
,
1813 "EAP-TEAP: TLS Data message after Outer TLV removal",
1815 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, resp
,
1817 if (!pos
|| len
< 1) {
1818 wpa_printf(MSG_INFO
,
1819 "EAP-TEAP: Invalid frame after Outer TLV removal");
1824 if (data
->state
== PHASE1
)
1825 eap_teap_state(data
, PHASE1B
);
1827 if (eap_server_tls_process(sm
, &data
->ssl
, resp
, data
,
1828 EAP_TYPE_TEAP
, eap_teap_process_version
,
1829 eap_teap_process_msg
) < 0)
1830 eap_teap_state(data
, FAILURE
);
1832 if (resp
!= respData
)
1837 static Boolean
eap_teap_isDone(struct eap_sm
*sm
, void *priv
)
1839 struct eap_teap_data
*data
= priv
;
1841 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1845 static u8
* eap_teap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1847 struct eap_teap_data
*data
= priv
;
1850 if (data
->state
!= SUCCESS
)
1853 eapKeyData
= os_malloc(EAP_TEAP_KEY_LEN
);
1857 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
1858 * is used in this derivation */
1859 if (eap_teap_derive_eap_msk(data
->tls_cs
, data
->simck_msk
,
1861 os_free(eapKeyData
);
1864 *len
= EAP_TEAP_KEY_LEN
;
1870 static u8
* eap_teap_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
1872 struct eap_teap_data
*data
= priv
;
1875 if (data
->state
!= SUCCESS
)
1878 eapKeyData
= os_malloc(EAP_EMSK_LEN
);
1882 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
1883 * is used in this derivation */
1884 if (eap_teap_derive_eap_emsk(data
->tls_cs
, data
->simck_msk
,
1886 os_free(eapKeyData
);
1889 *len
= EAP_EMSK_LEN
;
1895 static Boolean
eap_teap_isSuccess(struct eap_sm
*sm
, void *priv
)
1897 struct eap_teap_data
*data
= priv
;
1899 return data
->state
== SUCCESS
;
1903 static u8
* eap_teap_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
1905 struct eap_teap_data
*data
= priv
;
1906 const size_t max_id_len
= 100;
1910 if (data
->state
!= SUCCESS
)
1913 id
= os_malloc(max_id_len
);
1917 id
[0] = EAP_TYPE_TEAP
;
1918 res
= tls_get_tls_unique(data
->ssl
.conn
, id
+ 1, max_id_len
- 1);
1921 wpa_printf(MSG_ERROR
, "EAP-TEAP: Failed to derive Session-Id");
1926 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Derived Session-Id", id
, *len
);
1931 int eap_server_teap_register(void)
1933 struct eap_method
*eap
;
1935 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
1936 EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, "TEAP");
1940 eap
->init
= eap_teap_init
;
1941 eap
->reset
= eap_teap_reset
;
1942 eap
->buildReq
= eap_teap_buildReq
;
1943 eap
->check
= eap_teap_check
;
1944 eap
->process
= eap_teap_process
;
1945 eap
->isDone
= eap_teap_isDone
;
1946 eap
->getKey
= eap_teap_getKey
;
1947 eap
->get_emsk
= eap_teap_get_emsk
;
1948 eap
->isSuccess
= eap_teap_isSuccess
;
1949 eap
->getSessionId
= eap_teap_get_session_id
;
1951 return eap_server_method_register(eap
);