aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAyala Beker <ayala.beker@intel.com>2016-04-07 09:21:57 -0400
committerLuca Coelho <luciano.coelho@intel.com>2016-07-05 19:07:49 -0400
commit2a53d166c464d7b51d6f7204d445fc0254b25f51 (patch)
tree8b717a54a2272473558cf125ce42a415a9fc35f2 /drivers/net
parent9c07e9aafcbe4b2a98c18d9b0ee28c84d749ea84 (diff)
iwlwifi: mvm: add support for GCMP encryption
Newer hardware supports GCMP and GCMP 256-bit ciphers. Add support for adding/setting GCMP key for TX mode. In the TX command handling GCMP-256 is handled in a different way as the key size should be up to 128-bits: Set the key value to the key index in the key table, and specify that this key should be taken form the key table instead of from the TX command. While at it - convert security control flags to an enum. Signed-off-by: Ayala Beker <ayala.beker@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c39
6 files changed, 85 insertions, 24 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 38b1d045be8e..d1c4fb849111 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -141,6 +141,7 @@ enum iwl_sta_flags {
141 * @STA_KEY_FLG_CCM: CCMP encryption algorithm 141 * @STA_KEY_FLG_CCM: CCMP encryption algorithm
142 * @STA_KEY_FLG_TKIP: TKIP encryption algorithm 142 * @STA_KEY_FLG_TKIP: TKIP encryption algorithm
143 * @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support) 143 * @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)
144 * @STA_KEY_FLG_GCMP: GCMP encryption algorithm
144 * @STA_KEY_FLG_CMAC: CMAC encryption algorithm 145 * @STA_KEY_FLG_CMAC: CMAC encryption algorithm
145 * @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm 146 * @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm
146 * @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value 147 * @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
@@ -149,6 +150,7 @@ enum iwl_sta_flags {
149 * @STA_KEY_FLG_KEYID_MSK: the index of the key 150 * @STA_KEY_FLG_KEYID_MSK: the index of the key
150 * @STA_KEY_NOT_VALID: key is invalid 151 * @STA_KEY_NOT_VALID: key is invalid
151 * @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key 152 * @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key
153 * @STA_KEY_FLG_KEY_32BYTES for non-wep key set for 32 bytes key
152 * @STA_KEY_MULTICAST: set for multical key 154 * @STA_KEY_MULTICAST: set for multical key
153 * @STA_KEY_MFP: key is used for Management Frame Protection 155 * @STA_KEY_MFP: key is used for Management Frame Protection
154 */ 156 */
@@ -158,6 +160,7 @@ enum iwl_sta_key_flag {
158 STA_KEY_FLG_CCM = (2 << 0), 160 STA_KEY_FLG_CCM = (2 << 0),
159 STA_KEY_FLG_TKIP = (3 << 0), 161 STA_KEY_FLG_TKIP = (3 << 0),
160 STA_KEY_FLG_EXT = (4 << 0), 162 STA_KEY_FLG_EXT = (4 << 0),
163 STA_KEY_FLG_GCMP = (5 << 0),
161 STA_KEY_FLG_CMAC = (6 << 0), 164 STA_KEY_FLG_CMAC = (6 << 0),
162 STA_KEY_FLG_ENC_UNKNOWN = (7 << 0), 165 STA_KEY_FLG_ENC_UNKNOWN = (7 << 0),
163 STA_KEY_FLG_EN_MSK = (7 << 0), 166 STA_KEY_FLG_EN_MSK = (7 << 0),
@@ -167,6 +170,7 @@ enum iwl_sta_key_flag {
167 STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS), 170 STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS),
168 STA_KEY_NOT_VALID = BIT(11), 171 STA_KEY_NOT_VALID = BIT(11),
169 STA_KEY_FLG_WEP_13BYTES = BIT(12), 172 STA_KEY_FLG_WEP_13BYTES = BIT(12),
173 STA_KEY_FLG_KEY_32BYTES = BIT(12),
170 STA_KEY_MULTICAST = BIT(14), 174 STA_KEY_MULTICAST = BIT(14),
171 STA_KEY_MFP = BIT(15), 175 STA_KEY_MFP = BIT(15),
172}; 176};
@@ -388,7 +392,6 @@ struct iwl_mvm_add_sta_cmd {
388 * @key_offset: key offset in key storage 392 * @key_offset: key offset in key storage
389 * @key_flags: type %iwl_sta_key_flag 393 * @key_flags: type %iwl_sta_key_flag
390 * @key: key material data 394 * @key: key material data
391 * @key2: key material data
392 * @rx_secur_seq_cnt: RX security sequence counter for the key 395 * @rx_secur_seq_cnt: RX security sequence counter for the key
393 * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection 396 * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
394 * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx 397 * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
@@ -397,8 +400,7 @@ struct iwl_mvm_add_sta_key_cmd {
397 u8 sta_id; 400 u8 sta_id;
398 u8 key_offset; 401 u8 key_offset;
399 __le16 key_flags; 402 __le16 key_flags;
400 u8 key[16]; 403 u8 key[32];
401 u8 key2[16];
402 u8 rx_secur_seq_cnt[16]; 404 u8 rx_secur_seq_cnt[16];
403 u8 tkip_rx_tsc_byte2; 405 u8 tkip_rx_tsc_byte2;
404 u8 reserved; 406 u8 reserved;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index ee59511323c1..4144623e1616 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -137,17 +137,32 @@ enum iwl_tx_pm_timeouts {
137 PM_FRAME_ASSOC = 3, 137 PM_FRAME_ASSOC = 3,
138}; 138};
139 139
140/*
141 * TX command security control
142 */
143#define TX_CMD_SEC_WEP 0x01
144#define TX_CMD_SEC_CCM 0x02
145#define TX_CMD_SEC_TKIP 0x03
146#define TX_CMD_SEC_EXT 0x04
147#define TX_CMD_SEC_MSK 0x07 140#define TX_CMD_SEC_MSK 0x07
148#define TX_CMD_SEC_WEP_KEY_IDX_POS 6 141#define TX_CMD_SEC_WEP_KEY_IDX_POS 6
149#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 142#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0
150#define TX_CMD_SEC_KEY128 0x08 143
144/**
145 * enum iwl_tx_cmd_sec_ctrl - bitmasks for security control in TX command
146 * @TX_CMD_SEC_WEP: WEP encryption algorithm.
147 * @TX_CMD_SEC_CCM: CCM encryption algorithm.
148 * @TX_CMD_SEC_TKIP: TKIP encryption algorithm.
149 * @TX_CMD_SEC_EXT: extended cipher algorithm.
150 * @TX_CMD_SEC_GCMP: GCMP encryption algorithm.
151 * @TX_CMD_SEC_KEY128: set for 104 bits WEP key.
152 * @TC_CMD_SEC_KEY_FROM_TABLE: for a non-WEP key, set if the key should be taken
153 * from the table instead of from the TX command.
154 * If the key is taken from the key table its index should be given by the
155 * first byte of the TX command key field.
156 */
157enum iwl_tx_cmd_sec_ctrl {
158 TX_CMD_SEC_WEP = 0x01,
159 TX_CMD_SEC_CCM = 0x02,
160 TX_CMD_SEC_TKIP = 0x03,
161 TX_CMD_SEC_EXT = 0x04,
162 TX_CMD_SEC_GCMP = 0x05,
163 TX_CMD_SEC_KEY128 = 0x08,
164 TC_CMD_SEC_KEY_FROM_TABLE = 0x08,
165};
151 166
152/* TODO: how does these values are OK with only 16 bit variable??? */ 167/* TODO: how does these values are OK with only 16 bit variable??? */
153/* 168/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index af1d266d6fe8..6b158f0de39d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -465,11 +465,20 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
465 hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; 465 hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
466 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; 466 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
467 467
468 BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 2); 468 BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 4);
469 memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers)); 469 memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
470 hw->wiphy->n_cipher_suites = ARRAY_SIZE(mvm_ciphers); 470 hw->wiphy->n_cipher_suites = ARRAY_SIZE(mvm_ciphers);
471 hw->wiphy->cipher_suites = mvm->ciphers; 471 hw->wiphy->cipher_suites = mvm->ciphers;
472 472
473 if (iwl_mvm_has_new_rx_api(mvm)) {
474 mvm->ciphers[hw->wiphy->n_cipher_suites] =
475 WLAN_CIPHER_SUITE_GCMP;
476 hw->wiphy->n_cipher_suites++;
477 mvm->ciphers[hw->wiphy->n_cipher_suites] =
478 WLAN_CIPHER_SUITE_GCMP_256;
479 hw->wiphy->n_cipher_suites++;
480 }
481
473 /* 482 /*
474 * Enable 11w if advertised by firmware and software crypto 483 * Enable 11w if advertised by firmware and software crypto
475 * is not enabled (as the firmware will interpret some mgmt 484 * is not enabled (as the firmware will interpret some mgmt
@@ -2721,6 +2730,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
2721 key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; 2730 key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
2722 break; 2731 break;
2723 case WLAN_CIPHER_SUITE_CCMP: 2732 case WLAN_CIPHER_SUITE_CCMP:
2733 case WLAN_CIPHER_SUITE_GCMP:
2734 case WLAN_CIPHER_SUITE_GCMP_256:
2724 key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; 2735 key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
2725 break; 2736 break;
2726 case WLAN_CIPHER_SUITE_AES_CMAC: 2737 case WLAN_CIPHER_SUITE_AES_CMAC:
@@ -2782,7 +2793,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
2782 sta && iwl_mvm_has_new_rx_api(mvm) && 2793 sta && iwl_mvm_has_new_rx_api(mvm) &&
2783 key->flags & IEEE80211_KEY_FLAG_PAIRWISE && 2794 key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
2784 (key->cipher == WLAN_CIPHER_SUITE_CCMP || 2795 (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
2785 key->cipher == WLAN_CIPHER_SUITE_GCMP)) { 2796 key->cipher == WLAN_CIPHER_SUITE_GCMP ||
2797 key->cipher == WLAN_CIPHER_SUITE_GCMP_256)) {
2786 struct ieee80211_key_seq seq; 2798 struct ieee80211_key_seq seq;
2787 int tid, q; 2799 int tid, q;
2788 2800
@@ -2836,7 +2848,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
2836 if (sta && iwl_mvm_has_new_rx_api(mvm) && 2848 if (sta && iwl_mvm_has_new_rx_api(mvm) &&
2837 key->flags & IEEE80211_KEY_FLAG_PAIRWISE && 2849 key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
2838 (key->cipher == WLAN_CIPHER_SUITE_CCMP || 2850 (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
2839 key->cipher == WLAN_CIPHER_SUITE_GCMP)) { 2851 key->cipher == WLAN_CIPHER_SUITE_GCMP ||
2852 key->cipher == WLAN_CIPHER_SUITE_GCMP_256)) {
2840 mvmsta = iwl_mvm_sta_from_mac80211(sta); 2853 mvmsta = iwl_mvm_sta_from_mac80211(sta);
2841 ptk_pn = rcu_dereference_protected( 2854 ptk_pn = rcu_dereference_protected(
2842 mvmsta->ptk_pn[keyidx], 2855 mvmsta->ptk_pn[keyidx],
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 6092af23969f..e240f198e001 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -707,6 +707,7 @@ enum iwl_mvm_queue_status {
707}; 707};
708 708
709#define IWL_MVM_DQA_QUEUE_TIMEOUT (5 * HZ) 709#define IWL_MVM_DQA_QUEUE_TIMEOUT (5 * HZ)
710#define IWL_MVM_NUM_CIPHERS 8
710 711
711struct iwl_mvm { 712struct iwl_mvm {
712 /* for logger access */ 713 /* for logger access */
@@ -1015,7 +1016,7 @@ struct iwl_mvm {
1015 1016
1016 struct iwl_mvm_shared_mem_cfg shared_mem_cfg; 1017 struct iwl_mvm_shared_mem_cfg shared_mem_cfg;
1017 1018
1018 u32 ciphers[6]; 1019 u32 ciphers[IWL_MVM_NUM_CIPHERS];
1019 struct iwl_mvm_tof_data tof_data; 1020 struct iwl_mvm_tof_data tof_data;
1020 1021
1021 struct ieee80211_vif *nan_vif; 1022 struct ieee80211_vif *nan_vif;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index cf0681765ec4..7321bb6b8d67 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2243,6 +2243,13 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
2243 key_flags |= cpu_to_le16(STA_KEY_FLG_WEP); 2243 key_flags |= cpu_to_le16(STA_KEY_FLG_WEP);
2244 memcpy(cmd.key + 3, keyconf->key, keyconf->keylen); 2244 memcpy(cmd.key + 3, keyconf->key, keyconf->keylen);
2245 break; 2245 break;
2246 case WLAN_CIPHER_SUITE_GCMP_256:
2247 key_flags |= cpu_to_le16(STA_KEY_FLG_KEY_32BYTES);
2248 /* fall through */
2249 case WLAN_CIPHER_SUITE_GCMP:
2250 key_flags |= cpu_to_le16(STA_KEY_FLG_GCMP);
2251 memcpy(cmd.key, keyconf->key, keyconf->keylen);
2252 break;
2246 default: 2253 default:
2247 key_flags |= cpu_to_le16(STA_KEY_FLG_EXT); 2254 key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
2248 memcpy(cmd.key, keyconf->key, keyconf->keylen); 2255 memcpy(cmd.key, keyconf->key, keyconf->keylen);
@@ -2363,6 +2370,8 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
2363 case WLAN_CIPHER_SUITE_CCMP: 2370 case WLAN_CIPHER_SUITE_CCMP:
2364 case WLAN_CIPHER_SUITE_WEP40: 2371 case WLAN_CIPHER_SUITE_WEP40:
2365 case WLAN_CIPHER_SUITE_WEP104: 2372 case WLAN_CIPHER_SUITE_WEP104:
2373 case WLAN_CIPHER_SUITE_GCMP:
2374 case WLAN_CIPHER_SUITE_GCMP_256:
2366 ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast, 2375 ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
2367 0, NULL, 0, key_offset); 2376 0, NULL, 0, key_offset);
2368 break; 2377 break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 1f23ceeb2350..2373142b0f43 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -388,6 +388,23 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
388 tx_cmd->rate_n_flags = cpu_to_le32((u32)rate_plcp | rate_flags); 388 tx_cmd->rate_n_flags = cpu_to_le32((u32)rate_plcp | rate_flags);
389} 389}
390 390
391static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
392 u8 *crypto_hdr)
393{
394 struct ieee80211_key_conf *keyconf = info->control.hw_key;
395 u64 pn;
396
397 pn = atomic64_inc_return(&keyconf->tx_pn);
398 crypto_hdr[0] = pn;
399 crypto_hdr[2] = 0;
400 crypto_hdr[3] = 0x20 | (keyconf->keyidx << 6);
401 crypto_hdr[1] = pn >> 8;
402 crypto_hdr[4] = pn >> 16;
403 crypto_hdr[5] = pn >> 24;
404 crypto_hdr[6] = pn >> 32;
405 crypto_hdr[7] = pn >> 40;
406}
407
391/* 408/*
392 * Sets the fields in the Tx cmd that are crypto related 409 * Sets the fields in the Tx cmd that are crypto related
393 */ 410 */
@@ -405,15 +422,7 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
405 case WLAN_CIPHER_SUITE_CCMP: 422 case WLAN_CIPHER_SUITE_CCMP:
406 case WLAN_CIPHER_SUITE_CCMP_256: 423 case WLAN_CIPHER_SUITE_CCMP_256:
407 iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd); 424 iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd);
408 pn = atomic64_inc_return(&keyconf->tx_pn); 425 iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
409 crypto_hdr[0] = pn;
410 crypto_hdr[2] = 0;
411 crypto_hdr[3] = 0x20 | (keyconf->keyidx << 6);
412 crypto_hdr[1] = pn >> 8;
413 crypto_hdr[4] = pn >> 16;
414 crypto_hdr[5] = pn >> 24;
415 crypto_hdr[6] = pn >> 32;
416 crypto_hdr[7] = pn >> 40;
417 break; 426 break;
418 427
419 case WLAN_CIPHER_SUITE_TKIP: 428 case WLAN_CIPHER_SUITE_TKIP:
@@ -433,6 +442,18 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
433 442
434 memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); 443 memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
435 break; 444 break;
445 case WLAN_CIPHER_SUITE_GCMP:
446 case WLAN_CIPHER_SUITE_GCMP_256:
447 /* TODO: Taking the key from the table might introduce a race
448 * when PTK rekeying is done, having an old packets with a PN
449 * based on the old key but the message encrypted with a new
450 * one.
451 * Need to handle this.
452 */
453 tx_cmd->sec_ctl |= TX_CMD_SEC_GCMP | TC_CMD_SEC_KEY_FROM_TABLE;
454 tx_cmd->key[0] = keyconf->hw_key_idx;
455 iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
456 break;
436 default: 457 default:
437 tx_cmd->sec_ctl |= TX_CMD_SEC_EXT; 458 tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
438 } 459 }