OSDN Git Service

iwlwifi: mvm: add support for responder dynamic config command version 3
authorAvraham Stern <avraham.stern@intel.com>
Mon, 28 Sep 2020 09:23:21 +0000 (12:23 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Thu, 1 Oct 2020 18:59:38 +0000 (21:59 +0300)
Version 3 of the dynamic config command adds support for configuring
the HLTK for secure ranging with a station.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200928121852.f54be85420dd.I39b498fbbbc2f6eed6ce1f77b0f59f7a72fab343@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/location.h
drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c

index cdf52b3..465a8e3 100644 (file)
@@ -321,12 +321,54 @@ struct iwl_tof_responder_config_cmd {
  *     data (if exists) follows, and then 0-padding again to complete a
  *     4-multiple long buffer.
  */
-struct iwl_tof_responder_dyn_config_cmd {
+struct iwl_tof_responder_dyn_config_cmd_v2 {
        __le32 lci_len;
        __le32 civic_len;
        u8 lci_civic[];
 } __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_2 */
 
+#define IWL_LCI_MAX_SIZE       160
+#define IWL_CIVIC_MAX_SIZE     160
+#define HLTK_11AZ_LEN  32
+
+/**
+ * enum iwl_responder_dyn_cfg_valid_flags - valid flags for dyn_config_cmd
+ * @IWL_RESPONDER_DYN_CFG_VALID_LCI: LCI data is valid
+ * @IWL_RESPONDER_DYN_CFG_VALID_CIVIC: Civic data is valid
+ * @IWL_RESPONDER_DYN_CFG_VALID_PASN_STA: the pasn_addr, HLTK and cipher fields
+ *     are valid.
+ */
+enum iwl_responder_dyn_cfg_valid_flags {
+       IWL_RESPONDER_DYN_CFG_VALID_LCI = BIT(0),
+       IWL_RESPONDER_DYN_CFG_VALID_CIVIC = BIT(1),
+       IWL_RESPONDER_DYN_CFG_VALID_PASN_STA = BIT(2),
+};
+
+/**
+ * struct iwl_tof_responder_dyn_config_cmd - Dynamic responder settings
+ * @cipher: The negotiated cipher. see &enum iwl_location_cipher.
+ * @valid_flags: flags indicating which fields in the command are valid. see
+ *     &enum iwl_responder_dyn_cfg_valid_flags.
+ * @lci_len: length of the LCI data in bytes
+ * @civic_len: length of the Civic data in bytes
+ * @lci_buf: the LCI buffer
+ * @civic_buf: the Civic buffer
+ * @hltk_buf: HLTK for secure LTF bits generation for the specified station
+ * @addr: mac address of the station for which to use the HLTK
+ * @reserved: for alignment
+ */
+struct iwl_tof_responder_dyn_config_cmd {
+       u8 cipher;
+       u8 valid_flags;
+       u8 lci_len;
+       u8 civic_len;
+       u8 lci_buf[IWL_LCI_MAX_SIZE];
+       u8 civic_buf[IWL_LCI_MAX_SIZE];
+       u8 hltk_buf[HLTK_11AZ_LEN];
+       u8 addr[ETH_ALEN];
+       u8 reserved[2];
+} __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_3 */
+
 /**
  * struct iwl_tof_range_req_ext_cmd - extended range req for WLS
  * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF
@@ -507,7 +549,6 @@ enum iwl_location_bw {
        IWL_LOCATION_BW_80MHZ,
 };
 
-#define HLTK_11AZ_LEN  32
 #define TK_11AZ_LEN    32
 
 #define LOCATION_BW_POS        4
index 160f3f9..e24e5bc 100644 (file)
@@ -68,6 +68,12 @@ struct iwl_mvm_pasn_sta {
        u8 addr[ETH_ALEN];
 };
 
+struct iwl_mvm_pasn_hltk_data {
+       u8 *addr;
+       u8 cipher;
+       u8 *hltk;
+};
+
 static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,
                                           u8 *bw, u8 *ctrl_ch_position)
 {
@@ -143,8 +149,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
                .sta_id = mvmvif->bcast_sta.sta_id,
        };
        u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
-                                          TOF_RESPONDER_CONFIG_CMD,
-                                          IWL_FW_CMD_VER_UNKNOWN);
+                                          TOF_RESPONDER_CONFIG_CMD, 6);
        int err;
 
        lockdep_assert_held(&mvm->mutex);
@@ -169,11 +174,11 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
 }
 
 static int
-iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
-                                 struct ieee80211_vif *vif,
-                                 struct ieee80211_ftm_responder_params *params)
+iwl_mvm_ftm_responder_dyn_cfg_v2(struct iwl_mvm *mvm,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_ftm_responder_params *params)
 {
-       struct iwl_tof_responder_dyn_config_cmd cmd = {
+       struct iwl_tof_responder_dyn_config_cmd_v2 cmd = {
                .lci_len = cpu_to_le32(params->lci_len + 2),
                .civic_len = cpu_to_le32(params->civicloc_len + 2),
        };
@@ -214,6 +219,93 @@ iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
        return iwl_mvm_send_cmd(mvm, &hcmd);
 }
 
+static int
+iwl_mvm_ftm_responder_dyn_cfg_v3(struct iwl_mvm *mvm,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_ftm_responder_params *params,
+                                struct iwl_mvm_pasn_hltk_data *hltk_data)
+{
+       struct iwl_tof_responder_dyn_config_cmd cmd;
+       struct iwl_host_cmd hcmd = {
+               .id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
+                                LOCATION_GROUP, 0),
+               .data[0] = &cmd,
+               .len[0] = sizeof(cmd),
+               /* may not be able to DMA from stack */
+               .dataflags[0] = IWL_HCMD_DFL_DUP,
+       };
+
+       lockdep_assert_held(&mvm->mutex);
+
+       cmd.valid_flags = 0;
+
+       if (params) {
+               if (params->lci_len + 2 > sizeof(cmd.lci_buf) ||
+                   params->civicloc_len + 2 > sizeof(cmd.civic_buf)) {
+                       IWL_ERR(mvm,
+                               "LCI/civic data too big (lci=%zd, civic=%zd)\n",
+                               params->lci_len, params->civicloc_len);
+                       return -ENOBUFS;
+               }
+
+               cmd.lci_buf[0] = WLAN_EID_MEASURE_REPORT;
+               cmd.lci_buf[1] = params->lci_len;
+               memcpy(cmd.lci_buf + 2, params->lci, params->lci_len);
+               cmd.lci_len = params->lci_len + 2;
+
+               cmd.civic_buf[0] = WLAN_EID_MEASURE_REPORT;
+               cmd.civic_buf[1] = params->civicloc_len;
+               memcpy(cmd.civic_buf + 2, params->civicloc,
+                      params->civicloc_len);
+               cmd.civic_len = params->civicloc_len + 2;
+
+               cmd.valid_flags |= IWL_RESPONDER_DYN_CFG_VALID_LCI |
+                       IWL_RESPONDER_DYN_CFG_VALID_CIVIC;
+       }
+
+       if (hltk_data) {
+               if (hltk_data->cipher > IWL_LOCATION_CIPHER_GCMP_256) {
+                       IWL_ERR(mvm, "invalid cipher: %u\n",
+                               hltk_data->cipher);
+                       return -EINVAL;
+               }
+
+               cmd.cipher = hltk_data->cipher;
+               memcpy(cmd.addr, hltk_data->addr, sizeof(cmd.addr));
+               memcpy(cmd.hltk_buf, hltk_data->hltk, sizeof(cmd.hltk_buf));
+               cmd.valid_flags |= IWL_RESPONDER_DYN_CFG_VALID_PASN_STA;
+       }
+
+       return iwl_mvm_send_cmd(mvm, &hcmd);
+}
+
+static int
+iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
+                                 struct ieee80211_vif *vif,
+                                 struct ieee80211_ftm_responder_params *params)
+{
+       int ret;
+       u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
+                                          TOF_RESPONDER_DYN_CONFIG_CMD, 2);
+
+       switch (cmd_ver) {
+       case 2:
+               ret = iwl_mvm_ftm_responder_dyn_cfg_v2(mvm, vif,
+                                                      params);
+               break;
+       case 3:
+               ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif,
+                                                      params, NULL);
+               break;
+       default:
+               IWL_ERR(mvm, "Unsupported DYN_CONFIG_CMD version %u\n",
+                       cmd_ver);
+               ret = -ENOTSUPP;
+       }
+
+       return ret;
+}
+
 int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
                                      struct ieee80211_vif *vif,
                                      u8 *addr, u32 cipher, u8 *tk, u32 tk_len,