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_wep.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * Alternatively, this software may be distributed under the terms of the
   17  * GNU General Public License ("GPL") version 2 as published by the Free
   18  * Software Foundation.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 #ifdef __FreeBSD__
   34 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_wep.c,v 1.7 2005/06/10 16:11:24 sam Exp $");
   35 #endif
   36 #ifdef __NetBSD__
   37 __KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_wep.c,v 1.8 2008/12/17 20:51:37 cegger Exp $");
   38 #endif
   39 
   40 /*
   41  * IEEE 802.11 WEP crypto support.
   42  */
   43 #include <sys/param.h>
   44 #include <sys/systm.h> 
   45 #include <sys/mbuf.h>   
   46 #include <sys/malloc.h>
   47 #include <sys/kernel.h>
   48 #include <sys/endian.h>
   49 
   50 #include <sys/socket.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_ether.h>
   54 #include <net/if_media.h>
   55 
   56 #include <net80211/ieee80211_var.h>
   57 
   58 static  void *wep_attach(struct ieee80211com *, struct ieee80211_key *);
   59 static  void wep_detach(struct ieee80211_key *);
   60 static  int wep_setkey(struct ieee80211_key *);
   61 static  int wep_encap(struct ieee80211_key *, struct mbuf *, u_int8_t keyid);
   62 static  int wep_decap(struct ieee80211_key *, struct mbuf *, int hdrlen);
   63 static  int wep_enmic(struct ieee80211_key *, struct mbuf *, int);
   64 static  int wep_demic(struct ieee80211_key *, struct mbuf *, int);
   65 
   66 const struct ieee80211_cipher ieee80211_cipher_wep = {
   67         .ic_name        = "WEP",
   68         .ic_cipher      = IEEE80211_CIPHER_WEP,
   69         .ic_header      = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
   70         .ic_trailer     = IEEE80211_WEP_CRCLEN,
   71         .ic_miclen      = 0,
   72         .ic_attach      = wep_attach,
   73         .ic_detach      = wep_detach,
   74         .ic_setkey      = wep_setkey,
   75         .ic_encap       = wep_encap,
   76         .ic_decap       = wep_decap,
   77         .ic_enmic       = wep_enmic,
   78         .ic_demic       = wep_demic,
   79 };
   80 
   81 #define wep     ieee80211_cipher_wep
   82 
   83 static  int wep_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
   84 static  int wep_decrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
   85 
   86 struct wep_ctx {
   87         struct ieee80211com *wc_ic;     /* for diagnostics */
   88         u_int32_t       wc_iv;          /* initial vector for crypto */
   89 };
   90 
   91 static void *
   92 wep_attach(struct ieee80211com *ic, struct ieee80211_key *k)
   93 {
   94         struct wep_ctx *ctx;
   95 
   96         ctx = malloc(sizeof(struct wep_ctx),
   97                 M_DEVBUF, M_NOWAIT | M_ZERO);
   98         if (ctx == NULL) {
   99                 ic->ic_stats.is_crypto_nomem++;
  100                 return NULL;
  101         }
  102 
  103         ctx->wc_ic = ic;
  104         get_random_bytes(&ctx->wc_iv, sizeof(ctx->wc_iv));
  105         return ctx;
  106 }
  107 
  108 static void
  109 wep_detach(struct ieee80211_key *k)
  110 {
  111         struct wep_ctx *ctx = k->wk_private;
  112 
  113         free(ctx, M_DEVBUF);
  114 }
  115 
  116 static int
  117 wep_setkey(struct ieee80211_key *k)
  118 {
  119         return k->wk_keylen >= 40/NBBY;
  120 }
  121 
  122 /*
  123  * Add privacy headers appropriate for the specified key.
  124  */
  125 static int
  126 wep_encap(struct ieee80211_key *k, struct mbuf *m, u_int8_t keyid)
  127 {
  128         struct wep_ctx *ctx = k->wk_private;
  129         struct ieee80211com *ic = ctx->wc_ic;
  130         u_int32_t iv;
  131         u_int8_t *ivp;
  132         int hdrlen;
  133 
  134         hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
  135 
  136         /*
  137          * Copy down 802.11 header and add the IV + KeyID.
  138          */
  139         M_PREPEND(m, wep.ic_header, M_NOWAIT);
  140         if (m == NULL)
  141                 return 0;
  142         ivp = mtod(m, u_int8_t *);
  143         ovbcopy(ivp + wep.ic_header, ivp, hdrlen);
  144         ivp += hdrlen;
  145 
  146         /*
  147          * XXX
  148          * IV must not duplicate during the lifetime of the key.
  149          * But no mechanism to renew keys is defined in IEEE 802.11
  150          * for WEP.  And the IV may be duplicated at other stations
  151          * because the session key itself is shared.  So we use a
  152          * pseudo random IV for now, though it is not the right way.
  153          *
  154          * NB: Rather than use a strictly random IV we select a
  155          * random one to start and then increment the value for
  156          * each frame.  This is an explicit tradeoff between
  157          * overhead and security.  Given the basic insecurity of
  158          * WEP this seems worthwhile.
  159          */
  160 
  161         /*
  162          * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
  163          * (B, 255, N) with 3 <= B < 16 and 0 <= N <= 255
  164          */
  165         iv = ctx->wc_iv;
  166         if ((iv & 0xff00) == 0xff00) {
  167                 int B = (iv & 0xff0000) >> 16;
  168                 if (3 <= B && B < 16)
  169                         iv += 0x0100;
  170         }
  171         ctx->wc_iv = iv + 1;
  172 
  173         /*
  174          * NB: Preserve byte order of IV for packet
  175          *     sniffers; it doesn't matter otherwise.
  176          */
  177 #if _BYTE_ORDER == _BIG_ENDIAN
  178         ivp[0] = iv >> 0;
  179         ivp[1] = iv >> 8;
  180         ivp[2] = iv >> 16;
  181 #else
  182         ivp[2] = iv >> 0;
  183         ivp[1] = iv >> 8;
  184         ivp[0] = iv >> 16;
  185 #endif
  186         ivp[3] = keyid;
  187 
  188         /*
  189          * Finally, do software encrypt if neeed.
  190          */
  191         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
  192             !wep_encrypt(k, m, hdrlen))
  193                 return 0;
  194 
  195         return 1;
  196 }
  197 
  198 /*
  199  * Add MIC to the frame as needed.
  200  */
  201 static int
  202 wep_enmic(struct ieee80211_key *k, struct mbuf *m,
  203     int force)
  204 {
  205 
  206         return 1;
  207 }
  208 
  209 /*
  210  * Validate and strip privacy headers (and trailer) for a
  211  * received frame.  If necessary, decrypt the frame using
  212  * the specified key.
  213  */
  214 static int
  215 wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
  216 {
  217         struct wep_ctx *ctx = k->wk_private;
  218         struct ieee80211_frame *wh;
  219 
  220         wh = mtod(m, struct ieee80211_frame *);
  221 
  222         /*
  223          * Check if the device handled the decrypt in hardware.
  224          * If so we just strip the header; otherwise we need to
  225          * handle the decrypt in software.
  226          */
  227         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
  228             !wep_decrypt(k, m, hdrlen)) {
  229                 IEEE80211_DPRINTF(ctx->wc_ic, IEEE80211_MSG_CRYPTO,
  230                     "[%s] WEP ICV mismatch on decrypt\n",
  231                     ether_sprintf(wh->i_addr2));
  232                 ctx->wc_ic->ic_stats.is_rx_wepfail++;
  233                 return 0;
  234         }
  235 
  236         /*
  237          * Copy up 802.11 header and strip crypto bits.
  238          */
  239         ovbcopy(mtod(m, void *), mtod(m, u_int8_t *) + wep.ic_header, hdrlen);
  240         m_adj(m, wep.ic_header);
  241         m_adj(m, -wep.ic_trailer);
  242 
  243         return 1;
  244 }
  245 
  246 /*
  247  * Verify and strip MIC from the frame.
  248  */
  249 static int
  250 wep_demic(struct ieee80211_key *k, struct mbuf *skb,
  251     int force)
  252 {
  253         return 1;
  254 }
  255 
  256 static const uint32_t crc32_table[256] = {
  257         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  258         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  259         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  260         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  261         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  262         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  263         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  264         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  265         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  266         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  267         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  268         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  269         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  270         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  271         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  272         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  273         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  274         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  275         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  276         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  277         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  278         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  279         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  280         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  281         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  282         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  283         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  284         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  285         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  286         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  287         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  288         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  289         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  290         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  291         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  292         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  293         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  294         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  295         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  296         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  297         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  298         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  299         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  300         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  301         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  302         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  303         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  304         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  305         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  306         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  307         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  308         0x2d02ef8dL
  309 };
  310 
  311 static int
  312 wep_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
  313 {
  314 #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
  315         struct wep_ctx *ctx = key->wk_private;
  316         struct mbuf *m = m0;
  317         u_int8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  318         uint8_t icv[IEEE80211_WEP_CRCLEN];
  319         uint32_t i, j, k, crc;
  320         size_t buflen, data_len;
  321         uint8_t S[256];
  322         uint8_t *pos;
  323         u_int off, keylen;
  324 
  325         ctx->wc_ic->ic_stats.is_crypto_wep++;
  326 
  327         /* NB: this assumes the header was pulled up */
  328         memcpy(rc4key, mtod(m, u_int8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
  329         memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
  330 
  331         /* Setup RC4 state */
  332         for (i = 0; i < 256; i++)
  333                 S[i] = i;
  334         j = 0;
  335         keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
  336         for (i = 0; i < 256; i++) {
  337                 j = (j + S[i] + rc4key[i % keylen]) & 0xff;
  338                 S_SWAP(i, j);
  339         }
  340 
  341         off = hdrlen + wep.ic_header;
  342         data_len = m->m_pkthdr.len - off;
  343 
  344         /* Compute CRC32 over unencrypted data and apply RC4 to data */
  345         crc = ~0;
  346         i = j = 0;
  347         pos = mtod(m, uint8_t *) + off;
  348         buflen = m->m_len - off;
  349         for (;;) {
  350                 if (buflen > data_len)
  351                         buflen = data_len;
  352                 data_len -= buflen;
  353                 for (k = 0; k < buflen; k++) {
  354                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  355                         i = (i + 1) & 0xff;
  356                         j = (j + S[i]) & 0xff;
  357                         S_SWAP(i, j);
  358                         *pos++ ^= S[(S[i] + S[j]) & 0xff];
  359                 }
  360                 if (m->m_next == NULL) {
  361                         if (data_len != 0) {            /* out of data */
  362                                 IEEE80211_DPRINTF(ctx->wc_ic,
  363                                     IEEE80211_MSG_CRYPTO,
  364                                     "[%s] out of data for WEP (data_len %zu)\n",
  365                                     ether_sprintf(mtod(m0,
  366                                         struct ieee80211_frame *)->i_addr2),
  367                                     data_len);
  368                                 return 0;
  369                         }
  370                         break;
  371                 }
  372                 m = m->m_next;
  373                 pos = mtod(m, uint8_t *);
  374                 buflen = m->m_len;
  375         }
  376         crc = ~crc;
  377 
  378         /* Append little-endian CRC32 and encrypt it to produce ICV */
  379         icv[0] = crc;
  380         icv[1] = crc >> 8;
  381         icv[2] = crc >> 16;
  382         icv[3] = crc >> 24;
  383         for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
  384                 i = (i + 1) & 0xff;
  385                 j = (j + S[i]) & 0xff;
  386                 S_SWAP(i, j);
  387                 icv[k] ^= S[(S[i] + S[j]) & 0xff];
  388         }
  389         return m_append(m0, IEEE80211_WEP_CRCLEN, icv);
  390 #undef S_SWAP
  391 }
  392 
  393 static int
  394 wep_decrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
  395 {
  396 #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
  397         struct wep_ctx *ctx = key->wk_private;
  398         struct mbuf *m = m0;
  399         u_int8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  400         uint8_t icv[IEEE80211_WEP_CRCLEN];
  401         uint32_t i, j, k, crc;
  402         size_t buflen, data_len;
  403         uint8_t S[256];
  404         uint8_t *pos;
  405         u_int off, keylen;
  406 
  407         ctx->wc_ic->ic_stats.is_crypto_wep++;
  408 
  409         /* NB: this assumes the header was pulled up */
  410         memcpy(rc4key, mtod(m, u_int8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
  411         memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
  412 
  413         /* Setup RC4 state */
  414         for (i = 0; i < 256; i++)
  415                 S[i] = i;
  416         j = 0;
  417         keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
  418         for (i = 0; i < 256; i++) {
  419                 j = (j + S[i] + rc4key[i % keylen]) & 0xff;
  420                 S_SWAP(i, j);
  421         }
  422 
  423         off = hdrlen + wep.ic_header;
  424         data_len = m->m_pkthdr.len - (off + wep.ic_trailer),
  425 
  426         /* Compute CRC32 over unencrypted data and apply RC4 to data */
  427         crc = ~0;
  428         i = j = 0;
  429         pos = mtod(m, uint8_t *) + off;
  430         buflen = m->m_len - off;
  431         for (;;) {
  432                 if (buflen > data_len)
  433                         buflen = data_len;
  434                 data_len -= buflen;
  435                 for (k = 0; k < buflen; k++) {
  436                         i = (i + 1) & 0xff;
  437                         j = (j + S[i]) & 0xff;
  438                         S_SWAP(i, j);
  439                         *pos ^= S[(S[i] + S[j]) & 0xff];
  440                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  441                         pos++;
  442                 }
  443                 m = m->m_next;
  444                 if (m == NULL) {
  445                         if (data_len != 0) {            /* out of data */
  446                                 IEEE80211_DPRINTF(ctx->wc_ic,
  447                                     IEEE80211_MSG_CRYPTO,
  448                                     "[%s] out of data for WEP (data_len %zu)\n",
  449                                     ether_sprintf(mtod(m0,
  450                                         struct ieee80211_frame *)->i_addr2),
  451                                     data_len);
  452                                 return 0;
  453                         }
  454                         break;
  455                 }
  456                 pos = mtod(m, uint8_t *);
  457                 buflen = m->m_len;
  458         }
  459         crc = ~crc;
  460 
  461         /* Encrypt little-endian CRC32 and verify that it matches with
  462          * received ICV */
  463         icv[0] = crc;
  464         icv[1] = crc >> 8;
  465         icv[2] = crc >> 16;
  466         icv[3] = crc >> 24;
  467         for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
  468                 i = (i + 1) & 0xff;
  469                 j = (j + S[i]) & 0xff;
  470                 S_SWAP(i, j);
  471                 /* XXX assumes ICV is contiguous in mbuf */
  472                 if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
  473                         /* ICV mismatch - drop frame */
  474                         return 0;
  475                 }
  476         }
  477         return 1;
  478 #undef S_SWAP
  479 }
  480 
  481 IEEE80211_CRYPTO_SETUP(wep_register)
  482 {
  483         ieee80211_crypto_register(&wep);
  484 }

Cache object: 310fa3bfb1ed41aa9490f218ef0b128e


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