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 /*      $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $      */
    2 /*-
    3  * Copyright (c) 2001 Atsushi Onoe
    4  * Copyright (c) 2002, 2003 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.c,v 1.3 2003/10/17 23:15:30 sam Exp $");
   37 #else
   38 __KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $");
   39 #endif
   40 
   41 #include "opt_inet.h"
   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/socket.h>
   49 #include <sys/sockio.h>
   50 #include <sys/endian.h>
   51 #include <sys/errno.h>
   52 #ifdef __FreeBSD__
   53 #include <sys/bus.h>
   54 #endif
   55 #include <sys/proc.h>
   56 #include <sys/sysctl.h>
   57 
   58 #ifdef __FreeBSD__
   59 #include <machine/atomic.h>
   60 #endif
   61  
   62 #include <net/if.h>
   63 #include <net/if_dl.h>
   64 #include <net/if_media.h>
   65 #include <net/if_arp.h>
   66 #ifdef __FreeBSD__
   67 #include <net/ethernet.h>
   68 #else
   69 #include <net/if_ether.h>
   70 #endif
   71 #include <net/if_llc.h>
   72 
   73 #include <net80211/ieee80211_var.h>
   74 #include <net80211/ieee80211_compat.h>
   75 
   76 #include <net/bpf.h>
   77 
   78 #ifdef INET
   79 #include <netinet/in.h> 
   80 #ifdef __FreeBSD__
   81 #include <netinet/if_ether.h>
   82 #else
   83 #include <net/if_ether.h>
   84 #endif
   85 #endif
   86 
   87 #ifdef __FreeBSD__
   88 #include <crypto/rc4/rc4.h>
   89 #define arc4_ctxlen()                   sizeof (struct rc4_state)
   90 #define arc4_setkey(_c,_k,_l)           rc4_init(_c,_k,_l)
   91 #define arc4_encrypt(_c,_d,_s,_l)       rc4_crypt(_c,_s,_d,_l)
   92 #else
   93 #include <crypto/arc4/arc4.h>
   94 #endif
   95 
   96 static  void ieee80211_crc_init(void);
   97 static  u_int32_t ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len);
   98 
   99 void
  100 ieee80211_crypto_attach(struct ifnet *ifp)
  101 {
  102         struct ieee80211com *ic = (void *)ifp;
  103 
  104         /*
  105          * Setup crypto support.
  106          */
  107         ieee80211_crc_init();
  108         ic->ic_iv = arc4random();
  109 }
  110 
  111 void
  112 ieee80211_crypto_detach(struct ifnet *ifp)
  113 {
  114         struct ieee80211com *ic = (void *)ifp;
  115 
  116         if (ic->ic_wep_ctx != NULL) {
  117                 free(ic->ic_wep_ctx, M_DEVBUF);
  118                 ic->ic_wep_ctx = NULL;
  119         }
  120 }
  121 
  122 struct mbuf *
  123 ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
  124 {
  125         struct ieee80211com *ic = (void *)ifp;
  126         struct mbuf *m, *n, *n0;
  127         struct ieee80211_frame *wh;
  128         int i, left, len, moff, noff, kid;
  129         u_int32_t iv, crc;
  130         u_int8_t *ivp;
  131         void *ctx;
  132         u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
  133         u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
  134 
  135         n0 = NULL;
  136         if ((ctx = ic->ic_wep_ctx) == NULL) {
  137                 ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
  138                 if (ctx == NULL) {
  139                         ic->ic_stats.is_crypto_nomem++;
  140                         goto fail;
  141                 }
  142                 ic->ic_wep_ctx = ctx;
  143         }
  144         m = m0;
  145         left = m->m_pkthdr.len;
  146         MGET(n, M_DONTWAIT, m->m_type);
  147         n0 = n;
  148         if (n == NULL) {
  149                 if (txflag)
  150                         ic->ic_stats.is_tx_nombuf++;
  151                 else
  152                         ic->ic_stats.is_rx_nombuf++;
  153                 goto fail;
  154         }
  155 #ifdef __FreeBSD__
  156         M_MOVE_PKTHDR(n, m);
  157 #else
  158         M_COPY_PKTHDR(n, m);
  159 #endif
  160         len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
  161         if (txflag) {
  162                 n->m_pkthdr.len += len;
  163         } else {
  164                 n->m_pkthdr.len -= len;
  165                 left -= len;
  166         }
  167         n->m_len = MHLEN;
  168         if (n->m_pkthdr.len >= MINCLSIZE) {
  169                 MCLGET(n, M_DONTWAIT);
  170                 if (n->m_flags & M_EXT)
  171                         n->m_len = n->m_ext.ext_size;
  172         }
  173         len = sizeof(struct ieee80211_frame);
  174         memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
  175         wh = mtod(n, struct ieee80211_frame *);
  176         left -= len;
  177         moff = len;
  178         noff = len;
  179         if (txflag) {
  180                 kid = ic->ic_wep_txkey;
  181                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
  182                 iv = ic->ic_iv;
  183                 /*
  184                  * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
  185                  * (B, 255, N) with 3 <= B < 8
  186                  */
  187                 if (iv >= 0x03ff00 &&
  188                     (iv & 0xf8ff00) == 0x00ff00)
  189                         iv += 0x000100;
  190                 ic->ic_iv = iv + 1;
  191                 /* put iv in little endian to prepare 802.11i */
  192                 ivp = mtod(n, u_int8_t *) + noff;
  193                 for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
  194                         ivp[i] = iv & 0xff;
  195                         iv >>= 8;
  196                 }
  197                 ivp[IEEE80211_WEP_IVLEN] = kid << 6;    /* pad and keyid */
  198                 noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
  199         } else {
  200                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
  201                 ivp = mtod(m, u_int8_t *) + moff;
  202                 kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
  203                 moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
  204         }
  205         memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
  206         memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
  207             ic->ic_nw_keys[kid].wk_len);
  208         arc4_setkey(ctx, keybuf,
  209             IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
  210 
  211         /* encrypt with calculating CRC */
  212         crc = ~0;
  213         while (left > 0) {
  214                 len = m->m_len - moff;
  215                 if (len == 0) {
  216                         m = m->m_next;
  217                         moff = 0;
  218                         continue;
  219                 }
  220                 if (len > n->m_len - noff) {
  221                         len = n->m_len - noff;
  222                         if (len == 0) {
  223                                 MGET(n->m_next, M_DONTWAIT, n->m_type);
  224                                 if (n->m_next == NULL) {
  225                                         if (txflag)
  226                                                 ic->ic_stats.is_tx_nombuf++;
  227                                         else
  228                                                 ic->ic_stats.is_rx_nombuf++;
  229                                         goto fail;
  230                                 }
  231                                 n = n->m_next;
  232                                 n->m_len = MLEN;
  233                                 if (left >= MINCLSIZE) {
  234                                         MCLGET(n, M_DONTWAIT);
  235                                         if (n->m_flags & M_EXT)
  236                                                 n->m_len = n->m_ext.ext_size;
  237                                 }
  238                                 noff = 0;
  239                                 continue;
  240                         }
  241                 }
  242                 if (len > left)
  243                         len = left;
  244                 arc4_encrypt(ctx, mtod(n, caddr_t) + noff,
  245                     mtod(m, caddr_t) + moff, len);
  246                 if (txflag)
  247                         crc = ieee80211_crc_update(crc,
  248                             mtod(m, u_int8_t *) + moff, len);
  249                 else
  250                         crc = ieee80211_crc_update(crc,
  251                             mtod(n, u_int8_t *) + noff, len);
  252                 left -= len;
  253                 moff += len;
  254                 noff += len;
  255         }
  256         crc = ~crc;
  257         if (txflag) {
  258                 *(u_int32_t *)crcbuf = htole32(crc);
  259                 if (n->m_len >= noff + sizeof(crcbuf))
  260                         n->m_len = noff + sizeof(crcbuf);
  261                 else {
  262                         n->m_len = noff;
  263                         MGET(n->m_next, M_DONTWAIT, n->m_type);
  264                         if (n->m_next == NULL) {
  265                                 ic->ic_stats.is_tx_nombuf++;
  266                                 goto fail;
  267                         }
  268                         n = n->m_next;
  269                         n->m_len = sizeof(crcbuf);
  270                         noff = 0;
  271                 }
  272                 arc4_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
  273                     sizeof(crcbuf));
  274         } else {
  275                 n->m_len = noff;
  276                 for (noff = 0; noff < sizeof(crcbuf); noff += len) {
  277                         len = sizeof(crcbuf) - noff;
  278                         if (len > m->m_len - moff)
  279                                 len = m->m_len - moff;
  280                         if (len > 0)
  281                                 arc4_encrypt(ctx, crcbuf + noff,
  282                                     mtod(m, caddr_t) + moff, len);
  283                         m = m->m_next;
  284                         moff = 0;
  285                 }
  286                 if (crc != le32toh(*(u_int32_t *)crcbuf)) {
  287 #ifdef IEEE80211_DEBUG
  288                         if (ieee80211_debug) {
  289                                 if_printf(ifp, "decrypt CRC error\n");
  290                                 if (ieee80211_debug > 1)
  291                                         ieee80211_dump_pkt(n0->m_data,
  292                                             n0->m_len, -1, -1);
  293                         }
  294 #endif
  295                         ic->ic_stats.is_rx_decryptcrc++;
  296                         goto fail;
  297                 }
  298         }
  299         m_freem(m0);
  300         return n0;
  301 
  302   fail:
  303         m_freem(m0);
  304         m_freem(n0);
  305         return NULL;
  306 }
  307 
  308 /*
  309  * CRC 32 -- routine from RFC 2083
  310  */
  311 
  312 /* Table of CRCs of all 8-bit messages */
  313 static u_int32_t ieee80211_crc_table[256];
  314 
  315 /* Make the table for a fast CRC. */
  316 static void
  317 ieee80211_crc_init(void)
  318 {
  319         u_int32_t c;
  320         int n, k;
  321 
  322         for (n = 0; n < 256; n++) {
  323                 c = (u_int32_t)n;
  324                 for (k = 0; k < 8; k++) {
  325                         if (c & 1)
  326                                 c = 0xedb88320UL ^ (c >> 1);
  327                         else
  328                                 c = c >> 1;
  329                 }
  330                 ieee80211_crc_table[n] = c;
  331         }
  332 }
  333 
  334 /*
  335  * Update a running CRC with the bytes buf[0..len-1]--the CRC
  336  * should be initialized to all 1's, and the transmitted value
  337  * is the 1's complement of the final running CRC
  338  */
  339 
  340 static u_int32_t
  341 ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
  342 {
  343         u_int8_t *endbuf;
  344 
  345         for (endbuf = buf + len; buf < endbuf; buf++)
  346                 crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
  347         return crc;
  348 }

Cache object: fc19c0ea17847ce31ec40392231c07da


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