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/net80211/ieee80211_crypto_tkip.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 /*      $NetBSD: ieee80211_crypto_tkip.c,v 1.17 2020/11/03 15:06:50 mlelstv Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * Alternatively, this software may be distributed under the terms of the
   19  * GNU General Public License ("GPL") version 2 as published by the Free
   20  * Software Foundation.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 #ifdef __FreeBSD__
   36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_tkip.c,v 1.10 2005/08/08 18:46:35 sam Exp $");
   37 #endif
   38 #ifdef __NetBSD__
   39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_tkip.c,v 1.17 2020/11/03 15:06:50 mlelstv Exp $");
   40 #endif
   41 
   42 /*
   43  * IEEE 802.11i TKIP crypto support.
   44  *
   45  * Part of this module is derived from similar code in the Host
   46  * AP driver. The code is used with the consent of the author and
   47  * its license is included below.
   48  */
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/mbuf.h>
   52 #include <sys/kmem.h>
   53 #include <sys/kernel.h>
   54 #include <sys/endian.h>
   55 
   56 #include <sys/socket.h>
   57 
   58 #include <net/if.h>
   59 #include <net/if_ether.h>
   60 #include <net/if_media.h>
   61 
   62 #include <net80211/ieee80211_var.h>
   63 
   64 static  void *tkip_attach(struct ieee80211com *, struct ieee80211_key *);
   65 static  void tkip_detach(struct ieee80211_key *);
   66 static  int tkip_setkey(struct ieee80211_key *);
   67 static  int tkip_encap(struct ieee80211_key *, struct mbuf *m, u_int8_t keyid);
   68 static  int tkip_enmic(struct ieee80211_key *, struct mbuf *, int);
   69 static  int tkip_decap(struct ieee80211_key *, struct mbuf *, int);
   70 static  int tkip_demic(struct ieee80211_key *, struct mbuf *, int);
   71 
   72 const struct ieee80211_cipher ieee80211_cipher_tkip  = {
   73         .ic_name        = "TKIP",
   74         .ic_cipher      = IEEE80211_CIPHER_TKIP,
   75         .ic_header      = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
   76                           IEEE80211_WEP_EXTIVLEN,
   77         .ic_trailer     = IEEE80211_WEP_CRCLEN,
   78         .ic_miclen      = IEEE80211_WEP_MICLEN,
   79         .ic_attach      = tkip_attach,
   80         .ic_detach      = tkip_detach,
   81         .ic_setkey      = tkip_setkey,
   82         .ic_encap       = tkip_encap,
   83         .ic_decap       = tkip_decap,
   84         .ic_enmic       = tkip_enmic,
   85         .ic_demic       = tkip_demic,
   86 };
   87 
   88 #define tkip    ieee80211_cipher_tkip
   89 
   90 typedef uint8_t u8;
   91 typedef uint16_t u16;
   92 typedef uint32_t __u32;
   93 typedef uint32_t u32;
   94 
   95 struct tkip_ctx {
   96         struct ieee80211com *tc_ic;     /* for diagnostics */
   97 
   98         u16     tx_ttak[5];
   99         int     tx_phase1_done;
  100         u8      tx_rc4key[16];          /* XXX for test module; make locals? */
  101 
  102         u16     rx_ttak[5];
  103         int     rx_phase1_done;
  104         u8      rx_rc4key[16];          /* XXX for test module; make locals? */
  105         uint64_t rx_rsc;                /* held until MIC verified */
  106 };
  107 
  108 static  void michael_mic(struct tkip_ctx *, const u8 *key,
  109                 struct mbuf *m, u_int off, size_t data_len,
  110                 u8 mic[IEEE80211_WEP_MICLEN]);
  111 static  int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *,
  112                 struct mbuf *, int hdr_len);
  113 static  int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *,
  114                 struct mbuf *, int hdr_len);
  115 
  116 static void *
  117 tkip_attach(struct ieee80211com *ic, struct ieee80211_key *k)
  118 {
  119         struct tkip_ctx *ctx;
  120 
  121         ctx = kmem_intr_zalloc(sizeof(struct tkip_ctx), KM_NOSLEEP);
  122         if (ctx == NULL) {
  123                 ic->ic_stats.is_crypto_nomem++;
  124                 return NULL;
  125         }
  126 
  127         ctx->tc_ic = ic;
  128         return ctx;
  129 }
  130 
  131 static void
  132 tkip_detach(struct ieee80211_key *k)
  133 {
  134         struct tkip_ctx *ctx = k->wk_private;
  135 
  136         kmem_intr_free(ctx, sizeof(struct tkip_ctx));
  137 }
  138 
  139 static int
  140 tkip_setkey(struct ieee80211_key *k)
  141 {
  142         struct tkip_ctx *ctx = k->wk_private;
  143 
  144         if (k->wk_keylen != (128/NBBY)) {
  145                 (void) ctx;             /* XXX */
  146                 IEEE80211_DPRINTF(ctx->tc_ic, IEEE80211_MSG_CRYPTO,
  147                         "%s: Invalid key length %u, expecting %u\n",
  148                         __func__, k->wk_keylen, 128/NBBY);
  149                 return 0;
  150         }
  151         k->wk_keytsc = 1;               /* TSC starts at 1 */
  152         return 1;
  153 }
  154 
  155 /*
  156  * Add privacy headers and do any s/w encryption required.
  157  */
  158 static int
  159 tkip_encap(struct ieee80211_key *k, struct mbuf *m, u_int8_t keyid)
  160 {
  161         struct tkip_ctx *ctx = k->wk_private;
  162         struct ieee80211com *ic = ctx->tc_ic;
  163         u_int8_t *ivp;
  164         int hdrlen;
  165 
  166         /*
  167          * Handle TKIP counter measures requirement.
  168          */
  169         if (ic->ic_flags & IEEE80211_F_COUNTERM) {
  170 #ifdef IEEE80211_DEBUG
  171                 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
  172 #endif
  173 
  174                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
  175                         "[%s] Discard frame due to countermeasures (%s)\n",
  176                         ether_sprintf(wh->i_addr2), __func__);
  177                 ic->ic_stats.is_crypto_tkipcm++;
  178                 return 0;
  179         }
  180 
  181         hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
  182         ivp = mtod(m, u_int8_t *) + hdrlen;
  183 
  184         ivp[0] = k->wk_keytsc >> 8;             /* TSC1 */
  185         ivp[1] = (ivp[0] | 0x20) & 0x7f;        /* WEP seed */
  186         ivp[2] = k->wk_keytsc >> 0;             /* TSC0 */
  187         ivp[3] = keyid | IEEE80211_WEP_EXTIV;   /* KeyID | ExtID */
  188         ivp[4] = k->wk_keytsc >> 16;            /* TSC2 */
  189         ivp[5] = k->wk_keytsc >> 24;            /* TSC3 */
  190         ivp[6] = k->wk_keytsc >> 32;            /* TSC4 */
  191         ivp[7] = k->wk_keytsc >> 40;            /* TSC5 */
  192 
  193         /*
  194          * Finally, do software encrypt if neeed.
  195          */
  196         if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
  197                 if (!tkip_encrypt(ctx, k, m, hdrlen))
  198                         return 0;
  199                 /* NB: tkip_encrypt handles wk_keytsc */
  200         } else
  201                 k->wk_keytsc++;
  202 
  203         return 1;
  204 }
  205 
  206 /*
  207  * Add MIC to the frame as needed.
  208  */
  209 static int
  210 tkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
  211 {
  212         struct tkip_ctx *ctx = k->wk_private;
  213 
  214         if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
  215                 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
  216                 struct ieee80211com *ic = ctx->tc_ic;
  217                 int hdrlen;
  218                 uint8_t mic[IEEE80211_WEP_MICLEN];
  219 
  220                 ic->ic_stats.is_crypto_tkipenmic++;
  221 
  222                 hdrlen = ieee80211_hdrspace(ic, wh);
  223 
  224                 michael_mic(ctx, k->wk_txmic,
  225                         m, hdrlen, m->m_pkthdr.len - hdrlen, mic);
  226                 return m_append(m, tkip.ic_miclen, mic);
  227         }
  228         return 1;
  229 }
  230 
  231 static __inline uint64_t
  232 READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
  233 {
  234         uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | ((u32)b3 << 24);
  235         uint16_t iv16 = (b4 << 0) | (b5 << 8);
  236         return (((uint64_t)iv16) << 32) | iv32;
  237 }
  238 
  239 /*
  240  * Validate and strip privacy headers (and trailer) for a
  241  * received frame.  If necessary, decrypt the frame using
  242  * the specified key.
  243  */
  244 static int
  245 tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
  246 {
  247         struct tkip_ctx *ctx = k->wk_private;
  248         struct ieee80211com *ic = ctx->tc_ic;
  249         struct ieee80211_frame *wh;
  250         uint8_t *ivp;
  251 
  252         /*
  253          * Header should have extended IV and sequence number;
  254          * verify the former and validate the latter.
  255          */
  256         wh = mtod(m, struct ieee80211_frame *);
  257         ivp = mtod(m, uint8_t *) + hdrlen;
  258         if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
  259                 /*
  260                  * No extended IV; discard frame.
  261                  */
  262                 IEEE80211_DPRINTF(ctx->tc_ic, IEEE80211_MSG_CRYPTO,
  263                         "[%s] missing ExtIV for TKIP cipher\n",
  264                         ether_sprintf(wh->i_addr2));
  265                 ctx->tc_ic->ic_stats.is_rx_tkipformat++;
  266                 return 0;
  267         }
  268         /*
  269          * Handle TKIP counter measures requirement.
  270          */
  271         if (ic->ic_flags & IEEE80211_F_COUNTERM) {
  272                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
  273                         "[%s] discard frame due to countermeasures (%s)\n",
  274                         ether_sprintf(wh->i_addr2), __func__);
  275                 ic->ic_stats.is_crypto_tkipcm++;
  276                 return 0;
  277         }
  278 
  279         ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
  280         if (ctx->rx_rsc <= k->wk_keyrsc) {
  281                 /*
  282                  * Replay violation; notify upper layer.
  283                  */
  284                 ieee80211_notify_replay_failure(ctx->tc_ic, wh, k, ctx->rx_rsc);
  285                 ctx->tc_ic->ic_stats.is_rx_tkipreplay++;
  286                 return 0;
  287         }
  288         /*
  289          * NB: We can't update the rsc in the key until MIC is verified.
  290          *
  291          * We assume we are not preempted between doing the check above
  292          * and updating wk_keyrsc when stripping the MIC in tkip_demic.
  293          * Otherwise we might process another packet and discard it as
  294          * a replay.
  295          */
  296 
  297         /*
  298          * Check if the device handled the decrypt in hardware.
  299          * If so we just strip the header; otherwise we need to
  300          * handle the decrypt in software.
  301          */
  302         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
  303             !tkip_decrypt(ctx, k, m, hdrlen))
  304                 return 0;
  305 
  306         /*
  307          * Copy up 802.11 header and strip crypto bits.
  308          */
  309         memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen);
  310         m_adj(m, tkip.ic_header);
  311         m_adj(m, -tkip.ic_trailer);
  312 
  313         return 1;
  314 }
  315 
  316 /*
  317  * Verify and strip MIC from the frame.
  318  */
  319 static int
  320 tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
  321 {
  322         struct tkip_ctx *ctx = k->wk_private;
  323 
  324         if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
  325                 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
  326                 struct ieee80211com *ic = ctx->tc_ic;
  327                 int hdrlen = ieee80211_hdrspace(ic, wh);
  328                 u8 mic[IEEE80211_WEP_MICLEN];
  329                 u8 mic0[IEEE80211_WEP_MICLEN];
  330 
  331                 ic->ic_stats.is_crypto_tkipdemic++;
  332 
  333                 michael_mic(ctx, k->wk_rxmic,
  334                         m, hdrlen, m->m_pkthdr.len - (hdrlen + tkip.ic_miclen),
  335                         mic);
  336                 m_copydata(m, m->m_pkthdr.len - tkip.ic_miclen,
  337                         tkip.ic_miclen, mic0);
  338                 if (memcmp(mic, mic0, tkip.ic_miclen)) {
  339                         /* NB: 802.11 layer handles statistic and debug msg */
  340                         ieee80211_notify_michael_failure(ic, wh,
  341                                 k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
  342                                         k->wk_rxkeyix : k->wk_keyix);
  343                         return 0;
  344                 }
  345         }
  346         /*
  347          * Strip MIC from the tail.
  348          */
  349         m_adj(m, -tkip.ic_miclen);
  350 
  351         /*
  352          * Ok to update rsc now that MIC has been verified.
  353          */
  354         k->wk_keyrsc = ctx->rx_rsc;
  355 
  356         return 1;
  357 }
  358 
  359 /*
  360  * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
  361  *
  362  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
  363  *
  364  * This program is free software; you can redistribute it and/or modify
  365  * it under the terms of the GNU General Public License version 2 as
  366  * published by the Free Software Foundation. See README and COPYING for
  367  * more details.
  368  *
  369  * Alternatively, this software may be distributed under the terms of BSD
  370  * license.
  371  */
  372 
  373 static const __u32 crc32_table[256] = {
  374         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  375         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  376         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  377         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  378         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  379         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  380         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  381         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  382         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  383         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  384         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  385         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  386         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  387         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  388         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  389         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  390         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  391         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  392         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  393         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  394         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  395         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  396         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  397         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  398         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  399         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  400         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  401         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  402         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  403         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  404         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  405         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  406         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  407         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  408         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  409         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  410         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  411         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  412         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  413         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  414         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  415         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  416         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  417         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  418         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  419         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  420         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  421         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  422         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  423         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  424         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  425         0x2d02ef8dL
  426 };
  427 
  428 static __inline u16 RotR1(u16 val)
  429 {
  430         return (val >> 1) | (val << 15);
  431 }
  432 
  433 static __inline u8 Lo8(u16 val)
  434 {
  435         return val & 0xff;
  436 }
  437 
  438 static __inline u8 Hi8(u16 val)
  439 {
  440         return val >> 8;
  441 }
  442 
  443 static __inline u16 Lo16(u32 val)
  444 {
  445         return val & 0xffff;
  446 }
  447 
  448 static __inline u16 Hi16(u32 val)
  449 {
  450         return val >> 16;
  451 }
  452 
  453 static __inline u16 Mk16(u8 hi, u8 lo)
  454 {
  455         return lo | (((u16) hi) << 8);
  456 }
  457 
  458 static __inline u16 Mk16_le(const u16 *v)
  459 {
  460         return le16toh(*v);
  461 }
  462 
  463 static const u16 Sbox[256] = {
  464         0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
  465         0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
  466         0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
  467         0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
  468         0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
  469         0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
  470         0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
  471         0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
  472         0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
  473         0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
  474         0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
  475         0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
  476         0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
  477         0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
  478         0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
  479         0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
  480         0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
  481         0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
  482         0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
  483         0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
  484         0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
  485         0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
  486         0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
  487         0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
  488         0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
  489         0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
  490         0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
  491         0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
  492         0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
  493         0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
  494         0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
  495         0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
  496 };
  497 
  498 static __inline u16 _S_(u16 v)
  499 {
  500         u16 t = Sbox[Hi8(v)];
  501         return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
  502 }
  503 
  504 #define PHASE1_LOOP_COUNT 8
  505 
  506 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
  507 {
  508         int i, j;
  509 
  510         /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
  511         TTAK[0] = Lo16(IV32);
  512         TTAK[1] = Hi16(IV32);
  513         TTAK[2] = Mk16(TA[1], TA[0]);
  514         TTAK[3] = Mk16(TA[3], TA[2]);
  515         TTAK[4] = Mk16(TA[5], TA[4]);
  516 
  517         for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
  518                 j = 2 * (i & 1);
  519                 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
  520                 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
  521                 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
  522                 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
  523                 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
  524         }
  525 }
  526 
  527 #ifndef _BYTE_ORDER
  528 #error "Don't know native byte order"
  529 #endif
  530 
  531 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
  532                                u16 IV16)
  533 {
  534         /* Make temporary area overlap WEP seed so that the final copy can be
  535          * avoided on little endian hosts. */
  536         u16 *PPK = (u16 *) &WEPSeed[4];
  537 
  538         /* Step 1 - make copy of TTAK and bring in TSC */
  539         PPK[0] = TTAK[0];
  540         PPK[1] = TTAK[1];
  541         PPK[2] = TTAK[2];
  542         PPK[3] = TTAK[3];
  543         PPK[4] = TTAK[4];
  544         PPK[5] = TTAK[4] + IV16;
  545 
  546         /* Step 2 - 96-bit bijective mixing using S-box */
  547         PPK[0] += _S_(PPK[5] ^ Mk16_le((const u16 *) &TK[0]));
  548         PPK[1] += _S_(PPK[0] ^ Mk16_le((const u16 *) &TK[2]));
  549         PPK[2] += _S_(PPK[1] ^ Mk16_le((const u16 *) &TK[4]));
  550         PPK[3] += _S_(PPK[2] ^ Mk16_le((const u16 *) &TK[6]));
  551         PPK[4] += _S_(PPK[3] ^ Mk16_le((const u16 *) &TK[8]));
  552         PPK[5] += _S_(PPK[4] ^ Mk16_le((const u16 *) &TK[10]));
  553 
  554         PPK[0] += RotR1(PPK[5] ^ Mk16_le((const u16 *) &TK[12]));
  555         PPK[1] += RotR1(PPK[0] ^ Mk16_le((const u16 *) &TK[14]));
  556         PPK[2] += RotR1(PPK[1]);
  557         PPK[3] += RotR1(PPK[2]);
  558         PPK[4] += RotR1(PPK[3]);
  559         PPK[5] += RotR1(PPK[4]);
  560 
  561         /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
  562          * WEPSeed[0..2] is transmitted as WEP IV */
  563         WEPSeed[0] = Hi8(IV16);
  564         WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
  565         WEPSeed[2] = Lo8(IV16);
  566         WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const u16 *) &TK[0])) >> 1);
  567 
  568 #if _BYTE_ORDER == _BIG_ENDIAN
  569         {
  570                 int i;
  571                 for (i = 0; i < 6; i++)
  572                         PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
  573         }
  574 #endif
  575 }
  576 
  577 static void
  578 wep_encrypt(u8 *key, struct mbuf *m0, u_int off, size_t data_len,
  579         uint8_t icv[IEEE80211_WEP_CRCLEN])
  580 {
  581         u32 i, j, k, crc;
  582         size_t buflen;
  583         u8 S[256];
  584         u8 *pos;
  585         struct mbuf *m;
  586 #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
  587 
  588         /* Setup RC4 state */
  589         for (i = 0; i < 256; i++)
  590                 S[i] = i;
  591         j = 0;
  592         for (i = 0; i < 256; i++) {
  593                 j = (j + S[i] + key[i & 0x0f]) & 0xff;
  594                 S_SWAP(i, j);
  595         }
  596 
  597         /* Compute CRC32 over unencrypted data and apply RC4 to data */
  598         crc = ~0;
  599         i = j = 0;
  600         m = m0;
  601         pos = mtod(m, uint8_t *) + off;
  602         buflen = m->m_len - off;
  603         for (;;) {
  604                 if (buflen > data_len)
  605                         buflen = data_len;
  606                 data_len -= buflen;
  607                 for (k = 0; k < buflen; k++) {
  608                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  609                         i = (i + 1) & 0xff;
  610                         j = (j + S[i]) & 0xff;
  611                         S_SWAP(i, j);
  612                         *pos++ ^= S[(S[i] + S[j]) & 0xff];
  613                 }
  614                 m = m->m_next;
  615                 if (m == NULL) {
  616                         IASSERT(data_len == 0,
  617                             ("out of buffers with data_len %zu\n", data_len));
  618                         break;
  619                 }
  620                 pos = mtod(m, uint8_t *);
  621                 buflen = m->m_len;
  622         }
  623         crc = ~crc;
  624 
  625         /* Append little-endian CRC32 and encrypt it to produce ICV */
  626         icv[0] = crc;
  627         icv[1] = crc >> 8;
  628         icv[2] = crc >> 16;
  629         icv[3] = crc >> 24;
  630         for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
  631                 i = (i + 1) & 0xff;
  632                 j = (j + S[i]) & 0xff;
  633                 S_SWAP(i, j);
  634                 icv[k] ^= S[(S[i] + S[j]) & 0xff];
  635         }
  636 }
  637 
  638 static int
  639 wep_decrypt(u8 *key, struct mbuf *m, u_int off, size_t data_len)
  640 {
  641         u32 i, j, k, crc;
  642         u8 S[256];
  643         u8 *pos, icv[4];
  644         size_t buflen;
  645 
  646         /* Setup RC4 state */
  647         for (i = 0; i < 256; i++)
  648                 S[i] = i;
  649         j = 0;
  650         for (i = 0; i < 256; i++) {
  651                 j = (j + S[i] + key[i & 0x0f]) & 0xff;
  652                 S_SWAP(i, j);
  653         }
  654 
  655         /* Apply RC4 to data and compute CRC32 over decrypted data */
  656         crc = ~0;
  657         i = j = 0;
  658         pos = mtod(m, uint8_t *) + off;
  659         buflen = m->m_len - off;
  660         for (;;) {
  661                 if (buflen > data_len)
  662                         buflen = data_len;
  663                 data_len -= buflen;
  664                 for (k = 0; k < buflen; k++) {
  665                         i = (i + 1) & 0xff;
  666                         j = (j + S[i]) & 0xff;
  667                         S_SWAP(i, j);
  668                         *pos ^= S[(S[i] + S[j]) & 0xff];
  669                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  670                         pos++;
  671                 }
  672                 m = m->m_next;
  673                 if (m == NULL) {
  674                         IASSERT(data_len == 0,
  675                             ("out of buffers with data_len %zu\n", data_len));
  676                         break;
  677                 }
  678                 pos = mtod(m, uint8_t *);
  679                 buflen = m->m_len;
  680         }
  681         crc = ~crc;
  682 
  683         /* Encrypt little-endian CRC32 and verify that it matches with the
  684          * received ICV */
  685         icv[0] = crc;
  686         icv[1] = crc >> 8;
  687         icv[2] = crc >> 16;
  688         icv[3] = crc >> 24;
  689         for (k = 0; k < 4; k++) {
  690                 i = (i + 1) & 0xff;
  691                 j = (j + S[i]) & 0xff;
  692                 S_SWAP(i, j);
  693                 if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
  694                         /* ICV mismatch - drop frame */
  695                         return -1;
  696                 }
  697         }
  698 
  699         return 0;
  700 }
  701 
  702 
  703 static __inline u32 rotl(u32 val, int bits)
  704 {
  705         return (val << bits) | (val >> (32 - bits));
  706 }
  707 
  708 
  709 static __inline u32 rotr(u32 val, int bits)
  710 {
  711         return (val >> bits) | (val << (32 - bits));
  712 }
  713 
  714 
  715 static __inline u32 xswap(u32 val)
  716 {
  717         return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
  718 }
  719 
  720 
  721 #define michael_block(l, r)     \
  722 do {                            \
  723         r ^= rotl(l, 17);       \
  724         l += r;                 \
  725         r ^= xswap(l);          \
  726         l += r;                 \
  727         r ^= rotl(l, 3);        \
  728         l += r;                 \
  729         r ^= rotr(l, 2);        \
  730         l += r;                 \
  731 } while (0)
  732 
  733 
  734 static __inline u32 get_le32_split(u8 b0, u8 b1, u8 b2, u8 b3)
  735 {
  736         return b0 | (b1 << 8) | (b2 << 16) | ((u32)b3 << 24);
  737 }
  738 
  739 static __inline u32 get_le32(const u8 *p)
  740 {
  741         return get_le32_split(p[0], p[1], p[2], p[3]);
  742 }
  743 
  744 
  745 static __inline void put_le32(u8 *p, u32 v)
  746 {
  747         p[0] = v;
  748         p[1] = v >> 8;
  749         p[2] = v >> 16;
  750         p[3] = v >> 24;
  751 }
  752 
  753 /*
  754  * Craft pseudo header used to calculate the MIC.
  755  */
  756 static void
  757 michael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
  758 {
  759         const struct ieee80211_frame_addr4 *wh =
  760                 (const struct ieee80211_frame_addr4 *) wh0;
  761 
  762         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  763         case IEEE80211_FC1_DIR_NODS:
  764                 IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
  765                 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
  766                 break;
  767         case IEEE80211_FC1_DIR_TODS:
  768                 IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
  769                 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
  770                 break;
  771         case IEEE80211_FC1_DIR_FROMDS:
  772                 IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
  773                 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
  774                 break;
  775         case IEEE80211_FC1_DIR_DSTODS:
  776                 IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
  777                 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
  778                 break;
  779         }
  780 
  781         if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
  782                 const struct ieee80211_qosframe *qwh =
  783                         (const struct ieee80211_qosframe *) wh;
  784                 hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
  785         } else
  786                 hdr[12] = 0;
  787         hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
  788 }
  789 
  790 static void
  791 michael_mic(struct tkip_ctx *ctx, const u8 *key,
  792         struct mbuf *m, u_int off, size_t data_len,
  793         u8 mic[IEEE80211_WEP_MICLEN])
  794 {
  795         uint8_t hdr[16];
  796         u32 l, r;
  797         const uint8_t *data;
  798         u_int space;
  799         uint8_t spill[4];
  800         int nspill = 0;
  801 
  802         michael_mic_hdr(mtod(m, struct ieee80211_frame *), hdr);
  803 
  804         l = get_le32(key);
  805         r = get_le32(key + 4);
  806 
  807         /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
  808         l ^= get_le32(hdr);
  809         michael_block(l, r);
  810         l ^= get_le32(&hdr[4]);
  811         michael_block(l, r);
  812         l ^= get_le32(&hdr[8]);
  813         michael_block(l, r);
  814         l ^= get_le32(&hdr[12]);
  815         michael_block(l, r);
  816 
  817         /* first buffer has special handling */
  818         data = mtod(m, const uint8_t *) + off;
  819         space = m->m_len - off;
  820         for (;;) {
  821                 if (space > data_len)
  822                         space = data_len;
  823                 if (nspill) {
  824                         int n = uimin(4 - nspill, space);
  825                         memcpy(spill + nspill, data, n);
  826                         nspill += n;
  827                         data += n;
  828                         space -= n;
  829                         data_len -= n;
  830                         if (nspill == 4) {
  831                                 l ^= get_le32(spill);
  832                                 michael_block(l, r);
  833                                 nspill = 0;
  834                         } else
  835                                 goto next;
  836                 }
  837                 /* collect 32-bit blocks from current buffer */
  838                 while (space >= sizeof(uint32_t)) {
  839                         l ^= get_le32(data);
  840                         michael_block(l, r);
  841                         data += sizeof(uint32_t);
  842                         space -= sizeof(uint32_t);
  843                         data_len -= sizeof(uint32_t);
  844                 }
  845                 if (space) {
  846                         memcpy(spill, data, space);
  847                         nspill = space;
  848                         data_len -= space;
  849                 }
  850 next:
  851                 if (!data_len)
  852                         break;
  853                 m = m->m_next;
  854                 KASSERT(m);
  855                 /*
  856                  * Setup for next buffer.
  857                  */
  858                 data = mtod(m, const uint8_t *);
  859                 space = m->m_len;
  860         }
  861         /* Last block and padding (0x5a, 4..7 x 0) */
  862         spill[nspill++] = 0x5a;
  863         for (; nspill < 4; nspill++)
  864                 spill[nspill] = 0;
  865         l ^= get_le32(spill);
  866         michael_block(l, r);
  867         /* l ^= 0; */
  868         michael_block(l, r);
  869 
  870         put_le32(mic, l);
  871         put_le32(mic + 4, r);
  872 }
  873 
  874 static int
  875 tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
  876         struct mbuf *m, int hdrlen)
  877 {
  878         struct ieee80211_frame *wh;
  879         uint8_t icv[IEEE80211_WEP_CRCLEN];
  880 
  881         ctx->tc_ic->ic_stats.is_crypto_tkip++;
  882 
  883         wh = mtod(m, struct ieee80211_frame *);
  884         if (!ctx->tx_phase1_done) {
  885                 tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
  886                                    (u32)(key->wk_keytsc >> 16));
  887                 ctx->tx_phase1_done = 1;
  888         }
  889         tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
  890                 (u16)key->wk_keytsc);
  891 
  892         wep_encrypt(ctx->tx_rc4key,
  893                 m, hdrlen + tkip.ic_header,
  894                 m->m_pkthdr.len - (hdrlen + tkip.ic_header),
  895                 icv);
  896 
  897         if (!m_append(m, IEEE80211_WEP_CRCLEN, icv)) {
  898                 return 0;
  899         }
  900 
  901         key->wk_keytsc++;
  902         if ((u16)(key->wk_keytsc) == 0)
  903                 ctx->tx_phase1_done = 0;
  904 
  905         return 1;
  906 }
  907 
  908 static int
  909 tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
  910         struct mbuf *m, int hdrlen)
  911 {
  912         struct ieee80211_frame *wh;
  913         u32 iv32;
  914         u16 iv16;
  915 
  916         ctx->tc_ic->ic_stats.is_crypto_tkip++;
  917 
  918         wh = mtod(m, struct ieee80211_frame *);
  919         /* NB: tkip_decap already verified header and left seq in rx_rsc */
  920         iv16 = (u16) ctx->rx_rsc;
  921         iv32 = (u32) (ctx->rx_rsc >> 16);
  922 
  923         if (iv32 != (u32)(key->wk_keyrsc >> 16) || !ctx->rx_phase1_done) {
  924                 tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
  925                         wh->i_addr2, iv32);
  926                 ctx->rx_phase1_done = 1;
  927         }
  928         tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
  929 
  930         /* NB: m is unstripped; deduct headers + ICV to get payload */
  931         if (wep_decrypt(ctx->rx_rc4key, m, hdrlen + tkip.ic_header,
  932             m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
  933                 if (iv32 != (u32)(key->wk_keyrsc >> 16)) {
  934                         /* Previously cached Phase1 result was already lost, so
  935                          * it needs to be recalculated for the next packet. */
  936                         ctx->rx_phase1_done = 0;
  937                 }
  938                 IEEE80211_DPRINTF(ctx->tc_ic, IEEE80211_MSG_CRYPTO,
  939                     "[%s] TKIP ICV mismatch on decrypt\n",
  940                     ether_sprintf(wh->i_addr2));
  941                 ctx->tc_ic->ic_stats.is_rx_tkipicv++;
  942                 return 0;
  943         }
  944 
  945         return 1;
  946 }
  947 
  948 IEEE80211_CRYPTO_SETUP(tkip_register)
  949 {
  950         ieee80211_crypto_register(&tkip);
  951 }

Cache object: f7217d94066cc2b6b0fd630497b3f9b9


[ 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.