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

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

    1 /*-
    2  * Copyright (c) 2001 Atsushi Onoe
    3  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * Alternatively, this software may be distributed under the terms of the
   18  * GNU General Public License ("GPL") version 2 as published by the Free
   19  * Software Foundation.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.3 2003/10/17 23:15:30 sam Exp $");
   35 
   36 #include "opt_inet.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h> 
   40 #include <sys/mbuf.h>   
   41 #include <sys/malloc.h>
   42 #include <sys/kernel.h>
   43 #include <sys/socket.h>
   44 #include <sys/sockio.h>
   45 #include <sys/endian.h>
   46 #include <sys/errno.h>
   47 #include <sys/bus.h>
   48 #include <sys/proc.h>
   49 #include <sys/sysctl.h>
   50 
   51 #include <machine/atomic.h>
   52  
   53 #include <net/if.h>
   54 #include <net/if_dl.h>
   55 #include <net/if_media.h>
   56 #include <net/if_arp.h>
   57 #include <net/ethernet.h>
   58 #include <net/if_llc.h>
   59 
   60 #include <net80211/ieee80211_var.h>
   61 
   62 #include <net/bpf.h>
   63 
   64 #ifdef INET
   65 #include <netinet/in.h> 
   66 #include <netinet/if_ether.h>
   67 #endif
   68 
   69 #include <crypto/rc4/rc4.h>
   70 #define arc4_ctxlen()                   sizeof (struct rc4_state)
   71 #define arc4_setkey(_c,_k,_l)           rc4_init(_c,_k,_l)
   72 #define arc4_encrypt(_c,_d,_s,_l)       rc4_crypt(_c,_s,_d,_l)
   73 
   74 static  void ieee80211_crc_init(void);
   75 static  u_int32_t ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len);
   76 
   77 void
   78 ieee80211_crypto_attach(struct ifnet *ifp)
   79 {
   80         struct ieee80211com *ic = (void *)ifp;
   81 
   82         /*
   83          * Setup crypto support.
   84          */
   85         ieee80211_crc_init();
   86         ic->ic_iv = arc4random();
   87 }
   88 
   89 void
   90 ieee80211_crypto_detach(struct ifnet *ifp)
   91 {
   92         struct ieee80211com *ic = (void *)ifp;
   93 
   94         if (ic->ic_wep_ctx != NULL) {
   95                 free(ic->ic_wep_ctx, M_DEVBUF);
   96                 ic->ic_wep_ctx = NULL;
   97         }
   98 }
   99 
  100 struct mbuf *
  101 ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
  102 {
  103         struct ieee80211com *ic = (void *)ifp;
  104         struct mbuf *m, *n, *n0;
  105         struct ieee80211_frame *wh;
  106         int i, left, len, moff, noff, kid;
  107         u_int32_t iv, crc;
  108         u_int8_t *ivp;
  109         void *ctx;
  110         u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  111         u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
  112 
  113         n0 = NULL;
  114         if ((ctx = ic->ic_wep_ctx) == NULL) {
  115                 ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
  116                 if (ctx == NULL) {
  117                         ic->ic_stats.is_crypto_nomem++;
  118                         goto fail;
  119                 }
  120                 ic->ic_wep_ctx = ctx;
  121         }
  122         m = m0;
  123         left = m->m_pkthdr.len;
  124         MGET(n, M_DONTWAIT, m->m_type);
  125         n0 = n;
  126         if (n == NULL) {
  127                 if (txflag)
  128                         ic->ic_stats.is_tx_nombuf++;
  129                 else
  130                         ic->ic_stats.is_rx_nombuf++;
  131                 goto fail;
  132         }
  133         M_MOVE_PKTHDR(n, m);
  134         len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
  135         if (txflag) {
  136                 n->m_pkthdr.len += len;
  137         } else {
  138                 n->m_pkthdr.len -= len;
  139                 left -= len;
  140         }
  141         n->m_len = MHLEN;
  142         if (n->m_pkthdr.len >= MINCLSIZE) {
  143                 MCLGET(n, M_DONTWAIT);
  144                 if (n->m_flags & M_EXT)
  145                         n->m_len = n->m_ext.ext_size;
  146         }
  147         len = sizeof(struct ieee80211_frame);
  148         memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
  149         wh = mtod(n, struct ieee80211_frame *);
  150         left -= len;
  151         moff = len;
  152         noff = len;
  153         if (txflag) {
  154                 kid = ic->ic_wep_txkey;
  155                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
  156                 iv = ic->ic_iv;
  157                 /*
  158                  * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
  159                  * (B, 255, N) with 3 <= B < 8
  160                  */
  161                 if (iv >= 0x03ff00 &&
  162                     (iv & 0xf8ff00) == 0x00ff00)
  163                         iv += 0x000100;
  164                 ic->ic_iv = iv + 1;
  165                 /* put iv in little endian to prepare 802.11i */
  166                 ivp = mtod(n, u_int8_t *) + noff;
  167                 for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
  168                         ivp[i] = iv & 0xff;
  169                         iv >>= 8;
  170                 }
  171                 ivp[IEEE80211_WEP_IVLEN] = kid << 6;    /* pad and keyid */
  172                 noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
  173         } else {
  174                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
  175                 ivp = mtod(m, u_int8_t *) + moff;
  176                 kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
  177                 moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
  178         }
  179         memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
  180         memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
  181             ic->ic_nw_keys[kid].wk_len);
  182         arc4_setkey(ctx, keybuf,
  183             IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
  184 
  185         /* encrypt with calculating CRC */
  186         crc = ~0;
  187         while (left > 0) {
  188                 len = m->m_len - moff;
  189                 if (len == 0) {
  190                         m = m->m_next;
  191                         moff = 0;
  192                         continue;
  193                 }
  194                 if (len > n->m_len - noff) {
  195                         len = n->m_len - noff;
  196                         if (len == 0) {
  197                                 MGET(n->m_next, M_DONTWAIT, n->m_type);
  198                                 if (n->m_next == NULL) {
  199                                         if (txflag)
  200                                                 ic->ic_stats.is_tx_nombuf++;
  201                                         else
  202                                                 ic->ic_stats.is_rx_nombuf++;
  203                                         goto fail;
  204                                 }
  205                                 n = n->m_next;
  206                                 n->m_len = MLEN;
  207                                 if (left >= MINCLSIZE) {
  208                                         MCLGET(n, M_DONTWAIT);
  209                                         if (n->m_flags & M_EXT)
  210                                                 n->m_len = n->m_ext.ext_size;
  211                                 }
  212                                 noff = 0;
  213                                 continue;
  214                         }
  215                 }
  216                 if (len > left)
  217                         len = left;
  218                 arc4_encrypt(ctx, mtod(n, caddr_t) + noff,
  219                     mtod(m, caddr_t) + moff, len);
  220                 if (txflag)
  221                         crc = ieee80211_crc_update(crc,
  222                             mtod(m, u_int8_t *) + moff, len);
  223                 else
  224                         crc = ieee80211_crc_update(crc,
  225                             mtod(n, u_int8_t *) + noff, len);
  226                 left -= len;
  227                 moff += len;
  228                 noff += len;
  229         }
  230         crc = ~crc;
  231         if (txflag) {
  232                 *(u_int32_t *)crcbuf = htole32(crc);
  233                 if (n->m_len >= noff + sizeof(crcbuf))
  234                         n->m_len = noff + sizeof(crcbuf);
  235                 else {
  236                         n->m_len = noff;
  237                         MGET(n->m_next, M_DONTWAIT, n->m_type);
  238                         if (n->m_next == NULL) {
  239                                 ic->ic_stats.is_tx_nombuf++;
  240                                 goto fail;
  241                         }
  242                         n = n->m_next;
  243                         n->m_len = sizeof(crcbuf);
  244                         noff = 0;
  245                 }
  246                 arc4_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
  247                     sizeof(crcbuf));
  248         } else {
  249                 n->m_len = noff;
  250                 for (noff = 0; noff < sizeof(crcbuf); noff += len) {
  251                         len = sizeof(crcbuf) - noff;
  252                         if (len > m->m_len - moff)
  253                                 len = m->m_len - moff;
  254                         if (len > 0)
  255                                 arc4_encrypt(ctx, crcbuf + noff,
  256                                     mtod(m, caddr_t) + moff, len);
  257                         m = m->m_next;
  258                         moff = 0;
  259                 }
  260                 if (crc != le32toh(*(u_int32_t *)crcbuf)) {
  261 #ifdef IEEE80211_DEBUG
  262                         if (ieee80211_debug) {
  263                                 if_printf(ifp, "decrypt CRC error\n");
  264                                 if (ieee80211_debug > 1)
  265                                         ieee80211_dump_pkt(n0->m_data,
  266                                             n0->m_len, -1, -1);
  267                         }
  268 #endif
  269                         ic->ic_stats.is_rx_decryptcrc++;
  270                         goto fail;
  271                 }
  272         }
  273         m_freem(m0);
  274         return n0;
  275 
  276   fail:
  277         m_freem(m0);
  278         m_freem(n0);
  279         return NULL;
  280 }
  281 
  282 /*
  283  * CRC 32 -- routine from RFC 2083
  284  */
  285 
  286 /* Table of CRCs of all 8-bit messages */
  287 static u_int32_t ieee80211_crc_table[256];
  288 
  289 /* Make the table for a fast CRC. */
  290 static void
  291 ieee80211_crc_init(void)
  292 {
  293         u_int32_t c;
  294         int n, k;
  295 
  296         for (n = 0; n < 256; n++) {
  297                 c = (u_int32_t)n;
  298                 for (k = 0; k < 8; k++) {
  299                         if (c & 1)
  300                                 c = 0xedb88320UL ^ (c >> 1);
  301                         else
  302                                 c = c >> 1;
  303                 }
  304                 ieee80211_crc_table[n] = c;
  305         }
  306 }
  307 
  308 /*
  309  * Update a running CRC with the bytes buf[0..len-1]--the CRC
  310  * should be initialized to all 1's, and the transmitted value
  311  * is the 1's complement of the final running CRC
  312  */
  313 
  314 static u_int32_t
  315 ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
  316 {
  317         u_int8_t *endbuf;
  318 
  319         for (endbuf = buf + len; buf < endbuf; buf++)
  320                 crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
  321         return crc;
  322 }

Cache object: 0bbd34d3b6b62ccadcc29ce8cefeb1bd


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