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