14126Szf162725 /*
2*10266SQuaker.Fang@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
34126Szf162725 * Use is subject to license terms.
44126Szf162725 */
54126Szf162725
64126Szf162725 /*
74126Szf162725 * Copyright (c) 2001 Atsushi Onoe
8*10266SQuaker.Fang@Sun.COM * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
94126Szf162725 * All rights reserved.
104126Szf162725 *
114126Szf162725 * Redistribution and use in source and binary forms, with or without
124126Szf162725 * modification, are permitted provided that the following conditions
134126Szf162725 * are met:
144126Szf162725 * 1. Redistributions of source code must retain the above copyright
154126Szf162725 * notice, this list of conditions and the following disclaimer.
164126Szf162725 * 2. Redistributions in binary form must reproduce the above copyright
174126Szf162725 * notice, this list of conditions and the following disclaimer in the
184126Szf162725 * documentation and/or other materials provided with the distribution.
194126Szf162725 * 3. The name of the author may not be used to endorse or promote products
204126Szf162725 * derived from this software without specific prior written permission.
214126Szf162725 *
224126Szf162725 * Alternatively, this software may be distributed under the terms of the
234126Szf162725 * GNU General Public License ("GPL") version 2 as published by the Free
244126Szf162725 * Software Foundation.
254126Szf162725 *
264126Szf162725 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
274126Szf162725 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
284126Szf162725 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
294126Szf162725 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
304126Szf162725 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
314126Szf162725 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
324126Szf162725 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
334126Szf162725 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
344126Szf162725 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
354126Szf162725 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364126Szf162725 */
374126Szf162725
384126Szf162725 /*
394126Szf162725 * IEEE 802.11i CCMP crypto support.
404126Szf162725 */
414126Szf162725 #include <sys/byteorder.h>
424126Szf162725 #include <sys/crypto/common.h>
434126Szf162725 #include <sys/crypto/api.h>
444126Szf162725 #include <sys/crc32.h>
454126Szf162725 #include <sys/random.h>
467249Sff224033 #include <sys/strsun.h>
474126Szf162725 #include "net80211_impl.h"
484126Szf162725
494126Szf162725 struct ccmp_ctx {
504126Szf162725 struct ieee80211com *cc_ic; /* for diagnostics */
514126Szf162725 };
524126Szf162725
536977Szf162725 #define AES_BLOCK_LEN 16
546977Szf162725 #define AES_NONCE_LEN 13
556977Szf162725
564126Szf162725 static void *ccmp_attach(struct ieee80211com *, struct ieee80211_key *);
574126Szf162725 static void ccmp_detach(struct ieee80211_key *);
584126Szf162725 static int ccmp_setkey(struct ieee80211_key *);
594126Szf162725 static int ccmp_encap(struct ieee80211_key *k, mblk_t *, uint8_t);
604126Szf162725 static int ccmp_decap(struct ieee80211_key *, mblk_t *, int);
614126Szf162725 static int ccmp_enmic(struct ieee80211_key *, mblk_t *, int);
624126Szf162725 static int ccmp_demic(struct ieee80211_key *, mblk_t *, int);
634126Szf162725
646977Szf162725 static int ccmp_encrypt(struct ieee80211_key *, mblk_t *, int);
656977Szf162725 static int ccmp_decrypt(struct ieee80211_key *, uint64_t pn, mblk_t *, int);
666977Szf162725
674126Szf162725 const struct ieee80211_cipher ccmp = {
684126Szf162725 "AES-CCM",
694126Szf162725 IEEE80211_CIPHER_AES_CCM,
704126Szf162725 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
714126Szf162725 IEEE80211_WEP_EXTIVLEN,
724126Szf162725 IEEE80211_WEP_MICLEN,
734126Szf162725 0,
744126Szf162725 ccmp_attach,
754126Szf162725 ccmp_detach,
764126Szf162725 ccmp_setkey,
774126Szf162725 ccmp_encap,
784126Szf162725 ccmp_decap,
794126Szf162725 ccmp_enmic,
804126Szf162725 ccmp_demic,
814126Szf162725 };
824126Szf162725
834126Szf162725 /* ARGSUSED */
844126Szf162725 static void *
ccmp_attach(struct ieee80211com * ic,struct ieee80211_key * k)854126Szf162725 ccmp_attach(struct ieee80211com *ic, struct ieee80211_key *k)
864126Szf162725 {
874126Szf162725 struct ccmp_ctx *ctx;
884126Szf162725
894126Szf162725 ctx = kmem_zalloc(sizeof (struct ccmp_ctx), KM_SLEEP);
904126Szf162725 if (ctx == NULL)
914126Szf162725 return (NULL);
924126Szf162725
934126Szf162725 ctx->cc_ic = ic;
944126Szf162725 return (ctx);
954126Szf162725 }
964126Szf162725
974126Szf162725 static void
ccmp_detach(struct ieee80211_key * k)984126Szf162725 ccmp_detach(struct ieee80211_key *k)
994126Szf162725 {
1004126Szf162725 struct ccmp_ctx *ctx = k->wk_private;
1014126Szf162725
1024126Szf162725 if (ctx != NULL)
1034126Szf162725 kmem_free(ctx, sizeof (struct ccmp_ctx));
1044126Szf162725 }
1054126Szf162725
1064126Szf162725 static int
ccmp_setkey(struct ieee80211_key * k)1074126Szf162725 ccmp_setkey(struct ieee80211_key *k)
1084126Szf162725 {
1094126Szf162725 if (k->wk_keylen != (128/NBBY))
1104126Szf162725 return (0);
1114126Szf162725
1124126Szf162725 return (1);
1134126Szf162725 }
1144126Szf162725
1154126Szf162725 /*
1164126Szf162725 * Add privacy headers appropriate for the specified key.
1174126Szf162725 */
1184126Szf162725 static int
ccmp_encap(struct ieee80211_key * k,mblk_t * mp,uint8_t keyid)1194126Szf162725 ccmp_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
1204126Szf162725 {
121*10266SQuaker.Fang@Sun.COM struct ccmp_ctx *ctx = k->wk_private;
1224126Szf162725 uint8_t *ivp;
1234126Szf162725 int hdrlen;
1244126Szf162725
125*10266SQuaker.Fang@Sun.COM hdrlen = ieee80211_hdrspace(ctx->cc_ic, mp->b_rptr);
1264126Szf162725 /*
1274126Szf162725 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
1284126Szf162725 */
1294126Szf162725 ivp = mp->b_rptr;
1304126Szf162725 ivp += hdrlen;
1314126Szf162725
1324126Szf162725 k->wk_keytsc++; /* wrap at 48 bits */
1334126Szf162725 ivp[0] = k->wk_keytsc >> 0; /* PN0 */
1344126Szf162725 ivp[1] = k->wk_keytsc >> 8; /* PN1 */
1354126Szf162725 ivp[2] = 0; /* Reserved */
1364126Szf162725 ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
1374126Szf162725 ivp[4] = k->wk_keytsc >> 16; /* PN2 */
1384126Szf162725 ivp[5] = k->wk_keytsc >> 24; /* PN3 */
1394126Szf162725 ivp[6] = k->wk_keytsc >> 32; /* PN4 */
1404126Szf162725 ivp[7] = k->wk_keytsc >> 40; /* PN5 */
1414126Szf162725
1424126Szf162725 /*
1436977Szf162725 * Finally, do software encrypt if neeed.
1444126Szf162725 */
1456977Szf162725 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
1466977Szf162725 !ccmp_encrypt(k, mp, hdrlen))
1474126Szf162725 return (0);
1484126Szf162725
1494126Szf162725 return (1);
1504126Szf162725 }
1514126Szf162725
1524126Szf162725 /*
1534126Szf162725 * Validate and strip privacy headers (and trailer) for a
1544126Szf162725 * received frame. The specified key should be correct but
1554126Szf162725 * is also verified.
1564126Szf162725 */
1574126Szf162725 static int
ccmp_decap(struct ieee80211_key * k,mblk_t * mp,int hdrlen)1584126Szf162725 ccmp_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
1594126Szf162725 {
1604126Szf162725 uint8_t *ivp;
1614126Szf162725 uint64_t pn;
1624126Szf162725
1634126Szf162725 /*
1644126Szf162725 * Header should have extended IV and sequence number;
1654126Szf162725 * verify the former and validate the latter.
1664126Szf162725 */
1674126Szf162725 ivp = mp->b_rptr + hdrlen;
1684126Szf162725 if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
1694126Szf162725 /*
1704126Szf162725 * No extended IV; discard frame.
1714126Szf162725 */
1724126Szf162725 return (0);
1734126Szf162725 }
1744126Szf162725
1754126Szf162725 pn = ieee80211_read_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
1764126Szf162725 if (pn <= k->wk_keyrsc) {
1774126Szf162725 /*
1784126Szf162725 * Replay violation.
1794126Szf162725 */
1804126Szf162725 return (0);
1814126Szf162725 }
1824126Szf162725
1834126Szf162725 /*
1846977Szf162725 * Check if the device handled the decrypt in hardware.
1856977Szf162725 * If so we just strip the header; otherwise we need to
1866977Szf162725 * handle the decrypt in software. Note that for the
1876977Szf162725 * latter we leave the header in place for use in the
1886977Szf162725 * decryption work.
1894126Szf162725 */
1906977Szf162725 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
1916977Szf162725 !ccmp_decrypt(k, pn, mp, hdrlen))
1924126Szf162725 return (0);
1934126Szf162725
1944126Szf162725 /*
1954126Szf162725 * Copy up 802.11 header and strip crypto bits.
1964126Szf162725 */
197*10266SQuaker.Fang@Sun.COM (void) memmove(mp->b_rptr + ccmp.ic_header, mp->b_rptr, hdrlen);
1984126Szf162725 mp->b_rptr += ccmp.ic_header;
1994126Szf162725 mp->b_wptr -= ccmp.ic_trailer;
2004126Szf162725
2014126Szf162725 /*
2024126Szf162725 * Ok to update rsc now.
2034126Szf162725 */
2044126Szf162725 k->wk_keyrsc = pn;
2054126Szf162725
2064126Szf162725 return (1);
2074126Szf162725 }
2084126Szf162725
2094126Szf162725 /*
2104126Szf162725 * Add MIC to the frame as needed.
2114126Szf162725 */
2124126Szf162725 /* ARGSUSED */
2134126Szf162725 static int
ccmp_enmic(struct ieee80211_key * k,mblk_t * mp,int force)2144126Szf162725 ccmp_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
2154126Szf162725 {
2164126Szf162725 return (1);
2174126Szf162725 }
2184126Szf162725
2194126Szf162725 /*
2204126Szf162725 * Verify and strip MIC from the frame.
2214126Szf162725 */
2224126Szf162725 /* ARGSUSED */
2234126Szf162725 static int
ccmp_demic(struct ieee80211_key * k,mblk_t * mp,int force)2244126Szf162725 ccmp_demic(struct ieee80211_key *k, mblk_t *mp, int force)
2254126Szf162725 {
2264126Szf162725 return (1);
2274126Szf162725 }
2286977Szf162725
2296977Szf162725 static int
aes_ccm_encrypt(CK_AES_CCM_PARAMS * cmparam,const uint8_t * key,int keylen,const uint8_t * plaintext,int plain_len,uint8_t * ciphertext,int cipher_len)2306977Szf162725 aes_ccm_encrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
2316977Szf162725 const uint8_t *plaintext, int plain_len,
2326977Szf162725 uint8_t *ciphertext, int cipher_len)
2336977Szf162725 {
2346977Szf162725 crypto_mechanism_t mech;
2356977Szf162725 crypto_key_t crkey;
2366977Szf162725 crypto_data_t d1, d2;
2376977Szf162725
2386977Szf162725 int rv;
2396977Szf162725
2406977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO,
2416977Szf162725 "aes_ccm_encrypt(len=%d, keylen=%d)", plain_len, keylen);
2426977Szf162725
2436977Szf162725 bzero(&crkey, sizeof (crkey));
2446977Szf162725
2456977Szf162725 crkey.ck_format = CRYPTO_KEY_RAW;
2466977Szf162725 crkey.ck_data = (char *)key;
2476977Szf162725 /* keys are measured in bits, not bytes, so multiply by 8 */
2486977Szf162725 crkey.ck_length = keylen * 8;
2496977Szf162725
2506977Szf162725 mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM);
2516977Szf162725 mech.cm_param = (caddr_t)cmparam;
2526977Szf162725 mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
2536977Szf162725
2546977Szf162725 #if defined(__amd64) || defined(__sparc)
2556977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
2566977Szf162725 #else
2576977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
2586977Szf162725 #endif
2596977Szf162725
2606977Szf162725 bzero(&d1, sizeof (d1));
2616977Szf162725 bzero(&d2, sizeof (d2));
2626977Szf162725
2636977Szf162725 d1.cd_format = CRYPTO_DATA_RAW;
2646977Szf162725 d1.cd_offset = 0;
2656977Szf162725 d1.cd_length = plain_len;
2666977Szf162725 d1.cd_raw.iov_base = (char *)plaintext;
2676977Szf162725 d1.cd_raw.iov_len = plain_len;
2686977Szf162725
2696977Szf162725 d2.cd_format = CRYPTO_DATA_RAW;
2706977Szf162725 d2.cd_offset = 0;
2716977Szf162725 d2.cd_length = cipher_len;
2726977Szf162725 d2.cd_raw.iov_base = (char *)ciphertext;
2736977Szf162725 d2.cd_raw.iov_len = cipher_len;
2746977Szf162725
2756977Szf162725
2766977Szf162725 rv = crypto_encrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
2776977Szf162725 if (rv != CRYPTO_SUCCESS)
2786977Szf162725 ieee80211_err("aes_ccm_encrypt failed (%x)", rv);
2796977Szf162725 return (rv);
2806977Szf162725 }
2816977Szf162725
2826977Szf162725 static int
aes_ccm_decrypt(CK_AES_CCM_PARAMS * cmparam,const uint8_t * key,int keylen,const uint8_t * ciphertext,int cipher_len,uint8_t * plaintext,int plain_len)2836977Szf162725 aes_ccm_decrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
2846977Szf162725 const uint8_t *ciphertext, int cipher_len,
2856977Szf162725 uint8_t *plaintext, int plain_len)
2866977Szf162725 {
2876977Szf162725 crypto_mechanism_t mech;
2886977Szf162725 crypto_key_t crkey;
2896977Szf162725 crypto_data_t d1, d2;
2906977Szf162725
2916977Szf162725 int rv;
2926977Szf162725
2936977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO,
2946977Szf162725 "aes_ccm_decrypt(len=%d, keylen=%d)", cipher_len, keylen);
2956977Szf162725
2966977Szf162725 bzero(&crkey, sizeof (crkey));
2976977Szf162725
2986977Szf162725 crkey.ck_format = CRYPTO_KEY_RAW;
2996977Szf162725 crkey.ck_data = (char *)key;
3006977Szf162725 /* keys are measured in bits, not bytes, so multiply by 8 */
3016977Szf162725 crkey.ck_length = keylen * 8;
3026977Szf162725
3036977Szf162725 mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM);
3046977Szf162725 mech.cm_param = (caddr_t)cmparam;
3056977Szf162725 mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
3066977Szf162725
3076977Szf162725 #if defined(__amd64) || defined(__sparc)
3086977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
3096977Szf162725 #else
3106977Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
3116977Szf162725 #endif
3126977Szf162725
3136977Szf162725 bzero(&d1, sizeof (d1));
3146977Szf162725 bzero(&d2, sizeof (d2));
3156977Szf162725
3166977Szf162725 d1.cd_format = CRYPTO_DATA_RAW;
3176977Szf162725 d1.cd_offset = 0;
3186977Szf162725 d1.cd_length = cipher_len;
3196977Szf162725 d1.cd_raw.iov_base = (char *)ciphertext;
3206977Szf162725 d1.cd_raw.iov_len = cipher_len;
3216977Szf162725
3226977Szf162725 d2.cd_format = CRYPTO_DATA_RAW;
3236977Szf162725 d2.cd_offset = 0;
3246977Szf162725 d2.cd_length = plain_len;
3256977Szf162725 d2.cd_raw.iov_base = (char *)plaintext;
3266977Szf162725 d2.cd_raw.iov_len = plain_len;
3276977Szf162725
3286977Szf162725
3296977Szf162725 rv = crypto_decrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
3306977Szf162725 if (rv != CRYPTO_SUCCESS)
3316977Szf162725 ieee80211_err("aes_ccm_decrypt failed (%x)", rv);
3326977Szf162725 return (rv);
3336977Szf162725 }
3346977Szf162725
3356977Szf162725 /*
3366977Szf162725 * For the avoidance of doubt, except that if any license choice other
3376977Szf162725 * than GPL or LGPL is available it will apply instead, Sun elects to
3386977Szf162725 * use only the General Public License version 2 (GPLv2) at this time
3396977Szf162725 * for any software where a choice of GPL license versions is made
3406977Szf162725 * available with the language indicating that GPLv2 or any later
3416977Szf162725 * version may be used, or where a choice of which version of the GPL
3426977Szf162725 * is applied is otherwise unspecified.
3436977Szf162725 */
3446977Szf162725
3456977Szf162725 /*
3466977Szf162725 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3476977Szf162725 *
3486977Szf162725 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
3496977Szf162725 *
3506977Szf162725 * This program is free software; you can redistribute it and/or modify
3516977Szf162725 * it under the terms of the GNU General Public License version 2 as
3526977Szf162725 * published by the Free Software Foundation. See README and COPYING for
3536977Szf162725 * more details.
3546977Szf162725 *
3556977Szf162725 * Alternatively, this software may be distributed under the terms of BSD
3566977Szf162725 * license.
3576977Szf162725 */
3586977Szf162725
3596977Szf162725 static void
ccmp_init(struct ieee80211_frame * wh,uint64_t pn,size_t dlen,uint8_t b0[AES_BLOCK_LEN],uint8_t aad[2* AES_BLOCK_LEN])3606977Szf162725 ccmp_init(struct ieee80211_frame *wh, uint64_t pn, size_t dlen,
3616977Szf162725 uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN])
3626977Szf162725 {
3636977Szf162725 /*
3646977Szf162725 * CCM Initial Block:
3656977Szf162725 * Flag (Include authentication header, M=3 (8-octet MIC),
3666977Szf162725 * L=1 (2-octet Dlen))
3676977Szf162725 * Nonce: 0x00 | A2 | PN
3686977Szf162725 * Dlen
3696977Szf162725 */
3706977Szf162725 b0[0] = 0x59;
3716977Szf162725 /* b0[1] set below */
3726977Szf162725 IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
3736977Szf162725 b0[8] = pn >> 40;
3746977Szf162725 b0[9] = pn >> 32;
3756977Szf162725 b0[10] = pn >> 24;
3766977Szf162725 b0[11] = pn >> 16;
3776977Szf162725 b0[12] = pn >> 8;
3786977Szf162725 b0[13] = (uint8_t)(pn >> 0);
3796977Szf162725 b0[14] = (dlen >> 8) & 0xff;
3806977Szf162725 b0[15] = dlen & 0xff;
3816977Szf162725
3826977Szf162725 /*
3836977Szf162725 * AAD:
3846977Szf162725 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
3856977Szf162725 * A1 | A2 | A3
3866977Szf162725 * SC with bits 4..15 (seq#) masked to zero
3876977Szf162725 * A4 (if present)
3886977Szf162725 * QC (if present)
3896977Szf162725 */
3906977Szf162725 aad[0] = 0; /* AAD length >> 8 */
3916977Szf162725 /* aad[1] set below */
3926977Szf162725 aad[2] = wh->i_fc[0] & 0x8f; /* magic #s */
3936977Szf162725 aad[3] = wh->i_fc[1] & 0xc7; /* magic #s */
3946977Szf162725 /* we know 3 addresses are contiguous */
3956977Szf162725 (void) memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN);
3966977Szf162725 aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK;
3976977Szf162725 aad[23] = 0; /* all bits masked */
3986977Szf162725 /*
3996977Szf162725 * Construct variable-length portion of AAD based
4006977Szf162725 * on whether this is a 4-address frame/QOS frame.
4016977Szf162725 * We always zero-pad to 32 bytes before running it
4026977Szf162725 * through the cipher.
4036977Szf162725 *
4046977Szf162725 * We also fill in the priority bits of the CCM
4056977Szf162725 * initial block as we know whether or not we have
4066977Szf162725 * a QOS frame.
4076977Szf162725 */
408*10266SQuaker.Fang@Sun.COM if (IEEE80211_QOS_HAS_SEQ(wh)) {
409*10266SQuaker.Fang@Sun.COM struct ieee80211_qosframe *qwh =
410*10266SQuaker.Fang@Sun.COM (struct ieee80211_qosframe *)wh;
411*10266SQuaker.Fang@Sun.COM aad[24] = qwh->i_qos[0] & 0x0f; /* just priority bits */
412*10266SQuaker.Fang@Sun.COM aad[25] = 0;
413*10266SQuaker.Fang@Sun.COM b0[1] = aad[24];
414*10266SQuaker.Fang@Sun.COM aad[1] = 22 + 2;
415*10266SQuaker.Fang@Sun.COM } else {
416*10266SQuaker.Fang@Sun.COM *(uint16_t *)&aad[24] = 0;
417*10266SQuaker.Fang@Sun.COM b0[1] = 0;
418*10266SQuaker.Fang@Sun.COM aad[1] = 22;
419*10266SQuaker.Fang@Sun.COM }
4206977Szf162725 *(uint16_t *)&aad[26] = 0;
4216977Szf162725 *(uint32_t *)&aad[28] = 0;
4226977Szf162725 }
4236977Szf162725
4246977Szf162725 static int
ccmp_encrypt(struct ieee80211_key * key,mblk_t * mp,int hdrlen)4256977Szf162725 ccmp_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
4266977Szf162725 {
4276977Szf162725 struct ieee80211_frame *wh;
4286977Szf162725 int rv, data_len;
4296977Szf162725 uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
4306977Szf162725 uint8_t *pos;
4316977Szf162725 CK_AES_CCM_PARAMS cmparam;
4326977Szf162725
4336977Szf162725 wh = (struct ieee80211_frame *)mp->b_rptr;
4347249Sff224033 data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
4356977Szf162725 pos = mp->b_rptr + hdrlen + ccmp.ic_header;
4366977Szf162725
4376977Szf162725 ccmp_init(wh, key->wk_keytsc, data_len, b0, aad);
4386977Szf162725
4396977Szf162725 cmparam.ulMACSize = IEEE80211_WEP_MICLEN;
4406977Szf162725 cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
4416977Szf162725 cmparam.ulAuthDataSize = aad[1]; /* A size */
4426977Szf162725 cmparam.ulDataSize = data_len; /* data length; */
4436977Szf162725 cmparam.nonce = &b0[1]; /* N */
4446977Szf162725 cmparam.authData = &aad[2]; /* A */
4456977Szf162725
4466977Szf162725 rv = aes_ccm_encrypt(&cmparam,
4476977Szf162725 key->wk_key, key->wk_keylen,
4488383SQuaker.Fang@Sun.COM pos, data_len, pos, data_len + IEEE80211_WEP_MICLEN);
4496977Szf162725
4506977Szf162725 mp->b_wptr += ccmp.ic_trailer;
4516977Szf162725
4526977Szf162725 return ((rv == CRYPTO_SUCCESS)? 1 : 0);
4536977Szf162725 }
4546977Szf162725
4556977Szf162725 static int
ccmp_decrypt(struct ieee80211_key * key,uint64_t pn,mblk_t * mp,int hdrlen)4566977Szf162725 ccmp_decrypt(struct ieee80211_key *key, uint64_t pn, mblk_t *mp, int hdrlen)
4576977Szf162725 {
4586977Szf162725 struct ieee80211_frame *wh;
4596977Szf162725 int rv, data_len;
4606977Szf162725 uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
4616977Szf162725 uint8_t *pos;
4626977Szf162725 CK_AES_CCM_PARAMS cmparam;
4636977Szf162725
4646977Szf162725 wh = (struct ieee80211_frame *)mp->b_rptr;
4657249Sff224033 data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
4666977Szf162725 pos = mp->b_rptr + hdrlen + ccmp.ic_header;
4676977Szf162725
4686977Szf162725 ccmp_init(wh, pn, data_len, b0, aad);
4696977Szf162725
4706977Szf162725 cmparam.ulMACSize = IEEE80211_WEP_MICLEN; /* MIC = 8 */
4716977Szf162725 cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
4726977Szf162725 cmparam.ulAuthDataSize = aad[1]; /* A size */
4736977Szf162725 cmparam.ulDataSize = data_len;
4746977Szf162725 cmparam.nonce = &b0[1]; /* N */
4756977Szf162725 cmparam.authData = &aad[2]; /* A */
4766977Szf162725
4776977Szf162725 rv = aes_ccm_decrypt(&cmparam,
4788383SQuaker.Fang@Sun.COM key->wk_key, key->wk_keylen, pos, data_len, pos, data_len);
4796977Szf162725
4806977Szf162725 return ((rv == CRYPTO_SUCCESS)? 1 : 0);
4816977Szf162725 }
482