Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e36e5433 authored by Max Stepanov's avatar Max Stepanov Committed by Emmanuel Grumbach
Browse files

iwlwifi: mvm: add a generic cipher scheme support



This patch adds a cipher scheme support to extend a set of
the supported ciphers. The driver reads a cipher scheme list TLV
from FW image and passes it to mac80211 on hw registration.
After the cipher schemes are registered the driver handles key
installation and Tx/Rx calls related to the new ciphers.

Signed-off-by: default avatarMax Stepanov <Max.Stepanov@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 1f3b0ff8
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -322,6 +322,41 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
	pieces->img[type].sec[sec].offset = offset;
}

static int iwl_store_cscheme(struct iwl_fw *fw, const u8 *data, const u32 len)
{
	int i, j;
	struct iwl_fw_cscheme_list *l = (struct iwl_fw_cscheme_list *)data;
	struct iwl_fw_cipher_scheme *fwcs;
	struct ieee80211_cipher_scheme *cs;
	u32 cipher;

	if (len < sizeof(*l) ||
	    len < sizeof(l->size) + l->size * sizeof(l->cs[0]))
		return -EINVAL;

	for (i = 0, j = 0; i < IWL_UCODE_MAX_CS && i < l->size; i++) {
		fwcs = &l->cs[j];
		cipher = le32_to_cpu(fwcs->cipher);

		/* we skip schemes with zero cipher suite selector */
		if (!cipher)
			continue;

		cs = &fw->cs[j++];
		cs->cipher = cipher;
		cs->iftype = BIT(NL80211_IFTYPE_STATION);
		cs->hdr_len = fwcs->hdr_len;
		cs->pn_len = fwcs->pn_len;
		cs->pn_off = fwcs->pn_off;
		cs->key_idx_off = fwcs->key_idx_off;
		cs->key_idx_mask = fwcs->key_idx_mask;
		cs->key_idx_shift = fwcs->key_idx_shift;
		cs->mic_len = fwcs->mic_len;
	}

	return 0;
}

/*
 * Gets uCode section from tlv.
 */
@@ -729,6 +764,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
				return -EINVAL;
			}
			break;
		case IWL_UCODE_TLV_CSCHEME:
			if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len))
				goto invalid_tlv_len;
			break;
		default:
			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
			break;
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ enum iwl_ucode_tlv_type {
	IWL_UCODE_TLV_SECURE_SEC_INIT	= 25,
	IWL_UCODE_TLV_SECURE_SEC_WOWLAN	= 26,
	IWL_UCODE_TLV_NUM_OF_CPU	= 27,
	IWL_UCODE_TLV_CSCHEME		= 28,
};

struct iwl_ucode_tlv {
+41 −0
Original line number Diff line number Diff line
@@ -209,6 +209,44 @@ enum iwl_fw_phy_cfg {
	FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
};

#define IWL_UCODE_MAX_CS		1

/**
 * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
 * @cipher: a cipher suite selector
 * @flags: cipher scheme flags (currently reserved for a future use)
 * @hdr_len: a size of MPDU security header
 * @pn_len: a size of PN
 * @pn_off: an offset of pn from the beginning of the security header
 * @key_idx_off: an offset of key index byte in the security header
 * @key_idx_mask: a bit mask of key_idx bits
 * @key_idx_shift: bit shift needed to get key_idx
 * @mic_len: mic length in bytes
 * @hw_cipher: a HW cipher index used in host commands
 */
struct iwl_fw_cipher_scheme {
	__le32 cipher;
	u8 flags;
	u8 hdr_len;
	u8 pn_len;
	u8 pn_off;
	u8 key_idx_off;
	u8 key_idx_mask;
	u8 key_idx_shift;
	u8 mic_len;
	u8 hw_cipher;
} __packed;

/**
 * struct iwl_fw_cscheme_list - a cipher scheme list
 * @size: a number of entries
 * @cs: cipher scheme entries
 */
struct iwl_fw_cscheme_list {
	u8 size;
	struct iwl_fw_cipher_scheme cs[];
} __packed;

/**
 * struct iwl_fw - variables associated with the firmware
 *
@@ -224,6 +262,7 @@ enum iwl_fw_phy_cfg {
 * @inst_evtlog_size: event log size for runtime ucode.
 * @inst_errlog_ptr: error log offfset for runtime ucode.
 * @mvm_fw: indicates this is MVM firmware
 * @cipher_scheme: optional external cipher scheme.
 */
struct iwl_fw {
	u32 ucode_ver;
@@ -243,6 +282,8 @@ struct iwl_fw {
	u32 phy_config;

	bool mvm_fw;

	struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
};

static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
+9 −1
Original line number Diff line number Diff line
@@ -138,7 +138,14 @@ enum iwl_sta_flags {

/**
 * enum iwl_sta_key_flag - key flags for the ADD_STA host command
 * @STA_KEY_FLG_EN_MSK: mask for encryption algorithm
 * @STA_KEY_FLG_NO_ENC: no encryption
 * @STA_KEY_FLG_WEP: WEP encryption algorithm
 * @STA_KEY_FLG_CCM: CCMP encryption algorithm
 * @STA_KEY_FLG_TKIP: TKIP encryption algorithm
 * @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)
 * @STA_KEY_FLG_CMAC: CMAC encryption algorithm
 * @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm
 * @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
 * @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
 *	station info array (1 - n 1X mode)
 * @STA_KEY_FLG_KEYID_MSK: the index of the key
@@ -152,6 +159,7 @@ enum iwl_sta_key_flag {
	STA_KEY_FLG_WEP			= (1 << 0),
	STA_KEY_FLG_CCM			= (2 << 0),
	STA_KEY_FLG_TKIP		= (3 << 0),
	STA_KEY_FLG_EXT			= (4 << 0),
	STA_KEY_FLG_CMAC		= (6 << 0),
	STA_KEY_FLG_ENC_UNKNOWN		= (7 << 0),
	STA_KEY_FLG_EN_MSK		= (7 << 0),
+1 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ enum iwl_tx_flags {
#define TX_CMD_SEC_WEP			0x01
#define TX_CMD_SEC_CCM			0x02
#define TX_CMD_SEC_TKIP			0x03
#define TX_CMD_SEC_EXT			0x04
#define TX_CMD_SEC_MSK			0x07
#define TX_CMD_SEC_WEP_KEY_IDX_POS	6
#define TX_CMD_SEC_WEP_KEY_IDX_MSK	0xc0
Loading