From: Shivani Baranwal Date: Sun, 4 Aug 2024 22:41:30 +0000 (+0530) Subject: P2P2: Validate DIRA and configure PMK X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c009ac4747995cf84e0d034a025bd6d6b1260126;p=thirdparty%2Fhostap.git P2P2: Validate DIRA and configure PMK When DIRA is matched, configure PMK for pairing verification of a previously paired peer. Signed-off-by: Shivani Baranwal --- diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 6312f5834..bb970f802 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -6006,6 +6006,16 @@ static int p2p_derive_nonce_tag(struct p2p_data *p2p) } +static void p2p_validate_dira(struct p2p_data *p2p, struct p2p_device *dev, + const u8 *dira, u16 dira_len) +{ + if (p2p->cfg->validate_dira) + p2p->cfg->validate_dira(p2p->cfg->cb_ctx, + dev->info.p2p_device_addr, + dira, dira_len); +} + + struct wpabuf * p2p_usd_elems(struct p2p_data *p2p) { struct wpabuf *buf; @@ -6117,6 +6127,9 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, if (!ether_addr_equal(peer_addr, p2p_dev_addr)) os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN); + if (msg.dira && msg.dira_len) + p2p_validate_dira(p2p, dev, msg.dira, msg.dira_len); + p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR " dev_capab=0x%x group_capab=0x%x listen_freq=%d", MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab, @@ -7032,4 +7045,14 @@ int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt, return ret; } + +void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst, + const u8 *pmk, size_t pmk_len, const u8 *pmkid) +{ + pasn_initiator_pmksa_cache_add(p2p->initiator_pmksa, src, dst, pmk, + pmk_len, pmkid); + pasn_responder_pmksa_cache_add(p2p->responder_pmksa, src, dst, pmk, + pmk_len, pmkid); +} + #endif /* CONFIG_PASN */ diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index cd214d484..c7a803bc3 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1325,6 +1325,22 @@ struct p2p_config { void (*bootstrap_completed)(void *ctx, const u8 *addr, enum p2p_status_code status, int freq); + /** + * validate_dira - Indicate reception of DIRA to be validated against a + * list of available device identity keys + * @ctx: Callback context from cb_ctx + * @peer_addr: P2P Device address of the peer + * @dira: DIRA attribute present in the USD frames + * @dira_len: Length of DIRA + * + * This function can be used to validate DIRA and configure PMK of a + * paired/persistent peer from configuration. The handler function is + * expected to call p2p_pasn_pmksa_set_pmk() to set the PMK/PMKID in + * case a matching entry is found. + */ + void (*validate_dira)(void *ctx, const u8 *peer_addr, + const u8 *dira, size_t dira_len); + /** * pasn_send_mgmt - Function handler to transmit a Management frame * @ctx: Callback context from cb_ctx @@ -2705,5 +2721,7 @@ int p2p_parse_data_element(struct p2p_data *p2p, const u8 *data, size_t len); int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data, size_t data_len, bool acked, bool verify); int p2p_config_sae_password(struct p2p_data *p2p, const char *pw); +void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst, + const u8 *pmk, size_t pmk_len, const u8 *pmkid); #endif /* P2P_H */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 1cbe6f1aa..e967efd89 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -5223,6 +5223,70 @@ static void wpas_bootstrap_completed(void *ctx, const u8 *addr, } +static void wpas_validate_dira(void *ctx, const u8 *peer_addr, + const u8 *dira, size_t dira_len) +{ + struct wpa_supplicant *wpa_s = ctx; + int ret; + u8 tag[DEVICE_MAX_HASH_LEN]; + struct wpa_dev_ik *ik; + const u8 *addr[3]; + size_t len[3]; + const char *label = "DIR"; + + if (dira_len < 1 || dira[0] != DIRA_CIPHER_VERSION_128) { + wpa_printf(MSG_ERROR, + "P2P2: Unsupported DIRA cipher version %d", dira[0]); + return; + } + + if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN) + { + wpa_printf(MSG_INFO, "P2P2: Truncated DIRA (length %zu)", + dira_len); + return; + } + + addr[0] = (const u8 *) label; + len[0] = DIR_STR_LEN; + addr[1] = peer_addr; + len[1] = ETH_ALEN; + addr[2] = &dira[1]; + len[2] = DEVICE_IDENTITY_NONCE_LEN; + + for (ik = wpa_s->conf->identity; ik; ik = ik->next) { + if (wpabuf_len(ik->dik) != DEVICE_IDENTITY_KEY_LEN || + ik->dik_cipher != DIRA_CIPHER_VERSION_128) + continue; + + ret = hmac_sha256_vector(wpabuf_head(ik->dik), + DEVICE_IDENTITY_KEY_LEN, + 3, addr, len, tag); + if (ret < 0) { + wpa_printf(MSG_ERROR, + "P2P2: Failed to derive DIRA Tag"); + return; + } + + if (os_memcmp(tag, &dira[1 + DEVICE_IDENTITY_NONCE_LEN], + DEVICE_IDENTITY_TAG_LEN) == 0) { + wpa_printf(MSG_DEBUG, "P2P2: DIRA Tag matched"); + break; + } + } + + if (!ik) + return; + +#ifdef CONFIG_PASN + p2p_pasn_pmksa_set_pmk(wpa_s->global->p2p, wpa_s->global->p2p_dev_addr, + peer_addr, + wpabuf_head(ik->pmk), wpabuf_len(ik->pmk), + wpabuf_head(ik->pmkid)); +#endif /* CONFIG_PASN */ +} + + #ifdef CONFIG_PASN static int wpas_p2p_initiate_pasn_verify(struct wpa_supplicant *wpa_s, @@ -5432,6 +5496,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback; p2p.bootstrap_req_rx = wpas_bootstrap_req_rx; p2p.bootstrap_completed = wpas_bootstrap_completed; + p2p.validate_dira = wpas_validate_dira; #ifdef CONFIG_PASN p2p.pasn_send_mgmt = wpas_p2p_pasn_send_mgmt; p2p.prepare_data_element = wpas_p2p_prepare_data_element;