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$");
   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         net80211_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, IEEE80211_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         const struct ieee80211_rx_stats *rxs;
  245 
  246         rxs = ieee80211_get_rx_params_ptr(m);
  247 
  248         if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
  249                 goto finish;
  250 
  251         /*
  252          * Check if the device handled the decrypt in hardware.
  253          * If so we just strip the header; otherwise we need to
  254          * handle the decrypt in software.
  255          */
  256         if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) &&
  257             !wep_decrypt(k, m, hdrlen)) {
  258 #ifdef IEEE80211_DEBUG
  259                 struct ieee80211_frame *wh;
  260 
  261                 wh = mtod(m, struct ieee80211_frame *);
  262 #endif
  263                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
  264                     "%s", "WEP ICV mismatch on decrypt");
  265                 vap->iv_stats.is_rx_wepfail++;
  266                 return 0;
  267         }
  268 
  269         /*
  270          * Copy up 802.11 header and strip crypto bits.
  271          */
  272         ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + wep.ic_header, hdrlen);
  273         m_adj(m, wep.ic_header);
  274 
  275 finish:
  276         /* XXX TODO: do we have to strip this for offload devices? */
  277         m_adj(m, -wep.ic_trailer);
  278 
  279         return 1;
  280 }
  281 
  282 /*
  283  * Verify and strip MIC from the frame.
  284  */
  285 static int
  286 wep_demic(struct ieee80211_key *k, struct mbuf *skb, int force)
  287 {
  288         return 1;
  289 }
  290 
  291 static const uint32_t crc32_table[256] = {
  292         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  293         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  294         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  295         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  296         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  297         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  298         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  299         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  300         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  301         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  302         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  303         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  304         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  305         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  306         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  307         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  308         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  309         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  310         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  311         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  312         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  313         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  314         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  315         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  316         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  317         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  318         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  319         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  320         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  321         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  322         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  323         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  324         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  325         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  326         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  327         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  328         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  329         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  330         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  331         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  332         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  333         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  334         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  335         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  336         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  337         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  338         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  339         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  340         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  341         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  342         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  343         0x2d02ef8dL
  344 };
  345 
  346 static int
  347 wep_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
  348 {
  349 #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
  350         struct wep_ctx *ctx = key->wk_private;
  351         struct ieee80211vap *vap = ctx->wc_vap;
  352         struct mbuf *m = m0;
  353         uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  354         uint8_t icv[IEEE80211_WEP_CRCLEN];
  355         uint32_t i, j, k, crc;
  356         size_t buflen, data_len;
  357         uint8_t S[256];
  358         uint8_t *pos;
  359         u_int off, keylen;
  360 
  361         vap->iv_stats.is_crypto_wep++;
  362 
  363         /* NB: this assumes the header was pulled up */
  364         memcpy(rc4key, mtod(m, uint8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
  365         memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
  366 
  367         /* Setup RC4 state */
  368         for (i = 0; i < 256; i++)
  369                 S[i] = i;
  370         j = 0;
  371         keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
  372         for (i = 0; i < 256; i++) {
  373                 j = (j + S[i] + rc4key[i % keylen]) & 0xff;
  374                 S_SWAP(i, j);
  375         }
  376 
  377         off = hdrlen + wep.ic_header;
  378         data_len = m->m_pkthdr.len - off;
  379 
  380         /* Compute CRC32 over unencrypted data and apply RC4 to data */
  381         crc = ~0;
  382         i = j = 0;
  383         pos = mtod(m, uint8_t *) + off;
  384         buflen = m->m_len - off;
  385         for (;;) {
  386                 if (buflen > data_len)
  387                         buflen = data_len;
  388                 data_len -= buflen;
  389                 for (k = 0; k < buflen; k++) {
  390                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  391                         i = (i + 1) & 0xff;
  392                         j = (j + S[i]) & 0xff;
  393                         S_SWAP(i, j);
  394                         *pos++ ^= S[(S[i] + S[j]) & 0xff];
  395                 }
  396                 if (m->m_next == NULL) {
  397                         if (data_len != 0) {            /* out of data */
  398                                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
  399                                     ether_sprintf(mtod(m0,
  400                                         struct ieee80211_frame *)->i_addr2),
  401                                     "out of data for WEP (data_len %zu)",
  402                                     data_len);
  403                                 /* XXX stat */
  404                                 return 0;
  405                         }
  406                         break;
  407                 }
  408                 m = m->m_next;
  409                 pos = mtod(m, uint8_t *);
  410                 buflen = m->m_len;
  411         }
  412         crc = ~crc;
  413 
  414         /* Append little-endian CRC32 and encrypt it to produce ICV */
  415         icv[0] = crc;
  416         icv[1] = crc >> 8;
  417         icv[2] = crc >> 16;
  418         icv[3] = crc >> 24;
  419         for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
  420                 i = (i + 1) & 0xff;
  421                 j = (j + S[i]) & 0xff;
  422                 S_SWAP(i, j);
  423                 icv[k] ^= S[(S[i] + S[j]) & 0xff];
  424         }
  425         return m_append(m0, IEEE80211_WEP_CRCLEN, icv);
  426 #undef S_SWAP
  427 }
  428 
  429 static int
  430 wep_decrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
  431 {
  432 #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
  433         struct wep_ctx *ctx = key->wk_private;
  434         struct ieee80211vap *vap = ctx->wc_vap;
  435         struct mbuf *m = m0;
  436         uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  437         uint8_t icv[IEEE80211_WEP_CRCLEN];
  438         uint32_t i, j, k, crc;
  439         size_t buflen, data_len;
  440         uint8_t S[256];
  441         uint8_t *pos;
  442         u_int off, keylen;
  443 
  444         vap->iv_stats.is_crypto_wep++;
  445 
  446         /* NB: this assumes the header was pulled up */
  447         memcpy(rc4key, mtod(m, uint8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
  448         memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
  449 
  450         /* Setup RC4 state */
  451         for (i = 0; i < 256; i++)
  452                 S[i] = i;
  453         j = 0;
  454         keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
  455         for (i = 0; i < 256; i++) {
  456                 j = (j + S[i] + rc4key[i % keylen]) & 0xff;
  457                 S_SWAP(i, j);
  458         }
  459 
  460         off = hdrlen + wep.ic_header;
  461         data_len = m->m_pkthdr.len - (off + wep.ic_trailer);
  462 
  463         /* Compute CRC32 over unencrypted data and apply RC4 to data */
  464         crc = ~0;
  465         i = j = 0;
  466         pos = mtod(m, uint8_t *) + off;
  467         buflen = m->m_len - off;
  468         for (;;) {
  469                 if (buflen > data_len)
  470                         buflen = data_len;
  471                 data_len -= buflen;
  472                 for (k = 0; k < buflen; k++) {
  473                         i = (i + 1) & 0xff;
  474                         j = (j + S[i]) & 0xff;
  475                         S_SWAP(i, j);
  476                         *pos ^= S[(S[i] + S[j]) & 0xff];
  477                         crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
  478                         pos++;
  479                 }
  480                 m = m->m_next;
  481                 if (m == NULL) {
  482                         if (data_len != 0) {            /* out of data */
  483                                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
  484                                     mtod(m0, struct ieee80211_frame *)->i_addr2,
  485                                     "out of data for WEP (data_len %zu)",
  486                                     data_len);
  487                                 return 0;
  488                         }
  489                         break;
  490                 }
  491                 pos = mtod(m, uint8_t *);
  492                 buflen = m->m_len;
  493         }
  494         crc = ~crc;
  495 
  496         /* Encrypt little-endian CRC32 and verify that it matches with
  497          * received ICV */
  498         icv[0] = crc;
  499         icv[1] = crc >> 8;
  500         icv[2] = crc >> 16;
  501         icv[3] = crc >> 24;
  502         for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
  503                 i = (i + 1) & 0xff;
  504                 j = (j + S[i]) & 0xff;
  505                 S_SWAP(i, j);
  506                 /* XXX assumes ICV is contiguous in mbuf */
  507                 if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
  508                         /* ICV mismatch - drop frame */
  509                         return 0;
  510                 }
  511         }
  512         return 1;
  513 #undef S_SWAP
  514 }
  515 
  516 /*
  517  * Module glue.
  518  */
  519 IEEE80211_CRYPTO_MODULE(wep, 1);

Cache object: f97b5aea5ba0ad63cd565ef81d2822e1


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