3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2025-02-10 15:24:09 +01:00

handshake: Add pmksa setter & stealer

The majority of this patch was authored by Denis Kenzior, but
I have appended setting the PMK inside handshake_state_set_pmksa
as well as checking if the pmkid exists in
handshake_state_steal_pmkid.

Authored-by: Denis Kenzior <denkenz@gmail.com>
Authored-by: James Prestwood <prestwoj@gmail.com>
This commit is contained in:
Denis Kenzior 2024-11-22 07:15:45 -08:00
parent 235f6e5f14
commit c36358cc7c
3 changed files with 90 additions and 0 deletions

View File

@ -458,6 +458,7 @@ unit_test_eap_sim_SOURCES = unit/test-eap-sim.c \
src/eapol.h src/eapol.c \ src/eapol.h src/eapol.c \
src/eapolutil.h src/eapolutil.c \ src/eapolutil.h src/eapolutil.c \
src/handshake.h src/handshake.c \ src/handshake.h src/handshake.c \
src/pmksa.h src/pmksa.c \
src/eap.h src/eap.c src/eap-private.h \ src/eap.h src/eap.c src/eap-private.h \
src/util.h src/util.c \ src/util.h src/util.c \
src/simauth.h src/simauth.c \ src/simauth.h src/simauth.c \
@ -517,6 +518,7 @@ unit_test_eapol_SOURCES = unit/test-eapol.c \
src/eapol.h src/eapol.c \ src/eapol.h src/eapol.c \
src/eapolutil.h src/eapolutil.c \ src/eapolutil.h src/eapolutil.c \
src/handshake.h src/handshake.c \ src/handshake.h src/handshake.c \
src/pmksa.h src/pmksa.c \
src/eap.h src/eap.c src/eap-private.h \ src/eap.h src/eap.c src/eap-private.h \
src/eap-tls.c src/eap-ttls.c \ src/eap-tls.c src/eap-ttls.c \
src/eap-md5.c src/util.c \ src/eap-md5.c src/util.c \
@ -547,6 +549,7 @@ unit_test_wsc_SOURCES = unit/test-wsc.c src/wscutil.h src/wscutil.c \
src/eapol.h src/eapol.c \ src/eapol.h src/eapol.c \
src/eapolutil.h src/eapolutil.c \ src/eapolutil.h src/eapolutil.c \
src/handshake.h src/handshake.c \ src/handshake.h src/handshake.c \
src/pmksa.h src/pmksa.c \
src/eap.h src/eap.c src/eap-private.h \ src/eap.h src/eap.c src/eap-private.h \
src/util.h src/util.c \ src/util.h src/util.c \
src/erp.h src/erp.c \ src/erp.h src/erp.c \
@ -565,6 +568,7 @@ unit_test_sae_SOURCES = unit/test-sae.c \
src/crypto.h src/crypto.c \ src/crypto.h src/crypto.c \
src/ie.h src/ie.c \ src/ie.h src/ie.c \
src/handshake.h src/handshake.c \ src/handshake.h src/handshake.c \
src/pmksa.h src/pmksa.c \
src/erp.h src/erp.c \ src/erp.h src/erp.c \
src/band.h src/band.c \ src/band.h src/band.c \
src/util.h src/util.c \ src/util.h src/util.c \

View File

@ -43,6 +43,7 @@
#include "src/handshake.h" #include "src/handshake.h"
#include "src/erp.h" #include "src/erp.h"
#include "src/band.h" #include "src/band.h"
#include "src/pmksa.h"
static inline unsigned int n_ecc_groups(void) static inline unsigned int n_ecc_groups(void)
{ {
@ -138,6 +139,9 @@ void handshake_state_unref(struct handshake_state *s)
l_free(s->fils_ip_resp_ie); l_free(s->fils_ip_resp_ie);
l_free(s->vendor_ies); l_free(s->vendor_ies);
if (s->have_pmksa)
l_free(s->pmksa);
if (s->erp_cache) if (s->erp_cache)
erp_cache_put(s->erp_cache); erp_cache_put(s->erp_cache);
@ -701,6 +705,11 @@ void handshake_state_install_ptk(struct handshake_state *s)
{ {
s->ptk_complete = true; s->ptk_complete = true;
if (!s->have_pmksa && IE_AKM_IS_SAE(s->akm_suite)) {
l_debug("Adding PMKSA expiration");
s->expiration = l_time_now() + pmksa_lifetime();
}
if (install_tk) { if (install_tk) {
uint32_t cipher = ie_rsn_cipher_suite_to_cipher( uint32_t cipher = ie_rsn_cipher_suite_to_cipher(
s->pairwise_cipher); s->pairwise_cipher);
@ -1203,3 +1212,71 @@ done:
return r; return r;
} }
bool handshake_state_set_pmksa(struct handshake_state *s,
struct pmksa *pmksa)
{
/* checks for both expiration || pmksa being set */
if (s->expiration)
return false;
s->pmksa = pmksa;
s->have_pmksa = true;
handshake_state_set_pmkid(s, pmksa->pmkid);
handshake_state_set_pmk(s, pmksa->pmk, pmksa->pmk_len);
return true;
}
static struct pmksa *handshake_state_steal_pmksa(struct handshake_state *s)
{
struct pmksa *pmksa;
uint64_t now = l_time_now();
if (s->have_pmksa) {
pmksa = l_steal_ptr(s->pmksa);
s->have_pmksa = false;
if (l_time_after(now, pmksa->expiration)) {
l_free(pmksa);
pmksa = NULL;
}
return pmksa;
}
if (s->expiration && l_time_after(now, s->expiration)) {
s->expiration = 0;
return NULL;
}
if (!s->have_pmkid)
return NULL;
pmksa = l_new(struct pmksa, 1);
pmksa->expiration = s->expiration;
memcpy(pmksa->spa, s->spa, sizeof(s->spa));
memcpy(pmksa->aa, s->aa, sizeof(s->aa));
memcpy(pmksa->ssid, s->ssid, s->ssid_len);
pmksa->ssid_len = s->ssid_len;
pmksa->akm = s->akm_suite;
memcpy(pmksa->pmkid, s->pmkid, sizeof(s->pmkid));
pmksa->pmk_len = s->pmk_len;
memcpy(pmksa->pmk, s->pmk, s->pmk_len);
return pmksa;
}
void handshake_state_cache_pmksa(struct handshake_state *s)
{
struct pmksa *pmksa = handshake_state_steal_pmksa(s);
l_debug("%p", pmksa);
if (!pmksa)
return;
if (L_WARN_ON(pmksa_cache_put(pmksa) < 0))
l_free(pmksa);
}

View File

@ -29,6 +29,7 @@
struct handshake_state; struct handshake_state;
enum crypto_cipher; enum crypto_cipher;
struct eapol_frame; struct eapol_frame;
struct pmksa;
enum handshake_kde { enum handshake_kde {
/* 802.11-2020 Table 12-9 in section 12.7.2 */ /* 802.11-2020 Table 12-9 in section 12.7.2 */
@ -141,6 +142,11 @@ struct handshake_state {
bool supplicant_ocvc : 1; bool supplicant_ocvc : 1;
bool ext_key_id_capable : 1; bool ext_key_id_capable : 1;
bool force_default_ecc_group : 1; bool force_default_ecc_group : 1;
bool have_pmksa : 1;
union {
struct pmksa *pmksa;
uint64_t expiration;
};
uint8_t ssid[SSID_MAX_SIZE]; uint8_t ssid[SSID_MAX_SIZE];
size_t ssid_len; size_t ssid_len;
char *passphrase; char *passphrase;
@ -302,6 +308,9 @@ void handshake_state_set_chandef(struct handshake_state *s,
int handshake_state_verify_oci(struct handshake_state *s, const uint8_t *oci, int handshake_state_verify_oci(struct handshake_state *s, const uint8_t *oci,
size_t oci_len); size_t oci_len);
bool handshake_state_set_pmksa(struct handshake_state *s, struct pmksa *pmksa);
void handshake_state_cache_pmksa(struct handshake_state *s);
bool handshake_util_ap_ie_matches(const struct ie_rsn_info *msg_info, bool handshake_util_ap_ie_matches(const struct ie_rsn_info *msg_info,
const uint8_t *scan_ie, bool is_wpa); const uint8_t *scan_ie, bool is_wpa);