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