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_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 unsigned int basic_auth_not_done
:1;
60 unsigned int inner_eap_not_done
:1;
61 int anon_provisioning
;
62 int skipped_inner_auth
;
63 int send_new_pac
; /* server triggered re-keying of Tunnel PAC */
64 struct wpabuf
*pending_phase2_resp
;
65 struct wpabuf
*server_outer_tlvs
;
66 struct wpabuf
*peer_outer_tlvs
;
67 u8
*identity
; /* from PAC-Opaque */
73 int pac_key_refresh_time
;
75 enum teap_error_codes error_code
;
76 enum teap_identity_types cur_id_type
;
80 static int eap_teap_process_phase2_start(struct eap_sm
*sm
,
81 struct eap_teap_data
*data
);
84 static const char * eap_teap_state_txt(int state
)
94 return "PHASE2_START";
97 case PHASE2_BASIC_AUTH
:
98 return "PHASE2_BASIC_AUTH";
100 return "PHASE2_METHOD";
102 return "CRYPTO_BINDING";
104 return "REQUEST_PAC";
105 case FAILURE_SEND_RESULT
:
106 return "FAILURE_SEND_RESULT";
107 case SUCCESS_SEND_RESULT
:
108 return "SUCCESS_SEND_RESULT";
119 static void eap_teap_state(struct eap_teap_data
*data
, int state
)
121 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s -> %s",
122 eap_teap_state_txt(data
->state
),
123 eap_teap_state_txt(state
));
128 static enum eap_type
eap_teap_req_failure(struct eap_teap_data
*data
,
129 enum teap_error_codes error
)
131 eap_teap_state(data
, FAILURE_SEND_RESULT
);
132 return EAP_TYPE_NONE
;
136 static int eap_teap_session_ticket_cb(void *ctx
, const u8
*ticket
, size_t len
,
137 const u8
*client_random
,
138 const u8
*server_random
,
141 struct eap_teap_data
*data
= ctx
;
142 const u8
*pac_opaque
;
143 size_t pac_opaque_len
;
144 u8
*buf
, *pos
, *end
, *pac_key
= NULL
;
145 os_time_t lifetime
= 0;
148 size_t identity_len
= 0;
150 wpa_printf(MSG_DEBUG
, "EAP-TEAP: SessionTicket callback");
151 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: SessionTicket (PAC-Opaque)",
154 if (len
< 4 || WPA_GET_BE16(ticket
) != PAC_TYPE_PAC_OPAQUE
) {
155 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Ignore invalid SessionTicket");
159 pac_opaque_len
= WPA_GET_BE16(ticket
+ 2);
160 pac_opaque
= ticket
+ 4;
161 if (pac_opaque_len
< 8 || pac_opaque_len
% 8 ||
162 pac_opaque_len
> len
- 4) {
163 wpa_printf(MSG_DEBUG
,
164 "EAP-TEAP: Ignore invalid PAC-Opaque (len=%lu left=%lu)",
165 (unsigned long) pac_opaque_len
,
166 (unsigned long) len
);
169 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Received PAC-Opaque",
170 pac_opaque
, pac_opaque_len
);
172 buf
= os_malloc(pac_opaque_len
- 8);
174 wpa_printf(MSG_DEBUG
,
175 "EAP-TEAP: Failed to allocate memory for decrypting PAC-Opaque");
179 if (aes_unwrap(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
),
180 (pac_opaque_len
- 8) / 8, pac_opaque
, buf
) < 0) {
181 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Failed to decrypt PAC-Opaque");
184 * This may have been caused by server changing the PAC-Opaque
185 * encryption key, so just ignore this PAC-Opaque instead of
186 * failing the authentication completely. Provisioning can now
187 * be used to provision a new PAC.
192 end
= buf
+ pac_opaque_len
- 8;
193 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: Decrypted PAC-Opaque",
197 while (end
- pos
> 1) {
202 if (elen
> end
- pos
)
206 case PAC_OPAQUE_TYPE_PAD
:
208 case PAC_OPAQUE_TYPE_KEY
:
209 if (elen
!= EAP_TEAP_PAC_KEY_LEN
) {
210 wpa_printf(MSG_DEBUG
,
211 "EAP-TEAP: Invalid PAC-Key length %d",
217 wpa_hexdump_key(MSG_DEBUG
,
218 "EAP-TEAP: PAC-Key from decrypted PAC-Opaque",
219 pac_key
, EAP_TEAP_PAC_KEY_LEN
);
221 case PAC_OPAQUE_TYPE_LIFETIME
:
223 wpa_printf(MSG_DEBUG
,
224 "EAP-TEAP: Invalid PAC-Key lifetime length %d",
229 lifetime
= WPA_GET_BE32(pos
);
231 case PAC_OPAQUE_TYPE_IDENTITY
:
242 wpa_printf(MSG_DEBUG
,
243 "EAP-TEAP: No PAC-Key included in PAC-Opaque");
249 wpa_hexdump_ascii(MSG_DEBUG
,
250 "EAP-TEAP: Identity from PAC-Opaque",
251 identity
, identity_len
);
252 os_free(data
->identity
);
253 data
->identity
= os_malloc(identity_len
);
254 if (data
->identity
) {
255 os_memcpy(data
->identity
, identity
, identity_len
);
256 data
->identity_len
= identity_len
;
260 if (os_get_time(&now
) < 0 || lifetime
<= 0 || now
.sec
> lifetime
) {
261 wpa_printf(MSG_DEBUG
,
262 "EAP-TEAP: PAC-Key not valid anymore (lifetime=%ld now=%ld)",
264 data
->send_new_pac
= 2;
266 * Allow PAC to be used to allow a PAC update with some level
267 * of server authentication (i.e., do not fall back to full TLS
268 * handshake since we cannot be sure that the peer would be
269 * able to validate server certificate now). However, reject
270 * the authentication since the PAC was not valid anymore. Peer
271 * can connect again with the newly provisioned PAC after this.
273 } else if (lifetime
- now
.sec
< data
->pac_key_refresh_time
) {
274 wpa_printf(MSG_DEBUG
,
275 "EAP-TEAP: PAC-Key soft timeout; send an update if authentication succeeds");
276 data
->send_new_pac
= 1;
279 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
280 os_memcpy(master_secret
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
288 static int eap_teap_derive_key_auth(struct eap_sm
*sm
,
289 struct eap_teap_data
*data
)
293 /* RFC 7170, Section 5.1 */
294 res
= tls_connection_export_key(sm
->cfg
->ssl_ctx
, data
->ssl
.conn
,
295 TEAP_TLS_EXPORTER_LABEL_SKS
, NULL
, 0,
296 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
299 wpa_hexdump_key(MSG_DEBUG
,
300 "EAP-TEAP: session_key_seed (S-IMCK[0])",
301 data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
302 os_memcpy(data
->simck_emsk
, data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
308 static int eap_teap_update_icmk(struct eap_sm
*sm
, struct eap_teap_data
*data
)
310 u8
*msk
= NULL
, *emsk
= NULL
;
311 size_t msk_len
= 0, emsk_len
= 0;
314 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Deriving ICMK[%d] (S-IMCK and CMK)",
315 data
->simck_idx
+ 1);
317 if (sm
->cfg
->eap_teap_auth
== 1)
318 return eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
322 if (!data
->phase2_method
|| !data
->phase2_priv
) {
323 wpa_printf(MSG_INFO
, "EAP-TEAP: Phase 2 method not available");
327 if (data
->phase2_method
->getKey
) {
328 msk
= data
->phase2_method
->getKey(sm
, data
->phase2_priv
,
332 "EAP-TEAP: Could not fetch Phase 2 MSK");
337 if (data
->phase2_method
->get_emsk
) {
338 emsk
= data
->phase2_method
->get_emsk(sm
, data
->phase2_priv
,
342 res
= eap_teap_derive_imck(data
->tls_cs
,
343 data
->simck_msk
, data
->simck_emsk
,
344 msk
, msk_len
, emsk
, emsk_len
,
345 data
->simck_msk
, data
->cmk_msk
,
346 data
->simck_emsk
, data
->cmk_emsk
);
347 bin_clear_free(msk
, msk_len
);
348 bin_clear_free(emsk
, emsk_len
);
352 data
->cmk_emsk_available
= 1;
358 static void * eap_teap_init(struct eap_sm
*sm
)
360 struct eap_teap_data
*data
;
362 data
= os_zalloc(sizeof(*data
));
365 data
->teap_version
= EAP_TEAP_VERSION
;
368 if (eap_server_tls_ssl_init(sm
, &data
->ssl
, 0, EAP_TYPE_TEAP
)) {
369 wpa_printf(MSG_INFO
, "EAP-TEAP: Failed to initialize SSL.");
370 eap_teap_reset(sm
, data
);
374 /* TODO: Add anon-DH TLS cipher suites (and if one is negotiated,
375 * enforce inner EAP with mutual authentication to be used) */
377 if (tls_connection_set_session_ticket_cb(sm
->cfg
->ssl_ctx
,
379 eap_teap_session_ticket_cb
,
382 "EAP-TEAP: Failed to set SessionTicket callback");
383 eap_teap_reset(sm
, data
);
387 if (!sm
->cfg
->pac_opaque_encr_key
) {
389 "EAP-TEAP: No PAC-Opaque encryption key configured");
390 eap_teap_reset(sm
, data
);
393 os_memcpy(data
->pac_opaque_encr
, sm
->cfg
->pac_opaque_encr_key
,
394 sizeof(data
->pac_opaque_encr
));
396 if (!sm
->cfg
->eap_fast_a_id
) {
397 wpa_printf(MSG_INFO
, "EAP-TEAP: No A-ID configured");
398 eap_teap_reset(sm
, data
);
401 data
->srv_id
= os_malloc(sm
->cfg
->eap_fast_a_id_len
);
403 eap_teap_reset(sm
, data
);
406 os_memcpy(data
->srv_id
, sm
->cfg
->eap_fast_a_id
,
407 sm
->cfg
->eap_fast_a_id_len
);
408 data
->srv_id_len
= sm
->cfg
->eap_fast_a_id_len
;
410 if (!sm
->cfg
->eap_fast_a_id_info
) {
411 wpa_printf(MSG_INFO
, "EAP-TEAP: No A-ID-Info configured");
412 eap_teap_reset(sm
, data
);
415 data
->srv_id_info
= os_strdup(sm
->cfg
->eap_fast_a_id_info
);
416 if (!data
->srv_id_info
) {
417 eap_teap_reset(sm
, data
);
421 /* PAC-Key lifetime in seconds (hard limit) */
422 data
->pac_key_lifetime
= sm
->cfg
->pac_key_lifetime
;
425 * PAC-Key refresh time in seconds (soft limit on remaining hard
426 * limit). The server will generate a new PAC-Key when this number of
427 * seconds (or fewer) of the lifetime remains.
429 data
->pac_key_refresh_time
= sm
->cfg
->pac_key_refresh_time
;
435 static void eap_teap_reset(struct eap_sm
*sm
, void *priv
)
437 struct eap_teap_data
*data
= priv
;
441 if (data
->phase2_priv
&& data
->phase2_method
)
442 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
443 eap_server_tls_ssl_deinit(sm
, &data
->ssl
);
444 os_free(data
->srv_id
);
445 os_free(data
->srv_id_info
);
446 wpabuf_free(data
->pending_phase2_resp
);
447 wpabuf_free(data
->server_outer_tlvs
);
448 wpabuf_free(data
->peer_outer_tlvs
);
449 os_free(data
->identity
);
450 forced_memzero(data
->simck_msk
, EAP_TEAP_SIMCK_LEN
);
451 forced_memzero(data
->simck_emsk
, EAP_TEAP_SIMCK_LEN
);
452 forced_memzero(data
->cmk_msk
, EAP_TEAP_CMK_LEN
);
453 forced_memzero(data
->cmk_emsk
, EAP_TEAP_CMK_LEN
);
454 forced_memzero(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
));
455 bin_clear_free(data
, sizeof(*data
));
459 static struct wpabuf
* eap_teap_build_start(struct eap_sm
*sm
,
460 struct eap_teap_data
*data
, u8 id
)
463 size_t outer_tlv_len
= sizeof(struct teap_tlv_hdr
) + data
->srv_id_len
;
464 const u8
*start
, *end
;
466 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
,
467 1 + 4 + outer_tlv_len
, EAP_CODE_REQUEST
, id
);
469 wpa_printf(MSG_ERROR
,
470 "EAP-TEAP: Failed to allocate memory for request");
471 eap_teap_state(data
, FAILURE
);
475 wpabuf_put_u8(req
, EAP_TLS_FLAGS_START
| EAP_TEAP_FLAGS_OUTER_TLV_LEN
|
477 wpabuf_put_be32(req
, outer_tlv_len
);
479 start
= wpabuf_put(req
, 0);
481 /* RFC 7170, Section 4.2.2: Authority-ID TLV */
482 eap_teap_put_tlv(req
, TEAP_TLV_AUTHORITY_ID
,
483 data
->srv_id
, data
->srv_id_len
);
485 end
= wpabuf_put(req
, 0);
486 wpabuf_free(data
->server_outer_tlvs
);
487 data
->server_outer_tlvs
= wpabuf_alloc_copy(start
, end
- start
);
488 if (!data
->server_outer_tlvs
) {
489 eap_teap_state(data
, FAILURE
);
493 eap_teap_state(data
, PHASE1
);
499 static int eap_teap_phase1_done(struct eap_sm
*sm
, struct eap_teap_data
*data
)
503 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 1 done, starting Phase 2");
505 data
->tls_cs
= tls_connection_get_cipher_suite(data
->ssl
.conn
);
506 wpa_printf(MSG_DEBUG
, "EAP-TEAP: TLS cipher suite 0x%04x",
509 if (tls_get_cipher(sm
->cfg
->ssl_ctx
, data
->ssl
.conn
,
510 cipher
, sizeof(cipher
)) < 0) {
511 wpa_printf(MSG_DEBUG
,
512 "EAP-TEAP: Failed to get cipher information");
513 eap_teap_state(data
, FAILURE
);
516 data
->anon_provisioning
= os_strstr(cipher
, "ADH") != NULL
;
518 if (data
->anon_provisioning
)
519 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Anonymous provisioning");
521 if (eap_teap_derive_key_auth(sm
, data
) < 0) {
522 eap_teap_state(data
, FAILURE
);
526 eap_teap_state(data
, PHASE2_START
);
532 static struct wpabuf
* eap_teap_build_phase2_req(struct eap_sm
*sm
,
533 struct eap_teap_data
*data
,
536 struct wpabuf
*req
, *id_tlv
= NULL
;
538 if (sm
->cfg
->eap_teap_auth
== 1 ||
539 (data
->phase2_priv
&& data
->phase2_method
&&
540 data
->phase2_method
->vendor
== EAP_VENDOR_IETF
&&
541 data
->phase2_method
->method
== EAP_TYPE_IDENTITY
)) {
542 switch (sm
->cfg
->eap_teap_id
) {
543 case EAP_TEAP_ID_ALLOW_ANY
:
545 case EAP_TEAP_ID_REQUIRE_USER
:
546 case EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE
:
547 data
->cur_id_type
= TEAP_IDENTITY_TYPE_USER
;
548 id_tlv
= eap_teap_tlv_identity_type(data
->cur_id_type
);
550 case EAP_TEAP_ID_REQUIRE_MACHINE
:
551 case EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER
:
552 data
->cur_id_type
= TEAP_IDENTITY_TYPE_MACHINE
;
553 id_tlv
= eap_teap_tlv_identity_type(data
->cur_id_type
);
555 case EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE
:
556 if (data
->cur_id_type
== TEAP_IDENTITY_TYPE_USER
)
557 data
->cur_id_type
= TEAP_IDENTITY_TYPE_MACHINE
;
559 data
->cur_id_type
= TEAP_IDENTITY_TYPE_USER
;
560 id_tlv
= eap_teap_tlv_identity_type(data
->cur_id_type
);
565 if (sm
->cfg
->eap_teap_auth
== 1) {
566 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initiate Basic-Password-Auth");
567 data
->basic_auth_not_done
= 1;
568 req
= wpabuf_alloc(sizeof(struct teap_tlv_hdr
));
573 eap_teap_put_tlv_hdr(req
, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ
, 0);
574 return wpabuf_concat(req
, id_tlv
);
577 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initiate inner EAP method");
578 data
->inner_eap_not_done
= 1;
579 if (!data
->phase2_priv
) {
580 wpa_printf(MSG_DEBUG
,
581 "EAP-TEAP: Phase 2 method not initialized");
586 req
= data
->phase2_method
->buildReq(sm
, data
->phase2_priv
, id
);
592 wpa_hexdump_buf_key(MSG_MSGDUMP
, "EAP-TEAP: Phase 2 EAP-Request", req
);
594 return wpabuf_concat(eap_teap_tlv_eap_payload(req
), id_tlv
);
598 static struct wpabuf
* eap_teap_build_crypto_binding(
599 struct eap_sm
*sm
, struct eap_teap_data
*data
)
602 struct teap_tlv_result
*result
;
603 struct teap_tlv_crypto_binding
*cb
;
606 buf
= wpabuf_alloc(2 * sizeof(*result
) + sizeof(*cb
));
610 if (data
->send_new_pac
|| data
->anon_provisioning
||
611 data
->basic_auth_not_done
|| data
->inner_eap_not_done
||
612 data
->phase2_method
|| sm
->cfg
->eap_teap_separate_result
)
613 data
->final_result
= 0;
615 data
->final_result
= 1;
617 if (!data
->final_result
|| data
->eap_seq
> 0 ||
618 sm
->cfg
->eap_teap_auth
== 1) {
619 /* Intermediate-Result */
620 wpa_printf(MSG_DEBUG
,
621 "EAP-TEAP: Add Intermediate-Result TLV (status=SUCCESS)");
622 result
= wpabuf_put(buf
, sizeof(*result
));
623 result
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
624 TEAP_TLV_INTERMEDIATE_RESULT
);
625 result
->length
= host_to_be16(2);
626 result
->status
= host_to_be16(TEAP_STATUS_SUCCESS
);
629 if (data
->final_result
) {
631 wpa_printf(MSG_DEBUG
,
632 "EAP-TEAP: Add Result TLV (status=SUCCESS)");
633 result
= wpabuf_put(buf
, sizeof(*result
));
634 result
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
636 result
->length
= host_to_be16(2);
637 result
->status
= host_to_be16(TEAP_STATUS_SUCCESS
);
640 /* Crypto-Binding TLV */
641 cb
= wpabuf_put(buf
, sizeof(*cb
));
642 cb
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
|
643 TEAP_TLV_CRYPTO_BINDING
);
644 cb
->length
= host_to_be16(sizeof(*cb
) - sizeof(struct teap_tlv_hdr
));
645 cb
->version
= EAP_TEAP_VERSION
;
646 cb
->received_version
= data
->peer_version
;
647 /* FIX: RFC 7170 is not clear on which Flags value to use when
648 * Crypto-Binding TLV is used with Basic-Password-Auth */
649 flags
= data
->cmk_emsk_available
?
650 TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
:
651 TEAP_CRYPTO_BINDING_MSK_CMAC
;
652 subtype
= TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST
;
653 cb
->subtype
= (flags
<< 4) | subtype
;
654 if (random_get_bytes(cb
->nonce
, sizeof(cb
->nonce
)) < 0) {
660 * RFC 7170, Section 4.2.13:
661 * The nonce in a request MUST have its least significant bit set to 0.
663 cb
->nonce
[sizeof(cb
->nonce
) - 1] &= ~0x01;
665 os_memcpy(data
->crypto_binding_nonce
, cb
->nonce
, sizeof(cb
->nonce
));
667 if (eap_teap_compound_mac(data
->tls_cs
, cb
, data
->server_outer_tlvs
,
668 data
->peer_outer_tlvs
, data
->cmk_msk
,
669 cb
->msk_compound_mac
) < 0) {
674 if (data
->cmk_emsk_available
&&
675 eap_teap_compound_mac(data
->tls_cs
, cb
, data
->server_outer_tlvs
,
676 data
->peer_outer_tlvs
, data
->cmk_emsk
,
677 cb
->emsk_compound_mac
) < 0) {
682 wpa_printf(MSG_DEBUG
,
683 "EAP-TEAP: Add Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
684 cb
->version
, cb
->received_version
, flags
, subtype
);
685 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
686 cb
->nonce
, sizeof(cb
->nonce
));
687 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
688 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
689 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
690 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
696 static struct wpabuf
* eap_teap_build_pac(struct eap_sm
*sm
,
697 struct eap_teap_data
*data
)
699 u8 pac_key
[EAP_TEAP_PAC_KEY_LEN
];
700 u8
*pac_buf
, *pac_opaque
;
703 size_t buf_len
, srv_id_info_len
, pac_len
;
704 struct teap_tlv_hdr
*pac_tlv
;
705 struct pac_attr_hdr
*pac_info
;
706 struct teap_tlv_result
*result
;
709 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Build a new PAC");
711 if (random_get_bytes(pac_key
, EAP_TEAP_PAC_KEY_LEN
) < 0 ||
712 os_get_time(&now
) < 0)
714 wpa_hexdump_key(MSG_DEBUG
, "EAP-TEAP: Generated PAC-Key",
715 pac_key
, EAP_TEAP_PAC_KEY_LEN
);
717 pac_len
= (2 + EAP_TEAP_PAC_KEY_LEN
) + (2 + 4) +
718 (2 + sm
->identity_len
) + 8;
719 pac_buf
= os_malloc(pac_len
);
723 srv_id_info_len
= os_strlen(data
->srv_id_info
);
726 *pos
++ = PAC_OPAQUE_TYPE_KEY
;
727 *pos
++ = EAP_TEAP_PAC_KEY_LEN
;
728 os_memcpy(pos
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
729 pos
+= EAP_TEAP_PAC_KEY_LEN
;
731 wpa_printf(MSG_DEBUG
, "EAP-TEAP: PAC-Key lifetime: %u seconds",
732 data
->pac_key_lifetime
);
733 *pos
++ = PAC_OPAQUE_TYPE_LIFETIME
;
735 WPA_PUT_BE32(pos
, now
.sec
+ data
->pac_key_lifetime
);
739 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque Identity",
740 sm
->identity
, sm
->identity_len
);
741 *pos
++ = PAC_OPAQUE_TYPE_IDENTITY
;
742 *pos
++ = sm
->identity_len
;
743 os_memcpy(pos
, sm
->identity
, sm
->identity_len
);
744 pos
+= sm
->identity_len
;
747 pac_len
= pos
- pac_buf
;
748 while (pac_len
% 8) {
749 *pos
++ = PAC_OPAQUE_TYPE_PAD
;
753 pac_opaque
= os_malloc(pac_len
+ 8);
758 if (aes_wrap(data
->pac_opaque_encr
, sizeof(data
->pac_opaque_encr
),
759 pac_len
/ 8, pac_buf
, pac_opaque
) < 0) {
767 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: PAC-Opaque", pac_opaque
, pac_len
);
769 buf_len
= sizeof(*pac_tlv
) +
770 sizeof(struct pac_attr_hdr
) + EAP_TEAP_PAC_KEY_LEN
+
771 sizeof(struct pac_attr_hdr
) + pac_len
+
772 data
->srv_id_len
+ srv_id_info_len
+ 100 + sizeof(*result
);
773 buf
= wpabuf_alloc(buf_len
);
780 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add Result TLV (status=SUCCESS)");
781 result
= wpabuf_put(buf
, sizeof(*result
));
782 WPA_PUT_BE16((u8
*) &result
->tlv_type
,
783 TEAP_TLV_MANDATORY
| TEAP_TLV_RESULT
);
784 WPA_PUT_BE16((u8
*) &result
->length
, 2);
785 WPA_PUT_BE16((u8
*) &result
->status
, TEAP_STATUS_SUCCESS
);
788 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Add PAC TLV");
789 pac_tlv
= wpabuf_put(buf
, sizeof(*pac_tlv
));
790 pac_tlv
->tlv_type
= host_to_be16(TEAP_TLV_MANDATORY
| TEAP_TLV_PAC
);
793 eap_teap_put_tlv(buf
, PAC_TYPE_PAC_KEY
, pac_key
, EAP_TEAP_PAC_KEY_LEN
);
796 eap_teap_put_tlv(buf
, PAC_TYPE_PAC_OPAQUE
, pac_opaque
, pac_len
);
800 pac_info
= wpabuf_put(buf
, sizeof(*pac_info
));
801 pac_info
->type
= host_to_be16(PAC_TYPE_PAC_INFO
);
803 /* PAC-Lifetime (inside PAC-Info) */
804 eap_teap_put_tlv_hdr(buf
, PAC_TYPE_CRED_LIFETIME
, 4);
805 wpabuf_put_be32(buf
, now
.sec
+ data
->pac_key_lifetime
);
807 /* A-ID (inside PAC-Info) */
808 eap_teap_put_tlv(buf
, PAC_TYPE_A_ID
, data
->srv_id
, data
->srv_id_len
);
810 /* Note: headers may be misaligned after A-ID */
813 eap_teap_put_tlv(buf
, PAC_TYPE_I_ID
, sm
->identity
,
817 /* A-ID-Info (inside PAC-Info) */
818 eap_teap_put_tlv(buf
, PAC_TYPE_A_ID_INFO
, data
->srv_id_info
,
821 /* PAC-Type (inside PAC-Info) */
822 eap_teap_put_tlv_hdr(buf
, PAC_TYPE_PAC_TYPE
, 2);
823 wpabuf_put_be16(buf
, PAC_TYPE_TUNNEL_PAC
);
825 /* Update PAC-Info and PAC TLV Length fields */
826 pos
= wpabuf_put(buf
, 0);
827 pac_info
->len
= host_to_be16(pos
- (u8
*) (pac_info
+ 1));
828 pac_tlv
->length
= host_to_be16(pos
- (u8
*) (pac_tlv
+ 1));
834 static int eap_teap_encrypt_phase2(struct eap_sm
*sm
,
835 struct eap_teap_data
*data
,
836 struct wpabuf
*plain
, int piggyback
)
840 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Encrypting Phase 2 TLVs",
842 encr
= eap_server_tls_encrypt(sm
, &data
->ssl
, plain
);
848 if (data
->ssl
.tls_out
&& piggyback
) {
849 wpa_printf(MSG_DEBUG
,
850 "EAP-TEAP: Piggyback Phase 2 data (len=%d) with last Phase 1 Message (len=%d used=%d)",
851 (int) wpabuf_len(encr
),
852 (int) wpabuf_len(data
->ssl
.tls_out
),
853 (int) data
->ssl
.tls_out_pos
);
854 if (wpabuf_resize(&data
->ssl
.tls_out
, wpabuf_len(encr
)) < 0) {
855 wpa_printf(MSG_WARNING
,
856 "EAP-TEAP: Failed to resize output buffer");
860 wpabuf_put_buf(data
->ssl
.tls_out
, encr
);
863 wpabuf_free(data
->ssl
.tls_out
);
864 data
->ssl
.tls_out_pos
= 0;
865 data
->ssl
.tls_out
= encr
;
872 static struct wpabuf
* eap_teap_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
874 struct eap_teap_data
*data
= priv
;
875 struct wpabuf
*req
= NULL
;
878 if (data
->ssl
.state
== FRAG_ACK
) {
879 return eap_server_tls_build_ack(id
, EAP_TYPE_TEAP
,
883 if (data
->ssl
.state
== WAIT_FRAG_ACK
) {
884 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TEAP
,
885 data
->teap_version
, id
);
888 switch (data
->state
) {
890 return eap_teap_build_start(sm
, data
, id
);
892 if (tls_connection_established(sm
->cfg
->ssl_ctx
,
894 if (eap_teap_phase1_done(sm
, data
) < 0)
896 if (data
->state
== PHASE2_START
) {
900 * Try to generate Phase 2 data to piggyback
901 * with the end of Phase 1 to avoid extra
904 wpa_printf(MSG_DEBUG
,
905 "EAP-TEAP: Try to start Phase 2");
906 res
= eap_teap_process_phase2_start(sm
, data
);
908 req
= eap_teap_build_crypto_binding(
916 req
= eap_teap_build_phase2_req(sm
, data
, id
);
922 case PHASE2_BASIC_AUTH
:
924 req
= eap_teap_build_phase2_req(sm
, data
, id
);
927 req
= eap_teap_build_crypto_binding(sm
, data
);
928 if (data
->phase2_method
) {
930 * Include the start of the next EAP method in the
931 * sequence in the same message with Crypto-Binding to
936 eap
= eap_teap_build_phase2_req(sm
, data
, id
);
937 req
= wpabuf_concat(req
, eap
);
938 eap_teap_state(data
, PHASE2_METHOD
);
942 req
= eap_teap_build_pac(sm
, data
);
944 case FAILURE_SEND_RESULT
:
945 req
= eap_teap_tlv_result(TEAP_STATUS_FAILURE
, 0);
946 if (data
->error_code
)
948 req
, eap_teap_tlv_error(data
->error_code
));
950 case SUCCESS_SEND_RESULT
:
951 req
= eap_teap_tlv_result(TEAP_STATUS_SUCCESS
, 0);
952 data
->final_result
= 1;
955 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s - unexpected state %d",
956 __func__
, data
->state
);
960 if (req
&& eap_teap_encrypt_phase2(sm
, data
, req
, piggyback
) < 0)
963 return eap_server_tls_build_msg(&data
->ssl
, EAP_TYPE_TEAP
,
964 data
->teap_version
, id
);
968 static Boolean
eap_teap_check(struct eap_sm
*sm
, void *priv
,
969 struct wpabuf
*respData
)
974 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, respData
, &len
);
975 if (!pos
|| len
< 1) {
976 wpa_printf(MSG_INFO
, "EAP-TEAP: Invalid frame");
984 static int eap_teap_phase2_init(struct eap_sm
*sm
, struct eap_teap_data
*data
,
985 int vendor
, enum eap_type eap_type
)
987 if (data
->phase2_priv
&& data
->phase2_method
) {
988 data
->phase2_method
->reset(sm
, data
->phase2_priv
);
989 data
->phase2_method
= NULL
;
990 data
->phase2_priv
= NULL
;
992 data
->phase2_method
= eap_server_get_eap_method(vendor
, eap_type
);
993 if (!data
->phase2_method
)
997 data
->phase2_priv
= data
->phase2_method
->init(sm
);
1000 return data
->phase2_priv
? 0 : -1;
1004 static int eap_teap_valid_id_type(struct eap_sm
*sm
, struct eap_teap_data
*data
,
1005 enum teap_identity_types id_type
)
1007 if (sm
->cfg
->eap_teap_id
== EAP_TEAP_ID_REQUIRE_USER
&&
1008 id_type
!= TEAP_IDENTITY_TYPE_USER
)
1010 if (sm
->cfg
->eap_teap_id
== EAP_TEAP_ID_REQUIRE_MACHINE
&&
1011 id_type
!= TEAP_IDENTITY_TYPE_MACHINE
)
1013 if (sm
->cfg
->eap_teap_id
== EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE
&&
1014 id_type
!= data
->cur_id_type
)
1016 if (sm
->cfg
->eap_teap_id
!= EAP_TEAP_ID_ALLOW_ANY
&&
1017 id_type
!= TEAP_IDENTITY_TYPE_USER
&&
1018 id_type
!= TEAP_IDENTITY_TYPE_MACHINE
)
1024 static void eap_teap_process_phase2_response(struct eap_sm
*sm
,
1025 struct eap_teap_data
*data
,
1026 u8
*in_data
, size_t in_len
,
1027 enum teap_identity_types id_type
)
1029 int next_vendor
= EAP_VENDOR_IETF
;
1030 enum eap_type next_type
= EAP_TYPE_NONE
;
1031 struct eap_hdr
*hdr
;
1035 const struct eap_method
*m
= data
->phase2_method
;
1036 void *priv
= data
->phase2_priv
;
1039 wpa_printf(MSG_DEBUG
,
1040 "EAP-TEAP: %s - Phase 2 not initialized?!",
1045 hdr
= (struct eap_hdr
*) in_data
;
1046 pos
= (u8
*) (hdr
+ 1);
1048 if (in_len
> sizeof(*hdr
) && *pos
== EAP_TYPE_NAK
) {
1049 left
= in_len
- sizeof(*hdr
);
1050 wpa_hexdump(MSG_DEBUG
,
1051 "EAP-TEAP: Phase 2 type Nak'ed; allowed types",
1053 #ifdef EAP_SERVER_TNC
1054 if (m
&& m
->vendor
== EAP_VENDOR_IETF
&&
1055 m
->method
== EAP_TYPE_TNC
) {
1056 wpa_printf(MSG_DEBUG
,
1057 "EAP-TEAP: Peer Nak'ed required TNC negotiation");
1058 next_vendor
= EAP_VENDOR_IETF
;
1059 next_type
= eap_teap_req_failure(data
, 0);
1060 eap_teap_phase2_init(sm
, data
, next_vendor
, next_type
);
1063 #endif /* EAP_SERVER_TNC */
1064 eap_sm_process_nak(sm
, pos
+ 1, left
- 1);
1065 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
1066 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
1068 next_vendor
= sm
->user
->methods
[
1069 sm
->user_eap_method_index
].vendor
;
1070 next_type
= sm
->user
->methods
[
1071 sm
->user_eap_method_index
++].method
;
1072 wpa_printf(MSG_DEBUG
, "EAP-TEAP: try EAP type %u:%u",
1073 next_vendor
, next_type
);
1075 next_vendor
= EAP_VENDOR_IETF
;
1076 next_type
= eap_teap_req_failure(data
, 0);
1078 eap_teap_phase2_init(sm
, data
, next_vendor
, next_type
);
1082 wpabuf_set(&buf
, in_data
, in_len
);
1084 if (m
->check(sm
, priv
, &buf
)) {
1085 wpa_printf(MSG_DEBUG
,
1086 "EAP-TEAP: Phase 2 check() asked to ignore the packet");
1087 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1091 m
->process(sm
, priv
, &buf
);
1093 if (!m
->isDone(sm
, priv
))
1096 if (!m
->isSuccess(sm
, priv
)) {
1097 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Phase 2 method failed");
1098 next_vendor
= EAP_VENDOR_IETF
;
1099 next_type
= eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1100 eap_teap_phase2_init(sm
, data
, next_vendor
, next_type
);
1104 switch (data
->state
) {
1106 if (!eap_teap_valid_id_type(sm
, data
, id_type
)) {
1107 wpa_printf(MSG_DEBUG
,
1108 "EAP-TEAP: Provided Identity-Type %u not allowed",
1110 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1113 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1114 wpa_hexdump_ascii(MSG_DEBUG
,
1115 "EAP-TEAP: Phase 2 Identity not found in the user database",
1116 sm
->identity
, sm
->identity_len
);
1117 next_vendor
= EAP_VENDOR_IETF
;
1118 next_type
= eap_teap_req_failure(
1119 data
, TEAP_ERROR_INNER_METHOD
);
1123 eap_teap_state(data
, PHASE2_METHOD
);
1124 if (data
->anon_provisioning
) {
1125 /* TODO: Allow any inner EAP method that provides
1126 * mutual authentication and EMSK derivation (i.e.,
1127 * EAP-pwd or EAP-EKE). */
1128 next_vendor
= EAP_VENDOR_IETF
;
1129 next_type
= EAP_TYPE_PWD
;
1130 sm
->user_eap_method_index
= 0;
1132 next_vendor
= sm
->user
->methods
[0].vendor
;
1133 next_type
= sm
->user
->methods
[0].method
;
1134 sm
->user_eap_method_index
= 1;
1136 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Try EAP type %u:%u",
1137 next_vendor
, next_type
);
1140 case CRYPTO_BINDING
:
1141 eap_teap_update_icmk(sm
, data
);
1142 if (data
->state
== PHASE2_METHOD
&&
1143 (sm
->cfg
->eap_teap_id
!=
1144 EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE
||
1145 data
->cur_id_type
== TEAP_IDENTITY_TYPE_MACHINE
))
1146 data
->inner_eap_not_done
= 0;
1147 eap_teap_state(data
, CRYPTO_BINDING
);
1149 next_vendor
= EAP_VENDOR_IETF
;
1150 next_type
= EAP_TYPE_NONE
;
1151 #ifdef EAP_SERVER_TNC
1152 if (sm
->cfg
->tnc
&& !data
->tnc_started
) {
1153 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Initialize TNC");
1154 next_vendor
= EAP_VENDOR_IETF
;
1155 next_type
= EAP_TYPE_TNC
;
1156 data
->tnc_started
= 1;
1158 #endif /* EAP_SERVER_TNC */
1163 wpa_printf(MSG_DEBUG
, "EAP-TEAP: %s - unexpected state %d",
1164 __func__
, data
->state
);
1168 eap_teap_phase2_init(sm
, data
, next_vendor
, next_type
);
1172 static void eap_teap_process_phase2_eap(struct eap_sm
*sm
,
1173 struct eap_teap_data
*data
,
1174 u8
*in_data
, size_t in_len
,
1175 enum teap_identity_types id_type
)
1177 struct eap_hdr
*hdr
;
1180 hdr
= (struct eap_hdr
*) in_data
;
1181 if (in_len
< (int) sizeof(*hdr
)) {
1182 wpa_printf(MSG_INFO
,
1183 "EAP-TEAP: Too short Phase 2 EAP frame (len=%lu)",
1184 (unsigned long) in_len
);
1185 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1188 len
= be_to_host16(hdr
->length
);
1190 wpa_printf(MSG_INFO
,
1191 "EAP-TEAP: Length mismatch in Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1192 (unsigned long) in_len
, (unsigned long) len
);
1193 eap_teap_req_failure(data
, TEAP_ERROR_INNER_METHOD
);
1196 wpa_printf(MSG_DEBUG
,
1197 "EAP-TEAP: Received Phase 2: code=%d identifier=%d length=%lu",
1198 hdr
->code
, hdr
->identifier
,
1199 (unsigned long) len
);
1200 switch (hdr
->code
) {
1201 case EAP_CODE_RESPONSE
:
1202 eap_teap_process_phase2_response(sm
, data
, (u8
*) hdr
, len
,
1206 wpa_printf(MSG_INFO
,
1207 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
1214 static void eap_teap_process_basic_auth_resp(struct eap_sm
*sm
,
1215 struct eap_teap_data
*data
,
1216 u8
*in_data
, size_t in_len
,
1217 enum teap_identity_types id_type
)
1219 u8
*pos
, *end
, *username
, *password
, *new_id
;
1220 u8 userlen
, passlen
;
1222 if (!eap_teap_valid_id_type(sm
, data
, id_type
)) {
1223 wpa_printf(MSG_DEBUG
,
1224 "EAP-TEAP: Provided Identity-Type %u not allowed",
1226 eap_teap_req_failure(data
, 0);
1233 if (end
- pos
< 1) {
1234 wpa_printf(MSG_DEBUG
,
1235 "EAP-TEAP: No room for Basic-Password-Auth-Resp Userlen field");
1236 eap_teap_req_failure(data
, 0);
1240 if (end
- pos
< userlen
) {
1241 wpa_printf(MSG_DEBUG
,
1242 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Username field");
1243 eap_teap_req_failure(data
, 0);
1248 wpa_hexdump_ascii(MSG_DEBUG
,
1249 "EAP-TEAP: Basic-Password-Auth-Resp Username",
1252 if (end
- pos
< 1) {
1253 wpa_printf(MSG_DEBUG
,
1254 "EAP-TEAP: No room for Basic-Password-Auth-Resp Passlen field");
1255 eap_teap_req_failure(data
, 0);
1259 if (end
- pos
< passlen
) {
1260 wpa_printf(MSG_DEBUG
,
1261 "EAP-TEAP: Truncated Basic-Password-Auth-Resp Password field");
1262 eap_teap_req_failure(data
, 0);
1267 wpa_hexdump_ascii_key(MSG_DEBUG
,
1268 "EAP-TEAP: Basic-Password-Auth-Resp Password",
1272 wpa_printf(MSG_DEBUG
,
1273 "EAP-TEAP: Unexpected %d extra octet(s) at the end of Basic-Password-Auth-Resp TLV",
1275 eap_teap_req_failure(data
, 0);
1279 if (eap_user_get(sm
, username
, userlen
, 1) != 0) {
1280 wpa_printf(MSG_DEBUG
,
1281 "EAP-TEAP: Username not found in the user database");
1282 eap_teap_req_failure(data
, 0);
1286 if (!sm
->user
|| !sm
->user
->password
|| sm
->user
->password_hash
) {
1287 wpa_printf(MSG_DEBUG
,
1288 "EAP-TEAP: No plaintext user password configured");
1289 eap_teap_req_failure(data
, 0);
1293 if (sm
->user
->password_len
!= passlen
||
1294 os_memcmp_const(sm
->user
->password
, password
, passlen
) != 0) {
1295 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Invalid password");
1296 eap_teap_req_failure(data
, 0);
1300 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Correct password");
1301 new_id
= os_memdup(username
, userlen
);
1303 os_free(sm
->identity
);
1304 sm
->identity
= new_id
;
1305 sm
->identity_len
= userlen
;
1307 if (sm
->cfg
->eap_teap_id
!= EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE
||
1308 data
->cur_id_type
== TEAP_IDENTITY_TYPE_MACHINE
)
1309 data
->basic_auth_not_done
= 0;
1310 eap_teap_state(data
, CRYPTO_BINDING
);
1311 eap_teap_update_icmk(sm
, data
);
1315 static int eap_teap_parse_tlvs(struct wpabuf
*data
,
1316 struct eap_teap_tlv_parse
*tlv
)
1323 os_memset(tlv
, 0, sizeof(*tlv
));
1325 pos
= wpabuf_mhead(data
);
1326 end
= pos
+ wpabuf_len(data
);
1327 while (end
- pos
> 4) {
1328 mandatory
= pos
[0] & 0x80;
1329 tlv_type
= WPA_GET_BE16(pos
) & 0x3fff;
1331 len
= WPA_GET_BE16(pos
);
1333 if (len
> (size_t) (end
- pos
)) {
1334 wpa_printf(MSG_INFO
, "EAP-TEAP: TLV overflow");
1337 wpa_printf(MSG_DEBUG
,
1338 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1339 tlv_type
, eap_teap_tlv_type_str(tlv_type
),
1341 mandatory
? " (mandatory)" : "");
1343 res
= eap_teap_parse_tlv(tlv
, tlv_type
, pos
, len
);
1348 wpa_printf(MSG_DEBUG
,
1349 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1351 /* TODO: generate NAK TLV */
1355 wpa_printf(MSG_DEBUG
,
1356 "EAP-TEAP: Ignore unknown optional TLV type %u",
1367 static int eap_teap_validate_crypto_binding(
1368 struct eap_teap_data
*data
, const struct teap_tlv_crypto_binding
*cb
,
1373 subtype
= cb
->subtype
& 0x0f;
1374 flags
= cb
->subtype
>> 4;
1376 wpa_printf(MSG_DEBUG
,
1377 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
1378 cb
->version
, cb
->received_version
, flags
, subtype
);
1379 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: Nonce",
1380 cb
->nonce
, sizeof(cb
->nonce
));
1381 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: EMSK Compound MAC",
1382 cb
->emsk_compound_mac
, sizeof(cb
->emsk_compound_mac
));
1383 wpa_hexdump(MSG_MSGDUMP
, "EAP-TEAP: MSK Compound MAC",
1384 cb
->msk_compound_mac
, sizeof(cb
->msk_compound_mac
));
1386 if (cb
->version
!= EAP_TEAP_VERSION
||
1387 cb
->received_version
!= data
->peer_version
) {
1388 wpa_printf(MSG_DEBUG
,
1389 "EAP-TEAP: Unexpected version in Crypto-Binding: Version %u Received Version %u",
1390 cb
->version
, cb
->received_version
);
1394 if (flags
< 1 || flags
> 3) {
1395 wpa_printf(MSG_DEBUG
,
1396 "EAP-TEAP: Unexpected Flags in Crypto-Binding: %u",
1401 if (subtype
!= TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE
) {
1402 wpa_printf(MSG_DEBUG
,
1403 "EAP-TEAP: Unexpected Sub-Type in Crypto-Binding: %u",
1408 if (os_memcmp_const(data
->crypto_binding_nonce
, cb
->nonce
,
1409 EAP_TEAP_NONCE_LEN
- 1) != 0 ||
1410 (data
->crypto_binding_nonce
[EAP_TEAP_NONCE_LEN
- 1] | 1) !=
1411 cb
->nonce
[EAP_TEAP_NONCE_LEN
- 1]) {
1412 wpa_printf(MSG_DEBUG
,
1413 "EAP-TEAP: Invalid Nonce in Crypto-Binding");
1417 if (flags
== TEAP_CRYPTO_BINDING_MSK_CMAC
||
1418 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) {
1419 u8 msk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
1421 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
1422 data
->server_outer_tlvs
,
1423 data
->peer_outer_tlvs
, data
->cmk_msk
,
1424 msk_compound_mac
) < 0)
1426 if (os_memcmp_const(msk_compound_mac
, cb
->msk_compound_mac
,
1427 EAP_TEAP_COMPOUND_MAC_LEN
) != 0) {
1428 wpa_hexdump(MSG_DEBUG
,
1429 "EAP-TEAP: Calculated MSK Compound MAC",
1431 EAP_TEAP_COMPOUND_MAC_LEN
);
1432 wpa_printf(MSG_INFO
,
1433 "EAP-TEAP: MSK Compound MAC did not match");
1438 if ((flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
||
1439 flags
== TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC
) &&
1440 data
->cmk_emsk_available
) {
1441 u8 emsk_compound_mac
[EAP_TEAP_COMPOUND_MAC_LEN
];
1443 if (eap_teap_compound_mac(data
->tls_cs
, cb
,
1444 data
->server_outer_tlvs
,
1445 data
->peer_outer_tlvs
, data
->cmk_emsk
,
1446 emsk_compound_mac
) < 0)
1448 if (os_memcmp_const(emsk_compound_mac
, cb
->emsk_compound_mac
,
1449 EAP_TEAP_COMPOUND_MAC_LEN
) != 0) {
1450 wpa_hexdump(MSG_DEBUG
,
1451 "EAP-TEAP: Calculated EMSK Compound MAC",
1453 EAP_TEAP_COMPOUND_MAC_LEN
);
1454 wpa_printf(MSG_INFO
,
1455 "EAP-TEAP: EMSK Compound MAC did not match");
1460 if (flags
== TEAP_CRYPTO_BINDING_EMSK_CMAC
&&
1461 !data
->cmk_emsk_available
) {
1462 wpa_printf(MSG_INFO
,
1463 "EAP-TEAP: Peer included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
1471 static int eap_teap_pac_type(u8
*pac
, size_t len
, u16 type
)
1473 struct teap_attr_pac_type
*tlv
;
1475 if (!pac
|| len
!= sizeof(*tlv
))
1478 tlv
= (struct teap_attr_pac_type
*) pac
;
1480 return be_to_host16(tlv
->type
) == PAC_TYPE_PAC_TYPE
&&
1481 be_to_host16(tlv
->length
) == 2 &&
1482 be_to_host16(tlv
->pac_type
) == type
;
1486 static void eap_teap_process_phase2_tlvs(struct eap_sm
*sm
,
1487 struct eap_teap_data
*data
,
1488 struct wpabuf
*in_data
)
1490 struct eap_teap_tlv_parse tlv
;
1491 int check_crypto_binding
= data
->state
== CRYPTO_BINDING
;
1493 if (eap_teap_parse_tlvs(in_data
, &tlv
) < 0) {
1494 wpa_printf(MSG_DEBUG
,
1495 "EAP-TEAP: Failed to parse received Phase 2 TLVs");
1499 if (tlv
.result
== TEAP_STATUS_FAILURE
) {
1500 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Result TLV indicated failure");
1501 eap_teap_state(data
, FAILURE
);
1506 wpa_printf(MSG_DEBUG
,
1507 "EAP-TEAP: Peer NAK'ed Vendor-Id %u NAK-Type %u",
1508 WPA_GET_BE32(tlv
.nak
), WPA_GET_BE16(tlv
.nak
+ 4));
1509 eap_teap_state(data
, FAILURE_SEND_RESULT
);
1513 if (data
->state
== REQUEST_PAC
) {
1516 if (!tlv
.pac
|| tlv
.pac_len
< 6) {
1517 wpa_printf(MSG_DEBUG
,
1518 "EAP-TEAP: No PAC Acknowledgement received");
1519 eap_teap_state(data
, FAILURE
);
1523 type
= WPA_GET_BE16(tlv
.pac
);
1524 len
= WPA_GET_BE16(tlv
.pac
+ 2);
1525 res
= WPA_GET_BE16(tlv
.pac
+ 4);
1527 if (type
!= PAC_TYPE_PAC_ACKNOWLEDGEMENT
|| len
!= 2 ||
1528 res
!= TEAP_STATUS_SUCCESS
) {
1529 wpa_printf(MSG_DEBUG
,
1530 "EAP-TEAP: PAC TLV did not contain acknowledgement");
1531 eap_teap_state(data
, FAILURE
);
1535 wpa_printf(MSG_DEBUG
,
1536 "EAP-TEAP: PAC-Acknowledgement received - PAC provisioning succeeded");
1537 eap_teap_state(data
, SUCCESS
);
1541 if (check_crypto_binding
) {
1542 if (!tlv
.crypto_binding
) {
1543 wpa_printf(MSG_DEBUG
,
1544 "EAP-TEAP: No Crypto-Binding TLV received");
1545 eap_teap_state(data
, FAILURE
);
1549 if (data
->final_result
&&
1550 tlv
.result
!= TEAP_STATUS_SUCCESS
) {
1551 wpa_printf(MSG_DEBUG
,
1552 "EAP-TEAP: Crypto-Binding TLV without Success Result");
1553 eap_teap_state(data
, FAILURE
);
1557 if (sm
->cfg
->eap_teap_auth
!= 1 &&
1558 !data
->skipped_inner_auth
&&
1559 tlv
.iresult
!= TEAP_STATUS_SUCCESS
) {
1560 wpa_printf(MSG_DEBUG
,
1561 "EAP-TEAP: Crypto-Binding TLV without intermediate Success Result");
1562 eap_teap_state(data
, FAILURE
);
1566 if (eap_teap_validate_crypto_binding(data
, tlv
.crypto_binding
,
1567 tlv
.crypto_binding_len
)) {
1568 eap_teap_state(data
, FAILURE
);
1572 wpa_printf(MSG_DEBUG
,
1573 "EAP-TEAP: Valid Crypto-Binding TLV received");
1574 if (data
->final_result
) {
1575 wpa_printf(MSG_DEBUG
,
1576 "EAP-TEAP: Authentication completed successfully");
1579 if (data
->anon_provisioning
&&
1580 sm
->cfg
->eap_fast_prov
!= ANON_PROV
&&
1581 sm
->cfg
->eap_fast_prov
!= BOTH_PROV
) {
1582 wpa_printf(MSG_DEBUG
,
1583 "EAP-TEAP: Client is trying to use unauthenticated provisioning which is disabled");
1584 eap_teap_state(data
, FAILURE
);
1588 if (sm
->cfg
->eap_fast_prov
!= AUTH_PROV
&&
1589 sm
->cfg
->eap_fast_prov
!= BOTH_PROV
&&
1590 tlv
.request_action
== TEAP_REQUEST_ACTION_PROCESS_TLV
&&
1591 eap_teap_pac_type(tlv
.pac
, tlv
.pac_len
,
1592 PAC_TYPE_TUNNEL_PAC
)) {
1593 wpa_printf(MSG_DEBUG
,
1594 "EAP-TEAP: Client is trying to use authenticated provisioning which is disabled");
1595 eap_teap_state(data
, FAILURE
);
1599 if (data
->anon_provisioning
||
1600 (tlv
.request_action
== TEAP_REQUEST_ACTION_PROCESS_TLV
&&
1601 eap_teap_pac_type(tlv
.pac
, tlv
.pac_len
,
1602 PAC_TYPE_TUNNEL_PAC
))) {
1603 wpa_printf(MSG_DEBUG
,
1604 "EAP-TEAP: Requested a new Tunnel PAC");
1605 eap_teap_state(data
, REQUEST_PAC
);
1606 } else if (data
->send_new_pac
) {
1607 wpa_printf(MSG_DEBUG
,
1608 "EAP-TEAP: Server triggered re-keying of Tunnel PAC");
1609 eap_teap_state(data
, REQUEST_PAC
);
1610 } else if (data
->final_result
) {
1611 eap_teap_state(data
, SUCCESS
);
1612 } else if (sm
->cfg
->eap_teap_separate_result
) {
1613 eap_teap_state(data
, SUCCESS_SEND_RESULT
);
1617 if (tlv
.basic_auth_resp
) {
1618 if (sm
->cfg
->eap_teap_auth
!= 1) {
1619 wpa_printf(MSG_DEBUG
,
1620 "EAP-TEAP: Unexpected Basic-Password-Auth-Resp when trying to use inner EAP");
1621 eap_teap_state(data
, FAILURE
);
1624 eap_teap_process_basic_auth_resp(sm
, data
, tlv
.basic_auth_resp
,
1625 tlv
.basic_auth_resp_len
,
1629 if (tlv
.eap_payload_tlv
) {
1630 if (sm
->cfg
->eap_teap_auth
== 1) {
1631 wpa_printf(MSG_DEBUG
,
1632 "EAP-TEAP: Unexpected EAP Payload TLV when trying to use Basic-Password-Auth");
1633 eap_teap_state(data
, FAILURE
);
1636 eap_teap_process_phase2_eap(sm
, data
, tlv
.eap_payload_tlv
,
1637 tlv
.eap_payload_tlv_len
,
1641 if (data
->state
== SUCCESS_SEND_RESULT
&&
1642 tlv
.result
== TEAP_STATUS_SUCCESS
) {
1643 wpa_printf(MSG_DEBUG
,
1644 "EAP-TEAP: Peer agreed with final success - authentication completed");
1645 eap_teap_state(data
, SUCCESS
);
1646 } else if (check_crypto_binding
&& data
->state
== CRYPTO_BINDING
&&
1647 sm
->cfg
->eap_teap_auth
== 1 && data
->basic_auth_not_done
) {
1648 wpa_printf(MSG_DEBUG
,
1649 "EAP-TEAP: Continue with basic password authentication for second credential");
1650 eap_teap_state(data
, PHASE2_BASIC_AUTH
);
1651 } else if (check_crypto_binding
&& data
->state
== CRYPTO_BINDING
&&
1652 sm
->cfg
->eap_teap_auth
== 0 && data
->inner_eap_not_done
) {
1653 wpa_printf(MSG_DEBUG
,
1654 "EAP-TEAP: Continue with inner EAP authentication for second credential");
1655 eap_teap_state(data
, PHASE2_ID
);
1656 if (eap_teap_phase2_init(sm
, data
, EAP_VENDOR_IETF
,
1657 EAP_TYPE_IDENTITY
) < 0)
1658 eap_teap_state(data
, FAILURE
);
1663 static void eap_teap_process_phase2(struct eap_sm
*sm
,
1664 struct eap_teap_data
*data
,
1665 struct wpabuf
*in_buf
)
1667 struct wpabuf
*in_decrypted
;
1669 wpa_printf(MSG_DEBUG
,
1670 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1671 (unsigned long) wpabuf_len(in_buf
));
1673 if (data
->pending_phase2_resp
) {
1674 wpa_printf(MSG_DEBUG
,
1675 "EAP-TEAP: Pending Phase 2 response - skip decryption and use old data");
1676 eap_teap_process_phase2_tlvs(sm
, data
,
1677 data
->pending_phase2_resp
);
1678 wpabuf_free(data
->pending_phase2_resp
);
1679 data
->pending_phase2_resp
= NULL
;
1683 in_decrypted
= tls_connection_decrypt(sm
->cfg
->ssl_ctx
, data
->ssl
.conn
,
1685 if (!in_decrypted
) {
1686 wpa_printf(MSG_INFO
,
1687 "EAP-TEAP: Failed to decrypt Phase 2 data");
1688 eap_teap_state(data
, FAILURE
);
1692 wpa_hexdump_buf_key(MSG_DEBUG
, "EAP-TEAP: Decrypted Phase 2 TLVs",
1695 eap_teap_process_phase2_tlvs(sm
, data
, in_decrypted
);
1697 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
1698 wpa_printf(MSG_DEBUG
,
1699 "EAP-TEAP: Phase 2 method is in pending wait state - save decrypted response");
1700 wpabuf_free(data
->pending_phase2_resp
);
1701 data
->pending_phase2_resp
= in_decrypted
;
1705 wpabuf_free(in_decrypted
);
1709 static int eap_teap_process_version(struct eap_sm
*sm
, void *priv
,
1712 struct eap_teap_data
*data
= priv
;
1714 if (peer_version
< 1) {
1715 /* Version 1 was the first defined version, so reject 0 */
1716 wpa_printf(MSG_INFO
,
1717 "EAP-TEAP: Peer used unknown TEAP version %u",
1722 if (peer_version
< data
->teap_version
) {
1723 wpa_printf(MSG_DEBUG
, "EAP-TEAP: peer ver=%u, own ver=%u; "
1725 peer_version
, data
->teap_version
, peer_version
);
1726 data
->teap_version
= peer_version
;
1729 data
->peer_version
= peer_version
;
1735 static int eap_teap_process_phase1(struct eap_sm
*sm
,
1736 struct eap_teap_data
*data
)
1738 if (eap_server_tls_phase1(sm
, &data
->ssl
) < 0) {
1739 wpa_printf(MSG_INFO
, "EAP-TEAP: TLS processing failed");
1740 eap_teap_state(data
, FAILURE
);
1744 if (!tls_connection_established(sm
->cfg
->ssl_ctx
, data
->ssl
.conn
) ||
1745 wpabuf_len(data
->ssl
.tls_out
) > 0)
1749 * Phase 1 was completed with the received message (e.g., when using
1750 * abbreviated handshake), so Phase 2 can be started immediately
1751 * without having to send through an empty message to the peer.
1754 return eap_teap_phase1_done(sm
, data
);
1758 static int eap_teap_process_phase2_start(struct eap_sm
*sm
,
1759 struct eap_teap_data
*data
)
1762 enum eap_type next_type
;
1764 if (data
->identity
) {
1765 /* Used PAC and identity is from PAC-Opaque */
1766 os_free(sm
->identity
);
1767 sm
->identity
= data
->identity
;
1768 data
->identity
= NULL
;
1769 sm
->identity_len
= data
->identity_len
;
1770 data
->identity_len
= 0;
1771 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
1772 wpa_hexdump_ascii(MSG_DEBUG
,
1773 "EAP-TEAP: Phase 2 Identity not found in the user database",
1774 sm
->identity
, sm
->identity_len
);
1775 next_vendor
= EAP_VENDOR_IETF
;
1776 next_type
= EAP_TYPE_NONE
;
1777 eap_teap_state(data
, PHASE2_METHOD
);
1778 } else if (sm
->cfg
->eap_teap_pac_no_inner
) {
1779 wpa_printf(MSG_DEBUG
,
1780 "EAP-TEAP: Used PAC and identity already known - skip inner auth");
1781 data
->skipped_inner_auth
= 1;
1782 /* FIX: Need to derive CMK here. However, how is that
1783 * supposed to be done? RFC 7170 does not tell that for
1784 * the no-inner-auth case. */
1785 eap_teap_derive_cmk_basic_pw_auth(data
->tls_cs
,
1788 eap_teap_state(data
, CRYPTO_BINDING
);
1790 } else if (sm
->cfg
->eap_teap_auth
== 1) {
1791 eap_teap_state(data
, PHASE2_BASIC_AUTH
);
1794 wpa_printf(MSG_DEBUG
,
1795 "EAP-TEAP: Identity already known - skip Phase 2 Identity Request");
1796 next_vendor
= sm
->user
->methods
[0].vendor
;
1797 next_type
= sm
->user
->methods
[0].method
;
1798 sm
->user_eap_method_index
= 1;
1799 eap_teap_state(data
, PHASE2_METHOD
);
1802 } else if (sm
->cfg
->eap_teap_auth
== 1) {
1803 eap_teap_state(data
, PHASE2_BASIC_AUTH
);
1806 eap_teap_state(data
, PHASE2_ID
);
1807 next_vendor
= EAP_VENDOR_IETF
;
1808 next_type
= EAP_TYPE_IDENTITY
;
1811 return eap_teap_phase2_init(sm
, data
, next_vendor
, next_type
);
1815 static void eap_teap_process_msg(struct eap_sm
*sm
, void *priv
,
1816 const struct wpabuf
*respData
)
1818 struct eap_teap_data
*data
= priv
;
1820 switch (data
->state
) {
1823 if (eap_teap_process_phase1(sm
, data
))
1828 eap_teap_process_phase2_start(sm
, data
);
1831 case PHASE2_BASIC_AUTH
:
1833 case CRYPTO_BINDING
:
1835 case SUCCESS_SEND_RESULT
:
1836 eap_teap_process_phase2(sm
, data
, data
->ssl
.tls_in
);
1838 case FAILURE_SEND_RESULT
:
1839 /* Protected failure result indication completed. Ignore the
1840 * received message (which is supposed to include Result TLV
1841 * indicating failure) and terminate exchange with cleartext
1843 eap_teap_state(data
, FAILURE
);
1846 wpa_printf(MSG_DEBUG
, "EAP-TEAP: Unexpected state %d in %s",
1847 data
->state
, __func__
);
1853 static void eap_teap_process(struct eap_sm
*sm
, void *priv
,
1854 struct wpabuf
*respData
)
1856 struct eap_teap_data
*data
= priv
;
1859 struct wpabuf
*resp
= respData
;
1862 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, respData
, &len
);
1863 if (!pos
|| len
< 1)
1869 if (flags
& EAP_TEAP_FLAGS_OUTER_TLV_LEN
) {
1870 /* Extract Outer TLVs from the message before common TLS
1872 u32 message_len
= 0, outer_tlv_len
;
1875 if (data
->state
!= PHASE1
) {
1876 wpa_printf(MSG_INFO
,
1877 "EAP-TEAP: Unexpected Outer TLVs in a message that is not the first message from the peer");
1881 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
) {
1883 wpa_printf(MSG_INFO
,
1884 "EAP-TEAP: Too short message to include Message Length field");
1888 message_len
= WPA_GET_BE32(pos
);
1891 if (message_len
< 4) {
1892 wpa_printf(MSG_INFO
,
1893 "EAP-TEAP: Message Length field has too msall value to include Outer TLV Length field");
1899 wpa_printf(MSG_INFO
,
1900 "EAP-TEAP: Too short message to include Outer TLVs Length field");
1904 outer_tlv_len
= WPA_GET_BE32(pos
);
1908 wpa_printf(MSG_DEBUG
,
1909 "EAP-TEAP: Message Length %u Outer TLV Length %u",
1910 message_len
, outer_tlv_len
);
1911 if (len
< outer_tlv_len
) {
1912 wpa_printf(MSG_INFO
,
1913 "EAP-TEAP: Too short message to include Outer TLVs field");
1918 (message_len
< outer_tlv_len
||
1919 message_len
< 4 + outer_tlv_len
)) {
1920 wpa_printf(MSG_INFO
,
1921 "EAP-TEAP: Message Length field has too small value to include Outer TLVs");
1925 if (wpabuf_len(respData
) < 4 + outer_tlv_len
||
1926 len
< outer_tlv_len
)
1928 resp
= wpabuf_alloc(wpabuf_len(respData
) - 4 - outer_tlv_len
);
1931 hdr
= wpabuf_head(respData
);
1932 wpabuf_put_u8(resp
, *hdr
++); /* Code */
1933 wpabuf_put_u8(resp
, *hdr
++); /* Identifier */
1934 wpabuf_put_be16(resp
, WPA_GET_BE16(hdr
) - 4 - outer_tlv_len
);
1936 wpabuf_put_u8(resp
, *hdr
++); /* Type */
1938 wpabuf_put_u8(resp
, flags
& ~EAP_TEAP_FLAGS_OUTER_TLV_LEN
);
1940 if (flags
& EAP_TLS_FLAGS_LENGTH_INCLUDED
)
1941 wpabuf_put_be32(resp
, message_len
- 4 - outer_tlv_len
);
1943 wpabuf_put_data(resp
, pos
, len
- outer_tlv_len
);
1944 pos
+= len
- outer_tlv_len
;
1945 wpabuf_free(data
->peer_outer_tlvs
);
1946 data
->peer_outer_tlvs
= wpabuf_alloc_copy(pos
, outer_tlv_len
);
1947 if (!data
->peer_outer_tlvs
)
1949 wpa_hexdump_buf(MSG_DEBUG
, "EAP-TEAP: Outer TLVs",
1950 data
->peer_outer_tlvs
);
1952 wpa_hexdump_buf(MSG_DEBUG
,
1953 "EAP-TEAP: TLS Data message after Outer TLV removal",
1955 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, resp
,
1957 if (!pos
|| len
< 1) {
1958 wpa_printf(MSG_INFO
,
1959 "EAP-TEAP: Invalid frame after Outer TLV removal");
1964 if (data
->state
== PHASE1
)
1965 eap_teap_state(data
, PHASE1B
);
1967 if (eap_server_tls_process(sm
, &data
->ssl
, resp
, data
,
1968 EAP_TYPE_TEAP
, eap_teap_process_version
,
1969 eap_teap_process_msg
) < 0)
1970 eap_teap_state(data
, FAILURE
);
1972 if (resp
!= respData
)
1977 static Boolean
eap_teap_isDone(struct eap_sm
*sm
, void *priv
)
1979 struct eap_teap_data
*data
= priv
;
1981 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
1985 static u8
* eap_teap_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
1987 struct eap_teap_data
*data
= priv
;
1990 if (data
->state
!= SUCCESS
)
1993 eapKeyData
= os_malloc(EAP_TEAP_KEY_LEN
);
1997 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
1998 * is used in this derivation */
1999 if (eap_teap_derive_eap_msk(data
->tls_cs
, data
->simck_msk
,
2001 os_free(eapKeyData
);
2004 *len
= EAP_TEAP_KEY_LEN
;
2010 static u8
* eap_teap_get_emsk(struct eap_sm
*sm
, void *priv
, size_t *len
)
2012 struct eap_teap_data
*data
= priv
;
2015 if (data
->state
!= SUCCESS
)
2018 eapKeyData
= os_malloc(EAP_EMSK_LEN
);
2022 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
2023 * is used in this derivation */
2024 if (eap_teap_derive_eap_emsk(data
->tls_cs
, data
->simck_msk
,
2026 os_free(eapKeyData
);
2029 *len
= EAP_EMSK_LEN
;
2035 static Boolean
eap_teap_isSuccess(struct eap_sm
*sm
, void *priv
)
2037 struct eap_teap_data
*data
= priv
;
2039 return data
->state
== SUCCESS
;
2043 static u8
* eap_teap_get_session_id(struct eap_sm
*sm
, void *priv
, size_t *len
)
2045 struct eap_teap_data
*data
= priv
;
2046 const size_t max_id_len
= 100;
2050 if (data
->state
!= SUCCESS
)
2053 id
= os_malloc(max_id_len
);
2057 id
[0] = EAP_TYPE_TEAP
;
2058 res
= tls_get_tls_unique(data
->ssl
.conn
, id
+ 1, max_id_len
- 1);
2061 wpa_printf(MSG_ERROR
, "EAP-TEAP: Failed to derive Session-Id");
2066 wpa_hexdump(MSG_DEBUG
, "EAP-TEAP: Derived Session-Id", id
, *len
);
2071 int eap_server_teap_register(void)
2073 struct eap_method
*eap
;
2075 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
2076 EAP_VENDOR_IETF
, EAP_TYPE_TEAP
, "TEAP");
2080 eap
->init
= eap_teap_init
;
2081 eap
->reset
= eap_teap_reset
;
2082 eap
->buildReq
= eap_teap_buildReq
;
2083 eap
->check
= eap_teap_check
;
2084 eap
->process
= eap_teap_process
;
2085 eap
->isDone
= eap_teap_isDone
;
2086 eap
->getKey
= eap_teap_getKey
;
2087 eap
->get_emsk
= eap_teap_get_emsk
;
2088 eap
->isSuccess
= eap_teap_isSuccess
;
2089 eap
->getSessionId
= eap_teap_get_session_id
;
2091 return eap_server_method_register(eap
);