Coverage Report

Created: 2025-04-24 06:18

/src/hostap/src/common/dpp_crypto.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * DPP crypto functionality
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 "utils/base64.h"
14
#include "utils/json.h"
15
#include "common/ieee802_11_defs.h"
16
#include "crypto/crypto.h"
17
#include "crypto/random.h"
18
#include "crypto/sha384.h"
19
#include "crypto/sha512.h"
20
#include "tls/asn1.h"
21
#include "dpp.h"
22
#include "dpp_i.h"
23
24
25
static const struct dpp_curve_params dpp_curves[] = {
26
  /* The mandatory to support and the default NIST P-256 curve needs to
27
   * be the first entry on this list. */
28
  { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
29
  { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
30
  { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
31
  { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
32
  { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
33
  { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
34
  { NULL, 0, 0, 0, 0, NULL, 0, NULL }
35
};
36
37
38
const struct dpp_curve_params * dpp_get_curve_name(const char *name)
39
0
{
40
0
  int i;
41
42
0
  if (!name)
43
0
    return &dpp_curves[0];
44
45
0
  for (i = 0; dpp_curves[i].name; i++) {
46
0
    if (os_strcmp(name, dpp_curves[i].name) == 0 ||
47
0
        (dpp_curves[i].jwk_crv &&
48
0
         os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
49
0
      return &dpp_curves[i];
50
0
  }
51
0
  return NULL;
52
0
}
53
54
55
const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name)
56
0
{
57
0
  int i;
58
59
0
  for (i = 0; dpp_curves[i].name; i++) {
60
0
    if (dpp_curves[i].jwk_crv &&
61
0
        os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
62
0
      return &dpp_curves[i];
63
0
  }
64
0
  return NULL;
65
0
}
66
67
68
const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
69
51
{
70
51
  int i;
71
72
99
  for (i = 0; dpp_curves[i].name; i++) {
73
91
    if (dpp_curves[i].ike_group == group)
74
43
      return &dpp_curves[i];
75
91
  }
76
8
  return NULL;
77
51
}
78
79
80
void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
81
0
{
82
0
  struct wpabuf *der = NULL;
83
84
0
  crypto_ec_key_debug_print(key, title);
85
86
0
  der = crypto_ec_key_get_ecprivate_key(key, true);
87
0
  if (der) {
88
0
    wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
89
0
  } else {
90
0
    der = crypto_ec_key_get_subject_public_key(key);
91
0
    if (der)
92
0
      wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
93
0
  }
94
95
0
  wpabuf_clear_free(der);
96
0
}
97
98
99
static int dpp_hash_vector(const struct dpp_curve_params *curve,
100
         size_t num_elem, const u8 *addr[], const size_t *len,
101
         u8 *mac)
102
0
{
103
0
  if (curve->hash_len == 32)
104
0
    return sha256_vector(num_elem, addr, len, mac);
105
0
  if (curve->hash_len == 48)
106
0
    return sha384_vector(num_elem, addr, len, mac);
107
0
  if (curve->hash_len == 64)
108
0
    return sha512_vector(num_elem, addr, len, mac);
109
0
  return -1;
110
0
}
111
112
113
int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
114
        const char *label, u8 *out, size_t outlen)
115
0
{
116
0
  if (hash_len == 32)
117
0
    return hmac_sha256_kdf(secret, secret_len, NULL,
118
0
               (const u8 *) label, os_strlen(label),
119
0
               out, outlen);
120
0
  if (hash_len == 48)
121
0
    return hmac_sha384_kdf(secret, secret_len, NULL,
122
0
               (const u8 *) label, os_strlen(label),
123
0
               out, outlen);
124
0
  if (hash_len == 64)
125
0
    return hmac_sha512_kdf(secret, secret_len, NULL,
126
0
               (const u8 *) label, os_strlen(label),
127
0
               out, outlen);
128
0
  return -1;
129
0
}
130
131
132
int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
133
        size_t num_elem, const u8 *addr[], const size_t *len,
134
        u8 *mac)
135
0
{
136
0
  if (hash_len == 32)
137
0
    return hmac_sha256_vector(key, key_len, num_elem, addr, len,
138
0
            mac);
139
0
  if (hash_len == 48)
140
0
    return hmac_sha384_vector(key, key_len, num_elem, addr, len,
141
0
            mac);
142
0
  if (hash_len == 64)
143
0
    return hmac_sha512_vector(key, key_len, num_elem, addr, len,
144
0
            mac);
145
0
  return -1;
146
0
}
147
148
149
static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
150
        const u8 *data, size_t data_len, u8 *mac)
151
0
{
152
0
  if (hash_len == 32)
153
0
    return hmac_sha256(key, key_len, data, data_len, mac);
154
0
  if (hash_len == 48)
155
0
    return hmac_sha384(key, key_len, data, data_len, mac);
156
0
  if (hash_len == 64)
157
0
    return hmac_sha512(key, key_len, data, data_len, mac);
158
0
  return -1;
159
0
}
160
161
162
#ifdef CONFIG_DPP2
163
164
static int dpp_pbkdf2_f(size_t hash_len,
165
      const u8 *password, size_t password_len,
166
      const u8 *salt, size_t salt_len,
167
      unsigned int iterations, unsigned int count, u8 *digest)
168
0
{
169
0
  unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN];
170
0
  unsigned int i;
171
0
  size_t j;
172
0
  u8 count_buf[4];
173
0
  const u8 *addr[2];
174
0
  size_t len[2];
175
176
0
  addr[0] = salt;
177
0
  len[0] = salt_len;
178
0
  addr[1] = count_buf;
179
0
  len[1] = 4;
180
181
  /* F(P, S, c, i) = U1 xor U2 xor ... Uc
182
   * U1 = PRF(P, S || i)
183
   * U2 = PRF(P, U1)
184
   * Uc = PRF(P, Uc-1)
185
   */
186
187
0
  WPA_PUT_BE32(count_buf, count);
188
0
  if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len,
189
0
          tmp))
190
0
    return -1;
191
0
  os_memcpy(digest, tmp, hash_len);
192
193
0
  for (i = 1; i < iterations; i++) {
194
0
    if (dpp_hmac(hash_len, password, password_len, tmp, hash_len,
195
0
           tmp2))
196
0
      return -1;
197
0
    os_memcpy(tmp, tmp2, hash_len);
198
0
    for (j = 0; j < hash_len; j++)
199
0
      digest[j] ^= tmp2[j];
200
0
  }
201
202
0
  return 0;
203
0
}
204
205
206
int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
207
         const u8 *salt, size_t salt_len, unsigned int iterations,
208
         u8 *buf, size_t buflen)
209
0
{
210
0
  unsigned int count = 0;
211
0
  unsigned char *pos = buf;
212
0
  size_t left = buflen, plen;
213
0
  unsigned char digest[DPP_MAX_HASH_LEN];
214
215
0
  while (left > 0) {
216
0
    count++;
217
0
    if (dpp_pbkdf2_f(hash_len, password, password_len,
218
0
         salt, salt_len, iterations, count, digest))
219
0
      return -1;
220
0
    plen = left > hash_len ? hash_len : left;
221
0
    os_memcpy(pos, digest, plen);
222
0
    pos += plen;
223
0
    left -= plen;
224
0
  }
225
226
0
  return 0;
227
0
}
228
229
#endif /* CONFIG_DPP2 */
230
231
232
struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
233
              const u8 *buf, size_t len)
234
0
{
235
0
  int ike_group = crypto_ec_key_group(group_key);
236
237
0
  if (len & 1)
238
0
    return NULL;
239
240
0
  if (ike_group < 0) {
241
0
    wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
242
0
    return NULL;
243
0
  }
244
245
0
  return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
246
0
}
247
248
249
int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash)
250
0
{
251
0
  struct wpabuf *uncomp;
252
0
  const u8 *addr[1];
253
0
  size_t len[1];
254
0
  int res;
255
256
0
  if (!key)
257
0
    return -1;
258
259
0
  uncomp = crypto_ec_key_get_pubkey_point(key, 1);
260
0
  if (!uncomp)
261
0
    return -1;
262
0
  addr[0] = wpabuf_head(uncomp);
263
0
  len[0] = wpabuf_len(uncomp);
264
0
  res = sha256_vector(1, addr, len, hash);
265
0
  wpabuf_free(uncomp);
266
0
  return res;
267
0
}
268
269
270
struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
271
0
{
272
0
  struct crypto_ec_key *key;
273
274
0
  wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
275
276
0
  key = crypto_ec_key_gen(curve->ike_group);
277
0
  if (key && wpa_debug_show_keys)
278
0
      dpp_debug_print_key("Own generated key", key);
279
280
0
  return key;
281
0
}
282
283
284
struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
285
               const u8 *privkey, size_t privkey_len)
286
0
{
287
0
  struct crypto_ec_key *key;
288
0
  int group;
289
290
0
  key = crypto_ec_key_parse_priv(privkey, privkey_len);
291
0
  if (!key) {
292
0
    wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
293
0
    return NULL;
294
0
  }
295
296
0
  group = crypto_ec_key_group(key);
297
0
  if (group < 0) {
298
0
    crypto_ec_key_deinit(key);
299
0
    return NULL;
300
0
  }
301
302
0
  *curve = dpp_get_curve_ike_group(group);
303
0
  if (!*curve) {
304
0
    wpa_printf(MSG_INFO,
305
0
         "DPP: Unsupported curve (group=%d) in pre-assigned key",
306
0
         group);
307
0
    crypto_ec_key_deinit(key);
308
0
    return NULL;
309
0
  }
310
311
0
  return key;
312
0
}
313
314
315
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
316
0
{
317
0
  struct wpabuf *der;
318
0
  int res;
319
320
0
  der = crypto_ec_key_get_subject_public_key(bi->pubkey);
321
0
  if (!der)
322
0
    return -1;
323
0
  wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
324
0
      der);
325
0
  res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
326
0
  if (res < 0)
327
0
    wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
328
0
  wpabuf_free(der);
329
0
  return res;
330
0
}
331
332
333
int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
334
         const u8 *privkey, size_t privkey_len)
335
0
{
336
0
  char *base64 = NULL;
337
0
  char *pos, *end;
338
0
  size_t len;
339
0
  struct wpabuf *der = NULL;
340
341
0
  bi->curve = dpp_get_curve_name(curve);
342
0
  if (!bi->curve) {
343
0
    wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
344
0
    return -1;
345
0
  }
346
347
0
  if (privkey)
348
0
    bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
349
0
  else
350
0
    bi->pubkey = dpp_gen_keypair(bi->curve);
351
0
  if (!bi->pubkey)
352
0
    goto fail;
353
0
  bi->own = 1;
354
355
0
  der = crypto_ec_key_get_subject_public_key(bi->pubkey);
356
0
  if (!der)
357
0
    goto fail;
358
0
  wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
359
0
      der);
360
361
0
  if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
362
0
    wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
363
0
    goto fail;
364
0
  }
365
366
0
  base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
367
0
  wpabuf_free(der);
368
0
  der = NULL;
369
0
  if (!base64)
370
0
    goto fail;
371
0
  pos = base64;
372
0
  end = pos + len;
373
0
  for (;;) {
374
0
    pos = os_strchr(pos, '\n');
375
0
    if (!pos)
376
0
      break;
377
0
    os_memmove(pos, pos + 1, end - pos);
378
0
  }
379
0
  os_free(bi->pk);
380
0
  bi->pk = base64;
381
0
  return 0;
382
0
fail:
383
0
  os_free(base64);
384
0
  wpabuf_free(der);
385
0
  return -1;
386
0
}
387
388
389
int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len)
390
0
{
391
0
  u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
392
0
  const char *info = "first intermediate key";
393
0
  int res;
394
395
  /* k1 = HKDF(<>, "first intermediate key", M.x) */
396
397
  /* HKDF-Extract(<>, M.x) */
398
0
  os_memset(salt, 0, hash_len);
399
0
  if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
400
0
    return -1;
401
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
402
0
      prk, hash_len);
403
404
  /* HKDF-Expand(PRK, info, L) */
405
0
  res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
406
0
  os_memset(prk, 0, hash_len);
407
0
  if (res < 0)
408
0
    return -1;
409
410
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
411
0
      k1, hash_len);
412
0
  return 0;
413
0
}
414
415
416
int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len)
417
0
{
418
0
  u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
419
0
  const char *info = "second intermediate key";
420
0
  int res;
421
422
  /* k2 = HKDF(<>, "second intermediate key", N.x) */
423
424
  /* HKDF-Extract(<>, N.x) */
425
0
  os_memset(salt, 0, hash_len);
426
0
  res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
427
0
  if (res < 0)
428
0
    return -1;
429
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
430
0
      prk, hash_len);
431
432
  /* HKDF-Expand(PRK, info, L) */
433
0
  res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
434
0
  os_memset(prk, 0, hash_len);
435
0
  if (res < 0)
436
0
    return -1;
437
438
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
439
0
      k2, hash_len);
440
0
  return 0;
441
0
}
442
443
444
int dpp_derive_bk_ke(struct dpp_authentication *auth)
445
0
{
446
0
  unsigned int hash_len = auth->curve->hash_len;
447
0
  size_t nonce_len = auth->curve->nonce_len;
448
0
  u8 nonces[2 * DPP_MAX_NONCE_LEN];
449
0
  const char *info_ke = "DPP Key";
450
0
  int res;
451
0
  const u8 *addr[3];
452
0
  size_t len[3];
453
0
  size_t num_elem = 0;
454
455
0
  if (!auth->Mx_len || !auth->Nx_len) {
456
0
    wpa_printf(MSG_DEBUG,
457
0
         "DPP: Mx/Nx not available - cannot derive ke");
458
0
    return -1;
459
0
  }
460
461
  /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
462
0
  os_memcpy(nonces, auth->i_nonce, nonce_len);
463
0
  os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
464
0
  addr[num_elem] = auth->Mx;
465
0
  len[num_elem] = auth->Mx_len;
466
0
  num_elem++;
467
0
  addr[num_elem] = auth->Nx;
468
0
  len[num_elem] = auth->Nx_len;
469
0
  num_elem++;
470
0
  if (auth->peer_bi && auth->own_bi) {
471
0
    if (!auth->Lx_len) {
472
0
      wpa_printf(MSG_DEBUG,
473
0
           "DPP: Lx not available - cannot derive ke");
474
0
      return -1;
475
0
    }
476
0
    addr[num_elem] = auth->Lx;
477
0
    len[num_elem] = auth->secret_len;
478
0
    num_elem++;
479
0
  }
480
0
  res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
481
0
            num_elem, addr, len, auth->bk);
482
0
  if (res < 0)
483
0
    return -1;
484
0
  wpa_hexdump_key(MSG_DEBUG,
485
0
      "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])",
486
0
      auth->bk, hash_len);
487
488
  /* ke = HKDF-Expand(bk, "DPP Key", length) */
489
0
  res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke,
490
0
            hash_len);
491
0
  if (res < 0)
492
0
    return -1;
493
494
0
  wpa_hexdump_key(MSG_DEBUG,
495
0
      "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)",
496
0
      auth->ke, hash_len);
497
498
0
  return 0;
499
0
}
500
501
502
int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
503
       u8 *secret, size_t *secret_len)
504
0
{
505
0
  struct crypto_ecdh *ecdh;
506
0
  struct wpabuf *peer_pub, *secret_buf = NULL;
507
0
  int ret = -1;
508
509
0
  *secret_len = 0;
510
511
0
  ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
512
0
  if (!ecdh) {
513
0
    wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
514
0
    return -1;
515
0
  }
516
517
0
  peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
518
0
  if (!peer_pub) {
519
0
    wpa_printf(MSG_ERROR,
520
0
         "DPP: crypto_ec_key_get_pubkey_point() failed");
521
0
    goto fail;
522
0
  }
523
524
0
  secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
525
0
               wpabuf_len(peer_pub));
526
0
  if (!secret_buf) {
527
0
    wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
528
0
    goto fail;
529
0
  }
530
531
0
  if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
532
0
    wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
533
0
    goto fail;
534
0
  }
535
536
0
  *secret_len = wpabuf_len(secret_buf);
537
0
  os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
538
0
  ret = 0;
539
540
0
fail:
541
0
  wpabuf_clear_free(secret_buf);
542
0
  wpabuf_free(peer_pub);
543
0
  crypto_ecdh_deinit(ecdh);
544
0
  return ret;
545
0
}
546
547
548
int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
549
           const u8 *data, size_t data_len)
550
168
{
551
168
  const u8 *addr[2];
552
168
  size_t len[2];
553
554
168
  addr[0] = data;
555
168
  len[0] = data_len;
556
168
  if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
557
0
    return -1;
558
168
  wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
559
168
        bi->pubkey_hash, SHA256_MAC_LEN);
560
561
168
  addr[0] = (const u8 *) "chirp";
562
168
  len[0] = 5;
563
168
  addr[1] = data;
564
168
  len[1] = data_len;
565
168
  if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
566
0
    return -1;
567
168
  wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
568
168
        bi->pubkey_hash_chirp, SHA256_MAC_LEN);
569
570
168
  return 0;
571
168
}
572
573
574
int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
575
             const u8 *data, size_t data_len)
576
168
{
577
168
  struct crypto_ec_key *key;
578
579
168
  if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
580
0
    wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
581
0
    return -1;
582
0
  }
583
584
168
  key = crypto_ec_key_parse_pub(data, data_len);
585
168
  if (!key) {
586
117
    wpa_printf(MSG_DEBUG,
587
117
         "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
588
117
    return -1;
589
117
  }
590
591
51
  bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
592
51
  if (!bi->curve) {
593
8
    wpa_printf(MSG_DEBUG,
594
8
         "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
595
8
         crypto_ec_key_group(key));
596
8
    goto fail;
597
8
  }
598
599
43
  bi->pubkey = key;
600
43
  return 0;
601
8
fail:
602
8
  crypto_ec_key_deinit(key);
603
8
  return -1;
604
51
}
605
606
607
static struct wpabuf *
608
dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
609
           const u8 *prot_hdr, u16 prot_hdr_len,
610
           int *hash_func)
611
0
{
612
0
  struct json_token *root, *token;
613
0
  struct wpabuf *kid = NULL;
614
615
0
  root = json_parse((const char *) prot_hdr, prot_hdr_len);
616
0
  if (!root) {
617
0
    wpa_printf(MSG_DEBUG,
618
0
         "DPP: JSON parsing failed for JWS Protected Header");
619
0
    goto fail;
620
0
  }
621
622
0
  if (root->type != JSON_OBJECT) {
623
0
    wpa_printf(MSG_DEBUG,
624
0
         "DPP: JWS Protected Header root is not an object");
625
0
    goto fail;
626
0
  }
627
628
0
  token = json_get_member(root, "typ");
629
0
  if (!token || token->type != JSON_STRING) {
630
0
    wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
631
0
    goto fail;
632
0
  }
633
0
  wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
634
0
       token->string);
635
0
  if (os_strcmp(token->string, "dppCon") != 0) {
636
0
    wpa_printf(MSG_DEBUG,
637
0
         "DPP: Unsupported JWS Protected Header typ=%s",
638
0
         token->string);
639
0
    goto fail;
640
0
  }
641
642
0
  token = json_get_member(root, "alg");
643
0
  if (!token || token->type != JSON_STRING) {
644
0
    wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
645
0
    goto fail;
646
0
  }
647
0
  wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
648
0
       token->string);
649
0
  if (os_strcmp(token->string, curve->jws_alg) != 0) {
650
0
    wpa_printf(MSG_DEBUG,
651
0
         "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
652
0
         token->string, curve->jws_alg);
653
0
    goto fail;
654
0
  }
655
0
  if (os_strcmp(token->string, "ES256") == 0 ||
656
0
      os_strcmp(token->string, "BS256") == 0) {
657
0
    *hash_func = CRYPTO_HASH_ALG_SHA256;
658
0
  } else if (os_strcmp(token->string, "ES384") == 0 ||
659
0
       os_strcmp(token->string, "BS384") == 0) {
660
0
    *hash_func = CRYPTO_HASH_ALG_SHA384;
661
0
  } else if (os_strcmp(token->string, "ES512") == 0 ||
662
0
       os_strcmp(token->string, "BS512") == 0) {
663
0
    *hash_func = CRYPTO_HASH_ALG_SHA512;
664
0
  } else {
665
0
    *hash_func = -1;
666
0
    wpa_printf(MSG_DEBUG,
667
0
         "DPP: Unsupported JWS Protected Header alg=%s",
668
0
         token->string);
669
0
    goto fail;
670
0
  }
671
672
0
  kid = json_get_member_base64url(root, "kid");
673
0
  if (!kid) {
674
0
    wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
675
0
    goto fail;
676
0
  }
677
0
  wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
678
0
      kid);
679
680
0
fail:
681
0
  json_free(root);
682
0
  return kid;
683
0
}
684
685
686
static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
687
          struct wpabuf *r_hash)
688
0
{
689
0
  struct wpabuf *uncomp;
690
0
  int res;
691
0
  u8 hash[SHA256_MAC_LEN];
692
0
  const u8 *addr[1];
693
0
  size_t len[1];
694
695
0
  if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
696
0
    return -1;
697
0
  uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
698
0
  if (!uncomp)
699
0
    return -1;
700
0
  addr[0] = wpabuf_head(uncomp);
701
0
  len[0] = wpabuf_len(uncomp);
702
0
  wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
703
0
        addr[0], len[0]);
704
0
  res = sha256_vector(1, addr, len, hash);
705
0
  wpabuf_free(uncomp);
706
0
  if (res < 0)
707
0
    return -1;
708
0
  if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
709
0
    wpa_printf(MSG_DEBUG,
710
0
         "DPP: Received hash value does not match calculated public key hash value");
711
0
    wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
712
0
          hash, SHA256_MAC_LEN);
713
0
    return -1;
714
0
  }
715
0
  return 0;
716
0
}
717
718
719
enum dpp_status_error
720
dpp_process_signed_connector(struct dpp_signed_connector_info *info,
721
           struct crypto_ec_key *csign_pub,
722
           const char *connector)
723
0
{
724
0
  enum dpp_status_error ret = 255;
725
0
  const char *pos, *end, *signed_start, *signed_end;
726
0
  struct wpabuf *kid = NULL;
727
0
  unsigned char *prot_hdr = NULL, *signature = NULL;
728
0
  size_t prot_hdr_len = 0, signature_len = 0, signed_len;
729
0
  int res, hash_func = -1;
730
0
  const struct dpp_curve_params *curve;
731
0
  u8 *hash = NULL;
732
733
0
  curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
734
0
  if (!curve)
735
0
    goto fail;
736
0
  wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
737
0
  os_memset(info, 0, sizeof(*info));
738
739
0
  signed_start = pos = connector;
740
0
  end = os_strchr(pos, '.');
741
0
  if (!end) {
742
0
    wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
743
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
744
0
    goto fail;
745
0
  }
746
0
  prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
747
0
  if (!prot_hdr) {
748
0
    wpa_printf(MSG_DEBUG,
749
0
         "DPP: Failed to base64url decode signedConnector JWS Protected Header");
750
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
751
0
    goto fail;
752
0
  }
753
0
  wpa_hexdump_ascii(MSG_DEBUG,
754
0
        "DPP: signedConnector - JWS Protected Header",
755
0
        prot_hdr, prot_hdr_len);
756
0
  kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
757
0
  if (!kid) {
758
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
759
0
    goto fail;
760
0
  }
761
0
  if (wpabuf_len(kid) != SHA256_MAC_LEN) {
762
0
    wpa_printf(MSG_DEBUG,
763
0
         "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
764
0
         (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
765
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
766
0
    goto fail;
767
0
  }
768
769
0
  pos = end + 1;
770
0
  end = os_strchr(pos, '.');
771
0
  if (!end) {
772
0
    wpa_printf(MSG_DEBUG,
773
0
         "DPP: Missing dot(2) in signedConnector");
774
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
775
0
    goto fail;
776
0
  }
777
0
  signed_end = end - 1;
778
0
  info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
779
0
  if (!info->payload) {
780
0
    wpa_printf(MSG_DEBUG,
781
0
         "DPP: Failed to base64url decode signedConnector JWS Payload");
782
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
783
0
    goto fail;
784
0
  }
785
0
  wpa_hexdump_ascii(MSG_DEBUG,
786
0
        "DPP: signedConnector - JWS Payload",
787
0
        info->payload, info->payload_len);
788
0
  pos = end + 1;
789
0
  signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
790
0
  if (!signature) {
791
0
    wpa_printf(MSG_DEBUG,
792
0
         "DPP: Failed to base64url decode signedConnector signature");
793
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
794
0
    goto fail;
795
0
    }
796
0
  wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
797
0
        signature, signature_len);
798
799
0
  if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
800
0
    ret = DPP_STATUS_NO_MATCH;
801
0
    goto fail;
802
0
  }
803
804
0
  if (signature_len & 0x01) {
805
0
    wpa_printf(MSG_DEBUG,
806
0
         "DPP: Unexpected signedConnector signature length (%d)",
807
0
         (int) signature_len);
808
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
809
0
    goto fail;
810
0
  }
811
812
0
  hash = os_malloc(curve->hash_len);
813
0
  if (!hash)
814
0
    goto fail;
815
816
0
  signed_len = signed_end - signed_start + 1;
817
0
  if (hash_func == CRYPTO_HASH_ALG_SHA256)
818
0
    res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
819
0
            hash);
820
0
  else if (hash_func == CRYPTO_HASH_ALG_SHA384)
821
0
    res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
822
0
            hash);
823
0
  else if (hash_func == CRYPTO_HASH_ALG_SHA512)
824
0
    res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
825
0
            hash);
826
0
  else
827
0
    goto fail;
828
829
0
  if (res)
830
0
    goto fail;
831
832
0
  res = crypto_ec_key_verify_signature_r_s(csign_pub,
833
0
             hash, curve->hash_len,
834
0
             signature, signature_len / 2,
835
0
             signature + signature_len / 2,
836
0
             signature_len / 2);
837
0
  if (res != 1) {
838
0
    wpa_printf(MSG_DEBUG,
839
0
         "DPP: signedConnector signature check failed (res=%d)",
840
0
         res);
841
0
    ret = DPP_STATUS_INVALID_CONNECTOR;
842
0
    goto fail;
843
0
  }
844
845
0
  ret = DPP_STATUS_OK;
846
0
fail:
847
0
  os_free(hash);
848
0
  os_free(prot_hdr);
849
0
  wpabuf_free(kid);
850
0
  os_free(signature);
851
0
  return ret;
852
0
}
853
854
855
enum dpp_status_error
856
dpp_check_signed_connector(struct dpp_signed_connector_info *info,
857
         const u8 *csign_key, size_t csign_key_len,
858
         const u8 *peer_connector, size_t peer_connector_len)
859
0
{
860
0
  struct crypto_ec_key *csign;
861
0
  char *signed_connector = NULL;
862
0
  enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
863
864
0
  csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
865
0
  if (!csign) {
866
0
    wpa_printf(MSG_ERROR,
867
0
         "DPP: Failed to parse local C-sign-key information");
868
0
    goto fail;
869
0
  }
870
871
0
  wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
872
0
        peer_connector, peer_connector_len);
873
0
  signed_connector = os_malloc(peer_connector_len + 1);
874
0
  if (!signed_connector)
875
0
    goto fail;
876
0
  os_memcpy(signed_connector, peer_connector, peer_connector_len);
877
0
  signed_connector[peer_connector_len] = '\0';
878
0
  res = dpp_process_signed_connector(info, csign, signed_connector);
879
0
fail:
880
0
  os_free(signed_connector);
881
0
  crypto_ec_key_deinit(csign);
882
0
  return res;
883
0
}
884
885
886
int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
887
0
{
888
0
  struct wpabuf *pix, *prx, *bix, *brx;
889
0
  const u8 *addr[7];
890
0
  size_t len[7];
891
0
  size_t i, num_elem = 0;
892
0
  size_t nonce_len;
893
0
  u8 zero = 0;
894
0
  int res = -1;
895
896
  /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
897
0
  nonce_len = auth->curve->nonce_len;
898
899
0
  if (auth->initiator) {
900
0
    pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
901
0
    prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
902
0
                 0);
903
0
    if (auth->own_bi)
904
0
      bix = crypto_ec_key_get_pubkey_point(
905
0
        auth->own_bi->pubkey, 0);
906
0
    else
907
0
      bix = NULL;
908
0
    brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
909
0
  } else {
910
0
    pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
911
0
                 0);
912
0
    prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
913
0
    if (auth->peer_bi)
914
0
      bix = crypto_ec_key_get_pubkey_point(
915
0
        auth->peer_bi->pubkey, 0);
916
0
    else
917
0
      bix = NULL;
918
0
    brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
919
0
  }
920
0
  if (!pix || !prx || !brx)
921
0
    goto fail;
922
923
0
  addr[num_elem] = auth->i_nonce;
924
0
  len[num_elem] = nonce_len;
925
0
  num_elem++;
926
927
0
  addr[num_elem] = auth->r_nonce;
928
0
  len[num_elem] = nonce_len;
929
0
  num_elem++;
930
931
0
  addr[num_elem] = wpabuf_head(pix);
932
0
  len[num_elem] = wpabuf_len(pix) / 2;
933
0
  num_elem++;
934
935
0
  addr[num_elem] = wpabuf_head(prx);
936
0
  len[num_elem] = wpabuf_len(prx) / 2;
937
0
  num_elem++;
938
939
0
  if (bix) {
940
0
    addr[num_elem] = wpabuf_head(bix);
941
0
    len[num_elem] = wpabuf_len(bix) / 2;
942
0
    num_elem++;
943
0
  }
944
945
0
  addr[num_elem] = wpabuf_head(brx);
946
0
  len[num_elem] = wpabuf_len(brx) / 2;
947
0
  num_elem++;
948
949
0
  addr[num_elem] = &zero;
950
0
  len[num_elem] = 1;
951
0
  num_elem++;
952
953
0
  wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
954
0
  for (i = 0; i < num_elem; i++)
955
0
    wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
956
0
  res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
957
0
  if (res == 0)
958
0
    wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
959
0
          auth->curve->hash_len);
960
0
fail:
961
0
  wpabuf_free(pix);
962
0
  wpabuf_free(prx);
963
0
  wpabuf_free(bix);
964
0
  wpabuf_free(brx);
965
0
  return res;
966
0
}
967
968
969
int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
970
0
{
971
0
  struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
972
0
  const u8 *addr[7];
973
0
  size_t len[7];
974
0
  size_t i, num_elem = 0;
975
0
  size_t nonce_len;
976
0
  u8 one = 1;
977
0
  int res = -1;
978
979
  /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
980
0
  nonce_len = auth->curve->nonce_len;
981
982
0
  if (auth->initiator) {
983
0
    pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
984
0
    prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
985
0
                 0);
986
0
    if (auth->own_bi)
987
0
      bix = crypto_ec_key_get_pubkey_point(
988
0
        auth->own_bi->pubkey, 0);
989
0
    else
990
0
      bix = NULL;
991
0
    if (!auth->peer_bi)
992
0
      goto fail;
993
0
    brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
994
0
  } else {
995
0
    pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
996
0
                 0);
997
0
    prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
998
0
    if (auth->peer_bi)
999
0
      bix = crypto_ec_key_get_pubkey_point(
1000
0
        auth->peer_bi->pubkey, 0);
1001
0
    else
1002
0
      bix = NULL;
1003
0
    if (!auth->own_bi)
1004
0
      goto fail;
1005
0
    brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
1006
0
  }
1007
0
  if (!pix || !prx || !brx)
1008
0
    goto fail;
1009
1010
0
  addr[num_elem] = auth->r_nonce;
1011
0
  len[num_elem] = nonce_len;
1012
0
  num_elem++;
1013
1014
0
  addr[num_elem] = auth->i_nonce;
1015
0
  len[num_elem] = nonce_len;
1016
0
  num_elem++;
1017
1018
0
  addr[num_elem] = wpabuf_head(prx);
1019
0
  len[num_elem] = wpabuf_len(prx) / 2;
1020
0
  num_elem++;
1021
1022
0
  addr[num_elem] = wpabuf_head(pix);
1023
0
  len[num_elem] = wpabuf_len(pix) / 2;
1024
0
  num_elem++;
1025
1026
0
  addr[num_elem] = wpabuf_head(brx);
1027
0
  len[num_elem] = wpabuf_len(brx) / 2;
1028
0
  num_elem++;
1029
1030
0
  if (bix) {
1031
0
    addr[num_elem] = wpabuf_head(bix);
1032
0
    len[num_elem] = wpabuf_len(bix) / 2;
1033
0
    num_elem++;
1034
0
  }
1035
1036
0
  addr[num_elem] = &one;
1037
0
  len[num_elem] = 1;
1038
0
  num_elem++;
1039
1040
0
  wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1041
0
  for (i = 0; i < num_elem; i++)
1042
0
    wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1043
0
  res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1044
0
  if (res == 0)
1045
0
    wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1046
0
          auth->curve->hash_len);
1047
0
fail:
1048
0
  wpabuf_free(pix);
1049
0
  wpabuf_free(prx);
1050
0
  wpabuf_free(bix);
1051
0
  wpabuf_free(brx);
1052
0
  return res;
1053
0
}
1054
1055
1056
int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1057
0
{
1058
0
  struct crypto_ec *ec;
1059
0
  struct crypto_ec_point *L = NULL, *BI = NULL;
1060
0
  const struct crypto_bignum *q;
1061
0
  struct crypto_bignum *sum = NULL, *lx = NULL, *bR = NULL, *pR = NULL;
1062
0
  int ret = -1;
1063
1064
  /* L = ((bR + pR) modulo q) * BI */
1065
1066
0
  ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1067
0
  if (!ec)
1068
0
    goto fail;
1069
1070
0
  q = crypto_ec_get_order(ec);
1071
0
  BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1072
0
  bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1073
0
  pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1074
0
  sum = crypto_bignum_init();
1075
0
  L = crypto_ec_point_init(ec);
1076
0
  lx = crypto_bignum_init();
1077
0
  if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
1078
0
      crypto_bignum_addmod(bR, pR, q, sum) ||
1079
0
      crypto_ec_point_mul(ec, BI, sum, L) ||
1080
0
      crypto_ec_point_x(ec, L, lx) ||
1081
0
      crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1082
0
         auth->secret_len) < 0)
1083
0
    goto fail;
1084
1085
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1086
0
  auth->Lx_len = auth->secret_len;
1087
0
  ret = 0;
1088
0
fail:
1089
0
  crypto_bignum_deinit(lx, 1);
1090
0
  crypto_bignum_deinit(sum, 1);
1091
0
  crypto_bignum_deinit(bR, 1);
1092
0
  crypto_bignum_deinit(pR, 1);
1093
0
  crypto_ec_point_deinit(L, 1);
1094
0
  crypto_ec_point_deinit(BI, 1);
1095
0
  crypto_ec_deinit(ec);
1096
0
  return ret;
1097
0
}
1098
1099
1100
int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1101
0
{
1102
0
  struct crypto_ec *ec;
1103
0
  struct crypto_ec_point *L = NULL, *sum = NULL, *BR = NULL, *PR = NULL;
1104
0
  struct crypto_bignum *lx = NULL, *bI = NULL;
1105
0
  int ret = -1;
1106
1107
  /* L = bI * (BR + PR) */
1108
1109
0
  ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1110
0
  if (!ec)
1111
0
    goto fail;
1112
1113
0
  BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1114
0
  PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1115
0
  bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1116
0
  sum = crypto_ec_point_init(ec);
1117
0
  L = crypto_ec_point_init(ec);
1118
0
  lx = crypto_bignum_init();
1119
0
  if (!BR || !PR || !bI || !sum || !L || !lx ||
1120
0
      crypto_ec_point_add(ec, BR, PR, sum) ||
1121
0
      crypto_ec_point_mul(ec, sum, bI, L) ||
1122
0
      crypto_ec_point_x(ec, L, lx) ||
1123
0
      crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1124
0
         auth->secret_len) < 0)
1125
0
    goto fail;
1126
1127
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1128
0
  auth->Lx_len = auth->secret_len;
1129
0
  ret = 0;
1130
0
fail:
1131
0
  crypto_bignum_deinit(lx, 1);
1132
0
  crypto_bignum_deinit(bI, 1);
1133
0
  crypto_ec_point_deinit(sum, 1);
1134
0
  crypto_ec_point_deinit(L, 1);
1135
0
  crypto_ec_point_deinit(BR, 1);
1136
0
  crypto_ec_point_deinit(PR, 1);
1137
0
  crypto_ec_deinit(ec);
1138
0
  return ret;
1139
0
}
1140
1141
1142
int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1143
0
{
1144
0
  u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1145
0
  const char *info = "DPP PMK";
1146
0
  int res;
1147
1148
  /* PMK = HKDF(<>, "DPP PMK", N.x) */
1149
1150
  /* HKDF-Extract(<>, N.x) */
1151
0
  os_memset(salt, 0, hash_len);
1152
0
  if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1153
0
    return -1;
1154
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1155
0
      prk, hash_len);
1156
1157
  /* HKDF-Expand(PRK, info, L) */
1158
0
  res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1159
0
  os_memset(prk, 0, hash_len);
1160
0
  if (res < 0)
1161
0
    return -1;
1162
1163
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1164
0
      pmk, hash_len);
1165
0
  return 0;
1166
0
}
1167
1168
1169
int dpp_derive_pmkid(const struct dpp_curve_params *curve,
1170
         struct crypto_ec_key *own_key,
1171
         struct crypto_ec_key *peer_key, u8 *pmkid)
1172
0
{
1173
0
  struct wpabuf *nkx, *pkx;
1174
0
  int ret = -1, res;
1175
0
  const u8 *addr[2];
1176
0
  size_t len[2];
1177
0
  u8 hash[SHA256_MAC_LEN];
1178
1179
  /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
1180
0
  nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
1181
0
  pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
1182
0
  if (!nkx || !pkx)
1183
0
    goto fail;
1184
0
  addr[0] = wpabuf_head(nkx);
1185
0
  len[0] = wpabuf_len(nkx) / 2;
1186
0
  addr[1] = wpabuf_head(pkx);
1187
0
  len[1] = wpabuf_len(pkx) / 2;
1188
0
  if (len[0] != len[1])
1189
0
    goto fail;
1190
0
  if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1191
0
    addr[0] = wpabuf_head(pkx);
1192
0
    addr[1] = wpabuf_head(nkx);
1193
0
  }
1194
0
  wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1195
0
  wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1196
0
  res = sha256_vector(2, addr, len, hash);
1197
0
  if (res < 0)
1198
0
    goto fail;
1199
0
  wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1200
0
  os_memcpy(pmkid, hash, PMKID_LEN);
1201
0
  wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1202
0
  ret = 0;
1203
0
fail:
1204
0
  wpabuf_free(nkx);
1205
0
  wpabuf_free(pkx);
1206
0
  return ret;
1207
0
}
1208
1209
1210
/* Role-specific elements for PKEX */
1211
1212
/* NIST P-256 */
1213
static const u8 pkex_init_x_p256[32] = {
1214
  0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1215
  0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1216
  0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1217
  0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1218
 };
1219
static const u8 pkex_init_y_p256[32] = {
1220
  0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1221
  0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1222
  0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1223
  0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1224
 };
1225
static const u8 pkex_resp_x_p256[32] = {
1226
  0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1227
  0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1228
  0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1229
  0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1230
};
1231
static const u8 pkex_resp_y_p256[32] = {
1232
  0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1233
  0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1234
  0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1235
  0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1236
};
1237
1238
/* NIST P-384 */
1239
static const u8 pkex_init_x_p384[48] = {
1240
  0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1241
  0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1242
  0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1243
  0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1244
  0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1245
  0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1246
};
1247
static const u8 pkex_init_y_p384[48] = {
1248
  0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1249
  0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1250
  0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1251
  0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1252
  0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1253
  0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1254
};
1255
static const u8 pkex_resp_x_p384[48] = {
1256
  0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1257
  0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1258
  0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1259
  0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1260
  0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1261
  0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1262
};
1263
static const u8 pkex_resp_y_p384[48] = {
1264
  0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1265
  0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1266
  0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1267
  0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1268
  0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1269
  0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1270
};
1271
1272
/* NIST P-521 */
1273
static const u8 pkex_init_x_p521[66] = {
1274
  0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1275
  0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1276
  0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1277
  0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1278
  0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1279
  0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1280
  0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1281
  0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1282
  0x97, 0x76
1283
};
1284
static const u8 pkex_init_y_p521[66] = {
1285
  0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1286
  0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1287
  0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1288
  0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1289
  0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1290
  0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1291
  0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1292
  0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1293
  0x03, 0xa8
1294
};
1295
static const u8 pkex_resp_x_p521[66] = {
1296
  0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1297
  0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1298
  0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1299
  0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1300
  0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1301
  0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1302
  0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1303
  0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1304
  0x84, 0xb4
1305
};
1306
static const u8 pkex_resp_y_p521[66] = {
1307
  0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1308
  0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1309
  0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1310
  0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1311
  0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1312
  0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1313
  0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1314
  0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1315
  0xce, 0xe1
1316
};
1317
1318
/* Brainpool P-256r1 */
1319
static const u8 pkex_init_x_bp_p256r1[32] = {
1320
  0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1321
  0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1322
  0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1323
  0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1324
};
1325
static const u8 pkex_init_y_bp_p256r1[32] = {
1326
  0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1327
  0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1328
  0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1329
  0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1330
};
1331
static const u8 pkex_resp_x_bp_p256r1[32] = {
1332
  0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1333
  0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1334
  0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1335
  0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1336
};
1337
static const u8 pkex_resp_y_bp_p256r1[32] = {
1338
  0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1339
  0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1340
  0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1341
  0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1342
};
1343
1344
/* Brainpool P-384r1 */
1345
static const u8 pkex_init_x_bp_p384r1[48] = {
1346
  0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1347
  0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1348
  0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1349
  0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1350
  0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1351
  0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1352
};
1353
static const u8 pkex_init_y_bp_p384r1[48] = {
1354
  0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1355
  0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1356
  0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1357
  0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1358
  0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1359
  0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1360
};
1361
static const u8 pkex_resp_x_bp_p384r1[48] = {
1362
  0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1363
  0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1364
  0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1365
  0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1366
  0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1367
  0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1368
};
1369
static const u8 pkex_resp_y_bp_p384r1[48] = {
1370
  0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1371
  0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1372
  0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1373
  0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1374
  0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1375
  0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1376
};
1377
1378
/* Brainpool P-512r1 */
1379
static const u8 pkex_init_x_bp_p512r1[64] = {
1380
  0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1381
  0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1382
  0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1383
  0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1384
  0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1385
  0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1386
  0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1387
  0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1388
};
1389
static const u8 pkex_init_y_bp_p512r1[64] = {
1390
  0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1391
  0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1392
  0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1393
  0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1394
  0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1395
  0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1396
  0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1397
  0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1398
};
1399
static const u8 pkex_resp_x_bp_p512r1[64] = {
1400
  0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1401
  0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1402
  0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1403
  0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1404
  0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1405
  0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1406
  0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1407
  0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1408
};
1409
static const u8 pkex_resp_y_bp_p512r1[64] = {
1410
  0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1411
  0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1412
  0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1413
  0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1414
  0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1415
  0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1416
  0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1417
  0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1418
};
1419
1420
1421
static struct crypto_ec_key *
1422
dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
1423
0
{
1424
0
  const u8 *x, *y;
1425
1426
0
  switch (curve->ike_group) {
1427
0
  case 19:
1428
0
    x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1429
0
    y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1430
0
    break;
1431
0
  case 20:
1432
0
    x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1433
0
    y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1434
0
    break;
1435
0
  case 21:
1436
0
    x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1437
0
    y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1438
0
    break;
1439
0
  case 28:
1440
0
    x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1441
0
    y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1442
0
    break;
1443
0
  case 29:
1444
0
    x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1445
0
    y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1446
0
    break;
1447
0
  case 30:
1448
0
    x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1449
0
    y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1450
0
    break;
1451
0
  default:
1452
0
    return NULL;
1453
0
  }
1454
1455
0
  return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
1456
0
}
1457
1458
1459
struct crypto_ec_point *
1460
dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
1461
       const char *code, size_t code_len, const char *identifier,
1462
       struct crypto_ec **ret_ec)
1463
0
{
1464
0
  u8 hash[DPP_MAX_HASH_LEN];
1465
0
  const u8 *addr[3];
1466
0
  size_t len[3];
1467
0
  unsigned int num_elem = 0;
1468
0
  struct crypto_ec_point *Qi = NULL, *Pi = NULL;
1469
0
  struct crypto_ec_key *Pi_key = NULL;
1470
0
  struct crypto_bignum *hash_bn = NULL;
1471
0
  struct crypto_ec *ec = NULL;
1472
1473
  /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
1474
1475
0
  if (mac_init) {
1476
0
    wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
1477
0
         MAC2STR(mac_init));
1478
0
    addr[num_elem] = mac_init;
1479
0
    len[num_elem] = ETH_ALEN;
1480
0
    num_elem++;
1481
0
  }
1482
0
  if (identifier) {
1483
0
    wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1484
0
         identifier);
1485
0
    addr[num_elem] = (const u8 *) identifier;
1486
0
    len[num_elem] = os_strlen(identifier);
1487
0
    num_elem++;
1488
0
  }
1489
0
  wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1490
0
  addr[num_elem] = (const u8 *) code;
1491
0
  len[num_elem] = code_len;
1492
0
  num_elem++;
1493
0
  if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1494
0
    goto fail;
1495
0
  wpa_hexdump_key(MSG_DEBUG,
1496
0
      "DPP: H([MAC-Initiator |] [identifier |] code)",
1497
0
      hash, curve->hash_len);
1498
0
  Pi_key = dpp_pkex_get_role_elem(curve, 1);
1499
0
  if (!Pi_key)
1500
0
    goto fail;
1501
0
  dpp_debug_print_key("DPP: Pi", Pi_key);
1502
1503
0
  ec = crypto_ec_init(curve->ike_group);
1504
0
  if (!ec)
1505
0
    goto fail;
1506
1507
0
  Pi = crypto_ec_key_get_public_key(Pi_key);
1508
0
  Qi = crypto_ec_point_init(ec);
1509
0
  hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1510
0
  if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
1511
0
    goto fail;
1512
1513
0
  if (crypto_ec_point_is_at_infinity(ec, Qi)) {
1514
0
    wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1515
0
    goto fail;
1516
0
  }
1517
0
  crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
1518
0
out:
1519
0
  crypto_ec_key_deinit(Pi_key);
1520
0
  crypto_ec_point_deinit(Pi, 1);
1521
0
  crypto_bignum_deinit(hash_bn, 1);
1522
0
  if (ret_ec && Qi)
1523
0
    *ret_ec = ec;
1524
0
  else
1525
0
    crypto_ec_deinit(ec);
1526
0
  return Qi;
1527
0
fail:
1528
0
  crypto_ec_point_deinit(Qi, 1);
1529
0
  Qi = NULL;
1530
0
  goto out;
1531
0
}
1532
1533
1534
struct crypto_ec_point *
1535
dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
1536
       const char *code, size_t code_len, const char *identifier,
1537
       struct crypto_ec **ret_ec)
1538
0
{
1539
0
  u8 hash[DPP_MAX_HASH_LEN];
1540
0
  const u8 *addr[3];
1541
0
  size_t len[3];
1542
0
  unsigned int num_elem = 0;
1543
0
  struct crypto_ec_point *Qr = NULL, *Pr = NULL;
1544
0
  struct crypto_ec_key *Pr_key = NULL;
1545
0
  struct crypto_bignum *hash_bn = NULL;
1546
0
  struct crypto_ec *ec = NULL;
1547
1548
  /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
1549
1550
0
  if (mac_resp) {
1551
0
    wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
1552
0
         MAC2STR(mac_resp));
1553
0
    addr[num_elem] = mac_resp;
1554
0
    len[num_elem] = ETH_ALEN;
1555
0
    num_elem++;
1556
0
  }
1557
0
  if (identifier) {
1558
0
    wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1559
0
         identifier);
1560
0
    addr[num_elem] = (const u8 *) identifier;
1561
0
    len[num_elem] = os_strlen(identifier);
1562
0
    num_elem++;
1563
0
  }
1564
0
  wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1565
0
  addr[num_elem] = (const u8 *) code;
1566
0
  len[num_elem] = code_len;
1567
0
  num_elem++;
1568
0
  if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1569
0
    goto fail;
1570
0
  wpa_hexdump_key(MSG_DEBUG,
1571
0
      "DPP: H([MAC-Responder |] [identifier |] code)",
1572
0
      hash, curve->hash_len);
1573
0
  Pr_key = dpp_pkex_get_role_elem(curve, 0);
1574
0
  if (!Pr_key)
1575
0
    goto fail;
1576
0
  dpp_debug_print_key("DPP: Pr", Pr_key);
1577
1578
0
  ec = crypto_ec_init(curve->ike_group);
1579
0
  if (!ec)
1580
0
    goto fail;
1581
1582
0
  Pr = crypto_ec_key_get_public_key(Pr_key);
1583
0
  Qr = crypto_ec_point_init(ec);
1584
0
  hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1585
0
  if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
1586
0
    goto fail;
1587
1588
0
  if (crypto_ec_point_is_at_infinity(ec, Qr)) {
1589
0
    wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1590
0
    goto fail;
1591
0
  }
1592
0
  crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
1593
1594
0
out:
1595
0
  crypto_ec_key_deinit(Pr_key);
1596
0
  crypto_ec_point_deinit(Pr, 1);
1597
0
  crypto_bignum_deinit(hash_bn, 1);
1598
0
  if (ret_ec && Qr)
1599
0
    *ret_ec = ec;
1600
0
  else
1601
0
    crypto_ec_deinit(ec);
1602
0
  return Qr;
1603
0
fail:
1604
0
  crypto_ec_point_deinit(Qr, 1);
1605
0
  Qr = NULL;
1606
0
  goto out;
1607
0
}
1608
1609
1610
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
1611
          u8 ver_init, u8 ver_resp,
1612
          const u8 *Mx, size_t Mx_len,
1613
          const u8 *Nx, size_t Nx_len,
1614
          const char *code, size_t code_len,
1615
          const u8 *Kx, size_t Kx_len,
1616
          u8 *z, unsigned int hash_len)
1617
0
{
1618
0
  u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1619
0
  int res;
1620
0
  u8 *info, *pos;
1621
0
  size_t info_len;
1622
1623
  /*
1624
   * v1: info = MAC-Initiator | MAC-Responder
1625
   * v2: info = Protocol Version-Initiator | Protocol Version-Responder
1626
   * z = HKDF(<>, info | M.x | N.x | code, K.x)
1627
   */
1628
1629
  /* HKDF-Extract(<>, IKM=K.x) */
1630
0
  os_memset(salt, 0, hash_len);
1631
0
  if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1632
0
    return -1;
1633
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1634
0
      prk, hash_len);
1635
0
  if (mac_init && mac_resp)
1636
0
    info_len = 2 * ETH_ALEN;
1637
0
  else
1638
0
    info_len = 2;
1639
0
  info_len += Mx_len + Nx_len + code_len;
1640
0
  info = os_malloc(info_len);
1641
0
  if (!info)
1642
0
    return -1;
1643
0
  pos = info;
1644
0
  if (mac_init && mac_resp) {
1645
0
    os_memcpy(pos, mac_init, ETH_ALEN);
1646
0
    pos += ETH_ALEN;
1647
0
    os_memcpy(pos, mac_resp, ETH_ALEN);
1648
0
    pos += ETH_ALEN;
1649
0
  } else {
1650
0
    *pos++ = ver_init;
1651
0
    *pos++ = ver_resp;
1652
0
  }
1653
0
  os_memcpy(pos, Mx, Mx_len);
1654
0
  pos += Mx_len;
1655
0
  os_memcpy(pos, Nx, Nx_len);
1656
0
  pos += Nx_len;
1657
0
  os_memcpy(pos, code, code_len);
1658
1659
  /* HKDF-Expand(PRK, info, L) */
1660
0
  if (hash_len == 32)
1661
0
    res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1662
0
              z, hash_len);
1663
0
  else if (hash_len == 48)
1664
0
    res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1665
0
              z, hash_len);
1666
0
  else if (hash_len == 64)
1667
0
    res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1668
0
              z, hash_len);
1669
0
  else
1670
0
    res = -1;
1671
0
  os_free(info);
1672
0
  os_memset(prk, 0, hash_len);
1673
0
  if (res < 0)
1674
0
    return -1;
1675
1676
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1677
0
      z, hash_len);
1678
0
  return 0;
1679
0
}
1680
1681
1682
int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1683
             const u8 *net_access_key,
1684
             size_t net_access_key_len,
1685
             struct json_token *peer_net_access_key)
1686
0
{
1687
0
  struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
1688
0
  struct crypto_bignum *sum = NULL, *cR = NULL, *pR = NULL;
1689
0
  const struct crypto_bignum *q;
1690
0
  struct crypto_ec *ec = NULL;
1691
0
  struct crypto_ec_point *M = NULL, *CI = NULL;
1692
0
  u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1693
0
  u8 prk[DPP_MAX_HASH_LEN];
1694
0
  const struct dpp_curve_params *curve;
1695
0
  int res = -1;
1696
0
  u8 nonces[2 * DPP_MAX_NONCE_LEN];
1697
1698
0
  own_key = dpp_set_keypair(&auth->curve, net_access_key,
1699
0
          net_access_key_len);
1700
0
  if (!own_key) {
1701
0
    dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1702
0
    goto fail;
1703
0
  }
1704
1705
0
  peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1706
0
  if (!peer_key)
1707
0
    goto fail;
1708
0
  dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1709
1710
0
  if (auth->curve != curve) {
1711
0
    wpa_printf(MSG_DEBUG,
1712
0
         "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1713
0
         auth->curve->name, curve->name);
1714
0
    goto fail;
1715
0
  }
1716
1717
0
  auth->own_protocol_key = dpp_gen_keypair(curve);
1718
0
  if (!auth->own_protocol_key)
1719
0
    goto fail;
1720
1721
0
  if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1722
0
    wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1723
0
    goto fail;
1724
0
  }
1725
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1726
0
      auth->e_nonce, auth->curve->nonce_len);
1727
1728
  /* M = { cR + pR } * CI */
1729
0
  ec = crypto_ec_init(curve->ike_group);
1730
0
  if (!ec)
1731
0
    goto fail;
1732
1733
0
  sum = crypto_bignum_init();
1734
0
  q = crypto_ec_get_order(ec);
1735
0
  M = crypto_ec_point_init(ec);
1736
0
  cR = crypto_ec_key_get_private_key(own_key);
1737
0
  pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1738
0
  CI = crypto_ec_key_get_public_key(peer_key);
1739
0
  if (!sum || !q || !M || !cR || !pR || !CI ||
1740
0
      crypto_bignum_addmod(cR, pR, q, sum) ||
1741
0
      crypto_ec_point_mul(ec, CI, sum, M) ||
1742
0
      crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1743
0
    wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1744
0
    goto fail;
1745
0
  }
1746
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1747
1748
  /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1749
1750
  /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1751
0
  os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1752
0
  os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1753
0
  if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1754
0
         Mx, curve->prime_len, prk) < 0)
1755
0
    goto fail;
1756
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1757
1758
  /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1759
0
  if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1760
0
          "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1761
0
    goto fail;
1762
0
  wpa_hexdump_key(MSG_DEBUG,
1763
0
      "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1764
0
      auth->ke, curve->hash_len);
1765
1766
0
  res = 0;
1767
0
  crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1768
0
  auth->reconfig_old_protocol_key = own_key;
1769
0
  own_key = NULL;
1770
0
fail:
1771
0
  forced_memzero(prk, sizeof(prk));
1772
0
  forced_memzero(Mx, sizeof(Mx));
1773
0
  crypto_ec_point_deinit(M, 1);
1774
0
  crypto_ec_point_deinit(CI, 1);
1775
0
  crypto_bignum_deinit(sum, 1);
1776
0
  crypto_bignum_deinit(cR, 1);
1777
0
  crypto_bignum_deinit(pR, 1);
1778
0
  crypto_ec_key_deinit(own_key);
1779
0
  crypto_ec_key_deinit(peer_key);
1780
0
  crypto_ec_deinit(ec);
1781
0
  return res;
1782
0
}
1783
1784
1785
int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1786
             const u8 *r_proto, u16 r_proto_len,
1787
             struct json_token *net_access_key)
1788
0
{
1789
0
  struct crypto_ec_key *pr = NULL, *peer_key = NULL;
1790
0
  struct crypto_bignum *cI = NULL;
1791
0
  struct crypto_ec *ec = NULL;
1792
0
  struct crypto_ec_point *sum = NULL, *M = NULL, *CR = NULL, *PR = NULL;
1793
0
  u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1794
0
  u8 prk[DPP_MAX_HASH_LEN];
1795
0
  int res = -1;
1796
0
  const struct dpp_curve_params *curve;
1797
0
  u8 nonces[2 * DPP_MAX_NONCE_LEN];
1798
1799
0
  pr = dpp_set_pubkey_point(auth->conf->connector_key,
1800
0
          r_proto, r_proto_len);
1801
0
  if (!pr) {
1802
0
    dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1803
0
    goto fail;
1804
0
  }
1805
0
  dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
1806
0
  crypto_ec_key_deinit(auth->peer_protocol_key);
1807
0
  auth->peer_protocol_key = pr;
1808
0
  pr = NULL;
1809
1810
0
  peer_key = dpp_parse_jwk(net_access_key, &curve);
1811
0
  if (!peer_key)
1812
0
    goto fail;
1813
0
  dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1814
0
  if (auth->curve != curve) {
1815
0
    wpa_printf(MSG_DEBUG,
1816
0
         "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1817
0
         auth->curve->name, curve->name);
1818
0
    goto fail;
1819
0
  }
1820
1821
  /* M = cI * { CR + PR } */
1822
0
  ec = crypto_ec_init(curve->ike_group);
1823
0
  if (!ec)
1824
0
    goto fail;
1825
1826
0
  cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
1827
0
  sum = crypto_ec_point_init(ec);
1828
0
  M = crypto_ec_point_init(ec);
1829
0
  CR = crypto_ec_key_get_public_key(peer_key);
1830
0
  PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1831
0
  if (!cI || !sum || !M || !CR || !PR ||
1832
0
      crypto_ec_point_add(ec, CR, PR, sum) ||
1833
0
      crypto_ec_point_mul(ec, sum, cI, M) ||
1834
0
      crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1835
0
    wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1836
0
    goto fail;
1837
0
  }
1838
1839
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1840
1841
  /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1842
1843
  /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1844
0
  os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1845
0
  os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1846
0
  if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1847
0
         Mx, curve->prime_len, prk) < 0)
1848
0
    goto fail;
1849
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1850
1851
  /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1852
0
  if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1853
0
          "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1854
0
    goto fail;
1855
0
  wpa_hexdump_key(MSG_DEBUG,
1856
0
      "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1857
0
      auth->ke, curve->hash_len);
1858
1859
0
  res = 0;
1860
0
fail:
1861
0
  forced_memzero(prk, sizeof(prk));
1862
0
  forced_memzero(Mx, sizeof(Mx));
1863
0
  crypto_bignum_deinit(cI, 1);
1864
0
  crypto_ec_key_deinit(pr);
1865
0
  crypto_ec_key_deinit(peer_key);
1866
0
  crypto_ec_point_deinit(sum, 1);
1867
0
  crypto_ec_point_deinit(M, 1);
1868
0
  crypto_ec_point_deinit(CR, 1);
1869
0
  crypto_ec_point_deinit(PR, 1);
1870
0
  crypto_ec_deinit(ec);
1871
0
  return res;
1872
0
}
1873
1874
1875
static char *
1876
dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1877
0
{
1878
0
  struct wpabuf *jws_prot_hdr;
1879
0
  char *signed1;
1880
1881
0
  jws_prot_hdr = wpabuf_alloc(100);
1882
0
  if (!jws_prot_hdr)
1883
0
    return NULL;
1884
0
  json_start_object(jws_prot_hdr, NULL);
1885
0
  json_add_string(jws_prot_hdr, "typ", "dppCon");
1886
0
  json_value_sep(jws_prot_hdr);
1887
0
  json_add_string(jws_prot_hdr, "kid", conf->kid);
1888
0
  json_value_sep(jws_prot_hdr);
1889
0
  json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1890
0
  json_end_object(jws_prot_hdr);
1891
0
  signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1892
0
            wpabuf_len(jws_prot_hdr),
1893
0
            signed1_len);
1894
0
  wpabuf_free(jws_prot_hdr);
1895
0
  return signed1;
1896
0
}
1897
1898
1899
static char *
1900
dpp_build_conn_signature(struct dpp_configurator *conf,
1901
       const char *signed1, size_t signed1_len,
1902
       const char *signed2, size_t signed2_len,
1903
       size_t *signed3_len)
1904
0
{
1905
0
  const struct dpp_curve_params *curve;
1906
0
  struct wpabuf *sig = NULL;
1907
0
  char *signed3 = NULL;
1908
0
  char *dot = ".";
1909
0
  const u8 *vector[3];
1910
0
  size_t vector_len[3];
1911
0
  u8 *hash;
1912
0
  int ret;
1913
1914
0
  vector[0] = (const u8 *) signed1;
1915
0
  vector[1] = (const u8 *) dot;
1916
0
  vector[2] = (const u8 *) signed2;
1917
0
  vector_len[0] = signed1_len;
1918
0
  vector_len[1] = 1;
1919
0
  vector_len[2] = signed2_len;
1920
1921
0
  curve = conf->curve;
1922
0
  hash = os_malloc(curve->hash_len);
1923
0
  if (!hash)
1924
0
    goto fail;
1925
0
  if (curve->hash_len == SHA256_MAC_LEN) {
1926
0
    ret = sha256_vector(3, vector, vector_len, hash);
1927
0
  } else if (curve->hash_len == SHA384_MAC_LEN) {
1928
0
    ret = sha384_vector(3, vector, vector_len, hash);
1929
0
  } else if (curve->hash_len == SHA512_MAC_LEN) {
1930
0
    ret = sha512_vector(3, vector, vector_len, hash);
1931
0
  } else {
1932
0
    wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1933
0
    goto fail;
1934
0
  }
1935
0
  if (ret) {
1936
0
    wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
1937
0
    goto fail;
1938
0
  }
1939
0
  wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
1940
0
        hash, curve->hash_len);
1941
1942
0
  sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
1943
0
  if (!sig) {
1944
0
    wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
1945
0
    goto fail;
1946
0
  }
1947
1948
0
  wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
1949
0
        wpabuf_head(sig), wpabuf_len(sig));
1950
0
  signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
1951
0
            signed3_len);
1952
1953
0
fail:
1954
0
  os_free(hash);
1955
0
  wpabuf_free(sig);
1956
0
  return signed3;
1957
0
}
1958
1959
char * dpp_sign_connector(struct dpp_configurator *conf,
1960
        const struct wpabuf *dppcon)
1961
0
{
1962
0
  char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1963
0
  char *signed_conn = NULL, *pos;
1964
0
  size_t signed1_len, signed2_len, signed3_len;
1965
1966
0
  signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1967
0
  signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1968
0
            &signed2_len);
1969
0
  if (!signed1 || !signed2)
1970
0
    goto fail;
1971
1972
0
  signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1973
0
             signed2, signed2_len, &signed3_len);
1974
0
  if (!signed3)
1975
0
    goto fail;
1976
1977
0
  signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1978
0
  if (!signed_conn)
1979
0
    goto fail;
1980
0
  pos = signed_conn;
1981
0
  os_memcpy(pos, signed1, signed1_len);
1982
0
  pos += signed1_len;
1983
0
  *pos++ = '.';
1984
0
  os_memcpy(pos, signed2, signed2_len);
1985
0
  pos += signed2_len;
1986
0
  *pos++ = '.';
1987
0
  os_memcpy(pos, signed3, signed3_len);
1988
0
  pos += signed3_len;
1989
0
  *pos = '\0';
1990
1991
0
fail:
1992
0
  os_free(signed1);
1993
0
  os_free(signed2);
1994
0
  os_free(signed3);
1995
0
  return signed_conn;
1996
0
}
1997
1998
1999
#ifdef CONFIG_DPP2
2000
2001
struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
2002
            size_t net_access_key_len)
2003
0
{
2004
0
  struct wpabuf *pub = NULL;
2005
0
  struct crypto_ec_key *own_key;
2006
0
  struct dpp_pfs *pfs;
2007
2008
0
  pfs = os_zalloc(sizeof(*pfs));
2009
0
  if (!pfs)
2010
0
    return NULL;
2011
2012
0
  own_key = dpp_set_keypair(&pfs->curve, net_access_key,
2013
0
          net_access_key_len);
2014
0
  if (!own_key) {
2015
0
    wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2016
0
    goto fail;
2017
0
  }
2018
0
  crypto_ec_key_deinit(own_key);
2019
2020
0
  pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
2021
0
  if (!pfs->ecdh)
2022
0
    goto fail;
2023
2024
0
  pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
2025
0
  pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
2026
0
  if (!pub)
2027
0
    goto fail;
2028
2029
0
  pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2030
0
  if (!pfs->ie)
2031
0
    goto fail;
2032
0
  wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2033
0
  wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2034
0
  wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2035
0
  wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2036
0
  wpabuf_put_buf(pfs->ie, pub);
2037
0
  wpabuf_free(pub);
2038
0
  wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2039
0
      pfs->ie);
2040
2041
0
  return pfs;
2042
0
fail:
2043
0
  wpabuf_free(pub);
2044
0
  dpp_pfs_free(pfs);
2045
0
  return NULL;
2046
0
}
2047
2048
2049
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2050
0
{
2051
0
  if (peer_ie_len < 2)
2052
0
    return -1;
2053
0
  if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2054
0
    wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2055
0
    return -1;
2056
0
  }
2057
2058
0
  pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2059
0
                peer_ie_len - 2);
2060
0
  pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2061
0
  if (!pfs->secret) {
2062
0
    wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2063
0
    return -1;
2064
0
  }
2065
0
  wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2066
0
  return 0;
2067
0
}
2068
2069
2070
void dpp_pfs_free(struct dpp_pfs *pfs)
2071
0
{
2072
0
  if (!pfs)
2073
0
    return;
2074
0
  crypto_ecdh_deinit(pfs->ecdh);
2075
0
  wpabuf_free(pfs->ie);
2076
0
  wpabuf_clear_free(pfs->secret);
2077
0
  os_free(pfs);
2078
0
}
2079
2080
2081
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2082
0
{
2083
0
  struct crypto_csr *csr = NULL;
2084
0
  struct wpabuf *buf = NULL;
2085
0
  struct crypto_ec_key *key;
2086
0
  unsigned int hash_len = auth->curve->hash_len;
2087
0
  struct wpabuf *priv_key;
2088
0
  u8 cp[DPP_CP_LEN];
2089
0
  char *password = NULL;
2090
0
  size_t password_len = 0;
2091
0
  int hash_sign_algo;
2092
2093
  /* TODO: use auth->csrattrs */
2094
2095
  /* TODO: support generation of a new private key if csrAttrs requests
2096
   * a specific group to be used */
2097
0
  key = auth->own_protocol_key;
2098
2099
0
  priv_key = crypto_ec_key_get_ecprivate_key(key, true);
2100
0
  if (!priv_key)
2101
0
    goto fail;
2102
0
  wpabuf_free(auth->priv_key);
2103
0
  auth->priv_key = priv_key;
2104
2105
0
  csr = crypto_csr_init();
2106
0
  if (!csr || crypto_csr_set_ec_public_key(csr, key))
2107
0
    goto fail;
2108
2109
0
  if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
2110
0
    goto fail;
2111
2112
  /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2113
0
  if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2114
0
          "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2115
0
    goto fail;
2116
0
  wpa_hexdump_key(MSG_DEBUG,
2117
0
      "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2118
0
      cp, DPP_CP_LEN);
2119
0
  password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2120
0
  forced_memzero(cp, DPP_CP_LEN);
2121
0
  if (!password ||
2122
0
      crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2123
0
             ASN1_TAG_UTF8STRING, (const u8 *) password,
2124
0
             password_len))
2125
0
    goto fail;
2126
2127
  /* TODO: hash func selection based on csrAttrs */
2128
0
  if (hash_len == SHA256_MAC_LEN) {
2129
0
    hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
2130
0
  } else if (hash_len == SHA384_MAC_LEN) {
2131
0
    hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
2132
0
  } else if (hash_len == SHA512_MAC_LEN) {
2133
0
    hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
2134
0
  } else {
2135
0
    wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2136
0
    goto fail;
2137
0
  }
2138
2139
0
  buf = crypto_csr_sign(csr, key, hash_sign_algo);
2140
0
  if (!buf)
2141
0
    goto fail;
2142
0
  wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2143
2144
0
fail:
2145
0
  bin_clear_free(password, password_len);
2146
0
  crypto_csr_deinit(csr);
2147
0
  return buf;
2148
0
}
2149
2150
2151
int dpp_validate_csr(struct dpp_authentication *auth,
2152
         const struct wpabuf *csrbuf)
2153
0
{
2154
0
  struct crypto_csr *csr;
2155
0
  const u8 *attr;
2156
0
  size_t attr_len;
2157
0
  int attr_type;
2158
0
  unsigned char *cp = NULL;
2159
0
  size_t cp_len;
2160
0
  u8 exp_cp[DPP_CP_LEN];
2161
0
  unsigned int hash_len = auth->curve->hash_len;
2162
0
  int ret = -1;
2163
2164
0
  csr = crypto_csr_verify(csrbuf);
2165
0
  if (!csr) {
2166
0
    wpa_printf(MSG_DEBUG,
2167
0
         "DPP: CSR invalid or invalid signature");
2168
0
    goto fail;
2169
0
  }
2170
2171
0
  attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2172
0
          &attr_len, &attr_type);
2173
0
  if (!attr) {
2174
0
    wpa_printf(MSG_DEBUG,
2175
0
         "DPP: CSR does not include challengePassword");
2176
0
    goto fail;
2177
0
  }
2178
  /* This is supposed to be UTF8String, but allow other strings as well
2179
   * since challengePassword is using ASCII (base64 encoded). */
2180
0
  if (attr_type != ASN1_TAG_UTF8STRING &&
2181
0
      attr_type != ASN1_TAG_PRINTABLESTRING &&
2182
0
      attr_type != ASN1_TAG_IA5STRING) {
2183
0
    wpa_printf(MSG_DEBUG,
2184
0
         "DPP: Unexpected challengePassword attribute type %d",
2185
0
         attr_type);
2186
0
    goto fail;
2187
0
  }
2188
2189
0
  cp = base64_decode((const char *) attr, attr_len, &cp_len);
2190
0
  if (!cp) {
2191
0
    wpa_printf(MSG_DEBUG,
2192
0
         "DPP: Could not base64 decode challengePassword");
2193
0
    goto fail;
2194
0
  }
2195
0
  if (cp_len != DPP_CP_LEN) {
2196
0
    wpa_printf(MSG_DEBUG,
2197
0
         "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2198
0
         cp_len);
2199
0
    goto fail;
2200
0
  }
2201
0
  wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2202
0
      cp, cp_len);
2203
2204
  /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2205
0
  if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2206
0
          "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2207
0
    goto fail;
2208
0
  wpa_hexdump_key(MSG_DEBUG,
2209
0
      "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2210
0
      exp_cp, DPP_CP_LEN);
2211
0
  if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2212
0
    wpa_printf(MSG_DEBUG,
2213
0
         "DPP: CSR challengePassword does not match calculated cp");
2214
0
    goto fail;
2215
0
  }
2216
2217
0
  ret = 0;
2218
0
fail:
2219
0
  os_free(cp);
2220
0
  crypto_csr_deinit(csr);
2221
0
  return ret;
2222
0
}
2223
2224
2225
struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2226
               size_t csign_key_len,
2227
               const u8 *pp_key,
2228
               size_t pp_key_len)
2229
0
{
2230
0
  struct crypto_ec_key *csign = NULL, *ppkey = NULL;
2231
0
  struct dpp_reconfig_id *id = NULL;
2232
0
  struct crypto_ec *ec = NULL;
2233
0
  const struct crypto_bignum *q;
2234
0
  struct crypto_bignum *bn = NULL;
2235
0
  struct crypto_ec_point *e_id = NULL;
2236
0
  const struct crypto_ec_point *generator;
2237
2238
0
  csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
2239
0
  if (!csign)
2240
0
    goto fail;
2241
2242
0
  if (!pp_key)
2243
0
    goto fail;
2244
0
  ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
2245
0
  if (!ppkey)
2246
0
    goto fail;
2247
2248
0
  ec = crypto_ec_init(crypto_ec_key_group(csign));
2249
0
  if (!ec)
2250
0
    goto fail;
2251
2252
0
  e_id = crypto_ec_point_init(ec);
2253
0
  bn = crypto_bignum_init();
2254
0
  q = crypto_ec_get_order(ec);
2255
0
  generator = crypto_ec_get_generator(ec);
2256
0
  if (!e_id || !bn || !q || !generator ||
2257
0
      crypto_bignum_rand(bn, q) ||
2258
0
      crypto_ec_point_mul(ec, generator, bn, e_id))
2259
0
    goto fail;
2260
2261
0
  crypto_ec_point_debug_print(ec, e_id,
2262
0
            "DPP: Generated random point E-id");
2263
2264
0
  id = os_zalloc(sizeof(*id));
2265
0
  if (!id)
2266
0
    goto fail;
2267
2268
0
  id->ec = ec;
2269
0
  ec = NULL;
2270
0
  id->e_id = e_id;
2271
0
  e_id = NULL;
2272
0
  id->csign = csign;
2273
0
  csign = NULL;
2274
0
  id->pp_key = ppkey;
2275
0
  ppkey = NULL;
2276
0
fail:
2277
0
  crypto_ec_point_deinit(e_id, 1);
2278
0
  crypto_ec_key_deinit(csign);
2279
0
  crypto_ec_key_deinit(ppkey);
2280
0
  crypto_bignum_deinit(bn, 1);
2281
0
  crypto_ec_deinit(ec);
2282
0
  return id;
2283
0
}
2284
2285
2286
int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2287
0
{
2288
0
  const struct crypto_bignum *q;
2289
0
  struct crypto_bignum *bn;
2290
0
  const struct crypto_ec_point *generator;
2291
0
  struct crypto_ec_point *e_prime_id, *a_nonce, *pp;
2292
0
  int ret = -1;
2293
2294
0
  pp = crypto_ec_key_get_public_key(id->pp_key);
2295
0
  e_prime_id = crypto_ec_point_init(id->ec);
2296
0
  a_nonce = crypto_ec_point_init(id->ec);
2297
0
  bn = crypto_bignum_init();
2298
0
  q = crypto_ec_get_order(id->ec);
2299
0
  generator = crypto_ec_get_generator(id->ec);
2300
2301
  /* Generate random 0 <= a-nonce < q
2302
   * A-NONCE = a-nonce * G
2303
   * E'-id = E-id + a-nonce * P_pk */
2304
0
  if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
2305
0
      crypto_bignum_rand(bn, q) || /* bn = a-nonce */
2306
0
      crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
2307
0
      crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
2308
0
      crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
2309
0
    goto fail;
2310
2311
0
  crypto_ec_point_debug_print(id->ec, a_nonce,
2312
0
            "DPP: Generated A-NONCE");
2313
0
  crypto_ec_point_debug_print(id->ec, e_prime_id,
2314
0
            "DPP: Encrypted E-id to E'-id");
2315
2316
0
  crypto_ec_key_deinit(id->a_nonce);
2317
0
  crypto_ec_key_deinit(id->e_prime_id);
2318
0
  id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
2319
0
  id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
2320
0
  if (!id->a_nonce || !id->e_prime_id)
2321
0
    goto fail;
2322
2323
0
  ret = 0;
2324
2325
0
fail:
2326
0
  crypto_ec_point_deinit(e_prime_id, 1);
2327
0
  crypto_ec_point_deinit(a_nonce, 1);
2328
0
  crypto_ec_point_deinit(pp, 1);
2329
0
  crypto_bignum_deinit(bn, 1);
2330
0
  return ret;
2331
0
}
2332
2333
2334
void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2335
0
{
2336
0
  if (id) {
2337
0
    crypto_ec_point_deinit(id->e_id, 1);
2338
0
    crypto_ec_key_deinit(id->csign);
2339
0
    crypto_ec_key_deinit(id->a_nonce);
2340
0
    crypto_ec_key_deinit(id->e_prime_id);
2341
0
    crypto_ec_key_deinit(id->pp_key);
2342
0
    crypto_ec_deinit(id->ec);
2343
0
    os_free(id);
2344
0
  }
2345
0
}
2346
2347
2348
struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
2349
            struct crypto_ec_key *a_nonce,
2350
            struct crypto_ec_key *e_prime_id)
2351
0
{
2352
0
  struct crypto_ec *ec;
2353
0
  struct crypto_bignum *pp = NULL;
2354
0
  struct crypto_ec_point *e_id = NULL;
2355
0
  struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
2356
2357
0
  if (!ppkey)
2358
0
    return NULL;
2359
2360
  /* E-id = E'-id - s_C * A-NONCE */
2361
0
  ec = crypto_ec_init(crypto_ec_key_group(ppkey));
2362
0
  if (!ec)
2363
0
    return NULL;
2364
2365
0
  pp = crypto_ec_key_get_private_key(ppkey);
2366
0
  a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
2367
0
  e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
2368
0
  e_id = crypto_ec_point_init(ec);
2369
0
  if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
2370
0
      crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
2371
0
      crypto_ec_point_invert(ec, e_id) ||
2372
0
      crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
2373
0
    crypto_ec_point_deinit(e_id, 1);
2374
0
    goto fail;
2375
0
  }
2376
2377
0
  crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
2378
2379
0
fail:
2380
0
  crypto_ec_point_deinit(a_nonce_point, 1);
2381
0
  crypto_ec_point_deinit(e_prime_id_point, 1);
2382
0
  crypto_bignum_deinit(pp, 1);
2383
0
  crypto_ec_deinit(ec);
2384
0
  return e_id;
2385
0
}
2386
2387
#endif /* CONFIG_DPP2 */
2388
2389
2390
#ifdef CONFIG_DPP3
2391
2392
int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
2393
{
2394
  int ret = -1, res;
2395
  u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
2396
  size_t Sx_len;
2397
  unsigned int hash_len;
2398
  const char *info = "New DPP Protocol Key";
2399
  const u8 *addr[3];
2400
  size_t len[3];
2401
  u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
2402
  struct wpabuf *pcx = NULL, *pex = NULL;
2403
2404
  hash_len = auth->curve->hash_len;
2405
2406
  /*
2407
   * Configurator: S = pc * Pe
2408
   * Enrollee: S = pe * Pc
2409
   * k = HKDF(bk, "New DPP Protocol Key", S.x)
2410
   *   = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
2411
   *                 len(new-curve-hash-out))
2412
   * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)
2413
   *
2414
   * auth->own_protocol_key and auth->peer_protocol_key have already been
2415
   * updated to use the new keys. The new curve determines the size of
2416
   * the (new) protocol keys and S.x. The other parameters (bk, hash
2417
   * algorithm, k) are determined based on the initially determined curve
2418
   * during the (re)authentication exchange.
2419
   */
2420
2421
  if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2422
         Sx, &Sx_len) < 0)
2423
    goto fail;
2424
2425
  wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
2426
2427
  /* tmp = HKDF-Extract(bk, S.x) */
2428
  addr[0] = Sx;
2429
  len[0] = Sx_len;
2430
  res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp);
2431
  if (res < 0)
2432
    goto fail;
2433
  wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
2434
      tmp, hash_len);
2435
  /* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output))
2436
   */
2437
  res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
2438
  if (res < 0)
2439
    return -1;
2440
2441
  wpa_hexdump_key(MSG_DEBUG,
2442
      "DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
2443
      k, hash_len);
2444
2445
  /* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */
2446
  addr[0] = auth->e_nonce;
2447
  len[0] = auth->curve->nonce_len;
2448
2449
  if (auth->configurator) {
2450
    pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2451
    pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2452
                 0);
2453
  } else {
2454
    pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2455
                 0);
2456
    pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2457
  }
2458
  if (!pcx || !pex)
2459
    goto fail;
2460
  addr[1] = wpabuf_head(pcx);
2461
  len[1] = wpabuf_len(pcx) / 2;
2462
  addr[2] = wpabuf_head(pex);
2463
  len[2] = wpabuf_len(pex) / 2;
2464
2465
  if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0)
2466
    goto fail;
2467
  wpa_hexdump_key(MSG_DEBUG,
2468
      "DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)",
2469
      auth_i, hash_len);
2470
  ret = 0;
2471
fail:
2472
  forced_memzero(Sx, sizeof(Sx));
2473
  forced_memzero(tmp, sizeof(tmp));
2474
  forced_memzero(k, sizeof(k));
2475
  wpabuf_free(pcx);
2476
  wpabuf_free(pex);
2477
  return ret;
2478
}
2479
2480
2481
int dpp_hpke_suite(int iana_group, enum hpke_kem_id *kem_id,
2482
       enum hpke_kdf_id *kdf_id, enum hpke_aead_id *aead_id)
2483
{
2484
  switch (iana_group) {
2485
  case 19:
2486
    *kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2487
    *kdf_id = HPKE_KDF_HKDF_SHA256;
2488
    *aead_id = HPKE_AEAD_AES_128_GCM;
2489
    return 0;
2490
  case 20:
2491
    *kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2492
    *kdf_id = HPKE_KDF_HKDF_SHA384;
2493
    *aead_id = HPKE_AEAD_AES_256_GCM;
2494
    return 0;
2495
  case 21:
2496
    *kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2497
    *kdf_id = HPKE_KDF_HKDF_SHA512;
2498
    *aead_id = HPKE_AEAD_AES_256_GCM;
2499
    return 0;
2500
  case 28:
2501
    *kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2502
    *kdf_id = HPKE_KDF_HKDF_SHA256;
2503
    *aead_id = HPKE_AEAD_AES_128_GCM;
2504
    return 0;
2505
  case 29:
2506
    *kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2507
    *kdf_id = HPKE_KDF_HKDF_SHA384;
2508
    *aead_id = HPKE_AEAD_AES_256_GCM;
2509
    return 0;
2510
  case 30:
2511
    *kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2512
    *kdf_id = HPKE_KDF_HKDF_SHA512;
2513
    *aead_id = HPKE_AEAD_AES_256_GCM;
2514
    return 0;
2515
  }
2516
2517
  return -1;
2518
}
2519
2520
#endif /* CONFIG_DPP3 */
2521
2522
2523
#ifdef CONFIG_TESTING_OPTIONS
2524
2525
int dpp_test_gen_invalid_key(struct wpabuf *msg,
2526
           const struct dpp_curve_params *curve)
2527
{
2528
  struct crypto_ec *ec;
2529
  struct crypto_ec_key *key = NULL;
2530
  struct crypto_ec_point *p = NULL, *pub_key = NULL;
2531
  u8 *x, *y;
2532
  int ret = -1;
2533
2534
  ec = crypto_ec_init(curve->ike_group);
2535
  x = wpabuf_put(msg, curve->prime_len);
2536
  y = wpabuf_put(msg, curve->prime_len);
2537
  if (!ec)
2538
    goto fail;
2539
2540
retry:
2541
  /* Generate valid key pair */
2542
  key = crypto_ec_key_gen(curve->ike_group);
2543
  if (!key)
2544
    goto fail;
2545
2546
  /* Retrieve public key coordinates */
2547
  pub_key = crypto_ec_key_get_public_key(key);
2548
  if (!pub_key || crypto_ec_point_to_bin(ec, pub_key, x, y))
2549
    goto fail;
2550
2551
  /* And corrupt them */
2552
  y[curve->prime_len - 1] ^= 0x01;
2553
  p = crypto_ec_point_from_bin(ec, x);
2554
  if (p && crypto_ec_point_is_on_curve(ec, p)) {
2555
    crypto_ec_point_deinit(p, 0);
2556
    p = NULL;
2557
    goto retry;
2558
  }
2559
2560
  ret = 0;
2561
fail:
2562
  crypto_ec_point_deinit(p, 0);
2563
  crypto_ec_point_deinit(pub_key, 0);
2564
  crypto_ec_key_deinit(key);
2565
  crypto_ec_deinit(ec);
2566
  return ret;
2567
}
2568
2569
2570
char * dpp_corrupt_connector_signature(const char *connector)
2571
{
2572
  char *tmp, *pos, *signed3 = NULL;
2573
  unsigned char *signature = NULL;
2574
  size_t signature_len = 0, signed3_len;
2575
2576
  tmp = os_zalloc(os_strlen(connector) + 5);
2577
  if (!tmp)
2578
    goto fail;
2579
  os_memcpy(tmp, connector, os_strlen(connector));
2580
2581
  pos = os_strchr(tmp, '.');
2582
  if (!pos)
2583
    goto fail;
2584
2585
  pos = os_strchr(pos + 1, '.');
2586
  if (!pos)
2587
    goto fail;
2588
  pos++;
2589
2590
  wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2591
       pos);
2592
  signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2593
  if (!signature || signature_len == 0)
2594
    goto fail;
2595
  wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2596
        signature, signature_len);
2597
  signature[signature_len - 1] ^= 0x01;
2598
  wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2599
        signature, signature_len);
2600
  signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2601
  if (!signed3)
2602
    goto fail;
2603
  os_memcpy(pos, signed3, signed3_len);
2604
  pos[signed3_len] = '\0';
2605
  wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2606
       pos);
2607
2608
out:
2609
  os_free(signature);
2610
  os_free(signed3);
2611
  return tmp;
2612
fail:
2613
  os_free(tmp);
2614
  tmp = NULL;
2615
  goto out;
2616
}
2617
2618
#endif /* CONFIG_TESTING_OPTIONS */