From 4ff0df39eb0eb1623ce496ae9b5706c8599e8bc4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 14:00:28 +0300 Subject: [PATCH] SAE-PK: Testing functionality to allow behavior overrides The new sae_commit_status and sae_pk_omit configuration parameters and an extra key at the end of sae_password pk argument can be used to override SAE-PK behavior for testing purposes. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 4 ++++ src/ap/ap_config.c | 4 ++++ src/ap/ap_config.h | 2 ++ src/ap/ieee802_11.c | 16 +++++++++++++++ src/common/sae.h | 6 ++++++ src/common/sae_pk.c | 47 ++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 76 insertions(+), 3 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 49894c5ba..dac0e8054 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4231,6 +4231,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->own_ie_override = tmp; } else if (os_strcmp(buf, "sae_reflection_attack") == 0) { bss->sae_reflection_attack = atoi(pos); + } else if (os_strcmp(buf, "sae_commit_status") == 0) { + bss->sae_commit_status = atoi(pos); + } else if (os_strcmp(buf, "sae_pk_omit") == 0) { + bss->sae_pk_omit = atoi(pos); } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index a4e1bbb3d..1c6b4a00e 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -160,6 +160,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) /* Default to strict CRL checking. */ bss->check_crl_strict = 1; + +#ifdef CONFIG_TESTING_OPTIONS + bss->sae_commit_status = -1; +#endif /* CONFIG_TESTING_OPTIONS */ } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index cafc44edd..4c2e60095 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -678,6 +678,8 @@ struct hostapd_bss_config { u8 bss_load_test_set; struct wpabuf *own_ie_override; int sae_reflection_attack; + int sae_commit_status; + int sae_pk_omit; struct wpabuf *sae_commit_override; struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index eca8b19ad..8b994d6a5 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -567,6 +567,13 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, if (buf == NULL) return NULL; +#ifdef CONFIG_SAE_PK +#ifdef CONFIG_TESTING_OPTIONS + if (sta->sae->tmp) + sta->sae->tmp->omit_pk_elem = hapd->conf->sae_pk_omit; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_SAE_PK */ + if (sae_write_confirm(sta->sae, buf) < 0) { wpabuf_free(buf); return NULL; @@ -600,6 +607,15 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; else status = WLAN_STATUS_SUCCESS; +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->sae_commit_status >= 0 && + hapd->conf->sae_commit_status != status) { + wpa_printf(MSG_INFO, + "TESTING: Override SAE commit status code %u --> %d", + status, hapd->conf->sae_commit_status); + status = hapd->conf->sae_commit_status; + } +#endif /* CONFIG_TESTING_OPTIONS */ reply_res = send_auth_reply(hapd, sta, sta->addr, bssid, WLAN_AUTH_SAE, 1, status, wpabuf_head(data), diff --git a/src/common/sae.h b/src/common/sae.h index 887cd4e9a..261935fdb 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -31,6 +31,9 @@ struct sae_pk { struct crypto_ec_key *key; int group; struct wpabuf *pubkey; /* DER encoded subjectPublicKey */ +#ifdef CONFIG_TESTING_OPTIONS + struct crypto_ec_key *sign_key_override; +#endif /* CONFIG_TESTING_OPTIONS */ }; @@ -73,6 +76,9 @@ struct sae_temporary_data { u8 ssid[32]; size_t ssid_len; bool reject_group; +#ifdef CONFIG_TESTING_OPTIONS + bool omit_pk_elem; +#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_SAE_PK */ }; diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 806498c38..bb9c979a1 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -203,6 +203,9 @@ void sae_deinit_pk(struct sae_pk *pk) if (pk) { wpabuf_free(pk->m); crypto_ec_key_deinit(pk->key); +#ifdef CONFIG_TESTING_OPTIONS + crypto_ec_key_deinit(pk->sign_key_override); +#endif /* CONFIG_TESTING_OPTIONS */ wpabuf_free(pk->pubkey); os_free(pk); } @@ -213,9 +216,12 @@ struct sae_pk * sae_parse_pk(const char *val) { struct sae_pk *pk; const char *pos; +#ifdef CONFIG_TESTING_OPTIONS + const char *pos2; +#endif /* CONFIG_TESTING_OPTIONS */ size_t len; unsigned char *der; - size_t der_len; + size_t der_len, b_len; /* : */ @@ -239,7 +245,15 @@ struct sae_pk * sae_parse_pk(const char *val) } pos++; - der = base64_decode(pos, os_strlen(pos), &der_len); + b_len = os_strlen(pos); +#ifdef CONFIG_TESTING_OPTIONS + pos2 = os_strchr(pos, ':'); + if (pos2) { + b_len = pos2 - pos; + pos2++; + } +#endif /* CONFIG_TESTING_OPTIONS */ + der = base64_decode(pos, b_len, &der_len); if (!der) { wpa_printf(MSG_INFO, "SAE: Failed to base64 decode PK key"); goto fail; @@ -254,6 +268,22 @@ struct sae_pk * sae_parse_pk(const char *val) if (!pk->pubkey) goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (pos2) { + der = base64_decode(pos2, os_strlen(pos2), &der_len); + if (!der) { + wpa_printf(MSG_INFO, + "SAE: Failed to base64 decode PK key"); + goto fail; + } + + pk->sign_key_override = crypto_ec_key_parse_priv(der, der_len); + bin_clear_free(der, der_len); + if (!pk->sign_key_override) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + return pk; fail: sae_deinit_pk(pk); @@ -342,6 +372,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) const struct sae_pk *pk; u8 hash[SAE_MAX_HASH_LEN]; size_t hash_len; + struct crypto_ec_key *key; if (!tmp) return -1; @@ -350,6 +381,16 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) if (!pk) return 0; + key = pk->key; +#ifdef CONFIG_TESTING_OPTIONS + if (tmp->omit_pk_elem) + return 0; + if (pk->sign_key_override) { + wpa_printf(MSG_INFO, "TESTING: Override SAE-PK signing key"); + key = pk->sign_key_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); return -1; @@ -368,7 +409,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) wpabuf_len(pk->m), wpabuf_head(pk->pubkey), wpabuf_len(pk->pubkey), hash) < 0) goto fail; - sig = crypto_ec_key_sign(pk->key, hash, hash_len); + sig = crypto_ec_key_sign(key, hash, hash_len); if (!sig) goto fail; wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig);