blob: 4fac7de8ae44262f3b4909ceb565790599c17fa6 [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;
1038 struct crypto_ec_point *L = NULL;
1039 const struct crypto_ec_point *BI;
1040 const struct crypto_bignum *bR, *pR, *q;
1041 struct crypto_bignum *sum = NULL, *lx = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001042 int ret = -1;
1043
1044 /* L = ((bR + pR) modulo q) * BI */
1045
Hai Shaloma20dcd72022-02-04 13:43:00 -08001046 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1047 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001048 goto fail;
1049
Hai Shaloma20dcd72022-02-04 13:43:00 -08001050 q = crypto_ec_get_order(ec);
1051 BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1052 bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1053 pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1054 sum = crypto_bignum_init();
1055 L = crypto_ec_point_init(ec);
1056 lx = crypto_bignum_init();
1057 if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
1058 crypto_bignum_addmod(bR, pR, q, sum) ||
1059 crypto_ec_point_mul(ec, BI, sum, L) ||
1060 crypto_ec_point_x(ec, L, lx) ||
1061 crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1062 auth->secret_len) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001063 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001064
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001065 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1066 auth->Lx_len = auth->secret_len;
1067 ret = 0;
1068fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001069 crypto_bignum_deinit(lx, 1);
1070 crypto_bignum_deinit(sum, 1);
1071 crypto_ec_point_deinit(L, 1);
1072 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001073 return ret;
1074}
1075
1076
1077int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1078{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001079 struct crypto_ec *ec;
1080 struct crypto_ec_point *L = NULL, *sum = NULL;
1081 const struct crypto_ec_point *BR, *PR;
1082 const struct crypto_bignum *bI;
1083 struct crypto_bignum *lx = 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);
1111 crypto_ec_point_deinit(sum, 1);
1112 crypto_ec_point_deinit(L, 1);
1113 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001114 return ret;
1115}
1116
1117
1118int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1119{
1120 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1121 const char *info = "DPP PMK";
1122 int res;
1123
1124 /* PMK = HKDF(<>, "DPP PMK", N.x) */
1125
1126 /* HKDF-Extract(<>, N.x) */
1127 os_memset(salt, 0, hash_len);
1128 if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1129 return -1;
1130 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1131 prk, hash_len);
1132
1133 /* HKDF-Expand(PRK, info, L) */
1134 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1135 os_memset(prk, 0, hash_len);
1136 if (res < 0)
1137 return -1;
1138
1139 wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1140 pmk, hash_len);
1141 return 0;
1142}
1143
1144
1145int dpp_derive_pmkid(const struct dpp_curve_params *curve,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001146 struct crypto_ec_key *own_key,
1147 struct crypto_ec_key *peer_key, u8 *pmkid)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001148{
1149 struct wpabuf *nkx, *pkx;
1150 int ret = -1, res;
1151 const u8 *addr[2];
1152 size_t len[2];
1153 u8 hash[SHA256_MAC_LEN];
1154
1155 /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001156 nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
1157 pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001158 if (!nkx || !pkx)
1159 goto fail;
1160 addr[0] = wpabuf_head(nkx);
1161 len[0] = wpabuf_len(nkx) / 2;
1162 addr[1] = wpabuf_head(pkx);
1163 len[1] = wpabuf_len(pkx) / 2;
1164 if (len[0] != len[1])
1165 goto fail;
1166 if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1167 addr[0] = wpabuf_head(pkx);
1168 addr[1] = wpabuf_head(nkx);
1169 }
1170 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1171 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1172 res = sha256_vector(2, addr, len, hash);
1173 if (res < 0)
1174 goto fail;
1175 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1176 os_memcpy(pmkid, hash, PMKID_LEN);
1177 wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1178 ret = 0;
1179fail:
1180 wpabuf_free(nkx);
1181 wpabuf_free(pkx);
1182 return ret;
1183}
1184
1185
1186/* Role-specific elements for PKEX */
1187
1188/* NIST P-256 */
1189static const u8 pkex_init_x_p256[32] = {
1190 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1191 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1192 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1193 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1194 };
1195static const u8 pkex_init_y_p256[32] = {
1196 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1197 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1198 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1199 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1200 };
1201static const u8 pkex_resp_x_p256[32] = {
1202 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1203 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1204 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1205 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1206};
1207static const u8 pkex_resp_y_p256[32] = {
1208 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1209 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1210 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1211 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1212};
1213
1214/* NIST P-384 */
1215static const u8 pkex_init_x_p384[48] = {
1216 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1217 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1218 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1219 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1220 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1221 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1222};
1223static const u8 pkex_init_y_p384[48] = {
1224 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1225 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1226 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1227 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1228 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1229 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1230};
1231static const u8 pkex_resp_x_p384[48] = {
1232 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1233 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1234 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1235 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1236 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1237 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1238};
1239static const u8 pkex_resp_y_p384[48] = {
1240 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1241 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1242 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1243 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1244 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1245 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1246};
1247
1248/* NIST P-521 */
1249static const u8 pkex_init_x_p521[66] = {
1250 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1251 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1252 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1253 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1254 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1255 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1256 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1257 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1258 0x97, 0x76
1259};
1260static const u8 pkex_init_y_p521[66] = {
1261 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1262 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1263 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1264 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1265 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1266 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1267 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1268 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1269 0x03, 0xa8
1270};
1271static const u8 pkex_resp_x_p521[66] = {
1272 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1273 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1274 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1275 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1276 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1277 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1278 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1279 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1280 0x84, 0xb4
1281};
1282static const u8 pkex_resp_y_p521[66] = {
1283 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1284 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1285 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1286 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1287 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1288 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1289 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1290 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1291 0xce, 0xe1
1292};
1293
1294/* Brainpool P-256r1 */
1295static const u8 pkex_init_x_bp_p256r1[32] = {
1296 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1297 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1298 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1299 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1300};
1301static const u8 pkex_init_y_bp_p256r1[32] = {
1302 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1303 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1304 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1305 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1306};
1307static const u8 pkex_resp_x_bp_p256r1[32] = {
1308 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1309 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1310 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1311 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1312};
1313static const u8 pkex_resp_y_bp_p256r1[32] = {
1314 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1315 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1316 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1317 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1318};
1319
1320/* Brainpool P-384r1 */
1321static const u8 pkex_init_x_bp_p384r1[48] = {
1322 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1323 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1324 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1325 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1326 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1327 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1328};
1329static const u8 pkex_init_y_bp_p384r1[48] = {
1330 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1331 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1332 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1333 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1334 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1335 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1336};
1337static const u8 pkex_resp_x_bp_p384r1[48] = {
1338 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1339 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1340 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1341 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1342 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1343 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1344};
1345static const u8 pkex_resp_y_bp_p384r1[48] = {
1346 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1347 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1348 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1349 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1350 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1351 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1352};
1353
1354/* Brainpool P-512r1 */
1355static const u8 pkex_init_x_bp_p512r1[64] = {
1356 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1357 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1358 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1359 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1360 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1361 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1362 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1363 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1364};
1365static const u8 pkex_init_y_bp_p512r1[64] = {
1366 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1367 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1368 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1369 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1370 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1371 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1372 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1373 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1374};
1375static const u8 pkex_resp_x_bp_p512r1[64] = {
1376 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1377 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1378 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1379 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1380 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1381 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1382 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1383 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1384};
1385static const u8 pkex_resp_y_bp_p512r1[64] = {
1386 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1387 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1388 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1389 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1390 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1391 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1392 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1393 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1394};
1395
1396
Hai Shaloma20dcd72022-02-04 13:43:00 -08001397static struct crypto_ec_key *
1398dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001399{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001400 const u8 *x, *y;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001401
1402 switch (curve->ike_group) {
1403 case 19:
1404 x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1405 y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1406 break;
1407 case 20:
1408 x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1409 y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1410 break;
1411 case 21:
1412 x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1413 y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1414 break;
1415 case 28:
1416 x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1417 y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1418 break;
1419 case 29:
1420 x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1421 y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1422 break;
1423 case 30:
1424 x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1425 y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1426 break;
1427 default:
1428 return NULL;
1429 }
1430
Hai Shaloma20dcd72022-02-04 13:43:00 -08001431 return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001432}
1433
1434
Hai Shaloma20dcd72022-02-04 13:43:00 -08001435struct crypto_ec_point *
1436dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
1437 const char *code, const char *identifier,
1438 struct crypto_ec **ret_ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001439{
1440 u8 hash[DPP_MAX_HASH_LEN];
1441 const u8 *addr[3];
1442 size_t len[3];
1443 unsigned int num_elem = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001444 struct crypto_ec_point *Qi = NULL;
1445 struct crypto_ec_key *Pi_key = NULL;
1446 const struct crypto_ec_point *Pi = NULL;
1447 struct crypto_bignum *hash_bn = NULL;
1448 struct crypto_ec *ec = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001449
Hai Shaloma20dcd72022-02-04 13:43:00 -08001450 /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001451
Hai Shaloma20dcd72022-02-04 13:43:00 -08001452 if (mac_init) {
1453 wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
1454 MAC2STR(mac_init));
1455 addr[num_elem] = mac_init;
1456 len[num_elem] = ETH_ALEN;
1457 num_elem++;
1458 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001459 if (identifier) {
1460 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1461 identifier);
1462 addr[num_elem] = (const u8 *) identifier;
1463 len[num_elem] = os_strlen(identifier);
1464 num_elem++;
1465 }
1466 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1467 addr[num_elem] = (const u8 *) code;
1468 len[num_elem] = os_strlen(code);
1469 num_elem++;
1470 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1471 goto fail;
1472 wpa_hexdump_key(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001473 "DPP: H([MAC-Initiator |] [identifier |] code)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001474 hash, curve->hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001475 Pi_key = dpp_pkex_get_role_elem(curve, 1);
1476 if (!Pi_key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001477 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001478 dpp_debug_print_key("DPP: Pi", Pi_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001479
Hai Shaloma20dcd72022-02-04 13:43:00 -08001480 ec = crypto_ec_init(curve->ike_group);
1481 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001482 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001483
1484 Pi = crypto_ec_key_get_public_key(Pi_key);
1485 Qi = crypto_ec_point_init(ec);
1486 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1487 if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001488 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001489
1490 if (crypto_ec_point_is_at_infinity(ec, Qi)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001491 wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1492 goto fail;
1493 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001494 crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001495out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001496 crypto_ec_key_deinit(Pi_key);
1497 crypto_bignum_deinit(hash_bn, 1);
1498 if (ret_ec && Qi)
1499 *ret_ec = ec;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001500 else
Hai Shaloma20dcd72022-02-04 13:43:00 -08001501 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001502 return Qi;
1503fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001504 crypto_ec_point_deinit(Qi, 1);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001505 Qi = NULL;
1506 goto out;
1507}
1508
1509
Hai Shaloma20dcd72022-02-04 13:43:00 -08001510struct crypto_ec_point *
1511dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
1512 const char *code, const char *identifier,
1513 struct crypto_ec **ret_ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001514{
1515 u8 hash[DPP_MAX_HASH_LEN];
1516 const u8 *addr[3];
1517 size_t len[3];
1518 unsigned int num_elem = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001519 struct crypto_ec_point *Qr = NULL;
1520 struct crypto_ec_key *Pr_key = NULL;
1521 const struct crypto_ec_point *Pr = NULL;
1522 struct crypto_bignum *hash_bn = NULL;
1523 struct crypto_ec *ec = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001524
Hai Shaloma20dcd72022-02-04 13:43:00 -08001525 /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001526
Hai Shaloma20dcd72022-02-04 13:43:00 -08001527 if (mac_resp) {
1528 wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
1529 MAC2STR(mac_resp));
1530 addr[num_elem] = mac_resp;
1531 len[num_elem] = ETH_ALEN;
1532 num_elem++;
1533 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001534 if (identifier) {
1535 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1536 identifier);
1537 addr[num_elem] = (const u8 *) identifier;
1538 len[num_elem] = os_strlen(identifier);
1539 num_elem++;
1540 }
1541 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1542 addr[num_elem] = (const u8 *) code;
1543 len[num_elem] = os_strlen(code);
1544 num_elem++;
1545 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1546 goto fail;
1547 wpa_hexdump_key(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001548 "DPP: H([MAC-Responder |] [identifier |] code)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001549 hash, curve->hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001550 Pr_key = dpp_pkex_get_role_elem(curve, 0);
1551 if (!Pr_key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001552 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001553 dpp_debug_print_key("DPP: Pr", Pr_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001554
Hai Shaloma20dcd72022-02-04 13:43:00 -08001555 ec = crypto_ec_init(curve->ike_group);
1556 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001557 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001558
1559 Pr = crypto_ec_key_get_public_key(Pr_key);
1560 Qr = crypto_ec_point_init(ec);
1561 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1562 if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001563 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001564
1565 if (crypto_ec_point_is_at_infinity(ec, Qr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001566 wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1567 goto fail;
1568 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001569 crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
1570
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001571out:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001572 crypto_ec_key_deinit(Pr_key);
1573 crypto_bignum_deinit(hash_bn, 1);
1574 if (ret_ec && Qr)
1575 *ret_ec = ec;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001576 else
Hai Shaloma20dcd72022-02-04 13:43:00 -08001577 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001578 return Qr;
1579fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001580 crypto_ec_point_deinit(Qr, 1);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001581 Qr = NULL;
1582 goto out;
1583}
1584
1585
1586int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001587 u8 ver_init, u8 ver_resp,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001588 const u8 *Mx, size_t Mx_len,
1589 const u8 *Nx, size_t Nx_len,
1590 const char *code,
1591 const u8 *Kx, size_t Kx_len,
1592 u8 *z, unsigned int hash_len)
1593{
1594 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1595 int res;
1596 u8 *info, *pos;
1597 size_t info_len;
1598
Hai Shaloma20dcd72022-02-04 13:43:00 -08001599 /*
1600 * v1: info = MAC-Initiator | MAC-Responder
1601 * v2: info = Protocol Version-Initiator | Protocol Version-Responder
1602 * z = HKDF(<>, info | M.x | N.x | code, K.x)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001603 */
1604
1605 /* HKDF-Extract(<>, IKM=K.x) */
1606 os_memset(salt, 0, hash_len);
1607 if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1608 return -1;
1609 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1610 prk, hash_len);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001611 if (mac_init && mac_resp)
1612 info_len = 2 * ETH_ALEN;
1613 else
1614 info_len = 2;
1615 info_len += Mx_len + Nx_len + os_strlen(code);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001616 info = os_malloc(info_len);
1617 if (!info)
1618 return -1;
1619 pos = info;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001620 if (mac_init && mac_resp) {
1621 os_memcpy(pos, mac_init, ETH_ALEN);
1622 pos += ETH_ALEN;
1623 os_memcpy(pos, mac_resp, ETH_ALEN);
1624 pos += ETH_ALEN;
1625 } else {
1626 *pos++ = ver_init;
1627 *pos++ = ver_resp;
1628 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001629 os_memcpy(pos, Mx, Mx_len);
1630 pos += Mx_len;
1631 os_memcpy(pos, Nx, Nx_len);
1632 pos += Nx_len;
1633 os_memcpy(pos, code, os_strlen(code));
1634
1635 /* HKDF-Expand(PRK, info, L) */
1636 if (hash_len == 32)
1637 res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1638 z, hash_len);
1639 else if (hash_len == 48)
1640 res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1641 z, hash_len);
1642 else if (hash_len == 64)
1643 res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1644 z, hash_len);
1645 else
1646 res = -1;
1647 os_free(info);
1648 os_memset(prk, 0, hash_len);
1649 if (res < 0)
1650 return -1;
1651
1652 wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1653 z, hash_len);
1654 return 0;
1655}
1656
1657
1658int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1659 const u8 *net_access_key,
1660 size_t net_access_key_len,
1661 struct json_token *peer_net_access_key)
1662{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001663 struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
1664 struct crypto_bignum *sum = NULL;
1665 const struct crypto_bignum *q, *cR, *pR;
1666 struct crypto_ec *ec = NULL;
1667 struct crypto_ec_point *M = NULL;
1668 const struct crypto_ec_point *CI;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001669 u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1670 u8 prk[DPP_MAX_HASH_LEN];
1671 const struct dpp_curve_params *curve;
1672 int res = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07001673 u8 nonces[2 * DPP_MAX_NONCE_LEN];
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001674
1675 own_key = dpp_set_keypair(&auth->curve, net_access_key,
1676 net_access_key_len);
1677 if (!own_key) {
1678 dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1679 goto fail;
1680 }
1681
1682 peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1683 if (!peer_key)
1684 goto fail;
1685 dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1686
1687 if (auth->curve != curve) {
1688 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001689 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001690 auth->curve->name, curve->name);
1691 goto fail;
1692 }
1693
1694 auth->own_protocol_key = dpp_gen_keypair(curve);
1695 if (!auth->own_protocol_key)
1696 goto fail;
1697
Hai Shalom899fcc72020-10-19 14:38:18 -07001698 if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1699 wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1700 goto fail;
1701 }
1702 wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1703 auth->e_nonce, auth->curve->nonce_len);
1704
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001705 /* M = { cR + pR } * CI */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001706 ec = crypto_ec_init(curve->ike_group);
1707 if (!ec)
Hai Shalom60840252021-02-19 19:02:11 -08001708 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001709
1710 sum = crypto_bignum_init();
1711 q = crypto_ec_get_order(ec);
1712 M = crypto_ec_point_init(ec);
1713 cR = crypto_ec_key_get_private_key(own_key);
1714 pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1715 CI = crypto_ec_key_get_public_key(peer_key);
1716 if (!sum || !q || !M || !cR || !pR || !CI ||
1717 crypto_bignum_addmod(cR, pR, q, sum) ||
1718 crypto_ec_point_mul(ec, CI, sum, M) ||
1719 crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1720 wpa_printf(MSG_ERROR, "DPP: Error during M computation");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001721 goto fail;
1722 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001723 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1724
Hai Shalom899fcc72020-10-19 14:38:18 -07001725 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001726
Hai Shalom899fcc72020-10-19 14:38:18 -07001727 /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1728 os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1729 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1730 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001731 Mx, curve->prime_len, prk) < 0)
1732 goto fail;
1733 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1734
1735 /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1736 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1737 "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1738 goto fail;
1739 wpa_hexdump_key(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001740 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001741 auth->ke, curve->hash_len);
1742
1743 res = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001744 crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001745 auth->reconfig_old_protocol_key = own_key;
1746 own_key = NULL;
1747fail:
1748 forced_memzero(prk, sizeof(prk));
1749 forced_memzero(Mx, sizeof(Mx));
Hai Shaloma20dcd72022-02-04 13:43:00 -08001750 crypto_ec_point_deinit(M, 1);
1751 crypto_bignum_deinit(sum, 1);
1752 crypto_ec_key_deinit(own_key);
1753 crypto_ec_key_deinit(peer_key);
1754 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001755 return res;
1756}
1757
1758
1759int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1760 const u8 *r_proto, u16 r_proto_len,
1761 struct json_token *net_access_key)
1762{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001763 struct crypto_ec_key *pr = NULL, *peer_key = NULL;
1764 const struct crypto_ec_point *CR, *PR;
1765 const struct crypto_bignum *cI;
1766 struct crypto_ec *ec = NULL;
1767 struct crypto_ec_point *sum = NULL, *M = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001768 u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1769 u8 prk[DPP_MAX_HASH_LEN];
1770 int res = -1;
1771 const struct dpp_curve_params *curve;
Hai Shalom899fcc72020-10-19 14:38:18 -07001772 u8 nonces[2 * DPP_MAX_NONCE_LEN];
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001773
1774 pr = dpp_set_pubkey_point(auth->conf->connector_key,
1775 r_proto, r_proto_len);
1776 if (!pr) {
1777 dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1778 goto fail;
1779 }
1780 dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001781 crypto_ec_key_deinit(auth->peer_protocol_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001782 auth->peer_protocol_key = pr;
1783 pr = NULL;
1784
1785 peer_key = dpp_parse_jwk(net_access_key, &curve);
1786 if (!peer_key)
1787 goto fail;
1788 dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1789 if (auth->curve != curve) {
1790 wpa_printf(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001791 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001792 auth->curve->name, curve->name);
1793 goto fail;
1794 }
1795
1796 /* M = cI * { CR + PR } */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001797 ec = crypto_ec_init(curve->ike_group);
1798 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001799 goto fail;
1800
Hai Shaloma20dcd72022-02-04 13:43:00 -08001801 cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
1802 sum = crypto_ec_point_init(ec);
1803 M = crypto_ec_point_init(ec);
1804 CR = crypto_ec_key_get_public_key(peer_key);
1805 PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1806 if (!cI || !sum || !M || !CR || !PR ||
1807 crypto_ec_point_add(ec, CR, PR, sum) ||
1808 crypto_ec_point_mul(ec, sum, cI, M) ||
1809 crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1810 wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1811 goto fail;
1812 }
1813
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001814 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1815
Hai Shalom899fcc72020-10-19 14:38:18 -07001816 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001817
Hai Shalom899fcc72020-10-19 14:38:18 -07001818 /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1819 os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1820 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1821 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001822 Mx, curve->prime_len, prk) < 0)
1823 goto fail;
1824 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1825
1826 /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1827 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1828 "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1829 goto fail;
1830 wpa_hexdump_key(MSG_DEBUG,
Hai Shalom899fcc72020-10-19 14:38:18 -07001831 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001832 auth->ke, curve->hash_len);
1833
1834 res = 0;
1835fail:
1836 forced_memzero(prk, sizeof(prk));
1837 forced_memzero(Mx, sizeof(Mx));
Hai Shaloma20dcd72022-02-04 13:43:00 -08001838 crypto_ec_key_deinit(pr);
1839 crypto_ec_key_deinit(peer_key);
1840 crypto_ec_point_deinit(sum, 1);
1841 crypto_ec_point_deinit(M, 1);
1842 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001843 return res;
1844}
1845
1846
1847static char *
1848dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1849{
1850 struct wpabuf *jws_prot_hdr;
1851 char *signed1;
1852
1853 jws_prot_hdr = wpabuf_alloc(100);
1854 if (!jws_prot_hdr)
1855 return NULL;
1856 json_start_object(jws_prot_hdr, NULL);
1857 json_add_string(jws_prot_hdr, "typ", "dppCon");
1858 json_value_sep(jws_prot_hdr);
1859 json_add_string(jws_prot_hdr, "kid", conf->kid);
1860 json_value_sep(jws_prot_hdr);
1861 json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1862 json_end_object(jws_prot_hdr);
1863 signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1864 wpabuf_len(jws_prot_hdr),
1865 signed1_len);
1866 wpabuf_free(jws_prot_hdr);
1867 return signed1;
1868}
1869
1870
1871static char *
1872dpp_build_conn_signature(struct dpp_configurator *conf,
1873 const char *signed1, size_t signed1_len,
1874 const char *signed2, size_t signed2_len,
1875 size_t *signed3_len)
1876{
1877 const struct dpp_curve_params *curve;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001878 struct wpabuf *sig = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001879 char *signed3 = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001880 char *dot = ".";
Hai Shaloma20dcd72022-02-04 13:43:00 -08001881 const u8 *vector[3];
1882 size_t vector_len[3];
1883 u8 *hash;
1884 int ret;
1885
1886 vector[0] = (const u8 *) signed1;
1887 vector[1] = (const u8 *) dot;
1888 vector[2] = (const u8 *) signed2;
1889 vector_len[0] = signed1_len;
1890 vector_len[1] = 1;
1891 vector_len[2] = signed2_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001892
1893 curve = conf->curve;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001894 hash = os_malloc(curve->hash_len);
1895 if (!hash)
1896 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001897 if (curve->hash_len == SHA256_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001898 ret = sha256_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001899 } else if (curve->hash_len == SHA384_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001900 ret = sha384_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001901 } else if (curve->hash_len == SHA512_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001902 ret = sha512_vector(3, vector, vector_len, hash);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001903 } else {
1904 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1905 goto fail;
1906 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001907 if (ret) {
1908 wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
1909 goto fail;
1910 }
1911 wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
1912 hash, curve->hash_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001913
Hai Shaloma20dcd72022-02-04 13:43:00 -08001914 sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
1915 if (!sig) {
1916 wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001917 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001918 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001919
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001920 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
Hai Shaloma20dcd72022-02-04 13:43:00 -08001921 wpabuf_head(sig), wpabuf_len(sig));
1922 signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
1923 signed3_len);
1924
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001925fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001926 os_free(hash);
1927 wpabuf_free(sig);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001928 return signed3;
1929}
1930
1931char * dpp_sign_connector(struct dpp_configurator *conf,
1932 const struct wpabuf *dppcon)
1933{
1934 char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1935 char *signed_conn = NULL, *pos;
1936 size_t signed1_len, signed2_len, signed3_len;
1937
1938 signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1939 signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1940 &signed2_len);
1941 if (!signed1 || !signed2)
1942 goto fail;
1943
1944 signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1945 signed2, signed2_len, &signed3_len);
1946 if (!signed3)
1947 goto fail;
1948
1949 signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1950 if (!signed_conn)
1951 goto fail;
1952 pos = signed_conn;
1953 os_memcpy(pos, signed1, signed1_len);
1954 pos += signed1_len;
1955 *pos++ = '.';
1956 os_memcpy(pos, signed2, signed2_len);
1957 pos += signed2_len;
1958 *pos++ = '.';
1959 os_memcpy(pos, signed3, signed3_len);
1960 pos += signed3_len;
1961 *pos = '\0';
1962
1963fail:
1964 os_free(signed1);
1965 os_free(signed2);
1966 os_free(signed3);
1967 return signed_conn;
1968}
1969
1970
1971#ifdef CONFIG_DPP2
1972
1973struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
1974 size_t net_access_key_len)
1975{
1976 struct wpabuf *pub = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001977 struct crypto_ec_key *own_key;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001978 struct dpp_pfs *pfs;
1979
1980 pfs = os_zalloc(sizeof(*pfs));
1981 if (!pfs)
1982 return NULL;
1983
1984 own_key = dpp_set_keypair(&pfs->curve, net_access_key,
1985 net_access_key_len);
1986 if (!own_key) {
1987 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
1988 goto fail;
1989 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001990 crypto_ec_key_deinit(own_key);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001991
1992 pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
1993 if (!pfs->ecdh)
1994 goto fail;
1995
1996 pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
1997 pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
1998 if (!pub)
1999 goto fail;
2000
2001 pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2002 if (!pfs->ie)
2003 goto fail;
2004 wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2005 wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2006 wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2007 wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2008 wpabuf_put_buf(pfs->ie, pub);
2009 wpabuf_free(pub);
2010 wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2011 pfs->ie);
2012
2013 return pfs;
2014fail:
2015 wpabuf_free(pub);
2016 dpp_pfs_free(pfs);
2017 return NULL;
2018}
2019
2020
2021int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2022{
2023 if (peer_ie_len < 2)
2024 return -1;
2025 if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2026 wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2027 return -1;
2028 }
2029
2030 pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2031 peer_ie_len - 2);
2032 pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2033 if (!pfs->secret) {
2034 wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2035 return -1;
2036 }
2037 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2038 return 0;
2039}
2040
2041
2042void dpp_pfs_free(struct dpp_pfs *pfs)
2043{
2044 if (!pfs)
2045 return;
2046 crypto_ecdh_deinit(pfs->ecdh);
2047 wpabuf_free(pfs->ie);
2048 wpabuf_clear_free(pfs->secret);
2049 os_free(pfs);
2050}
2051
Hai Shalom899fcc72020-10-19 14:38:18 -07002052
2053struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2054{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002055 struct crypto_csr *csr = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002056 struct wpabuf *buf = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002057 struct crypto_ec_key *key;
Hai Shalom899fcc72020-10-19 14:38:18 -07002058 unsigned int hash_len = auth->curve->hash_len;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002059 struct wpabuf *priv_key;
Hai Shalom899fcc72020-10-19 14:38:18 -07002060 u8 cp[DPP_CP_LEN];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002061 char *password = NULL;
2062 size_t password_len = 0;
2063 int hash_sign_algo;
Hai Shalom899fcc72020-10-19 14:38:18 -07002064
2065 /* TODO: use auth->csrattrs */
2066
2067 /* TODO: support generation of a new private key if csrAttrs requests
2068 * a specific group to be used */
2069 key = auth->own_protocol_key;
2070
Hai Shaloma20dcd72022-02-04 13:43:00 -08002071 priv_key = crypto_ec_key_get_ecprivate_key(key, true);
2072 if (!priv_key)
Hai Shalom899fcc72020-10-19 14:38:18 -07002073 goto fail;
2074 wpabuf_free(auth->priv_key);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002075 auth->priv_key = priv_key;
2076
2077 csr = crypto_csr_init();
2078 if (!csr || crypto_csr_set_ec_public_key(csr, key))
Hai Shalom899fcc72020-10-19 14:38:18 -07002079 goto fail;
2080
Hai Shaloma20dcd72022-02-04 13:43:00 -08002081 if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
Hai Shalom899fcc72020-10-19 14:38:18 -07002082 goto fail;
2083
Hai Shalom899fcc72020-10-19 14:38:18 -07002084 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2085 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2086 "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2087 goto fail;
2088 wpa_hexdump_key(MSG_DEBUG,
2089 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2090 cp, DPP_CP_LEN);
2091 password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2092 forced_memzero(cp, DPP_CP_LEN);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002093 if (!password ||
2094 crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2095 ASN1_TAG_UTF8STRING, (const u8 *) password,
2096 password_len))
Hai Shalom899fcc72020-10-19 14:38:18 -07002097 goto fail;
2098
Hai Shalom899fcc72020-10-19 14:38:18 -07002099 /* TODO: hash func selection based on csrAttrs */
2100 if (hash_len == SHA256_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002101 hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
Hai Shalom899fcc72020-10-19 14:38:18 -07002102 } else if (hash_len == SHA384_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002103 hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07002104 } else if (hash_len == SHA512_MAC_LEN) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002105 hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
Hai Shalom899fcc72020-10-19 14:38:18 -07002106 } else {
2107 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2108 goto fail;
2109 }
2110
Hai Shaloma20dcd72022-02-04 13:43:00 -08002111 buf = crypto_csr_sign(csr, key, hash_sign_algo);
2112 if (!buf)
Hai Shalom899fcc72020-10-19 14:38:18 -07002113 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -07002114 wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2115
2116fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002117 bin_clear_free(password, password_len);
2118 crypto_csr_deinit(csr);
Hai Shalom899fcc72020-10-19 14:38:18 -07002119 return buf;
2120}
2121
2122
Hai Shaloma20dcd72022-02-04 13:43:00 -08002123int dpp_validate_csr(struct dpp_authentication *auth,
2124 const struct wpabuf *csrbuf)
Hai Shalom899fcc72020-10-19 14:38:18 -07002125{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002126 struct crypto_csr *csr;
2127 const u8 *attr;
2128 size_t attr_len;
2129 int attr_type;
Hai Shalom899fcc72020-10-19 14:38:18 -07002130 unsigned char *cp = NULL;
2131 size_t cp_len;
2132 u8 exp_cp[DPP_CP_LEN];
2133 unsigned int hash_len = auth->curve->hash_len;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002134 int ret = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07002135
Hai Shaloma20dcd72022-02-04 13:43:00 -08002136 csr = crypto_csr_verify(csrbuf);
2137 if (!csr) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002138 wpa_printf(MSG_DEBUG,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002139 "DPP: CSR invalid or invalid signature");
Hai Shalom899fcc72020-10-19 14:38:18 -07002140 goto fail;
2141 }
2142
Hai Shaloma20dcd72022-02-04 13:43:00 -08002143 attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2144 &attr_len, &attr_type);
2145 if (!attr) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002146 wpa_printf(MSG_DEBUG,
2147 "DPP: CSR does not include challengePassword");
2148 goto fail;
2149 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002150 /* This is supposed to be UTF8String, but allow other strings as well
2151 * since challengePassword is using ASCII (base64 encoded). */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002152 if (attr_type != ASN1_TAG_UTF8STRING &&
2153 attr_type != ASN1_TAG_PRINTABLESTRING &&
2154 attr_type != ASN1_TAG_IA5STRING) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002155 wpa_printf(MSG_DEBUG,
2156 "DPP: Unexpected challengePassword attribute type %d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002157 attr_type);
Hai Shalom899fcc72020-10-19 14:38:18 -07002158 goto fail;
2159 }
2160
Hai Shaloma20dcd72022-02-04 13:43:00 -08002161 cp = base64_decode((const char *) attr, attr_len, &cp_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002162 if (!cp) {
2163 wpa_printf(MSG_DEBUG,
2164 "DPP: Could not base64 decode challengePassword");
2165 goto fail;
2166 }
2167 if (cp_len != DPP_CP_LEN) {
2168 wpa_printf(MSG_DEBUG,
2169 "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2170 cp_len);
2171 goto fail;
2172 }
2173 wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2174 cp, cp_len);
2175
2176 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2177 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2178 "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2179 goto fail;
2180 wpa_hexdump_key(MSG_DEBUG,
2181 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2182 exp_cp, DPP_CP_LEN);
2183 if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2184 wpa_printf(MSG_DEBUG,
2185 "DPP: CSR challengePassword does not match calculated cp");
2186 goto fail;
2187 }
2188
2189 ret = 0;
2190fail:
2191 os_free(cp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002192 crypto_csr_deinit(csr);
Hai Shalom899fcc72020-10-19 14:38:18 -07002193 return ret;
2194}
2195
2196
2197struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2198 size_t csign_key_len,
2199 const u8 *pp_key,
2200 size_t pp_key_len)
2201{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002202 struct crypto_ec_key *csign = NULL, *ppkey = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002203 struct dpp_reconfig_id *id = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002204 struct crypto_ec *ec = NULL;
2205 const struct crypto_bignum *q;
2206 struct crypto_bignum *bn = NULL;
2207 struct crypto_ec_point *e_id = NULL;
2208 const struct crypto_ec_point *generator;
Hai Shalom899fcc72020-10-19 14:38:18 -07002209
Hai Shaloma20dcd72022-02-04 13:43:00 -08002210 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002211 if (!csign)
2212 goto fail;
2213
2214 if (!pp_key)
2215 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002216 ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002217 if (!ppkey)
2218 goto fail;
2219
Hai Shaloma20dcd72022-02-04 13:43:00 -08002220 ec = crypto_ec_init(crypto_ec_key_group(csign));
2221 if (!ec)
Hai Shalom899fcc72020-10-19 14:38:18 -07002222 goto fail;
2223
Hai Shaloma20dcd72022-02-04 13:43:00 -08002224 e_id = crypto_ec_point_init(ec);
2225 bn = crypto_bignum_init();
2226 q = crypto_ec_get_order(ec);
2227 generator = crypto_ec_get_generator(ec);
2228 if (!e_id || !bn || !q || !generator ||
2229 crypto_bignum_rand(bn, q) ||
2230 crypto_ec_point_mul(ec, generator, bn, e_id))
Hai Shalom899fcc72020-10-19 14:38:18 -07002231 goto fail;
2232
Hai Shaloma20dcd72022-02-04 13:43:00 -08002233 crypto_ec_point_debug_print(ec, e_id,
2234 "DPP: Generated random point E-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002235
2236 id = os_zalloc(sizeof(*id));
2237 if (!id)
2238 goto fail;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002239
2240 id->ec = ec;
2241 ec = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07002242 id->e_id = e_id;
2243 e_id = NULL;
2244 id->csign = csign;
2245 csign = NULL;
2246 id->pp_key = ppkey;
2247 ppkey = NULL;
2248fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002249 crypto_ec_point_deinit(e_id, 1);
2250 crypto_ec_key_deinit(csign);
2251 crypto_ec_key_deinit(ppkey);
2252 crypto_bignum_deinit(bn, 1);
2253 crypto_ec_deinit(ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002254 return id;
2255}
2256
2257
Hai Shalom899fcc72020-10-19 14:38:18 -07002258int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2259{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002260 const struct crypto_bignum *q;
2261 struct crypto_bignum *bn;
2262 const struct crypto_ec_point *pp, *generator;
2263 struct crypto_ec_point *e_prime_id, *a_nonce;
Hai Shalom899fcc72020-10-19 14:38:18 -07002264 int ret = -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07002265
Hai Shaloma20dcd72022-02-04 13:43:00 -08002266 pp = crypto_ec_key_get_public_key(id->pp_key);
2267 e_prime_id = crypto_ec_point_init(id->ec);
2268 a_nonce = crypto_ec_point_init(id->ec);
2269 bn = crypto_bignum_init();
2270 q = crypto_ec_get_order(id->ec);
2271 generator = crypto_ec_get_generator(id->ec);
2272
Hai Shalom899fcc72020-10-19 14:38:18 -07002273 /* Generate random 0 <= a-nonce < q
2274 * A-NONCE = a-nonce * G
2275 * E'-id = E-id + a-nonce * P_pk */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002276 if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
2277 crypto_bignum_rand(bn, q) || /* bn = a-nonce */
2278 crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
2279 crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
2280 crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
Hai Shalom899fcc72020-10-19 14:38:18 -07002281 goto fail;
2282
Hai Shaloma20dcd72022-02-04 13:43:00 -08002283 crypto_ec_point_debug_print(id->ec, a_nonce,
2284 "DPP: Generated A-NONCE");
2285 crypto_ec_point_debug_print(id->ec, e_prime_id,
2286 "DPP: Encrypted E-id to E'-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002287
Hai Shaloma20dcd72022-02-04 13:43:00 -08002288 crypto_ec_key_deinit(id->a_nonce);
2289 crypto_ec_key_deinit(id->e_prime_id);
2290 id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
2291 id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
Hai Shalom899fcc72020-10-19 14:38:18 -07002292 if (!id->a_nonce || !id->e_prime_id)
2293 goto fail;
2294
2295 ret = 0;
2296
2297fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002298 crypto_ec_point_deinit(e_prime_id, 1);
2299 crypto_ec_point_deinit(a_nonce, 1);
2300 crypto_bignum_deinit(bn, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07002301 return ret;
2302}
2303
2304
2305void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2306{
2307 if (id) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002308 crypto_ec_point_deinit(id->e_id, 1);
2309 crypto_ec_key_deinit(id->csign);
2310 crypto_ec_key_deinit(id->a_nonce);
2311 crypto_ec_key_deinit(id->e_prime_id);
2312 crypto_ec_key_deinit(id->pp_key);
2313 crypto_ec_deinit(id->ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002314 os_free(id);
2315 }
2316}
2317
2318
Hai Shaloma20dcd72022-02-04 13:43:00 -08002319struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
2320 struct crypto_ec_key *a_nonce,
2321 struct crypto_ec_key *e_prime_id)
Hai Shalom899fcc72020-10-19 14:38:18 -07002322{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002323 struct crypto_ec *ec;
2324 const struct crypto_bignum *pp;
2325 struct crypto_ec_point *e_id = NULL;
2326 const struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
Hai Shalom899fcc72020-10-19 14:38:18 -07002327
2328 if (!ppkey)
2329 return NULL;
2330
2331 /* E-id = E'-id - s_C * A-NONCE */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002332 ec = crypto_ec_init(crypto_ec_key_group(ppkey));
2333 if (!ec)
Hai Shalom899fcc72020-10-19 14:38:18 -07002334 return NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002335
2336 pp = crypto_ec_key_get_private_key(ppkey);
2337 a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
2338 e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
2339 e_id = crypto_ec_point_init(ec);
2340 if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
2341 crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
2342 crypto_ec_point_invert(ec, e_id) ||
2343 crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
2344 crypto_ec_point_deinit(e_id, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07002345 goto fail;
2346 }
2347
Hai Shaloma20dcd72022-02-04 13:43:00 -08002348 crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
Hai Shalom899fcc72020-10-19 14:38:18 -07002349
2350fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002351 crypto_ec_deinit(ec);
Hai Shalom899fcc72020-10-19 14:38:18 -07002352 return e_id;
2353}
2354
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002355#endif /* CONFIG_DPP2 */
2356
2357
2358#ifdef CONFIG_TESTING_OPTIONS
2359
2360int dpp_test_gen_invalid_key(struct wpabuf *msg,
2361 const struct dpp_curve_params *curve)
2362{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002363 struct crypto_ec *ec;
2364 struct crypto_ec_key *key = NULL;
2365 const struct crypto_ec_point *pub_key;
2366 struct crypto_ec_point *p = NULL;
2367 u8 *x, *y;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002368 int ret = -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002369
Hai Shaloma20dcd72022-02-04 13:43:00 -08002370 ec = crypto_ec_init(curve->ike_group);
2371 x = wpabuf_put(msg, curve->prime_len);
2372 y = wpabuf_put(msg, curve->prime_len);
2373 if (!ec)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002374 goto fail;
2375
Hai Shaloma20dcd72022-02-04 13:43:00 -08002376retry:
2377 /* Generate valid key pair */
2378 key = crypto_ec_key_gen(curve->ike_group);
2379 if (!key)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002380 goto fail;
2381
Hai Shaloma20dcd72022-02-04 13:43:00 -08002382 /* Retrieve public key coordinates */
2383 pub_key = crypto_ec_key_get_public_key(key);
2384 if (!pub_key)
2385 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002386
Hai Shaloma20dcd72022-02-04 13:43:00 -08002387 crypto_ec_point_to_bin(ec, pub_key, x, y);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002388
Hai Shaloma20dcd72022-02-04 13:43:00 -08002389 /* And corrupt them */
2390 y[curve->prime_len - 1] ^= 0x01;
2391 p = crypto_ec_point_from_bin(ec, x);
2392 if (p && crypto_ec_point_is_on_curve(ec, p)) {
2393 crypto_ec_point_deinit(p, 0);
2394 p = NULL;
2395 goto retry;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002396 }
2397
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002398 ret = 0;
2399fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002400 crypto_ec_point_deinit(p, 0);
2401 crypto_ec_key_deinit(key);
2402 crypto_ec_deinit(ec);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002403 return ret;
2404}
2405
2406
2407char * dpp_corrupt_connector_signature(const char *connector)
2408{
2409 char *tmp, *pos, *signed3 = NULL;
2410 unsigned char *signature = NULL;
2411 size_t signature_len = 0, signed3_len;
2412
2413 tmp = os_zalloc(os_strlen(connector) + 5);
2414 if (!tmp)
2415 goto fail;
2416 os_memcpy(tmp, connector, os_strlen(connector));
2417
2418 pos = os_strchr(tmp, '.');
2419 if (!pos)
2420 goto fail;
2421
2422 pos = os_strchr(pos + 1, '.');
2423 if (!pos)
2424 goto fail;
2425 pos++;
2426
2427 wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2428 pos);
2429 signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2430 if (!signature || signature_len == 0)
2431 goto fail;
2432 wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2433 signature, signature_len);
2434 signature[signature_len - 1] ^= 0x01;
2435 wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2436 signature, signature_len);
2437 signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2438 if (!signed3)
2439 goto fail;
2440 os_memcpy(pos, signed3, signed3_len);
2441 pos[signed3_len] = '\0';
2442 wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2443 pos);
2444
2445out:
2446 os_free(signature);
2447 os_free(signed3);
2448 return tmp;
2449fail:
2450 os_free(tmp);
2451 tmp = NULL;
2452 goto out;
2453}
2454
2455#endif /* CONFIG_TESTING_OPTIONS */