The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
    3  *
    4  * Permission to use, copy, modify, and/or distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   14  * PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include "opt_ah.h"
   18 
   19 #include "ah.h"
   20 #include "ah_internal.h"
   21 
   22 #include "ar9300/ar9300.h"
   23 #include "ar9300/ar9300reg.h"
   24 
   25 /*
   26  * Note: The key cache hardware requires that each double-word
   27  * pair be written in even/odd order (since the destination is
   28  * a 64-bit register).  Don't reorder the writes in this code
   29  * w/o considering this!
   30  */
   31 #define KEY_XOR         0xaa
   32 
   33 #define IS_MIC_ENABLED(ah) \
   34     (AH9300(ah)->ah_sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
   35 
   36 /*
   37  * This isn't the keytable type; this is actually something separate
   38  * for the TX descriptor.
   39  */
   40 static const int keyType[] = {
   41         1,      /* HAL_CIPHER_WEP */
   42         0,      /* HAL_CIPHER_AES_OCB */
   43         2,      /* HAL_CIPHER_AES_CCM */
   44         0,      /* HAL_CIPHER_CKIP */
   45         3,      /* HAL_CIPHER_TKIP */
   46         0       /* HAL_CIPHER_CLR */
   47 };
   48 
   49 /*
   50  * Return the size of the hardware key cache.
   51  */
   52 u_int32_t
   53 ar9300_get_key_cache_size(struct ath_hal *ah)
   54 {
   55     return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize;
   56 }
   57 
   58 /*
   59  * Return AH_TRUE if the specific key cache entry is valid.
   60  */
   61 HAL_BOOL
   62 ar9300_is_key_cache_entry_valid(struct ath_hal *ah, u_int16_t entry)
   63 {
   64     if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
   65         u_int32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
   66         if (val & AR_KEYTABLE_VALID) {
   67             return AH_TRUE;
   68         }
   69     }
   70     return AH_FALSE;
   71 }
   72 
   73 /*
   74  * Clear the specified key cache entry and any associated MIC entry.
   75  */
   76 HAL_BOOL
   77 ar9300_reset_key_cache_entry(struct ath_hal *ah, u_int16_t entry)
   78 {
   79     u_int32_t key_type;
   80     struct ath_hal_9300 *ahp = AH9300(ah);
   81 
   82     if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
   83         HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
   84             "%s: entry %u out of range\n", __func__, entry);
   85         return AH_FALSE;
   86     }
   87 
   88     ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR];
   89 
   90     key_type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));
   91 
   92     /* XXX why not clear key type/valid bit first? */
   93     OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
   94     OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
   95     OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
   96     OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
   97     OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
   98     OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
   99     OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
  100     OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
  101     if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
  102         u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
  103 
  104         HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize);
  105         OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
  106         OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
  107         OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
  108         OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
  109         /* NB: key type and MAC are known to be ok */
  110     }
  111 
  112     if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
  113         return AH_TRUE;
  114     }
  115 
  116     if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL)
  117         == HAL_OK) {
  118         if (key_type == AR_KEYTABLE_TYPE_TKIP    ||
  119             key_type == AR_KEYTABLE_TYPE_40      ||
  120             key_type == AR_KEYTABLE_TYPE_104     ||
  121             key_type == AR_KEYTABLE_TYPE_128) {
  122             /* SW WAR for Bug 31602 */
  123             if (--ahp->ah_rifs_sec_cnt == 0) {
  124                 HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  125                     "%s: Count = %d, enabling RIFS\n",
  126                     __func__, ahp->ah_rifs_sec_cnt);
  127                 ar9300_set_rifs_delay(ah, AH_TRUE);
  128             }
  129         }
  130     }
  131     return AH_TRUE;
  132 }
  133 
  134 /*
  135  * Sets the mac part of the specified key cache entry (and any
  136  * associated MIC entry) and mark them valid.
  137  */
  138 HAL_BOOL
  139 ar9300_set_key_cache_entry_mac(
  140     struct ath_hal *ah,
  141     u_int16_t entry,
  142     const u_int8_t *mac)
  143 {
  144     u_int32_t mac_hi, mac_lo;
  145     u_int32_t unicast_addr = AR_KEYTABLE_VALID;
  146 
  147     if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
  148         HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  149             "%s: entry %u out of range\n", __func__, entry);
  150         return AH_FALSE;
  151     }
  152     /*
  153      * Set MAC address -- shifted right by 1.  mac_lo is
  154      * the 4 MSBs, and mac_hi is the 2 LSBs.
  155      */
  156     if (mac != AH_NULL) {
  157         /*
  158          *  If upper layers have requested mcast MACaddr lookup, then
  159          *  signify this to the hw by setting the (poorly named) valid_bit
  160          *  to 0.  Yes, really 0. The hardware specs, pcu_registers.txt, is
  161          *  has incorrectly named valid_bit. It should be called "Unicast".
  162          *  When the Key Cache entry is to decrypt Unicast frames, this bit
  163          *  should be '1'; for multicast and broadcast frames, this bit is ''.
  164          */
  165         if (mac[0] & 0x01) {
  166             unicast_addr = 0;    /* Not an unicast address */
  167         }
  168 
  169         mac_hi = (mac[5] << 8)  |  mac[4];
  170         mac_lo = (mac[3] << 24) | (mac[2] << 16)
  171               | (mac[1] << 8)  |  mac[0];
  172         mac_lo >>= 1; /* Note that the bit 0 is shifted out. This bit is used to
  173                       * indicate that this is a multicast key cache. */
  174         mac_lo |= (mac_hi & 1) << 31; /* carry */
  175         mac_hi >>= 1;
  176     } else {
  177         mac_lo = mac_hi = 0;
  178     }
  179     OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), mac_lo);
  180     OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), mac_hi | unicast_addr);
  181     return AH_TRUE;
  182 }
  183 
  184 /*
  185  * Sets the contents of the specified key cache entry
  186  * and any associated MIC entry.
  187  */
  188 HAL_BOOL
  189 ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
  190                        const HAL_KEYVAL *k, const u_int8_t *mac,
  191                        int xor_key)
  192 {
  193     const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
  194     u_int32_t key0, key1, key2, key3, key4;
  195     u_int32_t key_type;
  196     u_int32_t xor_mask = xor_key ?
  197         (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
  198     struct ath_hal_9300 *ahp = AH9300(ah);
  199     u_int32_t pwrmgt, pwrmgt_mic, uapsd_cfg, psta = 0;
  200     int is_proxysta_key = k->kv_type & HAL_KEY_PROXY_STA_MASK;
  201 
  202 
  203     if (entry >= p_cap->halKeyCacheSize) {
  204         HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  205             "%s: entry %u out of range\n", __func__, entry);
  206         return AH_FALSE;
  207     }
  208     HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n",
  209         __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
  210         is_proxysta_key);
  211         
  212     switch (k->kv_type & AH_KEYTYPE_MASK) {
  213     case HAL_CIPHER_AES_OCB:
  214         key_type = AR_KEYTABLE_TYPE_AES;
  215         break;
  216     case HAL_CIPHER_AES_CCM:
  217         if (!p_cap->halCipherAesCcmSupport) {
  218             HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
  219                 "mac rev 0x%x\n",
  220                 __func__, AH_PRIVATE(ah)->ah_macRev);
  221             return AH_FALSE;
  222         }
  223         key_type = AR_KEYTABLE_TYPE_CCM;
  224         break;
  225     case HAL_CIPHER_TKIP:
  226         key_type = AR_KEYTABLE_TYPE_TKIP;
  227         if (IS_MIC_ENABLED(ah) && entry + 64 >= p_cap->halKeyCacheSize) {
  228             HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  229                 "%s: entry %u inappropriate for TKIP\n",
  230                 __func__, entry);
  231             return AH_FALSE;
  232         }
  233         break;
  234     case HAL_CIPHER_WEP:
  235         if (k->kv_len < 40 / NBBY) {
  236             HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
  237                 __func__, k->kv_len);
  238             return AH_FALSE;
  239         }
  240         if (k->kv_len <= 40 / NBBY) {
  241             key_type = AR_KEYTABLE_TYPE_40;
  242         } else if (k->kv_len <= 104 / NBBY) {
  243             key_type = AR_KEYTABLE_TYPE_104;
  244         } else {
  245             key_type = AR_KEYTABLE_TYPE_128;
  246         }
  247         break;
  248     case HAL_CIPHER_CLR:
  249         key_type = AR_KEYTABLE_TYPE_CLR;
  250         break;
  251     default:
  252         HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
  253             __func__, k->kv_type);
  254         return AH_FALSE;
  255     }
  256 
  257     key0 =  LE_READ_4(k->kv_val +  0) ^ xor_mask;
  258     key1 = (LE_READ_2(k->kv_val +  4) ^ xor_mask) & 0xffff;
  259     key2 =  LE_READ_4(k->kv_val +  6) ^ xor_mask;
  260     key3 = (LE_READ_2(k->kv_val + 10) ^ xor_mask) & 0xffff;
  261     key4 =  LE_READ_4(k->kv_val + 12) ^ xor_mask;
  262     if (k->kv_len <= 104 / NBBY) {
  263         key4 &= 0xff;
  264     }
  265 
  266     /* Extract the UAPSD AC bits and shift it appropriately */
  267     uapsd_cfg = k->kv_apsd;
  268     uapsd_cfg = (u_int32_t) SM(uapsd_cfg, AR_KEYTABLE_UAPSD);
  269 
  270     /* Need to preserve the power management bit used by MAC */
  271     pwrmgt = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEYTABLE_PWRMGT;
  272     
  273     if (is_proxysta_key) {
  274         u_int8_t bcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  275         if (!mac || OS_MEMCMP(mac, bcast_mac, 6)) {
  276             psta = AR_KEYTABLE_DIR_ACK_BIT;
  277         }
  278     }
  279     /*
  280      * Note: key cache hardware requires that each double-word
  281      * pair be written in even/odd order (since the destination is
  282      * a 64-bit register).  Don't reorder these writes w/o
  283      * considering this!
  284      */
  285     if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
  286         u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
  287 
  288         /* Need to preserve the power management bit used by MAC */
  289         pwrmgt_mic =
  290             OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEYTABLE_PWRMGT;
  291 
  292         /*
  293          * Invalidate the encrypt/decrypt key until the MIC
  294          * key is installed so pending rx frames will fail
  295          * with decrypt errors rather than a MIC error.
  296          */
  297         OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
  298         OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
  299         OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
  300         OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
  301         OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
  302         OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry),
  303             key_type | pwrmgt | uapsd_cfg | psta);
  304         ar9300_set_key_cache_entry_mac(ah, entry, mac);
  305 
  306         /*
  307          * since the AR_MISC_MODE register was written with the contents of
  308          * ah_misc_mode (if any) in ar9300_attach, just check ah_misc_mode and
  309          * save a pci read per key set.
  310          */
  311         if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
  312             u_int32_t mic0, mic1, mic2, mic3, mic4;
  313             /*
  314              * both RX and TX mic values can be combined into
  315              * one cache slot entry.
  316              * 8*N + 800         31:0    RX Michael key 0
  317              * 8*N + 804         15:0    TX Michael key 0 [31:16]
  318              * 8*N + 808         31:0    RX Michael key 1
  319              * 8*N + 80C         15:0    TX Michael key 0 [15:0]
  320              * 8*N + 810         31:0    TX Michael key 1
  321              * 8*N + 814         15:0    reserved
  322              * 8*N + 818         31:0    reserved
  323              * 8*N + 81C         14:0    reserved
  324              *                   15      key valid == 0
  325              */
  326             /* RX mic */
  327             mic0 = LE_READ_4(k->kv_mic + 0);
  328             mic2 = LE_READ_4(k->kv_mic + 4);
  329             /* TX mic */
  330             mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
  331             mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
  332             mic4 = LE_READ_4(k->kv_txmic + 4);
  333             OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
  334             OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
  335             OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
  336             OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
  337             OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
  338             OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
  339                          AR_KEYTABLE_TYPE_CLR | pwrmgt_mic | uapsd_cfg);
  340 
  341         } else {
  342             u_int32_t mic0, mic2;
  343 
  344             mic0 = LE_READ_4(k->kv_mic + 0);
  345             mic2 = LE_READ_4(k->kv_mic + 4);
  346             OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
  347             OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
  348             OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
  349             OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
  350             OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
  351             OS_REG_WRITE(ah,
  352                 AR_KEYTABLE_TYPE(micentry | pwrmgt_mic | uapsd_cfg),
  353                 AR_KEYTABLE_TYPE_CLR);
  354         }
  355         /* NB: MIC key is not marked valid and has no MAC address */
  356         OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
  357         OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
  358 
  359         /* correct intentionally corrupted key */
  360         OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
  361         OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
  362     } else {
  363         OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
  364         OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
  365         OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
  366         OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
  367         OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
  368         OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry),
  369             key_type | pwrmgt | uapsd_cfg | psta);
  370 
  371         /*
  372         ath_hal_printf(ah, "%s[%d] mac %s proxy %d\n",
  373             __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
  374             is_proxysta_key);
  375          */
  376 
  377         ar9300_set_key_cache_entry_mac(ah, entry, mac);
  378     }
  379 
  380     ahp->ah_keytype[entry] = keyType[k->kv_type];
  381     HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry=%d, k->kv_type=%d,"
  382       "keyType=%d\n", __func__, entry, k->kv_type, keyType[k->kv_type]);
  383 
  384 
  385     if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
  386         return AH_TRUE;
  387     }
  388 
  389     if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL)
  390         == HAL_OK) {
  391         if (key_type == AR_KEYTABLE_TYPE_TKIP    ||
  392             key_type == AR_KEYTABLE_TYPE_40      ||
  393             key_type == AR_KEYTABLE_TYPE_104     ||
  394             key_type == AR_KEYTABLE_TYPE_128) {
  395             /* SW WAR for Bug 31602 */
  396             ahp->ah_rifs_sec_cnt++;
  397             HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  398                 "%s: Count = %d, disabling RIFS\n",
  399                 __func__, ahp->ah_rifs_sec_cnt);
  400             ar9300_set_rifs_delay(ah, AH_FALSE);
  401         }
  402     }
  403     HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n",
  404         __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
  405         is_proxysta_key);
  406 
  407     return AH_TRUE;
  408 }
  409 
  410 /*
  411  * Enable the Keysearch for every subframe of an aggregate
  412  */
  413 void
  414 ar9300_enable_keysearch_always(struct ath_hal *ah, int enable)
  415 {
  416     u_int32_t val;
  417 
  418     if (!ah) {
  419         return;
  420     }
  421     val = OS_REG_READ(ah, AR_PCU_MISC);
  422     if (enable) {
  423         val |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
  424     } else {
  425         val &= ~AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
  426     }
  427     OS_REG_WRITE(ah, AR_PCU_MISC, val);
  428 }
  429 void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry)
  430 {
  431 #define AH_KEY_REG_SIZE 8
  432     int i;
  433 
  434     for (i = 0; i < AH_KEY_REG_SIZE; i++) {
  435         entry[i] = OS_REG_READ(ah, AR_KEYTABLE_KEY0(n) + i * 4);
  436     }
  437 #undef AH_KEY_REG_SIZE
  438 }
  439 
  440 #if ATH_SUPPORT_KEYPLUMB_WAR
  441 /*
  442  * Check the contents of the specified key cache entry
  443  * and any associated MIC entry.
  444  */
  445     HAL_BOOL
  446 ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
  447         const HAL_KEYVAL *k, int xorKey)
  448 {
  449     const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
  450     u_int32_t key0, key1, key2, key3, key4;
  451     u_int32_t keyType;
  452     u_int32_t xorMask = xorKey ?
  453         (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
  454     struct ath_hal_9300 *ahp = AH9300(ah);
  455 
  456 
  457     if (entry >= pCap->hal_key_cache_size) {
  458         HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  459                 "%s: entry %u out of range\n", __func__, entry);
  460         return AH_FALSE;
  461     }
  462     switch (k->kv_type) {
  463         case HAL_CIPHER_AES_OCB:
  464             keyType = AR_KEYTABLE_TYPE_AES;
  465             break;
  466         case HAL_CIPHER_AES_CCM:
  467             if (!pCap->hal_cipher_aes_ccm_support) {
  468                 HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
  469                         "mac rev 0x%x\n",
  470                         __func__, AH_PRIVATE(ah)->ah_macRev);
  471                 return AH_FALSE;
  472             }
  473             keyType = AR_KEYTABLE_TYPE_CCM;
  474             break;
  475         case HAL_CIPHER_TKIP:
  476             keyType = AR_KEYTABLE_TYPE_TKIP;
  477             if (IS_MIC_ENABLED(ah) && entry + 64 >= pCap->hal_key_cache_size) {
  478                 HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
  479                         "%s: entry %u inappropriate for TKIP\n",
  480                         __func__, entry);
  481                 return AH_FALSE;
  482             }
  483             break;
  484         case HAL_CIPHER_WEP:
  485             if (k->kv_len < 40 / NBBY) {
  486                 HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
  487                         __func__, k->kv_len);
  488                 return AH_FALSE;
  489             }
  490             if (k->kv_len <= 40 / NBBY) {
  491                 keyType = AR_KEYTABLE_TYPE_40;
  492             } else if (k->kv_len <= 104 / NBBY) {
  493                 keyType = AR_KEYTABLE_TYPE_104;
  494             } else {
  495                 keyType = AR_KEYTABLE_TYPE_128;
  496             }
  497             break;
  498         case HAL_CIPHER_CLR:
  499             keyType = AR_KEYTABLE_TYPE_CLR;
  500             return AH_TRUE;
  501         default:
  502             HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
  503                     __func__, k->kv_type);
  504             return AH_TRUE;
  505     }
  506 
  507     key0 =  LE_READ_4(k->kv_val +  0) ^ xorMask;
  508     key1 = (LE_READ_2(k->kv_val +  4) ^ xorMask) & 0xffff;
  509     key2 =  LE_READ_4(k->kv_val +  6) ^ xorMask;
  510     key3 = (LE_READ_2(k->kv_val + 10) ^ xorMask) & 0xffff;
  511     key4 =  LE_READ_4(k->kv_val + 12) ^ xorMask;
  512     if (k->kv_len <= 104 / NBBY) {
  513         key4 &= 0xff;
  514     }
  515 
  516     /*
  517      * Note: key cache hardware requires that each double-word
  518      * pair be written in even/odd order (since the destination is
  519      * a 64-bit register).  Don't reorder these writes w/o
  520      * considering this!
  521      */
  522     if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
  523         u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
  524 
  525 
  526         /*
  527          * Invalidate the encrypt/decrypt key until the MIC
  528          * key is installed so pending rx frames will fail
  529          * with decrypt errors rather than a MIC error.
  530          */
  531         if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) && 
  532                 (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
  533                 (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
  534                 (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
  535                 (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
  536                 ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) 
  537         {
  538 
  539             /*
  540              * since the AR_MISC_MODE register was written with the contents of
  541              * ah_miscMode (if any) in ar9300Attach, just check ah_miscMode and
  542              * save a pci read per key set.
  543              */
  544             if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
  545                 u_int32_t mic0,mic1,mic2,mic3,mic4;
  546                 /*
  547                  * both RX and TX mic values can be combined into
  548                  * one cache slot entry.
  549                  * 8*N + 800         31:0    RX Michael key 0
  550                  * 8*N + 804         15:0    TX Michael key 0 [31:16]
  551                  * 8*N + 808         31:0    RX Michael key 1
  552                  * 8*N + 80C         15:0    TX Michael key 0 [15:0]
  553                  * 8*N + 810         31:0    TX Michael key 1
  554                  * 8*N + 814         15:0    reserved
  555                  * 8*N + 818         31:0    reserved
  556                  * 8*N + 81C         14:0    reserved
  557                  *                   15      key valid == 0
  558                  */
  559                 /* RX mic */
  560                 mic0 = LE_READ_4(k->kv_mic + 0);
  561                 mic2 = LE_READ_4(k->kv_mic + 4);
  562                 /* TX mic */
  563                 mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
  564                 mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
  565                 mic4 = LE_READ_4(k->kv_txmic + 4);
  566                 if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(micentry)) == mic0) &&
  567                         (OS_REG_READ(ah, AR_KEYTABLE_KEY1(micentry)) == mic1) &&
  568                         (OS_REG_READ(ah, AR_KEYTABLE_KEY2(micentry)) == mic2) &&
  569                         (OS_REG_READ(ah, AR_KEYTABLE_KEY3(micentry)) == mic3) &&
  570                         (OS_REG_READ(ah, AR_KEYTABLE_KEY4(micentry)) == mic4) &&
  571                         ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEY_TYPE) == (AR_KEYTABLE_TYPE_CLR & AR_KEY_TYPE))) {
  572                     return AH_TRUE;
  573                 }
  574 
  575             } else {
  576                 return AH_TRUE;
  577             }
  578         }
  579     } else {
  580         if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
  581                 (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
  582                 (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
  583                 (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
  584                 (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
  585                 ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) {
  586             return AH_TRUE;
  587         }
  588     }
  589     return AH_FALSE;
  590 }
  591 #endif

Cache object: 836c755f4dfdeba4b92ef4b3b15aa2b9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.