regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / crypt / dot11decrypt_gcmp.c
blob7e7ae3be55cc3705a96e05257a5097e8870a39d3
1 /* dot11decrypt_gcmp.c
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 /****************************************************************************/
11 /* File includes */
12 #include "config.h"
14 #include "dot11decrypt_debug.h"
15 #include "dot11decrypt_int.h"
16 #include "dot11decrypt_system.h"
17 #include "dot11decrypt_util.h"
19 #include <wsutil/wsgcrypt.h>
21 /****************************************************************************/
22 /* Internal definitions */
24 /****************************************************************************/
25 /* Internal macros */
27 #define READ_6(b0, b1, b2, b3, b4, b5) \
28 ((((uint64_t)((uint16_t)((b4 << 0) | (b5 << 8)))) << 32) | \
29 ((uint32_t)((b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24))))
31 /****************************************************************************/
32 /* Internal function prototypes declarations */
34 /****************************************************************************/
35 /* Function definitions */
37 /* From IEEE 802.11 2016 Chapter 12.5.5.3.4 Construct GCM nonce */
38 static void
39 gcmp_construct_nonce(
40 PDOT11DECRYPT_MAC_FRAME wh,
41 uint64_t pn,
42 uint8_t nonce[12])
44 /* Nonce: A2 | PN */
45 DOT11DECRYPT_ADDR_COPY(nonce, wh->addr2);
46 nonce[6] = (uint8_t)(pn >> 40);
47 nonce[7] = (uint8_t)(pn >> 32);
48 nonce[8] = (uint8_t)(pn >> 24);
49 nonce[9] = (uint8_t)(pn >> 16);
50 nonce[10] = (uint8_t)(pn >> 8);
51 nonce[11] = (uint8_t)(pn >> 0);
54 int Dot11DecryptGcmpDecrypt(
55 uint8_t *m,
56 int mac_header_len,
57 int len,
58 uint8_t *TK1,
59 int tk_len)
61 PDOT11DECRYPT_MAC_FRAME wh;
62 uint8_t aad[30];
63 uint8_t nonce[12];
64 uint8_t mic[16];
65 ssize_t data_len;
66 size_t aad_len;
67 int z = mac_header_len;
68 gcry_cipher_hd_t handle;
69 uint64_t pn;
70 uint8_t *ivp = m + z;
72 wh = (PDOT11DECRYPT_MAC_FRAME )m;
73 data_len = len - (z + DOT11DECRYPT_GCMP_HEADER + sizeof(mic));
74 if (data_len < 1) {
75 return 0;
78 memcpy(mic, m + len - sizeof(mic), sizeof(mic));
79 pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
80 gcmp_construct_nonce(wh, pn, nonce);
81 dot11decrypt_construct_aad(wh, aad, &aad_len);
83 if (gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_GCM, 0)) {
84 return 1;
86 if (gcry_cipher_setkey(handle, TK1, tk_len)) {
87 goto err_out;
89 if (gcry_cipher_setiv(handle, nonce, sizeof(nonce))) {
90 goto err_out;
92 if (gcry_cipher_authenticate(handle, aad, aad_len)) {
93 goto err_out;
95 if (gcry_cipher_decrypt(handle, m + z + DOT11DECRYPT_GCMP_HEADER, data_len, NULL, 0)) {
96 goto err_out;
98 if (gcry_cipher_checktag(handle, mic, sizeof(mic))) {
99 goto err_out;
102 /* TODO replay check (IEEE 802.11i-2004, pg. 62) */
103 /* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62) */
105 gcry_cipher_close(handle);
106 return 0;
107 err_out:
108 gcry_cipher_close(handle);
109 return 1;