Commit 0e703de3 authored by Ajay Singh's avatar Ajay Singh Committed by Kalle Valo
Browse files

wifi: wilc1000: add IGTK support



Add support to handle IGTK keys which are required for MFP to FW. Index ID
4 and 5 are used to store the IGTK key.

Signed-off-by: default avatarAjay Singh <ajay.kathat@microchip.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220524120606.9675-4-ajay.kathat@microchip.com
parent c5b331d4
Loading
Loading
Loading
Loading
+92 −22
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
	int ret;
	u32 i;
	u8 security = WILC_FW_SEC_NO;
	enum mfptype mfp_type = WILC_FW_MFP_NONE;
	enum authtype auth_type = WILC_FW_AUTH_ANY;
	u32 cipher_group;
	struct cfg80211_bss *bss;
@@ -416,6 +417,13 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
	wfi_drv->conn_info.arg = priv;
	wfi_drv->conn_info.param = join_params;

	if (sme->mfp == NL80211_MFP_OPTIONAL)
		mfp_type = WILC_FW_MFP_OPTIONAL;
	else if (sme->mfp == NL80211_MFP_REQUIRED)
		mfp_type = WILC_FW_MFP_REQUIRED;

	wfi_drv->conn_info.mfp_type = mfp_type;

	ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len);
	if (ret) {
		netdev_err(dev, "wilc_set_join_req(): Error\n");
@@ -495,6 +503,18 @@ static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx)
	return 0;
}

static int wilc_wfi_cfg_allocate_wpa_igtk_entry(struct wilc_priv *priv, u8 idx)
{
	idx -= 4;
	if (!priv->wilc_igtk[idx]) {
		priv->wilc_igtk[idx] = kzalloc(sizeof(*priv->wilc_igtk[idx]),
					       GFP_KERNEL);
		if (!priv->wilc_igtk[idx])
			return -ENOMEM;
	}
	return 0;
}

static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info,
				      struct key_params *params)
{
@@ -531,6 +551,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
	u8 op_mode;
	struct wilc_vif *vif = netdev_priv(netdev);
	struct wilc_priv *priv = &vif->priv;
	struct wilc_wfi_key *key;

	switch (params->cipher) {
	case WLAN_CIPHER_SUITE_TKIP:
@@ -594,6 +615,26 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
					   key_index);

		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
		ret = wilc_wfi_cfg_allocate_wpa_igtk_entry(priv, key_index);
		if (ret)
			return -ENOMEM;

		key = priv->wilc_igtk[key_index - 4];
		ret = wilc_wfi_cfg_copy_wpa_info(key, params);
		if (ret)
			return -ENOMEM;

		if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
		    priv->wdev.iftype == NL80211_IFTYPE_P2P_GO)
			op_mode = WILC_AP_MODE;
		else
			op_mode = WILC_STATION_MODE;

		ret = wilc_add_igtk(vif, params->key, keylen, params->seq,
				    params->seq_len, mac_addr, op_mode,
				    key_index);
		break;

	default:
		netdev_err(netdev, "%s: Unsupported cipher\n", __func__);
@@ -611,6 +652,17 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
	struct wilc_vif *vif = netdev_priv(netdev);
	struct wilc_priv *priv = &vif->priv;

	if (!pairwise && (key_index == 4 || key_index == 5)) {
		key_index -= 4;
		if (priv->wilc_igtk[key_index]) {
			kfree(priv->wilc_igtk[key_index]->key);
			priv->wilc_igtk[key_index]->key = NULL;
			kfree(priv->wilc_igtk[key_index]->seq);
			priv->wilc_igtk[key_index]->seq = NULL;
			kfree(priv->wilc_igtk[key_index]);
			priv->wilc_igtk[key_index] = NULL;
		}
	} else {
		if (priv->wilc_gtk[key_index]) {
			kfree(priv->wilc_gtk[key_index]->key);
			priv->wilc_gtk[key_index]->key = NULL;
@@ -620,7 +672,6 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
			kfree(priv->wilc_gtk[key_index]);
			priv->wilc_gtk[key_index] = NULL;
		}

		if (priv->wilc_ptk[key_index]) {
			kfree(priv->wilc_ptk[key_index]->key);
			priv->wilc_ptk[key_index]->key = NULL;
@@ -629,6 +680,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
			kfree(priv->wilc_ptk[key_index]);
			priv->wilc_ptk[key_index] = NULL;
		}
	}

	return 0;
}
@@ -642,11 +694,20 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
	struct  key_params key_params;

	if (!pairwise) {
		if (key_index == 4 || key_index == 5) {
			key_index -= 4;
			key_params.key = priv->wilc_igtk[key_index]->key;
			key_params.cipher = priv->wilc_igtk[key_index]->cipher;
			key_params.key_len = priv->wilc_igtk[key_index]->key_len;
			key_params.seq = priv->wilc_igtk[key_index]->seq;
			key_params.seq_len = priv->wilc_igtk[key_index]->seq_len;
		} else {
			key_params.key = priv->wilc_gtk[key_index]->key;
			key_params.cipher = priv->wilc_gtk[key_index]->cipher;
			key_params.key_len = priv->wilc_gtk[key_index]->key_len;
			key_params.seq = priv->wilc_gtk[key_index]->seq;
			key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
		}
	} else {
		key_params.key = priv->wilc_ptk[key_index]->key;
		key_params.cipher = priv->wilc_ptk[key_index]->cipher;
@@ -667,6 +728,14 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
	return 0;
}

static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,
				u8 key_index)
{
	struct wilc_vif *vif = netdev_priv(netdev);

	return wilc_set_default_mgmt_key_index(vif, key_index);
}

static int get_station(struct wiphy *wiphy, struct net_device *dev,
		       const u8 *mac, struct station_info *sinfo)
{
@@ -1626,6 +1695,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
	.del_key = del_key,
	.get_key = get_key,
	.set_default_key = set_default_key,
	.set_default_mgmt_key = set_default_mgmt_key,
	.add_virtual_intf = add_virtual_intf,
	.del_virtual_intf = del_virtual_intf,
	.change_virtual_intf = change_virtual_intf,
+8 −0
Original line number Diff line number Diff line
@@ -54,6 +54,14 @@ struct wilc_ap_wpa_ptk {
	u8 key[];
} __packed;

struct wilc_wpa_igtk {
	u8 index;
	u8 pn_len;
	u8 pn[6];
	u8 key_len;
	u8 key[];
} __packed;

struct wilc_gtk_key {
	u8 mac_addr[ETH_ALEN];
	u8 rsc[8];
+55 −1
Original line number Diff line number Diff line
@@ -271,12 +271,19 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
static int wilc_send_connect_wid(struct wilc_vif *vif)
{
	int result = 0;
	struct wid wid_list[4];
	struct wid wid_list[5];
	u32 wid_cnt = 0;
	struct host_if_drv *hif_drv = vif->hif_drv;
	struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
	struct wilc_join_bss_param *bss_param = conn_attr->param;


        wid_list[wid_cnt].id = WID_SET_MFP;
        wid_list[wid_cnt].type = WID_CHAR;
        wid_list[wid_cnt].size = sizeof(char);
        wid_list[wid_cnt].val = (s8 *)&conn_attr->mfp_type;
        wid_cnt++;

	wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
	wid_list[wid_cnt].type = WID_BIN_DATA;
	wid_list[wid_cnt].val = conn_attr->req_ies;
@@ -1143,6 +1150,36 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
	return result;
}

int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len,
		  const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode, u8 index)
{
	int result = 0;
	u8 t_key_len = igtk_key_len;
	struct wid wid;
	struct wilc_wpa_igtk *key_buf;

	key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
	if (!key_buf)
		return -ENOMEM;

	key_buf->index = index;

	memcpy(&key_buf->pn[0], pn, pn_len);
	key_buf->pn_len = pn_len;

	memcpy(&key_buf->key[0], igtk, igtk_key_len);
	key_buf->key_len = t_key_len;

	wid.id = WID_ADD_IGTK;
	wid.type = WID_STR;
	wid.size = sizeof(*key_buf) + t_key_len;
	wid.val = (s8 *)key_buf;
	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
	kfree(key_buf);

	return result;
}

int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
		    u8 index, u32 key_rsc_len, const u8 *key_rsc,
		    const u8 *rx_mic, const u8 *tx_mic, u8 mode,
@@ -1932,3 +1969,20 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)

	return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
}

int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index)
{
        struct wid wid;
        int result;

        wid.id = WID_DEFAULT_MGMT_KEY_ID;
        wid.type = WID_CHAR;
        wid.size = sizeof(char);
        wid.val = &index;
        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
        if (result)
                netdev_err(vif->ndev,
                           "Failed to send default mgmt key index\n");

        return result;
}
+5 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ struct wilc_conn_info {
	u8 bssid[ETH_ALEN];
	u8 security;
	enum authtype auth_type;
	enum mfptype mfp_type;
	u8 ch;
	u8 *req_ies;
	size_t req_ies_len;
@@ -155,6 +156,9 @@ struct wilc_vif;
int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
		 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
		 u8 mode, u8 cipher_mode, u8 index);
int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len,
		  const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode,
		  u8 index);
s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
			   u32 *out_val);
int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
@@ -210,4 +214,5 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
				struct cfg80211_crypto_settings *crypto);
int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index);
#endif
+1 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ struct wilc_priv {
	struct net_device *real_ndev;
	struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA];
	struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA];
	struct wilc_wfi_key *wilc_igtk[2];
	u8 wilc_groupkey;

	/* mutexes */
Loading