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