a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Use is subject to license terms.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Copyright (c) 2001 Atsushi Onoe
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
a399b7655a1d835aa8606c2b29e4e777baac8635zf * All rights reserved.
a399b7655a1d835aa8606c2b29e4e777baac8635zf *
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Redistribution and use in source and binary forms, with or without
a399b7655a1d835aa8606c2b29e4e777baac8635zf * modification, are permitted provided that the following conditions
a399b7655a1d835aa8606c2b29e4e777baac8635zf * are met:
a399b7655a1d835aa8606c2b29e4e777baac8635zf * 1. Redistributions of source code must retain the above copyright
a399b7655a1d835aa8606c2b29e4e777baac8635zf * notice, this list of conditions and the following disclaimer.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * 2. Redistributions in binary form must reproduce the above copyright
a399b7655a1d835aa8606c2b29e4e777baac8635zf * notice, this list of conditions and the following disclaimer in the
a399b7655a1d835aa8606c2b29e4e777baac8635zf * documentation and/or other materials provided with the distribution.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * 3. The name of the author may not be used to endorse or promote products
a399b7655a1d835aa8606c2b29e4e777baac8635zf * derived from this software without specific prior written permission.
a399b7655a1d835aa8606c2b29e4e777baac8635zf *
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Alternatively, this software may be distributed under the terms of the
a399b7655a1d835aa8606c2b29e4e777baac8635zf * GNU General Public License ("GPL") version 2 as published by the Free
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Software Foundation.
a399b7655a1d835aa8606c2b29e4e777baac8635zf *
a399b7655a1d835aa8606c2b29e4e777baac8635zf * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
a399b7655a1d835aa8606c2b29e4e777baac8635zf * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
a399b7655a1d835aa8606c2b29e4e777baac8635zf * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
a399b7655a1d835aa8606c2b29e4e777baac8635zf * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
a399b7655a1d835aa8606c2b29e4e777baac8635zf * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
a399b7655a1d835aa8606c2b29e4e777baac8635zf * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
a399b7655a1d835aa8606c2b29e4e777baac8635zf * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
a399b7655a1d835aa8606c2b29e4e777baac8635zf * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
a399b7655a1d835aa8606c2b29e4e777baac8635zf * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * IEEE 802.11i CCMP crypto support.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include <sys/byteorder.h>
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include <sys/crypto/common.h>
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include <sys/crypto/api.h>
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include <sys/crc32.h>
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include <sys/random.h>
ff3124eff995e6cd8ebd8c6543648e0670920034ff#include <sys/strsun.h>
a399b7655a1d835aa8606c2b29e4e777baac8635zf#include "net80211_impl.h"
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zfstruct ccmp_ctx {
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ieee80211com *cc_ic; /* for diagnostics */
a399b7655a1d835aa8606c2b29e4e777baac8635zf};
a399b7655a1d835aa8606c2b29e4e777baac8635zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#define AES_BLOCK_LEN 16
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#define AES_NONCE_LEN 13
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic void *ccmp_attach(struct ieee80211com *, struct ieee80211_key *);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic void ccmp_detach(struct ieee80211_key *);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int ccmp_setkey(struct ieee80211_key *);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int ccmp_encap(struct ieee80211_key *k, mblk_t *, uint8_t);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int ccmp_decap(struct ieee80211_key *, mblk_t *, int);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int ccmp_enmic(struct ieee80211_key *, mblk_t *, int);
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int ccmp_demic(struct ieee80211_key *, mblk_t *, int);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int ccmp_encrypt(struct ieee80211_key *, mblk_t *, int);
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int ccmp_decrypt(struct ieee80211_key *, uint64_t pn, mblk_t *, int);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
a399b7655a1d835aa8606c2b29e4e777baac8635zfconst struct ieee80211_cipher ccmp = {
a399b7655a1d835aa8606c2b29e4e777baac8635zf "AES-CCM",
a399b7655a1d835aa8606c2b29e4e777baac8635zf IEEE80211_CIPHER_AES_CCM,
a399b7655a1d835aa8606c2b29e4e777baac8635zf IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
a399b7655a1d835aa8606c2b29e4e777baac8635zf IEEE80211_WEP_EXTIVLEN,
a399b7655a1d835aa8606c2b29e4e777baac8635zf IEEE80211_WEP_MICLEN,
a399b7655a1d835aa8606c2b29e4e777baac8635zf 0,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_attach,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_detach,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_setkey,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_encap,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_decap,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_enmic,
a399b7655a1d835aa8606c2b29e4e777baac8635zf ccmp_demic,
a399b7655a1d835aa8606c2b29e4e777baac8635zf};
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/* ARGSUSED */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic void *
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_attach(struct ieee80211com *ic, struct ieee80211_key *k)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ccmp_ctx *ctx;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf ctx = kmem_zalloc(sizeof (struct ccmp_ctx), KM_SLEEP);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ctx == NULL)
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (NULL);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf ctx->cc_ic = ic;
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (ctx);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic void
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_detach(struct ieee80211_key *k)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ccmp_ctx *ctx = k->wk_private;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ctx != NULL)
a399b7655a1d835aa8606c2b29e4e777baac8635zf kmem_free(ctx, sizeof (struct ccmp_ctx));
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_setkey(struct ieee80211_key *k)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (k->wk_keylen != (128/NBBY))
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Add privacy headers appropriate for the specified key.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ccmp_ctx *ctx = k->wk_private;
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint8_t *ivp;
a399b7655a1d835aa8606c2b29e4e777baac8635zf int hdrlen;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang hdrlen = ieee80211_hdrspace(ctx->cc_ic, mp->b_rptr);
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp = mp->b_rptr;
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp += hdrlen;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf k->wk_keytsc++; /* wrap at 48 bits */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[0] = k->wk_keytsc >> 0; /* PN0 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[1] = k->wk_keytsc >> 8; /* PN1 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[2] = 0; /* Reserved */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[4] = k->wk_keytsc >> 16; /* PN2 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[5] = k->wk_keytsc >> 24; /* PN3 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[6] = k->wk_keytsc >> 32; /* PN4 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp[7] = k->wk_keytsc >> 40; /* PN5 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Finally, do software encrypt if neeed.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
5a8842de5fe559531366f065b0f32f31b6dd09b0zf !ccmp_encrypt(k, mp, hdrlen))
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Validate and strip privacy headers (and trailer) for a
a399b7655a1d835aa8606c2b29e4e777baac8635zf * received frame. The specified key should be correct but
a399b7655a1d835aa8606c2b29e4e777baac8635zf * is also verified.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint8_t *ivp;
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint64_t pn;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Header should have extended IV and sequence number;
a399b7655a1d835aa8606c2b29e4e777baac8635zf * verify the former and validate the latter.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf ivp = mp->b_rptr + hdrlen;
a399b7655a1d835aa8606c2b29e4e777baac8635zf if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * No extended IV; discard frame.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf pn = ieee80211_read_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (pn <= k->wk_keyrsc) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Replay violation.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Check if the device handled the decrypt in hardware.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * If so we just strip the header; otherwise we need to
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * handle the decrypt in software. Note that for the
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * latter we leave the header in place for use in the
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * decryption work.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
5a8842de5fe559531366f065b0f32f31b6dd09b0zf !ccmp_decrypt(k, pn, mp, hdrlen))
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Copy up 802.11 header and strip crypto bits.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (void) memmove(mp->b_rptr + ccmp.ic_header, mp->b_rptr, hdrlen);
a399b7655a1d835aa8606c2b29e4e777baac8635zf mp->b_rptr += ccmp.ic_header;
a399b7655a1d835aa8606c2b29e4e777baac8635zf mp->b_wptr -= ccmp.ic_trailer;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Ok to update rsc now.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf k->wk_keyrsc = pn;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Add MIC to the frame as needed.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf/* ARGSUSED */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Verify and strip MIC from the frame.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf/* ARGSUSED */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfccmp_demic(struct ieee80211_key *k, mblk_t *mp, int force)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int
5a8842de5fe559531366f065b0f32f31b6dd09b0zfaes_ccm_encrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf const uint8_t *plaintext, int plain_len,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t *ciphertext, int cipher_len)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf{
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_mechanism_t mech;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_key_t crkey;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_data_t d1, d2;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf int rv;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf "aes_ccm_encrypt(len=%d, keylen=%d)", plain_len, keylen);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&crkey, sizeof (crkey));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_format = CRYPTO_KEY_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_data = (char *)key;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /* keys are measured in bits, not bytes, so multiply by 8 */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_length = keylen * 8;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_param = (caddr_t)cmparam;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#if defined(__amd64) || defined(__sparc)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#else
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#endif
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&d1, sizeof (d1));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&d2, sizeof (d2));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_format = CRYPTO_DATA_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_offset = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_length = plain_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_raw.iov_base = (char *)plaintext;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_raw.iov_len = plain_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_format = CRYPTO_DATA_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_offset = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_length = cipher_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_raw.iov_base = (char *)ciphertext;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_raw.iov_len = cipher_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf rv = crypto_encrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf if (rv != CRYPTO_SUCCESS)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_err("aes_ccm_encrypt failed (%x)", rv);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf return (rv);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf}
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int
5a8842de5fe559531366f065b0f32f31b6dd09b0zfaes_ccm_decrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf const uint8_t *ciphertext, int cipher_len,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t *plaintext, int plain_len)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf{
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_mechanism_t mech;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_key_t crkey;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crypto_data_t d1, d2;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf int rv;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf "aes_ccm_decrypt(len=%d, keylen=%d)", cipher_len, keylen);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&crkey, sizeof (crkey));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_format = CRYPTO_KEY_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_data = (char *)key;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /* keys are measured in bits, not bytes, so multiply by 8 */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf crkey.ck_length = keylen * 8;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_param = (caddr_t)cmparam;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#if defined(__amd64) || defined(__sparc)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#else
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf#endif
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&d1, sizeof (d1));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf bzero(&d2, sizeof (d2));
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_format = CRYPTO_DATA_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_offset = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_length = cipher_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_raw.iov_base = (char *)ciphertext;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d1.cd_raw.iov_len = cipher_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_format = CRYPTO_DATA_RAW;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_offset = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_length = plain_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_raw.iov_base = (char *)plaintext;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf d2.cd_raw.iov_len = plain_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf rv = crypto_decrypt(&mech, &d1, &crkey, NULL, &d2, NULL);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf if (rv != CRYPTO_SUCCESS)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ieee80211_err("aes_ccm_decrypt failed (%x)", rv);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf return (rv);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf}
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf/*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * For the avoidance of doubt, except that if any license choice other
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * than GPL or LGPL is available it will apply instead, Sun elects to
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * use only the General Public License version 2 (GPLv2) at this time
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * for any software where a choice of GPL license versions is made
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * available with the language indicating that GPLv2 or any later
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * version may be used, or where a choice of which version of the GPL
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * is applied is otherwise unspecified.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf/*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * This program is free software; you can redistribute it and/or modify
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * it under the terms of the GNU General Public License version 2 as
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * published by the Free Software Foundation. See README and COPYING for
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * more details.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Alternatively, this software may be distributed under the terms of BSD
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * license.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic void
5a8842de5fe559531366f065b0f32f31b6dd09b0zfccmp_init(struct ieee80211_frame *wh, uint64_t pn, size_t dlen,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN])
5a8842de5fe559531366f065b0f32f31b6dd09b0zf{
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * CCM Initial Block:
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Flag (Include authentication header, M=3 (8-octet MIC),
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * L=1 (2-octet Dlen))
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Nonce: 0x00 | A2 | PN
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Dlen
5a8842de5fe559531366f065b0f32f31b6dd09b0zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[0] = 0x59;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /* b0[1] set below */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[8] = pn >> 40;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[9] = pn >> 32;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[10] = pn >> 24;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[11] = pn >> 16;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[12] = pn >> 8;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[13] = (uint8_t)(pn >> 0);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[14] = (dlen >> 8) & 0xff;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf b0[15] = dlen & 0xff;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * AAD:
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * A1 | A2 | A3
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * SC with bits 4..15 (seq#) masked to zero
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * A4 (if present)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * QC (if present)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf aad[0] = 0; /* AAD length >> 8 */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /* aad[1] set below */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf aad[2] = wh->i_fc[0] & 0x8f; /* magic #s */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf aad[3] = wh->i_fc[1] & 0xc7; /* magic #s */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /* we know 3 addresses are contiguous */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf (void) memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf aad[23] = 0; /* all bits masked */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf /*
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * Construct variable-length portion of AAD based
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * on whether this is a 4-address frame/QOS frame.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * We always zero-pad to 32 bytes before running it
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * through the cipher.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * We also fill in the priority bits of the CCM
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * initial block as we know whether or not we have
5a8842de5fe559531366f065b0f32f31b6dd09b0zf * a QOS frame.
5a8842de5fe559531366f065b0f32f31b6dd09b0zf */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_QOS_HAS_SEQ(wh)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ieee80211_qosframe *qwh =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (struct ieee80211_qosframe *)wh;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang aad[24] = qwh->i_qos[0] & 0x0f; /* just priority bits */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang aad[25] = 0;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang b0[1] = aad[24];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang aad[1] = 22 + 2;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *(uint16_t *)&aad[24] = 0;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang b0[1] = 0;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang aad[1] = 22;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *(uint16_t *)&aad[26] = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf *(uint32_t *)&aad[28] = 0;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf}
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int
5a8842de5fe559531366f065b0f32f31b6dd09b0zfccmp_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf{
5a8842de5fe559531366f065b0f32f31b6dd09b0zf struct ieee80211_frame *wh;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf int rv, data_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t *pos;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf CK_AES_CCM_PARAMS cmparam;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf wh = (struct ieee80211_frame *)mp->b_rptr;
ff3124eff995e6cd8ebd8c6543648e0670920034ff data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf pos = mp->b_rptr + hdrlen + ccmp.ic_header;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ccmp_init(wh, key->wk_keytsc, data_len, b0, aad);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulMACSize = IEEE80211_WEP_MICLEN;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulAuthDataSize = aad[1]; /* A size */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulDataSize = data_len; /* data length; */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.nonce = &b0[1]; /* N */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.authData = &aad[2]; /* A */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf rv = aes_ccm_encrypt(&cmparam,
5a8842de5fe559531366f065b0f32f31b6dd09b0zf key->wk_key, key->wk_keylen,
51e5a319aebb4a8c4d5dce22f31c832366a26943Quaker Fang pos, data_len, pos, data_len + IEEE80211_WEP_MICLEN);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf mp->b_wptr += ccmp.ic_trailer;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf return ((rv == CRYPTO_SUCCESS)? 1 : 0);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf}
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zfstatic int
5a8842de5fe559531366f065b0f32f31b6dd09b0zfccmp_decrypt(struct ieee80211_key *key, uint64_t pn, mblk_t *mp, int hdrlen)
5a8842de5fe559531366f065b0f32f31b6dd09b0zf{
5a8842de5fe559531366f065b0f32f31b6dd09b0zf struct ieee80211_frame *wh;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf int rv, data_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN];
5a8842de5fe559531366f065b0f32f31b6dd09b0zf uint8_t *pos;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf CK_AES_CCM_PARAMS cmparam;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf wh = (struct ieee80211_frame *)mp->b_rptr;
ff3124eff995e6cd8ebd8c6543648e0670920034ff data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf pos = mp->b_rptr + hdrlen + ccmp.ic_header;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf ccmp_init(wh, pn, data_len, b0, aad);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulMACSize = IEEE80211_WEP_MICLEN; /* MIC = 8 */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulAuthDataSize = aad[1]; /* A size */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.ulDataSize = data_len;
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.nonce = &b0[1]; /* N */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf cmparam.authData = &aad[2]; /* A */
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf rv = aes_ccm_decrypt(&cmparam,
51e5a319aebb4a8c4d5dce22f31c832366a26943Quaker Fang key->wk_key, key->wk_keylen, pos, data_len, pos, data_len);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf
5a8842de5fe559531366f065b0f32f31b6dd09b0zf return ((rv == CRYPTO_SUCCESS)? 1 : 0);
5a8842de5fe559531366f065b0f32f31b6dd09b0zf}