Coverage Report

Created: 2026-09-14 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/src/pasn/pasn_common.c
Line
Count
Source
1
/*
2
 * PASN common processing
3
 *
4
 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5
 *
6
 * This software may be distributed under the terms of the BSD license.
7
 * See README for more details.
8
 */
9
10
#include "utils/includes.h"
11
12
#include "utils/common.h"
13
#include "common/wpa_common.h"
14
#include "common/sae.h"
15
#include "crypto/sha384.h"
16
#include "crypto/crypto.h"
17
#include "common/ieee802_11_defs.h"
18
#include "common/ieee802_11_common.h"
19
#include "crypto/aes_wrap.h"
20
#include "pasn_common.h"
21
22
23
struct pasn_data * pasn_data_init(void)
24
2.41k
{
25
2.41k
  struct pasn_data *pasn = os_zalloc(sizeof(struct pasn_data));
26
27
2.41k
  return pasn;
28
2.41k
}
29
30
31
void pasn_data_deinit(struct pasn_data *pasn)
32
2.41k
{
33
2.41k
  if (!pasn)
34
0
    return;
35
2.41k
  os_free(pasn->rsnxe_ie);
36
2.41k
  os_free(pasn->rsn_ie);
37
2.41k
  wpabuf_free(pasn->frame);
38
2.41k
  os_free(pasn->pasn_groups);
39
2.41k
  wpabuf_free(pasn->auth1);
40
2.41k
  os_free(pasn->dec_pw_id);
41
2.41k
  wpabuf_free(pasn->security_profile);
42
2.41k
  bin_clear_free(pasn, sizeof(struct pasn_data));
43
2.41k
}
44
45
46
void pasn_register_callbacks(struct pasn_data *pasn, void *cb_ctx,
47
           int (*send_mgmt)(void *ctx, const u8 *data,
48
                size_t data_len, int noack,
49
                unsigned int freq,
50
                unsigned int wait),
51
           int (*validate_custom_pmkid)(void *ctx,
52
                const u8 *addr,
53
                const u8 *pmkid),
54
           int (*eppke_set_key)(void *ctx, enum wpa_alg alg,
55
              const u8 *addr, int vlan_id,
56
              const u8 *key,
57
              size_t key_len),
58
           struct rsn_pmksa_cache_entry *
59
           (*pmksa_cache_search)(void *ctx, const u8 *spa,
60
               const u8 *pmkid, bool is_ml))
61
0
{
62
0
  if (!pasn)
63
0
    return;
64
65
0
  pasn->cb_ctx = cb_ctx;
66
0
  pasn->send_mgmt = send_mgmt;
67
0
  pasn->validate_custom_pmkid = validate_custom_pmkid;
68
#ifdef CONFIG_ENC_ASSOC
69
  pasn->eppke_set_key = eppke_set_key;
70
#endif /* CONFIG_ENC_ASSOC */
71
0
  pasn->pmksa_cache_search = pmksa_cache_search;
72
0
}
73
74
75
void pasn_enable_kdk_derivation(struct pasn_data *pasn)
76
0
{
77
0
  if (!pasn)
78
0
    return;
79
0
  pasn->derive_kdk = true;
80
0
  pasn->kdk_len = WPA_KDK_MAX_LEN;
81
0
}
82
83
84
void pasn_disable_kdk_derivation(struct pasn_data *pasn)
85
0
{
86
0
  if (!pasn)
87
0
    return;
88
0
  pasn->derive_kdk = false;
89
0
  pasn->kdk_len = 0;
90
0
}
91
92
93
void pasn_set_akmp(struct pasn_data *pasn, int akmp)
94
0
{
95
0
  if (!pasn)
96
0
    return;
97
0
  pasn->akmp = akmp;
98
0
}
99
100
101
void pasn_set_cipher(struct pasn_data *pasn, int cipher)
102
0
{
103
0
  if (!pasn)
104
0
    return;
105
0
  pasn->cipher = cipher;
106
0
}
107
108
109
void pasn_set_own_addr(struct pasn_data *pasn, const u8 *addr)
110
0
{
111
0
  if (!pasn || !addr)
112
0
    return;
113
0
  os_memcpy(pasn->own_addr, addr, ETH_ALEN);
114
0
}
115
116
117
#ifdef CONFIG_ENC_ASSOC
118
void pasn_set_own_mld_addr(struct pasn_data *pasn, const u8 *addr)
119
{
120
  if (!pasn || !addr)
121
    return;
122
  os_memcpy(pasn->mld_addr, addr, ETH_ALEN);
123
}
124
#endif /* CONFIG_ENC_ASSOC */
125
126
127
void pasn_set_peer_addr(struct pasn_data *pasn, const u8 *addr)
128
0
{
129
0
  if (!pasn || !addr)
130
0
    return;
131
0
  os_memcpy(pasn->peer_addr, addr, ETH_ALEN);
132
0
}
133
134
135
void pasn_set_bssid(struct pasn_data *pasn, const u8 *addr)
136
0
{
137
0
  if (!pasn || !addr)
138
0
    return;
139
0
  os_memcpy(pasn->bssid, addr, ETH_ALEN);
140
0
}
141
142
143
int pasn_set_pt(struct pasn_data *pasn, struct sae_pt *pt)
144
0
{
145
0
  if (!pasn)
146
0
    return -1;
147
0
#ifdef CONFIG_SAE
148
0
  pasn->pt = pt;
149
0
  return 0;
150
#else /* CONFIG_SAE */
151
  return -1;
152
#endif /* CONFIG_SAE */
153
0
}
154
155
156
void pasn_set_wpa_key_mgmt(struct pasn_data *pasn, int key_mgmt)
157
0
{
158
0
  if (!pasn)
159
0
    return;
160
0
  pasn->wpa_key_mgmt = key_mgmt;
161
0
}
162
163
164
void pasn_set_mfp(struct pasn_data *pasn, enum mfp_options mfp)
165
0
{
166
0
  if (pasn)
167
0
    pasn->ieee80211w = mfp;
168
0
}
169
170
171
void pasn_set_rsn_pairwise(struct pasn_data *pasn, int rsn_pairwise)
172
0
{
173
0
  if (!pasn)
174
0
    return;
175
0
  pasn->rsn_pairwise = rsn_pairwise;
176
0
}
177
178
179
void pasn_set_rsnxe_caps(struct pasn_data *pasn, u64 rsnxe_capab)
180
0
{
181
0
  if (!pasn)
182
0
    return;
183
0
  pasn->rsnxe_capab = rsnxe_capab;
184
0
}
185
186
187
void pasn_set_rsnxe_ie(struct pasn_data *pasn, const u8 *rsnxe_ie)
188
0
{
189
0
  if (!pasn || !rsnxe_ie)
190
0
    return;
191
0
  os_free(pasn->rsnxe_ie);
192
0
  pasn->rsnxe_ie = os_memdup(rsnxe_ie, 2 + rsnxe_ie[1]);
193
0
}
194
195
196
void pasn_set_rsne(struct pasn_data *pasn, const u8 *rsne)
197
0
{
198
0
  if (!pasn || !rsne)
199
0
    return;
200
0
  os_free(pasn->rsn_ie);
201
0
  pasn->rsn_ie = os_memdup(rsne, 2 + rsne[1]);
202
0
  pasn->rsn_ie_len = pasn->rsn_ie ? 2 + rsne[1] : 0;
203
0
}
204
205
206
void pasn_set_custom_pmkid(struct pasn_data *pasn, const u8 *pmkid)
207
0
{
208
0
  if (!pasn || !pmkid)
209
0
    return;
210
0
  os_memcpy(pasn->custom_pmkid, pmkid, PMKID_LEN);
211
0
  pasn->custom_pmkid_valid = true;
212
0
}
213
214
215
int pasn_set_extra_ies(struct pasn_data *pasn, const u8 *extra_ies,
216
           size_t extra_ies_len)
217
0
{
218
0
  if (!pasn || !extra_ies_len || !extra_ies)
219
0
    return -1;
220
221
0
  if (pasn->extra_ies) {
222
0
    os_free((u8 *) pasn->extra_ies);
223
0
    pasn->extra_ies_len = 0;
224
0
  }
225
226
0
  pasn->extra_ies = os_memdup(extra_ies, extra_ies_len);
227
0
  if (!pasn->extra_ies) {
228
0
    wpa_printf(MSG_ERROR,
229
0
         "PASN: Extra IEs memory allocation failed");
230
0
    return -1;
231
0
  }
232
0
  pasn->extra_ies_len = extra_ies_len;
233
0
  return 0;
234
0
}
235
236
237
int pasn_set_security_profile(struct pasn_data *pasn, const u8 *sp,
238
            size_t sp_len)
239
0
{
240
0
  if (!pasn || !sp || !sp_len)
241
0
    return -1;
242
243
0
  wpabuf_free(pasn->security_profile);
244
0
  pasn->security_profile = wpabuf_alloc_copy(sp, sp_len);
245
0
  if (!pasn->security_profile) {
246
0
    wpa_printf(MSG_ERROR,
247
0
         "PASN: Security Profile element memory allocation failed");
248
0
    return -1;
249
0
  }
250
251
0
  wpa_printf(MSG_DEBUG,
252
0
       "PASN: Security Profile element set (len=%zu)", sp_len);
253
0
  return 0;
254
0
}
255
256
257
void pasn_set_noauth(struct pasn_data *pasn, bool noauth)
258
0
{
259
0
  if (!pasn)
260
0
    return;
261
0
  pasn->noauth = noauth;
262
0
}
263
264
265
int pasn_get_akmp(struct pasn_data *pasn)
266
0
{
267
0
  if (!pasn)
268
0
    return 0;
269
0
  return pasn->akmp;
270
0
}
271
272
273
int pasn_get_cipher(struct pasn_data *pasn)
274
0
{
275
0
  if (!pasn)
276
0
    return 0;
277
0
  return pasn->cipher;
278
0
}
279
280
281
size_t pasn_get_pmk_len(struct pasn_data *pasn)
282
0
{
283
0
  if (!pasn)
284
0
    return 0;
285
0
  return pasn->pmk_len;
286
0
}
287
288
289
u8 * pasn_get_pmk(struct pasn_data *pasn)
290
0
{
291
0
  if (!pasn)
292
0
    return NULL;
293
0
  return pasn->pmk;
294
0
}
295
296
297
struct wpa_ptk * pasn_get_ptk(struct pasn_data *pasn)
298
0
{
299
0
  if (!pasn)
300
0
    return NULL;
301
0
  return &pasn->ptk;
302
0
}
303
304
305
int pasn_add_encrypted_data(struct pasn_data *pasn, struct wpabuf *buf,
306
          const u8 *data, size_t data_len)
307
0
{
308
0
  int ret;
309
0
  u8 *encrypted_data, *padded_data = NULL;
310
0
  u8 *len;
311
0
  size_t pad_len = 0;
312
313
0
  if (!pasn->ptk.kek_len) {
314
0
    wpa_printf(MSG_DEBUG, "PASN: KEK not available");
315
0
    return -2;
316
0
  }
317
318
0
  pad_len = data_len % 8;
319
0
  if (pad_len) {
320
0
    pad_len = 8 - pad_len;
321
0
    padded_data = os_zalloc(data_len + pad_len);
322
0
    if (!padded_data)
323
0
      return -1;
324
0
    os_memcpy(padded_data, data, data_len);
325
0
    data = padded_data;
326
0
    padded_data[data_len] = 0xdd;
327
0
  }
328
0
  data_len += pad_len + 8;
329
330
0
  encrypted_data = os_malloc(data_len);
331
0
  if (!encrypted_data) {
332
0
    os_free(padded_data);
333
0
    return -1;
334
0
  }
335
336
0
  ret = aes_wrap(pasn->ptk.kek, pasn->ptk.kek_len,
337
0
           (data_len - 8) / 8, data, encrypted_data);
338
0
  if (ret) {
339
0
    wpa_printf(MSG_DEBUG, "PASN: AES wrap failed, ret=%d", ret);
340
0
    goto out;
341
0
  }
342
343
0
  if (wpabuf_tailroom(buf) < 1 + 1 + 1 + data_len) {
344
0
    wpa_printf(MSG_DEBUG,
345
0
         "PASN: Not enough room in the buffer for PASN Encrypred Data element");
346
0
    ret = -1;
347
0
    goto out;
348
0
  }
349
350
0
  wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
351
0
  len = wpabuf_put(buf, 1);
352
353
0
  wpabuf_put_u8(buf, WLAN_EID_EXT_PASN_ENCRYPTED_DATA);
354
355
0
  wpabuf_put_data(buf, encrypted_data, data_len);
356
0
  *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
357
358
0
out:
359
0
  os_free(padded_data);
360
0
  os_free(encrypted_data);
361
0
  return ret;
362
0
}
363
364
365
int pasn_parse_encrypted_data(struct pasn_data *pasn, const u8 *data,
366
            size_t len)
367
0
{
368
0
  int ret = -1;
369
0
  u8 *buf;
370
0
  u16 buf_len;
371
0
  struct ieee802_11_elems elems;
372
0
  if (ieee802_11_parse_elems(data, len, &elems, 0) == ParseFailed) {
373
0
    wpa_printf(MSG_DEBUG,
374
0
         "PASN: Failed parsing Authentication frame");
375
0
    return -1;
376
0
  }
377
378
0
  if (!elems.pasn_encrypted_data || elems.pasn_encrypted_data_len < 8 ||
379
0
      elems.pasn_encrypted_data_len % 8) {
380
0
    wpa_printf(MSG_DEBUG, "PASN: No encrypted elements");
381
0
    return 0;
382
0
  }
383
384
0
  buf_len = elems.pasn_encrypted_data_len - 8;
385
386
0
  buf = os_malloc(buf_len);
387
0
  if (!buf)
388
0
    return -1;
389
390
0
  ret = aes_unwrap(pasn->ptk.kek, pasn->ptk.kek_len, buf_len / 8,
391
0
       elems.pasn_encrypted_data, buf);
392
0
  if (ret)
393
0
    wpa_printf(MSG_DEBUG, "PASN: AES unwrap failed, ret=%d", ret);
394
0
  else if (pasn->parse_data_element && pasn->cb_ctx)
395
0
    ret = pasn->parse_data_element(pasn->cb_ctx, buf, buf_len);
396
397
0
  os_free(buf);
398
0
  return ret;
399
0
}