EAP-TEAP server: Allow tunneled EAP method sequence to be optimized

Include the start of the next EAP method in an EAP Payload TLV in the
same message with the Crypto-Binding TLV for the previous EAP method to
get rid of one roundtrip when using more than a single EAP
authentication method within the tunnel. The previous, not optimized,
sequence can still be used with eap_teap_method_sequence=1 for more
complete testing coverage.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-12-01 17:04:13 +02:00 committed by Jouni Malinen
parent f791b5bbc7
commit 1a800a9400
6 changed files with 40 additions and 3 deletions

View file

@ -2585,6 +2585,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->eap_teap_separate_result = atoi(pos); bss->eap_teap_separate_result = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_id") == 0) { } else if (os_strcmp(buf, "eap_teap_id") == 0) {
bss->eap_teap_id = atoi(pos); bss->eap_teap_id = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_method_sequence") == 0) {
bss->eap_teap_method_sequence = atoi(pos);
#endif /* EAP_SERVER_TEAP */ #endif /* EAP_SERVER_TEAP */
#ifdef EAP_SERVER_SIM #ifdef EAP_SERVER_SIM
} else if (os_strcmp(buf, "eap_sim_db") == 0) { } else if (os_strcmp(buf, "eap_sim_db") == 0) {

View file

@ -1412,6 +1412,12 @@ eap_server=0
# 5 = require both user and machine identity # 5 = require both user and machine identity
#eap_teap_id=0 #eap_teap_id=0
# EAP-TEAP tunneled EAP method behavior
# 0 = minimize roundtrips by merging start of the next EAP method with the
# crypto-binding of the previous one.
# 1 = complete crypto-binding before starting the next EAP method
#eap_teap_method_sequence=0
# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND # EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
# (default: 0 = disabled). # (default: 0 = disabled).
#eap_sim_aka_result_ind=1 #eap_sim_aka_result_ind=1

View file

@ -443,6 +443,7 @@ struct hostapd_bss_config {
int eap_teap_pac_no_inner; int eap_teap_pac_no_inner;
int eap_teap_separate_result; int eap_teap_separate_result;
int eap_teap_id; int eap_teap_id;
int eap_teap_method_sequence;
int eap_sim_aka_result_ind; int eap_sim_aka_result_ind;
int eap_sim_id; int eap_sim_id;
char *imsi_privacy_key; char *imsi_privacy_key;

View file

@ -211,6 +211,7 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
cfg->eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner; cfg->eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner;
cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result; cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result;
cfg->eap_teap_id = hapd->conf->eap_teap_id; cfg->eap_teap_id = hapd->conf->eap_teap_id;
cfg->eap_teap_method_sequence = hapd->conf->eap_teap_method_sequence;
cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
cfg->eap_sim_id = hapd->conf->eap_sim_id; cfg->eap_sim_id = hapd->conf->eap_sim_id;
cfg->imsi_privacy_key = hapd->imsi_privacy_key; cfg->imsi_privacy_key = hapd->imsi_privacy_key;

View file

@ -209,6 +209,7 @@ struct eap_config {
EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4, EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4,
EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5, EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5,
} eap_teap_id; } eap_teap_id;
int eap_teap_method_sequence;
/** /**
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication

View file

@ -74,11 +74,15 @@ struct eap_teap_data {
enum teap_error_codes error_code; enum teap_error_codes error_code;
enum teap_identity_types cur_id_type; enum teap_identity_types cur_id_type;
bool check_crypto_binding;
}; };
static int eap_teap_process_phase2_start(struct eap_sm *sm, static int eap_teap_process_phase2_start(struct eap_sm *sm,
struct eap_teap_data *data); struct eap_teap_data *data);
static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data,
int vendor, enum eap_type eap_type);
static const char * eap_teap_state_txt(int state) static const char * eap_teap_state_txt(int state)
@ -704,6 +708,8 @@ static struct wpabuf * eap_teap_build_crypto_binding(
wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC", wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
cb->msk_compound_mac, sizeof(cb->msk_compound_mac)); cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
data->check_crypto_binding = true;
return buf; return buf;
} }
@ -889,6 +895,7 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id)
struct eap_teap_data *data = priv; struct eap_teap_data *data = priv;
struct wpabuf *req = NULL; struct wpabuf *req = NULL;
int piggyback = 0; int piggyback = 0;
bool move_to_method = true;
if (data->ssl.state == FRAG_ACK) { if (data->ssl.state == FRAG_ACK) {
return eap_server_tls_build_ack(id, EAP_TYPE_TEAP, return eap_server_tls_build_ack(id, EAP_TYPE_TEAP,
@ -940,6 +947,21 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id)
break; break;
case CRYPTO_BINDING: case CRYPTO_BINDING:
req = eap_teap_build_crypto_binding(sm, data); req = eap_teap_build_crypto_binding(sm, data);
if (req && sm->cfg->eap_teap_auth == 0 &&
data->inner_eap_not_done &&
!data->phase2_method &&
sm->cfg->eap_teap_method_sequence == 0) {
wpa_printf(MSG_DEBUG,
"EAP-TEAP: Continue with inner EAP authentication for second credential (optimized)");
eap_teap_state(data, PHASE2_ID);
if (eap_teap_phase2_init(sm, data, EAP_VENDOR_IETF,
EAP_TYPE_IDENTITY) < 0) {
eap_teap_state(data, FAILURE);
wpabuf_free(req);
return NULL;
}
move_to_method = false;
}
if (data->phase2_method) { if (data->phase2_method) {
/* /*
* Include the start of the next EAP method in the * Include the start of the next EAP method in the
@ -950,6 +972,7 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id)
eap = eap_teap_build_phase2_req(sm, data, id); eap = eap_teap_build_phase2_req(sm, data, id);
req = wpabuf_concat(req, eap); req = wpabuf_concat(req, eap);
if (move_to_method)
eap_teap_state(data, PHASE2_METHOD); eap_teap_state(data, PHASE2_METHOD);
} }
break; break;
@ -1510,7 +1533,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
struct wpabuf *in_data) struct wpabuf *in_data)
{ {
struct eap_teap_tlv_parse tlv; struct eap_teap_tlv_parse tlv;
int check_crypto_binding = data->state == CRYPTO_BINDING; bool check_crypto_binding = data->state == CRYPTO_BINDING ||
data->check_crypto_binding;
if (eap_teap_parse_tlvs(in_data, &tlv) < 0) { if (eap_teap_parse_tlvs(in_data, &tlv) < 0) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
@ -1593,6 +1617,7 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"EAP-TEAP: Valid Crypto-Binding TLV received"); "EAP-TEAP: Valid Crypto-Binding TLV received");
data->check_crypto_binding = false;
if (data->final_result) { if (data->final_result) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"EAP-TEAP: Authentication completed successfully"); "EAP-TEAP: Authentication completed successfully");
@ -1671,7 +1696,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
"EAP-TEAP: Continue with basic password authentication for second credential"); "EAP-TEAP: Continue with basic password authentication for second credential");
eap_teap_state(data, PHASE2_BASIC_AUTH); eap_teap_state(data, PHASE2_BASIC_AUTH);
} else if (check_crypto_binding && data->state == CRYPTO_BINDING && } else if (check_crypto_binding && data->state == CRYPTO_BINDING &&
sm->cfg->eap_teap_auth == 0 && data->inner_eap_not_done) { sm->cfg->eap_teap_auth == 0 && data->inner_eap_not_done &&
sm->cfg->eap_teap_method_sequence == 1) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"EAP-TEAP: Continue with inner EAP authentication for second credential"); "EAP-TEAP: Continue with inner EAP authentication for second credential");
eap_teap_state(data, PHASE2_ID); eap_teap_state(data, PHASE2_ID);