Coverage Report

Created: 2025-08-26 06:04

/src/hostap/src/common/dpp_auth.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * DPP authentication exchange
3
 * Copyright (c) 2017, Qualcomm Atheros, Inc.
4
 * Copyright (c) 2018-2020, The Linux Foundation
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/ieee802_11_common.h"
14
#include "common/wpa_ctrl.h"
15
#include "crypto/aes.h"
16
#include "crypto/aes_siv.h"
17
#include "crypto/random.h"
18
#include "dpp.h"
19
#include "dpp_i.h"
20
21
22
#ifdef CONFIG_TESTING_OPTIONS
23
u8 dpp_protocol_key_override[600];
24
size_t dpp_protocol_key_override_len = 0;
25
u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
26
size_t dpp_nonce_override_len = 0;
27
#endif /* CONFIG_TESTING_OPTIONS */
28
29
30
static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg,
31
            const u8 *hash)
32
0
{
33
0
  if (hash) {
34
0
    wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
35
0
    wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
36
0
    wpabuf_put_le16(msg, SHA256_MAC_LEN);
37
0
    wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
38
0
  }
39
0
}
40
41
42
static void dpp_auth_success(struct dpp_authentication *auth)
43
0
{
44
0
  wpa_printf(MSG_DEBUG,
45
0
       "DPP: Authentication success - clear temporary keys");
46
0
  os_memset(auth->Mx, 0, sizeof(auth->Mx));
47
0
  auth->Mx_len = 0;
48
0
  os_memset(auth->Nx, 0, sizeof(auth->Nx));
49
0
  auth->Nx_len = 0;
50
0
  os_memset(auth->Lx, 0, sizeof(auth->Lx));
51
0
  auth->Lx_len = 0;
52
0
  os_memset(auth->k1, 0, sizeof(auth->k1));
53
0
  os_memset(auth->k2, 0, sizeof(auth->k2));
54
55
0
  auth->auth_success = 1;
56
0
}
57
58
59
static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
60
            const struct wpabuf *pi,
61
            size_t nonce_len,
62
            const u8 *r_pubkey_hash,
63
            const u8 *i_pubkey_hash,
64
            unsigned int neg_freq)
65
0
{
66
0
  struct wpabuf *msg;
67
0
  u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
68
0
  u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
69
0
  u8 *pos;
70
0
  const u8 *addr[2];
71
0
  size_t len[2], siv_len, attr_len;
72
0
  u8 *attr_start, *attr_end;
73
74
  /* Build DPP Authentication Request frame attributes */
75
0
  attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) +
76
0
    4 + sizeof(wrapped_data);
77
0
  if (neg_freq > 0)
78
0
    attr_len += 4 + 2;
79
0
#ifdef CONFIG_DPP2
80
0
  attr_len += 5;
81
0
#endif /* CONFIG_DPP2 */
82
#ifdef CONFIG_TESTING_OPTIONS
83
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
84
    attr_len += 5;
85
#endif /* CONFIG_TESTING_OPTIONS */
86
0
  msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
87
0
  if (!msg)
88
0
    return NULL;
89
90
0
  attr_start = wpabuf_put(msg, 0);
91
92
  /* Responder Bootstrapping Key Hash */
93
0
  dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
94
95
  /* Initiator Bootstrapping Key Hash */
96
0
  dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
97
98
  /* Initiator Protocol Key */
99
0
  if (pi) {
100
0
    wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
101
0
    wpabuf_put_le16(msg, wpabuf_len(pi));
102
0
    wpabuf_put_buf(msg, pi);
103
0
  }
104
105
  /* Channel */
106
0
  if (neg_freq > 0) {
107
0
    u8 op_class, channel;
108
109
0
    if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class,
110
0
              &channel) ==
111
0
        NUM_HOSTAPD_MODES) {
112
0
      wpa_printf(MSG_INFO,
113
0
           "DPP: Unsupported negotiation frequency request: %d",
114
0
           neg_freq);
115
0
      wpabuf_free(msg);
116
0
      return NULL;
117
0
    }
118
0
    wpabuf_put_le16(msg, DPP_ATTR_CHANNEL);
119
0
    wpabuf_put_le16(msg, 2);
120
0
    wpabuf_put_u8(msg, op_class);
121
0
    wpabuf_put_u8(msg, channel);
122
0
  }
123
124
0
#ifdef CONFIG_DPP2
125
  /* Protocol Version */
126
0
  if (DPP_VERSION > 1) {
127
0
    wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
128
0
    wpabuf_put_le16(msg, 1);
129
0
    wpabuf_put_u8(msg, DPP_VERSION);
130
0
  }
131
0
#endif /* CONFIG_DPP2 */
132
133
#ifdef CONFIG_TESTING_OPTIONS
134
  if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) {
135
    wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
136
    goto skip_wrapped_data;
137
  }
138
#endif /* CONFIG_TESTING_OPTIONS */
139
140
  /* Wrapped data ({I-nonce, I-capabilities}k1) */
141
0
  pos = clear;
142
143
#ifdef CONFIG_TESTING_OPTIONS
144
  if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) {
145
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
146
    goto skip_i_nonce;
147
  }
148
  if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) {
149
    wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce");
150
    WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
151
    pos += 2;
152
    WPA_PUT_LE16(pos, nonce_len - 1);
153
    pos += 2;
154
    os_memcpy(pos, auth->i_nonce, nonce_len - 1);
155
    pos += nonce_len - 1;
156
    goto skip_i_nonce;
157
  }
158
#endif /* CONFIG_TESTING_OPTIONS */
159
160
  /* I-nonce */
161
0
  WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
162
0
  pos += 2;
163
0
  WPA_PUT_LE16(pos, nonce_len);
164
0
  pos += 2;
165
0
  os_memcpy(pos, auth->i_nonce, nonce_len);
166
0
  pos += nonce_len;
167
168
#ifdef CONFIG_TESTING_OPTIONS
169
skip_i_nonce:
170
  if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) {
171
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab");
172
    goto skip_i_capab;
173
  }
174
#endif /* CONFIG_TESTING_OPTIONS */
175
176
  /* I-capabilities */
177
0
  WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
178
0
  pos += 2;
179
0
  WPA_PUT_LE16(pos, 1);
180
0
  pos += 2;
181
0
  auth->i_capab = auth->allowed_roles;
182
0
  *pos++ = auth->i_capab;
183
#ifdef CONFIG_TESTING_OPTIONS
184
  if (dpp_test == DPP_TEST_ZERO_I_CAPAB) {
185
    wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities");
186
    pos[-1] = 0;
187
  }
188
skip_i_capab:
189
#endif /* CONFIG_TESTING_OPTIONS */
190
191
0
  attr_end = wpabuf_put(msg, 0);
192
193
  /* OUI, OUI type, Crypto Suite, DPP frame type */
194
0
  addr[0] = wpabuf_head_u8(msg) + 2;
195
0
  len[0] = 3 + 1 + 1 + 1;
196
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
197
198
  /* Attributes before Wrapped Data */
199
0
  addr[1] = attr_start;
200
0
  len[1] = attr_end - attr_start;
201
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
202
203
0
  siv_len = pos - clear;
204
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
205
0
  if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
206
0
          2, addr, len, wrapped_data) < 0) {
207
0
    wpabuf_free(msg);
208
0
    return NULL;
209
0
  }
210
0
  siv_len += AES_BLOCK_SIZE;
211
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
212
0
        wrapped_data, siv_len);
213
214
0
  wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
215
0
  wpabuf_put_le16(msg, siv_len);
216
0
  wpabuf_put_data(msg, wrapped_data, siv_len);
217
218
#ifdef CONFIG_TESTING_OPTIONS
219
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) {
220
    wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
221
    dpp_build_attr_status(msg, DPP_STATUS_OK);
222
  }
223
skip_wrapped_data:
224
#endif /* CONFIG_TESTING_OPTIONS */
225
226
0
  wpa_hexdump_buf(MSG_DEBUG,
227
0
      "DPP: Authentication Request frame attributes", msg);
228
229
0
  return msg;
230
0
}
231
232
233
static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth,
234
             enum dpp_status_error status,
235
             const struct wpabuf *pr,
236
             size_t nonce_len,
237
             const u8 *r_pubkey_hash,
238
             const u8 *i_pubkey_hash,
239
             const u8 *r_nonce, const u8 *i_nonce,
240
             const u8 *wrapped_r_auth,
241
             size_t wrapped_r_auth_len,
242
             const u8 *siv_key)
243
0
{
244
0
  struct wpabuf *msg;
245
0
#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
246
0
    4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE
247
0
  u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
248
0
  u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
249
0
  const u8 *addr[2];
250
0
  size_t len[2], siv_len, attr_len;
251
0
  u8 *attr_start, *attr_end, *pos;
252
253
0
  auth->waiting_auth_conf = 1;
254
0
  auth->auth_resp_status = status;
255
0
  auth->auth_resp_tries = 0;
256
257
  /* Build DPP Authentication Response frame attributes */
258
0
  attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
259
0
    4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data);
260
0
#ifdef CONFIG_DPP2
261
0
  attr_len += 5;
262
0
#endif /* CONFIG_DPP2 */
263
#ifdef CONFIG_TESTING_OPTIONS
264
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP)
265
    attr_len += 5;
266
#endif /* CONFIG_TESTING_OPTIONS */
267
0
  msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
268
0
  if (!msg)
269
0
    return NULL;
270
271
0
  attr_start = wpabuf_put(msg, 0);
272
273
  /* DPP Status */
274
0
  if (status != 255)
275
0
    dpp_build_attr_status(msg, status);
276
277
  /* Responder Bootstrapping Key Hash */
278
0
  dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
279
280
  /* Initiator Bootstrapping Key Hash (mutual authentication) */
281
0
  dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
282
283
  /* Responder Protocol Key */
284
0
  if (pr) {
285
0
    wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
286
0
    wpabuf_put_le16(msg, wpabuf_len(pr));
287
0
    wpabuf_put_buf(msg, pr);
288
0
  }
289
290
0
#ifdef CONFIG_DPP2
291
  /* Protocol Version */
292
0
  if (auth->peer_version >= 2) {
293
0
    wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
294
0
    wpabuf_put_le16(msg, 1);
295
0
    wpabuf_put_u8(msg, DPP_VERSION);
296
0
  }
297
0
#endif /* CONFIG_DPP2 */
298
299
0
  attr_end = wpabuf_put(msg, 0);
300
301
#ifdef CONFIG_TESTING_OPTIONS
302
  if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) {
303
    wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
304
    goto skip_wrapped_data;
305
  }
306
#endif /* CONFIG_TESTING_OPTIONS */
307
308
  /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
309
0
  pos = clear;
310
311
0
  if (r_nonce) {
312
    /* R-nonce */
313
0
    WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
314
0
    pos += 2;
315
0
    WPA_PUT_LE16(pos, nonce_len);
316
0
    pos += 2;
317
0
    os_memcpy(pos, r_nonce, nonce_len);
318
0
    pos += nonce_len;
319
0
  }
320
321
0
  if (i_nonce) {
322
    /* I-nonce */
323
0
    WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
324
0
    pos += 2;
325
0
    WPA_PUT_LE16(pos, nonce_len);
326
0
    pos += 2;
327
0
    os_memcpy(pos, i_nonce, nonce_len);
328
#ifdef CONFIG_TESTING_OPTIONS
329
    if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) {
330
      wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch");
331
      pos[nonce_len / 2] ^= 0x01;
332
    }
333
#endif /* CONFIG_TESTING_OPTIONS */
334
0
    pos += nonce_len;
335
0
  }
336
337
#ifdef CONFIG_TESTING_OPTIONS
338
  if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) {
339
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab");
340
    goto skip_r_capab;
341
  }
342
#endif /* CONFIG_TESTING_OPTIONS */
343
344
  /* R-capabilities */
345
0
  WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
346
0
  pos += 2;
347
0
  WPA_PUT_LE16(pos, 1);
348
0
  pos += 2;
349
0
  auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
350
0
    DPP_CAPAB_ENROLLEE;
351
0
  *pos++ = auth->r_capab;
352
#ifdef CONFIG_TESTING_OPTIONS
353
  if (dpp_test == DPP_TEST_ZERO_R_CAPAB) {
354
    wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities");
355
    pos[-1] = 0;
356
  } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) {
357
    wpa_printf(MSG_INFO,
358
         "DPP: TESTING - incompatible R-capabilities");
359
    if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) ==
360
        (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE))
361
      pos[-1] = 0;
362
    else
363
      pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE :
364
        DPP_CAPAB_CONFIGURATOR;
365
  }
366
skip_r_capab:
367
#endif /* CONFIG_TESTING_OPTIONS */
368
369
0
  if (wrapped_r_auth) {
370
    /* {R-auth}ke */
371
0
    WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
372
0
    pos += 2;
373
0
    WPA_PUT_LE16(pos, wrapped_r_auth_len);
374
0
    pos += 2;
375
0
    os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
376
0
    pos += wrapped_r_auth_len;
377
0
  }
378
379
  /* OUI, OUI type, Crypto Suite, DPP frame type */
380
0
  addr[0] = wpabuf_head_u8(msg) + 2;
381
0
  len[0] = 3 + 1 + 1 + 1;
382
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
383
384
  /* Attributes before Wrapped Data */
385
0
  addr[1] = attr_start;
386
0
  len[1] = attr_end - attr_start;
387
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
388
389
0
  siv_len = pos - clear;
390
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
391
0
  if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len,
392
0
          2, addr, len, wrapped_data) < 0) {
393
0
    wpabuf_free(msg);
394
0
    return NULL;
395
0
  }
396
0
  siv_len += AES_BLOCK_SIZE;
397
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
398
0
        wrapped_data, siv_len);
399
400
0
  wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
401
0
  wpabuf_put_le16(msg, siv_len);
402
0
  wpabuf_put_data(msg, wrapped_data, siv_len);
403
404
#ifdef CONFIG_TESTING_OPTIONS
405
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) {
406
    wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
407
    dpp_build_attr_status(msg, DPP_STATUS_OK);
408
  }
409
skip_wrapped_data:
410
#endif /* CONFIG_TESTING_OPTIONS */
411
412
0
  wpa_hexdump_buf(MSG_DEBUG,
413
0
      "DPP: Authentication Response frame attributes", msg);
414
0
  return msg;
415
0
}
416
417
418
static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
419
0
{
420
0
  size_t nonce_len;
421
0
  size_t secret_len;
422
0
  struct wpabuf *msg, *pr = NULL;
423
0
  u8 r_auth[4 + DPP_MAX_HASH_LEN];
424
0
  u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth;
425
0
  size_t wrapped_r_auth_len;
426
0
  int ret = -1;
427
0
  const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce;
428
0
  enum dpp_status_error status = DPP_STATUS_OK;
429
#ifdef CONFIG_TESTING_OPTIONS
430
  u8 test_hash[SHA256_MAC_LEN];
431
#endif /* CONFIG_TESTING_OPTIONS */
432
433
0
  wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
434
0
  if (!auth->own_bi)
435
0
    return -1;
436
437
#ifdef CONFIG_TESTING_OPTIONS
438
  if (dpp_nonce_override_len > 0) {
439
    wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce");
440
    nonce_len = dpp_nonce_override_len;
441
    os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len);
442
  } else {
443
    nonce_len = auth->curve->nonce_len;
444
    if (random_get_bytes(auth->r_nonce, nonce_len)) {
445
      wpa_printf(MSG_ERROR,
446
           "DPP: Failed to generate R-nonce");
447
      goto fail;
448
    }
449
  }
450
#else /* CONFIG_TESTING_OPTIONS */
451
0
  nonce_len = auth->curve->nonce_len;
452
0
  if (random_get_bytes(auth->r_nonce, nonce_len)) {
453
0
    wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
454
0
    goto fail;
455
0
  }
456
0
#endif /* CONFIG_TESTING_OPTIONS */
457
0
  wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
458
459
0
  crypto_ec_key_deinit(auth->own_protocol_key);
460
#ifdef CONFIG_TESTING_OPTIONS
461
  if (dpp_protocol_key_override_len) {
462
    const struct dpp_curve_params *tmp_curve;
463
464
    wpa_printf(MSG_INFO,
465
         "DPP: TESTING - override protocol key");
466
    auth->own_protocol_key = dpp_set_keypair(
467
      &tmp_curve, dpp_protocol_key_override,
468
      dpp_protocol_key_override_len);
469
  } else {
470
    auth->own_protocol_key = dpp_gen_keypair(auth->curve);
471
  }
472
#else /* CONFIG_TESTING_OPTIONS */
473
0
  auth->own_protocol_key = dpp_gen_keypair(auth->curve);
474
0
#endif /* CONFIG_TESTING_OPTIONS */
475
0
  if (!auth->own_protocol_key)
476
0
    goto fail;
477
478
0
  pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
479
0
  if (!pr)
480
0
    goto fail;
481
482
  /* ECDH: N = pR * PI */
483
0
  if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
484
0
         auth->Nx, &secret_len) < 0)
485
0
    goto fail;
486
487
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
488
0
      auth->Nx, auth->secret_len);
489
0
  auth->Nx_len = auth->secret_len;
490
491
0
  if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
492
0
        auth->curve->hash_len) < 0)
493
0
    goto fail;
494
495
0
  if (auth->own_bi && auth->peer_bi) {
496
    /* Mutual authentication */
497
0
    if (dpp_auth_derive_l_responder(auth) < 0)
498
0
      goto fail;
499
0
  }
500
501
0
  if (dpp_derive_bk_ke(auth) < 0)
502
0
    goto fail;
503
504
  /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
505
0
  WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
506
0
  WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
507
0
  if (dpp_gen_r_auth(auth, r_auth + 4) < 0)
508
0
    goto fail;
509
#ifdef CONFIG_TESTING_OPTIONS
510
  if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) {
511
    wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch");
512
    r_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
513
  }
514
#endif /* CONFIG_TESTING_OPTIONS */
515
0
  if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
516
0
          r_auth, 4 + auth->curve->hash_len,
517
0
          0, NULL, NULL, wrapped_r_auth) < 0)
518
0
    goto fail;
519
0
  wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
520
0
  wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
521
0
        wrapped_r_auth, wrapped_r_auth_len);
522
0
  w_r_auth = wrapped_r_auth;
523
524
0
  r_pubkey_hash = auth->own_bi->pubkey_hash;
525
0
  if (auth->peer_bi)
526
0
    i_pubkey_hash = auth->peer_bi->pubkey_hash;
527
0
  else
528
0
    i_pubkey_hash = NULL;
529
530
0
  i_nonce = auth->i_nonce;
531
0
  r_nonce = auth->r_nonce;
532
533
#ifdef CONFIG_TESTING_OPTIONS
534
  if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
535
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
536
    r_pubkey_hash = NULL;
537
  } else if (dpp_test ==
538
       DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
539
    wpa_printf(MSG_INFO,
540
         "DPP: TESTING - invalid R-Bootstrap Key Hash");
541
    os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
542
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
543
    r_pubkey_hash = test_hash;
544
  } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
545
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
546
    i_pubkey_hash = NULL;
547
  } else if (dpp_test ==
548
       DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
549
    wpa_printf(MSG_INFO,
550
         "DPP: TESTING - invalid I-Bootstrap Key Hash");
551
    if (i_pubkey_hash)
552
      os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
553
    else
554
      os_memset(test_hash, 0, SHA256_MAC_LEN);
555
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
556
    i_pubkey_hash = test_hash;
557
  } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) {
558
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key");
559
    wpabuf_free(pr);
560
    pr = NULL;
561
  } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) {
562
    wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key");
563
    wpabuf_free(pr);
564
    pr = wpabuf_alloc(2 * auth->curve->prime_len);
565
    if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0)
566
      goto fail;
567
  } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) {
568
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth");
569
    w_r_auth = NULL;
570
    wrapped_r_auth_len = 0;
571
  } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
572
    wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
573
    status = 255;
574
  } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) {
575
    wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
576
    status = 254;
577
  } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) {
578
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce");
579
    r_nonce = NULL;
580
  } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
581
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
582
    i_nonce = NULL;
583
  }
584
#endif /* CONFIG_TESTING_OPTIONS */
585
586
0
  msg = dpp_auth_build_resp(auth, status, pr, nonce_len,
587
0
          r_pubkey_hash, i_pubkey_hash,
588
0
          r_nonce, i_nonce,
589
0
          w_r_auth, wrapped_r_auth_len,
590
0
          auth->k2);
591
0
  if (!msg)
592
0
    goto fail;
593
0
  wpabuf_free(auth->resp_msg);
594
0
  auth->resp_msg = msg;
595
0
  ret = 0;
596
0
fail:
597
0
  wpabuf_free(pr);
598
0
  return ret;
599
0
}
600
601
602
static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
603
              enum dpp_status_error status)
604
0
{
605
0
  struct wpabuf *msg;
606
0
  const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce;
607
#ifdef CONFIG_TESTING_OPTIONS
608
  u8 test_hash[SHA256_MAC_LEN];
609
#endif /* CONFIG_TESTING_OPTIONS */
610
611
0
  if (!auth->own_bi)
612
0
    return -1;
613
0
  wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
614
615
0
  r_pubkey_hash = auth->own_bi->pubkey_hash;
616
0
  if (auth->peer_bi)
617
0
    i_pubkey_hash = auth->peer_bi->pubkey_hash;
618
0
  else
619
0
    i_pubkey_hash = NULL;
620
621
0
  i_nonce = auth->i_nonce;
622
623
#ifdef CONFIG_TESTING_OPTIONS
624
  if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
625
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
626
    r_pubkey_hash = NULL;
627
  } else if (dpp_test ==
628
       DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
629
    wpa_printf(MSG_INFO,
630
         "DPP: TESTING - invalid R-Bootstrap Key Hash");
631
    os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
632
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
633
    r_pubkey_hash = test_hash;
634
  } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
635
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
636
    i_pubkey_hash = NULL;
637
  } else if (dpp_test ==
638
       DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
639
    wpa_printf(MSG_INFO,
640
         "DPP: TESTING - invalid I-Bootstrap Key Hash");
641
    if (i_pubkey_hash)
642
      os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
643
    else
644
      os_memset(test_hash, 0, SHA256_MAC_LEN);
645
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
646
    i_pubkey_hash = test_hash;
647
  } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
648
    wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
649
    status = 255;
650
  } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
651
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
652
    i_nonce = NULL;
653
  }
654
#endif /* CONFIG_TESTING_OPTIONS */
655
656
0
  msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len,
657
0
          r_pubkey_hash, i_pubkey_hash,
658
0
          NULL, i_nonce, NULL, 0, auth->k1);
659
0
  if (!msg)
660
0
    return -1;
661
0
  wpabuf_free(auth->resp_msg);
662
0
  auth->resp_msg = msg;
663
0
  return 0;
664
0
}
665
666
667
struct dpp_authentication *
668
dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles,
669
    int qr_mutual, struct dpp_bootstrap_info *peer_bi,
670
    struct dpp_bootstrap_info *own_bi,
671
    unsigned int freq, const u8 *hdr, const u8 *attr_start,
672
    size_t attr_len)
673
0
{
674
0
  struct crypto_ec_key *pi = NULL;
675
0
  size_t secret_len;
676
0
  const u8 *addr[2];
677
0
  size_t len[2];
678
0
  u8 *unwrapped = NULL;
679
0
  size_t unwrapped_len = 0;
680
0
  const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap,
681
0
    *channel;
682
0
  u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len,
683
0
    i_bootstrap_len, channel_len;
684
0
  struct dpp_authentication *auth = NULL;
685
0
#ifdef CONFIG_DPP2
686
0
  const u8 *version;
687
0
  u16 version_len;
688
0
#endif /* CONFIG_DPP2 */
689
690
#ifdef CONFIG_TESTING_OPTIONS
691
  if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
692
    wpa_printf(MSG_INFO,
693
         "DPP: TESTING - stop at Authentication Request");
694
    return NULL;
695
  }
696
#endif /* CONFIG_TESTING_OPTIONS */
697
698
0
  wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
699
0
            &wrapped_data_len);
700
0
  if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
701
0
    wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
702
0
      "Missing or invalid required Wrapped Data attribute");
703
0
    return NULL;
704
0
  }
705
0
  wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
706
0
        wrapped_data, wrapped_data_len);
707
0
  attr_len = wrapped_data - 4 - attr_start;
708
709
0
  auth = dpp_alloc_auth(dpp, msg_ctx);
710
0
  if (!auth)
711
0
    goto fail;
712
0
  if (peer_bi && peer_bi->configurator_params &&
713
0
      dpp_set_configurator(auth, peer_bi->configurator_params) < 0)
714
0
    goto fail;
715
0
  auth->peer_bi = peer_bi;
716
0
  auth->own_bi = own_bi;
717
0
  auth->curve = own_bi->curve;
718
0
  auth->curr_freq = freq;
719
720
0
  auth->peer_version = 1; /* default to the first version */
721
0
#ifdef CONFIG_DPP2
722
0
  version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
723
0
             &version_len);
724
0
  if (version && DPP_VERSION > 1) {
725
0
    if (version_len < 1 || version[0] == 0) {
726
0
      dpp_auth_fail(auth,
727
0
              "Invalid Protocol Version attribute");
728
0
      goto fail;
729
0
    }
730
0
    auth->peer_version = version[0];
731
0
    wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
732
0
         auth->peer_version);
733
0
  }
734
0
#endif /* CONFIG_DPP2 */
735
736
0
  channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
737
0
             &channel_len);
738
0
  if (channel) {
739
0
    int neg_freq;
740
741
0
    if (channel_len < 2) {
742
0
      dpp_auth_fail(auth, "Too short Channel attribute");
743
0
      goto fail;
744
0
    }
745
746
0
    neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
747
0
    wpa_printf(MSG_DEBUG,
748
0
         "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
749
0
         channel[0], channel[1], neg_freq);
750
0
    if (neg_freq < 0) {
751
0
      dpp_auth_fail(auth,
752
0
              "Unsupported Channel attribute value");
753
0
      goto fail;
754
0
    }
755
756
0
    if (auth->curr_freq != (unsigned int) neg_freq) {
757
0
      wpa_printf(MSG_DEBUG,
758
0
           "DPP: Changing negotiation channel from %u MHz to %u MHz",
759
0
           freq, neg_freq);
760
0
      auth->curr_freq = neg_freq;
761
0
    }
762
0
  }
763
764
0
  i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
765
0
             &i_proto_len);
766
0
  if (!i_proto) {
767
0
    dpp_auth_fail(auth,
768
0
            "Missing required Initiator Protocol Key attribute");
769
0
    goto fail;
770
0
  }
771
0
  wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
772
0
        i_proto, i_proto_len);
773
774
  /* M = bR * PI */
775
0
  pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
776
0
  if (!pi) {
777
0
    dpp_auth_fail(auth, "Invalid Initiator Protocol Key");
778
0
    goto fail;
779
0
  }
780
0
  dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
781
782
0
  if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
783
0
    goto fail;
784
0
  auth->secret_len = secret_len;
785
786
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
787
0
      auth->Mx, auth->secret_len);
788
0
  auth->Mx_len = auth->secret_len;
789
790
0
  if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
791
0
        auth->curve->hash_len) < 0)
792
0
    goto fail;
793
794
0
  addr[0] = hdr;
795
0
  len[0] = DPP_HDR_LEN;
796
0
  addr[1] = attr_start;
797
0
  len[1] = attr_len;
798
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
799
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
800
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
801
0
        wrapped_data, wrapped_data_len);
802
0
  unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
803
0
  unwrapped = os_malloc(unwrapped_len);
804
0
  if (!unwrapped)
805
0
    goto fail;
806
0
  if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
807
0
          wrapped_data, wrapped_data_len,
808
0
          2, addr, len, unwrapped) < 0) {
809
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
810
0
    goto fail;
811
0
  }
812
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
813
0
        unwrapped, unwrapped_len);
814
815
0
  if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
816
0
    dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
817
0
    goto fail;
818
0
  }
819
820
0
  i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
821
0
             &i_nonce_len);
822
0
  if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
823
0
    dpp_auth_fail(auth, "Missing or invalid I-nonce");
824
0
    goto fail;
825
0
  }
826
0
  wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
827
0
  os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
828
829
0
  i_capab = dpp_get_attr(unwrapped, unwrapped_len,
830
0
             DPP_ATTR_I_CAPABILITIES,
831
0
             &i_capab_len);
832
0
  if (!i_capab || i_capab_len < 1) {
833
0
    dpp_auth_fail(auth, "Missing or invalid I-capabilities");
834
0
    goto fail;
835
0
  }
836
0
  auth->i_capab = i_capab[0];
837
0
  wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
838
839
0
  bin_clear_free(unwrapped, unwrapped_len);
840
0
  unwrapped = NULL;
841
842
0
  switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
843
0
  case DPP_CAPAB_ENROLLEE:
844
0
    if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
845
0
      wpa_printf(MSG_DEBUG,
846
0
           "DPP: Local policy does not allow Configurator role");
847
0
      goto not_compatible;
848
0
    }
849
0
    wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
850
0
    auth->configurator = 1;
851
0
    break;
852
0
  case DPP_CAPAB_CONFIGURATOR:
853
0
    if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
854
0
      wpa_printf(MSG_DEBUG,
855
0
           "DPP: Local policy does not allow Enrollee role");
856
0
      goto not_compatible;
857
0
    }
858
0
    wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
859
0
    auth->configurator = 0;
860
0
    break;
861
0
  case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE:
862
0
    if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) {
863
0
      wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
864
0
      auth->configurator = 0;
865
0
    } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) {
866
0
      wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
867
0
      auth->configurator = 1;
868
0
    } else {
869
0
      wpa_printf(MSG_DEBUG,
870
0
           "DPP: Local policy does not allow Configurator/Enrollee role");
871
0
      goto not_compatible;
872
0
    }
873
0
    break;
874
0
  default:
875
0
    wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
876
0
    wpa_msg(auth->msg_ctx, MSG_INFO,
877
0
      DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x",
878
0
      auth->i_capab & DPP_CAPAB_ROLE_MASK);
879
0
    goto fail;
880
0
  }
881
882
0
  auth->peer_protocol_key = pi;
883
0
  pi = NULL;
884
0
  if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
885
0
    char hex[SHA256_MAC_LEN * 2 + 1];
886
887
0
    wpa_printf(MSG_DEBUG,
888
0
         "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
889
0
    if (dpp_auth_build_resp_status(auth,
890
0
                 DPP_STATUS_RESPONSE_PENDING) < 0)
891
0
      goto fail;
892
0
    i_bootstrap = dpp_get_attr(attr_start, attr_len,
893
0
             DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
894
0
             &i_bootstrap_len);
895
0
    if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
896
0
      auth->response_pending = 1;
897
0
      os_memcpy(auth->waiting_pubkey_hash,
898
0
          i_bootstrap, i_bootstrap_len);
899
0
      wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
900
0
           i_bootstrap_len);
901
0
    } else {
902
0
      hex[0] = '\0';
903
0
    }
904
905
0
    wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
906
0
      "%s", hex);
907
0
    return auth;
908
0
  }
909
0
  if (dpp_auth_build_resp_ok(auth) < 0)
910
0
    goto fail;
911
912
0
  return auth;
913
914
0
not_compatible:
915
0
  wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
916
0
    "i-capab=0x%02x", auth->i_capab);
917
0
  if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
918
0
    auth->configurator = 1;
919
0
  else
920
0
    auth->configurator = 0;
921
0
  auth->peer_protocol_key = pi;
922
0
  pi = NULL;
923
0
  if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
924
0
    goto fail;
925
926
0
  auth->remove_on_tx_status = 1;
927
0
  return auth;
928
0
fail:
929
0
  bin_clear_free(unwrapped, unwrapped_len);
930
0
  crypto_ec_key_deinit(pi);
931
0
  dpp_auth_deinit(auth);
932
0
  return NULL;
933
0
}
934
935
936
int dpp_notify_new_qr_code(struct dpp_authentication *auth,
937
         struct dpp_bootstrap_info *peer_bi)
938
0
{
939
0
  if (!auth || !auth->response_pending ||
940
0
      os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
941
0
          SHA256_MAC_LEN) != 0)
942
0
    return 0;
943
944
0
  wpa_printf(MSG_DEBUG,
945
0
       "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
946
0
       MACSTR, MAC2STR(auth->peer_mac_addr));
947
0
  auth->peer_bi = peer_bi;
948
949
0
  if (dpp_auth_build_resp_ok(auth) < 0)
950
0
    return -1;
951
952
0
  return 1;
953
0
}
954
955
956
static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth,
957
             enum dpp_status_error status)
958
0
{
959
0
  struct wpabuf *msg;
960
0
  u8 i_auth[4 + DPP_MAX_HASH_LEN];
961
0
  size_t i_auth_len;
962
0
  u8 r_nonce[4 + DPP_MAX_NONCE_LEN];
963
0
  size_t r_nonce_len;
964
0
  const u8 *addr[2];
965
0
  size_t len[2], attr_len;
966
0
  u8 *wrapped_i_auth;
967
0
  u8 *wrapped_r_nonce;
968
0
  u8 *attr_start, *attr_end;
969
0
  const u8 *r_pubkey_hash, *i_pubkey_hash;
970
#ifdef CONFIG_TESTING_OPTIONS
971
  u8 test_hash[SHA256_MAC_LEN];
972
#endif /* CONFIG_TESTING_OPTIONS */
973
974
0
  wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
975
976
0
  i_auth_len = 4 + auth->curve->hash_len;
977
0
  r_nonce_len = 4 + auth->curve->nonce_len;
978
  /* Build DPP Authentication Confirmation frame attributes */
979
0
  attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
980
0
    4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE;
981
#ifdef CONFIG_TESTING_OPTIONS
982
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF)
983
    attr_len += 5;
984
#endif /* CONFIG_TESTING_OPTIONS */
985
0
  msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
986
0
  if (!msg)
987
0
    goto fail;
988
989
0
  attr_start = wpabuf_put(msg, 0);
990
991
0
  r_pubkey_hash = auth->peer_bi->pubkey_hash;
992
0
  if (auth->own_bi)
993
0
    i_pubkey_hash = auth->own_bi->pubkey_hash;
994
0
  else
995
0
    i_pubkey_hash = NULL;
996
997
#ifdef CONFIG_TESTING_OPTIONS
998
  if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) {
999
    wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1000
    goto skip_status;
1001
  } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) {
1002
    wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1003
    status = 254;
1004
  }
1005
#endif /* CONFIG_TESTING_OPTIONS */
1006
1007
  /* DPP Status */
1008
0
  dpp_build_attr_status(msg, status);
1009
1010
#ifdef CONFIG_TESTING_OPTIONS
1011
skip_status:
1012
  if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
1013
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
1014
    r_pubkey_hash = NULL;
1015
  } else if (dpp_test ==
1016
       DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
1017
    wpa_printf(MSG_INFO,
1018
         "DPP: TESTING - invalid R-Bootstrap Key Hash");
1019
    os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
1020
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1021
    r_pubkey_hash = test_hash;
1022
  } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
1023
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
1024
    i_pubkey_hash = NULL;
1025
  } else if (dpp_test ==
1026
       DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
1027
    wpa_printf(MSG_INFO,
1028
         "DPP: TESTING - invalid I-Bootstrap Key Hash");
1029
    if (i_pubkey_hash)
1030
      os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
1031
    else
1032
      os_memset(test_hash, 0, SHA256_MAC_LEN);
1033
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1034
    i_pubkey_hash = test_hash;
1035
  }
1036
#endif /* CONFIG_TESTING_OPTIONS */
1037
1038
  /* Responder Bootstrapping Key Hash */
1039
0
  dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
1040
1041
  /* Initiator Bootstrapping Key Hash (mutual authentication) */
1042
0
  dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
1043
1044
#ifdef CONFIG_TESTING_OPTIONS
1045
  if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF)
1046
    goto skip_wrapped_data;
1047
  if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
1048
    i_auth_len = 0;
1049
#endif /* CONFIG_TESTING_OPTIONS */
1050
1051
0
  attr_end = wpabuf_put(msg, 0);
1052
1053
  /* OUI, OUI type, Crypto Suite, DPP frame type */
1054
0
  addr[0] = wpabuf_head_u8(msg) + 2;
1055
0
  len[0] = 3 + 1 + 1 + 1;
1056
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1057
1058
  /* Attributes before Wrapped Data */
1059
0
  addr[1] = attr_start;
1060
0
  len[1] = attr_end - attr_start;
1061
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1062
1063
0
  if (status == DPP_STATUS_OK) {
1064
    /* I-auth wrapped with ke */
1065
0
    wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1066
0
    wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
1067
0
    wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
1068
1069
#ifdef CONFIG_TESTING_OPTIONS
1070
    if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
1071
      goto skip_i_auth;
1072
#endif /* CONFIG_TESTING_OPTIONS */
1073
1074
    /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |]
1075
     *        1) */
1076
0
    WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
1077
0
    WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
1078
0
    if (dpp_gen_i_auth(auth, i_auth + 4) < 0)
1079
0
      goto fail;
1080
1081
#ifdef CONFIG_TESTING_OPTIONS
1082
    if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) {
1083
      wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch");
1084
      i_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
1085
    }
1086
skip_i_auth:
1087
#endif /* CONFIG_TESTING_OPTIONS */
1088
0
    if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
1089
0
            i_auth, i_auth_len,
1090
0
            2, addr, len, wrapped_i_auth) < 0)
1091
0
      goto fail;
1092
0
    wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
1093
0
          wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
1094
0
  } else {
1095
    /* R-nonce wrapped with k2 */
1096
0
    wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1097
0
    wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE);
1098
0
    wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE);
1099
1100
0
    WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE);
1101
0
    WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len);
1102
0
    os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len);
1103
1104
0
    if (aes_siv_encrypt(auth->k2, auth->curve->hash_len,
1105
0
            r_nonce, r_nonce_len,
1106
0
            2, addr, len, wrapped_r_nonce) < 0)
1107
0
      goto fail;
1108
0
    wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2",
1109
0
          wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE);
1110
0
  }
1111
1112
#ifdef CONFIG_TESTING_OPTIONS
1113
  if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) {
1114
    wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1115
    dpp_build_attr_status(msg, DPP_STATUS_OK);
1116
  }
1117
skip_wrapped_data:
1118
#endif /* CONFIG_TESTING_OPTIONS */
1119
1120
0
  wpa_hexdump_buf(MSG_DEBUG,
1121
0
      "DPP: Authentication Confirmation frame attributes",
1122
0
      msg);
1123
0
  if (status == DPP_STATUS_OK)
1124
0
    dpp_auth_success(auth);
1125
1126
0
  return msg;
1127
1128
0
fail:
1129
0
  wpabuf_free(msg);
1130
0
  return NULL;
1131
0
}
1132
1133
1134
static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
1135
0
{
1136
0
  struct dpp_bootstrap_info *bi;
1137
1138
0
  if (auth->own_bi)
1139
0
    return 0; /* already generated */
1140
1141
0
  bi = os_zalloc(sizeof(*bi));
1142
0
  if (!bi)
1143
0
    return -1;
1144
0
  bi->type = DPP_BOOTSTRAP_QR_CODE;
1145
0
  if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 ||
1146
0
      dpp_gen_uri(bi) < 0)
1147
0
    goto fail;
1148
0
  wpa_printf(MSG_DEBUG,
1149
0
       "DPP: Auto-generated own bootstrapping key info: URI %s",
1150
0
       bi->uri);
1151
1152
0
  auth->tmp_own_bi = auth->own_bi = bi;
1153
1154
0
  return 0;
1155
0
fail:
1156
0
  dpp_bootstrap_info_free(bi);
1157
0
  return -1;
1158
0
}
1159
1160
1161
struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx,
1162
            struct dpp_bootstrap_info *peer_bi,
1163
            struct dpp_bootstrap_info *own_bi,
1164
            u8 dpp_allowed_roles,
1165
            unsigned int neg_freq,
1166
            struct hostapd_hw_modes *own_modes,
1167
            u16 num_modes)
1168
0
{
1169
0
  struct dpp_authentication *auth;
1170
0
  size_t nonce_len;
1171
0
  size_t secret_len;
1172
0
  struct wpabuf *pi = NULL;
1173
0
  const u8 *r_pubkey_hash, *i_pubkey_hash;
1174
#ifdef CONFIG_TESTING_OPTIONS
1175
  u8 test_hash[SHA256_MAC_LEN];
1176
#endif /* CONFIG_TESTING_OPTIONS */
1177
1178
0
  auth = dpp_alloc_auth(dpp, msg_ctx);
1179
0
  if (!auth)
1180
0
    return NULL;
1181
0
  if (peer_bi->configurator_params &&
1182
0
      dpp_set_configurator(auth, peer_bi->configurator_params) < 0)
1183
0
    goto fail;
1184
0
  auth->initiator = 1;
1185
0
  auth->waiting_auth_resp = 1;
1186
0
  auth->allowed_roles = dpp_allowed_roles;
1187
0
  auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR);
1188
0
  auth->peer_bi = peer_bi;
1189
0
  auth->own_bi = own_bi;
1190
0
  auth->curve = peer_bi->curve;
1191
1192
0
  if (dpp_autogen_bootstrap_key(auth) < 0 ||
1193
0
      dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0)
1194
0
    goto fail;
1195
1196
#ifdef CONFIG_TESTING_OPTIONS
1197
  if (dpp_nonce_override_len > 0) {
1198
    wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce");
1199
    nonce_len = dpp_nonce_override_len;
1200
    os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len);
1201
  } else {
1202
    nonce_len = auth->curve->nonce_len;
1203
    if (random_get_bytes(auth->i_nonce, nonce_len)) {
1204
      wpa_printf(MSG_ERROR,
1205
           "DPP: Failed to generate I-nonce");
1206
      goto fail;
1207
    }
1208
  }
1209
#else /* CONFIG_TESTING_OPTIONS */
1210
0
  nonce_len = auth->curve->nonce_len;
1211
0
  if (random_get_bytes(auth->i_nonce, nonce_len)) {
1212
0
    wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
1213
0
    goto fail;
1214
0
  }
1215
0
#endif /* CONFIG_TESTING_OPTIONS */
1216
0
  wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
1217
1218
#ifdef CONFIG_TESTING_OPTIONS
1219
  if (dpp_protocol_key_override_len) {
1220
    const struct dpp_curve_params *tmp_curve;
1221
1222
    wpa_printf(MSG_INFO,
1223
         "DPP: TESTING - override protocol key");
1224
    auth->own_protocol_key = dpp_set_keypair(
1225
      &tmp_curve, dpp_protocol_key_override,
1226
      dpp_protocol_key_override_len);
1227
  } else {
1228
    auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1229
  }
1230
#else /* CONFIG_TESTING_OPTIONS */
1231
0
  auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1232
0
#endif /* CONFIG_TESTING_OPTIONS */
1233
0
  if (!auth->own_protocol_key)
1234
0
    goto fail;
1235
1236
0
  pi = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
1237
0
  if (!pi)
1238
0
    goto fail;
1239
1240
  /* ECDH: M = pI * BR */
1241
0
  if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey,
1242
0
         auth->Mx, &secret_len) < 0)
1243
0
    goto fail;
1244
0
  auth->secret_len = secret_len;
1245
1246
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
1247
0
      auth->Mx, auth->secret_len);
1248
0
  auth->Mx_len = auth->secret_len;
1249
1250
0
  if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
1251
0
        auth->curve->hash_len) < 0)
1252
0
    goto fail;
1253
1254
0
  r_pubkey_hash = auth->peer_bi->pubkey_hash;
1255
0
  i_pubkey_hash = auth->own_bi->pubkey_hash;
1256
1257
#ifdef CONFIG_TESTING_OPTIONS
1258
  if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1259
    wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
1260
    r_pubkey_hash = NULL;
1261
  } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1262
    wpa_printf(MSG_INFO,
1263
         "DPP: TESTING - invalid R-Bootstrap Key Hash");
1264
    os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
1265
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1266
    r_pubkey_hash = test_hash;
1267
  } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1268
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
1269
    i_pubkey_hash = NULL;
1270
  } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1271
    wpa_printf(MSG_INFO,
1272
         "DPP: TESTING - invalid I-Bootstrap Key Hash");
1273
    os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
1274
    test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1275
    i_pubkey_hash = test_hash;
1276
  } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) {
1277
    wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key");
1278
    wpabuf_free(pi);
1279
    pi = NULL;
1280
  } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) {
1281
    wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key");
1282
    wpabuf_free(pi);
1283
    pi = wpabuf_alloc(2 * auth->curve->prime_len);
1284
    if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0)
1285
      goto fail;
1286
  }
1287
#endif /* CONFIG_TESTING_OPTIONS */
1288
1289
0
  if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq)
1290
0
    neg_freq = 0;
1291
0
  auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash,
1292
0
             i_pubkey_hash, neg_freq);
1293
0
  if (!auth->req_msg)
1294
0
    goto fail;
1295
1296
0
out:
1297
0
  wpabuf_free(pi);
1298
0
  return auth;
1299
0
fail:
1300
0
  dpp_auth_deinit(auth);
1301
0
  auth = NULL;
1302
0
  goto out;
1303
0
}
1304
static void
1305
dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
1306
      const u8 *attr_start, size_t attr_len,
1307
      const u8 *wrapped_data, u16 wrapped_data_len,
1308
      enum dpp_status_error status)
1309
0
{
1310
0
  const u8 *addr[2];
1311
0
  size_t len[2];
1312
0
  u8 *unwrapped = NULL;
1313
0
  size_t unwrapped_len = 0;
1314
0
  const u8 *i_nonce, *r_capab;
1315
0
  u16 i_nonce_len, r_capab_len;
1316
1317
0
  if (status == DPP_STATUS_NOT_COMPATIBLE) {
1318
0
    wpa_printf(MSG_DEBUG,
1319
0
         "DPP: Responder reported incompatible roles");
1320
0
  } else if (status == DPP_STATUS_RESPONSE_PENDING) {
1321
0
    wpa_printf(MSG_DEBUG,
1322
0
         "DPP: Responder reported more time needed");
1323
0
  } else {
1324
0
    wpa_printf(MSG_DEBUG,
1325
0
         "DPP: Responder reported failure (status %d)",
1326
0
         status);
1327
0
    dpp_auth_fail(auth, "Responder reported failure");
1328
0
    return;
1329
0
  }
1330
1331
0
  addr[0] = hdr;
1332
0
  len[0] = DPP_HDR_LEN;
1333
0
  addr[1] = attr_start;
1334
0
  len[1] = attr_len;
1335
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1336
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1337
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1338
0
        wrapped_data, wrapped_data_len);
1339
0
  unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1340
0
  unwrapped = os_malloc(unwrapped_len);
1341
0
  if (!unwrapped)
1342
0
    goto fail;
1343
0
  if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
1344
0
          wrapped_data, wrapped_data_len,
1345
0
          2, addr, len, unwrapped) < 0) {
1346
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
1347
0
    goto fail;
1348
0
  }
1349
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1350
0
        unwrapped, unwrapped_len);
1351
1352
0
  if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1353
0
    dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
1354
0
    goto fail;
1355
0
  }
1356
1357
0
  i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
1358
0
             &i_nonce_len);
1359
0
  if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
1360
0
    dpp_auth_fail(auth, "Missing or invalid I-nonce");
1361
0
    goto fail;
1362
0
  }
1363
0
  wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
1364
0
  if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
1365
0
    dpp_auth_fail(auth, "I-nonce mismatch");
1366
0
    goto fail;
1367
0
  }
1368
1369
0
  r_capab = dpp_get_attr(unwrapped, unwrapped_len,
1370
0
             DPP_ATTR_R_CAPABILITIES,
1371
0
             &r_capab_len);
1372
0
  if (!r_capab || r_capab_len < 1) {
1373
0
    dpp_auth_fail(auth, "Missing or invalid R-capabilities");
1374
0
    goto fail;
1375
0
  }
1376
0
  auth->r_capab = r_capab[0];
1377
0
  wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
1378
0
  if (status == DPP_STATUS_NOT_COMPATIBLE) {
1379
0
    wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
1380
0
      "r-capab=0x%02x", auth->r_capab);
1381
0
  } else if (status == DPP_STATUS_RESPONSE_PENDING) {
1382
0
    u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
1383
1384
0
    if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
1385
0
        (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
1386
0
      wpa_msg(auth->msg_ctx, MSG_INFO,
1387
0
        DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x",
1388
0
        role);
1389
0
    } else {
1390
0
      wpa_printf(MSG_DEBUG,
1391
0
           "DPP: Continue waiting for full DPP Authentication Response");
1392
0
      wpa_msg(auth->msg_ctx, MSG_INFO,
1393
0
        DPP_EVENT_RESPONSE_PENDING "%s",
1394
0
        auth->tmp_own_bi ? auth->tmp_own_bi->uri : "");
1395
0
    }
1396
0
  }
1397
0
fail:
1398
0
  bin_clear_free(unwrapped, unwrapped_len);
1399
0
}
1400
1401
1402
struct wpabuf *
1403
dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
1404
     const u8 *attr_start, size_t attr_len)
1405
0
{
1406
0
  struct crypto_ec_key *pr;
1407
0
  size_t secret_len;
1408
0
  const u8 *addr[2];
1409
0
  size_t len[2];
1410
0
  u8 *unwrapped = NULL, *unwrapped2 = NULL;
1411
0
  size_t unwrapped_len = 0, unwrapped2_len = 0;
1412
0
  const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
1413
0
    *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
1414
0
  u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
1415
0
    r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
1416
0
    wrapped2_len, r_auth_len;
1417
0
  u8 r_auth2[DPP_MAX_HASH_LEN];
1418
0
  u8 role;
1419
0
#ifdef CONFIG_DPP2
1420
0
  const u8 *version;
1421
0
  u16 version_len;
1422
0
#endif /* CONFIG_DPP2 */
1423
1424
#ifdef CONFIG_TESTING_OPTIONS
1425
  if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) {
1426
    wpa_printf(MSG_INFO,
1427
         "DPP: TESTING - stop at Authentication Response");
1428
    return NULL;
1429
  }
1430
#endif /* CONFIG_TESTING_OPTIONS */
1431
1432
0
  if (!auth->initiator || !auth->peer_bi || auth->reconfig) {
1433
0
    dpp_auth_fail(auth, "Unexpected Authentication Response");
1434
0
    return NULL;
1435
0
  }
1436
1437
0
  auth->waiting_auth_resp = 0;
1438
1439
0
  wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
1440
0
            &wrapped_data_len);
1441
0
  if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
1442
0
    dpp_auth_fail(auth,
1443
0
            "Missing or invalid required Wrapped Data attribute");
1444
0
    return NULL;
1445
0
  }
1446
0
  wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
1447
0
        wrapped_data, wrapped_data_len);
1448
1449
0
  attr_len = wrapped_data - 4 - attr_start;
1450
1451
0
  r_bootstrap = dpp_get_attr(attr_start, attr_len,
1452
0
           DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1453
0
           &r_bootstrap_len);
1454
0
  if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1455
0
    dpp_auth_fail(auth,
1456
0
            "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1457
0
    return NULL;
1458
0
  }
1459
0
  wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
1460
0
        r_bootstrap, r_bootstrap_len);
1461
0
  if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
1462
0
          SHA256_MAC_LEN) != 0) {
1463
0
    dpp_auth_fail(auth,
1464
0
            "Unexpected Responder Bootstrapping Key Hash value");
1465
0
    wpa_hexdump(MSG_DEBUG,
1466
0
          "DPP: Expected Responder Bootstrapping Key Hash",
1467
0
          auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
1468
0
    return NULL;
1469
0
  }
1470
1471
0
  i_bootstrap = dpp_get_attr(attr_start, attr_len,
1472
0
           DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1473
0
           &i_bootstrap_len);
1474
0
  if (i_bootstrap) {
1475
0
    if (i_bootstrap_len != SHA256_MAC_LEN) {
1476
0
      dpp_auth_fail(auth,
1477
0
              "Invalid Initiator Bootstrapping Key Hash attribute");
1478
0
      return NULL;
1479
0
    }
1480
0
    wpa_hexdump(MSG_MSGDUMP,
1481
0
          "DPP: Initiator Bootstrapping Key Hash",
1482
0
          i_bootstrap, i_bootstrap_len);
1483
0
    if (!auth->own_bi ||
1484
0
        os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
1485
0
            SHA256_MAC_LEN) != 0) {
1486
0
      dpp_auth_fail(auth,
1487
0
              "Initiator Bootstrapping Key Hash attribute did not match");
1488
0
      return NULL;
1489
0
    }
1490
0
  } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) {
1491
    /* PKEX bootstrapping mandates use of mutual authentication */
1492
0
    dpp_auth_fail(auth,
1493
0
            "Missing Initiator Bootstrapping Key Hash attribute");
1494
0
    return NULL;
1495
0
  } else if (auth->own_bi &&
1496
0
       auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI &&
1497
0
       auth->own_bi->nfc_negotiated) {
1498
    /* NFC negotiated connection handover bootstrapping mandates
1499
     * use of mutual authentication */
1500
0
    dpp_auth_fail(auth,
1501
0
            "Missing Initiator Bootstrapping Key Hash attribute");
1502
0
    return NULL;
1503
0
  }
1504
1505
0
  auth->peer_version = 1; /* default to the first version */
1506
0
#ifdef CONFIG_DPP2
1507
0
  version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
1508
0
             &version_len);
1509
0
  if (version && DPP_VERSION > 1) {
1510
0
    if (version_len < 1 || version[0] == 0) {
1511
0
      dpp_auth_fail(auth,
1512
0
              "Invalid Protocol Version attribute");
1513
0
      return NULL;
1514
0
    }
1515
0
    auth->peer_version = version[0];
1516
0
    wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
1517
0
         auth->peer_version);
1518
0
  }
1519
0
#endif /* CONFIG_DPP2 */
1520
1521
0
  status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
1522
0
            &status_len);
1523
0
  if (!status || status_len < 1) {
1524
0
    dpp_auth_fail(auth,
1525
0
            "Missing or invalid required DPP Status attribute");
1526
0
    return NULL;
1527
0
  }
1528
0
  wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
1529
0
  auth->auth_resp_status = status[0];
1530
0
  if (status[0] != DPP_STATUS_OK) {
1531
0
    dpp_auth_resp_rx_status(auth, hdr, attr_start,
1532
0
          attr_len, wrapped_data,
1533
0
          wrapped_data_len, status[0]);
1534
0
    return NULL;
1535
0
  }
1536
1537
0
  if (!i_bootstrap && auth->own_bi) {
1538
0
    wpa_printf(MSG_DEBUG,
1539
0
         "DPP: Responder decided not to use mutual authentication");
1540
0
    auth->own_bi = NULL;
1541
0
  }
1542
1543
0
  wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d",
1544
0
    auth->own_bi != NULL);
1545
1546
0
  r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
1547
0
             &r_proto_len);
1548
0
  if (!r_proto) {
1549
0
    dpp_auth_fail(auth,
1550
0
            "Missing required Responder Protocol Key attribute");
1551
0
    return NULL;
1552
0
  }
1553
0
  wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
1554
0
        r_proto, r_proto_len);
1555
1556
  /* N = pI * PR */
1557
0
  pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
1558
0
  if (!pr) {
1559
0
    dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1560
0
    return NULL;
1561
0
  }
1562
0
  dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
1563
1564
0
  if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
1565
0
    dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
1566
0
    goto fail;
1567
0
  }
1568
0
  crypto_ec_key_deinit(auth->peer_protocol_key);
1569
0
  auth->peer_protocol_key = pr;
1570
0
  pr = NULL;
1571
1572
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
1573
0
      auth->Nx, auth->secret_len);
1574
0
  auth->Nx_len = auth->secret_len;
1575
1576
0
  if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
1577
0
        auth->curve->hash_len) < 0)
1578
0
    goto fail;
1579
1580
0
  addr[0] = hdr;
1581
0
  len[0] = DPP_HDR_LEN;
1582
0
  addr[1] = attr_start;
1583
0
  len[1] = attr_len;
1584
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1585
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1586
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1587
0
        wrapped_data, wrapped_data_len);
1588
0
  unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1589
0
  unwrapped = os_malloc(unwrapped_len);
1590
0
  if (!unwrapped)
1591
0
    goto fail;
1592
0
  if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
1593
0
          wrapped_data, wrapped_data_len,
1594
0
          2, addr, len, unwrapped) < 0) {
1595
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
1596
0
    goto fail;
1597
0
  }
1598
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1599
0
        unwrapped, unwrapped_len);
1600
1601
0
  if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1602
0
    dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
1603
0
    goto fail;
1604
0
  }
1605
1606
0
  r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
1607
0
             &r_nonce_len);
1608
0
  if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
1609
0
    dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
1610
0
    goto fail;
1611
0
  }
1612
0
  wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
1613
0
  os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
1614
1615
0
  i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
1616
0
             &i_nonce_len);
1617
0
  if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
1618
0
    dpp_auth_fail(auth, "Missing or invalid I-nonce");
1619
0
    goto fail;
1620
0
  }
1621
0
  wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
1622
0
  if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
1623
0
    dpp_auth_fail(auth, "I-nonce mismatch");
1624
0
    goto fail;
1625
0
  }
1626
1627
0
  if (auth->own_bi) {
1628
    /* Mutual authentication */
1629
0
    if (dpp_auth_derive_l_initiator(auth) < 0)
1630
0
      goto fail;
1631
0
  }
1632
1633
0
  r_capab = dpp_get_attr(unwrapped, unwrapped_len,
1634
0
             DPP_ATTR_R_CAPABILITIES,
1635
0
             &r_capab_len);
1636
0
  if (!r_capab || r_capab_len < 1) {
1637
0
    dpp_auth_fail(auth, "Missing or invalid R-capabilities");
1638
0
    goto fail;
1639
0
  }
1640
0
  auth->r_capab = r_capab[0];
1641
0
  wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
1642
0
  role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
1643
0
  if ((auth->allowed_roles ==
1644
0
       (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) &&
1645
0
      (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) {
1646
    /* Peer selected its role, so move from "either role" to the
1647
     * role that is compatible with peer's selection. */
1648
0
    auth->configurator = role == DPP_CAPAB_ENROLLEE;
1649
0
    wpa_printf(MSG_DEBUG, "DPP: Acting as %s",
1650
0
         auth->configurator ? "Configurator" : "Enrollee");
1651
0
  } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
1652
0
       (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
1653
0
    wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
1654
0
    wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1655
0
      "Unexpected role in R-capabilities 0x%02x",
1656
0
      role);
1657
0
    if (role != DPP_CAPAB_ENROLLEE &&
1658
0
        role != DPP_CAPAB_CONFIGURATOR)
1659
0
      goto fail;
1660
0
    bin_clear_free(unwrapped, unwrapped_len);
1661
0
    auth->remove_on_tx_status = 1;
1662
0
    return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE);
1663
0
  }
1664
1665
0
  wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
1666
0
        DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
1667
0
  if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
1668
0
    dpp_auth_fail(auth,
1669
0
            "Missing or invalid Secondary Wrapped Data");
1670
0
    goto fail;
1671
0
  }
1672
1673
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1674
0
        wrapped2, wrapped2_len);
1675
1676
0
  if (dpp_derive_bk_ke(auth) < 0)
1677
0
    goto fail;
1678
1679
0
  unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
1680
0
  unwrapped2 = os_malloc(unwrapped2_len);
1681
0
  if (!unwrapped2)
1682
0
    goto fail;
1683
0
  if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
1684
0
          wrapped2, wrapped2_len,
1685
0
          0, NULL, NULL, unwrapped2) < 0) {
1686
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
1687
0
    goto fail;
1688
0
  }
1689
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1690
0
        unwrapped2, unwrapped2_len);
1691
1692
0
  if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
1693
0
    dpp_auth_fail(auth,
1694
0
            "Invalid attribute in secondary unwrapped data");
1695
0
    goto fail;
1696
0
  }
1697
1698
0
  r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
1699
0
             &r_auth_len);
1700
0
  if (!r_auth || r_auth_len != auth->curve->hash_len) {
1701
0
    dpp_auth_fail(auth,
1702
0
            "Missing or invalid Responder Authenticating Tag");
1703
0
    goto fail;
1704
0
  }
1705
0
  wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
1706
0
        r_auth, r_auth_len);
1707
  /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1708
0
  if (dpp_gen_r_auth(auth, r_auth2) < 0)
1709
0
    goto fail;
1710
0
  wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
1711
0
        r_auth2, r_auth_len);
1712
0
  if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
1713
0
    dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag");
1714
0
    bin_clear_free(unwrapped, unwrapped_len);
1715
0
    bin_clear_free(unwrapped2, unwrapped2_len);
1716
0
    auth->remove_on_tx_status = 1;
1717
0
    return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE);
1718
0
  }
1719
1720
0
  bin_clear_free(unwrapped, unwrapped_len);
1721
0
  bin_clear_free(unwrapped2, unwrapped2_len);
1722
1723
#ifdef CONFIG_TESTING_OPTIONS
1724
  if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) {
1725
    wpa_printf(MSG_INFO,
1726
         "DPP: TESTING - Authentication Response in place of Confirm");
1727
    if (dpp_auth_build_resp_ok(auth) < 0)
1728
      return NULL;
1729
    return wpabuf_dup(auth->resp_msg);
1730
  }
1731
#endif /* CONFIG_TESTING_OPTIONS */
1732
1733
0
  return dpp_auth_build_conf(auth, DPP_STATUS_OK);
1734
1735
0
fail:
1736
0
  bin_clear_free(unwrapped, unwrapped_len);
1737
0
  bin_clear_free(unwrapped2, unwrapped2_len);
1738
0
  crypto_ec_key_deinit(pr);
1739
0
  return NULL;
1740
0
}
1741
1742
1743
static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth,
1744
            const u8 *hdr,
1745
            const u8 *attr_start, size_t attr_len,
1746
            const u8 *wrapped_data,
1747
            u16 wrapped_data_len,
1748
            enum dpp_status_error status)
1749
0
{
1750
0
  const u8 *addr[2];
1751
0
  size_t len[2];
1752
0
  u8 *unwrapped = NULL;
1753
0
  size_t unwrapped_len = 0;
1754
0
  const u8 *r_nonce;
1755
0
  u16 r_nonce_len;
1756
1757
  /* Authentication Confirm failure cases are expected to include
1758
   * {R-nonce}k2 in the Wrapped Data attribute. */
1759
1760
0
  addr[0] = hdr;
1761
0
  len[0] = DPP_HDR_LEN;
1762
0
  addr[1] = attr_start;
1763
0
  len[1] = attr_len;
1764
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1765
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1766
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1767
0
        wrapped_data, wrapped_data_len);
1768
0
  unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1769
0
  unwrapped = os_malloc(unwrapped_len);
1770
0
  if (!unwrapped) {
1771
0
    dpp_auth_fail(auth, "Authentication failed");
1772
0
    goto fail;
1773
0
  }
1774
0
  if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
1775
0
          wrapped_data, wrapped_data_len,
1776
0
          2, addr, len, unwrapped) < 0) {
1777
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
1778
0
    goto fail;
1779
0
  }
1780
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1781
0
        unwrapped, unwrapped_len);
1782
1783
0
  if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1784
0
    dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
1785
0
    goto fail;
1786
0
  }
1787
1788
0
  r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
1789
0
             &r_nonce_len);
1790
0
  if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
1791
0
    dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
1792
0
    goto fail;
1793
0
  }
1794
0
  if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
1795
0
    wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce",
1796
0
          r_nonce, r_nonce_len);
1797
0
    wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce",
1798
0
          auth->r_nonce, r_nonce_len);
1799
0
    dpp_auth_fail(auth, "R-nonce mismatch");
1800
0
    goto fail;
1801
0
  }
1802
1803
0
  if (status == DPP_STATUS_NOT_COMPATIBLE)
1804
0
    dpp_auth_fail(auth, "Peer reported incompatible R-capab role");
1805
0
  else if (status == DPP_STATUS_AUTH_FAILURE)
1806
0
    dpp_auth_fail(auth, "Peer reported authentication failure)");
1807
1808
0
fail:
1809
0
  bin_clear_free(unwrapped, unwrapped_len);
1810
0
  return -1;
1811
0
}
1812
1813
1814
int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
1815
         const u8 *attr_start, size_t attr_len)
1816
0
{
1817
0
  const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
1818
0
  u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
1819
0
    i_auth_len;
1820
0
  const u8 *addr[2];
1821
0
  size_t len[2];
1822
0
  u8 *unwrapped = NULL;
1823
0
  size_t unwrapped_len = 0;
1824
0
  u8 i_auth2[DPP_MAX_HASH_LEN];
1825
1826
#ifdef CONFIG_TESTING_OPTIONS
1827
  if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1828
    wpa_printf(MSG_INFO,
1829
         "DPP: TESTING - stop at Authentication Confirm");
1830
    return -1;
1831
  }
1832
#endif /* CONFIG_TESTING_OPTIONS */
1833
1834
0
  if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf ||
1835
0
      auth->reconfig) {
1836
0
    wpa_printf(MSG_DEBUG,
1837
0
         "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d",
1838
0
         auth->initiator, !!auth->own_bi,
1839
0
         auth->waiting_auth_conf);
1840
0
    dpp_auth_fail(auth, "Unexpected Authentication Confirm");
1841
0
    return -1;
1842
0
  }
1843
1844
0
  auth->waiting_auth_conf = 0;
1845
1846
0
  wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
1847
0
            &wrapped_data_len);
1848
0
  if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
1849
0
    dpp_auth_fail(auth,
1850
0
            "Missing or invalid required Wrapped Data attribute");
1851
0
    return -1;
1852
0
  }
1853
0
  wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
1854
0
        wrapped_data, wrapped_data_len);
1855
1856
0
  attr_len = wrapped_data - 4 - attr_start;
1857
1858
0
  r_bootstrap = dpp_get_attr(attr_start, attr_len,
1859
0
           DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1860
0
           &r_bootstrap_len);
1861
0
  if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1862
0
    dpp_auth_fail(auth,
1863
0
            "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1864
0
    return -1;
1865
0
  }
1866
0
  wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
1867
0
        r_bootstrap, r_bootstrap_len);
1868
0
  if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
1869
0
          SHA256_MAC_LEN) != 0) {
1870
0
    wpa_hexdump(MSG_DEBUG,
1871
0
          "DPP: Expected Responder Bootstrapping Key Hash",
1872
0
          auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
1873
0
    dpp_auth_fail(auth,
1874
0
            "Responder Bootstrapping Key Hash mismatch");
1875
0
    return -1;
1876
0
  }
1877
1878
0
  i_bootstrap = dpp_get_attr(attr_start, attr_len,
1879
0
           DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1880
0
           &i_bootstrap_len);
1881
0
  if (i_bootstrap) {
1882
0
    if (i_bootstrap_len != SHA256_MAC_LEN) {
1883
0
      dpp_auth_fail(auth,
1884
0
              "Invalid Initiator Bootstrapping Key Hash attribute");
1885
0
      return -1;
1886
0
    }
1887
0
    wpa_hexdump(MSG_MSGDUMP,
1888
0
          "DPP: Initiator Bootstrapping Key Hash",
1889
0
          i_bootstrap, i_bootstrap_len);
1890
0
    if (!auth->peer_bi ||
1891
0
        os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
1892
0
            SHA256_MAC_LEN) != 0) {
1893
0
      dpp_auth_fail(auth,
1894
0
              "Initiator Bootstrapping Key Hash mismatch");
1895
0
      return -1;
1896
0
    }
1897
0
  } else if (auth->peer_bi) {
1898
    /* Mutual authentication and peer did not include its
1899
     * Bootstrapping Key Hash attribute. */
1900
0
    dpp_auth_fail(auth,
1901
0
            "Missing Initiator Bootstrapping Key Hash attribute");
1902
0
    return -1;
1903
0
  }
1904
1905
0
  status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
1906
0
            &status_len);
1907
0
  if (!status || status_len < 1) {
1908
0
    dpp_auth_fail(auth,
1909
0
            "Missing or invalid required DPP Status attribute");
1910
0
    return -1;
1911
0
  }
1912
0
  wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
1913
0
  if (status[0] == DPP_STATUS_NOT_COMPATIBLE ||
1914
0
      status[0] == DPP_STATUS_AUTH_FAILURE)
1915
0
    return dpp_auth_conf_rx_failure(auth, hdr, attr_start,
1916
0
            attr_len, wrapped_data,
1917
0
            wrapped_data_len, status[0]);
1918
1919
0
  if (status[0] != DPP_STATUS_OK) {
1920
0
    dpp_auth_fail(auth, "Authentication failed");
1921
0
    return -1;
1922
0
  }
1923
1924
0
  addr[0] = hdr;
1925
0
  len[0] = DPP_HDR_LEN;
1926
0
  addr[1] = attr_start;
1927
0
  len[1] = attr_len;
1928
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1929
0
  wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1930
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1931
0
        wrapped_data, wrapped_data_len);
1932
0
  unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1933
0
  unwrapped = os_malloc(unwrapped_len);
1934
0
  if (!unwrapped)
1935
0
    return -1;
1936
0
  if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
1937
0
          wrapped_data, wrapped_data_len,
1938
0
          2, addr, len, unwrapped) < 0) {
1939
0
    dpp_auth_fail(auth, "AES-SIV decryption failed");
1940
0
    goto fail;
1941
0
  }
1942
0
  wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1943
0
        unwrapped, unwrapped_len);
1944
1945
0
  if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1946
0
    dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
1947
0
    goto fail;
1948
0
  }
1949
1950
0
  i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
1951
0
            &i_auth_len);
1952
0
  if (!i_auth || i_auth_len != auth->curve->hash_len) {
1953
0
    dpp_auth_fail(auth,
1954
0
            "Missing or invalid Initiator Authenticating Tag");
1955
0
    goto fail;
1956
0
  }
1957
0
  wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
1958
0
        i_auth, i_auth_len);
1959
  /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
1960
0
  if (dpp_gen_i_auth(auth, i_auth2) < 0)
1961
0
    goto fail;
1962
0
  wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
1963
0
        i_auth2, i_auth_len);
1964
0
  if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
1965
0
    dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag");
1966
0
    goto fail;
1967
0
  }
1968
1969
0
  bin_clear_free(unwrapped, unwrapped_len);
1970
0
  dpp_auth_success(auth);
1971
0
  return 0;
1972
0
fail:
1973
0
  bin_clear_free(unwrapped, unwrapped_len);
1974
0
  return -1;
1975
0
}