1*2d4583c4SAdrian Chadd /*- 2*2d4583c4SAdrian Chadd * SPDX-License-Identifier: BSD-2-Clause 3*2d4583c4SAdrian Chadd * 4*2d4583c4SAdrian Chadd * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 5*2d4583c4SAdrian Chadd * All rights reserved. 6*2d4583c4SAdrian Chadd * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>. 7*2d4583c4SAdrian Chadd * 8*2d4583c4SAdrian Chadd * Redistribution and use in source and binary forms, with or without 9*2d4583c4SAdrian Chadd * modification, are permitted provided that the following conditions 10*2d4583c4SAdrian Chadd * are met: 11*2d4583c4SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 12*2d4583c4SAdrian Chadd * notice, this list of conditions and the following disclaimer. 13*2d4583c4SAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright 14*2d4583c4SAdrian Chadd * notice, this list of conditions and the following disclaimer in the 15*2d4583c4SAdrian Chadd * documentation and/or other materials provided with the distribution. 16*2d4583c4SAdrian Chadd * 17*2d4583c4SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18*2d4583c4SAdrian Chadd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19*2d4583c4SAdrian Chadd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*2d4583c4SAdrian Chadd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21*2d4583c4SAdrian Chadd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22*2d4583c4SAdrian Chadd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23*2d4583c4SAdrian Chadd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24*2d4583c4SAdrian Chadd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25*2d4583c4SAdrian Chadd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26*2d4583c4SAdrian Chadd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*2d4583c4SAdrian Chadd */ 28*2d4583c4SAdrian Chadd 29*2d4583c4SAdrian Chadd /* 30*2d4583c4SAdrian Chadd * IEEE 802.11 AES-GCMP crypto support. 31*2d4583c4SAdrian Chadd * 32*2d4583c4SAdrian Chadd * The AES-GCM crypto routines in sys/net80211/ieee80211_crypto_gcm.[ch] 33*2d4583c4SAdrian Chadd * are derived from similar code in hostapd 2.11 (src/crypto/aes-gcm.c). 34*2d4583c4SAdrian Chadd * The code is used with the consent of the author and its licence is 35*2d4583c4SAdrian Chadd * included in the above source files. 36*2d4583c4SAdrian Chadd */ 37*2d4583c4SAdrian Chadd #include "opt_wlan.h" 38*2d4583c4SAdrian Chadd 39*2d4583c4SAdrian Chadd #include <sys/param.h> 40*2d4583c4SAdrian Chadd #include <sys/systm.h> 41*2d4583c4SAdrian Chadd #include <sys/mbuf.h> 42*2d4583c4SAdrian Chadd #include <sys/malloc.h> 43*2d4583c4SAdrian Chadd #include <sys/kernel.h> 44*2d4583c4SAdrian Chadd #include <sys/module.h> 45*2d4583c4SAdrian Chadd 46*2d4583c4SAdrian Chadd #include <sys/socket.h> 47*2d4583c4SAdrian Chadd 48*2d4583c4SAdrian Chadd #include <net/if.h> 49*2d4583c4SAdrian Chadd #include <net/if_media.h> 50*2d4583c4SAdrian Chadd #include <net/ethernet.h> 51*2d4583c4SAdrian Chadd 52*2d4583c4SAdrian Chadd #include <net80211/ieee80211_var.h> 53*2d4583c4SAdrian Chadd #include <net80211/ieee80211_crypto_gcm.h> 54*2d4583c4SAdrian Chadd 55*2d4583c4SAdrian Chadd #include <crypto/rijndael/rijndael.h> 56*2d4583c4SAdrian Chadd 57*2d4583c4SAdrian Chadd #define AES_BLOCK_LEN 16 58*2d4583c4SAdrian Chadd 59*2d4583c4SAdrian Chadd /* 60*2d4583c4SAdrian Chadd * Note: GCMP_MIC_LEN defined in ieee80211_crypto_gcm.h, as it is also 61*2d4583c4SAdrian Chadd * used by the AES-GCM routines for sizing the S and T hashes which are 62*2d4583c4SAdrian Chadd * used by GCMP as the MIC. 63*2d4583c4SAdrian Chadd */ 64*2d4583c4SAdrian Chadd #define GCMP_PN_LEN 6 65*2d4583c4SAdrian Chadd #define GCMP_IV_LEN 12 66*2d4583c4SAdrian Chadd 67*2d4583c4SAdrian Chadd struct gcmp_ctx { 68*2d4583c4SAdrian Chadd struct ieee80211vap *cc_vap; /* for diagnostics+statistics */ 69*2d4583c4SAdrian Chadd struct ieee80211com *cc_ic; 70*2d4583c4SAdrian Chadd rijndael_ctx cc_aes; 71*2d4583c4SAdrian Chadd }; 72*2d4583c4SAdrian Chadd 73*2d4583c4SAdrian Chadd static void *gcmp_attach(struct ieee80211vap *, struct ieee80211_key *); 74*2d4583c4SAdrian Chadd static void gcmp_detach(struct ieee80211_key *); 75*2d4583c4SAdrian Chadd static int gcmp_setkey(struct ieee80211_key *); 76*2d4583c4SAdrian Chadd static void gcmp_setiv(struct ieee80211_key *, uint8_t *); 77*2d4583c4SAdrian Chadd static int gcmp_encap(struct ieee80211_key *, struct mbuf *); 78*2d4583c4SAdrian Chadd static int gcmp_decap(struct ieee80211_key *, struct mbuf *, int); 79*2d4583c4SAdrian Chadd static int gcmp_enmic(struct ieee80211_key *, struct mbuf *, int); 80*2d4583c4SAdrian Chadd static int gcmp_demic(struct ieee80211_key *, struct mbuf *, int); 81*2d4583c4SAdrian Chadd 82*2d4583c4SAdrian Chadd static const struct ieee80211_cipher gcmp = { 83*2d4583c4SAdrian Chadd .ic_name = "AES-GCMP", 84*2d4583c4SAdrian Chadd .ic_cipher = IEEE80211_CIPHER_AES_GCM_128, 85*2d4583c4SAdrian Chadd .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 86*2d4583c4SAdrian Chadd IEEE80211_WEP_EXTIVLEN, 87*2d4583c4SAdrian Chadd .ic_trailer = GCMP_MIC_LEN, 88*2d4583c4SAdrian Chadd .ic_miclen = 0, 89*2d4583c4SAdrian Chadd .ic_attach = gcmp_attach, 90*2d4583c4SAdrian Chadd .ic_detach = gcmp_detach, 91*2d4583c4SAdrian Chadd .ic_setkey = gcmp_setkey, 92*2d4583c4SAdrian Chadd .ic_setiv = gcmp_setiv, 93*2d4583c4SAdrian Chadd .ic_encap = gcmp_encap, 94*2d4583c4SAdrian Chadd .ic_decap = gcmp_decap, 95*2d4583c4SAdrian Chadd .ic_enmic = gcmp_enmic, 96*2d4583c4SAdrian Chadd .ic_demic = gcmp_demic, 97*2d4583c4SAdrian Chadd }; 98*2d4583c4SAdrian Chadd 99*2d4583c4SAdrian Chadd static const struct ieee80211_cipher gcmp_256 = { 100*2d4583c4SAdrian Chadd .ic_name = "AES-GCMP-256", 101*2d4583c4SAdrian Chadd .ic_cipher = IEEE80211_CIPHER_AES_GCM_256, 102*2d4583c4SAdrian Chadd .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 103*2d4583c4SAdrian Chadd IEEE80211_WEP_EXTIVLEN, 104*2d4583c4SAdrian Chadd .ic_trailer = GCMP_MIC_LEN, 105*2d4583c4SAdrian Chadd .ic_miclen = 0, 106*2d4583c4SAdrian Chadd .ic_attach = gcmp_attach, 107*2d4583c4SAdrian Chadd .ic_detach = gcmp_detach, 108*2d4583c4SAdrian Chadd .ic_setkey = gcmp_setkey, 109*2d4583c4SAdrian Chadd .ic_setiv = gcmp_setiv, 110*2d4583c4SAdrian Chadd .ic_encap = gcmp_encap, 111*2d4583c4SAdrian Chadd .ic_decap = gcmp_decap, 112*2d4583c4SAdrian Chadd .ic_enmic = gcmp_enmic, 113*2d4583c4SAdrian Chadd .ic_demic = gcmp_demic, 114*2d4583c4SAdrian Chadd }; 115*2d4583c4SAdrian Chadd 116*2d4583c4SAdrian Chadd 117*2d4583c4SAdrian Chadd static int gcmp_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen); 118*2d4583c4SAdrian Chadd static int gcmp_decrypt(struct ieee80211_key *, u_int64_t pn, 119*2d4583c4SAdrian Chadd struct mbuf *, int hdrlen); 120*2d4583c4SAdrian Chadd 121*2d4583c4SAdrian Chadd /* number of references from net80211 layer */ 122*2d4583c4SAdrian Chadd static int nrefs = 0; 123*2d4583c4SAdrian Chadd 124*2d4583c4SAdrian Chadd static void * 125*2d4583c4SAdrian Chadd gcmp_attach(struct ieee80211vap *vap, struct ieee80211_key *k) 126*2d4583c4SAdrian Chadd { 127*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx; 128*2d4583c4SAdrian Chadd 129*2d4583c4SAdrian Chadd ctx = (struct gcmp_ctx *) IEEE80211_MALLOC(sizeof(struct gcmp_ctx), 130*2d4583c4SAdrian Chadd M_80211_CRYPTO, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 131*2d4583c4SAdrian Chadd if (ctx == NULL) { 132*2d4583c4SAdrian Chadd vap->iv_stats.is_crypto_nomem++; 133*2d4583c4SAdrian Chadd return (NULL); 134*2d4583c4SAdrian Chadd } 135*2d4583c4SAdrian Chadd ctx->cc_vap = vap; 136*2d4583c4SAdrian Chadd ctx->cc_ic = vap->iv_ic; 137*2d4583c4SAdrian Chadd nrefs++; /* NB: we assume caller locking */ 138*2d4583c4SAdrian Chadd return (ctx); 139*2d4583c4SAdrian Chadd } 140*2d4583c4SAdrian Chadd 141*2d4583c4SAdrian Chadd static void 142*2d4583c4SAdrian Chadd gcmp_detach(struct ieee80211_key *k) 143*2d4583c4SAdrian Chadd { 144*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = k->wk_private; 145*2d4583c4SAdrian Chadd 146*2d4583c4SAdrian Chadd IEEE80211_FREE(ctx, M_80211_CRYPTO); 147*2d4583c4SAdrian Chadd KASSERT(nrefs > 0, ("imbalanced attach/detach")); 148*2d4583c4SAdrian Chadd nrefs--; /* NB: we assume caller locking */ 149*2d4583c4SAdrian Chadd } 150*2d4583c4SAdrian Chadd 151*2d4583c4SAdrian Chadd static int 152*2d4583c4SAdrian Chadd gcmp_get_trailer_len(struct ieee80211_key *k) 153*2d4583c4SAdrian Chadd { 154*2d4583c4SAdrian Chadd return (k->wk_cipher->ic_trailer); 155*2d4583c4SAdrian Chadd } 156*2d4583c4SAdrian Chadd 157*2d4583c4SAdrian Chadd static int 158*2d4583c4SAdrian Chadd gcmp_get_header_len(struct ieee80211_key *k) 159*2d4583c4SAdrian Chadd { 160*2d4583c4SAdrian Chadd return (k->wk_cipher->ic_header); 161*2d4583c4SAdrian Chadd } 162*2d4583c4SAdrian Chadd 163*2d4583c4SAdrian Chadd static int 164*2d4583c4SAdrian Chadd gcmp_setkey(struct ieee80211_key *k) 165*2d4583c4SAdrian Chadd { 166*2d4583c4SAdrian Chadd uint32_t keylen; 167*2d4583c4SAdrian Chadd 168*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = k->wk_private; 169*2d4583c4SAdrian Chadd 170*2d4583c4SAdrian Chadd switch (k->wk_cipher->ic_cipher) { 171*2d4583c4SAdrian Chadd case IEEE80211_CIPHER_AES_GCM_128: 172*2d4583c4SAdrian Chadd keylen = 128; 173*2d4583c4SAdrian Chadd break; 174*2d4583c4SAdrian Chadd case IEEE80211_CIPHER_AES_GCM_256: 175*2d4583c4SAdrian Chadd keylen = 256; 176*2d4583c4SAdrian Chadd break; 177*2d4583c4SAdrian Chadd default: 178*2d4583c4SAdrian Chadd IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO, 179*2d4583c4SAdrian Chadd "%s: Unexpected cipher (%u)", 180*2d4583c4SAdrian Chadd __func__, k->wk_cipher->ic_cipher); 181*2d4583c4SAdrian Chadd return (0); 182*2d4583c4SAdrian Chadd } 183*2d4583c4SAdrian Chadd 184*2d4583c4SAdrian Chadd if (k->wk_keylen != (keylen/NBBY)) { 185*2d4583c4SAdrian Chadd IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO, 186*2d4583c4SAdrian Chadd "%s: Invalid key length %u, expecting %u\n", 187*2d4583c4SAdrian Chadd __func__, k->wk_keylen, keylen/NBBY); 188*2d4583c4SAdrian Chadd return (0); 189*2d4583c4SAdrian Chadd } 190*2d4583c4SAdrian Chadd if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) 191*2d4583c4SAdrian Chadd rijndael_set_key(&ctx->cc_aes, k->wk_key, k->wk_keylen*NBBY); 192*2d4583c4SAdrian Chadd return (1); 193*2d4583c4SAdrian Chadd } 194*2d4583c4SAdrian Chadd 195*2d4583c4SAdrian Chadd static void 196*2d4583c4SAdrian Chadd gcmp_setiv(struct ieee80211_key *k, uint8_t *ivp) 197*2d4583c4SAdrian Chadd { 198*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = k->wk_private; 199*2d4583c4SAdrian Chadd struct ieee80211vap *vap = ctx->cc_vap; 200*2d4583c4SAdrian Chadd uint8_t keyid; 201*2d4583c4SAdrian Chadd 202*2d4583c4SAdrian Chadd keyid = ieee80211_crypto_get_keyid(vap, k) << 6; 203*2d4583c4SAdrian Chadd 204*2d4583c4SAdrian Chadd k->wk_keytsc++; 205*2d4583c4SAdrian Chadd ivp[0] = k->wk_keytsc >> 0; /* PN0 */ 206*2d4583c4SAdrian Chadd ivp[1] = k->wk_keytsc >> 8; /* PN1 */ 207*2d4583c4SAdrian Chadd ivp[2] = 0; /* Reserved */ 208*2d4583c4SAdrian Chadd ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ 209*2d4583c4SAdrian Chadd ivp[4] = k->wk_keytsc >> 16; /* PN2 */ 210*2d4583c4SAdrian Chadd ivp[5] = k->wk_keytsc >> 24; /* PN3 */ 211*2d4583c4SAdrian Chadd ivp[6] = k->wk_keytsc >> 32; /* PN4 */ 212*2d4583c4SAdrian Chadd ivp[7] = k->wk_keytsc >> 40; /* PN5 */ 213*2d4583c4SAdrian Chadd } 214*2d4583c4SAdrian Chadd 215*2d4583c4SAdrian Chadd /* 216*2d4583c4SAdrian Chadd * Add privacy headers appropriate for the specified key. 217*2d4583c4SAdrian Chadd */ 218*2d4583c4SAdrian Chadd static int 219*2d4583c4SAdrian Chadd gcmp_encap(struct ieee80211_key *k, struct mbuf *m) 220*2d4583c4SAdrian Chadd { 221*2d4583c4SAdrian Chadd const struct ieee80211_frame *wh; 222*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = k->wk_private; 223*2d4583c4SAdrian Chadd struct ieee80211com *ic = ctx->cc_ic; 224*2d4583c4SAdrian Chadd uint8_t *ivp; 225*2d4583c4SAdrian Chadd int hdrlen; 226*2d4583c4SAdrian Chadd int is_mgmt; 227*2d4583c4SAdrian Chadd 228*2d4583c4SAdrian Chadd hdrlen = ieee80211_hdrspace(ic, mtod(m, void *)); 229*2d4583c4SAdrian Chadd wh = mtod(m, const struct ieee80211_frame *); 230*2d4583c4SAdrian Chadd is_mgmt = IEEE80211_IS_MGMT(wh); 231*2d4583c4SAdrian Chadd 232*2d4583c4SAdrian Chadd /* 233*2d4583c4SAdrian Chadd * Check to see if we need to insert IV/MIC. 234*2d4583c4SAdrian Chadd * 235*2d4583c4SAdrian Chadd * Some offload devices don't require the IV to be inserted 236*2d4583c4SAdrian Chadd * as part of the hardware encryption. 237*2d4583c4SAdrian Chadd */ 238*2d4583c4SAdrian Chadd if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT)) 239*2d4583c4SAdrian Chadd return (1); 240*2d4583c4SAdrian Chadd if (!is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIV)) 241*2d4583c4SAdrian Chadd return (1); 242*2d4583c4SAdrian Chadd 243*2d4583c4SAdrian Chadd /* 244*2d4583c4SAdrian Chadd * Copy down 802.11 header and add the IV, KeyID, and ExtIV. 245*2d4583c4SAdrian Chadd */ 246*2d4583c4SAdrian Chadd M_PREPEND(m, gcmp_get_header_len(k), IEEE80211_M_NOWAIT); 247*2d4583c4SAdrian Chadd if (m == NULL) 248*2d4583c4SAdrian Chadd return (0); 249*2d4583c4SAdrian Chadd ivp = mtod(m, uint8_t *); 250*2d4583c4SAdrian Chadd ovbcopy(ivp + gcmp_get_header_len(k), ivp, hdrlen); 251*2d4583c4SAdrian Chadd ivp += hdrlen; 252*2d4583c4SAdrian Chadd 253*2d4583c4SAdrian Chadd gcmp_setiv(k, ivp); 254*2d4583c4SAdrian Chadd 255*2d4583c4SAdrian Chadd /* 256*2d4583c4SAdrian Chadd * Finally, do software encrypt if needed. 257*2d4583c4SAdrian Chadd */ 258*2d4583c4SAdrian Chadd if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) && 259*2d4583c4SAdrian Chadd !gcmp_encrypt(k, m, hdrlen)) 260*2d4583c4SAdrian Chadd return (0); 261*2d4583c4SAdrian Chadd 262*2d4583c4SAdrian Chadd return (1); 263*2d4583c4SAdrian Chadd } 264*2d4583c4SAdrian Chadd 265*2d4583c4SAdrian Chadd /* 266*2d4583c4SAdrian Chadd * Add MIC to the frame as needed. 267*2d4583c4SAdrian Chadd */ 268*2d4583c4SAdrian Chadd static int 269*2d4583c4SAdrian Chadd gcmp_enmic(struct ieee80211_key *k, struct mbuf *m, int force) 270*2d4583c4SAdrian Chadd { 271*2d4583c4SAdrian Chadd return (1); 272*2d4583c4SAdrian Chadd } 273*2d4583c4SAdrian Chadd 274*2d4583c4SAdrian Chadd static __inline uint64_t 275*2d4583c4SAdrian Chadd READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) 276*2d4583c4SAdrian Chadd { 277*2d4583c4SAdrian Chadd uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24); 278*2d4583c4SAdrian Chadd uint16_t iv16 = (b4 << 0) | (b5 << 8); 279*2d4583c4SAdrian Chadd return ((((uint64_t)iv16) << 32) | iv32); 280*2d4583c4SAdrian Chadd } 281*2d4583c4SAdrian Chadd 282*2d4583c4SAdrian Chadd /* 283*2d4583c4SAdrian Chadd * Validate and strip privacy headers (and trailer) for a 284*2d4583c4SAdrian Chadd * received frame. The specified key should be correct but 285*2d4583c4SAdrian Chadd * is also verified. 286*2d4583c4SAdrian Chadd */ 287*2d4583c4SAdrian Chadd static int 288*2d4583c4SAdrian Chadd gcmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) 289*2d4583c4SAdrian Chadd { 290*2d4583c4SAdrian Chadd const struct ieee80211_rx_stats *rxs; 291*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = k->wk_private; 292*2d4583c4SAdrian Chadd struct ieee80211vap *vap = ctx->cc_vap; 293*2d4583c4SAdrian Chadd struct ieee80211_frame *wh; 294*2d4583c4SAdrian Chadd uint8_t *ivp, tid; 295*2d4583c4SAdrian Chadd uint64_t pn; 296*2d4583c4SAdrian Chadd bool noreplaycheck; 297*2d4583c4SAdrian Chadd 298*2d4583c4SAdrian Chadd rxs = ieee80211_get_rx_params_ptr(m); 299*2d4583c4SAdrian Chadd 300*2d4583c4SAdrian Chadd if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) != 0) 301*2d4583c4SAdrian Chadd goto finish; 302*2d4583c4SAdrian Chadd 303*2d4583c4SAdrian Chadd /* 304*2d4583c4SAdrian Chadd * Header should have extended IV and sequence number; 305*2d4583c4SAdrian Chadd * verify the former and validate the latter. 306*2d4583c4SAdrian Chadd */ 307*2d4583c4SAdrian Chadd wh = mtod(m, struct ieee80211_frame *); 308*2d4583c4SAdrian Chadd ivp = mtod(m, uint8_t *) + hdrlen; 309*2d4583c4SAdrian Chadd if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { 310*2d4583c4SAdrian Chadd /* 311*2d4583c4SAdrian Chadd * No extended IV; discard frame. 312*2d4583c4SAdrian Chadd */ 313*2d4583c4SAdrian Chadd IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 314*2d4583c4SAdrian Chadd "%s", "missing ExtIV for AES-GCM cipher"); 315*2d4583c4SAdrian Chadd vap->iv_stats.is_rx_gcmpformat++; 316*2d4583c4SAdrian Chadd return (0); 317*2d4583c4SAdrian Chadd } 318*2d4583c4SAdrian Chadd tid = ieee80211_gettid(wh); 319*2d4583c4SAdrian Chadd pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); 320*2d4583c4SAdrian Chadd 321*2d4583c4SAdrian Chadd noreplaycheck = (k->wk_flags & IEEE80211_KEY_NOREPLAY) != 0; 322*2d4583c4SAdrian Chadd noreplaycheck |= (rxs != NULL) && 323*2d4583c4SAdrian Chadd (rxs->c_pktflags & IEEE80211_RX_F_PN_VALIDATED) != 0; 324*2d4583c4SAdrian Chadd if (pn <= k->wk_keyrsc[tid] && !noreplaycheck) { 325*2d4583c4SAdrian Chadd /* 326*2d4583c4SAdrian Chadd * Replay violation. 327*2d4583c4SAdrian Chadd */ 328*2d4583c4SAdrian Chadd ieee80211_notify_replay_failure(vap, wh, k, pn, tid); 329*2d4583c4SAdrian Chadd vap->iv_stats.is_rx_gcmpreplay++; 330*2d4583c4SAdrian Chadd return (0); 331*2d4583c4SAdrian Chadd } 332*2d4583c4SAdrian Chadd 333*2d4583c4SAdrian Chadd /* 334*2d4583c4SAdrian Chadd * Check if the device handled the decrypt in hardware. 335*2d4583c4SAdrian Chadd * If so we just strip the header; otherwise we need to 336*2d4583c4SAdrian Chadd * handle the decrypt in software. Note that for the 337*2d4583c4SAdrian Chadd * latter we leave the header in place for use in the 338*2d4583c4SAdrian Chadd * decryption work. 339*2d4583c4SAdrian Chadd */ 340*2d4583c4SAdrian Chadd if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) && 341*2d4583c4SAdrian Chadd !gcmp_decrypt(k, pn, m, hdrlen)) 342*2d4583c4SAdrian Chadd return (0); 343*2d4583c4SAdrian Chadd 344*2d4583c4SAdrian Chadd finish: 345*2d4583c4SAdrian Chadd /* 346*2d4583c4SAdrian Chadd * Copy up 802.11 header and strip crypto bits. 347*2d4583c4SAdrian Chadd */ 348*2d4583c4SAdrian Chadd if ((rxs == NULL) || (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) == 0) { 349*2d4583c4SAdrian Chadd ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + 350*2d4583c4SAdrian Chadd gcmp_get_header_len(k), hdrlen); 351*2d4583c4SAdrian Chadd m_adj(m, gcmp_get_header_len(k)); 352*2d4583c4SAdrian Chadd } 353*2d4583c4SAdrian Chadd 354*2d4583c4SAdrian Chadd if ((rxs == NULL) || (rxs->c_pktflags & IEEE80211_RX_F_MIC_STRIP) == 0) 355*2d4583c4SAdrian Chadd m_adj(m, -gcmp_get_trailer_len(k)); 356*2d4583c4SAdrian Chadd 357*2d4583c4SAdrian Chadd /* 358*2d4583c4SAdrian Chadd * Ok to update rsc now. 359*2d4583c4SAdrian Chadd */ 360*2d4583c4SAdrian Chadd if ((rxs == NULL) || (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) == 0) { 361*2d4583c4SAdrian Chadd /* 362*2d4583c4SAdrian Chadd * Do not go backwards in the IEEE80211_KEY_NOREPLAY cases 363*2d4583c4SAdrian Chadd * or in case hardware has checked but frames are arriving 364*2d4583c4SAdrian Chadd * reordered (e.g., LinuxKPI drivers doing RSS which we are 365*2d4583c4SAdrian Chadd * not prepared for at all). 366*2d4583c4SAdrian Chadd */ 367*2d4583c4SAdrian Chadd if (pn > k->wk_keyrsc[tid]) 368*2d4583c4SAdrian Chadd k->wk_keyrsc[tid] = pn; 369*2d4583c4SAdrian Chadd } 370*2d4583c4SAdrian Chadd 371*2d4583c4SAdrian Chadd return (1); 372*2d4583c4SAdrian Chadd } 373*2d4583c4SAdrian Chadd 374*2d4583c4SAdrian Chadd /* 375*2d4583c4SAdrian Chadd * Verify and strip MIC from the frame. 376*2d4583c4SAdrian Chadd */ 377*2d4583c4SAdrian Chadd static int 378*2d4583c4SAdrian Chadd gcmp_demic(struct ieee80211_key *k, struct mbuf *m, int force) 379*2d4583c4SAdrian Chadd { 380*2d4583c4SAdrian Chadd return (1); 381*2d4583c4SAdrian Chadd } 382*2d4583c4SAdrian Chadd 383*2d4583c4SAdrian Chadd /** 384*2d4583c4SAdrian Chadd * @brief Calculate the AAD required for this frame for AES-GCM. 385*2d4583c4SAdrian Chadd * 386*2d4583c4SAdrian Chadd * Note: This code was first copied over from ieee80211_crypto_ccmp.c, so 387*2d4583c4SAdrian Chadd * it has some CCMP-isms. 388*2d4583c4SAdrian Chadd * 389*2d4583c4SAdrian Chadd * NOTE: the first two bytes are a 16 bit big-endian length, which are used 390*2d4583c4SAdrian Chadd * by AES-CCM. AES-GCM doesn't require the length at the beginning. 391*2d4583c4SAdrian Chadd * 392*2d4583c4SAdrian Chadd * @param wh 802.11 frame to calculate the AAD over 393*2d4583c4SAdrian Chadd * @param aad AAD buffer, GCM_AAD_LEN bytes 394*2d4583c4SAdrian Chadd * @param The AAD length in bytes. 395*2d4583c4SAdrian Chadd */ 396*2d4583c4SAdrian Chadd static int 397*2d4583c4SAdrian Chadd gcmp_init_aad(const struct ieee80211_frame *wh, uint8_t *aad) 398*2d4583c4SAdrian Chadd { 399*2d4583c4SAdrian Chadd int aad_len; 400*2d4583c4SAdrian Chadd 401*2d4583c4SAdrian Chadd memset(aad, 0, GCM_AAD_LEN); 402*2d4583c4SAdrian Chadd 403*2d4583c4SAdrian Chadd #define IS_QOS_DATA(wh) IEEE80211_QOS_HAS_SEQ(wh) 404*2d4583c4SAdrian Chadd /* AAD: 405*2d4583c4SAdrian Chadd * FC with bits 4..6 and 11..13 masked to zero; 14 is always one 406*2d4583c4SAdrian Chadd * A1 | A2 | A3 407*2d4583c4SAdrian Chadd * SC with bits 4..15 (seq#) masked to zero 408*2d4583c4SAdrian Chadd * A4 (if present) 409*2d4583c4SAdrian Chadd * QC (if present) 410*2d4583c4SAdrian Chadd */ 411*2d4583c4SAdrian Chadd aad[0] = 0; /* AAD length >> 8 */ 412*2d4583c4SAdrian Chadd /* NB: aad[1] set below */ 413*2d4583c4SAdrian Chadd 414*2d4583c4SAdrian Chadd /* 415*2d4583c4SAdrian Chadd * TODO: go back over this in 802.11-2020 and triple check 416*2d4583c4SAdrian Chadd * the AAD assembly with regards to packet flags. 417*2d4583c4SAdrian Chadd */ 418*2d4583c4SAdrian Chadd 419*2d4583c4SAdrian Chadd aad[2] = wh->i_fc[0] & 0x8f; /* XXX magic #s */ 420*2d4583c4SAdrian Chadd /* 421*2d4583c4SAdrian Chadd * TODO: 12.5.3.3.3 - bit 14 should always be set; bit 15 masked to 0 422*2d4583c4SAdrian Chadd * if QoS control field, unmasked otherwise 423*2d4583c4SAdrian Chadd */ 424*2d4583c4SAdrian Chadd aad[3] = wh->i_fc[1] & 0xc7; /* XXX magic #s */ 425*2d4583c4SAdrian Chadd /* NB: we know 3 addresses are contiguous */ 426*2d4583c4SAdrian Chadd memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN); 427*2d4583c4SAdrian Chadd aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK; 428*2d4583c4SAdrian Chadd aad[23] = 0; /* all bits masked */ 429*2d4583c4SAdrian Chadd /* 430*2d4583c4SAdrian Chadd * Construct variable-length portion of AAD based 431*2d4583c4SAdrian Chadd * on whether this is a 4-address frame/QOS frame. 432*2d4583c4SAdrian Chadd * We always zero-pad to 32 bytes before running it 433*2d4583c4SAdrian Chadd * through the cipher. 434*2d4583c4SAdrian Chadd */ 435*2d4583c4SAdrian Chadd if (IEEE80211_IS_DSTODS(wh)) { 436*2d4583c4SAdrian Chadd IEEE80211_ADDR_COPY(aad + 24, 437*2d4583c4SAdrian Chadd ((const struct ieee80211_frame_addr4 *)wh)->i_addr4); 438*2d4583c4SAdrian Chadd if (IS_QOS_DATA(wh)) { 439*2d4583c4SAdrian Chadd const struct ieee80211_qosframe_addr4 *qwh4 = 440*2d4583c4SAdrian Chadd (const struct ieee80211_qosframe_addr4 *) wh; 441*2d4583c4SAdrian Chadd aad[30] = qwh4->i_qos[0] & 0x0f;/* just priority bits */ 442*2d4583c4SAdrian Chadd aad[31] = 0; 443*2d4583c4SAdrian Chadd aad_len = aad[1] = 22 + IEEE80211_ADDR_LEN + 2; 444*2d4583c4SAdrian Chadd } else { 445*2d4583c4SAdrian Chadd *(uint16_t *)&aad[30] = 0; 446*2d4583c4SAdrian Chadd aad_len = aad[1] = 22 + IEEE80211_ADDR_LEN; 447*2d4583c4SAdrian Chadd } 448*2d4583c4SAdrian Chadd } else { 449*2d4583c4SAdrian Chadd if (IS_QOS_DATA(wh)) { 450*2d4583c4SAdrian Chadd const struct ieee80211_qosframe *qwh = 451*2d4583c4SAdrian Chadd (const struct ieee80211_qosframe*) wh; 452*2d4583c4SAdrian Chadd aad[24] = qwh->i_qos[0] & 0x0f; /* just priority bits */ 453*2d4583c4SAdrian Chadd aad[25] = 0; 454*2d4583c4SAdrian Chadd aad_len = aad[1] = 22 + 2; 455*2d4583c4SAdrian Chadd } else { 456*2d4583c4SAdrian Chadd *(uint16_t *)&aad[24] = 0; 457*2d4583c4SAdrian Chadd aad_len = aad[1] = 22; 458*2d4583c4SAdrian Chadd } 459*2d4583c4SAdrian Chadd *(uint16_t *)&aad[26] = 0; 460*2d4583c4SAdrian Chadd *(uint32_t *)&aad[28] = 0; 461*2d4583c4SAdrian Chadd } 462*2d4583c4SAdrian Chadd #undef IS_QOS_DATA 463*2d4583c4SAdrian Chadd 464*2d4583c4SAdrian Chadd return (aad_len); 465*2d4583c4SAdrian Chadd } 466*2d4583c4SAdrian Chadd 467*2d4583c4SAdrian Chadd /* 468*2d4583c4SAdrian Chadd * Populate the 12 byte / 96 bit IV buffer. 469*2d4583c4SAdrian Chadd */ 470*2d4583c4SAdrian Chadd static int 471*2d4583c4SAdrian Chadd gcmp_init_iv(uint8_t *iv, const struct ieee80211_frame *wh, u_int64_t pn) 472*2d4583c4SAdrian Chadd { 473*2d4583c4SAdrian Chadd uint8_t j_pn[GCMP_PN_LEN]; 474*2d4583c4SAdrian Chadd 475*2d4583c4SAdrian Chadd /* Construct the pn buffer */ 476*2d4583c4SAdrian Chadd j_pn[0] = pn >> 40; 477*2d4583c4SAdrian Chadd j_pn[1] = pn >> 32; 478*2d4583c4SAdrian Chadd j_pn[2] = pn >> 24; 479*2d4583c4SAdrian Chadd j_pn[3] = pn >> 16; 480*2d4583c4SAdrian Chadd j_pn[4] = pn >> 8; 481*2d4583c4SAdrian Chadd j_pn[5] = pn >> 0; 482*2d4583c4SAdrian Chadd 483*2d4583c4SAdrian Chadd memcpy(iv, wh->i_addr2, IEEE80211_ADDR_LEN); 484*2d4583c4SAdrian Chadd memcpy(iv + IEEE80211_ADDR_LEN, j_pn, GCMP_PN_LEN); 485*2d4583c4SAdrian Chadd 486*2d4583c4SAdrian Chadd return (GCMP_IV_LEN); /* 96 bits */ 487*2d4583c4SAdrian Chadd } 488*2d4583c4SAdrian Chadd 489*2d4583c4SAdrian Chadd /* 490*2d4583c4SAdrian Chadd * @brief Encrypt an mbuf. 491*2d4583c4SAdrian Chadd * 492*2d4583c4SAdrian Chadd * This uses a temporary memory buffer to encrypt; the 493*2d4583c4SAdrian Chadd * current AES-GCM code expects things in a contiguous buffer 494*2d4583c4SAdrian Chadd * and this avoids the need of breaking out the GCTR and 495*2d4583c4SAdrian Chadd * GHASH routines into using mbuf iterators. 496*2d4583c4SAdrian Chadd * 497*2d4583c4SAdrian Chadd * @param key ieee80211_key to use 498*2d4583c4SAdrian Chadd * @param mbuf 802.11 frame to encrypt 499*2d4583c4SAdrian Chadd * @param hdrlen the length of the 802.11 header, including any padding 500*2d4583c4SAdrian Chadd * @returns 0 if error, > 0 if OK. 501*2d4583c4SAdrian Chadd */ 502*2d4583c4SAdrian Chadd static int 503*2d4583c4SAdrian Chadd gcmp_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen) 504*2d4583c4SAdrian Chadd { 505*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = key->wk_private; 506*2d4583c4SAdrian Chadd struct ieee80211_frame *wh; 507*2d4583c4SAdrian Chadd struct ieee80211vap *vap = ctx->cc_vap; 508*2d4583c4SAdrian Chadd struct mbuf *m = m0; 509*2d4583c4SAdrian Chadd int data_len, aad_len, iv_len, ret; 510*2d4583c4SAdrian Chadd uint8_t aad[GCM_AAD_LEN]; 511*2d4583c4SAdrian Chadd uint8_t T[GCMP_MIC_LEN]; 512*2d4583c4SAdrian Chadd uint8_t iv[GCMP_IV_LEN]; 513*2d4583c4SAdrian Chadd uint8_t *p_pktbuf = NULL; 514*2d4583c4SAdrian Chadd uint8_t *c_pktbuf = NULL; 515*2d4583c4SAdrian Chadd 516*2d4583c4SAdrian Chadd wh = mtod(m, struct ieee80211_frame *); 517*2d4583c4SAdrian Chadd data_len = m->m_pkthdr.len - (hdrlen + gcmp_get_header_len(key)); 518*2d4583c4SAdrian Chadd 519*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp++; 520*2d4583c4SAdrian Chadd 521*2d4583c4SAdrian Chadd p_pktbuf = IEEE80211_MALLOC(data_len, M_TEMP, 522*2d4583c4SAdrian Chadd IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 523*2d4583c4SAdrian Chadd if (p_pktbuf == NULL) { 524*2d4583c4SAdrian Chadd IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 525*2d4583c4SAdrian Chadd "%s", "AES-GCM encrypt failed; couldn't allocate buffer"); 526*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp_nomem++; 527*2d4583c4SAdrian Chadd return (0); 528*2d4583c4SAdrian Chadd } 529*2d4583c4SAdrian Chadd c_pktbuf = IEEE80211_MALLOC(data_len, M_TEMP, 530*2d4583c4SAdrian Chadd IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 531*2d4583c4SAdrian Chadd if (c_pktbuf == NULL) { 532*2d4583c4SAdrian Chadd IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 533*2d4583c4SAdrian Chadd "%s", "AES-GCM encrypt failed; couldn't allocate buffer"); 534*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp_nomem++; 535*2d4583c4SAdrian Chadd IEEE80211_FREE(p_pktbuf, M_TEMP); 536*2d4583c4SAdrian Chadd return (0); 537*2d4583c4SAdrian Chadd } 538*2d4583c4SAdrian Chadd 539*2d4583c4SAdrian Chadd /* Initialise AAD */ 540*2d4583c4SAdrian Chadd aad_len = gcmp_init_aad(wh, aad); 541*2d4583c4SAdrian Chadd 542*2d4583c4SAdrian Chadd /* Initialise local Nonce to work on */ 543*2d4583c4SAdrian Chadd /* TODO: rename iv stuff here to nonce */ 544*2d4583c4SAdrian Chadd iv_len = gcmp_init_iv(iv, wh, key->wk_keytsc); 545*2d4583c4SAdrian Chadd 546*2d4583c4SAdrian Chadd /* Copy mbuf data part into plaintext pktbuf */ 547*2d4583c4SAdrian Chadd m_copydata(m0, hdrlen + gcmp_get_header_len(key), data_len, 548*2d4583c4SAdrian Chadd p_pktbuf); 549*2d4583c4SAdrian Chadd 550*2d4583c4SAdrian Chadd /* Run encrypt */ 551*2d4583c4SAdrian Chadd /* 552*2d4583c4SAdrian Chadd * Note: aad + 2 to skip over the 2 byte length populated 553*2d4583c4SAdrian Chadd * at the beginning, since it's based on the AAD code in CCMP. 554*2d4583c4SAdrian Chadd */ 555*2d4583c4SAdrian Chadd ieee80211_crypto_aes_gcm_ae(&ctx->cc_aes, iv, iv_len, 556*2d4583c4SAdrian Chadd p_pktbuf, data_len, aad + 2, aad_len, c_pktbuf, T); 557*2d4583c4SAdrian Chadd 558*2d4583c4SAdrian Chadd /* Copy data back over mbuf */ 559*2d4583c4SAdrian Chadd m_copyback(m0, hdrlen + gcmp_get_header_len(key), data_len, 560*2d4583c4SAdrian Chadd c_pktbuf); 561*2d4583c4SAdrian Chadd 562*2d4583c4SAdrian Chadd /* Append MIC */ 563*2d4583c4SAdrian Chadd ret = m_append(m0, gcmp_get_trailer_len(key), T); 564*2d4583c4SAdrian Chadd if (ret == 0) { 565*2d4583c4SAdrian Chadd IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 566*2d4583c4SAdrian Chadd "%s", "AES-GCM encrypt failed; couldn't append T"); 567*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp_nospc++; 568*2d4583c4SAdrian Chadd } 569*2d4583c4SAdrian Chadd 570*2d4583c4SAdrian Chadd IEEE80211_FREE(p_pktbuf, M_TEMP); 571*2d4583c4SAdrian Chadd IEEE80211_FREE(c_pktbuf, M_TEMP); 572*2d4583c4SAdrian Chadd 573*2d4583c4SAdrian Chadd return (ret); 574*2d4583c4SAdrian Chadd } 575*2d4583c4SAdrian Chadd 576*2d4583c4SAdrian Chadd /* 577*2d4583c4SAdrian Chadd * @brief Decrypt an mbuf. 578*2d4583c4SAdrian Chadd * 579*2d4583c4SAdrian Chadd * This uses a temporary memory buffer to decrypt; the 580*2d4583c4SAdrian Chadd * current AES-GCM code expects things in a contiguous buffer 581*2d4583c4SAdrian Chadd * and this avoids the need of breaking out the GCTR and 582*2d4583c4SAdrian Chadd * GHASH routines into using mbuf iterators. 583*2d4583c4SAdrian Chadd * 584*2d4583c4SAdrian Chadd * @param key ieee80211_key to use 585*2d4583c4SAdrian Chadd * @param mbuf 802.11 frame to decrypt 586*2d4583c4SAdrian Chadd * @param hdrlen the length of the 802.11 header, including any padding 587*2d4583c4SAdrian Chadd * @returns 0 if error, > 0 if OK. 588*2d4583c4SAdrian Chadd */ 589*2d4583c4SAdrian Chadd static int 590*2d4583c4SAdrian Chadd gcmp_decrypt(struct ieee80211_key *key, u_int64_t pn, struct mbuf *m, 591*2d4583c4SAdrian Chadd int hdrlen) 592*2d4583c4SAdrian Chadd { 593*2d4583c4SAdrian Chadd const struct ieee80211_rx_stats *rxs; 594*2d4583c4SAdrian Chadd struct gcmp_ctx *ctx = key->wk_private; 595*2d4583c4SAdrian Chadd struct ieee80211vap *vap = ctx->cc_vap; 596*2d4583c4SAdrian Chadd struct ieee80211_frame *wh; 597*2d4583c4SAdrian Chadd int data_len, aad_len, iv_len, ret; 598*2d4583c4SAdrian Chadd uint8_t aad[GCM_AAD_LEN]; 599*2d4583c4SAdrian Chadd uint8_t T[GCMP_MIC_LEN]; 600*2d4583c4SAdrian Chadd uint8_t iv[GCMP_IV_LEN]; 601*2d4583c4SAdrian Chadd uint8_t *p_pktbuf = NULL; 602*2d4583c4SAdrian Chadd uint8_t *c_pktbuf = NULL; 603*2d4583c4SAdrian Chadd 604*2d4583c4SAdrian Chadd rxs = ieee80211_get_rx_params_ptr(m); 605*2d4583c4SAdrian Chadd if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED) != 0) 606*2d4583c4SAdrian Chadd return (1); 607*2d4583c4SAdrian Chadd 608*2d4583c4SAdrian Chadd wh = mtod(m, struct ieee80211_frame *); 609*2d4583c4SAdrian Chadd 610*2d4583c4SAdrian Chadd /* Data length doesn't include the MIC at the end */ 611*2d4583c4SAdrian Chadd data_len = m->m_pkthdr.len - 612*2d4583c4SAdrian Chadd (hdrlen + gcmp_get_header_len(key) + GCMP_MIC_LEN); 613*2d4583c4SAdrian Chadd 614*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp++; 615*2d4583c4SAdrian Chadd 616*2d4583c4SAdrian Chadd p_pktbuf = IEEE80211_MALLOC(data_len, M_TEMP, 617*2d4583c4SAdrian Chadd IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 618*2d4583c4SAdrian Chadd if (p_pktbuf == NULL) { 619*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp_nomem++; 620*2d4583c4SAdrian Chadd return (0); 621*2d4583c4SAdrian Chadd } 622*2d4583c4SAdrian Chadd c_pktbuf = IEEE80211_MALLOC(data_len, M_TEMP, 623*2d4583c4SAdrian Chadd IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 624*2d4583c4SAdrian Chadd if (c_pktbuf == NULL) { 625*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_crypto_gcmp_nomem++; 626*2d4583c4SAdrian Chadd IEEE80211_FREE(p_pktbuf, M_TEMP); 627*2d4583c4SAdrian Chadd return (0); 628*2d4583c4SAdrian Chadd } 629*2d4583c4SAdrian Chadd 630*2d4583c4SAdrian Chadd /* Initialise AAD */ 631*2d4583c4SAdrian Chadd aad_len = gcmp_init_aad(wh, aad); 632*2d4583c4SAdrian Chadd 633*2d4583c4SAdrian Chadd /* Initialise local IV copy to work on */ 634*2d4583c4SAdrian Chadd iv_len = gcmp_init_iv(iv, wh, pn); 635*2d4583c4SAdrian Chadd 636*2d4583c4SAdrian Chadd /* Copy mbuf into ciphertext pktbuf */ 637*2d4583c4SAdrian Chadd m_copydata(m, hdrlen + gcmp_get_header_len(key), data_len, 638*2d4583c4SAdrian Chadd c_pktbuf); 639*2d4583c4SAdrian Chadd 640*2d4583c4SAdrian Chadd /* Copy the MIC into the tag buffer */ 641*2d4583c4SAdrian Chadd m_copydata(m, hdrlen + gcmp_get_header_len(key) + data_len, 642*2d4583c4SAdrian Chadd GCMP_MIC_LEN, T); 643*2d4583c4SAdrian Chadd 644*2d4583c4SAdrian Chadd /* Run decrypt */ 645*2d4583c4SAdrian Chadd /* 646*2d4583c4SAdrian Chadd * Note: aad + 2 to skip over the 2 byte length populated 647*2d4583c4SAdrian Chadd * at the beginning, since it's based on the AAD code in CCMP. 648*2d4583c4SAdrian Chadd */ 649*2d4583c4SAdrian Chadd ret = ieee80211_crypto_aes_gcm_ad(&ctx->cc_aes, iv, iv_len, 650*2d4583c4SAdrian Chadd c_pktbuf, data_len, aad + 2, aad_len, T, p_pktbuf); 651*2d4583c4SAdrian Chadd 652*2d4583c4SAdrian Chadd /* If the MIC was stripped by HW/driver we are done. */ 653*2d4583c4SAdrian Chadd if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MIC_STRIP) != 0) 654*2d4583c4SAdrian Chadd goto skip_ok; 655*2d4583c4SAdrian Chadd 656*2d4583c4SAdrian Chadd if (ret != 0) { 657*2d4583c4SAdrian Chadd /* Decrypt failure */ 658*2d4583c4SAdrian Chadd ctx->cc_vap->iv_stats.is_rx_gcmpmic++; 659*2d4583c4SAdrian Chadd IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 660*2d4583c4SAdrian Chadd "%s", "AES-GCM decrypt failed; MIC mismatch"); 661*2d4583c4SAdrian Chadd IEEE80211_FREE(p_pktbuf, M_TEMP); 662*2d4583c4SAdrian Chadd IEEE80211_FREE(c_pktbuf, M_TEMP); 663*2d4583c4SAdrian Chadd return (0); 664*2d4583c4SAdrian Chadd } 665*2d4583c4SAdrian Chadd 666*2d4583c4SAdrian Chadd skip_ok: 667*2d4583c4SAdrian Chadd /* Copy data back over mbuf */ 668*2d4583c4SAdrian Chadd m_copyback(m, hdrlen + gcmp_get_header_len(key), data_len, 669*2d4583c4SAdrian Chadd p_pktbuf); 670*2d4583c4SAdrian Chadd 671*2d4583c4SAdrian Chadd IEEE80211_FREE(p_pktbuf, M_TEMP); 672*2d4583c4SAdrian Chadd IEEE80211_FREE(c_pktbuf, M_TEMP); 673*2d4583c4SAdrian Chadd 674*2d4583c4SAdrian Chadd return (1); 675*2d4583c4SAdrian Chadd } 676*2d4583c4SAdrian Chadd 677*2d4583c4SAdrian Chadd /* 678*2d4583c4SAdrian Chadd * Module glue. 679*2d4583c4SAdrian Chadd */ 680*2d4583c4SAdrian Chadd IEEE80211_CRYPTO_MODULE(gcmp, 1); 681*2d4583c4SAdrian Chadd IEEE80211_CRYPTO_MODULE_ADD(gcmp_256); 682