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