@@ -238,6 +238,38 @@ void pr_add_dev_ik(struct pr_data *pr, const u8 *dik, const char *password,
}
+void pr_set_peer_credentials(struct pr_data *pr, const u8 *addr,
+ const u8 *pmk, size_t pmk_len,
+ const char *password)
+{
+ struct pr_device *dev;
+
+ if (!pr || !addr)
+ return;
+
+ dev = pr_get_device(pr, addr);
+ if (!dev) {
+ wpa_printf(MSG_DEBUG, "PR: set_peer_credentials: " MACSTR
+ " not found", MAC2STR(addr));
+ return;
+ }
+
+ if (pmk && pmk_len) {
+ os_memcpy(dev->pmk, pmk, pmk_len);
+ dev->pmk_len = pmk_len;
+ dev->pmk_valid = true;
+ wpa_printf(MSG_DEBUG, "PR: PMK set for " MACSTR, MAC2STR(addr));
+ }
+
+ if (password) {
+ os_strlcpy(dev->password, password, sizeof(dev->password));
+ dev->password_valid = true;
+ wpa_printf(MSG_DEBUG, "PR: password set for " MACSTR,
+ MAC2STR(addr));
+ }
+}
+
+
static struct wpabuf * pr_encaps_elem(const struct wpabuf *subelems,
u32 ie_type)
{
@@ -361,6 +361,12 @@ struct pr_pasn_ranging_params {
u32 center_freq1;
u32 center_freq2;
u64 cookie;
+
+ /* Per-session credentials — if set, used instead of stored ones */
+ char password[100];
+ bool password_valid;
+ u8 pmk[PMK_LEN_MAX];
+ size_t pmk_len;
};
struct pr_dev_ik {
@@ -639,6 +645,9 @@ void pr_set_dev_addr(struct pr_data *pr, const u8 *addr);
void pr_clear_dev_iks(struct pr_data *pr);
void pr_add_dev_ik(struct pr_data *pr, const u8 *dik, const char *password,
const u8 *pmk, size_t pmk_len, bool own);
+void pr_set_peer_credentials(struct pr_data *pr, const u8 *addr,
+ const u8 *pmk, size_t pmk_len,
+ const char *password);
struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr);
void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
const u8 *peer_addr, unsigned int freq);
@@ -11625,6 +11625,33 @@ static int wpas_ctrl_iface_pr_pasn_start(struct wpa_supplicant *wpa_s,
params.egress_threshold = atoll(token + 17);
} else if (os_strcmp(token, "pd_suppress_results=1") == 0) {
params.pr_suppress_results = true;
+ } else if (os_strncmp(token, "password=", 9) == 0) {
+ size_t pwd_len = os_strlen(token + 9);
+
+ if (pwd_len == 0 || pwd_len >= sizeof(params.password)) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PR_PASN_START invalid password length %zu",
+ pwd_len);
+ return -1;
+ }
+ os_strlcpy(params.password, token + 9,
+ sizeof(params.password));
+ params.password_valid = true;
+ } else if (os_strncmp(token, "pmk=", 4) == 0) {
+ size_t pmk_len = os_strlen(token + 4) / 2;
+
+ if (pmk_len != 32 && pmk_len != 48 && pmk_len != 64) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PR_PASN_START invalid PMK length %zu",
+ pmk_len);
+ return -1;
+ }
+ if (hexstr2bin(token + 4, params.pmk, pmk_len)) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PR_PASN_START invalid PMK");
+ return -1;
+ }
+ params.pmk_len = pmk_len;
} else {
wpa_printf(MSG_DEBUG,
"CTRL: PR_PASN_START invalid parameter: '%s'",
@@ -11653,6 +11680,14 @@ static int wpas_ctrl_iface_pr_pasn_start(struct wpa_supplicant *wpa_s,
return -1;
}
+ /* pmk and password are only valid for authenticated modes */
+ if (params.auth_mode == PR_PASN_AUTH_MODE_PASN &&
+ (params.pmk_len > 0 || params.password_valid)) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PR_PASN_START pmk/password not applicable for unauthenticated mode");
+ return -1;
+ }
+
wpa_printf(MSG_DEBUG,
"CTRL: PR_PASN_START params: ranging type=0x%x, role=0x%x,"
" auth_mode=%d, freq=%d, addr=" MACSTR " src_addr=" MACSTR " pasn_role=%d",
@@ -1535,6 +1535,19 @@ void wpas_pr_pasn_trigger(struct wpa_supplicant *wpa_s,
os_memcpy(pr->pr_pasn_params, pr_pasn_params,
sizeof(*pr->pr_pasn_params));
+ /* Ensure peer device entry exists before setting credentials */
+ if (pr_pasn_params->pmk_len > 0 || pr_pasn_params->password_valid) {
+ pr_ensure_oob_peer(pr, pr_pasn_params->peer_addr,
+ pr_pasn_params->freq);
+ pr_set_peer_credentials(pr,
+ pr_pasn_params->peer_addr,
+ pr_pasn_params->pmk_len > 0 ?
+ pr_pasn_params->pmk : NULL,
+ pr_pasn_params->pmk_len,
+ pr_pasn_params->password_valid ?
+ pr_pasn_params->password : NULL);
+ }
+
/* Log EDCA parameters if applicable */
if (pr_pasn_params->ranging_type & PR_EDCA_BASED_RANGING) {
wpa_printf(MSG_DEBUG,