1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * Copyright (c) 2001 Atsushi Onoe
   8  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions and the following disclaimer.
  16  * 2. Redistributions in binary form must reproduce the above copyright
  17  *    notice, this list of conditions and the following disclaimer in the
  18  *    documentation and/or other materials provided with the distribution.
  19  * 3. The name of the author may not be used to endorse or promote products
  20  *    derived from this software without specific prior written permission.
  21  *
  22  * Alternatively, this software may be distributed under the terms of the
  23  * GNU General Public License ("GPL") version 2 as published by the Free
  24  * Software Foundation.
  25  *
  26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36  */
  37 
  38 /*
  39  * IEEE 802.11i CCMP crypto support.
  40  */
  41 #include <sys/byteorder.h>
  42 #include <sys/crypto/common.h>
  43 #include <sys/crypto/api.h>
  44 #include <sys/crc32.h>
  45 #include <sys/random.h>
  46 #include <sys/strsun.h>
  47 #include "net80211_impl.h"
  48 
  49 struct ccmp_ctx {
  50         struct ieee80211com *cc_ic;     /* for diagnostics */
  51 };
  52 
  53 #define AES_BLOCK_LEN   16
  54 #define AES_NONCE_LEN   13
  55 
  56 static void *ccmp_attach(struct ieee80211com *, struct ieee80211_key *);
  57 static void ccmp_detach(struct ieee80211_key *);
  58 static int ccmp_setkey(struct ieee80211_key *);
  59 static int ccmp_encap(struct ieee80211_key *k, mblk_t *, uint8_t);
  60 static int ccmp_decap(struct ieee80211_key *, mblk_t *, int);
  61 static int ccmp_enmic(struct ieee80211_key *, mblk_t *, int);
  62 static int ccmp_demic(struct ieee80211_key *, mblk_t *, int);
  63 
  64 static int ccmp_encrypt(struct ieee80211_key *, mblk_t *, int);
  65 static int ccmp_decrypt(struct ieee80211_key *, uint64_t pn, mblk_t *, int);
  66 
  67 const struct ieee80211_cipher ccmp = {
  68         "AES-CCM",
  69         IEEE80211_CIPHER_AES_CCM,
  70         IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
  71             IEEE80211_WEP_EXTIVLEN,
  72         IEEE80211_WEP_MICLEN,
  73         0,
  74         ccmp_attach,
  75         ccmp_detach,
  76         ccmp_setkey,
  77         ccmp_encap,
  78         ccmp_decap,
  79         ccmp_enmic,
  80         ccmp_demic,
  81 };
  82 
  83 /* ARGSUSED */
  84 static void *
  85 ccmp_attach(struct ieee80211com *ic, struct ieee80211_key *k)
  86 {
  87         struct ccmp_ctx *ctx;
  88 
  89         ctx = kmem_zalloc(sizeof (struct ccmp_ctx), KM_SLEEP);
  90         if (ctx == NULL)
  91                 return (NULL);
  92 
  93         ctx->cc_ic = ic;
  94         return (ctx);
  95 }
  96 
  97 static void
  98 ccmp_detach(struct ieee80211_key *k)
  99 {
 100         struct ccmp_ctx *ctx = k->wk_private;
 101 
 102         if (ctx != NULL)
 103                 kmem_free(ctx, sizeof (struct ccmp_ctx));
 104 }
 105 
 106 static int
 107 ccmp_setkey(struct ieee80211_key *k)
 108 {
 109         if (k->wk_keylen != (128/NBBY))
 110                 return (0);
 111 
 112         return (1);
 113 }
 114 
 115 /*
 116  * Add privacy headers appropriate for the specified key.
 117  */
 118 static int
 119 ccmp_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
 120 {
 121         struct ccmp_ctx *ctx = k->wk_private;
 122         uint8_t *ivp;
 123         int hdrlen;
 124 
 125         hdrlen = ieee80211_hdrspace(ctx->cc_ic, mp->b_rptr);
 126         /*
 127          * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
 128          */
 129         ivp = mp->b_rptr;
 130         ivp += hdrlen;
 131 
 132         k->wk_keytsc++;                              /* wrap at 48 bits */
 133         ivp[0] = k->wk_keytsc >> 0;            /* PN0 */
 134         ivp[1] = k->wk_keytsc >> 8;            /* PN1 */
 135         ivp[2] = 0;                             /* Reserved */
 136         ivp[3] = keyid | IEEE80211_WEP_EXTIV;   /* KeyID | ExtID */
 137         ivp[4] = k->wk_keytsc >> 16;           /* PN2 */
 138         ivp[5] = k->wk_keytsc >> 24;           /* PN3 */
 139         ivp[6] = k->wk_keytsc >> 32;           /* PN4 */
 140         ivp[7] = k->wk_keytsc >> 40;           /* PN5 */
 141 
 142         /*
 143          * Finally, do software encrypt if neeed.
 144          */
 145         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
 146             !ccmp_encrypt(k, mp, hdrlen))
 147                 return (0);
 148 
 149         return (1);
 150 }
 151 
 152 /*
 153  * Validate and strip privacy headers (and trailer) for a
 154  * received frame. The specified key should be correct but
 155  * is also verified.
 156  */
 157 static int
 158 ccmp_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
 159 {
 160         uint8_t *ivp;
 161         uint64_t pn;
 162 
 163         /*
 164          * Header should have extended IV and sequence number;
 165          * verify the former and validate the latter.
 166          */
 167         ivp = mp->b_rptr + hdrlen;
 168         if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
 169                 /*
 170                  * No extended IV; discard frame.
 171                  */
 172                 return (0);
 173         }
 174 
 175         pn = ieee80211_read_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
 176         if (pn <= k->wk_keyrsc) {
 177                 /*
 178                  * Replay violation.
 179                  */
 180                 return (0);
 181         }
 182 
 183         /*
 184          * Check if the device handled the decrypt in hardware.
 185          * If so we just strip the header; otherwise we need to
 186          * handle the decrypt in software.  Note that for the
 187          * latter we leave the header in place for use in the
 188          * decryption work.
 189          */
 190         if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
 191             !ccmp_decrypt(k, pn, mp, hdrlen))
 192                 return (0);
 193 
 194         /*
 195          * Copy up 802.11 header and strip crypto bits.
 196          */
 197         (void) memmove(mp->b_rptr + ccmp.ic_header, mp->b_rptr, hdrlen);
 198         mp->b_rptr += ccmp.ic_header;
 199         mp->b_wptr -= ccmp.ic_trailer;
 200 
 201         /*
 202          * Ok to update rsc now.
 203          */
 204         k->wk_keyrsc = pn;
 205 
 206         return (1);
 207 }
 208 
 209 /*
 210  * Add MIC to the frame as needed.
 211  */
 212 /* ARGSUSED */
 213 static int
 214 ccmp_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
 215 {
 216         return (1);
 217 }
 218 
 219 /*
 220  * Verify and strip MIC from the frame.
 221  */
 222 /* ARGSUSED */
 223 static int
 224 ccmp_demic(struct ieee80211_key *k, mblk_t *mp, int force)
 225 {
 226         return (1);
 227 }
 228 
 229 static int
 230 aes_ccm_encrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
 231     const uint8_t *plaintext, int plain_len,
 232     uint8_t *ciphertext, int cipher_len)
 233 {
 234         crypto_mechanism_t mech;
 235         crypto_key_t crkey;
 236         crypto_data_t d1, d2;
 237 
 238         int rv;
 239 
 240         ieee80211_dbg(IEEE80211_MSG_CRYPTO,
 241             "aes_ccm_encrypt(len=%d, keylen=%d)", plain_len, keylen);
 242 
 243         bzero(&crkey, sizeof (crkey));
 244 
 245         crkey.ck_format = CRYPTO_KEY_RAW;
 246         crkey.ck_data   = (char *)key;
 247         /* keys are measured in bits, not bytes, so multiply by 8 */
 248         crkey.ck_length = keylen * 8;
 249 
 250         mech.cm_type      = crypto_mech2id(SUN_CKM_AES_CCM);
 251         mech.cm_param     = (caddr_t)cmparam;
 252         mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
 253 
 254 #if defined(__amd64) || defined(__sparc)
 255         ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
 256 #else
 257         ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
 258 #endif
 259 
 260         bzero(&d1, sizeof (d1));
 261         bzero(&d2, sizeof (d2));
 262 
 263         d1.cd_format = CRYPTO_DATA_RAW;
 264         d1.cd_offset = 0;
 265         d1.cd_length = plain_len;
 266         d1.cd_raw.iov_base = (char *)plaintext;
 267         d1.cd_raw.iov_len  = plain_len;
 268 
 269         d2.cd_format = CRYPTO_DATA_RAW;
 270         d2.cd_offset = 0;
 271         d2.cd_length = cipher_len;
 272         d2.cd_raw.iov_base = (char *)ciphertext;
 273         d2.cd_raw.iov_len  = cipher_len;
 274 
 275 
 276         rv = crypto_encrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
 277         if (rv != CRYPTO_SUCCESS)
 278                 ieee80211_err("aes_ccm_encrypt failed (%x)", rv);
 279         return (rv);
 280 }
 281 
 282 static int
 283 aes_ccm_decrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
 284     const uint8_t *ciphertext, int cipher_len,
 285     uint8_t *plaintext, int plain_len)
 286 {
 287         crypto_mechanism_t mech;
 288         crypto_key_t crkey;
 289         crypto_data_t d1, d2;
 290 
 291         int rv;
 292 
 293         ieee80211_dbg(IEEE80211_MSG_CRYPTO,
 294             "aes_ccm_decrypt(len=%d, keylen=%d)", cipher_len, keylen);
 295 
 296         bzero(&crkey, sizeof (crkey));
 297 
 298         crkey.ck_format = CRYPTO_KEY_RAW;
 299         crkey.ck_data   = (char *)key;
 300         /* keys are measured in bits, not bytes, so multiply by 8 */
 301         crkey.ck_length = keylen * 8;
 302 
 303         mech.cm_type      = crypto_mech2id(SUN_CKM_AES_CCM);
 304         mech.cm_param     = (caddr_t)cmparam;
 305         mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
 306 
 307 #if defined(__amd64) || defined(__sparc)
 308         ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
 309 #else
 310         ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
 311 #endif
 312 
 313         bzero(&d1, sizeof (d1));
 314         bzero(&d2, sizeof (d2));
 315 
 316         d1.cd_format = CRYPTO_DATA_RAW;
 317         d1.cd_offset = 0;
 318         d1.cd_length = cipher_len;
 319         d1.cd_raw.iov_base = (char *)ciphertext;
 320         d1.cd_raw.iov_len  = cipher_len;
 321 
 322         d2.cd_format = CRYPTO_DATA_RAW;
 323         d2.cd_offset = 0;
 324         d2.cd_length = plain_len;
 325         d2.cd_raw.iov_base = (char *)plaintext;
 326         d2.cd_raw.iov_len  = plain_len;
 327 
 328 
 329         rv = crypto_decrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
 330         if (rv != CRYPTO_SUCCESS)
 331                 ieee80211_err("aes_ccm_decrypt failed (%x)", rv);
 332         return (rv);
 333 }
 334 
 335 /*
 336  * For the avoidance of doubt, except that if any license choice other
 337  * than GPL or LGPL is available it will apply instead, Sun elects to
 338  * use only the General Public License version 2 (GPLv2) at this time
 339  * for any software where a choice of GPL license versions is made
 340  * available with the language indicating that GPLv2 or any later
 341  * version may be used, or where a choice of which version of the GPL
 342  * is applied is otherwise unspecified.
 343  */
 344 
 345 /*
 346  * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
 347  *
 348  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
 349  *
 350  * This program is free software; you can redistribute it and/or modify
 351  * it under the terms of the GNU General Public License version 2 as
 352  * published by the Free Software Foundation. See README and COPYING for
 353  * more details.
 354  *
 355  * Alternatively, this software may be distributed under the terms of BSD
 356  * license.
 357  */
 358 
 359 static void
 360 ccmp_init(struct ieee80211_frame *wh, uint64_t pn, size_t dlen,
 361     uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN])
 362 {
 363         /*
 364          * CCM Initial Block:
 365          * Flag (Include authentication header, M=3 (8-octet MIC),
 366          * L=1 (2-octet Dlen))
 367          * Nonce: 0x00 | A2 | PN
 368          * Dlen
 369          */
 370         b0[0] = 0x59;
 371         /* b0[1] set below */
 372         IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
 373         b0[8] = pn >> 40;
 374         b0[9] = pn >> 32;
 375         b0[10] = pn >> 24;
 376         b0[11] = pn >> 16;
 377         b0[12] = pn >> 8;
 378         b0[13] = (uint8_t)(pn >> 0);
 379         b0[14] = (dlen >> 8) & 0xff;
 380         b0[15] = dlen & 0xff;
 381 
 382         /*
 383          * AAD:
 384          * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
 385          * A1 | A2 | A3
 386          * SC with bits 4..15 (seq#) masked to zero
 387          * A4 (if present)
 388          * QC (if present)
 389          */
 390         aad[0] = 0;     /* AAD length >> 8 */
 391         /* aad[1] set below */
 392         aad[2] = wh->i_fc[0] & 0x8f;     /* magic #s */
 393         aad[3] = wh->i_fc[1] & 0xc7;     /* magic #s */
 394         /* we know 3 addresses are contiguous */
 395         (void) memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN);
 396         aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK;
 397         aad[23] = 0; /* all bits masked */
 398         /*
 399          * Construct variable-length portion of AAD based
 400          * on whether this is a 4-address frame/QOS frame.
 401          * We always zero-pad to 32 bytes before running it
 402          * through the cipher.
 403          *
 404          * We also fill in the priority bits of the CCM
 405          * initial block as we know whether or not we have
 406          * a QOS frame.
 407          */
 408         if (IEEE80211_QOS_HAS_SEQ(wh)) {
 409                 struct ieee80211_qosframe *qwh =
 410                     (struct ieee80211_qosframe *)wh;
 411                 aad[24] = qwh->i_qos[0] & 0x0f;  /* just priority bits */
 412                 aad[25] = 0;
 413                 b0[1] = aad[24];
 414                 aad[1] = 22 + 2;
 415         } else {
 416                 *(uint16_t *)&aad[24] = 0;
 417                 b0[1] = 0;
 418                 aad[1] = 22;
 419         }
 420         *(uint16_t *)&aad[26] = 0;
 421         *(uint32_t *)&aad[28] = 0;
 422 }
 423 
 424 static int
 425 ccmp_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
 426 {
 427         struct ieee80211_frame *wh;
 428         int rv, data_len;
 429         uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
 430         uint8_t *pos;
 431         CK_AES_CCM_PARAMS cmparam;
 432 
 433         wh = (struct ieee80211_frame *)mp->b_rptr;
 434         data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
 435         pos = mp->b_rptr + hdrlen + ccmp.ic_header;
 436 
 437         ccmp_init(wh, key->wk_keytsc, data_len, b0, aad);
 438 
 439         cmparam.ulMACSize = IEEE80211_WEP_MICLEN;
 440         cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
 441         cmparam.ulAuthDataSize = aad[1]; /* A size */
 442         cmparam.ulDataSize = data_len;  /* data length; */
 443         cmparam.nonce = &b0[1]; /* N */
 444         cmparam.authData = &aad[2]; /* A */
 445 
 446         rv = aes_ccm_encrypt(&cmparam,
 447             key->wk_key, key->wk_keylen,
 448             pos, data_len, pos, data_len + IEEE80211_WEP_MICLEN);
 449 
 450         mp->b_wptr += ccmp.ic_trailer;
 451 
 452         return ((rv == CRYPTO_SUCCESS)? 1 : 0);
 453 }
 454 
 455 static int
 456 ccmp_decrypt(struct ieee80211_key *key, uint64_t pn, mblk_t *mp, int hdrlen)
 457 {
 458         struct ieee80211_frame *wh;
 459         int rv, data_len;
 460         uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
 461         uint8_t *pos;
 462         CK_AES_CCM_PARAMS cmparam;
 463 
 464         wh = (struct ieee80211_frame *)mp->b_rptr;
 465         data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
 466         pos = mp->b_rptr + hdrlen + ccmp.ic_header;
 467 
 468         ccmp_init(wh, pn, data_len, b0, aad);
 469 
 470         cmparam.ulMACSize = IEEE80211_WEP_MICLEN; /* MIC = 8 */
 471         cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
 472         cmparam.ulAuthDataSize = aad[1]; /* A size */
 473         cmparam.ulDataSize = data_len;
 474         cmparam.nonce = &b0[1]; /* N */
 475         cmparam.authData = &aad[2]; /* A */
 476 
 477         rv = aes_ccm_decrypt(&cmparam,
 478             key->wk_key, key->wk_keylen, pos, data_len, pos, data_len);
 479 
 480         return ((rv == CRYPTO_SUCCESS)? 1 : 0);
 481 }