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: Ajay Singh <ajay.kathat@microchip.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220524120606.9675-4-ajay.kathat@microchip.com
This commit is contained in:
Ajay Singh 2022-05-24 12:06:21 +00:00 committed by Kalle Valo
parent c5b331d4f5
commit 0e703de3ef
6 changed files with 170 additions and 22 deletions

View File

@ -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,23 +652,34 @@ 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 (priv->wilc_gtk[key_index]) {
kfree(priv->wilc_gtk[key_index]->key);
priv->wilc_gtk[key_index]->key = NULL;
kfree(priv->wilc_gtk[key_index]->seq);
priv->wilc_gtk[key_index]->seq = NULL;
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;
kfree(priv->wilc_gtk[key_index]->seq);
priv->wilc_gtk[key_index]->seq = NULL;
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;
kfree(priv->wilc_ptk[key_index]->seq);
priv->wilc_ptk[key_index]->seq = NULL;
kfree(priv->wilc_ptk[key_index]);
priv->wilc_ptk[key_index] = NULL;
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;
kfree(priv->wilc_ptk[key_index]->seq);
priv->wilc_ptk[key_index]->seq = NULL;
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) {
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;
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,

View File

@ -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];

View File

@ -271,12 +271,19 @@ error:
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;
}

View File

@ -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

View File

@ -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 */

View File

@ -91,6 +91,12 @@ enum authtype {
WILC_FW_AUTH_OPEN_SYSTEM_SHA256 = 13
};
enum mfptype {
WILC_FW_MFP_NONE = 0x0,
WILC_FW_MFP_OPTIONAL = 0x1,
WILC_FW_MFP_REQUIRED = 0x2
};
enum site_survey {
WILC_FW_SITE_SURVEY_1CH = 0,
WILC_FW_SITE_SURVEY_ALL_CH = 1,
@ -661,6 +667,9 @@ enum {
WID_LOG_TERMINAL_SWITCH = 0x00CD,
WID_TX_POWER = 0x00CE,
WID_WOWLAN_TRIGGER = 0X00CF,
WID_SET_MFP = 0x00D0,
WID_DEFAULT_MGMT_KEY_ID = 0x00D2,
/* EMAC Short WID list */
/* RTS Threshold */
/*
@ -750,6 +759,7 @@ enum {
WID_REMOVE_KEY = 0x301E,
WID_ASSOC_REQ_INFO = 0x301F,
WID_ASSOC_RES_INFO = 0x3020,
WID_ADD_IGTK = 0x3022,
WID_MANUFACTURER = 0x3026, /* Added for CAPI tool */
WID_MODEL_NAME = 0x3027, /* Added for CAPI tool */
WID_MODEL_NUM = 0x3028, /* Added for CAPI tool */