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_gen_keypair(const struct dpp_curve_params * curve)249 struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
250 {
251 struct crypto_ec_key *key;
252
253 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
254
255 key = crypto_ec_key_gen(curve->ike_group);
256 if (key && wpa_debug_show_keys)
257 dpp_debug_print_key("Own generated key", key);
258
259 return key;
260 }
261
262
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)263 struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
264 const u8 *privkey, size_t privkey_len)
265 {
266 struct crypto_ec_key *key;
267 int group;
268
269 key = crypto_ec_key_parse_priv(privkey, privkey_len);
270 if (!key) {
271 wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
272 return NULL;
273 }
274
275 group = crypto_ec_key_group(key);
276 if (group < 0) {
277 crypto_ec_key_deinit(key);
278 return NULL;
279 }
280
281 *curve = dpp_get_curve_ike_group(group);
282 if (!*curve) {
283 wpa_printf(MSG_INFO,
284 "DPP: Unsupported curve (group=%d) in pre-assigned key",
285 group);
286 crypto_ec_key_deinit(key);
287 return NULL;
288 }
289
290 return key;
291 }
292
293
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)294 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
295 {
296 struct wpabuf *der;
297 int res;
298
299 der = crypto_ec_key_get_subject_public_key(bi->pubkey);
300 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
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,const u8 * privkey,size_t privkey_len)312 int 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
334 der = crypto_ec_key_get_subject_public_key(bi->pubkey);
335 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;
361 fail:
362 os_free(base64);
363 wpabuf_free(der);
364 return -1;
365 }
366
367
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)368 int 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
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)395 int 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
dpp_derive_bk_ke(struct dpp_authentication * auth)423 int 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
467 /* ke = HKDF-Expand(bk, "DPP Key", length) */
468 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
dpp_ecdh(struct crypto_ec_key * own,struct crypto_ec_key * peer,u8 * secret,size_t * secret_len)481 int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
482 u8 *secret, size_t *secret_len)
483 {
484 struct crypto_ecdh *ecdh;
485 struct wpabuf *peer_pub, *secret_buf = NULL;
486 int ret = -1;
487
488 *secret_len = 0;
489
490 ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
491 if (!ecdh) {
492 wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
493 return -1;
494 }
495
496 peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
497 if (!peer_pub) {
498 wpa_printf(MSG_ERROR,
499 "DPP: crypto_ec_key_get_pubkey_point() failed");
500 goto fail;
501 }
502
503 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");
507 goto fail;
508 }
509
510 if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
511 wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
512 goto fail;
513 }
514
515 *secret_len = wpabuf_len(secret_buf);
516 os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
517 ret = 0;
518
519 fail:
520 wpabuf_clear_free(secret_buf);
521 wpabuf_free(peer_pub);
522 crypto_ecdh_deinit(ecdh);
523 return ret;
524 }
525
526
dpp_bi_pubkey_hash(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)527 int 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
dpp_get_subject_public_key(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)553 int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
554 const u8 *data, size_t data_len)
555 {
556 struct crypto_ec_key *key;
557
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
563 key = crypto_ec_key_parse_pub(data, data_len);
564 if (!key) {
565 wpa_printf(MSG_DEBUG,
566 "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
567 return -1;
568 }
569
570 bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
571 if (!bi->curve) {
572 wpa_printf(MSG_DEBUG,
573 "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
574 crypto_ec_key_group(key));
575 goto fail;
576 }
577
578 bi->pubkey = key;
579 return 0;
580 fail:
581 crypto_ec_key_deinit(key);
582 return -1;
583 }
584
585
586 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)587 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
588 const u8 *prot_hdr, u16 prot_hdr_len,
589 int *hash_func)
590 {
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 ||
635 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;
645 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
659 fail:
660 json_free(root);
661 return kid;
662 }
663
664
dpp_check_pubkey_match(struct crypto_ec_key * pub,struct wpabuf * r_hash)665 static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
666 struct wpabuf *r_hash)
667 {
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;
676 uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
677 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
698 enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_ec_key * csign_pub,const char * connector)699 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
700 struct crypto_ec_key *csign_pub,
701 const char *connector)
702 {
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;
707 size_t prot_hdr_len = 0, signature_len = 0, signed_len;
708 int res, hash_func = -1;
709 const struct dpp_curve_params *curve;
710 u8 *hash = NULL;
711
712 curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
713 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);
735 kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
736 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
791 hash = os_malloc(curve->hash_len);
792 if (!hash)
793 goto fail;
794
795 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
806 goto fail;
807
808 if (res)
809 goto fail;
810
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);
816 if (res != 1) {
817 wpa_printf(MSG_DEBUG,
818 "DPP: signedConnector signature check failed (res=%d)",
819 res);
820 ret = DPP_STATUS_INVALID_CONNECTOR;
821 goto fail;
822 }
823
824 ret = DPP_STATUS_OK;
825 fail:
826 os_free(hash);
827 os_free(prot_hdr);
828 wpabuf_free(kid);
829 os_free(signature);
830 return ret;
831 }
832
833
834 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)835 dpp_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 {
839 struct crypto_ec_key *csign;
840 char *signed_connector = NULL;
841 enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
842
843 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
844 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);
858 fail:
859 os_free(signed_connector);
860 crypto_ec_key_deinit(csign);
861 return res;
862 }
863
864
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)865 int 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) {
879 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);
882 if (auth->own_bi)
883 bix = crypto_ec_key_get_pubkey_point(
884 auth->own_bi->pubkey, 0);
885 else
886 bix = NULL;
887 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
888 } else {
889 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);
892 if (auth->peer_bi)
893 bix = crypto_ec_key_get_pubkey_point(
894 auth->peer_bi->pubkey, 0);
895 else
896 bix = NULL;
897 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
898 }
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);
939 fail:
940 wpabuf_free(pix);
941 wpabuf_free(prx);
942 wpabuf_free(bix);
943 wpabuf_free(brx);
944 return res;
945 }
946
947
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)948 int 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) {
962 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);
965 if (auth->own_bi)
966 bix = crypto_ec_key_get_pubkey_point(
967 auth->own_bi->pubkey, 0);
968 else
969 bix = NULL;
970 if (!auth->peer_bi)
971 goto fail;
972 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
973 } else {
974 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);
977 if (auth->peer_bi)
978 bix = crypto_ec_key_get_pubkey_point(
979 auth->peer_bi->pubkey, 0);
980 else
981 bix = NULL;
982 if (!auth->own_bi)
983 goto fail;
984 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
985 }
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);
1026 fail:
1027 wpabuf_free(pix);
1028 wpabuf_free(prx);
1029 wpabuf_free(bix);
1030 wpabuf_free(brx);
1031 return res;
1032 }
1033
1034
dpp_auth_derive_l_responder(struct dpp_authentication * auth)1035 int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1036 {
1037 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;
1042 int ret = -1;
1043
1044 /* L = ((bR + pR) modulo q) * BI */
1045
1046 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1047 if (!ec)
1048 goto fail;
1049
1050 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)
1063 goto fail;
1064
1065 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1066 auth->Lx_len = auth->secret_len;
1067 ret = 0;
1068 fail:
1069 crypto_bignum_deinit(lx, 1);
1070 crypto_bignum_deinit(sum, 1);
1071 crypto_ec_point_deinit(L, 1);
1072 crypto_ec_deinit(ec);
1073 return ret;
1074 }
1075
1076
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)1077 int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1078 {
1079 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;
1084 int ret = -1;
1085
1086 /* L = bI * (BR + PR) */
1087
1088 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1089 if (!ec)
1090 goto fail;
1091
1092 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)
1104 goto fail;
1105
1106 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1107 auth->Lx_len = auth->secret_len;
1108 ret = 0;
1109 fail:
1110 crypto_bignum_deinit(lx, 1);
1111 crypto_ec_point_deinit(sum, 1);
1112 crypto_ec_point_deinit(L, 1);
1113 crypto_ec_deinit(ec);
1114 return ret;
1115 }
1116
1117
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)1118 int 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
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_ec_key * own_key,struct crypto_ec_key * peer_key,u8 * pmkid)1145 int dpp_derive_pmkid(const struct dpp_curve_params *curve,
1146 struct crypto_ec_key *own_key,
1147 struct crypto_ec_key *peer_key, u8 *pmkid)
1148 {
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))) */
1156 nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
1157 pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
1158 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;
1179 fail:
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 */
1189 static 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 };
1195 static 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 };
1201 static 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 };
1207 static 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 */
1215 static 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 };
1223 static 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 };
1231 static 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 };
1239 static 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 */
1249 static 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 };
1260 static 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 };
1271 static 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 };
1282 static 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 */
1295 static 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 };
1301 static 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 };
1307 static 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 };
1313 static 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 */
1321 static 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 };
1329 static 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 };
1337 static 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 };
1345 static 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 */
1355 static 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 };
1365 static 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 };
1375 static 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 };
1385 static 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
1397 static struct crypto_ec_key *
dpp_pkex_get_role_elem(const struct dpp_curve_params * curve,int init)1398 dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
1399 {
1400 const u8 *x, *y;
1401
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
1431 return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
1432 }
1433
1434
1435 struct crypto_ec_point *
dpp_pkex_derive_Qi(const struct dpp_curve_params * curve,const u8 * mac_init,const char * code,const char * identifier,struct crypto_ec ** ret_ec)1436 dpp_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)
1439 {
1440 u8 hash[DPP_MAX_HASH_LEN];
1441 const u8 *addr[3];
1442 size_t len[3];
1443 unsigned int num_elem = 0;
1444 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;
1449
1450 /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
1451
1452 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 }
1459 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,
1473 "DPP: H([MAC-Initiator |] [identifier |] code)",
1474 hash, curve->hash_len);
1475 Pi_key = dpp_pkex_get_role_elem(curve, 1);
1476 if (!Pi_key)
1477 goto fail;
1478 dpp_debug_print_key("DPP: Pi", Pi_key);
1479
1480 ec = crypto_ec_init(curve->ike_group);
1481 if (!ec)
1482 goto fail;
1483
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))
1488 goto fail;
1489
1490 if (crypto_ec_point_is_at_infinity(ec, Qi)) {
1491 wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1492 goto fail;
1493 }
1494 crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
1495 out:
1496 crypto_ec_key_deinit(Pi_key);
1497 crypto_bignum_deinit(hash_bn, 1);
1498 if (ret_ec && Qi)
1499 *ret_ec = ec;
1500 else
1501 crypto_ec_deinit(ec);
1502 return Qi;
1503 fail:
1504 crypto_ec_point_deinit(Qi, 1);
1505 Qi = NULL;
1506 goto out;
1507 }
1508
1509
1510 struct crypto_ec_point *
dpp_pkex_derive_Qr(const struct dpp_curve_params * curve,const u8 * mac_resp,const char * code,const char * identifier,struct crypto_ec ** ret_ec)1511 dpp_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)
1514 {
1515 u8 hash[DPP_MAX_HASH_LEN];
1516 const u8 *addr[3];
1517 size_t len[3];
1518 unsigned int num_elem = 0;
1519 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;
1524
1525 /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
1526
1527 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 }
1534 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,
1548 "DPP: H([MAC-Responder |] [identifier |] code)",
1549 hash, curve->hash_len);
1550 Pr_key = dpp_pkex_get_role_elem(curve, 0);
1551 if (!Pr_key)
1552 goto fail;
1553 dpp_debug_print_key("DPP: Pr", Pr_key);
1554
1555 ec = crypto_ec_init(curve->ike_group);
1556 if (!ec)
1557 goto fail;
1558
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))
1563 goto fail;
1564
1565 if (crypto_ec_point_is_at_infinity(ec, Qr)) {
1566 wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1567 goto fail;
1568 }
1569 crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
1570
1571 out:
1572 crypto_ec_key_deinit(Pr_key);
1573 crypto_bignum_deinit(hash_bn, 1);
1574 if (ret_ec && Qr)
1575 *ret_ec = ec;
1576 else
1577 crypto_ec_deinit(ec);
1578 return Qr;
1579 fail:
1580 crypto_ec_point_deinit(Qr, 1);
1581 Qr = NULL;
1582 goto out;
1583 }
1584
1585
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,const u8 * Kx,size_t Kx_len,u8 * z,unsigned int hash_len)1586 int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
1587 u8 ver_init, u8 ver_resp,
1588 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
1599 /*
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)
1603 */
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);
1611 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);
1616 info = os_malloc(info_len);
1617 if (!info)
1618 return -1;
1619 pos = info;
1620 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 }
1629 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
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)1658 int 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 {
1663 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;
1669 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;
1673 u8 nonces[2 * DPP_MAX_NONCE_LEN];
1674
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,
1689 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1690 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
1698 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
1705 /* M = { cR + pR } * CI */
1706 ec = crypto_ec_init(curve->ike_group);
1707 if (!ec)
1708 goto fail;
1709
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");
1721 goto fail;
1722 }
1723 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1724
1725 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1726
1727 /* 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,
1731 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,
1740 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1741 auth->ke, curve->hash_len);
1742
1743 res = 0;
1744 crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1745 auth->reconfig_old_protocol_key = own_key;
1746 own_key = NULL;
1747 fail:
1748 forced_memzero(prk, sizeof(prk));
1749 forced_memzero(Mx, sizeof(Mx));
1750 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);
1755 return res;
1756 }
1757
1758
dpp_reconfig_derive_ke_initiator(struct dpp_authentication * auth,const u8 * r_proto,u16 r_proto_len,struct json_token * net_access_key)1759 int 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 {
1763 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;
1768 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;
1772 u8 nonces[2 * DPP_MAX_NONCE_LEN];
1773
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);
1781 crypto_ec_key_deinit(auth->peer_protocol_key);
1782 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,
1791 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1792 auth->curve->name, curve->name);
1793 goto fail;
1794 }
1795
1796 /* M = cI * { CR + PR } */
1797 ec = crypto_ec_init(curve->ike_group);
1798 if (!ec)
1799 goto fail;
1800
1801 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
1814 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1815
1816 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1817
1818 /* 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,
1822 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,
1831 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1832 auth->ke, curve->hash_len);
1833
1834 res = 0;
1835 fail:
1836 forced_memzero(prk, sizeof(prk));
1837 forced_memzero(Mx, sizeof(Mx));
1838 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);
1843 return res;
1844 }
1845
1846
1847 static char *
dpp_build_jws_prot_hdr(struct dpp_configurator * conf,size_t * signed1_len)1848 dpp_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
1871 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)1872 dpp_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;
1878 struct wpabuf *sig = NULL;
1879 char *signed3 = NULL;
1880 char *dot = ".";
1881 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;
1892
1893 curve = conf->curve;
1894 hash = os_malloc(curve->hash_len);
1895 if (!hash)
1896 goto fail;
1897 if (curve->hash_len == SHA256_MAC_LEN) {
1898 ret = sha256_vector(3, vector, vector_len, hash);
1899 } else if (curve->hash_len == SHA384_MAC_LEN) {
1900 ret = sha384_vector(3, vector, vector_len, hash);
1901 } else if (curve->hash_len == SHA512_MAC_LEN) {
1902 ret = sha512_vector(3, vector, vector_len, hash);
1903 } else {
1904 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1905 goto fail;
1906 }
1907 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);
1913
1914 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");
1917 goto fail;
1918 }
1919
1920 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
1921 wpabuf_head(sig), wpabuf_len(sig));
1922 signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
1923 signed3_len);
1924
1925 fail:
1926 os_free(hash);
1927 wpabuf_free(sig);
1928 return signed3;
1929 }
1930
dpp_sign_connector(struct dpp_configurator * conf,const struct wpabuf * dppcon)1931 char * 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
1963 fail:
1964 os_free(signed1);
1965 os_free(signed2);
1966 os_free(signed3);
1967 return signed_conn;
1968 }
1969
1970
1971 #ifdef CONFIG_DPP2
1972
dpp_pfs_init(const u8 * net_access_key,size_t net_access_key_len)1973 struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
1974 size_t net_access_key_len)
1975 {
1976 struct wpabuf *pub = NULL;
1977 struct crypto_ec_key *own_key;
1978 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 }
1990 crypto_ec_key_deinit(own_key);
1991
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;
2014 fail:
2015 wpabuf_free(pub);
2016 dpp_pfs_free(pfs);
2017 return NULL;
2018 }
2019
2020
dpp_pfs_process(struct dpp_pfs * pfs,const u8 * peer_ie,size_t peer_ie_len)2021 int 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
dpp_pfs_free(struct dpp_pfs * pfs)2042 void 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
2052
dpp_build_csr(struct dpp_authentication * auth,const char * name)2053 struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2054 {
2055 struct crypto_csr *csr = NULL;
2056 struct wpabuf *buf = NULL;
2057 struct crypto_ec_key *key;
2058 unsigned int hash_len = auth->curve->hash_len;
2059 struct wpabuf *priv_key;
2060 u8 cp[DPP_CP_LEN];
2061 char *password = NULL;
2062 size_t password_len;
2063 int hash_sign_algo;
2064
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
2071 priv_key = crypto_ec_key_get_ecprivate_key(key, true);
2072 if (!priv_key)
2073 goto fail;
2074 wpabuf_free(auth->priv_key);
2075 auth->priv_key = priv_key;
2076
2077 csr = crypto_csr_init();
2078 if (!csr || crypto_csr_set_ec_public_key(csr, key))
2079 goto fail;
2080
2081 if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
2082 goto fail;
2083
2084 /* 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);
2093 if (!password ||
2094 crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2095 ASN1_TAG_UTF8STRING, (const u8 *) password,
2096 password_len))
2097 goto fail;
2098
2099 /* TODO: hash func selection based on csrAttrs */
2100 if (hash_len == SHA256_MAC_LEN) {
2101 hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
2102 } else if (hash_len == SHA384_MAC_LEN) {
2103 hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
2104 } else if (hash_len == SHA512_MAC_LEN) {
2105 hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
2106 } else {
2107 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2108 goto fail;
2109 }
2110
2111 buf = crypto_csr_sign(csr, key, hash_sign_algo);
2112 if (!buf)
2113 goto fail;
2114 wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2115
2116 fail:
2117 bin_clear_free(password, password_len);
2118 crypto_csr_deinit(csr);
2119 return buf;
2120 }
2121
2122
dpp_validate_csr(struct dpp_authentication * auth,const struct wpabuf * csrbuf)2123 int dpp_validate_csr(struct dpp_authentication *auth,
2124 const struct wpabuf *csrbuf)
2125 {
2126 struct crypto_csr *csr;
2127 const u8 *attr;
2128 size_t attr_len;
2129 int attr_type;
2130 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;
2134 int ret = -1;
2135
2136 csr = crypto_csr_verify(csrbuf);
2137 if (!csr) {
2138 wpa_printf(MSG_DEBUG,
2139 "DPP: CSR invalid or invalid signature");
2140 goto fail;
2141 }
2142
2143 attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2144 &attr_len, &attr_type);
2145 if (!attr) {
2146 wpa_printf(MSG_DEBUG,
2147 "DPP: CSR does not include challengePassword");
2148 goto fail;
2149 }
2150 /* This is supposed to be UTF8String, but allow other strings as well
2151 * since challengePassword is using ASCII (base64 encoded). */
2152 if (attr_type != ASN1_TAG_UTF8STRING &&
2153 attr_type != ASN1_TAG_PRINTABLESTRING &&
2154 attr_type != ASN1_TAG_IA5STRING) {
2155 wpa_printf(MSG_DEBUG,
2156 "DPP: Unexpected challengePassword attribute type %d",
2157 attr_type);
2158 goto fail;
2159 }
2160
2161 cp = base64_decode((const char *) attr, attr_len, &cp_len);
2162 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;
2190 fail:
2191 os_free(cp);
2192 crypto_csr_deinit(csr);
2193 return ret;
2194 }
2195
2196
dpp_gen_reconfig_id(const u8 * csign_key,size_t csign_key_len,const u8 * pp_key,size_t pp_key_len)2197 struct 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 {
2202 struct crypto_ec_key *csign = NULL, *ppkey = NULL;
2203 struct dpp_reconfig_id *id = NULL;
2204 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;
2209
2210 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
2211 if (!csign)
2212 goto fail;
2213
2214 if (!pp_key)
2215 goto fail;
2216 ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
2217 if (!ppkey)
2218 goto fail;
2219
2220 ec = crypto_ec_init(crypto_ec_key_group(csign));
2221 if (!ec)
2222 goto fail;
2223
2224 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))
2231 goto fail;
2232
2233 crypto_ec_point_debug_print(ec, e_id,
2234 "DPP: Generated random point E-id");
2235
2236 id = os_zalloc(sizeof(*id));
2237 if (!id)
2238 goto fail;
2239
2240 id->ec = ec;
2241 ec = NULL;
2242 id->e_id = e_id;
2243 e_id = NULL;
2244 id->csign = csign;
2245 csign = NULL;
2246 id->pp_key = ppkey;
2247 ppkey = NULL;
2248 fail:
2249 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);
2254 return id;
2255 }
2256
2257
dpp_update_reconfig_id(struct dpp_reconfig_id * id)2258 int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2259 {
2260 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;
2264 int ret = -1;
2265
2266 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
2273 /* Generate random 0 <= a-nonce < q
2274 * A-NONCE = a-nonce * G
2275 * E'-id = E-id + a-nonce * P_pk */
2276 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))
2281 goto fail;
2282
2283 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");
2287
2288 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);
2292 if (!id->a_nonce || !id->e_prime_id)
2293 goto fail;
2294
2295 ret = 0;
2296
2297 fail:
2298 crypto_ec_point_deinit(e_prime_id, 1);
2299 crypto_ec_point_deinit(a_nonce, 1);
2300 crypto_bignum_deinit(bn, 1);
2301 return ret;
2302 }
2303
2304
dpp_free_reconfig_id(struct dpp_reconfig_id * id)2305 void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2306 {
2307 if (id) {
2308 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);
2314 os_free(id);
2315 }
2316 }
2317
2318
dpp_decrypt_e_id(struct crypto_ec_key * ppkey,struct crypto_ec_key * a_nonce,struct crypto_ec_key * e_prime_id)2319 struct 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)
2322 {
2323 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;
2327
2328 if (!ppkey)
2329 return NULL;
2330
2331 /* E-id = E'-id - s_C * A-NONCE */
2332 ec = crypto_ec_init(crypto_ec_key_group(ppkey));
2333 if (!ec)
2334 return NULL;
2335
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);
2345 goto fail;
2346 }
2347
2348 crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
2349
2350 fail:
2351 crypto_ec_deinit(ec);
2352 return e_id;
2353 }
2354
2355 #endif /* CONFIG_DPP2 */
2356
2357
2358 #ifdef CONFIG_DPP3
dpp_derive_auth_i(struct dpp_authentication * auth,u8 * auth_i)2359 int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
2360 {
2361 int ret = -1, res;
2362 u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
2363 size_t Sx_len;
2364 unsigned int hash_len;
2365 const char *info = "New DPP Protocol Key";
2366 const u8 *addr[3];
2367 size_t len[3];
2368 u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
2369 struct wpabuf *pcx = NULL, *pex = NULL;
2370
2371 hash_len = auth->curve->hash_len;
2372
2373 /*
2374 * Configurator: S = pc * Pe
2375 * Enrollee: S = pe * Pc
2376 * k = HKDF(bk, "New DPP Protocol Key", S.x)
2377 * = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
2378 * len(new-curve-hash-out))
2379 * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)
2380 *
2381 * auth->own_protocol_key and auth->peer_protocol_key have already been
2382 * updated to use the new keys. The new curve determines the size of
2383 * the (new) protocol keys and S.x. The other parameters (bk, hash
2384 * algorithm, k) are determined based on the initially determined curve
2385 * during the (re)authentication exchange.
2386 */
2387
2388 if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2389 Sx, &Sx_len) < 0)
2390 goto fail;
2391
2392 wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
2393
2394 /* tmp = HKDF-Extract(bk, S.x) */
2395 addr[0] = Sx;
2396 len[0] = Sx_len;
2397 res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp);
2398 if (res < 0)
2399 goto fail;
2400 wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
2401 tmp, hash_len);
2402 /* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output))
2403 */
2404 res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
2405 if (res < 0)
2406 return -1;
2407
2408 wpa_hexdump_key(MSG_DEBUG,
2409 "DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
2410 k, hash_len);
2411
2412 /* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */
2413 addr[0] = auth->e_nonce;
2414 len[0] = auth->curve->nonce_len;
2415
2416 if (auth->configurator) {
2417 pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2418 pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2419 0);
2420 } else {
2421 pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2422 0);
2423 pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2424 }
2425 if (!pcx || !pex)
2426 goto fail;
2427 addr[1] = wpabuf_head(pcx);
2428 len[1] = wpabuf_len(pcx) / 2;
2429 addr[2] = wpabuf_head(pex);
2430 len[2] = wpabuf_len(pex) / 2;
2431
2432 if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0)
2433 goto fail;
2434 wpa_hexdump_key(MSG_DEBUG,
2435 "DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)",
2436 auth_i, hash_len);
2437 ret = 0;
2438 fail:
2439 forced_memzero(Sx, sizeof(Sx));
2440 forced_memzero(tmp, sizeof(tmp));
2441 forced_memzero(k, sizeof(k));
2442 wpabuf_free(pcx);
2443 wpabuf_free(pex);
2444 return ret;
2445 }
2446 #endif /* CONFIG_DPP3 */
2447
2448
2449 #ifdef CONFIG_TESTING_OPTIONS
2450
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)2451 int dpp_test_gen_invalid_key(struct wpabuf *msg,
2452 const struct dpp_curve_params *curve)
2453 {
2454 struct crypto_ec *ec;
2455 struct crypto_ec_key *key = NULL;
2456 const struct crypto_ec_point *pub_key;
2457 struct crypto_ec_point *p = NULL;
2458 u8 *x, *y;
2459 int ret = -1;
2460
2461 ec = crypto_ec_init(curve->ike_group);
2462 x = wpabuf_put(msg, curve->prime_len);
2463 y = wpabuf_put(msg, curve->prime_len);
2464 if (!ec)
2465 goto fail;
2466
2467 retry:
2468 /* Generate valid key pair */
2469 key = crypto_ec_key_gen(curve->ike_group);
2470 if (!key)
2471 goto fail;
2472
2473 /* Retrieve public key coordinates */
2474 pub_key = crypto_ec_key_get_public_key(key);
2475 if (!pub_key)
2476 goto fail;
2477
2478 crypto_ec_point_to_bin(ec, pub_key, x, y);
2479
2480 /* And corrupt them */
2481 y[curve->prime_len - 1] ^= 0x01;
2482 p = crypto_ec_point_from_bin(ec, x);
2483 if (p && crypto_ec_point_is_on_curve(ec, p)) {
2484 crypto_ec_point_deinit(p, 0);
2485 p = NULL;
2486 goto retry;
2487 }
2488
2489 ret = 0;
2490 fail:
2491 crypto_ec_point_deinit(p, 0);
2492 crypto_ec_key_deinit(key);
2493 crypto_ec_deinit(ec);
2494 return ret;
2495 }
2496
2497
dpp_corrupt_connector_signature(const char * connector)2498 char * dpp_corrupt_connector_signature(const char *connector)
2499 {
2500 char *tmp, *pos, *signed3 = NULL;
2501 unsigned char *signature = NULL;
2502 size_t signature_len = 0, signed3_len;
2503
2504 tmp = os_zalloc(os_strlen(connector) + 5);
2505 if (!tmp)
2506 goto fail;
2507 os_memcpy(tmp, connector, os_strlen(connector));
2508
2509 pos = os_strchr(tmp, '.');
2510 if (!pos)
2511 goto fail;
2512
2513 pos = os_strchr(pos + 1, '.');
2514 if (!pos)
2515 goto fail;
2516 pos++;
2517
2518 wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2519 pos);
2520 signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2521 if (!signature || signature_len == 0)
2522 goto fail;
2523 wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2524 signature, signature_len);
2525 signature[signature_len - 1] ^= 0x01;
2526 wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2527 signature, signature_len);
2528 signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2529 if (!signed3)
2530 goto fail;
2531 os_memcpy(pos, signed3, signed3_len);
2532 pos[signed3_len] = '\0';
2533 wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2534 pos);
2535
2536 out:
2537 os_free(signature);
2538 os_free(signed3);
2539 return tmp;
2540 fail:
2541 os_free(tmp);
2542 tmp = NULL;
2543 goto out;
2544 }
2545
2546 #endif /* CONFIG_TESTING_OPTIONS */
2547