Annotation of sys/net80211/ieee80211_crypto.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ieee80211_crypto.c,v 1.31 2007/08/03 16:51:06 damien Exp $ */
! 2: /* $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2001 Atsushi Onoe
! 6: * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
! 7: * Copyright (c) 2007 Damien Bergamini
! 8: * All rights reserved.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 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 "bpfilter.h"
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/systm.h>
! 37: #include <sys/mbuf.h>
! 38: #include <sys/malloc.h>
! 39: #include <sys/kernel.h>
! 40: #include <sys/socket.h>
! 41: #include <sys/sockio.h>
! 42: #include <sys/endian.h>
! 43: #include <sys/errno.h>
! 44: #include <sys/proc.h>
! 45: #include <sys/sysctl.h>
! 46:
! 47: #include <net/if.h>
! 48: #include <net/if_dl.h>
! 49: #include <net/if_media.h>
! 50: #include <net/if_arp.h>
! 51: #include <net/if_llc.h>
! 52:
! 53: #if NBPFILTER > 0
! 54: #include <net/bpf.h>
! 55: #endif
! 56:
! 57: #ifdef INET
! 58: #include <netinet/in.h>
! 59: #include <netinet/if_ether.h>
! 60: #endif
! 61:
! 62: #include <net80211/ieee80211_var.h>
! 63:
! 64: #include <dev/rndvar.h>
! 65: #include <crypto/arc4.h>
! 66: #include <crypto/md5.h>
! 67: #include <crypto/sha1.h>
! 68: #include <crypto/rijndael.h>
! 69:
! 70: struct vector {
! 71: const void *base;
! 72: size_t len;
! 73: };
! 74:
! 75: void ieee80211_crc_init(void);
! 76: u_int32_t ieee80211_crc_update(u_int32_t, const u_int8_t *, int);
! 77: struct mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *, struct mbuf *,
! 78: struct ieee80211_key *);
! 79: struct mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *, struct mbuf *,
! 80: struct ieee80211_key *);
! 81: struct mbuf *ieee80211_tkip_encrypt(struct ieee80211com *, struct mbuf *,
! 82: struct ieee80211_key *);
! 83: struct mbuf *ieee80211_tkip_decrypt(struct ieee80211com *, struct mbuf *,
! 84: struct ieee80211_key *);
! 85: void ieee80211_aes_key_wrap(const u_int8_t *, size_t, const u_int8_t *,
! 86: size_t, u_int8_t *);
! 87: int ieee80211_aes_key_unwrap(const u_int8_t *, size_t, const u_int8_t *,
! 88: u_int8_t *, size_t);
! 89: void ieee80211_hmac_md5_v(const struct vector *, int, const u_int8_t *,
! 90: size_t, u_int8_t digest[]);
! 91: void ieee80211_hmac_md5(const u_int8_t *, size_t, const u_int8_t *, size_t,
! 92: u_int8_t digest[]);
! 93: void ieee80211_hmac_sha1_v(const struct vector *, int, const u_int8_t *,
! 94: size_t, u_int8_t digest[]);
! 95: void ieee80211_hmac_sha1(const u_int8_t *, size_t, const u_int8_t *, size_t,
! 96: u_int8_t digest[]);
! 97: void ieee80211_prf(const u_int8_t *, size_t, struct vector *, int,
! 98: u_int8_t *, size_t);
! 99: void ieee80211_derive_pmkid(const u_int8_t *, size_t, const u_int8_t *,
! 100: const u_int8_t *, u_int8_t *);
! 101: void ieee80211_derive_gtk(const u_int8_t *, size_t, const u_int8_t *,
! 102: const u_int8_t *, u_int8_t *, size_t);
! 103:
! 104: void
! 105: ieee80211_crypto_attach(struct ifnet *ifp)
! 106: {
! 107: struct ieee80211com *ic = (void *)ifp;
! 108:
! 109: ieee80211_crc_init();
! 110:
! 111: /* initialize 256-bit global key counter to a random value */
! 112: get_random_bytes(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN);
! 113: }
! 114:
! 115: void
! 116: ieee80211_crypto_detach(struct ifnet *ifp)
! 117: {
! 118: struct ieee80211com *ic = (void *)ifp;
! 119:
! 120: if (ic->ic_wep_ctx != NULL) {
! 121: free(ic->ic_wep_ctx, M_DEVBUF);
! 122: ic->ic_wep_ctx = NULL;
! 123: }
! 124: }
! 125:
! 126: struct mbuf *
! 127: ieee80211_encrypt(struct ieee80211com *ic, struct mbuf *m0,
! 128: struct ieee80211_node *ni)
! 129: {
! 130: struct ieee80211_frame *wh;
! 131: struct ieee80211_key *k;
! 132:
! 133: /* select the key for encryption */
! 134: wh = mtod(m0, struct ieee80211_frame *);
! 135: if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
! 136: ni->ni_pairwise_cipher == IEEE80211_CIPHER_USEGROUP)
! 137: k = &ic->ic_nw_keys[ic->ic_wep_txkey];
! 138: else
! 139: k = &ni->ni_pairwise_key;
! 140:
! 141: switch (k->k_cipher) {
! 142: case IEEE80211_CIPHER_WEP40:
! 143: case IEEE80211_CIPHER_WEP104:
! 144: m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 1);
! 145: break;
! 146: case IEEE80211_CIPHER_TKIP:
! 147: m0 = ieee80211_tkip_encrypt(ic, m0, k);
! 148: break;
! 149: case IEEE80211_CIPHER_CCMP:
! 150: m0 = ieee80211_ccmp_encrypt(ic, m0, k);
! 151: break;
! 152: default:
! 153: /* should not get there */
! 154: m_freem(m0);
! 155: m0 = NULL;
! 156: }
! 157: return m0;
! 158: }
! 159:
! 160: struct mbuf *
! 161: ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
! 162: struct ieee80211_node *ni)
! 163: {
! 164: struct ieee80211_frame *wh;
! 165: struct ieee80211_key *k;
! 166:
! 167: /* select the key for decryption */
! 168: wh = mtod(m0, struct ieee80211_frame *);
! 169: if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
! 170: ni->ni_pairwise_cipher == IEEE80211_CIPHER_USEGROUP) {
! 171: size_t hdrlen = sizeof(*wh); /* XXX QoS */
! 172: u_int8_t *ivp = (u_int8_t *)wh + hdrlen;
! 173: /* key identifier is always located at the same index */
! 174: int kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
! 175: k = &ic->ic_nw_keys[kid];
! 176: } else
! 177: k = &ni->ni_pairwise_key;
! 178:
! 179: switch (k->k_cipher) {
! 180: case IEEE80211_CIPHER_WEP40:
! 181: case IEEE80211_CIPHER_WEP104:
! 182: m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 0);
! 183: break;
! 184: case IEEE80211_CIPHER_TKIP:
! 185: m0 = ieee80211_tkip_decrypt(ic, m0, k);
! 186: break;
! 187: case IEEE80211_CIPHER_CCMP:
! 188: m0 = ieee80211_ccmp_decrypt(ic, m0, k);
! 189: break;
! 190: default:
! 191: /* should not get there */
! 192: m_freem(m0);
! 193: m0 = NULL;
! 194: }
! 195: return m0;
! 196: }
! 197:
! 198: #define IEEE80211_CCMP_HDRLEN 8
! 199: #define IEEE80211_CCMP_MICLEN 8
! 200:
! 201: struct mbuf *
! 202: ieee80211_ccmp_encrypt(struct ieee80211com *ic, struct mbuf *m0,
! 203: struct ieee80211_key *k)
! 204: {
! 205: struct ieee80211_frame *wh;
! 206: size_t hdrlen = sizeof(*wh); /* XXX QoS */
! 207: u_int8_t *ivp;
! 208:
! 209: M_PREPEND(m0, IEEE80211_CCMP_HDRLEN, M_NOWAIT);
! 210: if (m0 == NULL)
! 211: return m0;
! 212: wh = mtod(m0, struct ieee80211_frame *);
! 213: ovbcopy(mtod(m0, u_int8_t *) + IEEE80211_CCMP_HDRLEN, wh, hdrlen);
! 214: ivp = (u_int8_t *)wh + hdrlen;
! 215:
! 216: k->k_tsc++; /* increment the 48-bit PN */
! 217: ivp[0] = k->k_tsc; /* PN0 */
! 218: ivp[1] = k->k_tsc >> 8; /* PN1 */
! 219: ivp[2] = 0; /* Rsvd */
! 220: ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; /* KeyID | ExtIV */
! 221: ivp[4] = k->k_tsc >> 16; /* PN2 */
! 222: ivp[5] = k->k_tsc >> 24; /* PN3 */
! 223: ivp[6] = k->k_tsc >> 32; /* PN4 */
! 224: ivp[7] = k->k_tsc >> 40; /* PN5 */
! 225:
! 226: /* XXX encrypt payload if HW encryption not supported */
! 227:
! 228: return m0;
! 229: }
! 230:
! 231: struct mbuf *
! 232: ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
! 233: struct ieee80211_key *k)
! 234: {
! 235: struct ieee80211_frame *wh;
! 236: size_t hdrlen = sizeof(*wh); /* XXX QoS */
! 237: u_int64_t pn;
! 238: u_int8_t *ivp;
! 239:
! 240: wh = mtod(m0, struct ieee80211_frame *);
! 241: ivp = (u_int8_t *)wh + hdrlen;
! 242:
! 243: /* check that ExtIV bit is be set */
! 244: if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
! 245: m_freem(m0);
! 246: return NULL;
! 247: }
! 248: /* extract the 48-bit PN from the CCMP header */
! 249: pn = (u_int64_t)ivp[0] |
! 250: (u_int64_t)ivp[1] << 8 |
! 251: (u_int64_t)ivp[4] << 16 |
! 252: (u_int64_t)ivp[5] << 24 |
! 253: (u_int64_t)ivp[6] << 32 |
! 254: (u_int64_t)ivp[7] << 40;
! 255: /* NB: the keys are refreshed, we'll never overflow the 48 bits */
! 256: if (pn <= k->k_rsc) {
! 257: /* replayed frame, discard */
! 258: /* XXX statistics */
! 259: m_freem(m0);
! 260: return NULL;
! 261: }
! 262:
! 263: /* XXX decrypt payload if HW encryption not supported */
! 264:
! 265: ovbcopy(mtod(m0, u_int8_t *),
! 266: mtod(m0, u_int8_t *) + IEEE80211_CCMP_HDRLEN, hdrlen);
! 267: m_adj(m0, IEEE80211_CCMP_HDRLEN);
! 268: m_adj(m0, -IEEE80211_CCMP_MICLEN);
! 269:
! 270: /* update last seen packet number */
! 271: k->k_rsc = pn;
! 272:
! 273: return m0;
! 274: }
! 275:
! 276: #define IEEE80211_TKIP_HDRLEN 8
! 277: #define IEEE80211_TKIP_MICLEN 8
! 278: #define IEEE80211_TKIP_ICVLEN 4
! 279:
! 280: struct mbuf *
! 281: ieee80211_tkip_encrypt(struct ieee80211com *ic, struct mbuf *m0,
! 282: struct ieee80211_key *k)
! 283: {
! 284: struct ieee80211_frame *wh;
! 285: size_t hdrlen = sizeof(*wh); /* XXX QoS */
! 286: u_int8_t *ivp;
! 287:
! 288: M_PREPEND(m0, IEEE80211_TKIP_HDRLEN, M_NOWAIT);
! 289: if (m0 == NULL)
! 290: return m0;
! 291: wh = mtod(m0, struct ieee80211_frame *);
! 292: ovbcopy(mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, wh, hdrlen);
! 293: ivp = (u_int8_t *)wh + hdrlen;
! 294:
! 295: ivp[0] = k->k_tsc >> 8; /* TSC1 */
! 296: /* WEP Seed = (TSC1 | 0x20) & 0x7f (see 8.3.2.2) */
! 297: ivp[1] = (ivp[0] | 0x20) & 0x7f;
! 298: ivp[2] = k->k_tsc; /* TSC0 */
! 299: ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; /* KeyID | ExtIV */
! 300: ivp[4] = k->k_tsc >> 16; /* TSC2 */
! 301: ivp[5] = k->k_tsc >> 24; /* TSC3 */
! 302: ivp[6] = k->k_tsc >> 32; /* TSC4 */
! 303: ivp[7] = k->k_tsc >> 40; /* TSC5 */
! 304:
! 305: /* XXX encrypt payload if HW encryption not supported */
! 306:
! 307: k->k_tsc++; /* increment the 48-bit TSC */
! 308:
! 309: return m0;
! 310: }
! 311:
! 312: struct mbuf *
! 313: ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
! 314: struct ieee80211_key *k)
! 315: {
! 316: struct ieee80211_frame *wh;
! 317: size_t hdrlen = sizeof(*wh); /* XXX QoS */
! 318: u_int64_t tsc;
! 319: u_int8_t *ivp;
! 320:
! 321: wh = mtod(m0, struct ieee80211_frame *);
! 322: ivp = (u_int8_t *)wh + hdrlen;
! 323:
! 324: /* check that ExtIV bit is be set */
! 325: if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
! 326: m_freem(m0);
! 327: return NULL;
! 328: }
! 329: /* extract the 48-bit TSC from the TKIP header */
! 330: tsc = (u_int64_t)ivp[2] |
! 331: (u_int64_t)ivp[0] << 8 |
! 332: (u_int64_t)ivp[4] << 16 |
! 333: (u_int64_t)ivp[5] << 24 |
! 334: (u_int64_t)ivp[6] << 32 |
! 335: (u_int64_t)ivp[7] << 40;
! 336: /* NB: the keys are refreshed, we'll never overflow the 48 bits */
! 337: if (tsc <= k->k_rsc) {
! 338: /* replayed frame, discard */
! 339: /* XXX statistics */
! 340: m_freem(m0);
! 341: return NULL;
! 342: }
! 343:
! 344: /* XXX decrypt payload if HW encryption not supported */
! 345:
! 346: ovbcopy(mtod(m0, u_int8_t *),
! 347: mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, hdrlen);
! 348: m_adj(m0, IEEE80211_TKIP_HDRLEN);
! 349: m_adj(m0, -IEEE80211_TKIP_ICVLEN);
! 350:
! 351: /* update last seen packet number */
! 352: k->k_rsc = tsc;
! 353:
! 354: return m0;
! 355: }
! 356:
! 357: /* Round up to a multiple of IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN */
! 358: #define klen_round(x) \
! 359: (((x) + (IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN - 1)) & \
! 360: ~(IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN - 1))
! 361:
! 362: struct mbuf *
! 363: ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
! 364: {
! 365: struct ieee80211com *ic = (void *)ifp;
! 366: struct mbuf *m, *n, *n0;
! 367: struct ieee80211_frame *wh;
! 368: int i, left, len, moff, noff, kid;
! 369: u_int32_t iv, crc;
! 370: u_int8_t *ivp;
! 371: void *ctx;
! 372: u_int8_t keybuf[klen_round(IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE)];
! 373: u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
! 374:
! 375: n0 = NULL;
! 376: if ((ctx = ic->ic_wep_ctx) == NULL) {
! 377: ctx = malloc(sizeof(struct rc4_ctx), M_DEVBUF, M_NOWAIT);
! 378: if (ctx == NULL) {
! 379: ic->ic_stats.is_crypto_nomem++;
! 380: goto fail;
! 381: }
! 382: ic->ic_wep_ctx = ctx;
! 383: }
! 384: m = m0;
! 385: left = m->m_pkthdr.len;
! 386: MGET(n, M_DONTWAIT, m->m_type);
! 387: n0 = n;
! 388: if (n == NULL) {
! 389: if (txflag)
! 390: ic->ic_stats.is_tx_nombuf++;
! 391: else
! 392: ic->ic_stats.is_rx_nombuf++;
! 393: goto fail;
! 394: }
! 395: M_DUP_PKTHDR(n, m);
! 396: len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
! 397: if (txflag) {
! 398: n->m_pkthdr.len += len;
! 399: } else {
! 400: n->m_pkthdr.len -= len;
! 401: left -= len;
! 402: }
! 403: n->m_len = MHLEN;
! 404: if (n->m_pkthdr.len >= MINCLSIZE) {
! 405: MCLGET(n, M_DONTWAIT);
! 406: if (n->m_flags & M_EXT)
! 407: n->m_len = n->m_ext.ext_size;
! 408: }
! 409: wh = mtod(m, struct ieee80211_frame *);
! 410: if ((wh->i_fc[0] &
! 411: (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
! 412: (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
! 413: len = sizeof(struct ieee80211_qosframe);
! 414: else
! 415: len = sizeof(struct ieee80211_frame);
! 416: memcpy(mtod(n, caddr_t), wh, len);
! 417: wh = mtod(n, struct ieee80211_frame *);
! 418: left -= len;
! 419: moff = len;
! 420: noff = len;
! 421: if (txflag) {
! 422: kid = ic->ic_wep_txkey;
! 423: wh->i_fc[1] |= IEEE80211_FC1_WEP;
! 424: iv = ic->ic_iv ? ic->ic_iv : arc4random();
! 425: /*
! 426: * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
! 427: * (B, 255, N) with 3 <= B < 8
! 428: */
! 429: if (iv >= 0x03ff00 &&
! 430: (iv & 0xf8ff00) == 0x00ff00)
! 431: iv += 0x000100;
! 432: ic->ic_iv = iv + 1;
! 433: /* put iv in little endian to prepare 802.11i */
! 434: ivp = mtod(n, u_int8_t *) + noff;
! 435: for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
! 436: ivp[i] = iv & 0xff;
! 437: iv >>= 8;
! 438: }
! 439: ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */
! 440: noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
! 441: } else {
! 442: wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
! 443: ivp = mtod(m, u_int8_t *) + moff;
! 444: kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
! 445: moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
! 446: }
! 447:
! 448: /*
! 449: * Copy the IV and the key material. The input key has been padded
! 450: * with zeros by the ioctl. The output key buffer length is rounded
! 451: * to a multiple of 64bit to allow variable length keys padded by
! 452: * zeros.
! 453: */
! 454: bzero(&keybuf, sizeof(keybuf));
! 455: memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
! 456: memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].k_key,
! 457: ic->ic_nw_keys[kid].k_len);
! 458: len = klen_round(IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].k_len);
! 459: rc4_keysetup(ctx, keybuf, len);
! 460:
! 461: /* encrypt with calculating CRC */
! 462: crc = ~0;
! 463: while (left > 0) {
! 464: len = m->m_len - moff;
! 465: if (len == 0) {
! 466: m = m->m_next;
! 467: moff = 0;
! 468: continue;
! 469: }
! 470: if (len > n->m_len - noff) {
! 471: len = n->m_len - noff;
! 472: if (len == 0) {
! 473: MGET(n->m_next, M_DONTWAIT, n->m_type);
! 474: if (n->m_next == NULL) {
! 475: if (txflag)
! 476: ic->ic_stats.is_tx_nombuf++;
! 477: else
! 478: ic->ic_stats.is_rx_nombuf++;
! 479: goto fail;
! 480: }
! 481: n = n->m_next;
! 482: n->m_len = MLEN;
! 483: if (left >= MINCLSIZE) {
! 484: MCLGET(n, M_DONTWAIT);
! 485: if (n->m_flags & M_EXT)
! 486: n->m_len = n->m_ext.ext_size;
! 487: }
! 488: noff = 0;
! 489: continue;
! 490: }
! 491: }
! 492: if (len > left)
! 493: len = left;
! 494: rc4_crypt(ctx, mtod(m, caddr_t) + moff,
! 495: mtod(n, caddr_t) + noff, len);
! 496: if (txflag)
! 497: crc = ieee80211_crc_update(crc,
! 498: mtod(m, u_int8_t *) + moff, len);
! 499: else
! 500: crc = ieee80211_crc_update(crc,
! 501: mtod(n, u_int8_t *) + noff, len);
! 502: left -= len;
! 503: moff += len;
! 504: noff += len;
! 505: }
! 506: crc = ~crc;
! 507: if (txflag) {
! 508: *(u_int32_t *)crcbuf = htole32(crc);
! 509: if (n->m_len >= noff + sizeof(crcbuf))
! 510: n->m_len = noff + sizeof(crcbuf);
! 511: else {
! 512: n->m_len = noff;
! 513: MGET(n->m_next, M_DONTWAIT, n->m_type);
! 514: if (n->m_next == NULL) {
! 515: ic->ic_stats.is_tx_nombuf++;
! 516: goto fail;
! 517: }
! 518: n = n->m_next;
! 519: n->m_len = sizeof(crcbuf);
! 520: noff = 0;
! 521: }
! 522: rc4_crypt(ctx, crcbuf, mtod(n, caddr_t) + noff,
! 523: sizeof(crcbuf));
! 524: } else {
! 525: n->m_len = noff;
! 526: for (noff = 0; noff < sizeof(crcbuf); noff += len) {
! 527: len = sizeof(crcbuf) - noff;
! 528: if (len > m->m_len - moff)
! 529: len = m->m_len - moff;
! 530: if (len > 0)
! 531: rc4_crypt(ctx, mtod(m, caddr_t) + moff,
! 532: crcbuf + noff, len);
! 533: m = m->m_next;
! 534: moff = 0;
! 535: }
! 536: if (crc != letoh32(*(u_int32_t *)crcbuf)) {
! 537: #ifdef IEEE80211_DEBUG
! 538: if (ieee80211_debug) {
! 539: printf("%s: decrypt CRC error\n",
! 540: ifp->if_xname);
! 541: if (ieee80211_debug > 1)
! 542: ieee80211_dump_pkt(n0->m_data,
! 543: n0->m_len, -1, -1);
! 544: }
! 545: #endif
! 546: ic->ic_stats.is_rx_decryptcrc++;
! 547: goto fail;
! 548: }
! 549: }
! 550: m_freem(m0);
! 551: return n0;
! 552:
! 553: fail:
! 554: m_freem(m0);
! 555: m_freem(n0);
! 556: return NULL;
! 557: }
! 558:
! 559: /*
! 560: * CRC 32 -- routine from RFC 2083
! 561: */
! 562:
! 563: /* Table of CRCs of all 8-bit messages */
! 564: static u_int32_t ieee80211_crc_table[256];
! 565:
! 566: /* Make the table for a fast CRC. */
! 567: void
! 568: ieee80211_crc_init(void)
! 569: {
! 570: u_int32_t c;
! 571: int n, k;
! 572:
! 573: for (n = 0; n < 256; n++) {
! 574: c = (u_int32_t)n;
! 575: for (k = 0; k < 8; k++) {
! 576: if (c & 1)
! 577: c = 0xedb88320UL ^ (c >> 1);
! 578: else
! 579: c = c >> 1;
! 580: }
! 581: ieee80211_crc_table[n] = c;
! 582: }
! 583: }
! 584:
! 585: /*
! 586: * Update a running CRC with the bytes buf[0..len-1]--the CRC
! 587: * should be initialized to all 1's, and the transmitted value
! 588: * is the 1's complement of the final running CRC
! 589: */
! 590: u_int32_t
! 591: ieee80211_crc_update(u_int32_t crc, const u_int8_t *buf, int len)
! 592: {
! 593: const u_int8_t *endbuf;
! 594:
! 595: for (endbuf = buf + len; buf < endbuf; buf++)
! 596: crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
! 597: return crc;
! 598: }
! 599:
! 600: /*
! 601: * AES Key Wrap Algorithm (see RFC 3394).
! 602: */
! 603: static const u_int8_t aes_key_wrap_iv[8] =
! 604: { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
! 605:
! 606: void
! 607: ieee80211_aes_key_wrap(const u_int8_t *kek, size_t kek_len, const u_int8_t *pt,
! 608: size_t len, u_int8_t *ct)
! 609: {
! 610: rijndael_ctx ctx;
! 611: u_int8_t *a, *r, ar[16];
! 612: u_int64_t t, b[2];
! 613: size_t i;
! 614: int j;
! 615:
! 616: /* allow ciphertext and plaintext to overlap (ct == pt) */
! 617: ovbcopy(pt, ct + 8, len * 8);
! 618: a = ct;
! 619: memcpy(a, aes_key_wrap_iv, 8); /* default IV */
! 620:
! 621: rijndael_set_key_enc_only(&ctx, (u_int8_t *)kek, kek_len * 8);
! 622:
! 623: for (j = 0, t = 1; j < 6; j++) {
! 624: r = ct + 8;
! 625: for (i = 0; i < len; i++, t++) {
! 626: memcpy(ar, a, 8);
! 627: memcpy(ar + 8, r, 8);
! 628: rijndael_encrypt(&ctx, ar, (u_int8_t *)b);
! 629: b[0] ^= htobe64(t);
! 630: memcpy(a, &b[0], 8);
! 631: memcpy(r, &b[1], 8);
! 632:
! 633: r += 8;
! 634: }
! 635: }
! 636: }
! 637:
! 638: int
! 639: ieee80211_aes_key_unwrap(const u_int8_t *kek, size_t kek_len,
! 640: const u_int8_t *ct, u_int8_t *pt, size_t len)
! 641: {
! 642: rijndael_ctx ctx;
! 643: u_int8_t a[8], *r, b[16];
! 644: u_int64_t t, ar[2];
! 645: size_t i;
! 646: int j;
! 647:
! 648: memcpy(a, ct, 8);
! 649: /* allow ciphertext and plaintext to overlap (ct == pt) */
! 650: ovbcopy(ct + 8, pt, len * 8);
! 651:
! 652: rijndael_set_key(&ctx, (u_int8_t *)kek, kek_len * 8);
! 653:
! 654: for (j = 0, t = 6 * len; j < 6; j++) {
! 655: r = pt + (len - 1) * 8;
! 656: for (i = 0; i < len; i++, t--) {
! 657: memcpy(&ar[0], a, 8);
! 658: ar[0] ^= htobe64(t);
! 659: memcpy(&ar[1], r, 8);
! 660: rijndael_decrypt(&ctx, (u_int8_t *)ar, b);
! 661: memcpy(a, b, 8);
! 662: memcpy(r, b + 8, 8);
! 663:
! 664: r -= 8;
! 665: }
! 666: }
! 667: return memcmp(a, aes_key_wrap_iv, 8) != 0;
! 668: }
! 669:
! 670: void
! 671: ieee80211_hmac_md5_v(const struct vector *vec, int vcnt, const u_int8_t *key,
! 672: size_t key_len, u_int8_t digest[MD5_DIGEST_LENGTH])
! 673: {
! 674: MD5_CTX ctx;
! 675: u_int8_t k_pad[MD5_BLOCK_LENGTH];
! 676: u_int8_t tk[MD5_DIGEST_LENGTH];
! 677: int i;
! 678:
! 679: if (key_len > MD5_BLOCK_LENGTH) {
! 680: MD5Init(&ctx);
! 681: MD5Update(&ctx, (u_int8_t *)key, key_len);
! 682: MD5Final(tk, &ctx);
! 683:
! 684: key = tk;
! 685: key_len = MD5_DIGEST_LENGTH;
! 686: }
! 687:
! 688: bzero(k_pad, sizeof k_pad);
! 689: bcopy(key, k_pad, key_len);
! 690: for (i = 0; i < MD5_BLOCK_LENGTH; i++)
! 691: k_pad[i] ^= 0x36;
! 692:
! 693: MD5Init(&ctx);
! 694: MD5Update(&ctx, k_pad, MD5_BLOCK_LENGTH);
! 695: for (i = 0; i < vcnt; i++)
! 696: MD5Update(&ctx, (u_int8_t *)vec[i].base, vec[i].len);
! 697: MD5Final(digest, &ctx);
! 698:
! 699: bzero(k_pad, sizeof k_pad);
! 700: bcopy(key, k_pad, key_len);
! 701: for (i = 0; i < MD5_BLOCK_LENGTH; i++)
! 702: k_pad[i] ^= 0x5c;
! 703:
! 704: MD5Init(&ctx);
! 705: MD5Update(&ctx, k_pad, MD5_BLOCK_LENGTH);
! 706: MD5Update(&ctx, digest, MD5_DIGEST_LENGTH);
! 707: MD5Final(digest, &ctx);
! 708: }
! 709:
! 710: void
! 711: ieee80211_hmac_md5(const u_int8_t *text, size_t text_len, const u_int8_t *key,
! 712: size_t key_len, u_int8_t digest[MD5_DIGEST_LENGTH])
! 713: {
! 714: struct vector vec;
! 715: vec.base = text;
! 716: vec.len = text_len;
! 717: ieee80211_hmac_md5_v(&vec, 1, key, key_len, digest);
! 718: }
! 719:
! 720: void
! 721: ieee80211_hmac_sha1_v(const struct vector *vec, int vcnt, const u_int8_t *key,
! 722: size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
! 723: {
! 724: SHA1_CTX ctx;
! 725: u_int8_t k_pad[SHA1_BLOCK_LENGTH];
! 726: u_int8_t tk[SHA1_DIGEST_LENGTH];
! 727: int i;
! 728:
! 729: if (key_len > SHA1_BLOCK_LENGTH) {
! 730: SHA1Init(&ctx);
! 731: SHA1Update(&ctx, (u_int8_t *)key, key_len);
! 732: SHA1Final(tk, &ctx);
! 733:
! 734: key = tk;
! 735: key_len = SHA1_DIGEST_LENGTH;
! 736: }
! 737:
! 738: bzero(k_pad, sizeof k_pad);
! 739: bcopy(key, k_pad, key_len);
! 740: for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
! 741: k_pad[i] ^= 0x36;
! 742:
! 743: SHA1Init(&ctx);
! 744: SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
! 745: for (i = 0; i < vcnt; i++)
! 746: SHA1Update(&ctx, (u_int8_t *)vec[i].base, vec[i].len);
! 747: SHA1Final(digest, &ctx);
! 748:
! 749: bzero(k_pad, sizeof k_pad);
! 750: bcopy(key, k_pad, key_len);
! 751: for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
! 752: k_pad[i] ^= 0x5c;
! 753:
! 754: SHA1Init(&ctx);
! 755: SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
! 756: SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
! 757: SHA1Final(digest, &ctx);
! 758: }
! 759:
! 760: void
! 761: ieee80211_hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
! 762: size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
! 763: {
! 764: struct vector vec;
! 765: vec.base = text;
! 766: vec.len = text_len;
! 767: ieee80211_hmac_sha1_v(&vec, 1, key, key_len, digest);
! 768: }
! 769:
! 770: /*
! 771: * SHA1-based Pseudo-Random Function (see 8.5.1.1).
! 772: */
! 773: void
! 774: ieee80211_prf(const u_int8_t *key, size_t key_len, struct vector *vec,
! 775: int vcnt, u_int8_t *output, size_t len)
! 776: {
! 777: u_int8_t hash[SHA1_DIGEST_LENGTH];
! 778: u_int8_t count = 0;
! 779:
! 780: /* single octet count, starts at 0 */
! 781: vec[vcnt].base = &count;
! 782: vec[vcnt].len = 1;
! 783: vcnt++;
! 784:
! 785: while (len > SHA1_DIGEST_LENGTH) {
! 786: ieee80211_hmac_sha1_v(vec, vcnt, key, key_len, output);
! 787: count++;
! 788:
! 789: output += SHA1_DIGEST_LENGTH;
! 790: len -= SHA1_DIGEST_LENGTH;
! 791: }
! 792: if (len > 0) {
! 793: ieee80211_hmac_sha1_v(vec, vcnt, key, key_len, hash);
! 794: /* truncate HMAC-SHA1 to len bytes */
! 795: memcpy(output, hash, len);
! 796: }
! 797: }
! 798:
! 799: /*
! 800: * Derive Pairwise Transient Key (PTK) (see 8.5.1.2).
! 801: */
! 802: void
! 803: ieee80211_derive_ptk(const u_int8_t *pmk, size_t pmk_len, const u_int8_t *aa,
! 804: const u_int8_t *spa, const u_int8_t *anonce, const u_int8_t *snonce,
! 805: u_int8_t *ptk, size_t ptk_len)
! 806: {
! 807: struct vector vec[6]; /* +1 for PRF */
! 808: int ret;
! 809:
! 810: vec[0].base = "Pairwise key expansion";
! 811: vec[0].len = 23; /* include trailing '\0' */
! 812:
! 813: ret = memcmp(aa, spa, IEEE80211_ADDR_LEN) < 0;
! 814: /* Min(AA,SPA) */
! 815: vec[1].base = ret ? aa : spa;
! 816: vec[1].len = IEEE80211_ADDR_LEN;
! 817: /* Max(AA,SPA) */
! 818: vec[2].base = ret ? spa : aa;
! 819: vec[2].len = IEEE80211_ADDR_LEN;
! 820:
! 821: ret = memcmp(anonce, snonce, EAPOL_KEY_NONCE_LEN) < 0;
! 822: /* Min(ANonce,SNonce) */
! 823: vec[3].base = ret ? anonce : snonce;
! 824: vec[3].len = EAPOL_KEY_NONCE_LEN;
! 825: /* Max(ANonce,SNonce) */
! 826: vec[4].base = ret ? snonce : anonce;
! 827: vec[4].len = EAPOL_KEY_NONCE_LEN;
! 828:
! 829: ieee80211_prf(pmk, pmk_len, vec, 5, ptk, ptk_len);
! 830: }
! 831:
! 832: /*
! 833: * Derive Pairwise Master Key Identifier (PMKID) (see 8.5.1.2).
! 834: */
! 835: void
! 836: ieee80211_derive_pmkid(const u_int8_t *pmk, size_t pmk_len, const u_int8_t *aa,
! 837: const u_int8_t *spa, u_int8_t *pmkid)
! 838: {
! 839: struct vector vec[3];
! 840: u_int8_t hash[SHA1_DIGEST_LENGTH];
! 841:
! 842: vec[0].base = "PMK Name";
! 843: vec[0].len = 8; /* does *not* include trailing '\0' */
! 844: vec[1].base = aa;
! 845: vec[1].len = IEEE80211_ADDR_LEN;
! 846: vec[2].base = spa;
! 847: vec[2].len = IEEE80211_ADDR_LEN;
! 848:
! 849: ieee80211_hmac_sha1_v(vec, 3, pmk, pmk_len, hash);
! 850: /* use the first 128 bits of the HMAC-SHA1 */
! 851: memcpy(pmkid, hash, IEEE80211_PMKID_LEN);
! 852: }
! 853:
! 854: /*
! 855: * Derive Group Temporal Key (GTK) (see 8.5.1.3).
! 856: */
! 857: void
! 858: ieee80211_derive_gtk(const u_int8_t *gmk, size_t gmk_len, const u_int8_t *aa,
! 859: const u_int8_t *gnonce, u_int8_t *gtk, size_t gtk_len)
! 860: {
! 861: struct vector vec[4]; /* +1 for PRF */
! 862:
! 863: vec[0].base = "Group key expansion";
! 864: vec[0].len = 20; /* include trailing '\0' */
! 865: vec[1].base = aa;
! 866: vec[1].len = IEEE80211_ADDR_LEN;
! 867: vec[2].base = gnonce;
! 868: vec[2].len = EAPOL_KEY_NONCE_LEN;
! 869:
! 870: ieee80211_prf(gmk, gmk_len, vec, 3, gtk, gtk_len);
! 871: }
! 872:
! 873: /* unaligned big endian access */
! 874: #define BE_READ_2(p) \
! 875: ((u_int16_t) \
! 876: ((((const u_int8_t *)(p))[0] << 8) | \
! 877: (((const u_int8_t *)(p))[1])))
! 878:
! 879: #define BE_WRITE_2(p, v) do { \
! 880: ((u_int8_t *)(p))[0] = (v) >> 8; \
! 881: ((u_int8_t *)(p))[1] = (v) & 0xff; \
! 882: } while (0)
! 883:
! 884: /*
! 885: * Compute the Key MIC field of an EAPOL-Key frame using the specified Key
! 886: * Confirmation Key (KCK). The hash function can be either HMAC-MD5 or
! 887: * HMAC-SHA1 depending on the EAPOL-Key Key Descriptor Version.
! 888: */
! 889: void
! 890: ieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck)
! 891: {
! 892: u_int8_t hash[SHA1_DIGEST_LENGTH];
! 893: u_int16_t len, info;
! 894:
! 895: len = BE_READ_2(key->len) + 4;
! 896: info = BE_READ_2(key->info);
! 897:
! 898: switch (info & EAPOL_KEY_VERSION_MASK) {
! 899: case EAPOL_KEY_DESC_V1:
! 900: ieee80211_hmac_md5((u_int8_t *)key, len, kck, 16, key->mic);
! 901: break;
! 902: case EAPOL_KEY_DESC_V2:
! 903: ieee80211_hmac_sha1((u_int8_t *)key, len, kck, 16, hash);
! 904: /* truncate HMAC-SHA1 to its 128 MSBs */
! 905: memcpy(key->mic, hash, EAPOL_KEY_MIC_LEN);
! 906: break;
! 907: }
! 908: }
! 909:
! 910: /*
! 911: * Check the MIC of a received EAPOL-Key frame using the specified Key
! 912: * Confirmation Key (KCK).
! 913: */
! 914: int
! 915: ieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *key,
! 916: const u_int8_t *kck)
! 917: {
! 918: u_int8_t mic[EAPOL_KEY_MIC_LEN];
! 919:
! 920: memcpy(mic, key->mic, EAPOL_KEY_MIC_LEN);
! 921: memset(key->mic, 0, EAPOL_KEY_MIC_LEN);
! 922: ieee80211_eapol_key_mic(key, kck);
! 923:
! 924: return memcmp(key->mic, mic, EAPOL_KEY_MIC_LEN) != 0;
! 925: }
! 926:
! 927: /*
! 928: * Encrypt the Key Data field of an EAPOL-Key frame using the specified Key
! 929: * Encryption Key (KEK). The encryption algorithm can be either ARC4 or
! 930: * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.
! 931: */
! 932: void
! 933: ieee80211_eapol_key_encrypt(struct ieee80211com *ic,
! 934: struct ieee80211_eapol_key *key, const u_int8_t *kek)
! 935: {
! 936: struct rc4_ctx ctx;
! 937: u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
! 938: u_int16_t len, info;
! 939: u_int8_t *data;
! 940: int n;
! 941:
! 942: len = BE_READ_2(key->paylen);
! 943: info = BE_READ_2(key->info);
! 944: data = (u_int8_t *)(key + 1);
! 945:
! 946: switch (info & EAPOL_KEY_VERSION_MASK) {
! 947: case EAPOL_KEY_DESC_V1:
! 948: /* set IV to the lower 16 octets of our global key counter */
! 949: memcpy(key->iv, ic->ic_globalcnt + 16, 16);
! 950: /* increment our global key counter (256-bit, big-endian) */
! 951: for (n = 31; n >= 0 && ++ic->ic_globalcnt[n] == 0; n--);
! 952:
! 953: /* concatenate the EAPOL-Key IV field and the KEK */
! 954: memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
! 955: memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
! 956:
! 957: rc4_keysetup(&ctx, keybuf, sizeof keybuf);
! 958: /* discard the first 256 octets of the ARC4 key stream */
! 959: rc4_skip(&ctx, RC4STATE);
! 960: rc4_crypt(&ctx, data, data, len);
! 961: break;
! 962: case EAPOL_KEY_DESC_V2:
! 963: if (len < 16 || (len & 7) != 0) {
! 964: /* insert padding */
! 965: n = (len < 16) ? 16 - len : 8 - (len & 7);
! 966: data[len++] = IEEE80211_ELEMID_VENDOR;
! 967: memset(&data[len], 0, n - 1);
! 968: len += n - 1;
! 969: }
! 970: ieee80211_aes_key_wrap(kek, 16, data, len / 8, data);
! 971: len += 8; /* AES Key Wrap adds 8 bytes */
! 972: /* update key data length */
! 973: BE_WRITE_2(key->paylen, len);
! 974: /* update packet body length */
! 975: BE_WRITE_2(key->len, sizeof(*key) + len - 4);
! 976: break;
! 977: }
! 978: }
! 979:
! 980: /*
! 981: * Decrypt the Key Data field of an EAPOL-Key frame using the specified Key
! 982: * Encryption Key (KEK). The encryption algorithm can be either ARC4 or
! 983: * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.
! 984: */
! 985: int
! 986: ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
! 987: const u_int8_t *kek)
! 988: {
! 989: struct rc4_ctx ctx;
! 990: u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
! 991: u_int16_t len, info;
! 992: u_int8_t *data;
! 993:
! 994: len = BE_READ_2(key->paylen);
! 995: info = BE_READ_2(key->info);
! 996: data = (u_int8_t *)(key + 1);
! 997:
! 998: switch (info & EAPOL_KEY_VERSION_MASK) {
! 999: case EAPOL_KEY_DESC_V1:
! 1000: /* concatenate the EAPOL-Key IV field and the KEK */
! 1001: memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
! 1002: memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
! 1003:
! 1004: rc4_keysetup(&ctx, keybuf, sizeof keybuf);
! 1005: /* discard the first 256 octets of the ARC4 key stream */
! 1006: rc4_skip(&ctx, RC4STATE);
! 1007: rc4_crypt(&ctx, data, data, len);
! 1008: return 0;
! 1009: case EAPOL_KEY_DESC_V2:
! 1010: /* Key Data Length must be a multiple of 8 */
! 1011: if (len < 16 + 8 || (len & 7) != 0)
! 1012: return 1;
! 1013: len -= 8; /* AES Key Wrap adds 8 bytes */
! 1014: return ieee80211_aes_key_unwrap(kek, 16, data, data, len / 8);
! 1015: }
! 1016:
! 1017: return 1; /* unknown Key Descriptor Version */
! 1018: }
! 1019:
! 1020: /*
! 1021: * Return the length in bytes of a cipher suite key (see Table 60).
! 1022: */
! 1023: int
! 1024: ieee80211_cipher_keylen(enum ieee80211_cipher cipher)
! 1025: {
! 1026: switch (cipher) {
! 1027: case IEEE80211_CIPHER_WEP40:
! 1028: return 5;
! 1029: case IEEE80211_CIPHER_TKIP:
! 1030: return 32;
! 1031: case IEEE80211_CIPHER_CCMP:
! 1032: return 16;
! 1033: case IEEE80211_CIPHER_WEP104:
! 1034: return 13;
! 1035: default: /* unknown cipher */
! 1036: return 0;
! 1037: }
! 1038: }
CVSweb