LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath - key.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 16 291 5.5 %
Date: 2022-03-28 13:20:08 Functions: 1 8 12.5 %
Branches: 4 200 2.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009 Atheros Communications Inc.
       3                 :            :  * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
       4                 :            :  *
       5                 :            :  * Permission to use, copy, modify, and/or distribute this software for any
       6                 :            :  * purpose with or without fee is hereby granted, provided that the above
       7                 :            :  * copyright notice and this permission notice appear in all copies.
       8                 :            :  *
       9                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10                 :            :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11                 :            :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12                 :            :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13                 :            :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14                 :            :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15                 :            :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include <linux/export.h>
      19                 :            : #include <asm/unaligned.h>
      20                 :            : #include <net/mac80211.h>
      21                 :            : 
      22                 :            : #include "ath.h"
      23                 :            : #include "reg.h"
      24                 :            : 
      25                 :            : #define REG_READ                        (common->ops->read)
      26                 :            : #define REG_WRITE(_ah, _reg, _val)      (common->ops->write)(_ah, _val, _reg)
      27                 :            : #define ENABLE_REGWRITE_BUFFER(_ah)                     \
      28                 :            :         if (common->ops->enable_write_buffer)             \
      29                 :            :                 common->ops->enable_write_buffer((_ah));
      30                 :            : 
      31                 :            : #define REGWRITE_BUFFER_FLUSH(_ah)                      \
      32                 :            :         if (common->ops->write_flush)                     \
      33                 :            :                 common->ops->write_flush((_ah));
      34                 :            : 
      35                 :            : 
      36                 :            : #define IEEE80211_WEP_NKID      4       /* number of key ids */
      37                 :            : 
      38                 :            : /************************/
      39                 :            : /* Key Cache Management */
      40                 :            : /************************/
      41                 :            : 
      42                 :       1536 : bool ath_hw_keyreset(struct ath_common *common, u16 entry)
      43                 :            : {
      44                 :       1536 :         u32 keyType;
      45                 :       1536 :         void *ah = common->ah;
      46                 :            : 
      47         [ -  + ]:       1536 :         if (entry >= common->keymax) {
      48                 :          0 :                 ath_err(common, "keyreset: keycache entry %u out of range\n",
      49                 :            :                         entry);
      50                 :          0 :                 return false;
      51                 :            :         }
      52                 :            : 
      53                 :       1536 :         keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
      54                 :            : 
      55         [ -  + ]:       1536 :         ENABLE_REGWRITE_BUFFER(ah);
      56                 :            : 
      57                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
      58                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
      59                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
      60                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
      61                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
      62                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
      63                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
      64                 :       1536 :         REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
      65                 :            : 
      66         [ -  + ]:       1536 :         if (keyType == AR_KEYTABLE_TYPE_TKIP) {
      67                 :          0 :                 u16 micentry = entry + 64;
      68                 :            : 
      69                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
      70                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
      71                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
      72                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
      73         [ #  # ]:          0 :                 if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
      74                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
      75                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
      76                 :            :                                   AR_KEYTABLE_TYPE_CLR);
      77                 :            :                 }
      78                 :            : 
      79                 :            :         }
      80                 :            : 
      81         [ -  + ]:       1536 :         REGWRITE_BUFFER_FLUSH(ah);
      82                 :            : 
      83                 :            :         return true;
      84                 :            : }
      85                 :            : EXPORT_SYMBOL(ath_hw_keyreset);
      86                 :            : 
      87                 :          0 : static bool ath_hw_keysetmac(struct ath_common *common,
      88                 :            :                              u16 entry, const u8 *mac)
      89                 :            : {
      90                 :          0 :         u32 macHi, macLo;
      91                 :          0 :         u32 unicast_flag = AR_KEYTABLE_VALID;
      92                 :          0 :         void *ah = common->ah;
      93                 :            : 
      94         [ #  # ]:          0 :         if (entry >= common->keymax) {
      95                 :          0 :                 ath_err(common, "keysetmac: keycache entry %u out of range\n",
      96                 :            :                         entry);
      97                 :          0 :                 return false;
      98                 :            :         }
      99                 :            : 
     100         [ #  # ]:          0 :         if (mac != NULL) {
     101                 :            :                 /*
     102                 :            :                  * AR_KEYTABLE_VALID indicates that the address is a unicast
     103                 :            :                  * address, which must match the transmitter address for
     104                 :            :                  * decrypting frames.
     105                 :            :                  * Not setting this bit allows the hardware to use the key
     106                 :            :                  * for multicast frame decryption.
     107                 :            :                  */
     108         [ #  # ]:          0 :                 if (mac[0] & 0x01)
     109                 :          0 :                         unicast_flag = 0;
     110                 :            : 
     111                 :          0 :                 macLo = get_unaligned_le32(mac);
     112                 :          0 :                 macHi = get_unaligned_le16(mac + 4);
     113                 :          0 :                 macLo >>= 1;
     114                 :          0 :                 macLo |= (macHi & 1) << 31;
     115                 :          0 :                 macHi >>= 1;
     116                 :            :         } else {
     117                 :            :                 macLo = macHi = 0;
     118                 :            :         }
     119         [ #  # ]:          0 :         ENABLE_REGWRITE_BUFFER(ah);
     120                 :            : 
     121                 :          0 :         REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
     122                 :          0 :         REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
     123                 :            : 
     124         [ #  # ]:          0 :         REGWRITE_BUFFER_FLUSH(ah);
     125                 :            : 
     126                 :            :         return true;
     127                 :            : }
     128                 :            : 
     129                 :          0 : static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
     130                 :            :                                       const struct ath_keyval *k,
     131                 :            :                                       const u8 *mac)
     132                 :            : {
     133                 :          0 :         void *ah = common->ah;
     134                 :          0 :         u32 key0, key1, key2, key3, key4;
     135                 :          0 :         u32 keyType;
     136                 :            : 
     137         [ #  # ]:          0 :         if (entry >= common->keymax) {
     138                 :          0 :                 ath_err(common, "set-entry: keycache entry %u out of range\n",
     139                 :            :                         entry);
     140                 :          0 :                 return false;
     141                 :            :         }
     142                 :            : 
     143   [ #  #  #  #  :          0 :         switch (k->kv_type) {
                   #  # ]
     144                 :            :         case ATH_CIPHER_AES_OCB:
     145                 :            :                 keyType = AR_KEYTABLE_TYPE_AES;
     146                 :            :                 break;
     147                 :          0 :         case ATH_CIPHER_AES_CCM:
     148         [ #  # ]:          0 :                 if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
     149         [ #  # ]:          0 :                         ath_dbg(common, ANY,
     150                 :            :                                 "AES-CCM not supported by this mac rev\n");
     151                 :          0 :                         return false;
     152                 :            :                 }
     153                 :            :                 keyType = AR_KEYTABLE_TYPE_CCM;
     154                 :            :                 break;
     155                 :          0 :         case ATH_CIPHER_TKIP:
     156                 :          0 :                 keyType = AR_KEYTABLE_TYPE_TKIP;
     157         [ #  # ]:          0 :                 if (entry + 64 >= common->keymax) {
     158         [ #  # ]:          0 :                         ath_dbg(common, ANY,
     159                 :            :                                 "entry %u inappropriate for TKIP\n", entry);
     160                 :          0 :                         return false;
     161                 :            :                 }
     162                 :            :                 break;
     163                 :          0 :         case ATH_CIPHER_WEP:
     164         [ #  # ]:          0 :                 if (k->kv_len < WLAN_KEY_LEN_WEP40) {
     165         [ #  # ]:          0 :                         ath_dbg(common, ANY, "WEP key length %u too small\n",
     166                 :            :                                 k->kv_len);
     167                 :          0 :                         return false;
     168                 :            :                 }
     169         [ #  # ]:          0 :                 if (k->kv_len <= WLAN_KEY_LEN_WEP40)
     170                 :            :                         keyType = AR_KEYTABLE_TYPE_40;
     171         [ #  # ]:          0 :                 else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
     172                 :            :                         keyType = AR_KEYTABLE_TYPE_104;
     173                 :            :                 else
     174                 :          0 :                         keyType = AR_KEYTABLE_TYPE_128;
     175                 :            :                 break;
     176                 :          0 :         case ATH_CIPHER_CLR:
     177                 :          0 :                 keyType = AR_KEYTABLE_TYPE_CLR;
     178                 :          0 :                 break;
     179                 :          0 :         default:
     180                 :          0 :                 ath_err(common, "cipher %u not supported\n", k->kv_type);
     181                 :          0 :                 return false;
     182                 :            :         }
     183                 :            : 
     184         [ #  # ]:          0 :         key0 = get_unaligned_le32(k->kv_val + 0);
     185         [ #  # ]:          0 :         key1 = get_unaligned_le16(k->kv_val + 4);
     186                 :          0 :         key2 = get_unaligned_le32(k->kv_val + 6);
     187                 :          0 :         key3 = get_unaligned_le16(k->kv_val + 10);
     188                 :          0 :         key4 = get_unaligned_le32(k->kv_val + 12);
     189         [ #  # ]:          0 :         if (k->kv_len <= WLAN_KEY_LEN_WEP104)
     190                 :          0 :                 key4 &= 0xff;
     191                 :            : 
     192                 :            :         /*
     193                 :            :          * Note: Key cache registers access special memory area that requires
     194                 :            :          * two 32-bit writes to actually update the values in the internal
     195                 :            :          * memory. Consequently, the exact order and pairs used here must be
     196                 :            :          * maintained.
     197                 :            :          */
     198                 :            : 
     199         [ #  # ]:          0 :         if (keyType == AR_KEYTABLE_TYPE_TKIP) {
     200                 :          0 :                 u16 micentry = entry + 64;
     201                 :            : 
     202                 :            :                 /*
     203                 :            :                  * Write inverted key[47:0] first to avoid Michael MIC errors
     204                 :            :                  * on frames that could be sent or received at the same time.
     205                 :            :                  * The correct key will be written in the end once everything
     206                 :            :                  * else is ready.
     207                 :            :                  */
     208                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
     209                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
     210                 :            : 
     211                 :            :                 /* Write key[95:48] */
     212                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
     213                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
     214                 :            : 
     215                 :            :                 /* Write key[127:96] and key type */
     216                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
     217                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
     218                 :            : 
     219                 :            :                 /* Write MAC address for the entry */
     220                 :          0 :                 (void) ath_hw_keysetmac(common, entry, mac);
     221                 :            : 
     222         [ #  # ]:          0 :                 if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
     223                 :            :                         /*
     224                 :            :                          * TKIP uses two key cache entries:
     225                 :            :                          * Michael MIC TX/RX keys in the same key cache entry
     226                 :            :                          * (idx = main index + 64):
     227                 :            :                          * key0 [31:0] = RX key [31:0]
     228                 :            :                          * key1 [15:0] = TX key [31:16]
     229                 :            :                          * key1 [31:16] = reserved
     230                 :            :                          * key2 [31:0] = RX key [63:32]
     231                 :            :                          * key3 [15:0] = TX key [15:0]
     232                 :            :                          * key3 [31:16] = reserved
     233                 :            :                          * key4 [31:0] = TX key [63:32]
     234                 :            :                          */
     235                 :          0 :                         u32 mic0, mic1, mic2, mic3, mic4;
     236                 :            : 
     237         [ #  # ]:          0 :                         mic0 = get_unaligned_le32(k->kv_mic + 0);
     238                 :          0 :                         mic2 = get_unaligned_le32(k->kv_mic + 4);
     239         [ #  # ]:          0 :                         mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
     240                 :          0 :                         mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
     241                 :          0 :                         mic4 = get_unaligned_le32(k->kv_txmic + 4);
     242                 :            : 
     243         [ #  # ]:          0 :                         ENABLE_REGWRITE_BUFFER(ah);
     244                 :            : 
     245                 :            :                         /* Write RX[31:0] and TX[31:16] */
     246                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
     247                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
     248                 :            : 
     249                 :            :                         /* Write RX[63:32] and TX[15:0] */
     250                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
     251                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
     252                 :            : 
     253                 :            :                         /* Write TX[63:32] and keyType(reserved) */
     254                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
     255                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
     256                 :            :                                   AR_KEYTABLE_TYPE_CLR);
     257                 :            : 
     258         [ #  # ]:          0 :                         REGWRITE_BUFFER_FLUSH(ah);
     259                 :            : 
     260                 :            :                 } else {
     261                 :            :                         /*
     262                 :            :                          * TKIP uses four key cache entries (two for group
     263                 :            :                          * keys):
     264                 :            :                          * Michael MIC TX/RX keys are in different key cache
     265                 :            :                          * entries (idx = main index + 64 for TX and
     266                 :            :                          * main index + 32 + 96 for RX):
     267                 :            :                          * key0 [31:0] = TX/RX MIC key [31:0]
     268                 :            :                          * key1 [31:0] = reserved
     269                 :            :                          * key2 [31:0] = TX/RX MIC key [63:32]
     270                 :            :                          * key3 [31:0] = reserved
     271                 :            :                          * key4 [31:0] = reserved
     272                 :            :                          *
     273                 :            :                          * Upper layer code will call this function separately
     274                 :            :                          * for TX and RX keys when these registers offsets are
     275                 :            :                          * used.
     276                 :            :                          */
     277                 :          0 :                         u32 mic0, mic2;
     278                 :            : 
     279         [ #  # ]:          0 :                         mic0 = get_unaligned_le32(k->kv_mic + 0);
     280                 :          0 :                         mic2 = get_unaligned_le32(k->kv_mic + 4);
     281                 :            : 
     282         [ #  # ]:          0 :                         ENABLE_REGWRITE_BUFFER(ah);
     283                 :            : 
     284                 :            :                         /* Write MIC key[31:0] */
     285                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
     286                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
     287                 :            : 
     288                 :            :                         /* Write MIC key[63:32] */
     289                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
     290                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
     291                 :            : 
     292                 :            :                         /* Write TX[63:32] and keyType(reserved) */
     293                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
     294                 :          0 :                         REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
     295                 :            :                                   AR_KEYTABLE_TYPE_CLR);
     296                 :            : 
     297         [ #  # ]:          0 :                         REGWRITE_BUFFER_FLUSH(ah);
     298                 :            :                 }
     299                 :            : 
     300         [ #  # ]:          0 :                 ENABLE_REGWRITE_BUFFER(ah);
     301                 :            : 
     302                 :            :                 /* MAC address registers are reserved for the MIC entry */
     303                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
     304                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
     305                 :            : 
     306                 :            :                 /*
     307                 :            :                  * Write the correct (un-inverted) key[47:0] last to enable
     308                 :            :                  * TKIP now that all other registers are set with correct
     309                 :            :                  * values.
     310                 :            :                  */
     311                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
     312                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
     313                 :            : 
     314         [ #  # ]:          0 :                 REGWRITE_BUFFER_FLUSH(ah);
     315                 :            :         } else {
     316         [ #  # ]:          0 :                 ENABLE_REGWRITE_BUFFER(ah);
     317                 :            : 
     318                 :            :                 /* Write key[47:0] */
     319                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
     320                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
     321                 :            : 
     322                 :            :                 /* Write key[95:48] */
     323                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
     324                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
     325                 :            : 
     326                 :            :                 /* Write key[127:96] and key type */
     327                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
     328                 :          0 :                 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
     329                 :            : 
     330         [ #  # ]:          0 :                 REGWRITE_BUFFER_FLUSH(ah);
     331                 :            : 
     332                 :            :                 /* Write MAC address for the entry */
     333                 :          0 :                 (void) ath_hw_keysetmac(common, entry, mac);
     334                 :            :         }
     335                 :            : 
     336                 :            :         return true;
     337                 :            : }
     338                 :            : 
     339                 :          0 : static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
     340                 :            :                            struct ath_keyval *hk, const u8 *addr,
     341                 :            :                            bool authenticator)
     342                 :            : {
     343                 :          0 :         const u8 *key_rxmic;
     344                 :          0 :         const u8 *key_txmic;
     345                 :            : 
     346                 :          0 :         key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
     347                 :          0 :         key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
     348                 :            : 
     349         [ #  # ]:          0 :         if (addr == NULL) {
     350                 :            :                 /*
     351                 :            :                  * Group key installation - only two key cache entries are used
     352                 :            :                  * regardless of splitmic capability since group key is only
     353                 :            :                  * used either for TX or RX.
     354                 :            :                  */
     355         [ #  # ]:          0 :                 if (authenticator) {
     356                 :          0 :                         memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
     357                 :          0 :                         memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
     358                 :            :                 } else {
     359                 :          0 :                         memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
     360                 :          0 :                         memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
     361                 :            :                 }
     362                 :          0 :                 return ath_hw_set_keycache_entry(common, keyix, hk, addr);
     363                 :            :         }
     364         [ #  # ]:          0 :         if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
     365                 :            :                 /* TX and RX keys share the same key cache entry. */
     366                 :          0 :                 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
     367                 :          0 :                 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
     368                 :          0 :                 return ath_hw_set_keycache_entry(common, keyix, hk, addr);
     369                 :            :         }
     370                 :            : 
     371                 :            :         /* Separate key cache entries for TX and RX */
     372                 :            : 
     373                 :            :         /* TX key goes at first index, RX key at +32. */
     374                 :          0 :         memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
     375         [ #  # ]:          0 :         if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
     376                 :            :                 /* TX MIC entry failed. No need to proceed further */
     377                 :          0 :                 ath_err(common, "Setting TX MIC Key Failed\n");
     378                 :          0 :                 return 0;
     379                 :            :         }
     380                 :            : 
     381                 :          0 :         memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
     382                 :            :         /* XXX delete tx key on failure? */
     383                 :          0 :         return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
     384                 :            : }
     385                 :            : 
     386                 :          0 : static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
     387                 :            : {
     388                 :          0 :         int i;
     389                 :            : 
     390         [ #  # ]:          0 :         for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
     391   [ #  #  #  # ]:          0 :                 if (test_bit(i, common->keymap) ||
     392                 :          0 :                     test_bit(i + 64, common->keymap))
     393                 :          0 :                         continue; /* At least one part of TKIP key allocated */
     394   [ #  #  #  # ]:          0 :                 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
     395         [ #  # ]:          0 :                     (test_bit(i + 32, common->keymap) ||
     396                 :          0 :                      test_bit(i + 64 + 32, common->keymap)))
     397                 :          0 :                         continue; /* At least one part of TKIP key allocated */
     398                 :            : 
     399                 :            :                 /* Found a free slot for a TKIP key */
     400                 :            :                 return i;
     401                 :            :         }
     402                 :            :         return -1;
     403                 :            : }
     404                 :            : 
     405                 :          0 : static int ath_reserve_key_cache_slot(struct ath_common *common,
     406                 :            :                                       u32 cipher)
     407                 :            : {
     408                 :          0 :         int i;
     409                 :            : 
     410         [ #  # ]:          0 :         if (cipher == WLAN_CIPHER_SUITE_TKIP)
     411                 :          0 :                 return ath_reserve_key_cache_slot_tkip(common);
     412                 :            : 
     413                 :            :         /* First, try to find slots that would not be available for TKIP. */
     414         [ #  # ]:          0 :         if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
     415         [ #  # ]:          0 :                 for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
     416   [ #  #  #  # ]:          0 :                         if (!test_bit(i, common->keymap) &&
     417         [ #  # ]:          0 :                             (test_bit(i + 32, common->keymap) ||
     418         [ #  # ]:          0 :                              test_bit(i + 64, common->keymap) ||
     419                 :          0 :                              test_bit(i + 64 + 32, common->keymap)))
     420                 :          0 :                                 return i;
     421   [ #  #  #  # ]:          0 :                         if (!test_bit(i + 32, common->keymap) &&
     422         [ #  # ]:          0 :                             (test_bit(i, common->keymap) ||
     423         [ #  # ]:          0 :                              test_bit(i + 64, common->keymap) ||
     424                 :          0 :                              test_bit(i + 64 + 32, common->keymap)))
     425                 :          0 :                                 return i + 32;
     426   [ #  #  #  # ]:          0 :                         if (!test_bit(i + 64, common->keymap) &&
     427         [ #  # ]:          0 :                             (test_bit(i , common->keymap) ||
     428         [ #  # ]:          0 :                              test_bit(i + 32, common->keymap) ||
     429                 :          0 :                              test_bit(i + 64 + 32, common->keymap)))
     430                 :          0 :                                 return i + 64;
     431   [ #  #  #  # ]:          0 :                         if (!test_bit(i + 64 + 32, common->keymap) &&
     432         [ #  # ]:          0 :                             (test_bit(i, common->keymap) ||
     433         [ #  # ]:          0 :                              test_bit(i + 32, common->keymap) ||
     434                 :          0 :                              test_bit(i + 64, common->keymap)))
     435                 :          0 :                                 return i + 64 + 32;
     436                 :            :                 }
     437                 :            :         } else {
     438         [ #  # ]:          0 :                 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
     439   [ #  #  #  # ]:          0 :                         if (!test_bit(i, common->keymap) &&
     440                 :          0 :                             test_bit(i + 64, common->keymap))
     441                 :          0 :                                 return i;
     442   [ #  #  #  # ]:          0 :                         if (test_bit(i, common->keymap) &&
     443                 :          0 :                             !test_bit(i + 64, common->keymap))
     444                 :          0 :                                 return i + 64;
     445                 :            :                 }
     446                 :            :         }
     447                 :            : 
     448                 :            :         /* No partially used TKIP slots, pick any available slot */
     449         [ #  # ]:          0 :         for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
     450                 :            :                 /* Do not allow slots that could be needed for TKIP group keys
     451                 :            :                  * to be used. This limitation could be removed if we know that
     452                 :            :                  * TKIP will not be used. */
     453         [ #  # ]:          0 :                 if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
     454                 :          0 :                         continue;
     455         [ #  # ]:          0 :                 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
     456         [ #  # ]:          0 :                         if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
     457                 :          0 :                                 continue;
     458         [ #  # ]:          0 :                         if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
     459                 :          0 :                                 continue;
     460                 :            :                 }
     461                 :            : 
     462         [ #  # ]:          0 :                 if (!test_bit(i, common->keymap))
     463                 :          0 :                         return i; /* Found a free slot for a key */
     464                 :            :         }
     465                 :            : 
     466                 :            :         /* No free slot found */
     467                 :            :         return -1;
     468                 :            : }
     469                 :            : 
     470                 :            : /*
     471                 :            :  * Configure encryption in the HW.
     472                 :            :  */
     473                 :          0 : int ath_key_config(struct ath_common *common,
     474                 :            :                           struct ieee80211_vif *vif,
     475                 :            :                           struct ieee80211_sta *sta,
     476                 :            :                           struct ieee80211_key_conf *key)
     477                 :            : {
     478                 :          0 :         struct ath_keyval hk;
     479                 :          0 :         const u8 *mac = NULL;
     480                 :          0 :         u8 gmac[ETH_ALEN];
     481                 :          0 :         int ret = 0;
     482                 :          0 :         int idx;
     483                 :            : 
     484                 :          0 :         memset(&hk, 0, sizeof(hk));
     485                 :            : 
     486   [ #  #  #  #  :          0 :         switch (key->cipher) {
                      # ]
     487                 :          0 :         case 0:
     488                 :          0 :                 hk.kv_type = ATH_CIPHER_CLR;
     489                 :          0 :                 break;
     490                 :          0 :         case WLAN_CIPHER_SUITE_WEP40:
     491                 :            :         case WLAN_CIPHER_SUITE_WEP104:
     492                 :          0 :                 hk.kv_type = ATH_CIPHER_WEP;
     493                 :          0 :                 break;
     494                 :          0 :         case WLAN_CIPHER_SUITE_TKIP:
     495                 :          0 :                 hk.kv_type = ATH_CIPHER_TKIP;
     496                 :          0 :                 break;
     497                 :          0 :         case WLAN_CIPHER_SUITE_CCMP:
     498                 :          0 :                 hk.kv_type = ATH_CIPHER_AES_CCM;
     499                 :          0 :                 break;
     500                 :            :         default:
     501                 :            :                 return -EOPNOTSUPP;
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         hk.kv_len = key->keylen;
     505         [ #  # ]:          0 :         if (key->keylen)
     506                 :          0 :                 memcpy(hk.kv_val, key->key, key->keylen);
     507                 :            : 
     508         [ #  # ]:          0 :         if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
     509      [ #  #  # ]:          0 :                 switch (vif->type) {
     510                 :          0 :                 case NL80211_IFTYPE_AP:
     511                 :          0 :                         memcpy(gmac, vif->addr, ETH_ALEN);
     512                 :          0 :                         gmac[0] |= 0x01;
     513                 :          0 :                         mac = gmac;
     514                 :          0 :                         idx = ath_reserve_key_cache_slot(common, key->cipher);
     515                 :          0 :                         break;
     516                 :          0 :                 case NL80211_IFTYPE_ADHOC:
     517         [ #  # ]:          0 :                         if (!sta) {
     518                 :          0 :                                 idx = key->keyidx;
     519                 :          0 :                                 break;
     520                 :            :                         }
     521                 :          0 :                         memcpy(gmac, sta->addr, ETH_ALEN);
     522                 :          0 :                         gmac[0] |= 0x01;
     523                 :          0 :                         mac = gmac;
     524                 :          0 :                         idx = ath_reserve_key_cache_slot(common, key->cipher);
     525                 :          0 :                         break;
     526                 :          0 :                 default:
     527                 :          0 :                         idx = key->keyidx;
     528                 :          0 :                         break;
     529                 :            :                 }
     530         [ #  # ]:          0 :         } else if (key->keyidx) {
     531   [ #  #  #  # ]:          0 :                 if (WARN_ON(!sta))
     532                 :            :                         return -EOPNOTSUPP;
     533                 :          0 :                 mac = sta->addr;
     534                 :            : 
     535         [ #  # ]:          0 :                 if (vif->type != NL80211_IFTYPE_AP) {
     536                 :            :                         /* Only keyidx 0 should be used with unicast key, but
     537                 :            :                          * allow this for client mode for now. */
     538                 :          0 :                         idx = key->keyidx;
     539                 :            :                 } else
     540                 :            :                         return -EIO;
     541                 :            :         } else {
     542   [ #  #  #  # ]:          0 :                 if (WARN_ON(!sta))
     543                 :            :                         return -EOPNOTSUPP;
     544                 :          0 :                 mac = sta->addr;
     545                 :            : 
     546                 :          0 :                 idx = ath_reserve_key_cache_slot(common, key->cipher);
     547                 :            :         }
     548                 :            : 
     549         [ #  # ]:          0 :         if (idx < 0)
     550                 :            :                 return -ENOSPC; /* no free key cache entries */
     551                 :            : 
     552         [ #  # ]:          0 :         if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
     553                 :          0 :                 ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
     554                 :          0 :                                       vif->type == NL80211_IFTYPE_AP);
     555                 :            :         else
     556                 :          0 :                 ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
     557                 :            : 
     558         [ #  # ]:          0 :         if (!ret)
     559                 :            :                 return -EIO;
     560                 :            : 
     561                 :          0 :         set_bit(idx, common->keymap);
     562         [ #  # ]:          0 :         if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
     563                 :          0 :                 set_bit(idx, common->ccmp_keymap);
     564                 :            : 
     565         [ #  # ]:          0 :         if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
     566                 :          0 :                 set_bit(idx + 64, common->keymap);
     567                 :          0 :                 set_bit(idx, common->tkip_keymap);
     568                 :          0 :                 set_bit(idx + 64, common->tkip_keymap);
     569         [ #  # ]:          0 :                 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
     570                 :          0 :                         set_bit(idx + 32, common->keymap);
     571                 :          0 :                         set_bit(idx + 64 + 32, common->keymap);
     572                 :          0 :                         set_bit(idx + 32, common->tkip_keymap);
     573                 :          0 :                         set_bit(idx + 64 + 32, common->tkip_keymap);
     574                 :            :                 }
     575                 :            :         }
     576                 :            : 
     577                 :            :         return idx;
     578                 :            : }
     579                 :            : EXPORT_SYMBOL(ath_key_config);
     580                 :            : 
     581                 :            : /*
     582                 :            :  * Delete Key.
     583                 :            :  */
     584                 :          0 : void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
     585                 :            : {
     586                 :          0 :         ath_hw_keyreset(common, key->hw_key_idx);
     587         [ #  # ]:          0 :         if (key->hw_key_idx < IEEE80211_WEP_NKID)
     588                 :            :                 return;
     589                 :            : 
     590                 :          0 :         clear_bit(key->hw_key_idx, common->keymap);
     591                 :          0 :         clear_bit(key->hw_key_idx, common->ccmp_keymap);
     592         [ #  # ]:          0 :         if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
     593                 :            :                 return;
     594                 :            : 
     595                 :          0 :         clear_bit(key->hw_key_idx + 64, common->keymap);
     596                 :            : 
     597                 :          0 :         clear_bit(key->hw_key_idx, common->tkip_keymap);
     598                 :          0 :         clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
     599                 :            : 
     600         [ #  # ]:          0 :         if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
     601                 :          0 :                 ath_hw_keyreset(common, key->hw_key_idx + 32);
     602                 :          0 :                 clear_bit(key->hw_key_idx + 32, common->keymap);
     603                 :          0 :                 clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
     604                 :            : 
     605                 :          0 :                 clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
     606                 :          0 :                 clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
     607                 :            :         }
     608                 :            : }
     609                 :            : EXPORT_SYMBOL(ath_key_delete);

Generated by: LCOV version 1.14