Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/crypt/dot11decrypt_ccmp.c
Line
Count
Source (jump to first uncovered line)
1
/* dot11decrypt_ccmp.c
2
 *
3
 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
4
 * Copyright (c) 2006 CACE Technologies, Davis (California)
5
 * All rights reserved.
6
 *
7
 * SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
8
 */
9
10
/*
11
 * Note: This file was derived from the FreeBSD source code, RELENG 6,
12
 *    sys/net80211/ieee80211_crypto_ccmp.c
13
 */
14
15
/****************************************************************************/
16
/* File includes                */
17
#include "config.h"
18
19
#include "dot11decrypt_debug.h"
20
#include "dot11decrypt_system.h"
21
#include "dot11decrypt_util.h"
22
#include "dot11decrypt_int.h"
23
24
#include <wsutil/wsgcrypt.h>
25
26
/****************************************************************************/
27
/*  Internal definitions              */
28
29
/****************************************************************************/
30
/* Internal macros                */
31
32
#define READ_6(b0, b1, b2, b3, b4, b5) \
33
0
  ((((uint64_t)((uint16_t)((b4 << 0) | (b5 << 8)))) << 32) | \
34
0
      ((uint32_t)((b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24))))
35
36
/****************************************************************************/
37
/* Internal function prototypes declarations          */
38
39
/****************************************************************************/
40
/* Function definitions             */
41
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,
46
  uint64_t pn,
47
  uint8_t nonce[13])
48
0
{
49
0
  uint8_t mgmt = (DOT11DECRYPT_TYPE(wh->fc[0]) == DOT11DECRYPT_TYPE_MANAGEMENT);
50
51
0
  if (DOT11DECRYPT_IS_4ADDRESS(wh) && DOT11DECRYPT_IS_QOS_DATA(wh)) {
52
0
    PDOT11DECRYPT_MAC_FRAME_ADDR4_QOS qwh4 =
53
0
      (PDOT11DECRYPT_MAC_FRAME_ADDR4_QOS) wh;
54
0
    nonce[0] = (uint8_t)(qwh4->qos[0] & 0x0f);/* just priority bits */
55
0
  } else if (DOT11DECRYPT_IS_QOS_DATA(wh)) {
56
0
    PDOT11DECRYPT_MAC_FRAME_QOS qwh =
57
0
      (PDOT11DECRYPT_MAC_FRAME_QOS) wh;
58
0
      nonce[0] = (uint8_t)(qwh->qos[0] & 0x0f); /* just priority bits */
59
0
  } else {
60
0
    nonce[0] = 0;
61
0
  }
62
0
  if (mgmt) {
63
0
    nonce[0] |= 0x10; /* set MGMT flag */
64
0
  }
65
66
0
  DOT11DECRYPT_ADDR_COPY(nonce + 1, wh->addr2);
67
0
  nonce[7] = (uint8_t)(pn >> 40);
68
0
  nonce[8] = (uint8_t)(pn >> 32);
69
0
  nonce[9] = (uint8_t)(pn >> 24);
70
0
  nonce[10] = (uint8_t)(pn >> 16);
71
0
  nonce[11] = (uint8_t)(pn >> 8);
72
0
  nonce[12] = (uint8_t)(pn >> 0);
73
0
}
74
75
int Dot11DecryptCcmpDecrypt(
76
  uint8_t *m,
77
  int mac_header_len,
78
  int len,
79
  uint8_t *TK1,
80
  int tk_len,
81
  int mic_len)
82
0
{
83
0
  PDOT11DECRYPT_MAC_FRAME wh;
84
0
  uint8_t aad[30]; /* Max aad_len. See Table 12-1 IEEE 802.11 2016 */
85
0
  uint8_t nonce[13];
86
0
  uint8_t mic[16]; /* Big enough for CCMP-256 */
87
0
  ssize_t data_len;
88
0
  size_t aad_len;
89
0
  int z = mac_header_len;
90
0
  gcry_cipher_hd_t handle;
91
0
  uint64_t pn;
92
0
  uint8_t *ivp = m + z;
93
94
0
  wh = (PDOT11DECRYPT_MAC_FRAME )m;
95
0
  data_len = len - (z + DOT11DECRYPT_CCMP_HEADER + mic_len);
96
0
  if (data_len < 1) {
97
0
    return 0;
98
0
  }
99
100
0
  memcpy(mic, m + len - mic_len, mic_len);
101
0
  pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
102
0
  ccmp_construct_nonce(wh, pn, nonce);
103
0
  dot11decrypt_construct_aad(wh, aad, &aad_len);
104
105
0
  if (gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CCM, 0)) {
106
0
    return 1;
107
0
  }
108
0
  if (gcry_cipher_setkey(handle, TK1, tk_len)) {
109
0
    goto err_out;
110
0
  }
111
0
  if (gcry_cipher_setiv(handle, nonce, sizeof(nonce))) {
112
0
    goto err_out;
113
0
  }
114
115
0
  uint64_t ccm_lengths[3];
116
0
  ccm_lengths[0] = data_len;
117
0
  ccm_lengths[1] = aad_len;
118
0
  ccm_lengths[2] = mic_len;
119
0
  if (gcry_cipher_ctl(handle, GCRYCTL_SET_CCM_LENGTHS, ccm_lengths, sizeof(ccm_lengths))) {
120
0
    goto err_out;
121
0
  }
122
0
  if (gcry_cipher_authenticate(handle, aad, aad_len)) {
123
0
    goto err_out;
124
0
  }
125
0
  if (gcry_cipher_decrypt(handle, m + z + DOT11DECRYPT_CCMP_HEADER, data_len, NULL, 0)) {
126
0
    goto err_out;
127
0
  }
128
0
  if (gcry_cipher_checktag(handle, mic, mic_len)) {
129
0
    goto err_out;
130
0
  }
131
132
  /* TODO replay check  (IEEE 802.11i-2004, pg. 62)     */
133
  /* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62)    */
134
135
0
  gcry_cipher_close(handle);
136
0
  return 0;
137
0
err_out:
138
0
  gcry_cipher_close(handle);
139
0
  return 1;
140
0
}