blob: fb239f7729cde70bb295af3dd62f5934a073a1c9 [file] [log] [blame]
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001/*
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"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070011
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"
Hai Shalom899fcc72020-10-19 14:38:18 -070017#include "crypto/random.h"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070018#include "crypto/sha384.h"
19#include "crypto/sha512.h"
Hai Shaloma20dcd72022-02-04 13:43:00 -080020#include "tls/asn1.h"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070021#include "dpp.h"
22#include "dpp_i.h"
23
24
Hai Shalom4fbc08f2020-05-18 12:37:00 -070025static 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
38const struct dpp_curve_params * dpp_get_curve_name(const char *name)
39{
40 int i;
41
42 if (!name)
43 return &dpp_curves[0];
44
45 for (i = 0; dpp_curves[i].name; i++) {
46 if (os_strcmp(name, dpp_curves[i].name) == 0 ||
47 (dpp_curves[i].jwk_crv &&
48 os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
49 return &dpp_curves[i];
50 }
51 return NULL;
52}
53
54
55const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name)
56{
57 int i;
58
59 for (i = 0; dpp_curves[i].name; i++) {
60 if (dpp_curves[i].jwk_crv &&
61 os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
62 return &dpp_curves[i];
63 }
64 return NULL;
65}
66
67
Hai Shalom899fcc72020-10-19 14:38:18 -070068const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
69{
70 int i;
71
72 for (i = 0; dpp_curves[i].name; i++) {
73 if (dpp_curves[i].ike_group == group)
74 return &dpp_curves[i];
75 }
76 return NULL;
77}
78
79
Hai Shaloma20dcd72022-02-04 13:43:00 -080080void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -070081{
Hai Shaloma20dcd72022-02-04 13:43:00 -080082 struct wpabuf *der = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070083
Hai Shaloma20dcd72022-02-04 13:43:00 -080084 crypto_ec_key_debug_print(key, title);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070085
Hai Shaloma20dcd72022-02-04 13:43:00 -080086 der = crypto_ec_key_get_ecprivate_key(key, true);
87 if (der) {
88 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
89 } else {
90 der = crypto_ec_key_get_subject_public_key(key);
91 if (der)
92 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070093 }
94
Hai Shaloma20dcd72022-02-04 13:43:00 -080095 wpabuf_clear_free(der);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070096}
97
98
99static 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{
103 if (curve->hash_len == 32)
104 return sha256_vector(num_elem, addr, len, mac);
105 if (curve->hash_len == 48)
106 return sha384_vector(num_elem, addr, len, mac);
107 if (curve->hash_len == 64)
108 return sha512_vector(num_elem, addr, len, mac);
109 return -1;
110}
111
112
113int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
114 const char *label, u8 *out, size_t outlen)
115{
116 if (hash_len == 32)
117 return hmac_sha256_kdf(secret, secret_len, NULL,
118 (const u8 *) label, os_strlen(label),
119 out, outlen);
120 if (hash_len == 48)
121 return hmac_sha384_kdf(secret, secret_len, NULL,
122 (const u8 *) label, os_strlen(label),
123 out, outlen);
124 if (hash_len == 64)
125 return hmac_sha512_kdf(secret, secret_len, NULL,
126 (const u8 *) label, os_strlen(label),
127 out, outlen);
128 return -1;
129}
130
131
132int 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{
136 if (hash_len == 32)
137 return hmac_sha256_vector(key, key_len, num_elem, addr, len,
138 mac);
139 if (hash_len == 48)
140 return hmac_sha384_vector(key, key_len, num_elem, addr, len,
141 mac);
142 if (hash_len == 64)
143 return hmac_sha512_vector(key, key_len, num_elem, addr, len,
144 mac);
145 return -1;
146}
147
148
149static 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{
152 if (hash_len == 32)
153 return hmac_sha256(key, key_len, data, data_len, mac);
154 if (hash_len == 48)
155 return hmac_sha384(key, key_len, data, data_len, mac);
156 if (hash_len == 64)
157 return hmac_sha512(key, key_len, data, data_len, mac);
158 return -1;
159}
160
161
162#ifdef CONFIG_DPP2
163
164static 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{
169 unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN];
170 unsigned int i;
171 size_t j;
172 u8 count_buf[4];
173 const u8 *addr[2];
174 size_t len[2];
175
176 addr[0] = salt;
177 len[0] = salt_len;
178 addr[1] = count_buf;
179 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 WPA_PUT_BE32(count_buf, count);
188 if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len,
189 tmp))
190 return -1;
191 os_memcpy(digest, tmp, hash_len);
192
193 for (i = 1; i < iterations; i++) {
194 if (dpp_hmac(hash_len, password, password_len, tmp, hash_len,
195 tmp2))
196 return -1;
197 os_memcpy(tmp, tmp2, hash_len);
198 for (j = 0; j < hash_len; j++)
199 digest[j] ^= tmp2[j];
200 }
201
202 return 0;
203}
204
205
206int 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{
210 unsigned int count = 0;
211 unsigned char *pos = buf;
212 size_t left = buflen, plen;
213 unsigned char digest[DPP_MAX_HASH_LEN];
214
215 while (left > 0) {
216 count++;
217 if (dpp_pbkdf2_f(hash_len, password, password_len,
218 salt, salt_len, iterations, count, digest))
219 return -1;
220 plen = left > hash_len ? hash_len : left;
221 os_memcpy(pos, digest, plen);
222 pos += plen;
223 left -= plen;
224 }
225
226 return 0;
227}
228
229#endif /* CONFIG_DPP2 */
230
231
Hai Shaloma20dcd72022-02-04 13:43:00 -0800232struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
233 const u8 *buf, size_t len)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700234{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800235 int ike_group = crypto_ec_key_group(group_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700236
237 if (len & 1)
238 return NULL;
239
Hai Shaloma20dcd72022-02-04 13:43:00 -0800240 if (ike_group < 0) {
241 wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700242 return NULL;
243 }
244
Hai Shaloma20dcd72022-02-04 13:43:00 -0800245 return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700246}
247
248
Hai Shaloma20dcd72022-02-04 13:43:00 -0800249struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700250{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800251 struct crypto_ec_key *key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700252
253 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
254
Hai Shaloma20dcd72022-02-04 13:43:00 -0800255 key = crypto_ec_key_gen(curve->ike_group);
256 if (key && wpa_debug_show_keys)
257 dpp_debug_print_key("Own generated key", key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700258
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700259 return key;
260}
261
262
Hai Shaloma20dcd72022-02-04 13:43:00 -0800263struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
264 const u8 *privkey, size_t privkey_len)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700265{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800266 struct crypto_ec_key *key;
267 int group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700268
Hai Shaloma20dcd72022-02-04 13:43:00 -0800269 key = crypto_ec_key_parse_priv(privkey, privkey_len);
270 if (!key) {
271 wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700272 return NULL;
273 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800274
275 group = crypto_ec_key_group(key);
276 if (group < 0) {
277 crypto_ec_key_deinit(key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700278 return NULL;
279 }
Hai Shaloma20dcd72022-02-04 13:43:00 -0800280
281 *curve = dpp_get_curve_ike_group(group);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700282 if (!*curve) {
283 wpa_printf(MSG_INFO,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800284 "DPP: Unsupported curve (group=%d) in pre-assigned key",
285 group);
286 crypto_ec_key_deinit(key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700287 return NULL;
288 }
289
Hai Shaloma20dcd72022-02-04 13:43:00 -0800290 return key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700291}
292
293
294int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
295{
296 struct wpabuf *der;
297 int res;
298
Hai Shaloma20dcd72022-02-04 13:43:00 -0800299 der = crypto_ec_key_get_subject_public_key(bi->pubkey);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700300 if (!der)
301 return -1;
302 wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
303 der);
304 res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
305 if (res < 0)
306 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
307 wpabuf_free(der);
308 return res;
309}
310
311
312int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
313 const u8 *privkey, size_t privkey_len)
314{
315 char *base64 = NULL;
316 char *pos, *end;
317 size_t len;
318 struct wpabuf *der = NULL;
319
320 bi->curve = dpp_get_curve_name(curve);
321 if (!bi->curve) {
322 wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
323 return -1;
324 }
325
326 if (privkey)
327 bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
328 else
329 bi->pubkey = dpp_gen_keypair(bi->curve);
330 if (!bi->pubkey)
331 goto fail;
332 bi->own = 1;
333
Hai Shaloma20dcd72022-02-04 13:43:00 -0800334 der = crypto_ec_key_get_subject_public_key(bi->pubkey);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700335 if (!der)
336 goto fail;
337 wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
338 der);
339
340 if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
341 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
342 goto fail;
343 }
344
345 base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
346 wpabuf_free(der);
347 der = NULL;
348 if (!base64)
349 goto fail;
350 pos = base64;
351 end = pos + len;
352 for (;;) {
353 pos = os_strchr(pos, '\n');
354 if (!pos)
355 break;
356 os_memmove(pos, pos + 1, end - pos);
357 }
358 os_free(bi->pk);
359 bi->pk = base64;
360 return 0;
361fail:
362 os_free(base64);
363 wpabuf_free(der);
364 return -1;
365}
366
367
368int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len)
369{
370 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
371 const char *info = "first intermediate key";
372 int res;
373
374 /* k1 = HKDF(<>, "first intermediate key", M.x) */
375
376 /* HKDF-Extract(<>, M.x) */
377 os_memset(salt, 0, hash_len);
378 if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
379 return -1;
380 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
381 prk, hash_len);
382
383 /* HKDF-Expand(PRK, info, L) */
384 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
385 os_memset(prk, 0, hash_len);
386 if (res < 0)
387 return -1;
388
389 wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
390 k1, hash_len);
391 return 0;
392}
393
394
395int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len)
396{
397 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
398 const char *info = "second intermediate key";
399 int res;
400
401 /* k2 = HKDF(<>, "second intermediate key", N.x) */
402
403 /* HKDF-Extract(<>, N.x) */
404 os_memset(salt, 0, hash_len);
405 res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
406 if (res < 0)
407 return -1;
408 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
409 prk, hash_len);
410
411 /* HKDF-Expand(PRK, info, L) */
412 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
413 os_memset(prk, 0, hash_len);
414 if (res < 0)
415 return -1;
416
417 wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
418 k2, hash_len);
419 return 0;
420}
421
422
423int dpp_derive_bk_ke(struct dpp_authentication *auth)
424{
425 unsigned int hash_len = auth->curve->hash_len;
426 size_t nonce_len = auth->curve->nonce_len;
427 u8 nonces[2 * DPP_MAX_NONCE_LEN];
428 const char *info_ke = "DPP Key";
429 int res;
430 const u8 *addr[3];
431 size_t len[3];
432 size_t num_elem = 0;
433
434 if (!auth->Mx_len || !auth->Nx_len) {
435 wpa_printf(MSG_DEBUG,
436 "DPP: Mx/Nx not available - cannot derive ke");
437 return -1;
438 }
439
440 /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
441 os_memcpy(nonces, auth->i_nonce, nonce_len);
442 os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
443 addr[num_elem] = auth->Mx;
444 len[num_elem] = auth->Mx_len;
445 num_elem++;
446 addr[num_elem] = auth->Nx;
447 len[num_elem] = auth->Nx_len;
448 num_elem++;
449 if (auth->peer_bi && auth->own_bi) {
450 if (!auth->Lx_len) {
451 wpa_printf(MSG_DEBUG,
452 "DPP: Lx not available - cannot derive ke");
453 return -1;
454 }
455 addr[num_elem] = auth->Lx;
456 len[num_elem] = auth->secret_len;
457 num_elem++;
458 }
459 res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
460 num_elem, addr, len, auth->bk);
461 if (res < 0)
462 return -1;
463 wpa_hexdump_key(MSG_DEBUG,
464 "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])",
465 auth->bk, hash_len);
466
Hai Shalom899fcc72020-10-19 14:38:18 -0700467 /* ke = HKDF-Expand(bk, "DPP Key", length) */
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700468 res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke,
469 hash_len);
470 if (res < 0)
471 return -1;
472
473 wpa_hexdump_key(MSG_DEBUG,
474 "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)",
475 auth->ke, hash_len);
476
477 return 0;
478}
479
480
Hai Shaloma20dcd72022-02-04 13:43:00 -0800481int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
482 u8 *secret, size_t *secret_len)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700483{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800484 struct crypto_ecdh *ecdh;
485 struct wpabuf *peer_pub, *secret_buf = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700486 int ret = -1;
487
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700488 *secret_len = 0;
489
Hai Shaloma20dcd72022-02-04 13:43:00 -0800490 ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
491 if (!ecdh) {
492 wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700493 return -1;
494 }
495
Hai Shaloma20dcd72022-02-04 13:43:00 -0800496 peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
497 if (!peer_pub) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700498 wpa_printf(MSG_ERROR,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800499 "DPP: crypto_ec_key_get_pubkey_point() failed");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700500 goto fail;
501 }
502
Hai Shaloma20dcd72022-02-04 13:43:00 -0800503 secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
504 wpabuf_len(peer_pub));
505 if (!secret_buf) {
506 wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700507 goto fail;
508 }
509
Hai Shaloma20dcd72022-02-04 13:43:00 -0800510 if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
511 wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700512 goto fail;
513 }
514
Hai Shaloma20dcd72022-02-04 13:43:00 -0800515 *secret_len = wpabuf_len(secret_buf);
516 os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700517 ret = 0;
518
519fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -0800520 wpabuf_clear_free(secret_buf);
521 wpabuf_free(peer_pub);
522 crypto_ecdh_deinit(ecdh);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700523 return ret;
524}
525
526
527int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
528 const u8 *data, size_t data_len)
529{
530 const u8 *addr[2];
531 size_t len[2];
532
533 addr[0] = data;
534 len[0] = data_len;
535 if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
536 return -1;
537 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
538 bi->pubkey_hash, SHA256_MAC_LEN);
539
540 addr[0] = (const u8 *) "chirp";
541 len[0] = 5;
542 addr[1] = data;
543 len[1] = data_len;
544 if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
545 return -1;
546 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
547 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
548
549 return 0;
550}
551
552
553int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
554 const u8 *data, size_t data_len)
555{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800556 struct crypto_ec_key *key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700557
558 if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
559 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
560 return -1;
561 }
562
Hai Shaloma20dcd72022-02-04 13:43:00 -0800563 key = crypto_ec_key_parse_pub(data, data_len);
564 if (!key) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700565 wpa_printf(MSG_DEBUG,
566 "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
567 return -1;
568 }
569
Hai Shaloma20dcd72022-02-04 13:43:00 -0800570 bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700571 if (!bi->curve) {
572 wpa_printf(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800573 "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
574 crypto_ec_key_group(key));
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700575 goto fail;
576 }
577
Hai Shaloma20dcd72022-02-04 13:43:00 -0800578 bi->pubkey = key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700579 return 0;
580fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -0800581 crypto_ec_key_deinit(key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700582 return -1;
583}
584
585
586static struct wpabuf *
587dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
588 const u8 *prot_hdr, u16 prot_hdr_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800589 int *hash_func)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700590{
591 struct json_token *root, *token;
592 struct wpabuf *kid = NULL;
593
594 root = json_parse((const char *) prot_hdr, prot_hdr_len);
595 if (!root) {
596 wpa_printf(MSG_DEBUG,
597 "DPP: JSON parsing failed for JWS Protected Header");
598 goto fail;
599 }
600
601 if (root->type != JSON_OBJECT) {
602 wpa_printf(MSG_DEBUG,
603 "DPP: JWS Protected Header root is not an object");
604 goto fail;
605 }
606
607 token = json_get_member(root, "typ");
608 if (!token || token->type != JSON_STRING) {
609 wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
610 goto fail;
611 }
612 wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
613 token->string);
614 if (os_strcmp(token->string, "dppCon") != 0) {
615 wpa_printf(MSG_DEBUG,
616 "DPP: Unsupported JWS Protected Header typ=%s",
617 token->string);
618 goto fail;
619 }
620
621 token = json_get_member(root, "alg");
622 if (!token || token->type != JSON_STRING) {
623 wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
624 goto fail;
625 }
626 wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
627 token->string);
628 if (os_strcmp(token->string, curve->jws_alg) != 0) {
629 wpa_printf(MSG_DEBUG,
630 "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
631 token->string, curve->jws_alg);
632 goto fail;
633 }
634 if (os_strcmp(token->string, "ES256") == 0 ||
Hai Shaloma20dcd72022-02-04 13:43:00 -0800635 os_strcmp(token->string, "BS256") == 0) {
636 *hash_func = CRYPTO_HASH_ALG_SHA256;
637 } else if (os_strcmp(token->string, "ES384") == 0 ||
638 os_strcmp(token->string, "BS384") == 0) {
639 *hash_func = CRYPTO_HASH_ALG_SHA384;
640 } else if (os_strcmp(token->string, "ES512") == 0 ||
641 os_strcmp(token->string, "BS512") == 0) {
642 *hash_func = CRYPTO_HASH_ALG_SHA512;
643 } else {
644 *hash_func = -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700645 wpa_printf(MSG_DEBUG,
646 "DPP: Unsupported JWS Protected Header alg=%s",
647 token->string);
648 goto fail;
649 }
650
651 kid = json_get_member_base64url(root, "kid");
652 if (!kid) {
653 wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
654 goto fail;
655 }
656 wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
657 kid);
658
659fail:
660 json_free(root);
661 return kid;
662}
663
664
Hai Shaloma20dcd72022-02-04 13:43:00 -0800665static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
666 struct wpabuf *r_hash)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700667{
668 struct wpabuf *uncomp;
669 int res;
670 u8 hash[SHA256_MAC_LEN];
671 const u8 *addr[1];
672 size_t len[1];
673
674 if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
675 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800676 uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700677 if (!uncomp)
678 return -1;
679 addr[0] = wpabuf_head(uncomp);
680 len[0] = wpabuf_len(uncomp);
681 wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
682 addr[0], len[0]);
683 res = sha256_vector(1, addr, len, hash);
684 wpabuf_free(uncomp);
685 if (res < 0)
686 return -1;
687 if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
688 wpa_printf(MSG_DEBUG,
689 "DPP: Received hash value does not match calculated public key hash value");
690 wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
691 hash, SHA256_MAC_LEN);
692 return -1;
693 }
694 return 0;
695}
696
697
698enum dpp_status_error
699dpp_process_signed_connector(struct dpp_signed_connector_info *info,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800700 struct crypto_ec_key *csign_pub,
701 const char *connector)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700702{
703 enum dpp_status_error ret = 255;
704 const char *pos, *end, *signed_start, *signed_end;
705 struct wpabuf *kid = NULL;
706 unsigned char *prot_hdr = NULL, *signature = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800707 size_t prot_hdr_len = 0, signature_len = 0, signed_len;
708 int res, hash_func = -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700709 const struct dpp_curve_params *curve;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800710 u8 *hash = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700711
Hai Shaloma20dcd72022-02-04 13:43:00 -0800712 curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700713 if (!curve)
714 goto fail;
715 wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
716 os_memset(info, 0, sizeof(*info));
717
718 signed_start = pos = connector;
719 end = os_strchr(pos, '.');
720 if (!end) {
721 wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
722 ret = DPP_STATUS_INVALID_CONNECTOR;
723 goto fail;
724 }
725 prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
726 if (!prot_hdr) {
727 wpa_printf(MSG_DEBUG,
728 "DPP: Failed to base64url decode signedConnector JWS Protected Header");
729 ret = DPP_STATUS_INVALID_CONNECTOR;
730 goto fail;
731 }
732 wpa_hexdump_ascii(MSG_DEBUG,
733 "DPP: signedConnector - JWS Protected Header",
734 prot_hdr, prot_hdr_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800735 kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700736 if (!kid) {
737 ret = DPP_STATUS_INVALID_CONNECTOR;
738 goto fail;
739 }
740 if (wpabuf_len(kid) != SHA256_MAC_LEN) {
741 wpa_printf(MSG_DEBUG,
742 "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
743 (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
744 ret = DPP_STATUS_INVALID_CONNECTOR;
745 goto fail;
746 }
747
748 pos = end + 1;
749 end = os_strchr(pos, '.');
750 if (!end) {
751 wpa_printf(MSG_DEBUG,
752 "DPP: Missing dot(2) in signedConnector");
753 ret = DPP_STATUS_INVALID_CONNECTOR;
754 goto fail;
755 }
756 signed_end = end - 1;
757 info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
758 if (!info->payload) {
759 wpa_printf(MSG_DEBUG,
760 "DPP: Failed to base64url decode signedConnector JWS Payload");
761 ret = DPP_STATUS_INVALID_CONNECTOR;
762 goto fail;
763 }
764 wpa_hexdump_ascii(MSG_DEBUG,
765 "DPP: signedConnector - JWS Payload",
766 info->payload, info->payload_len);
767 pos = end + 1;
768 signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
769 if (!signature) {
770 wpa_printf(MSG_DEBUG,
771 "DPP: Failed to base64url decode signedConnector signature");
772 ret = DPP_STATUS_INVALID_CONNECTOR;
773 goto fail;
774 }
775 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
776 signature, signature_len);
777
778 if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
779 ret = DPP_STATUS_NO_MATCH;
780 goto fail;
781 }
782
783 if (signature_len & 0x01) {
784 wpa_printf(MSG_DEBUG,
785 "DPP: Unexpected signedConnector signature length (%d)",
786 (int) signature_len);
787 ret = DPP_STATUS_INVALID_CONNECTOR;
788 goto fail;
789 }
790
Hai Shaloma20dcd72022-02-04 13:43:00 -0800791 hash = os_malloc(curve->hash_len);
792 if (!hash)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700793 goto fail;
794
Hai Shaloma20dcd72022-02-04 13:43:00 -0800795 signed_len = signed_end - signed_start + 1;
796 if (hash_func == CRYPTO_HASH_ALG_SHA256)
797 res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
798 hash);
799 else if (hash_func == CRYPTO_HASH_ALG_SHA384)
800 res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
801 hash);
802 else if (hash_func == CRYPTO_HASH_ALG_SHA512)
803 res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
804 hash);
805 else
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700806 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800807
808 if (res)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700809 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800810
811 res = crypto_ec_key_verify_signature_r_s(csign_pub,
812 hash, curve->hash_len,
813 signature, signature_len / 2,
814 signature + signature_len / 2,
815 signature_len / 2);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700816 if (res != 1) {
817 wpa_printf(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800818 "DPP: signedConnector signature check failed (res=%d)",
819 res);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700820 ret = DPP_STATUS_INVALID_CONNECTOR;
821 goto fail;
822 }
823
824 ret = DPP_STATUS_OK;
825fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -0800826 os_free(hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700827 os_free(prot_hdr);
828 wpabuf_free(kid);
829 os_free(signature);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700830 return ret;
831}
832
833
834enum dpp_status_error
835dpp_check_signed_connector(struct dpp_signed_connector_info *info,
836 const u8 *csign_key, size_t csign_key_len,
837 const u8 *peer_connector, size_t peer_connector_len)
838{
Hai Shaloma20dcd72022-02-04 13:43:00 -0800839 struct crypto_ec_key *csign;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700840 char *signed_connector = NULL;
841 enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
842
Hai Shaloma20dcd72022-02-04 13:43:00 -0800843 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700844 if (!csign) {
845 wpa_printf(MSG_ERROR,
846 "DPP: Failed to parse local C-sign-key information");
847 goto fail;
848 }
849
850 wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
851 peer_connector, peer_connector_len);
852 signed_connector = os_malloc(peer_connector_len + 1);
853 if (!signed_connector)
854 goto fail;
855 os_memcpy(signed_connector, peer_connector, peer_connector_len);
856 signed_connector[peer_connector_len] = '\0';
857 res = dpp_process_signed_connector(info, csign, signed_connector);
858fail:
859 os_free(signed_connector);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800860 crypto_ec_key_deinit(csign);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700861 return res;
862}
863
864
865int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
866{
867 struct wpabuf *pix, *prx, *bix, *brx;
868 const u8 *addr[7];
869 size_t len[7];
870 size_t i, num_elem = 0;
871 size_t nonce_len;
872 u8 zero = 0;
873 int res = -1;
874
875 /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
876 nonce_len = auth->curve->nonce_len;
877
878 if (auth->initiator) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800879 pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
880 prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
881 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700882 if (auth->own_bi)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800883 bix = crypto_ec_key_get_pubkey_point(
884 auth->own_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700885 else
886 bix = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800887 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700888 } else {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800889 pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
890 0);
891 prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700892 if (auth->peer_bi)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800893 bix = crypto_ec_key_get_pubkey_point(
894 auth->peer_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700895 else
896 bix = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800897 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700898 }
899 if (!pix || !prx || !brx)
900 goto fail;
901
902 addr[num_elem] = auth->i_nonce;
903 len[num_elem] = nonce_len;
904 num_elem++;
905
906 addr[num_elem] = auth->r_nonce;
907 len[num_elem] = nonce_len;
908 num_elem++;
909
910 addr[num_elem] = wpabuf_head(pix);
911 len[num_elem] = wpabuf_len(pix) / 2;
912 num_elem++;
913
914 addr[num_elem] = wpabuf_head(prx);
915 len[num_elem] = wpabuf_len(prx) / 2;
916 num_elem++;
917
918 if (bix) {
919 addr[num_elem] = wpabuf_head(bix);
920 len[num_elem] = wpabuf_len(bix) / 2;
921 num_elem++;
922 }
923
924 addr[num_elem] = wpabuf_head(brx);
925 len[num_elem] = wpabuf_len(brx) / 2;
926 num_elem++;
927
928 addr[num_elem] = &zero;
929 len[num_elem] = 1;
930 num_elem++;
931
932 wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
933 for (i = 0; i < num_elem; i++)
934 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
935 res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
936 if (res == 0)
937 wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
938 auth->curve->hash_len);
939fail:
940 wpabuf_free(pix);
941 wpabuf_free(prx);
942 wpabuf_free(bix);
943 wpabuf_free(brx);
944 return res;
945}
946
947
948int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
949{
950 struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
951 const u8 *addr[7];
952 size_t len[7];
953 size_t i, num_elem = 0;
954 size_t nonce_len;
955 u8 one = 1;
956 int res = -1;
957
958 /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
959 nonce_len = auth->curve->nonce_len;
960
961 if (auth->initiator) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800962 pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
963 prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
964 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700965 if (auth->own_bi)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800966 bix = crypto_ec_key_get_pubkey_point(
967 auth->own_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700968 else
969 bix = NULL;
970 if (!auth->peer_bi)
971 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800972 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700973 } else {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800974 pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
975 0);
976 prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700977 if (auth->peer_bi)
Hai Shaloma20dcd72022-02-04 13:43:00 -0800978 bix = crypto_ec_key_get_pubkey_point(
979 auth->peer_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700980 else
981 bix = NULL;
982 if (!auth->own_bi)
983 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800984 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700985 }
986 if (!pix || !prx || !brx)
987 goto fail;
988
989 addr[num_elem] = auth->r_nonce;
990 len[num_elem] = nonce_len;
991 num_elem++;
992
993 addr[num_elem] = auth->i_nonce;
994 len[num_elem] = nonce_len;
995 num_elem++;
996
997 addr[num_elem] = wpabuf_head(prx);
998 len[num_elem] = wpabuf_len(prx) / 2;
999 num_elem++;
1000
1001 addr[num_elem] = wpabuf_head(pix);
1002 len[num_elem] = wpabuf_len(pix) / 2;
1003 num_elem++;
1004
1005 addr[num_elem] = wpabuf_head(brx);
1006 len[num_elem] = wpabuf_len(brx) / 2;
1007 num_elem++;
1008
1009 if (bix) {
1010 addr[num_elem] = wpabuf_head(bix);
1011 len[num_elem] = wpabuf_len(bix) / 2;
1012 num_elem++;
1013 }
1014
1015 addr[num_elem] = &one;
1016 len[num_elem] = 1;
1017 num_elem++;
1018
1019 wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1020 for (i = 0; i < num_elem; i++)
1021 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1022 res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1023 if (res == 0)
1024 wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1025 auth->curve->hash_len);
1026fail:
1027 wpabuf_free(pix);
1028 wpabuf_free(prx);
1029 wpabuf_free(bix);
1030 wpabuf_free(brx);
1031 return res;
1032}
1033
1034
1035int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1036{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001037 struct crypto_ec *ec;
Sunil8cd6f4d2022-06-28 18:40:46 +00001038 struct crypto_ec_point *L = NULL, *BI = NULL;
1039 const struct crypto_bignum *q;
1040 struct crypto_bignum *sum = NULL, *lx = NULL, *bR = NULL, *pR = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001041 int ret = -1;
1042
1043 /* L = ((bR + pR) modulo q) * BI */
1044
Hai Shaloma20dcd72022-02-04 13:43:00 -08001045 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1046 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001047 goto fail;
1048
Hai Shaloma20dcd72022-02-04 13:43:00 -08001049 q = crypto_ec_get_order(ec);
1050 BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1051 bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1052 pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1053 sum = crypto_bignum_init();
1054 L = crypto_ec_point_init(ec);
1055 lx = crypto_bignum_init();
1056 if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
1057 crypto_bignum_addmod(bR, pR, q, sum) ||
1058 crypto_ec_point_mul(ec, BI, sum, L) ||
1059 crypto_ec_point_x(ec, L, lx) ||
1060 crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1061 auth->secret_len) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001062 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001063
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001064 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1065 auth->Lx_len = auth->secret_len;
1066 ret = 0;
1067fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001068 crypto_bignum_deinit(lx, 1);
1069 crypto_bignum_deinit(sum, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001070 crypto_bignum_deinit(bR, 1);
1071 crypto_bignum_deinit(pR, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001072 crypto_ec_point_deinit(L, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001073 crypto_ec_point_deinit(BI, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001074 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001075 return ret;
1076}
1077
1078
1079int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1080{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001081 struct crypto_ec *ec;
Sunil8cd6f4d2022-06-28 18:40:46 +00001082 struct crypto_ec_point *L = NULL, *sum = NULL, *BR = NULL, *PR = NULL;
1083 struct crypto_bignum *lx = NULL, *bI = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001084 int ret = -1;
1085
1086 /* L = bI * (BR + PR) */
1087
Hai Shaloma20dcd72022-02-04 13:43:00 -08001088 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1089 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001090 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001091
Hai Shaloma20dcd72022-02-04 13:43:00 -08001092 BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1093 PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1094 bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1095 sum = crypto_ec_point_init(ec);
1096 L = crypto_ec_point_init(ec);
1097 lx = crypto_bignum_init();
1098 if (!BR || !PR || !bI || !sum || !L || !lx ||
1099 crypto_ec_point_add(ec, BR, PR, sum) ||
1100 crypto_ec_point_mul(ec, sum, bI, L) ||
1101 crypto_ec_point_x(ec, L, lx) ||
1102 crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1103 auth->secret_len) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001104 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001105
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001106 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1107 auth->Lx_len = auth->secret_len;
1108 ret = 0;
1109fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001110 crypto_bignum_deinit(lx, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001111 crypto_bignum_deinit(bI, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001112 crypto_ec_point_deinit(sum, 1);
1113 crypto_ec_point_deinit(L, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001114 crypto_ec_point_deinit(BR, 1);
1115 crypto_ec_point_deinit(PR, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001116 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001117 return ret;
1118}
1119
1120
1121int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1122{
1123 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1124 const char *info = "DPP PMK";
1125 int res;
1126
1127 /* PMK = HKDF(<>, "DPP PMK", N.x) */
1128
1129 /* HKDF-Extract(<>, N.x) */
1130 os_memset(salt, 0, hash_len);
1131 if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1132 return -1;
1133 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1134 prk, hash_len);
1135
1136 /* HKDF-Expand(PRK, info, L) */
1137 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1138 os_memset(prk, 0, hash_len);
1139 if (res < 0)
1140 return -1;
1141
1142 wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1143 pmk, hash_len);
1144 return 0;
1145}
1146
1147
1148int dpp_derive_pmkid(const struct dpp_curve_params *curve,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001149 struct crypto_ec_key *own_key,
1150 struct crypto_ec_key *peer_key, u8 *pmkid)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001151{
1152 struct wpabuf *nkx, *pkx;
1153 int ret = -1, res;
1154 const u8 *addr[2];
1155 size_t len[2];
1156 u8 hash[SHA256_MAC_LEN];
1157
1158 /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001159 nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
1160 pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001161 if (!nkx || !pkx)
1162 goto fail;
1163 addr[0] = wpabuf_head(nkx);
1164 len[0] = wpabuf_len(nkx) / 2;
1165 addr[1] = wpabuf_head(pkx);
1166 len[1] = wpabuf_len(pkx) / 2;
1167 if (len[0] != len[1])
1168 goto fail;
1169 if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1170 addr[0] = wpabuf_head(pkx);
1171 addr[1] = wpabuf_head(nkx);
1172 }
1173 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1174 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1175 res = sha256_vector(2, addr, len, hash);
1176 if (res < 0)
1177 goto fail;
1178 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1179 os_memcpy(pmkid, hash, PMKID_LEN);
1180 wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1181 ret = 0;
1182fail:
1183 wpabuf_free(nkx);
1184 wpabuf_free(pkx);
1185 return ret;
1186}
1187
1188
1189/* Role-specific elements for PKEX */
1190
1191/* NIST P-256 */
1192static const u8 pkex_init_x_p256[32] = {
1193 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1194 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1195 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1196 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1197 };
1198static const u8 pkex_init_y_p256[32] = {
1199 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1200 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1201 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1202 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1203 };
1204static const u8 pkex_resp_x_p256[32] = {
1205 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1206 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1207 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1208 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1209};
1210static const u8 pkex_resp_y_p256[32] = {
1211 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1212 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1213 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1214 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1215};
1216
1217/* NIST P-384 */
1218static const u8 pkex_init_x_p384[48] = {
1219 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1220 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1221 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1222 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1223 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1224 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1225};
1226static const u8 pkex_init_y_p384[48] = {
1227 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1228 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1229 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1230 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1231 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1232 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1233};
1234static const u8 pkex_resp_x_p384[48] = {
1235 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1236 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1237 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1238 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1239 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1240 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1241};
1242static const u8 pkex_resp_y_p384[48] = {
1243 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1244 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1245 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1246 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1247 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1248 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1249};
1250
1251/* NIST P-521 */
1252static const u8 pkex_init_x_p521[66] = {
1253 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1254 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1255 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1256 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1257 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1258 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1259 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1260 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1261 0x97, 0x76
1262};
1263static const u8 pkex_init_y_p521[66] = {
1264 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1265 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1266 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1267 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1268 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1269 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1270 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1271 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1272 0x03, 0xa8
1273};
1274static const u8 pkex_resp_x_p521[66] = {
1275 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1276 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1277 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1278 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1279 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1280 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1281 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1282 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1283 0x84, 0xb4
1284};
1285static const u8 pkex_resp_y_p521[66] = {
1286 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1287 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1288 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1289 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1290 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1291 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1292 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1293 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1294 0xce, 0xe1
1295};
1296
1297/* Brainpool P-256r1 */
1298static const u8 pkex_init_x_bp_p256r1[32] = {
1299 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1300 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1301 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1302 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1303};
1304static const u8 pkex_init_y_bp_p256r1[32] = {
1305 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1306 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1307 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1308 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1309};
1310static const u8 pkex_resp_x_bp_p256r1[32] = {
1311 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1312 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1313 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1314 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1315};
1316static const u8 pkex_resp_y_bp_p256r1[32] = {
1317 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1318 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1319 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1320 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1321};
1322
1323/* Brainpool P-384r1 */
1324static const u8 pkex_init_x_bp_p384r1[48] = {
1325 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1326 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1327 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1328 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1329 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1330 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1331};
1332static const u8 pkex_init_y_bp_p384r1[48] = {
1333 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1334 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1335 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1336 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1337 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1338 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1339};
1340static const u8 pkex_resp_x_bp_p384r1[48] = {
1341 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1342 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1343 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1344 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1345 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1346 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1347};
1348static const u8 pkex_resp_y_bp_p384r1[48] = {
1349 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1350 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1351 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1352 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1353 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1354 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1355};
1356
1357/* Brainpool P-512r1 */
1358static const u8 pkex_init_x_bp_p512r1[64] = {
1359 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1360 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1361 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1362 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1363 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1364 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1365 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1366 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1367};
1368static const u8 pkex_init_y_bp_p512r1[64] = {
1369 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1370 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1371 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1372 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1373 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1374 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1375 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1376 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1377};
1378static const u8 pkex_resp_x_bp_p512r1[64] = {
1379 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1380 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1381 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1382 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1383 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1384 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1385 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1386 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1387};
1388static const u8 pkex_resp_y_bp_p512r1[64] = {
1389 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1390 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1391 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1392 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1393 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1394 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1395 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1396 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1397};
1398
1399
Hai Shaloma20dcd72022-02-04 13:43:00 -08001400static struct crypto_ec_key *
1401dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001402{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001403 const u8 *x, *y;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001404
1405 switch (curve->ike_group) {
1406 case 19:
1407 x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1408 y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1409 break;
1410 case 20:
1411 x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1412 y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1413 break;
1414 case 21:
1415 x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1416 y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1417 break;
1418 case 28:
1419 x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1420 y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1421 break;
1422 case 29:
1423 x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1424 y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1425 break;
1426 case 30:
1427 x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1428 y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1429 break;
1430 default:
1431 return NULL;
1432 }
1433
Hai Shaloma20dcd72022-02-04 13:43:00 -08001434 return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001435}
1436
1437
Hai Shaloma20dcd72022-02-04 13:43:00 -08001438struct crypto_ec_point *
1439dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
1440 const char *code, const char *identifier,
1441 struct crypto_ec **ret_ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001442{
1443 u8 hash[DPP_MAX_HASH_LEN];
1444 const u8 *addr[3];
1445 size_t len[3];
1446 unsigned int num_elem = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00001447 struct crypto_ec_point *Qi = NULL, *Pi = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001448 struct crypto_ec_key *Pi_key = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001449 struct crypto_bignum *hash_bn = NULL;
1450 struct crypto_ec *ec = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001451
Hai Shaloma20dcd72022-02-04 13:43:00 -08001452 /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001453
Hai Shaloma20dcd72022-02-04 13:43:00 -08001454 if (mac_init) {
1455 wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
1456 MAC2STR(mac_init));
1457 addr[num_elem] = mac_init;
1458 len[num_elem] = ETH_ALEN;
1459 num_elem++;
1460 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001461 if (identifier) {
1462 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1463 identifier);
1464 addr[num_elem] = (const u8 *) identifier;
1465 len[num_elem] = os_strlen(identifier);
1466 num_elem++;
1467 }
1468 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1469 addr[num_elem] = (const u8 *) code;
1470 len[num_elem] = os_strlen(code);
1471 num_elem++;
1472 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1473 goto fail;
1474 wpa_hexdump_key(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001475 "DPP: H([MAC-Initiator |] [identifier |] code)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001476 hash, curve->hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001477 Pi_key = dpp_pkex_get_role_elem(curve, 1);
1478 if (!Pi_key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001479 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001480 dpp_debug_print_key("DPP: Pi", Pi_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001481
Hai Shaloma20dcd72022-02-04 13:43:00 -08001482 ec = crypto_ec_init(curve->ike_group);
1483 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001484 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001485
1486 Pi = crypto_ec_key_get_public_key(Pi_key);
1487 Qi = crypto_ec_point_init(ec);
1488 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1489 if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001490 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001491
1492 if (crypto_ec_point_is_at_infinity(ec, Qi)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001493 wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1494 goto fail;
1495 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001496 crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001497out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001498 crypto_ec_key_deinit(Pi_key);
Sunil8cd6f4d2022-06-28 18:40:46 +00001499 crypto_ec_point_deinit(Pi, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001500 crypto_bignum_deinit(hash_bn, 1);
1501 if (ret_ec && Qi)
1502 *ret_ec = ec;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001503 else
Hai Shaloma20dcd72022-02-04 13:43:00 -08001504 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001505 return Qi;
1506fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001507 crypto_ec_point_deinit(Qi, 1);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001508 Qi = NULL;
1509 goto out;
1510}
1511
1512
Hai Shaloma20dcd72022-02-04 13:43:00 -08001513struct crypto_ec_point *
1514dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
1515 const char *code, const char *identifier,
1516 struct crypto_ec **ret_ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001517{
1518 u8 hash[DPP_MAX_HASH_LEN];
1519 const u8 *addr[3];
1520 size_t len[3];
1521 unsigned int num_elem = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00001522 struct crypto_ec_point *Qr = NULL, *Pr = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001523 struct crypto_ec_key *Pr_key = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001524 struct crypto_bignum *hash_bn = NULL;
1525 struct crypto_ec *ec = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001526
Hai Shaloma20dcd72022-02-04 13:43:00 -08001527 /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001528
Hai Shaloma20dcd72022-02-04 13:43:00 -08001529 if (mac_resp) {
1530 wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
1531 MAC2STR(mac_resp));
1532 addr[num_elem] = mac_resp;
1533 len[num_elem] = ETH_ALEN;
1534 num_elem++;
1535 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001536 if (identifier) {
1537 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1538 identifier);
1539 addr[num_elem] = (const u8 *) identifier;
1540 len[num_elem] = os_strlen(identifier);
1541 num_elem++;
1542 }
1543 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1544 addr[num_elem] = (const u8 *) code;
1545 len[num_elem] = os_strlen(code);
1546 num_elem++;
1547 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1548 goto fail;
1549 wpa_hexdump_key(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001550 "DPP: H([MAC-Responder |] [identifier |] code)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001551 hash, curve->hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001552 Pr_key = dpp_pkex_get_role_elem(curve, 0);
1553 if (!Pr_key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001554 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001555 dpp_debug_print_key("DPP: Pr", Pr_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001556
Hai Shaloma20dcd72022-02-04 13:43:00 -08001557 ec = crypto_ec_init(curve->ike_group);
1558 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001559 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001560
1561 Pr = crypto_ec_key_get_public_key(Pr_key);
1562 Qr = crypto_ec_point_init(ec);
1563 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1564 if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001565 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001566
1567 if (crypto_ec_point_is_at_infinity(ec, Qr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001568 wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1569 goto fail;
1570 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001571 crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
1572
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001573out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001574 crypto_ec_key_deinit(Pr_key);
Sunil8cd6f4d2022-06-28 18:40:46 +00001575 crypto_ec_point_deinit(Pr, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001576 crypto_bignum_deinit(hash_bn, 1);
1577 if (ret_ec && Qr)
1578 *ret_ec = ec;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001579 else
Hai Shaloma20dcd72022-02-04 13:43:00 -08001580 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001581 return Qr;
1582fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001583 crypto_ec_point_deinit(Qr, 1);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001584 Qr = NULL;
1585 goto out;
1586}
1587
1588
1589int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001590 u8 ver_init, u8 ver_resp,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001591 const u8 *Mx, size_t Mx_len,
1592 const u8 *Nx, size_t Nx_len,
1593 const char *code,
1594 const u8 *Kx, size_t Kx_len,
1595 u8 *z, unsigned int hash_len)
1596{
1597 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1598 int res;
1599 u8 *info, *pos;
1600 size_t info_len;
1601
Hai Shaloma20dcd72022-02-04 13:43:00 -08001602 /*
1603 * v1: info = MAC-Initiator | MAC-Responder
1604 * v2: info = Protocol Version-Initiator | Protocol Version-Responder
1605 * z = HKDF(<>, info | M.x | N.x | code, K.x)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001606 */
1607
1608 /* HKDF-Extract(<>, IKM=K.x) */
1609 os_memset(salt, 0, hash_len);
1610 if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1611 return -1;
1612 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1613 prk, hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001614 if (mac_init && mac_resp)
1615 info_len = 2 * ETH_ALEN;
1616 else
1617 info_len = 2;
1618 info_len += Mx_len + Nx_len + os_strlen(code);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001619 info = os_malloc(info_len);
1620 if (!info)
1621 return -1;
1622 pos = info;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001623 if (mac_init && mac_resp) {
1624 os_memcpy(pos, mac_init, ETH_ALEN);
1625 pos += ETH_ALEN;
1626 os_memcpy(pos, mac_resp, ETH_ALEN);
1627 pos += ETH_ALEN;
1628 } else {
1629 *pos++ = ver_init;
1630 *pos++ = ver_resp;
1631 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001632 os_memcpy(pos, Mx, Mx_len);
1633 pos += Mx_len;
1634 os_memcpy(pos, Nx, Nx_len);
1635 pos += Nx_len;
1636 os_memcpy(pos, code, os_strlen(code));
1637
1638 /* HKDF-Expand(PRK, info, L) */
1639 if (hash_len == 32)
1640 res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1641 z, hash_len);
1642 else if (hash_len == 48)
1643 res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1644 z, hash_len);
1645 else if (hash_len == 64)
1646 res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1647 z, hash_len);
1648 else
1649 res = -1;
1650 os_free(info);
1651 os_memset(prk, 0, hash_len);
1652 if (res < 0)
1653 return -1;
1654
1655 wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1656 z, hash_len);
1657 return 0;
1658}
1659
1660
1661int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1662 const u8 *net_access_key,
1663 size_t net_access_key_len,
1664 struct json_token *peer_net_access_key)
1665{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001666 struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00001667 struct crypto_bignum *sum = NULL, *cR = NULL, *pR = NULL;
1668 const struct crypto_bignum *q;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001669 struct crypto_ec *ec = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00001670 struct crypto_ec_point *M = NULL, *CI = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001671 u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1672 u8 prk[DPP_MAX_HASH_LEN];
1673 const struct dpp_curve_params *curve;
1674 int res = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07001675 u8 nonces[2 * DPP_MAX_NONCE_LEN];
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001676
1677 own_key = dpp_set_keypair(&auth->curve, net_access_key,
1678 net_access_key_len);
1679 if (!own_key) {
1680 dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1681 goto fail;
1682 }
1683
1684 peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1685 if (!peer_key)
1686 goto fail;
1687 dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1688
1689 if (auth->curve != curve) {
1690 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001691 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001692 auth->curve->name, curve->name);
1693 goto fail;
1694 }
1695
1696 auth->own_protocol_key = dpp_gen_keypair(curve);
1697 if (!auth->own_protocol_key)
1698 goto fail;
1699
Hai Shalom899fcc72020-10-19 14:38:18 -07001700 if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1701 wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1702 goto fail;
1703 }
1704 wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1705 auth->e_nonce, auth->curve->nonce_len);
1706
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001707 /* M = { cR + pR } * CI */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001708 ec = crypto_ec_init(curve->ike_group);
1709 if (!ec)
Hai Shalom60840252021-02-19 19:02:11 -08001710 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001711
1712 sum = crypto_bignum_init();
1713 q = crypto_ec_get_order(ec);
1714 M = crypto_ec_point_init(ec);
1715 cR = crypto_ec_key_get_private_key(own_key);
1716 pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1717 CI = crypto_ec_key_get_public_key(peer_key);
1718 if (!sum || !q || !M || !cR || !pR || !CI ||
1719 crypto_bignum_addmod(cR, pR, q, sum) ||
1720 crypto_ec_point_mul(ec, CI, sum, M) ||
1721 crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1722 wpa_printf(MSG_ERROR, "DPP: Error during M computation");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001723 goto fail;
1724 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001725 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1726
Hai Shalom899fcc72020-10-19 14:38:18 -07001727 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001728
Hai Shalom899fcc72020-10-19 14:38:18 -07001729 /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1730 os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1731 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1732 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001733 Mx, curve->prime_len, prk) < 0)
1734 goto fail;
1735 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1736
1737 /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1738 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1739 "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1740 goto fail;
1741 wpa_hexdump_key(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001742 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001743 auth->ke, curve->hash_len);
1744
1745 res = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001746 crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001747 auth->reconfig_old_protocol_key = own_key;
1748 own_key = NULL;
1749fail:
1750 forced_memzero(prk, sizeof(prk));
1751 forced_memzero(Mx, sizeof(Mx));
Hai Shaloma20dcd72022-02-04 13:43:00 -08001752 crypto_ec_point_deinit(M, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001753 crypto_ec_point_deinit(CI, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001754 crypto_bignum_deinit(sum, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001755 crypto_bignum_deinit(cR, 1);
1756 crypto_bignum_deinit(pR, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001757 crypto_ec_key_deinit(own_key);
1758 crypto_ec_key_deinit(peer_key);
1759 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001760 return res;
1761}
1762
1763
1764int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1765 const u8 *r_proto, u16 r_proto_len,
1766 struct json_token *net_access_key)
1767{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001768 struct crypto_ec_key *pr = NULL, *peer_key = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00001769 struct crypto_bignum *cI = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001770 struct crypto_ec *ec = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00001771 struct crypto_ec_point *sum = NULL, *M = NULL, *CR = NULL, *PR = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001772 u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1773 u8 prk[DPP_MAX_HASH_LEN];
1774 int res = -1;
1775 const struct dpp_curve_params *curve;
Hai Shalom899fcc72020-10-19 14:38:18 -07001776 u8 nonces[2 * DPP_MAX_NONCE_LEN];
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001777
1778 pr = dpp_set_pubkey_point(auth->conf->connector_key,
1779 r_proto, r_proto_len);
1780 if (!pr) {
1781 dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1782 goto fail;
1783 }
1784 dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001785 crypto_ec_key_deinit(auth->peer_protocol_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001786 auth->peer_protocol_key = pr;
1787 pr = NULL;
1788
1789 peer_key = dpp_parse_jwk(net_access_key, &curve);
1790 if (!peer_key)
1791 goto fail;
1792 dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1793 if (auth->curve != curve) {
1794 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001795 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001796 auth->curve->name, curve->name);
1797 goto fail;
1798 }
1799
1800 /* M = cI * { CR + PR } */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001801 ec = crypto_ec_init(curve->ike_group);
1802 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001803 goto fail;
1804
Hai Shaloma20dcd72022-02-04 13:43:00 -08001805 cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
1806 sum = crypto_ec_point_init(ec);
1807 M = crypto_ec_point_init(ec);
1808 CR = crypto_ec_key_get_public_key(peer_key);
1809 PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1810 if (!cI || !sum || !M || !CR || !PR ||
1811 crypto_ec_point_add(ec, CR, PR, sum) ||
1812 crypto_ec_point_mul(ec, sum, cI, M) ||
1813 crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1814 wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1815 goto fail;
1816 }
1817
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001818 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1819
Hai Shalom899fcc72020-10-19 14:38:18 -07001820 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001821
Hai Shalom899fcc72020-10-19 14:38:18 -07001822 /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1823 os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1824 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1825 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001826 Mx, curve->prime_len, prk) < 0)
1827 goto fail;
1828 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1829
1830 /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1831 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1832 "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1833 goto fail;
1834 wpa_hexdump_key(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001835 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001836 auth->ke, curve->hash_len);
1837
1838 res = 0;
1839fail:
1840 forced_memzero(prk, sizeof(prk));
1841 forced_memzero(Mx, sizeof(Mx));
Sunil8cd6f4d2022-06-28 18:40:46 +00001842 crypto_bignum_deinit(cI, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001843 crypto_ec_key_deinit(pr);
1844 crypto_ec_key_deinit(peer_key);
1845 crypto_ec_point_deinit(sum, 1);
1846 crypto_ec_point_deinit(M, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00001847 crypto_ec_point_deinit(CR, 1);
1848 crypto_ec_point_deinit(PR, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001849 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001850 return res;
1851}
1852
1853
1854static char *
1855dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1856{
1857 struct wpabuf *jws_prot_hdr;
1858 char *signed1;
1859
1860 jws_prot_hdr = wpabuf_alloc(100);
1861 if (!jws_prot_hdr)
1862 return NULL;
1863 json_start_object(jws_prot_hdr, NULL);
1864 json_add_string(jws_prot_hdr, "typ", "dppCon");
1865 json_value_sep(jws_prot_hdr);
1866 json_add_string(jws_prot_hdr, "kid", conf->kid);
1867 json_value_sep(jws_prot_hdr);
1868 json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1869 json_end_object(jws_prot_hdr);
1870 signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1871 wpabuf_len(jws_prot_hdr),
1872 signed1_len);
1873 wpabuf_free(jws_prot_hdr);
1874 return signed1;
1875}
1876
1877
1878static char *
1879dpp_build_conn_signature(struct dpp_configurator *conf,
1880 const char *signed1, size_t signed1_len,
1881 const char *signed2, size_t signed2_len,
1882 size_t *signed3_len)
1883{
1884 const struct dpp_curve_params *curve;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001885 struct wpabuf *sig = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001886 char *signed3 = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001887 char *dot = ".";
Hai Shaloma20dcd72022-02-04 13:43:00 -08001888 const u8 *vector[3];
1889 size_t vector_len[3];
1890 u8 *hash;
1891 int ret;
1892
1893 vector[0] = (const u8 *) signed1;
1894 vector[1] = (const u8 *) dot;
1895 vector[2] = (const u8 *) signed2;
1896 vector_len[0] = signed1_len;
1897 vector_len[1] = 1;
1898 vector_len[2] = signed2_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001899
1900 curve = conf->curve;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001901 hash = os_malloc(curve->hash_len);
1902 if (!hash)
1903 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001904 if (curve->hash_len == SHA256_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001905 ret = sha256_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001906 } else if (curve->hash_len == SHA384_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001907 ret = sha384_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001908 } else if (curve->hash_len == SHA512_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001909 ret = sha512_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001910 } else {
1911 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1912 goto fail;
1913 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001914 if (ret) {
1915 wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
1916 goto fail;
1917 }
1918 wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
1919 hash, curve->hash_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001920
Hai Shaloma20dcd72022-02-04 13:43:00 -08001921 sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
1922 if (!sig) {
1923 wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001924 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001925 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001926
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001927 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
Hai Shaloma20dcd72022-02-04 13:43:00 -08001928 wpabuf_head(sig), wpabuf_len(sig));
1929 signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
1930 signed3_len);
1931
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001932fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001933 os_free(hash);
1934 wpabuf_free(sig);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001935 return signed3;
1936}
1937
1938char * dpp_sign_connector(struct dpp_configurator *conf,
1939 const struct wpabuf *dppcon)
1940{
1941 char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1942 char *signed_conn = NULL, *pos;
1943 size_t signed1_len, signed2_len, signed3_len;
1944
1945 signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1946 signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1947 &signed2_len);
1948 if (!signed1 || !signed2)
1949 goto fail;
1950
1951 signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1952 signed2, signed2_len, &signed3_len);
1953 if (!signed3)
1954 goto fail;
1955
1956 signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1957 if (!signed_conn)
1958 goto fail;
1959 pos = signed_conn;
1960 os_memcpy(pos, signed1, signed1_len);
1961 pos += signed1_len;
1962 *pos++ = '.';
1963 os_memcpy(pos, signed2, signed2_len);
1964 pos += signed2_len;
1965 *pos++ = '.';
1966 os_memcpy(pos, signed3, signed3_len);
1967 pos += signed3_len;
1968 *pos = '\0';
1969
1970fail:
1971 os_free(signed1);
1972 os_free(signed2);
1973 os_free(signed3);
1974 return signed_conn;
1975}
1976
1977
1978#ifdef CONFIG_DPP2
1979
1980struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
1981 size_t net_access_key_len)
1982{
1983 struct wpabuf *pub = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001984 struct crypto_ec_key *own_key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001985 struct dpp_pfs *pfs;
1986
1987 pfs = os_zalloc(sizeof(*pfs));
1988 if (!pfs)
1989 return NULL;
1990
1991 own_key = dpp_set_keypair(&pfs->curve, net_access_key,
1992 net_access_key_len);
1993 if (!own_key) {
1994 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
1995 goto fail;
1996 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001997 crypto_ec_key_deinit(own_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001998
1999 pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
2000 if (!pfs->ecdh)
2001 goto fail;
2002
2003 pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
2004 pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
2005 if (!pub)
2006 goto fail;
2007
2008 pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2009 if (!pfs->ie)
2010 goto fail;
2011 wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2012 wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2013 wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2014 wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2015 wpabuf_put_buf(pfs->ie, pub);
2016 wpabuf_free(pub);
2017 wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2018 pfs->ie);
2019
2020 return pfs;
2021fail:
2022 wpabuf_free(pub);
2023 dpp_pfs_free(pfs);
2024 return NULL;
2025}
2026
2027
2028int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2029{
2030 if (peer_ie_len < 2)
2031 return -1;
2032 if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2033 wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2034 return -1;
2035 }
2036
2037 pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2038 peer_ie_len - 2);
2039 pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2040 if (!pfs->secret) {
2041 wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2042 return -1;
2043 }
2044 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2045 return 0;
2046}
2047
2048
2049void dpp_pfs_free(struct dpp_pfs *pfs)
2050{
2051 if (!pfs)
2052 return;
2053 crypto_ecdh_deinit(pfs->ecdh);
2054 wpabuf_free(pfs->ie);
2055 wpabuf_clear_free(pfs->secret);
2056 os_free(pfs);
2057}
2058
Hai Shalom899fcc72020-10-19 14:38:18 -07002059
2060struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2061{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002062 struct crypto_csr *csr = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002063 struct wpabuf *buf = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002064 struct crypto_ec_key *key;
Hai Shalom899fcc72020-10-19 14:38:18 -07002065 unsigned int hash_len = auth->curve->hash_len;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002066 struct wpabuf *priv_key;
Hai Shalom899fcc72020-10-19 14:38:18 -07002067 u8 cp[DPP_CP_LEN];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002068 char *password = NULL;
2069 size_t password_len = 0;
2070 int hash_sign_algo;
Hai Shalom899fcc72020-10-19 14:38:18 -07002071
2072 /* TODO: use auth->csrattrs */
2073
2074 /* TODO: support generation of a new private key if csrAttrs requests
2075 * a specific group to be used */
2076 key = auth->own_protocol_key;
2077
Hai Shaloma20dcd72022-02-04 13:43:00 -08002078 priv_key = crypto_ec_key_get_ecprivate_key(key, true);
2079 if (!priv_key)
Hai Shalom899fcc72020-10-19 14:38:18 -07002080 goto fail;
2081 wpabuf_free(auth->priv_key);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002082 auth->priv_key = priv_key;
2083
2084 csr = crypto_csr_init();
2085 if (!csr || crypto_csr_set_ec_public_key(csr, key))
Hai Shalom899fcc72020-10-19 14:38:18 -07002086 goto fail;
2087
Hai Shaloma20dcd72022-02-04 13:43:00 -08002088 if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
Hai Shalom899fcc72020-10-19 14:38:18 -07002089 goto fail;
2090
Hai Shalom899fcc72020-10-19 14:38:18 -07002091 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2092 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2093 "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2094 goto fail;
2095 wpa_hexdump_key(MSG_DEBUG,
2096 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2097 cp, DPP_CP_LEN);
2098 password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2099 forced_memzero(cp, DPP_CP_LEN);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002100 if (!password ||
2101 crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2102 ASN1_TAG_UTF8STRING, (const u8 *) password,
2103 password_len))
Hai Shalom899fcc72020-10-19 14:38:18 -07002104 goto fail;
2105
Hai Shalom899fcc72020-10-19 14:38:18 -07002106 /* TODO: hash func selection based on csrAttrs */
2107 if (hash_len == SHA256_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002108 hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
Hai Shalom899fcc72020-10-19 14:38:18 -07002109 } else if (hash_len == SHA384_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002110 hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07002111 } else if (hash_len == SHA512_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002112 hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
Hai Shalom899fcc72020-10-19 14:38:18 -07002113 } else {
2114 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2115 goto fail;
2116 }
2117
Hai Shaloma20dcd72022-02-04 13:43:00 -08002118 buf = crypto_csr_sign(csr, key, hash_sign_algo);
2119 if (!buf)
Hai Shalom899fcc72020-10-19 14:38:18 -07002120 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -07002121 wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2122
2123fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002124 bin_clear_free(password, password_len);
2125 crypto_csr_deinit(csr);
Hai Shalom899fcc72020-10-19 14:38:18 -07002126 return buf;
2127}
2128
2129
Hai Shaloma20dcd72022-02-04 13:43:00 -08002130int dpp_validate_csr(struct dpp_authentication *auth,
2131 const struct wpabuf *csrbuf)
Hai Shalom899fcc72020-10-19 14:38:18 -07002132{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002133 struct crypto_csr *csr;
2134 const u8 *attr;
2135 size_t attr_len;
2136 int attr_type;
Hai Shalom899fcc72020-10-19 14:38:18 -07002137 unsigned char *cp = NULL;
2138 size_t cp_len;
2139 u8 exp_cp[DPP_CP_LEN];
2140 unsigned int hash_len = auth->curve->hash_len;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002141 int ret = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07002142
Hai Shaloma20dcd72022-02-04 13:43:00 -08002143 csr = crypto_csr_verify(csrbuf);
2144 if (!csr) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002145 wpa_printf(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002146 "DPP: CSR invalid or invalid signature");
Hai Shalom899fcc72020-10-19 14:38:18 -07002147 goto fail;
2148 }
2149
Hai Shaloma20dcd72022-02-04 13:43:00 -08002150 attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2151 &attr_len, &attr_type);
2152 if (!attr) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002153 wpa_printf(MSG_DEBUG,
2154 "DPP: CSR does not include challengePassword");
2155 goto fail;
2156 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002157 /* This is supposed to be UTF8String, but allow other strings as well
2158 * since challengePassword is using ASCII (base64 encoded). */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002159 if (attr_type != ASN1_TAG_UTF8STRING &&
2160 attr_type != ASN1_TAG_PRINTABLESTRING &&
2161 attr_type != ASN1_TAG_IA5STRING) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002162 wpa_printf(MSG_DEBUG,
2163 "DPP: Unexpected challengePassword attribute type %d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002164 attr_type);
Hai Shalom899fcc72020-10-19 14:38:18 -07002165 goto fail;
2166 }
2167
Hai Shaloma20dcd72022-02-04 13:43:00 -08002168 cp = base64_decode((const char *) attr, attr_len, &cp_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002169 if (!cp) {
2170 wpa_printf(MSG_DEBUG,
2171 "DPP: Could not base64 decode challengePassword");
2172 goto fail;
2173 }
2174 if (cp_len != DPP_CP_LEN) {
2175 wpa_printf(MSG_DEBUG,
2176 "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2177 cp_len);
2178 goto fail;
2179 }
2180 wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2181 cp, cp_len);
2182
2183 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2184 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2185 "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2186 goto fail;
2187 wpa_hexdump_key(MSG_DEBUG,
2188 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2189 exp_cp, DPP_CP_LEN);
2190 if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2191 wpa_printf(MSG_DEBUG,
2192 "DPP: CSR challengePassword does not match calculated cp");
2193 goto fail;
2194 }
2195
2196 ret = 0;
2197fail:
2198 os_free(cp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002199 crypto_csr_deinit(csr);
Hai Shalom899fcc72020-10-19 14:38:18 -07002200 return ret;
2201}
2202
2203
2204struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2205 size_t csign_key_len,
2206 const u8 *pp_key,
2207 size_t pp_key_len)
2208{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002209 struct crypto_ec_key *csign = NULL, *ppkey = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002210 struct dpp_reconfig_id *id = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002211 struct crypto_ec *ec = NULL;
2212 const struct crypto_bignum *q;
2213 struct crypto_bignum *bn = NULL;
2214 struct crypto_ec_point *e_id = NULL;
2215 const struct crypto_ec_point *generator;
Hai Shalom899fcc72020-10-19 14:38:18 -07002216
Hai Shaloma20dcd72022-02-04 13:43:00 -08002217 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002218 if (!csign)
2219 goto fail;
2220
2221 if (!pp_key)
2222 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002223 ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002224 if (!ppkey)
2225 goto fail;
2226
Hai Shaloma20dcd72022-02-04 13:43:00 -08002227 ec = crypto_ec_init(crypto_ec_key_group(csign));
2228 if (!ec)
Hai Shalom899fcc72020-10-19 14:38:18 -07002229 goto fail;
2230
Hai Shaloma20dcd72022-02-04 13:43:00 -08002231 e_id = crypto_ec_point_init(ec);
2232 bn = crypto_bignum_init();
2233 q = crypto_ec_get_order(ec);
2234 generator = crypto_ec_get_generator(ec);
2235 if (!e_id || !bn || !q || !generator ||
2236 crypto_bignum_rand(bn, q) ||
2237 crypto_ec_point_mul(ec, generator, bn, e_id))
Hai Shalom899fcc72020-10-19 14:38:18 -07002238 goto fail;
2239
Hai Shaloma20dcd72022-02-04 13:43:00 -08002240 crypto_ec_point_debug_print(ec, e_id,
2241 "DPP: Generated random point E-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002242
2243 id = os_zalloc(sizeof(*id));
2244 if (!id)
2245 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002246
2247 id->ec = ec;
2248 ec = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002249 id->e_id = e_id;
2250 e_id = NULL;
2251 id->csign = csign;
2252 csign = NULL;
2253 id->pp_key = ppkey;
2254 ppkey = NULL;
2255fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002256 crypto_ec_point_deinit(e_id, 1);
2257 crypto_ec_key_deinit(csign);
2258 crypto_ec_key_deinit(ppkey);
2259 crypto_bignum_deinit(bn, 1);
2260 crypto_ec_deinit(ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002261 return id;
2262}
2263
2264
Hai Shalom899fcc72020-10-19 14:38:18 -07002265int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2266{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002267 const struct crypto_bignum *q;
2268 struct crypto_bignum *bn;
Sunil8cd6f4d2022-06-28 18:40:46 +00002269 const struct crypto_ec_point *generator;
2270 struct crypto_ec_point *e_prime_id, *a_nonce, *pp;
Hai Shalom899fcc72020-10-19 14:38:18 -07002271 int ret = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07002272
Hai Shaloma20dcd72022-02-04 13:43:00 -08002273 pp = crypto_ec_key_get_public_key(id->pp_key);
2274 e_prime_id = crypto_ec_point_init(id->ec);
2275 a_nonce = crypto_ec_point_init(id->ec);
2276 bn = crypto_bignum_init();
2277 q = crypto_ec_get_order(id->ec);
2278 generator = crypto_ec_get_generator(id->ec);
2279
Hai Shalom899fcc72020-10-19 14:38:18 -07002280 /* Generate random 0 <= a-nonce < q
2281 * A-NONCE = a-nonce * G
2282 * E'-id = E-id + a-nonce * P_pk */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002283 if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
2284 crypto_bignum_rand(bn, q) || /* bn = a-nonce */
2285 crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
2286 crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
2287 crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
Hai Shalom899fcc72020-10-19 14:38:18 -07002288 goto fail;
2289
Hai Shaloma20dcd72022-02-04 13:43:00 -08002290 crypto_ec_point_debug_print(id->ec, a_nonce,
2291 "DPP: Generated A-NONCE");
2292 crypto_ec_point_debug_print(id->ec, e_prime_id,
2293 "DPP: Encrypted E-id to E'-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002294
Hai Shaloma20dcd72022-02-04 13:43:00 -08002295 crypto_ec_key_deinit(id->a_nonce);
2296 crypto_ec_key_deinit(id->e_prime_id);
2297 id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
2298 id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
Hai Shalom899fcc72020-10-19 14:38:18 -07002299 if (!id->a_nonce || !id->e_prime_id)
2300 goto fail;
2301
2302 ret = 0;
2303
2304fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002305 crypto_ec_point_deinit(e_prime_id, 1);
2306 crypto_ec_point_deinit(a_nonce, 1);
Sunil8cd6f4d2022-06-28 18:40:46 +00002307 crypto_ec_point_deinit(pp, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002308 crypto_bignum_deinit(bn, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07002309 return ret;
2310}
2311
2312
2313void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2314{
2315 if (id) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002316 crypto_ec_point_deinit(id->e_id, 1);
2317 crypto_ec_key_deinit(id->csign);
2318 crypto_ec_key_deinit(id->a_nonce);
2319 crypto_ec_key_deinit(id->e_prime_id);
2320 crypto_ec_key_deinit(id->pp_key);
2321 crypto_ec_deinit(id->ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002322 os_free(id);
2323 }
2324}
2325
2326
Hai Shaloma20dcd72022-02-04 13:43:00 -08002327struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
2328 struct crypto_ec_key *a_nonce,
2329 struct crypto_ec_key *e_prime_id)
Hai Shalom899fcc72020-10-19 14:38:18 -07002330{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002331 struct crypto_ec *ec;
Sunil8cd6f4d2022-06-28 18:40:46 +00002332 struct crypto_bignum *pp = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002333 struct crypto_ec_point *e_id = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00002334 struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
Hai Shalom899fcc72020-10-19 14:38:18 -07002335
2336 if (!ppkey)
2337 return NULL;
2338
2339 /* E-id = E'-id - s_C * A-NONCE */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002340 ec = crypto_ec_init(crypto_ec_key_group(ppkey));
2341 if (!ec)
Hai Shalom899fcc72020-10-19 14:38:18 -07002342 return NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002343
2344 pp = crypto_ec_key_get_private_key(ppkey);
2345 a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
2346 e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
2347 e_id = crypto_ec_point_init(ec);
2348 if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
2349 crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
2350 crypto_ec_point_invert(ec, e_id) ||
2351 crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
2352 crypto_ec_point_deinit(e_id, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07002353 goto fail;
2354 }
2355
Hai Shaloma20dcd72022-02-04 13:43:00 -08002356 crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002357
2358fail:
Sunil8cd6f4d2022-06-28 18:40:46 +00002359 crypto_ec_point_deinit(a_nonce_point, 1);
2360 crypto_ec_point_deinit(e_prime_id_point, 1);
2361 crypto_bignum_deinit(pp, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002362 crypto_ec_deinit(ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002363 return e_id;
2364}
2365
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002366#endif /* CONFIG_DPP2 */
2367
2368
Sunil Ravia04bd252022-05-02 22:54:18 -07002369#ifdef CONFIG_DPP3
2370int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
2371{
2372 int ret = -1, res;
2373 u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
2374 size_t Sx_len;
2375 unsigned int hash_len;
2376 const char *info = "New DPP Protocol Key";
2377 const u8 *addr[3];
2378 size_t len[3];
2379 u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
2380 struct wpabuf *pcx = NULL, *pex = NULL;
2381
2382 hash_len = auth->curve->hash_len;
2383
2384 /*
2385 * Configurator: S = pc * Pe
2386 * Enrollee: S = pe * Pc
2387 * k = HKDF(bk, "New DPP Protocol Key", S.x)
2388 * = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
2389 * len(new-curve-hash-out))
2390 * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)
2391 *
2392 * auth->own_protocol_key and auth->peer_protocol_key have already been
2393 * updated to use the new keys. The new curve determines the size of
2394 * the (new) protocol keys and S.x. The other parameters (bk, hash
2395 * algorithm, k) are determined based on the initially determined curve
2396 * during the (re)authentication exchange.
2397 */
2398
2399 if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2400 Sx, &Sx_len) < 0)
2401 goto fail;
2402
2403 wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
2404
2405 /* tmp = HKDF-Extract(bk, S.x) */
2406 addr[0] = Sx;
2407 len[0] = Sx_len;
2408 res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp);
2409 if (res < 0)
2410 goto fail;
2411 wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
2412 tmp, hash_len);
2413 /* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output))
2414 */
2415 res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
2416 if (res < 0)
2417 return -1;
2418
2419 wpa_hexdump_key(MSG_DEBUG,
2420 "DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
2421 k, hash_len);
2422
2423 /* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */
2424 addr[0] = auth->e_nonce;
2425 len[0] = auth->curve->nonce_len;
2426
2427 if (auth->configurator) {
2428 pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2429 pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2430 0);
2431 } else {
2432 pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2433 0);
2434 pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2435 }
2436 if (!pcx || !pex)
2437 goto fail;
2438 addr[1] = wpabuf_head(pcx);
2439 len[1] = wpabuf_len(pcx) / 2;
2440 addr[2] = wpabuf_head(pex);
2441 len[2] = wpabuf_len(pex) / 2;
2442
2443 if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0)
2444 goto fail;
2445 wpa_hexdump_key(MSG_DEBUG,
2446 "DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)",
2447 auth_i, hash_len);
2448 ret = 0;
2449fail:
2450 forced_memzero(Sx, sizeof(Sx));
2451 forced_memzero(tmp, sizeof(tmp));
2452 forced_memzero(k, sizeof(k));
2453 wpabuf_free(pcx);
2454 wpabuf_free(pex);
2455 return ret;
2456}
2457#endif /* CONFIG_DPP3 */
2458
2459
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002460#ifdef CONFIG_TESTING_OPTIONS
2461
2462int dpp_test_gen_invalid_key(struct wpabuf *msg,
2463 const struct dpp_curve_params *curve)
2464{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002465 struct crypto_ec *ec;
2466 struct crypto_ec_key *key = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00002467 struct crypto_ec_point *p = NULL, *pub_key = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002468 u8 *x, *y;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002469 int ret = -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002470
Hai Shaloma20dcd72022-02-04 13:43:00 -08002471 ec = crypto_ec_init(curve->ike_group);
2472 x = wpabuf_put(msg, curve->prime_len);
2473 y = wpabuf_put(msg, curve->prime_len);
2474 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002475 goto fail;
2476
Hai Shaloma20dcd72022-02-04 13:43:00 -08002477retry:
2478 /* Generate valid key pair */
2479 key = crypto_ec_key_gen(curve->ike_group);
2480 if (!key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002481 goto fail;
2482
Hai Shaloma20dcd72022-02-04 13:43:00 -08002483 /* Retrieve public key coordinates */
2484 pub_key = crypto_ec_key_get_public_key(key);
Sunil8cd6f4d2022-06-28 18:40:46 +00002485 if (!pub_key || crypto_ec_point_to_bin(ec, pub_key, x, y))
Hai Shaloma20dcd72022-02-04 13:43:00 -08002486 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002487
Hai Shaloma20dcd72022-02-04 13:43:00 -08002488 /* And corrupt them */
2489 y[curve->prime_len - 1] ^= 0x01;
2490 p = crypto_ec_point_from_bin(ec, x);
2491 if (p && crypto_ec_point_is_on_curve(ec, p)) {
2492 crypto_ec_point_deinit(p, 0);
2493 p = NULL;
2494 goto retry;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002495 }
2496
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002497 ret = 0;
2498fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002499 crypto_ec_point_deinit(p, 0);
Sunil8cd6f4d2022-06-28 18:40:46 +00002500 crypto_ec_point_deinit(pub_key, 0);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002501 crypto_ec_key_deinit(key);
2502 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002503 return ret;
2504}
2505
2506
2507char * dpp_corrupt_connector_signature(const char *connector)
2508{
2509 char *tmp, *pos, *signed3 = NULL;
2510 unsigned char *signature = NULL;
2511 size_t signature_len = 0, signed3_len;
2512
2513 tmp = os_zalloc(os_strlen(connector) + 5);
2514 if (!tmp)
2515 goto fail;
2516 os_memcpy(tmp, connector, os_strlen(connector));
2517
2518 pos = os_strchr(tmp, '.');
2519 if (!pos)
2520 goto fail;
2521
2522 pos = os_strchr(pos + 1, '.');
2523 if (!pos)
2524 goto fail;
2525 pos++;
2526
2527 wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2528 pos);
2529 signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2530 if (!signature || signature_len == 0)
2531 goto fail;
2532 wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2533 signature, signature_len);
2534 signature[signature_len - 1] ^= 0x01;
2535 wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2536 signature, signature_len);
2537 signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2538 if (!signed3)
2539 goto fail;
2540 os_memcpy(pos, signed3, signed3_len);
2541 pos[signed3_len] = '\0';
2542 wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2543 pos);
2544
2545out:
2546 os_free(signature);
2547 os_free(signed3);
2548 return tmp;
2549fail:
2550 os_free(tmp);
2551 tmp = NULL;
2552 goto out;
2553}
2554
2555#endif /* CONFIG_TESTING_OPTIONS */