3 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
4 * Copyright (c) 2006 CACE Technologies, Davis (California)
7 * SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
11 * Note: This file was derived from the FreeBSD source code, RELENG 6,
12 * sys/net80211/ieee80211_crypto_ccmp.c
15 /****************************************************************************/
19 #include "dot11decrypt_debug.h"
20 #include "dot11decrypt_system.h"
21 #include "dot11decrypt_util.h"
22 #include "dot11decrypt_int.h"
24 #include <wsutil/wsgcrypt.h>
26 /****************************************************************************/
27 /* Internal definitions */
29 /****************************************************************************/
32 #define READ_6(b0, b1, b2, b3, b4, b5) \
33 ((((uint64_t)((uint16_t)((b4 << 0) | (b5 << 8)))) << 32) | \
34 ((uint32_t)((b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24))))
36 /****************************************************************************/
37 /* Internal function prototypes declarations */
39 /****************************************************************************/
40 /* Function definitions */
42 /* From IEEE 802.11 2016 Chapter 12.5.3.3.4 Construct CCM nonce */
43 /* Nonce: Flags | A2 | PN */
44 static void ccmp_construct_nonce(
45 PDOT11DECRYPT_MAC_FRAME wh
,
49 uint8_t mgmt
= (DOT11DECRYPT_TYPE(wh
->fc
[0]) == DOT11DECRYPT_TYPE_MANAGEMENT
);
51 if (DOT11DECRYPT_IS_4ADDRESS(wh
) && DOT11DECRYPT_IS_QOS_DATA(wh
)) {
52 PDOT11DECRYPT_MAC_FRAME_ADDR4_QOS qwh4
=
53 (PDOT11DECRYPT_MAC_FRAME_ADDR4_QOS
) wh
;
54 nonce
[0] = (uint8_t)(qwh4
->qos
[0] & 0x0f);/* just priority bits */
55 } else if (DOT11DECRYPT_IS_QOS_DATA(wh
)) {
56 PDOT11DECRYPT_MAC_FRAME_QOS qwh
=
57 (PDOT11DECRYPT_MAC_FRAME_QOS
) wh
;
58 nonce
[0] = (uint8_t)(qwh
->qos
[0] & 0x0f); /* just priority bits */
63 nonce
[0] |= 0x10; /* set MGMT flag */
66 DOT11DECRYPT_ADDR_COPY(nonce
+ 1, wh
->addr2
);
67 nonce
[7] = (uint8_t)(pn
>> 40);
68 nonce
[8] = (uint8_t)(pn
>> 32);
69 nonce
[9] = (uint8_t)(pn
>> 24);
70 nonce
[10] = (uint8_t)(pn
>> 16);
71 nonce
[11] = (uint8_t)(pn
>> 8);
72 nonce
[12] = (uint8_t)(pn
>> 0);
75 int Dot11DecryptCcmpDecrypt(
83 PDOT11DECRYPT_MAC_FRAME wh
;
84 uint8_t aad
[30]; /* Max aad_len. See Table 12-1 IEEE 802.11 2016 */
86 uint8_t mic
[16]; /* Big enough for CCMP-256 */
89 int z
= mac_header_len
;
90 gcry_cipher_hd_t handle
;
94 wh
= (PDOT11DECRYPT_MAC_FRAME
)m
;
95 data_len
= len
- (z
+ DOT11DECRYPT_CCMP_HEADER
+ mic_len
);
100 memcpy(mic
, m
+ len
- mic_len
, mic_len
);
101 pn
= READ_6(ivp
[0], ivp
[1], ivp
[4], ivp
[5], ivp
[6], ivp
[7]);
102 ccmp_construct_nonce(wh
, pn
, nonce
);
103 dot11decrypt_construct_aad(wh
, aad
, &aad_len
);
105 if (gcry_cipher_open(&handle
, GCRY_CIPHER_AES
, GCRY_CIPHER_MODE_CCM
, 0)) {
108 if (gcry_cipher_setkey(handle
, TK1
, tk_len
)) {
111 if (gcry_cipher_setiv(handle
, nonce
, sizeof(nonce
))) {
115 uint64_t ccm_lengths
[3];
116 ccm_lengths
[0] = data_len
;
117 ccm_lengths
[1] = aad_len
;
118 ccm_lengths
[2] = mic_len
;
119 if (gcry_cipher_ctl(handle
, GCRYCTL_SET_CCM_LENGTHS
, ccm_lengths
, sizeof(ccm_lengths
))) {
122 if (gcry_cipher_authenticate(handle
, aad
, aad_len
)) {
125 if (gcry_cipher_decrypt(handle
, m
+ z
+ DOT11DECRYPT_CCMP_HEADER
, data_len
, NULL
, 0)) {
128 if (gcry_cipher_checktag(handle
, mic
, mic_len
)) {
132 /* TODO replay check (IEEE 802.11i-2004, pg. 62) */
133 /* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62) */
135 gcry_cipher_close(handle
);
138 gcry_cipher_close(handle
);