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

Cache object: f73324ef010694e6563b649336cecd8a


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