1 /*
2  * DPP functionality shared between hostapd and wpa_supplicant
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2019, 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 <fcntl.h>
12 
13 #include "utils/common.h"
14 #include "common/defs.h"
15 #include "utils/base64.h"
16 #include "utils/json.h"
17 #include "crypto/crypto.h"
18 #include "crypto/random.h"
19 #include "crypto/aes.h"
20 #include "crypto/aes_siv.h"
21 #include "crypto/sha256.h"
22 #include "dpp.h"
23 
24 static const char * dpp_netrole_str(enum dpp_netrole netrole);
25 
26 #ifdef CONFIG_WPA_TESTING_OPTIONS
27 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
28 u8 dpp_protocol_key_override[600];
29 size_t dpp_protocol_key_override_len = 0;
30 u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
31 size_t dpp_nonce_override_len = 0;
32 
33 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
34 				    const struct dpp_curve_params *curve);
35 #endif /* CONFIG_WPA_TESTING_OPTIONS */
36 
37 struct dpp_global {
38 	void *msg_ctx;
39 	struct dl_list bootstrap; /* struct dpp_bootstrap_info */
40 	struct dl_list configurator; /* struct dpp_configurator */
41 };
42 
43 static const struct dpp_curve_params dpp_curves[] = {
44 	/* The mandatory to support and the default NIST P-256 curve needs to
45 	 * be the first entry on this list. */
46 	{ "sec256r1", 32, 32, 16, 32, "P-256", 19, "ES256" },
47 	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
48 	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
49 	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
50 	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
51 	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
52 	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
53 };
54 
55 static struct wpabuf *
gas_build_req(u8 action,u8 dialog_token,size_t size)56 gas_build_req(u8 action, u8 dialog_token, size_t size)
57 {
58     struct wpabuf *buf;
59 
60     buf = wpabuf_alloc(100 + size);
61     if (buf == NULL)
62         return NULL;
63 
64     wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
65     wpabuf_put_u8(buf, action);
66     wpabuf_put_u8(buf, dialog_token);
67 
68     return buf;
69 }
70 
71 
gas_build_initial_req(u8 dialog_token,size_t size)72 struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
73 {
74     return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
75                  size);
76 }
77 
dpp_debug_print_key(const char * title,struct crypto_key * key)78 static void dpp_debug_print_key(const char *title, struct crypto_key *key)
79 {
80     crypto_debug_print_ec_key(title, key);
81 }
82 
dpp_debug_print_point(const char * title,struct crypto_ec * e,const struct crypto_ec_point * point)83 void dpp_debug_print_point(const char *title, struct crypto_ec *e,
84 				  const struct crypto_ec_point *point)
85 {
86 	u8 x[64], y[64];
87 
88 	if (crypto_ec_point_to_bin(e, point, x, y) < 0) {
89 		printf("error: failed to get corrdinates\n");
90 		return;
91 	}
92 
93 	wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x, y);
94 }
95 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)96 static int dpp_hash_vector(const struct dpp_curve_params *curve,
97 			   size_t num_elem, const u8 *addr[], const size_t *len,
98 			   u8 *mac)
99 {
100 	if (curve->hash_len == 32)
101 		return sha256_vector(num_elem, addr, len, mac);
102 #ifndef ESP_SUPPLICANT
103 	if (curve->hash_len == 48)
104 		return sha384_vector(num_elem, addr, len, mac);
105 	if (curve->hash_len == 64)
106 		return sha512_vector(num_elem, addr, len, mac);
107 #endif
108 	return -1;
109 }
110 
111 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)112 static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
113 			   const char *label, u8 *out, size_t outlen)
114 {
115 	if (hash_len == 32)
116 		return hmac_sha256_kdf(secret, secret_len, NULL,
117 				       (const u8 *) label, os_strlen(label),
118 				       out, outlen);
119 #ifndef ESP_SUPPLICANT
120 	if (hash_len == 48)
121 		return hmac_sha384_kdf(secret, secret_len, NULL,
122 				       (const u8 *) label, os_strlen(label),
123 				       out, outlen);
124 	if (hash_len == 64)
125 		return hmac_sha512_kdf(secret, secret_len, NULL,
126 				       (const u8 *) label, os_strlen(label),
127 				       out, outlen);
128 #endif
129 	return -1;
130 }
131 
132 
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)133 static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
134 			   size_t num_elem, const u8 *addr[],
135 			   const size_t *len, u8 *mac)
136 {
137 	if (hash_len == 32)
138 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
139 					  mac);
140 #ifndef ESP_SUPPLICANT
141 	if (hash_len == 48)
142 		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
143 					  mac);
144 	if (hash_len == 64)
145 		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
146 					  mac);
147 #endif
148 	return -1;
149 }
150 
151 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)152 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
153 		    const u8 *data, size_t data_len, u8 *mac)
154 {
155 	if (hash_len == 32)
156 		return hmac_sha256(key, key_len, data, data_len, mac);
157 #ifndef ESP_SUPPLICANT
158 	if (hash_len == 48)
159 		return hmac_sha384(key, key_len, data, data_len, mac);
160 	if (hash_len == 64)
161 		return hmac_sha512(key, key_len, data, data_len, mac);
162 #endif
163 	return -1;
164 }
165 
166 
dpp_bn2bin_pad(const struct crypto_bignum * bn,u8 * pos,size_t len)167 static int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len)
168 {
169 	if (crypto_bignum_to_bin(bn, pos, len, 0) < 0)
170 		return -1;
171 
172 	return 0;
173 }
174 
dpp_get_pubkey_point(struct crypto_key * pkey,int prefix)175 static struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix)
176 {
177 	int len, res;
178 	struct wpabuf *buf;
179 	unsigned char *pos = NULL;
180 
181 	len = crypto_ec_get_publickey_buf(pkey, pos, 0);
182 	if (len <= 0) {
183 		wpa_printf(MSG_ERROR,
184 			   "DDP: Failed to determine public key encoding length");
185 		return NULL;
186 	}
187 
188 	buf = wpabuf_alloc(len);
189 	if (!buf) {
190 		return NULL;
191 	}
192 
193 	pos = wpabuf_put(buf, len);
194 
195 	res = crypto_ec_get_publickey_buf(pkey, pos, len);
196 	if (res != len) {
197 		wpa_printf(MSG_ERROR,
198 			   "DDP: Failed to encode public key (res=%d/%d)",
199 			   res, len);
200 		wpabuf_free(buf);
201 		return NULL;
202 	}
203 
204 	if (!prefix) {
205 		/* Remove 0x04 prefix to match DPP definition */
206 		pos = wpabuf_mhead(buf);
207 		os_memmove(pos, pos + 1, len - 1);
208 		buf->used--;
209 	}
210 
211 	return buf;
212 }
213 
dpp_set_pubkey_point(struct crypto_key * group_key,const u8 * buf,size_t len)214 static struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key,
215 				       const u8 *buf, size_t len)
216 {
217 	const struct crypto_ec_group *group;
218 	struct crypto_key *pkey = NULL;
219 
220 	if (len & 1)
221 		return NULL;
222 
223 	group = crypto_ec_get_group_from_key(group_key);
224 	if (group)
225 		pkey = crypto_ec_set_pubkey_point(group, buf,
226 						  len);
227 	else
228 		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
229 
230 	return pkey;
231 }
232 
dpp_ecdh(struct crypto_key * own,struct crypto_key * peer,u8 * secret,size_t * secret_len)233 static int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer,
234 		    u8 *secret, size_t *secret_len)
235 {
236     return crypto_ecdh(own, peer, secret, secret_len);
237 }
238 
239 
dpp_auth_fail(struct dpp_authentication * auth,const char * txt)240 static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
241 {
242 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
243 }
244 
245 
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)246 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
247 			      size_t len)
248 {
249 	struct wpabuf *msg;
250 
251 	msg = wpabuf_alloc(8 + len);
252 	if (!msg)
253 		return NULL;
254 	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
255 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
256 	wpabuf_put_be24(msg, OUI_WFA);
257 	wpabuf_put_u8(msg, DPP_OUI_TYPE);
258 	wpabuf_put_u8(msg, 1); /* Crypto Suite */
259 	wpabuf_put_u8(msg, type);
260 	return msg;
261 }
262 
263 
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)264 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
265 {
266 	u16 id, alen;
267 	const u8 *pos = buf, *end = buf + len;
268 
269 	while (end - pos >= 4) {
270 		id = WPA_GET_LE16(pos);
271 		pos += 2;
272 		alen = WPA_GET_LE16(pos);
273 		pos += 2;
274 		if (alen > end - pos)
275 			return NULL;
276 		if (id == req_id) {
277 			*ret_len = alen;
278 			return pos;
279 		}
280 		pos += alen;
281 	}
282 
283 	return NULL;
284 }
285 
286 
dpp_get_attr_next(const u8 * prev,const u8 * buf,size_t len,u16 req_id,u16 * ret_len)287 static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len,
288 				    u16 req_id, u16 *ret_len)
289 {
290 	u16 id, alen;
291 	const u8 *pos, *end = buf + len;
292 
293 	if (!prev)
294 		pos = buf;
295 	else
296 		pos = prev + WPA_GET_LE16(prev - 2);
297 	while (end - pos >= 4) {
298 		id = WPA_GET_LE16(pos);
299 		pos += 2;
300 		alen = WPA_GET_LE16(pos);
301 		pos += 2;
302 		if (alen > end - pos)
303 			return NULL;
304 		if (id == req_id) {
305 			*ret_len = alen;
306 			return pos;
307 		}
308 		pos += alen;
309 	}
310 
311 	return NULL;
312 }
313 
314 
dpp_check_attrs(const u8 * buf,size_t len)315 int dpp_check_attrs(const u8 *buf, size_t len)
316 {
317 	const u8 *pos, *end;
318 	int wrapped_data = 0;
319 
320 	pos = buf;
321 	end = buf + len;
322 	while (end - pos >= 4) {
323 		u16 id, alen;
324 
325 		id = WPA_GET_LE16(pos);
326 		pos += 2;
327 		alen = WPA_GET_LE16(pos);
328 		pos += 2;
329 		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
330 			   id, alen);
331 		if (alen > end - pos) {
332 			wpa_printf(MSG_DEBUG,
333 				   "DPP: Truncated message - not enough room for the attribute - dropped");
334 			return -1;
335 		}
336 		if (wrapped_data) {
337 			wpa_printf(MSG_DEBUG,
338 				   "DPP: An unexpected attribute included after the Wrapped Data attribute");
339 			return -1;
340 		}
341 		if (id == DPP_ATTR_WRAPPED_DATA)
342 			wrapped_data = 1;
343 		pos += alen;
344 	}
345 
346 	if (end != pos) {
347 		wpa_printf(MSG_DEBUG,
348 			   "DPP: Unexpected octets (%d) after the last attribute",
349 			   (int) (end - pos));
350 		return -1;
351 	}
352 
353 	return 0;
354 }
355 
356 
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)357 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
358 {
359 	if (!info)
360 		return;
361 	os_free(info->uri);
362 	os_free(info->info);
363 	crypto_ec_free_key(info->pubkey);
364 	os_free(info);
365 }
366 
367 
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)368 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
369 {
370 	switch (type) {
371 	case DPP_BOOTSTRAP_QR_CODE:
372 		return "QRCODE";
373 	case DPP_BOOTSTRAP_PKEX:
374 		return "PKEX";
375 	case DPP_BOOTSTRAP_NFC_URI:
376 		return "NFC-URI";
377 	}
378 	return "??";
379 }
380 
381 
dpp_uri_valid_info(const char * info)382 static int dpp_uri_valid_info(const char *info)
383 {
384 	while (*info) {
385 		unsigned char val = *info++;
386 
387 		if (val < 0x20 || val > 0x7e || val == 0x3b)
388 			return 0;
389 	}
390 
391 	return 1;
392 }
393 
394 
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)395 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
396 {
397 	bi->uri = os_strdup(uri);
398 	return bi->uri ? 0 : -1;
399 }
400 
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)401 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
402 			    const char *chan_list)
403 {
404 #ifndef ESP_SUPPLICANT
405 	const char *pos = chan_list, *pos2;
406 	int opclass = -1, channel, freq;
407 
408 	while (pos && *pos && *pos != ';') {
409 		pos2 = pos;
410 		while (*pos2 >= '0' && *pos2 <= '9')
411 			pos2++;
412 		if (*pos2 == '/') {
413 			opclass = atoi(pos);
414 			pos = pos2 + 1;
415 		}
416 		if (opclass <= 0)
417 			goto fail;
418 		channel = atoi(pos);
419 		if (channel <= 0)
420 			goto fail;
421 		while (*pos >= '0' && *pos <= '9')
422 			pos++;
423 		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
424 		wpa_printf(MSG_DEBUG,
425 			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
426 			   opclass, channel, freq);
427 		if (freq < 0) {
428 			wpa_printf(MSG_DEBUG,
429 				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
430 				   opclass, channel);
431 		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
432 			wpa_printf(MSG_DEBUG,
433 				   "DPP: Too many channels in URI channel-list - ignore list");
434 			bi->num_freq = 0;
435 			break;
436 		} else {
437 			bi->freq[bi->num_freq++] = freq;
438 		}
439 
440 		if (*pos == ';' || *pos == '\0')
441 			break;
442 		if (*pos != ',')
443 			goto fail;
444 		pos++;
445 	}
446 
447 	return 0;
448 fail:
449 	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
450 	return -1;
451 #endif
452 	return 0;
453 }
454 
455 
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)456 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
457 {
458 	if (!mac)
459 		return 0;
460 
461 	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
462 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
463 		return -1;
464 	}
465 
466 	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
467 
468 	return 0;
469 }
470 
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)471 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
472 {
473 	const char *end;
474 
475 	if (!info)
476 		return 0;
477 
478 	end = os_strchr(info, ';');
479 	if (!end)
480 		end = info + os_strlen(info);
481 	bi->info = os_malloc(end - info + 1);
482 	if (!bi->info)
483 		return -1;
484 	os_memcpy(bi->info, info, end - info);
485 	bi->info[end - info] = '\0';
486 	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
487 	if (!dpp_uri_valid_info(bi->info)) {
488 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
489 		return -1;
490 	}
491 
492 	return 0;
493 }
494 
dpp_get_curve_group_id(int group_id)495 static const struct dpp_curve_params * dpp_get_curve_group_id(int group_id)
496 {
497 	unsigned int i;
498 
499 	if (!group_id)
500 		return NULL;
501 
502 	for (i = 0; dpp_curves[i].ike_group; i++) {
503         if (group_id == dpp_curves[i].ike_group)
504 			return &dpp_curves[i];
505 	}
506 	return NULL;
507 }
508 
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)509 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
510 {
511 	const char *end;
512 	u8 *data;
513 	size_t data_len;
514 	struct crypto_key *pkey;
515 	const unsigned char *p;
516 	struct crypto_ec_group *group;
517 	int id;
518 
519 	end = os_strchr(info, ';');
520 	if (!end)
521 		return -1;
522 
523 	data = (unsigned char *)base64_decode(info, end - info, &data_len);
524 	if (!data) {
525 		wpa_printf(MSG_DEBUG,
526 			   "DPP: Invalid base64 encoding on URI public-key");
527 		return -1;
528 	}
529 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
530 		    data, data_len);
531 
532 	if (sha256_vector(1, (const u8 **) &data, &data_len,
533 			  bi->pubkey_hash) < 0) {
534 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
535 		os_free(data);
536 		return -1;
537 	}
538 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
539 		    bi->pubkey_hash, SHA256_MAC_LEN);
540 
541 	/* DER encoded ASN.1 SubjectPublicKeyInfo
542 	 *
543 	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
544 	 *      algorithm            AlgorithmIdentifier,
545 	 *      subjectPublicKey     BIT STRING  }
546 	 *
547 	 * AlgorithmIdentifier  ::=  SEQUENCE  {
548 	 *      algorithm               OBJECT IDENTIFIER,
549 	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
550 	 *
551 	 * subjectPublicKey = compressed format public key per ANSI X9.63
552 	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
553 	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
554 	 *       prime256v1 (1.2.840.10045.3.1.7)
555 	 */
556 
557 	p = data;
558 
559 	pkey = crypto_ec_parse_subpub_key((unsigned char *)p, data_len);
560 	os_free(data);
561 
562 	if (!pkey) {
563 		wpa_printf(MSG_DEBUG,
564 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
565 		return -1;
566 	}
567 
568 	if (!crypto_is_ec_key(pkey)) {
569 		wpa_printf(MSG_DEBUG,
570 				"DPP: SubjectPublicKeyInfo does not describe an EC key");
571 		crypto_ec_free_key(pkey);
572 		return -1;
573 	}
574 
575 	group = crypto_ec_get_group_from_key(pkey);
576 	if (!group) {
577 		return -1;
578 	}
579 	id = crypto_ec_get_curve_id(group);
580 	bi->curve = dpp_get_curve_group_id(id);
581 	if (!bi->curve) {
582 		wpa_printf(MSG_DEBUG,
583 			   "DPP: Unsupported SubjectPublicKeyInfo curve");
584 		goto fail;
585 	}
586 
587 	bi->pubkey = pkey;
588 	return 0;
589 fail:
590 	crypto_ec_free_key(pkey);
591 	return -1;
592 }
593 
594 
dpp_parse_uri(const char * uri)595 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
596 {
597 	const char *pos = uri;
598 	const char *end;
599 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
600 	struct dpp_bootstrap_info *bi;
601 
602 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", (u8 *)uri, os_strlen(uri));
603 
604 	if (os_strncmp(pos, "DPP:", 4) != 0) {
605 		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
606 		return NULL;
607 	}
608 	pos += 4;
609 
610 	for (;;) {
611 		end = os_strchr(pos, ';');
612 		if (!end)
613 			break;
614 
615 		if (end == pos) {
616 			/* Handle terminating ";;" and ignore unexpected ";"
617 			 * for parsing robustness. */
618 			pos++;
619 			continue;
620 		}
621 
622 		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
623 			chan_list = pos + 2;
624 		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
625 			mac = pos + 2;
626 		else if (pos[0] == 'I' && pos[1] == ':' && !info)
627 			info = pos + 2;
628 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
629 			pk = pos + 2;
630 		else
631 			wpa_hexdump_ascii(MSG_DEBUG,
632 					  "DPP: Ignore unrecognized URI parameter",
633 					  (u8 *)pos, end - pos);
634 		pos = end + 1;
635 	}
636 
637 	if (!pk) {
638 		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
639 		return NULL;
640 	}
641 
642 	bi = os_zalloc(sizeof(*bi));
643 	if (!bi)
644 		return NULL;
645 
646 	if (dpp_clone_uri(bi, uri) < 0 ||
647 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
648 	    dpp_parse_uri_mac(bi, mac) < 0 ||
649 	    dpp_parse_uri_info(bi, info) < 0 ||
650 	    dpp_parse_uri_pk(bi, pk) < 0) {
651 		dpp_bootstrap_info_free(bi);
652 		bi = NULL;
653 	}
654 
655 	return bi;
656 }
657 
658 
dpp_gen_keypair(const struct dpp_curve_params * curve)659 static struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
660 {
661 	struct crypto_key *key = crypto_ec_gen_keypair(curve->ike_group);
662 
663 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
664 	dpp_debug_print_key("Own generated key", key);
665 
666 	return key;
667 }
668 
dpp_get_curve_name(const char * name)669 static const struct dpp_curve_params *dpp_get_curve_name(const char *name)
670 {
671 	int i;
672 
673 	for (i = 0; dpp_curves[i].name; i++) {
674 		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
675 		    (dpp_curves[i].jwk_crv &&
676 		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
677 			return &dpp_curves[i];
678 	}
679 	return NULL;
680 }
681 
682 
dpp_get_curve_jwk_crv(const char * name)683 static const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name)
684 {
685 	int i;
686 
687 	for (i = 0; dpp_curves[i].name; i++) {
688 		if (dpp_curves[i].jwk_crv &&
689 		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
690 			return &dpp_curves[i];
691 	}
692 
693 	return NULL;
694 }
695 
696 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)697 static struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve,
698 					   const u8 *privkey, size_t privkey_len)
699 {
700 	struct crypto_ec_group *group;
701 	struct crypto_key *pkey = crypto_ec_get_key(privkey, privkey_len);
702 	int id;
703 
704 	if (!pkey) {
705 		wpa_printf(MSG_ERROR, "%s: failed to get pkey\n", __func__);
706 		return NULL;
707 	}
708 	group = crypto_ec_get_group_from_key(pkey);
709 	if (!group) {
710 		return NULL;
711 	}
712 	id = crypto_ec_get_curve_id(group);
713 	*curve = dpp_get_curve_group_id(id);
714 	if (!*curve) {
715 		wpa_printf(MSG_INFO,
716 			   "DPP: Unsupported curve (id=%d) in pre-assigned key",
717 			   id);
718 		crypto_ec_free_key(pkey);
719 		return NULL;
720 	}
721 
722 	return pkey;
723 }
724 
dpp_bootstrap_key_der(struct crypto_key * key)725 static struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key)
726 {
727 	unsigned char *der = NULL;
728 	struct wpabuf *ret = NULL;
729 	int der_len;
730 
731 	der_len = crypto_ec_write_pub_key(key, &der);
732 	if (!der) {
733 		printf("failed to get der for bootstrapping key\n");
734 		return NULL;
735 	}
736 	ret = wpabuf_alloc_copy(der, der_len);
737 
738 	os_free(der);
739 	return ret;
740 }
741 
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)742 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
743 {
744 	struct wpabuf *der;
745 	int res;
746 	const u8 *addr[1];
747 	size_t len[1];
748 
749 	der = dpp_bootstrap_key_der(bi->pubkey);
750 	if (!der)
751 		return -1;
752 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
753 			der);
754 
755 	addr[0] = wpabuf_head(der);
756 	len[0] = wpabuf_len(der);
757 	res = sha256_vector(1, addr, len, bi->pubkey_hash);
758 	if (res < 0)
759 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
760 	else
761 		wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
762 			    SHA256_MAC_LEN);
763 	wpabuf_free(der);
764 	return res;
765 }
766 
767 
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,u8 * privkey,size_t privkey_len)768 char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
769 		  u8 *privkey, size_t privkey_len)
770 {
771 	char *base64 = NULL;
772 	char *pos, *end;
773 	size_t len;
774 	struct wpabuf *der = NULL;
775 	const u8 *addr[1];
776 	int res;
777 
778 	if (!curve) {
779 		bi->curve = &dpp_curves[0];
780 	} else {
781 		bi->curve = dpp_get_curve_name(curve);
782 		if (!bi->curve) {
783 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
784 				   curve);
785 			return NULL;
786 		}
787 	}
788 	if (privkey)
789 		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
790 	else
791 		bi->pubkey = dpp_gen_keypair(bi->curve);
792 	if (!bi->pubkey)
793 		goto fail;
794 	bi->own = 1;
795 
796 	der = dpp_bootstrap_key_der(bi->pubkey);
797 	if (!der)
798 		goto fail;
799 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
800 			der);
801 
802 	addr[0] = wpabuf_head(der);
803 	len = wpabuf_len(der);
804 	res = sha256_vector(1, addr, &len, bi->pubkey_hash);
805 	if (res < 0) {
806 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
807 		goto fail;
808 	}
809 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
810 		    SHA256_MAC_LEN);
811 
812 	base64 = (char *)base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
813 	wpabuf_free(der);
814 	der = NULL;
815 	if (!base64)
816 		goto fail;
817 	pos = base64;
818 	end = pos + len;
819 	for (;;) {
820 		pos = os_strchr(pos, '\n');
821 		if (!pos)
822 			break;
823 		os_memmove(pos, pos + 1, end - pos);
824 	}
825 	return base64;
826 fail:
827 	os_free(base64);
828 	wpabuf_free(der);
829 	return NULL;
830 }
831 
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)832 static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
833 			 unsigned int hash_len)
834 {
835 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
836 	const char *info = "first intermediate key";
837 	int res;
838 
839 	/* k1 = HKDF(<>, "first intermediate key", M.x) */
840 
841 	/* HKDF-Extract(<>, M.x) */
842 	os_memset(salt, 0, hash_len);
843 	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
844 		return -1;
845 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
846 			prk, hash_len);
847 
848 	/* HKDF-Expand(PRK, info, L) */
849 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
850 	os_memset(prk, 0, hash_len);
851 	if (res < 0)
852 		return -1;
853 
854 	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
855 			k1, hash_len);
856 	return 0;
857 }
858 
859 
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)860 static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
861 			 unsigned int hash_len)
862 {
863 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
864 	const char *info = "second intermediate key";
865 	int res;
866 
867 	/* k2 = HKDF(<>, "second intermediate key", N.x) */
868 
869 	/* HKDF-Extract(<>, N.x) */
870 	os_memset(salt, 0, hash_len);
871 	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
872 	if (res < 0)
873 		return -1;
874 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
875 			prk, hash_len);
876 
877 	/* HKDF-Expand(PRK, info, L) */
878 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
879 	os_memset(prk, 0, hash_len);
880 	if (res < 0)
881 		return -1;
882 
883 	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
884 			k2, hash_len);
885 	return 0;
886 }
887 
888 
dpp_derive_ke(struct dpp_authentication * auth,u8 * ke,unsigned int hash_len)889 static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
890 			 unsigned int hash_len)
891 {
892 	size_t nonce_len;
893 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
894 	const char *info_ke = "DPP Key";
895 	u8 prk[DPP_MAX_HASH_LEN];
896 	int res;
897 	const u8 *addr[3];
898 	size_t len[3];
899 	size_t num_elem = 0;
900 
901 	if (!auth->Mx_len || !auth->Nx_len) {
902 		wpa_printf(MSG_DEBUG,
903 			   "DPP: Mx/Nx not available - cannot derive ke");
904 		return -1;
905 	}
906 
907 	/* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
908 
909 	/* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
910 	nonce_len = auth->curve->nonce_len;
911 	os_memcpy(nonces, auth->i_nonce, nonce_len);
912 	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
913 	addr[num_elem] = auth->Mx;
914 	len[num_elem] = auth->Mx_len;
915 	num_elem++;
916 	addr[num_elem] = auth->Nx;
917 	len[num_elem] = auth->Nx_len;
918 	num_elem++;
919 	if (auth->peer_bi && auth->own_bi) {
920 		if (!auth->Lx_len) {
921 			wpa_printf(MSG_DEBUG,
922 				   "DPP: Lx not available - cannot derive ke");
923 			return -1;
924 		}
925 		addr[num_elem] = auth->Lx;
926 		len[num_elem] = auth->secret_len;
927 		num_elem++;
928 	}
929 	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
930 			      num_elem, addr, len, prk);
931 	if (res < 0)
932 		return -1;
933 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
934 			prk, hash_len);
935 
936 	/* HKDF-Expand(PRK, info, L) */
937 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len);
938 	os_memset(prk, 0, hash_len);
939 	if (res < 0)
940 		return -1;
941 
942 	wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
943 			ke, hash_len);
944 	return 0;
945 }
946 
947 
dpp_build_attr_status(struct wpabuf * msg,enum dpp_status_error status)948 static void dpp_build_attr_status(struct wpabuf *msg,
949 				  enum dpp_status_error status)
950 {
951 	wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
952 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
953 	wpabuf_put_le16(msg, 1);
954 	wpabuf_put_u8(msg, status);
955 }
956 
957 
dpp_build_attr_r_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)958 static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg,
959 						const u8 *hash)
960 {
961 	if (hash) {
962 		wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash");
963 		wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
964 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
965 		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
966 	}
967 }
968 
969 
dpp_build_attr_i_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)970 static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg,
971 						const u8 *hash)
972 {
973 	if (hash) {
974 		wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
975 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
976 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
977 		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
978 	}
979 }
980 
981 
dpp_auth_build_req(struct dpp_authentication * auth,const struct wpabuf * pi,size_t nonce_len,const u8 * r_pubkey_hash,const u8 * i_pubkey_hash,unsigned int neg_freq)982 static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
983 					  const struct wpabuf *pi,
984 					  size_t nonce_len,
985 					  const u8 *r_pubkey_hash,
986 					  const u8 *i_pubkey_hash,
987 					  unsigned int neg_freq)
988 {
989 	struct wpabuf *msg;
990 	u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
991 	u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
992 	u8 *pos;
993 	const u8 *addr[2];
994 
995 	size_t len[2], siv_len, attr_len;
996 	u8 *attr_start, *attr_end;
997 
998 	/* Build DPP Authentication Request frame attributes */
999 	attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) +
1000 		4 + sizeof(wrapped_data);
1001 	if (neg_freq > 0)
1002 		attr_len += 4 + 2;
1003 #ifdef CONFIG_WPA_TESTING_OPTIONS
1004 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
1005 		attr_len += 5;
1006 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1007 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
1008 	if (!msg)
1009 		return NULL;
1010 
1011 	attr_start = wpabuf_put(msg, 0);
1012 
1013 	/* Responder Bootstrapping Key Hash */
1014 	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
1015 
1016 	/* Initiator Bootstrapping Key Hash */
1017 	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
1018 
1019 	/* Initiator Protocol Key */
1020 	if (pi) {
1021 		wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
1022 		wpabuf_put_le16(msg, wpabuf_len(pi));
1023 		wpabuf_put_buf(msg, pi);
1024 	}
1025 
1026 	/* Channel */
1027 	if (neg_freq > 0) {
1028 		//TODO correct and fill
1029 		u8 op_class = 81, channel = 6;
1030 
1031 		wpabuf_put_le16(msg, DPP_ATTR_CHANNEL);
1032 		wpabuf_put_le16(msg, 2);
1033 		wpabuf_put_u8(msg, op_class);
1034 		wpabuf_put_u8(msg, channel);
1035 	}
1036 
1037 #ifdef CONFIG_WPA_TESTING_OPTIONS
1038 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) {
1039 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
1040 		goto skip_wrapped_data;
1041 	}
1042 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1043 
1044 	/* Wrapped data ({I-nonce, I-capabilities}k1) */
1045 	pos = clear;
1046 
1047 #ifdef CONFIG_WPA_TESTING_OPTIONS
1048 	if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) {
1049 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
1050 		goto skip_i_nonce;
1051 	}
1052 	if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) {
1053 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce");
1054 		WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1055 		pos += 2;
1056 		WPA_PUT_LE16(pos, nonce_len - 1);
1057 		pos += 2;
1058 		os_memcpy(pos, auth->i_nonce, nonce_len - 1);
1059 		pos += nonce_len - 1;
1060 		goto skip_i_nonce;
1061 	}
1062 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1063 
1064 	/* I-nonce */
1065 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1066 	pos += 2;
1067 	WPA_PUT_LE16(pos, nonce_len);
1068 	pos += 2;
1069 	os_memcpy(pos, auth->i_nonce, nonce_len);
1070 	pos += nonce_len;
1071 
1072 #ifdef CONFIG_WPA_TESTING_OPTIONS
1073 skip_i_nonce:
1074 	if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) {
1075 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab");
1076 		goto skip_i_capab;
1077 	}
1078 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1079 
1080 	/* I-capabilities */
1081 	WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
1082 	pos += 2;
1083 	WPA_PUT_LE16(pos, 1);
1084 	pos += 2;
1085 	auth->i_capab = auth->allowed_roles;
1086 	*pos++ = auth->i_capab;
1087 #ifdef CONFIG_WPA_TESTING_OPTIONS
1088 	if (dpp_test == DPP_TEST_ZERO_I_CAPAB) {
1089 		wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities");
1090 		pos[-1] = 0;
1091 	}
1092 skip_i_capab:
1093 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1094 
1095 	attr_end = wpabuf_put(msg, 0);
1096 
1097 	/* OUI, OUI type, Crypto Suite, DPP frame type */
1098 	addr[0] = wpabuf_head_u8(msg) + 2;
1099 	len[0] = 3 + 1 + 1 + 1;
1100 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1101 
1102 	/* Attributes before Wrapped Data */
1103 	addr[1] = attr_start;
1104 	len[1] = attr_end - attr_start;
1105 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1106 
1107 	siv_len = pos - clear;
1108 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1109 	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
1110 			    2, addr, len, wrapped_data) < 0) {
1111 		wpabuf_free(msg);
1112 		return NULL;
1113 	}
1114 	siv_len += AES_BLOCK_SIZE;
1115 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1116 		    wrapped_data, siv_len);
1117 
1118 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1119 	wpabuf_put_le16(msg, siv_len);
1120 	wpabuf_put_data(msg, wrapped_data, siv_len);
1121 
1122 #ifdef CONFIG_WPA_TESTING_OPTIONS
1123 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) {
1124 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1125 		dpp_build_attr_status(msg, DPP_STATUS_OK);
1126 	}
1127 skip_wrapped_data:
1128 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1129 
1130 	wpa_hexdump_buf(MSG_DEBUG,
1131 			"DPP: Authentication Request frame attributes", msg);
1132 
1133 	return msg;
1134 }
1135 
1136 
dpp_auth_build_resp(struct dpp_authentication * auth,enum dpp_status_error status,const struct wpabuf * pr,size_t nonce_len,const u8 * r_pubkey_hash,const u8 * i_pubkey_hash,const u8 * r_nonce,const u8 * i_nonce,const u8 * wrapped_r_auth,size_t wrapped_r_auth_len,const u8 * siv_key)1137 static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth,
1138 					   enum dpp_status_error status,
1139 					   const struct wpabuf *pr,
1140 					   size_t nonce_len,
1141 					   const u8 *r_pubkey_hash,
1142 					   const u8 *i_pubkey_hash,
1143 					   const u8 *r_nonce, const u8 *i_nonce,
1144 					   const u8 *wrapped_r_auth,
1145 					   size_t wrapped_r_auth_len,
1146 					   const u8 *siv_key)
1147 {
1148 	struct wpabuf *msg;
1149 #define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
1150 		4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE
1151 	u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
1152 	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
1153 	const u8 *addr[2];
1154 	size_t len[2], siv_len, attr_len;
1155 	u8 *attr_start, *attr_end, *pos;
1156 
1157 	auth->waiting_auth_conf = 1;
1158 	auth->auth_resp_tries = 0;
1159 
1160 	/* Build DPP Authentication Response frame attributes */
1161 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1162 		4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data);
1163 #ifdef CONFIG_WPA_TESTING_OPTIONS
1164 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP)
1165 		attr_len += 5;
1166 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1167 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
1168 	if (!msg)
1169 		return NULL;
1170 
1171 	attr_start = wpabuf_put(msg, 0);
1172 
1173 	/* DPP Status */
1174 	if (status != 255)
1175 		dpp_build_attr_status(msg, status);
1176 
1177 	/* Responder Bootstrapping Key Hash */
1178 	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
1179 
1180 	/* Initiator Bootstrapping Key Hash (mutual authentication) */
1181 	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
1182 
1183 	/* Responder Protocol Key */
1184 	if (pr) {
1185 		wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
1186 		wpabuf_put_le16(msg, wpabuf_len(pr));
1187 		wpabuf_put_buf(msg, pr);
1188 	}
1189 
1190 	attr_end = wpabuf_put(msg, 0);
1191 
1192 #ifdef CONFIG_WPA_TESTING_OPTIONS
1193 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) {
1194 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
1195 		goto skip_wrapped_data;
1196 	}
1197 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1198 
1199 	/* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
1200 	pos = clear;
1201 
1202 	if (r_nonce) {
1203 		/* R-nonce */
1204 		WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
1205 		pos += 2;
1206 		WPA_PUT_LE16(pos, nonce_len);
1207 		pos += 2;
1208 		os_memcpy(pos, r_nonce, nonce_len);
1209 		pos += nonce_len;
1210 	}
1211 
1212 	if (i_nonce) {
1213 		/* I-nonce */
1214 		WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1215 		pos += 2;
1216 		WPA_PUT_LE16(pos, nonce_len);
1217 		pos += 2;
1218 		os_memcpy(pos, i_nonce, nonce_len);
1219 #ifdef CONFIG_WPA_TESTING_OPTIONS
1220 		if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) {
1221 			wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch");
1222 			pos[nonce_len / 2] ^= 0x01;
1223 		}
1224 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1225 		pos += nonce_len;
1226 	}
1227 
1228 #ifdef CONFIG_WPA_TESTING_OPTIONS
1229 	if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) {
1230 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab");
1231 		goto skip_r_capab;
1232 	}
1233 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1234 
1235 	/* R-capabilities */
1236 	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
1237 	pos += 2;
1238 	WPA_PUT_LE16(pos, 1);
1239 	pos += 2;
1240 	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
1241 		DPP_CAPAB_ENROLLEE;
1242 	*pos++ = auth->r_capab;
1243 #ifdef CONFIG_WPA_TESTING_OPTIONS
1244 	if (dpp_test == DPP_TEST_ZERO_R_CAPAB) {
1245 		wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities");
1246 		pos[-1] = 0;
1247 	} else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) {
1248 		wpa_printf(MSG_INFO,
1249 			   "DPP: TESTING - incompatible R-capabilities");
1250 		if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) ==
1251 		    (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE))
1252 			pos[-1] = 0;
1253 		else
1254 			pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE :
1255 				DPP_CAPAB_CONFIGURATOR;
1256 	}
1257 skip_r_capab:
1258 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1259 
1260 	if (wrapped_r_auth) {
1261 		/* {R-auth}ke */
1262 		WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
1263 		pos += 2;
1264 		WPA_PUT_LE16(pos, wrapped_r_auth_len);
1265 		pos += 2;
1266 		os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
1267 		pos += wrapped_r_auth_len;
1268 	}
1269 
1270 	/* OUI, OUI type, Crypto Suite, DPP frame type */
1271 	addr[0] = wpabuf_head_u8(msg) + 2;
1272 	len[0] = 3 + 1 + 1 + 1;
1273 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1274 
1275 	/* Attributes before Wrapped Data */
1276 	addr[1] = attr_start;
1277 	len[1] = attr_end - attr_start;
1278 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1279 
1280 	siv_len = pos - clear;
1281 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1282 	if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len,
1283 			    2, addr, len, wrapped_data) < 0) {
1284 		wpabuf_free(msg);
1285 		return NULL;
1286 	}
1287 	siv_len += AES_BLOCK_SIZE;
1288 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1289 		    wrapped_data, siv_len);
1290 
1291 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1292 	wpabuf_put_le16(msg, siv_len);
1293 	wpabuf_put_data(msg, wrapped_data, siv_len);
1294 
1295 #ifdef CONFIG_WPA_TESTING_OPTIONS
1296 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) {
1297 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1298 		dpp_build_attr_status(msg, DPP_STATUS_OK);
1299 	}
1300 skip_wrapped_data:
1301 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1302 
1303 	wpa_hexdump_buf(MSG_DEBUG,
1304 			"DPP: Authentication Response frame attributes", msg);
1305 	return msg;
1306 }
1307 
1308 
dpp_channel_ok_init(struct hostapd_hw_modes * own_modes,u16 num_modes,unsigned int freq)1309 static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
1310 			       u16 num_modes, unsigned int freq)
1311 {
1312 #ifndef ESP_SUPPLICANT
1313 	u16 m;
1314 	int c, flag;
1315 
1316 	if (!own_modes || !num_modes)
1317 		return 1;
1318 
1319 	for (m = 0; m < num_modes; m++) {
1320 		for (c = 0; c < own_modes[m].num_channels; c++) {
1321 			if ((unsigned int) own_modes[m].channels[c].freq !=
1322 			    freq)
1323 				continue;
1324 			flag = own_modes[m].channels[c].flag;
1325 			if (!(flag & (HOSTAPD_CHAN_DISABLED |
1326 				      HOSTAPD_CHAN_NO_IR |
1327 				      HOSTAPD_CHAN_RADAR)))
1328 				return 1;
1329 		}
1330 	}
1331 
1332 	wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
1333 	return 0;
1334 #endif
1335 	return 1;
1336 }
1337 
1338 
freq_included(const unsigned int freqs[],unsigned int num,unsigned int freq)1339 static int freq_included(const unsigned int freqs[], unsigned int num,
1340 			 unsigned int freq)
1341 {
1342 	while (num > 0) {
1343 		if (freqs[--num] == freq)
1344 			return 1;
1345 	}
1346 	return 0;
1347 }
1348 
1349 
freq_to_start(unsigned int freqs[],unsigned int num,unsigned int freq)1350 static void freq_to_start(unsigned int freqs[], unsigned int num,
1351 			  unsigned int freq)
1352 {
1353 	unsigned int i;
1354 
1355 	for (i = 0; i < num; i++) {
1356 		if (freqs[i] == freq)
1357 			break;
1358 	}
1359 	if (i == 0 || i >= num)
1360 		return;
1361 	os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
1362 	freqs[0] = freq;
1363 }
1364 
1365 
dpp_channel_intersect(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)1366 static int dpp_channel_intersect(struct dpp_authentication *auth,
1367 				 struct hostapd_hw_modes *own_modes,
1368 				 u16 num_modes)
1369 {
1370 	struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
1371 	unsigned int i, freq;
1372 
1373 	for (i = 0; i < peer_bi->num_freq; i++) {
1374 		freq = peer_bi->freq[i];
1375 		if (freq_included(auth->freq, auth->num_freq, freq))
1376 			continue;
1377 		if (dpp_channel_ok_init(own_modes, num_modes, freq))
1378 			auth->freq[auth->num_freq++] = freq;
1379 	}
1380 	if (!auth->num_freq) {
1381 		wpa_printf(MSG_INFO,
1382 			   "DPP: No available channels for initiating DPP Authentication");
1383 		return -1;
1384 	}
1385 	auth->curr_freq = auth->freq[0];
1386 	return 0;
1387 }
1388 
1389 
dpp_channel_local_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)1390 static int dpp_channel_local_list(struct dpp_authentication *auth,
1391 				  struct hostapd_hw_modes *own_modes,
1392 				  u16 num_modes)
1393 {
1394 #ifndef ESP_SUPPLICANT
1395 	u16 m;
1396 	int c, flag;
1397 	unsigned int freq;
1398 
1399 	if (!own_modes || !num_modes) {
1400 		auth->freq[0] = 2412;
1401 		auth->freq[1] = 2437;
1402 		auth->freq[2] = 2462;
1403 		auth->num_freq = 3;
1404 		return 0;
1405 	}
1406 
1407 	for (m = 0; m < num_modes; m++) {
1408 		for (c = 0; c < own_modes[m].num_channels; c++) {
1409 			freq = own_modes[m].channels[c].freq;
1410 			flag = own_modes[m].channels[c].flag;
1411 			if (flag & (HOSTAPD_CHAN_DISABLED |
1412 				    HOSTAPD_CHAN_NO_IR |
1413 				    HOSTAPD_CHAN_RADAR))
1414 				continue;
1415 			if (freq_included(auth->freq, auth->num_freq, freq))
1416 				continue;
1417 			auth->freq[auth->num_freq++] = freq;
1418 			if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
1419 				m = num_modes;
1420 				break;
1421 			}
1422 		}
1423 	}
1424 #else
1425 	auth->freq[0] = 2412;
1426 	auth->freq[1] = 2437;
1427 	auth->freq[2] = 2462;
1428 	auth->num_freq = 3;
1429 #endif
1430 	return auth->num_freq == 0 ? -1 : 0;
1431 }
1432 
1433 
dpp_prepare_channel_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)1434 static int dpp_prepare_channel_list(struct dpp_authentication *auth,
1435 				    struct hostapd_hw_modes *own_modes,
1436 				    u16 num_modes)
1437 {
1438 	int res;
1439 	char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
1440 	unsigned int i;
1441 
1442 	if (auth->peer_bi->num_freq > 0)
1443 		res = dpp_channel_intersect(auth, own_modes, num_modes);
1444 	else
1445 		res = dpp_channel_local_list(auth, own_modes, num_modes);
1446 	if (res < 0)
1447 		return res;
1448 
1449 	/* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
1450 	 * likely channels first. */
1451 	freq_to_start(auth->freq, auth->num_freq, 2462);
1452 	freq_to_start(auth->freq, auth->num_freq, 2412);
1453 	freq_to_start(auth->freq, auth->num_freq, 2437);
1454 
1455 	auth->freq_idx = 0;
1456 	auth->curr_freq = auth->freq[0];
1457 
1458 	pos = freqs;
1459 	end = pos + sizeof(freqs);
1460 	for (i = 0; i < auth->num_freq; i++) {
1461 		res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
1462 		if (os_snprintf_error(end - pos, res))
1463 			break;
1464 		pos += res;
1465 	}
1466 	*pos = '\0';
1467 	wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
1468 		   freqs);
1469 
1470 	return 0;
1471 }
1472 
1473 
dpp_autogen_bootstrap_key(struct dpp_authentication * auth)1474 static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
1475 {
1476 	struct dpp_bootstrap_info *bi;
1477 	char *pk = NULL;
1478 	size_t len;
1479 
1480 	if (auth->own_bi)
1481 		return 0; /* already generated */
1482 
1483 	bi = os_zalloc(sizeof(*bi));
1484 	if (!bi)
1485 		return -1;
1486 	bi->type = DPP_BOOTSTRAP_QR_CODE;
1487 	pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0);
1488 	if (!pk)
1489 		goto fail;
1490 
1491 	len = 4; /* "DPP:" */
1492 	len += 4 + os_strlen(pk);
1493 	bi->uri = os_malloc(len + 1);
1494 	if (!bi->uri)
1495 		goto fail;
1496 	os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk);
1497 	wpa_printf(MSG_DEBUG,
1498 		   "DPP: Auto-generated own bootstrapping key info: URI %s",
1499 		   bi->uri);
1500 
1501 	auth->tmp_own_bi = auth->own_bi = bi;
1502 
1503 	os_free(pk);
1504 
1505 	return 0;
1506 fail:
1507 	os_free(pk);
1508 	dpp_bootstrap_info_free(bi);
1509 	return -1;
1510 }
1511 
1512 
dpp_auth_init(void * msg_ctx,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,u8 dpp_allowed_roles,unsigned int neg_freq,struct hostapd_hw_modes * own_modes,u16 num_modes)1513 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
1514 					  struct dpp_bootstrap_info *peer_bi,
1515 					  struct dpp_bootstrap_info *own_bi,
1516 					  u8 dpp_allowed_roles,
1517 					  unsigned int neg_freq,
1518 					  struct hostapd_hw_modes *own_modes,
1519 					  u16 num_modes)
1520 {
1521 	struct dpp_authentication *auth;
1522 	size_t nonce_len;
1523 	size_t secret_len;
1524 	struct wpabuf *pi = NULL;
1525 	const u8 *r_pubkey_hash, *i_pubkey_hash;
1526 #ifdef CONFIG_WPA_TESTING_OPTIONS
1527 	u8 test_hash[SHA256_MAC_LEN];
1528 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1529 
1530 	auth = os_zalloc(sizeof(*auth));
1531 	if (!auth)
1532 		return NULL;
1533 	auth->msg_ctx = msg_ctx;
1534 	auth->initiator = 1;
1535 	auth->waiting_auth_resp = 1;
1536 	auth->allowed_roles = dpp_allowed_roles;
1537 	auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR);
1538 	auth->peer_bi = peer_bi;
1539 	auth->own_bi = own_bi;
1540 	auth->curve = peer_bi->curve;
1541 
1542 	if (dpp_autogen_bootstrap_key(auth) < 0 ||
1543 	    dpp_prepare_channel_list(auth, own_modes, num_modes) < 0)
1544 		goto fail;
1545 
1546 #ifdef CONFIG_WPA_TESTING_OPTIONS
1547 	if (dpp_nonce_override_len > 0) {
1548 		wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce");
1549 		nonce_len = dpp_nonce_override_len;
1550 		os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len);
1551 	} else {
1552 		nonce_len = auth->curve->nonce_len;
1553 		if (random_get_bytes(auth->i_nonce, nonce_len)) {
1554 			wpa_printf(MSG_ERROR,
1555 				   "DPP: Failed to generate I-nonce");
1556 			goto fail;
1557 		}
1558 	}
1559 #else /* CONFIG_WPA_TESTING_OPTIONS */
1560 	nonce_len = auth->curve->nonce_len;
1561 	if (random_get_bytes(auth->i_nonce, nonce_len)) {
1562 		wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
1563 		goto fail;
1564 	}
1565 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1566 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
1567 
1568 #ifdef CONFIG_WPA_TESTING_OPTIONS
1569 	if (dpp_protocol_key_override_len) {
1570 		const struct dpp_curve_params *tmp_curve;
1571 
1572 		wpa_printf(MSG_INFO,
1573 			   "DPP: TESTING - override protocol key");
1574 		auth->own_protocol_key = dpp_set_keypair(
1575 			&tmp_curve, dpp_protocol_key_override,
1576 			dpp_protocol_key_override_len);
1577 	} else {
1578 		auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1579 	}
1580 #else /* CONFIG_WPA_TESTING_OPTIONS */
1581 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1582 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1583 	if (!auth->own_protocol_key)
1584 		goto fail;
1585 
1586 	pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1587 	if (!pi)
1588 		goto fail;
1589 
1590 	/* ECDH: M = pI * BR */
1591 	if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey,
1592 		     auth->Mx, &secret_len) < 0)
1593 		goto fail;
1594 	auth->secret_len = secret_len;
1595 
1596 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
1597 			auth->Mx, auth->secret_len);
1598 	auth->Mx_len = auth->secret_len;
1599 
1600 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
1601 			  auth->curve->hash_len) < 0)
1602 		goto fail;
1603 
1604 	r_pubkey_hash = auth->peer_bi->pubkey_hash;
1605 	i_pubkey_hash = auth->own_bi->pubkey_hash;
1606 
1607 #ifdef CONFIG_WPA_TESTING_OPTIONS
1608 	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1609 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
1610 		r_pubkey_hash = NULL;
1611 	} else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1612 		wpa_printf(MSG_INFO,
1613 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
1614 		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
1615 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1616 		r_pubkey_hash = test_hash;
1617 	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1618 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
1619 		i_pubkey_hash = NULL;
1620 	} else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
1621 		wpa_printf(MSG_INFO,
1622 			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
1623 		os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
1624 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
1625 		i_pubkey_hash = test_hash;
1626 	} else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) {
1627 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key");
1628 		wpabuf_free(pi);
1629 		pi = NULL;
1630 	} else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) {
1631 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key");
1632 		wpabuf_free(pi);
1633 		pi = wpabuf_alloc(2 * auth->curve->prime_len);
1634 		if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0)
1635 			goto fail;
1636 	}
1637 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1638 
1639 	auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash,
1640 					   i_pubkey_hash, neg_freq);
1641 	if (!auth->req_msg)
1642 		goto fail;
1643 
1644 out:
1645 	wpabuf_free(pi);
1646 	return auth;
1647 fail:
1648 	dpp_auth_deinit(auth);
1649 	auth = NULL;
1650 	goto out;
1651 }
1652 
1653 
dpp_build_conf_req_attr(struct dpp_authentication * auth,const char * json)1654 static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
1655 					       const char *json)
1656 {
1657 	size_t nonce_len;
1658 	size_t json_len, clear_len;
1659 	struct wpabuf *clear = NULL, *msg = NULL;
1660 	u8 *wrapped;
1661 	size_t attr_len;
1662 
1663 	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
1664 
1665 	nonce_len = auth->curve->nonce_len;
1666 	if (random_get_bytes(auth->e_nonce, nonce_len)) {
1667 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1668 		goto fail;
1669 	}
1670 	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
1671 	json_len = os_strlen(json);
1672 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configRequest JSON", (u8 *)json, json_len);
1673 
1674 	/* { E-nonce, configAttrib }ke */
1675 	clear_len = 4 + nonce_len + 4 + json_len;
1676 	clear = wpabuf_alloc(clear_len);
1677 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
1678 #ifdef CONFIG_WPA_TESTING_OPTIONS
1679 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
1680 		attr_len += 5;
1681 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1682 	msg = wpabuf_alloc(attr_len);
1683 	if (!clear || !msg)
1684 		goto fail;
1685 
1686 #ifdef CONFIG_WPA_TESTING_OPTIONS
1687 	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) {
1688 		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
1689 		goto skip_e_nonce;
1690 	}
1691 	if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) {
1692 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce");
1693 		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
1694 		wpabuf_put_le16(clear, nonce_len - 1);
1695 		wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1);
1696 		goto skip_e_nonce;
1697 	}
1698 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) {
1699 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
1700 		goto skip_wrapped_data;
1701 	}
1702 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1703 
1704 	/* E-nonce */
1705 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
1706 	wpabuf_put_le16(clear, nonce_len);
1707 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
1708 
1709 #ifdef CONFIG_WPA_TESTING_OPTIONS
1710 skip_e_nonce:
1711 	if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) {
1712 		wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib");
1713 		goto skip_conf_attr_obj;
1714 	}
1715 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1716 
1717 	/* configAttrib */
1718 	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
1719 	wpabuf_put_le16(clear, json_len);
1720 	wpabuf_put_data(clear, json, json_len);
1721 
1722 #ifdef CONFIG_WPA_TESTING_OPTIONS
1723 skip_conf_attr_obj:
1724 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1725 
1726 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1727 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
1728 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
1729 
1730 	/* No AES-SIV AD */
1731 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
1732 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
1733 			    wpabuf_head(clear), wpabuf_len(clear),
1734 			    0, NULL, NULL, wrapped) < 0)
1735 		goto fail;
1736 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1737 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
1738 
1739 #ifdef CONFIG_WPA_TESTING_OPTIONS
1740 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) {
1741 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1742 		dpp_build_attr_status(msg, DPP_STATUS_OK);
1743 	}
1744 skip_wrapped_data:
1745 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1746 
1747 	wpa_hexdump_buf(MSG_DEBUG,
1748 			"DPP: Configuration Request frame attributes", msg);
1749 	wpabuf_free(clear);
1750 	return msg;
1751 
1752 fail:
1753 	wpabuf_free(clear);
1754 	wpabuf_free(msg);
1755 	return NULL;
1756 }
1757 
1758 
dpp_write_adv_proto(struct wpabuf * buf)1759 static void dpp_write_adv_proto(struct wpabuf *buf)
1760 {
1761 	/* Advertisement Protocol IE */
1762 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
1763 	wpabuf_put_u8(buf, 8); /* Length */
1764 	wpabuf_put_u8(buf, 0x7f);
1765 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1766 	wpabuf_put_u8(buf, 5);
1767 	wpabuf_put_be24(buf, OUI_WFA);
1768 	wpabuf_put_u8(buf, DPP_OUI_TYPE);
1769 	wpabuf_put_u8(buf, 0x01);
1770 }
1771 
1772 
dpp_write_gas_query(struct wpabuf * buf,struct wpabuf * query)1773 static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
1774 {
1775 	/* GAS Query */
1776 	wpabuf_put_le16(buf, wpabuf_len(query));
1777 	wpabuf_put_buf(buf, query);
1778 }
1779 
1780 
dpp_build_conf_req(struct dpp_authentication * auth,const char * json)1781 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
1782 				   const char *json)
1783 {
1784 	struct wpabuf *buf, *conf_req;
1785 
1786 	conf_req = dpp_build_conf_req_attr(auth, json);
1787 	if (!conf_req) {
1788 		wpa_printf(MSG_DEBUG,
1789 			   "DPP: No configuration request data available");
1790 		return NULL;
1791 	}
1792 
1793 	buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
1794 	if (!buf) {
1795 		wpabuf_free(conf_req);
1796 		return NULL;
1797 	}
1798 
1799 	dpp_write_adv_proto(buf);
1800 	dpp_write_gas_query(buf, conf_req);
1801 	wpabuf_free(conf_req);
1802 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf);
1803 
1804 	return buf;
1805 }
1806 
1807 
dpp_build_conf_req_helper(struct dpp_authentication * auth,const char * name,enum dpp_netrole netrole,const char * mud_url,int * opclasses)1808 struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
1809 					  const char *name,
1810 					  enum dpp_netrole netrole,
1811 					  const char *mud_url, int *opclasses)
1812 {
1813 	size_t len, name_len;
1814 	const char *tech = "infra";
1815 	const char *dpp_name;
1816 	struct wpabuf *buf, *json;
1817 
1818 #ifdef CONFIG_WPA_TESTING_OPTIONS
1819 	if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
1820 		static const char *bogus_tech = "knfra";
1821 
1822 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
1823 		tech = bogus_tech;
1824 	}
1825 #endif /* CONFIG_WPA_TESTING_OPTIONS */
1826 
1827 	dpp_name = name ? name : "Test";
1828 	name_len = os_strlen(dpp_name);
1829 
1830 	len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
1831 	if (mud_url && mud_url[0])
1832 		len += 10 + os_strlen(mud_url);
1833 	json = wpabuf_alloc(len);
1834 	if (!json)
1835 		return NULL;
1836 
1837 	json_start_object(json, NULL);
1838 	if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) {
1839 		wpabuf_free(json);
1840 		return NULL;
1841 	}
1842 	json_value_sep(json);
1843 	json_add_string(json, "wi-fi_tech", tech);
1844 	json_value_sep(json);
1845 	json_add_string(json, "netRole", dpp_netrole_str(netrole));
1846 	if (mud_url && mud_url[0]) {
1847 		json_value_sep(json);
1848 		json_add_string(json, "mudurl", mud_url);
1849 	}
1850 	if (opclasses) {
1851 		int i;
1852 
1853 		json_value_sep(json);
1854 		json_start_array(json, "bandSupport");
1855 		for (i = 0; opclasses[i]; i++)
1856 			wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
1857 		json_end_array(json);
1858 	}
1859 	json_end_object(json);
1860 
1861 	buf = dpp_build_conf_req(auth, wpabuf_head(json));
1862 	wpabuf_free(json);
1863 
1864 	return buf;
1865 }
1866 
1867 
dpp_auth_success(struct dpp_authentication * auth)1868 static void dpp_auth_success(struct dpp_authentication *auth)
1869 {
1870 	wpa_printf(MSG_DEBUG,
1871 		   "DPP: Authentication success - clear temporary keys");
1872 	os_memset(auth->Mx, 0, sizeof(auth->Mx));
1873 	auth->Mx_len = 0;
1874 	os_memset(auth->Nx, 0, sizeof(auth->Nx));
1875 	auth->Nx_len = 0;
1876 	os_memset(auth->Lx, 0, sizeof(auth->Lx));
1877 	auth->Lx_len = 0;
1878 	os_memset(auth->k1, 0, sizeof(auth->k1));
1879 	os_memset(auth->k2, 0, sizeof(auth->k2));
1880 
1881 	auth->auth_success = 1;
1882 }
1883 
1884 
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)1885 static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
1886 {
1887 	struct wpabuf *pix, *prx, *bix, *brx;
1888 	const u8 *addr[7];
1889 	size_t len[7];
1890 	size_t i, num_elem = 0;
1891 	size_t nonce_len;
1892 	u8 zero = 0;
1893 	int res = -1;
1894 
1895 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1896 	nonce_len = auth->curve->nonce_len;
1897 
1898 	if (auth->initiator) {
1899 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1900 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1901 		if (auth->own_bi)
1902 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1903 		else
1904 			bix = NULL;
1905 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1906 	} else {
1907 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1908 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1909 		if (auth->peer_bi)
1910 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1911 		else
1912 			bix = NULL;
1913 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1914 	}
1915 	if (!pix || !prx || !brx)
1916 		goto fail;
1917 
1918 	addr[num_elem] = auth->i_nonce;
1919 	len[num_elem] = nonce_len;
1920 	num_elem++;
1921 
1922 	addr[num_elem] = auth->r_nonce;
1923 	len[num_elem] = nonce_len;
1924 	num_elem++;
1925 
1926 	addr[num_elem] = wpabuf_head(pix);
1927 	len[num_elem] = wpabuf_len(pix) / 2;
1928 	num_elem++;
1929 
1930 	addr[num_elem] = wpabuf_head(prx);
1931 	len[num_elem] = wpabuf_len(prx) / 2;
1932 	num_elem++;
1933 
1934 	if (bix) {
1935 		addr[num_elem] = wpabuf_head(bix);
1936 		len[num_elem] = wpabuf_len(bix) / 2;
1937 		num_elem++;
1938 	}
1939 
1940 	addr[num_elem] = wpabuf_head(brx);
1941 	len[num_elem] = wpabuf_len(brx) / 2;
1942 	num_elem++;
1943 
1944 	addr[num_elem] = &zero;
1945 	len[num_elem] = 1;
1946 	num_elem++;
1947 
1948 	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
1949 	for (i = 0; i < num_elem; i++)
1950 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1951 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
1952 	if (res == 0)
1953 		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
1954 			    auth->curve->hash_len);
1955 fail:
1956 	wpabuf_free(pix);
1957 	wpabuf_free(prx);
1958 	wpabuf_free(bix);
1959 	wpabuf_free(brx);
1960 	return res;
1961 }
1962 
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)1963 static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
1964 {
1965 	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
1966 	const u8 *addr[7];
1967 	size_t len[7];
1968 	size_t i, num_elem = 0;
1969 	size_t nonce_len;
1970 	u8 one = 1;
1971 	int res = -1;
1972 
1973 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
1974 	nonce_len = auth->curve->nonce_len;
1975 
1976 	if (auth->initiator) {
1977 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1978 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1979 		if (auth->own_bi)
1980 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1981 		else
1982 			bix = NULL;
1983 		if (!auth->peer_bi)
1984 			goto fail;
1985 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1986 	} else {
1987 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1988 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1989 		if (auth->peer_bi)
1990 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1991 		else
1992 			bix = NULL;
1993 		if (!auth->own_bi)
1994 			goto fail;
1995 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1996 	}
1997 	if (!pix || !prx || !brx)
1998 		goto fail;
1999 
2000 	addr[num_elem] = auth->r_nonce;
2001 	len[num_elem] = nonce_len;
2002 	num_elem++;
2003 
2004 	addr[num_elem] = auth->i_nonce;
2005 	len[num_elem] = nonce_len;
2006 	num_elem++;
2007 
2008 	addr[num_elem] = wpabuf_head(prx);
2009 	len[num_elem] = wpabuf_len(prx) / 2;
2010 	num_elem++;
2011 
2012 	addr[num_elem] = wpabuf_head(pix);
2013 	len[num_elem] = wpabuf_len(pix) / 2;
2014 	num_elem++;
2015 
2016 	addr[num_elem] = wpabuf_head(brx);
2017 	len[num_elem] = wpabuf_len(brx) / 2;
2018 	num_elem++;
2019 
2020 	if (bix) {
2021 		addr[num_elem] = wpabuf_head(bix);
2022 		len[num_elem] = wpabuf_len(bix) / 2;
2023 		num_elem++;
2024 	}
2025 
2026 	addr[num_elem] = &one;
2027 	len[num_elem] = 1;
2028 	num_elem++;
2029 
2030 	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
2031 	for (i = 0; i < num_elem; i++)
2032 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
2033 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
2034 	if (res == 0)
2035 		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
2036 			    auth->curve->hash_len);
2037 fail:
2038 	wpabuf_free(pix);
2039 	wpabuf_free(prx);
2040 	wpabuf_free(bix);
2041 	wpabuf_free(brx);
2042 	return res;
2043 }
2044 
2045 
dpp_auth_derive_l_responder(struct dpp_authentication * auth)2046 static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
2047 {
2048 	struct crypto_ec_group *group;
2049 	struct crypto_ec_point *l = NULL;
2050 	struct crypto_ec_point *BI_point;
2051 	struct crypto_bignum *lx, *sum, *q;
2052 	struct crypto_bignum *bR_bn, *pR_bn;
2053 	int ret = -1;
2054 
2055 	/* L = ((bR + pR) modulo q) * BI */
2056 
2057 	sum = crypto_bignum_init();
2058 	q = crypto_bignum_init();
2059 	lx = crypto_bignum_init();
2060 	if (!sum || !q || !lx)
2061 		goto fail;
2062 
2063 	BI_point = crypto_ec_get_public_key(auth->peer_bi->pubkey);
2064 	group = crypto_ec_get_group_from_key(auth->peer_bi->pubkey);
2065 	bR_bn = crypto_ec_get_private_key(auth->own_bi->pubkey);
2066 	pR_bn = crypto_ec_get_private_key(auth->own_protocol_key);
2067 
2068 	if (!bR_bn || !pR_bn)
2069 		goto fail;
2070 
2071 	if ((crypto_get_order(group, q) != 0) ||
2072 	    (crypto_bignum_addmod(sum, bR_bn, pR_bn, q) != 0))
2073 		goto fail;
2074 
2075 	l = crypto_ec_point_init((struct crypto_ec *)group);
2076 	if (!l || (crypto_ec_point_mul((struct crypto_ec *)group, BI_point, sum, l) != 0) ||
2077 	    (crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0)) {
2078 		wpa_printf(MSG_ERROR,
2079 				"OpenSSL: failed: %s", __func__);
2080 		goto fail;
2081 	}
2082 	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
2083 		goto fail;
2084 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
2085 	auth->Lx_len = auth->secret_len;
2086 	ret = 0;
2087 fail:
2088 	crypto_ec_point_deinit(l, 1);
2089 	crypto_bignum_deinit(lx, 0);
2090 	crypto_bignum_deinit(sum, 0);
2091 	crypto_bignum_deinit(q, 0);
2092 
2093 	return ret;
2094 }
2095 
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)2096 static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
2097 {
2098 	struct crypto_ec_group *group;
2099 	struct crypto_ec_point *l = NULL, *sum = NULL;
2100 	struct crypto_ec_point *BR_point, *PR_point;
2101 	struct crypto_bignum *lx;
2102 	struct crypto_bignum *bI_bn;
2103 	int ret = -1;
2104 
2105 	/* L = bI * (BR + PR) */
2106 
2107 	lx = crypto_bignum_init();
2108 	if (!lx)
2109 		goto fail;
2110 	BR_point = crypto_ec_get_public_key(auth->peer_bi->pubkey);
2111 	PR_point = crypto_ec_get_public_key(auth->peer_protocol_key);
2112 
2113 	group = crypto_ec_get_group_from_key(auth->own_bi->pubkey);
2114 	bI_bn = crypto_ec_get_private_key(auth->own_bi->pubkey);
2115 	if (!group || !bI_bn)
2116 		goto fail;
2117 	sum = crypto_ec_point_init((struct crypto_ec *)group);
2118 	l = crypto_ec_point_init((struct crypto_ec *)group);
2119 	if (!sum || !l ||
2120 	    crypto_ec_point_add((struct crypto_ec *)group, BR_point, PR_point, sum) != 0 ||
2121 	    crypto_ec_point_mul((struct crypto_ec *)group, sum, bI_bn, l) != 0 ||
2122 	    crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0) {
2123 		wpa_printf(MSG_ERROR,
2124 			   "OpenSSL: failed: %s", __func__);
2125 		goto fail;
2126 	}
2127 
2128 	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
2129 		goto fail;
2130 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
2131 	auth->Lx_len = auth->secret_len;
2132 	ret = 0;
2133 fail:
2134 	crypto_ec_point_deinit(l, 1);
2135 	crypto_ec_point_deinit(sum, 1);
2136 	crypto_bignum_deinit(lx, 0);
2137 
2138 
2139 	return ret;
2140 }
2141 
2142 
dpp_auth_build_resp_ok(struct dpp_authentication * auth)2143 static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
2144 {
2145 	size_t nonce_len;
2146 	size_t secret_len;
2147 	struct wpabuf *msg, *pr = NULL;
2148 	u8 r_auth[4 + DPP_MAX_HASH_LEN];
2149 	u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth;
2150 	size_t wrapped_r_auth_len;
2151 	int ret = -1;
2152 	const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce;
2153 	enum dpp_status_error status = DPP_STATUS_OK;
2154 #ifdef CONFIG_WPA_TESTING_OPTIONS
2155 	u8 test_hash[SHA256_MAC_LEN];
2156 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2157 
2158 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
2159 	if (!auth->own_bi)
2160 		return -1;
2161 
2162 #ifdef CONFIG_WPA_TESTING_OPTIONS
2163 	if (dpp_nonce_override_len > 0) {
2164 		wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce");
2165 		nonce_len = dpp_nonce_override_len;
2166 		os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len);
2167 	} else {
2168 		nonce_len = auth->curve->nonce_len;
2169 		if (random_get_bytes(auth->r_nonce, nonce_len)) {
2170 			wpa_printf(MSG_ERROR,
2171 				   "DPP: Failed to generate R-nonce");
2172 			goto fail;
2173 		}
2174 	}
2175 #else /* CONFIG_WPA_TESTING_OPTIONS */
2176 	nonce_len = auth->curve->nonce_len;
2177 	if (random_get_bytes(auth->r_nonce, nonce_len)) {
2178 		wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
2179 		goto fail;
2180 	}
2181 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2182 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
2183 
2184 	crypto_ec_free_key(auth->own_protocol_key);
2185 #ifdef CONFIG_WPA_TESTING_OPTIONS
2186 	if (dpp_protocol_key_override_len) {
2187 		const struct dpp_curve_params *tmp_curve;
2188 
2189 		wpa_printf(MSG_INFO,
2190 			   "DPP: TESTING - override protocol key");
2191 		auth->own_protocol_key = dpp_set_keypair(
2192 			&tmp_curve, dpp_protocol_key_override,
2193 			dpp_protocol_key_override_len);
2194 	} else {
2195 		auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2196 	}
2197 #else /* CONFIG_WPA_TESTING_OPTIONS */
2198 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2199 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2200 	if (!auth->own_protocol_key)
2201 		goto fail;
2202 
2203 	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2204 	if (!pr)
2205 		goto fail;
2206 
2207 	/* ECDH: N = pR * PI */
2208 	if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2209 		     auth->Nx, &secret_len) < 0)
2210 		goto fail;
2211 
2212 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
2213 			auth->Nx, auth->secret_len);
2214 	auth->Nx_len = auth->secret_len;
2215 
2216 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
2217 			  auth->curve->hash_len) < 0)
2218 		goto fail;
2219 
2220 	if (auth->own_bi && auth->peer_bi) {
2221 		/* Mutual authentication */
2222 		if (dpp_auth_derive_l_responder(auth) < 0)
2223 			goto fail;
2224 	}
2225 
2226 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
2227 		goto fail;
2228 
2229 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
2230 	WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
2231 	WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
2232 	if (dpp_gen_r_auth(auth, r_auth + 4) < 0)
2233 		goto fail;
2234 #ifdef CONFIG_WPA_TESTING_OPTIONS
2235 	if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) {
2236 		wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch");
2237 		r_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
2238 	}
2239 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2240 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2241 			    r_auth, 4 + auth->curve->hash_len,
2242 			    0, NULL, NULL, wrapped_r_auth) < 0)
2243 		goto fail;
2244 	wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
2245 	wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
2246 		    wrapped_r_auth, wrapped_r_auth_len);
2247 	w_r_auth = wrapped_r_auth;
2248 
2249 	r_pubkey_hash = auth->own_bi->pubkey_hash;
2250 	if (auth->peer_bi)
2251 		i_pubkey_hash = auth->peer_bi->pubkey_hash;
2252 	else
2253 		i_pubkey_hash = NULL;
2254 
2255 	i_nonce = auth->i_nonce;
2256 	r_nonce = auth->r_nonce;
2257 
2258 #ifdef CONFIG_WPA_TESTING_OPTIONS
2259 	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2260 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
2261 		r_pubkey_hash = NULL;
2262 	} else if (dpp_test ==
2263 		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2264 		wpa_printf(MSG_INFO,
2265 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
2266 		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
2267 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2268 		r_pubkey_hash = test_hash;
2269 	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2270 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
2271 		i_pubkey_hash = NULL;
2272 	} else if (dpp_test ==
2273 		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2274 		wpa_printf(MSG_INFO,
2275 			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
2276 		if (i_pubkey_hash)
2277 			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
2278 		else
2279 			os_memset(test_hash, 0, SHA256_MAC_LEN);
2280 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2281 		i_pubkey_hash = test_hash;
2282 	} else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) {
2283 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key");
2284 		wpabuf_free(pr);
2285 		pr = NULL;
2286 	} else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) {
2287 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key");
2288 		wpabuf_free(pr);
2289 		pr = wpabuf_alloc(2 * auth->curve->prime_len);
2290 		if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0)
2291 			goto fail;
2292 	} else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) {
2293 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth");
2294 		w_r_auth = NULL;
2295 		wrapped_r_auth_len = 0;
2296 	} else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
2297 		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
2298 		status = 255;
2299 	} else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) {
2300 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
2301 		status = 254;
2302 	} else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) {
2303 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce");
2304 		r_nonce = NULL;
2305 	} else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
2306 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
2307 		i_nonce = NULL;
2308 	}
2309 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2310 
2311 	msg = dpp_auth_build_resp(auth, status, pr, nonce_len,
2312 				  r_pubkey_hash, i_pubkey_hash,
2313 				  r_nonce, i_nonce,
2314 				  w_r_auth, wrapped_r_auth_len,
2315 				  auth->k2);
2316 	if (!msg)
2317 		goto fail;
2318 	wpabuf_free(auth->resp_msg);
2319 	auth->resp_msg = msg;
2320 	ret = 0;
2321 fail:
2322 	wpabuf_free(pr);
2323 	return ret;
2324 }
2325 
2326 
dpp_auth_build_resp_status(struct dpp_authentication * auth,enum dpp_status_error status)2327 static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
2328 				      enum dpp_status_error status)
2329 {
2330 	struct wpabuf *msg;
2331 	const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce;
2332 #ifdef CONFIG_WPA_TESTING_OPTIONS
2333 	u8 test_hash[SHA256_MAC_LEN];
2334 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2335 
2336 	if (!auth->own_bi)
2337 		return -1;
2338 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
2339 
2340 	r_pubkey_hash = auth->own_bi->pubkey_hash;
2341 	if (auth->peer_bi)
2342 		i_pubkey_hash = auth->peer_bi->pubkey_hash;
2343 	else
2344 		i_pubkey_hash = NULL;
2345 
2346 	i_nonce = auth->i_nonce;
2347 
2348 #ifdef CONFIG_WPA_TESTING_OPTIONS
2349 	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2350 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
2351 		r_pubkey_hash = NULL;
2352 	} else if (dpp_test ==
2353 		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2354 		wpa_printf(MSG_INFO,
2355 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
2356 		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
2357 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2358 		r_pubkey_hash = test_hash;
2359 	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2360 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
2361 		i_pubkey_hash = NULL;
2362 	} else if (dpp_test ==
2363 		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2364 		wpa_printf(MSG_INFO,
2365 			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
2366 		if (i_pubkey_hash)
2367 			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
2368 		else
2369 			os_memset(test_hash, 0, SHA256_MAC_LEN);
2370 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2371 		i_pubkey_hash = test_hash;
2372 	} else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
2373 		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
2374 		status = 255;
2375 	} else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
2376 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
2377 		i_nonce = NULL;
2378 	}
2379 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2380 
2381 	msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len,
2382 				  r_pubkey_hash, i_pubkey_hash,
2383 				  NULL, i_nonce, NULL, 0, auth->k1);
2384 	if (!msg)
2385 		return -1;
2386 	wpabuf_free(auth->resp_msg);
2387 	auth->resp_msg = msg;
2388 	return 0;
2389 }
2390 
2391 
2392 struct dpp_authentication *
dpp_auth_req_rx(void * msg_ctx,u8 dpp_allowed_roles,int qr_mutual,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,unsigned int curr_chan,const u8 * hdr,const u8 * attr_start,size_t attr_len)2393 dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
2394 		struct dpp_bootstrap_info *peer_bi,
2395 		struct dpp_bootstrap_info *own_bi,
2396 		unsigned int curr_chan, const u8 *hdr, const u8 *attr_start,
2397 		size_t attr_len)
2398 {
2399 	struct crypto_key *pi = NULL;
2400 	size_t secret_len;
2401 	const u8 *addr[2];
2402 	size_t len[2];
2403 	u8 *unwrapped = NULL;
2404 	size_t unwrapped_len = 0;
2405 	const u8 *wrapped_data;
2406 	const u8 *i_proto;
2407 	const u8 *i_nonce;
2408 	const u8 *i_capab;
2409 	const u8 *i_bootstrap;
2410 	u16 wrapped_data_len;
2411 	u16 i_proto_len;
2412 	u16 i_nonce_len;
2413 	u16 i_capab_len;
2414 	u16 i_bootstrap_len;
2415 	struct dpp_authentication *auth = NULL;
2416 
2417 #ifdef CONFIG_WPA_TESTING_OPTIONS
2418 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
2419 		wpa_printf(MSG_INFO,
2420 			   "DPP: TESTING - stop at Authentication Request");
2421 		return NULL;
2422 	}
2423 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2424 
2425 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2426 				    &wrapped_data_len);
2427 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
2428 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
2429 			"Missing or invalid required Wrapped Data attribute");
2430 		return NULL;
2431 	}
2432 	wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
2433 		    wrapped_data, wrapped_data_len);
2434 	attr_len = wrapped_data - 4 - attr_start;
2435 
2436 	auth = os_zalloc(sizeof(*auth));
2437 	if (!auth)
2438 		goto fail;
2439 	auth->msg_ctx = msg_ctx;
2440 	auth->peer_bi = peer_bi;
2441 	auth->own_bi = own_bi;
2442 	auth->curve = own_bi->curve;
2443 	auth->curr_chan = curr_chan;
2444 
2445 	auth->peer_version = 1; /* default to the first version */
2446 
2447 #if 0
2448 	channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
2449 			       &channel_len);
2450 	if (channel) {
2451 		//int neg_freq;
2452 
2453 		if (channel_len < 2) {
2454 			dpp_auth_fail(auth, "Too short Channel attribute");
2455 			goto fail;
2456 		}
2457 
2458 		neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
2459 		wpa_printf(MSG_DEBUG,
2460 			   "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
2461 			   channel[0], channel[1], neg_freq);
2462 		if (neg_freq < 0) {
2463 			dpp_auth_fail(auth,
2464 				      "Unsupported Channel attribute value");
2465 			goto fail;
2466 		}
2467 
2468 		if (auth->curr_freq != (unsigned int) neg_freq) {
2469 			wpa_printf(MSG_DEBUG,
2470 				   "DPP: Changing negotiation channel from %u MHz to %u MHz",
2471 				   freq, neg_freq);
2472 			auth->curr_freq = neg_freq;
2473 		}
2474 		/* rename it to chan */
2475 		auth->curr_chan = *channel;
2476 	}
2477 #endif
2478 
2479 	i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
2480 			       &i_proto_len);
2481 	if (!i_proto) {
2482 		dpp_auth_fail(auth,
2483 			      "Missing required Initiator Protocol Key attribute");
2484 		goto fail;
2485 	}
2486 	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
2487 		    i_proto, i_proto_len);
2488 
2489 	/* M = bR * PI */
2490 	pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
2491 	if (!pi) {
2492 		dpp_auth_fail(auth, "Invalid Initiator Protocol Key");
2493 		goto fail;
2494 	}
2495 	dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
2496 
2497 	if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
2498 		goto fail;
2499 	auth->secret_len = secret_len;
2500 
2501 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
2502 			auth->Mx, auth->secret_len);
2503 	auth->Mx_len = auth->secret_len;
2504 
2505 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
2506 			  auth->curve->hash_len) < 0)
2507 		goto fail;
2508 
2509 	addr[0] = hdr;
2510 	len[0] = DPP_HDR_LEN;
2511 	addr[1] = attr_start;
2512 	len[1] = attr_len;
2513 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2514 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2515 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2516 		    wrapped_data, wrapped_data_len);
2517 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2518 	unwrapped = os_malloc(unwrapped_len);
2519 	if (!unwrapped)
2520 		goto fail;
2521 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
2522 			    wrapped_data, wrapped_data_len,
2523 			    2, addr, len, unwrapped) < 0) {
2524 		dpp_auth_fail(auth, "AES-SIV decryption failed");
2525 		goto fail;
2526 	}
2527 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2528 		    unwrapped, unwrapped_len);
2529 
2530 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2531 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
2532 		goto fail;
2533 	}
2534 
2535 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2536 			       &i_nonce_len);
2537 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2538 		dpp_auth_fail(auth, "Missing or invalid I-nonce");
2539 		goto fail;
2540 	}
2541 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2542 	os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
2543 
2544 	i_capab = dpp_get_attr(unwrapped, unwrapped_len,
2545 			       DPP_ATTR_I_CAPABILITIES,
2546 			       &i_capab_len);
2547 	if (!i_capab || i_capab_len < 1) {
2548 		dpp_auth_fail(auth, "Missing or invalid I-capabilities");
2549 		goto fail;
2550 	}
2551 	auth->i_capab = i_capab[0];
2552 	wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
2553 
2554 	bin_clear_free(unwrapped, unwrapped_len);
2555 	unwrapped = NULL;
2556 
2557 	switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
2558 	case DPP_CAPAB_ENROLLEE:
2559 		if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
2560 			wpa_printf(MSG_DEBUG,
2561 				   "DPP: Local policy does not allow Configurator role");
2562 			goto not_compatible;
2563 		}
2564 		wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
2565 		auth->configurator = 1;
2566 		break;
2567 	case DPP_CAPAB_CONFIGURATOR:
2568 		if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
2569 			wpa_printf(MSG_DEBUG,
2570 				   "DPP: Local policy does not allow Enrollee role");
2571 			goto not_compatible;
2572 		}
2573 		wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
2574 		auth->configurator = 0;
2575 		break;
2576 	case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE:
2577 		if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) {
2578 			wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
2579 			auth->configurator = 0;
2580 		} else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) {
2581 			wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
2582 			auth->configurator = 1;
2583 		} else {
2584 			wpa_printf(MSG_DEBUG,
2585 				   "DPP: Local policy does not allow Configurator/Enrollee role");
2586 			goto not_compatible;
2587 		}
2588 		break;
2589 	default:
2590 		wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
2591 		goto fail;
2592 	}
2593 
2594 	auth->peer_protocol_key = pi;
2595 	pi = NULL;
2596 	if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
2597 		char hex[SHA256_MAC_LEN * 2 + 1];
2598 
2599 		wpa_printf(MSG_DEBUG,
2600 			   "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
2601 		if (dpp_auth_build_resp_status(auth,
2602 					       DPP_STATUS_RESPONSE_PENDING) < 0)
2603 			goto fail;
2604 		i_bootstrap = dpp_get_attr(attr_start, attr_len,
2605 					   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2606 					   &i_bootstrap_len);
2607 		if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
2608 			auth->response_pending = 1;
2609 			os_memcpy(auth->waiting_pubkey_hash,
2610 				  i_bootstrap, i_bootstrap_len);
2611 			wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
2612 					 i_bootstrap_len);
2613 		} else {
2614 			hex[0] = '\0';
2615 		}
2616 
2617 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
2618 			"%s", hex);
2619 		return auth;
2620 	}
2621 	if (dpp_auth_build_resp_ok(auth) < 0)
2622 		goto fail;
2623 
2624 	return auth;
2625 
2626 not_compatible:
2627 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
2628 		"i-capab=0x%02x", auth->i_capab);
2629 	if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
2630 		auth->configurator = 1;
2631 	else
2632 		auth->configurator = 0;
2633 	auth->peer_protocol_key = pi;
2634 	pi = NULL;
2635 	if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
2636 		goto fail;
2637 
2638 	auth->remove_on_tx_status = 1;
2639 	return auth;
2640 fail:
2641 	bin_clear_free(unwrapped, unwrapped_len);
2642 	crypto_ec_free_key(pi);
2643 	dpp_auth_deinit(auth);
2644 	return NULL;
2645 }
2646 
2647 
dpp_notify_new_qr_code(struct dpp_authentication * auth,struct dpp_bootstrap_info * peer_bi)2648 int dpp_notify_new_qr_code(struct dpp_authentication *auth,
2649 			   struct dpp_bootstrap_info *peer_bi)
2650 {
2651 	if (!auth || !auth->response_pending ||
2652 	    os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
2653 		      SHA256_MAC_LEN) != 0)
2654 		return 0;
2655 
2656 	wpa_printf(MSG_DEBUG,
2657 		   "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
2658 		   MACSTR, MAC2STR(auth->peer_mac_addr));
2659 	auth->peer_bi = peer_bi;
2660 
2661 	if (dpp_auth_build_resp_ok(auth) < 0)
2662 		return -1;
2663 
2664 	return 1;
2665 }
2666 
2667 
dpp_auth_build_conf(struct dpp_authentication * auth,enum dpp_status_error status)2668 static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth,
2669 					   enum dpp_status_error status)
2670 {
2671 	struct wpabuf *msg;
2672 	u8 i_auth[4 + DPP_MAX_HASH_LEN];
2673 	size_t i_auth_len;
2674 	u8 r_nonce[4 + DPP_MAX_NONCE_LEN];
2675 	size_t r_nonce_len;
2676 	const u8 *addr[2];
2677 	size_t len[2], attr_len;
2678 	u8 *wrapped_i_auth;
2679 	u8 *wrapped_r_nonce;
2680 	u8 *attr_start, *attr_end;
2681 	const u8 *r_pubkey_hash, *i_pubkey_hash;
2682 #ifdef CONFIG_WPA_TESTING_OPTIONS
2683 	u8 test_hash[SHA256_MAC_LEN];
2684 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2685 
2686 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
2687 
2688 	i_auth_len = 4 + auth->curve->hash_len;
2689 	r_nonce_len = 4 + auth->curve->nonce_len;
2690 	/* Build DPP Authentication Confirmation frame attributes */
2691 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
2692 		4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE;
2693 #ifdef CONFIG_WPA_TESTING_OPTIONS
2694 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF)
2695 		attr_len += 5;
2696 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2697 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
2698 	if (!msg)
2699 		goto fail;
2700 
2701 	attr_start = wpabuf_put(msg, 0);
2702 
2703 	r_pubkey_hash = auth->peer_bi->pubkey_hash;
2704 	if (auth->own_bi)
2705 		i_pubkey_hash = auth->own_bi->pubkey_hash;
2706 	else
2707 		i_pubkey_hash = NULL;
2708 
2709 #ifdef CONFIG_WPA_TESTING_OPTIONS
2710 	if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) {
2711 		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
2712 		goto skip_status;
2713 	} else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) {
2714 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
2715 		status = 254;
2716 	}
2717 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2718 
2719 	/* DPP Status */
2720 	dpp_build_attr_status(msg, status);
2721 
2722 #ifdef CONFIG_WPA_TESTING_OPTIONS
2723 skip_status:
2724 	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
2725 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
2726 		r_pubkey_hash = NULL;
2727 	} else if (dpp_test ==
2728 		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
2729 		wpa_printf(MSG_INFO,
2730 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
2731 		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
2732 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2733 		r_pubkey_hash = test_hash;
2734 	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
2735 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
2736 		i_pubkey_hash = NULL;
2737 	} else if (dpp_test ==
2738 		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
2739 		wpa_printf(MSG_INFO,
2740 			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
2741 		if (i_pubkey_hash)
2742 			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
2743 		else
2744 			os_memset(test_hash, 0, SHA256_MAC_LEN);
2745 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2746 		i_pubkey_hash = test_hash;
2747 	}
2748 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2749 
2750 	/* Responder Bootstrapping Key Hash */
2751 	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
2752 
2753 	/* Initiator Bootstrapping Key Hash (mutual authentication) */
2754 	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
2755 
2756 #ifdef CONFIG_WPA_TESTING_OPTIONS
2757 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF)
2758 		goto skip_wrapped_data;
2759 	if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
2760 		i_auth_len = 0;
2761 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2762 
2763 	attr_end = wpabuf_put(msg, 0);
2764 
2765 	/* OUI, OUI type, Crypto Suite, DPP frame type */
2766 	addr[0] = wpabuf_head_u8(msg) + 2;
2767 	len[0] = 3 + 1 + 1 + 1;
2768 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2769 
2770 	/* Attributes before Wrapped Data */
2771 	addr[1] = attr_start;
2772 	len[1] = attr_end - attr_start;
2773 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2774 
2775 	if (status == DPP_STATUS_OK) {
2776 		/* I-auth wrapped with ke */
2777 		wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2778 		wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
2779 		wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
2780 
2781 #ifdef CONFIG_WPA_TESTING_OPTIONS
2782 		if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
2783 			goto skip_i_auth;
2784 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2785 
2786 		/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |]
2787 		 *	      1) */
2788 		WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
2789 		WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
2790 		if (dpp_gen_i_auth(auth, i_auth + 4) < 0)
2791 			goto fail;
2792 
2793 #ifdef CONFIG_WPA_TESTING_OPTIONS
2794 		if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) {
2795 			wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch");
2796 			i_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
2797 		}
2798 skip_i_auth:
2799 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2800 		if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2801 				    i_auth, i_auth_len,
2802 				    2, addr, len, wrapped_i_auth) < 0)
2803 			goto fail;
2804 		wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
2805 			    wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
2806 	} else {
2807 		/* R-nonce wrapped with k2 */
2808 		wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2809 		wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE);
2810 		wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE);
2811 
2812 		WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE);
2813 		WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len);
2814 		os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len);
2815 
2816 		if (aes_siv_encrypt(auth->k2, auth->curve->hash_len,
2817 				    r_nonce, r_nonce_len,
2818 				    2, addr, len, wrapped_r_nonce) < 0)
2819 			goto fail;
2820 		wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2",
2821 			    wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE);
2822 	}
2823 
2824 #ifdef CONFIG_WPA_TESTING_OPTIONS
2825 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) {
2826 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
2827 		dpp_build_attr_status(msg, DPP_STATUS_OK);
2828 	}
2829 skip_wrapped_data:
2830 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2831 
2832 	wpa_hexdump_buf(MSG_DEBUG,
2833 			"DPP: Authentication Confirmation frame attributes",
2834 			msg);
2835 	if (status == DPP_STATUS_OK)
2836 		dpp_auth_success(auth);
2837 
2838 	return msg;
2839 
2840 fail:
2841 	wpabuf_free(msg);
2842 	return NULL;
2843 }
2844 
2845 
2846 static void
dpp_auth_resp_rx_status(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,const u8 * wrapped_data,u16 wrapped_data_len,enum dpp_status_error status)2847 dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
2848 			const u8 *attr_start, size_t attr_len,
2849 			const u8 *wrapped_data, u16 wrapped_data_len,
2850 			enum dpp_status_error status)
2851 {
2852 	const u8 *addr[2];
2853 	size_t len[2];
2854 	u8 *unwrapped = NULL;
2855 	size_t unwrapped_len = 0;
2856 	const u8 *i_nonce, *r_capab;
2857 	u16 i_nonce_len, r_capab_len;
2858 
2859 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
2860 		wpa_printf(MSG_DEBUG,
2861 			   "DPP: Responder reported incompatible roles");
2862 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
2863 		wpa_printf(MSG_DEBUG,
2864 			   "DPP: Responder reported more time needed");
2865 	} else {
2866 		wpa_printf(MSG_DEBUG,
2867 			   "DPP: Responder reported failure (status %d)",
2868 			   status);
2869 		dpp_auth_fail(auth, "Responder reported failure");
2870 		return;
2871 	}
2872 
2873 	addr[0] = hdr;
2874 	len[0] = DPP_HDR_LEN;
2875 	addr[1] = attr_start;
2876 	len[1] = attr_len;
2877 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2878 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2879 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2880 		    wrapped_data, wrapped_data_len);
2881 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2882 	unwrapped = os_malloc(unwrapped_len);
2883 	if (!unwrapped)
2884 		goto fail;
2885 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
2886 			    wrapped_data, wrapped_data_len,
2887 			    2, addr, len, unwrapped) < 0) {
2888 		dpp_auth_fail(auth, "AES-SIV decryption failed");
2889 		goto fail;
2890 	}
2891 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2892 		    unwrapped, unwrapped_len);
2893 
2894 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2895 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
2896 		goto fail;
2897 	}
2898 
2899 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2900 			       &i_nonce_len);
2901 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2902 		dpp_auth_fail(auth, "Missing or invalid I-nonce");
2903 		goto fail;
2904 	}
2905 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2906 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
2907 		dpp_auth_fail(auth, "I-nonce mismatch");
2908 		goto fail;
2909 	}
2910 
2911 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
2912 			       DPP_ATTR_R_CAPABILITIES,
2913 			       &r_capab_len);
2914 	if (!r_capab || r_capab_len < 1) {
2915 		dpp_auth_fail(auth, "Missing or invalid R-capabilities");
2916 		goto fail;
2917 	}
2918 	auth->r_capab = r_capab[0];
2919 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
2920 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
2921 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
2922 			"r-capab=0x%02x", auth->r_capab);
2923 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
2924 		u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
2925 
2926 		if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
2927 		    (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
2928 			wpa_msg(auth->msg_ctx, MSG_INFO,
2929 				DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x",
2930 				role);
2931 		} else {
2932 			wpa_printf(MSG_DEBUG,
2933 				   "DPP: Continue waiting for full DPP Authentication Response");
2934 			wpa_msg(auth->msg_ctx, MSG_INFO,
2935 				DPP_EVENT_RESPONSE_PENDING "%s",
2936 				auth->tmp_own_bi ? auth->tmp_own_bi->uri : "");
2937 		}
2938 	}
2939 fail:
2940 	bin_clear_free(unwrapped, unwrapped_len);
2941 }
2942 
2943 
2944 struct wpabuf *
dpp_auth_resp_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)2945 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
2946 		 const u8 *attr_start, size_t attr_len)
2947 {
2948 	struct crypto_key *pr;
2949 	size_t secret_len;
2950 	const u8 *addr[2];
2951 	size_t len[2];
2952 	u8 *unwrapped = NULL, *unwrapped2 = NULL;
2953 	size_t unwrapped_len = 0, unwrapped2_len = 0;
2954 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
2955 		*r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
2956 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
2957 		r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
2958 		wrapped2_len, r_auth_len;
2959 	u8 r_auth2[DPP_MAX_HASH_LEN];
2960 	u8 role;
2961 
2962 #ifdef CONFIG_WPA_TESTING_OPTIONS
2963 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) {
2964 		wpa_printf(MSG_INFO,
2965 			   "DPP: TESTING - stop at Authentication Response");
2966 		return NULL;
2967 	}
2968 #endif /* CONFIG_WPA_TESTING_OPTIONS */
2969 
2970 	if (!auth->initiator || !auth->peer_bi) {
2971 		dpp_auth_fail(auth, "Unexpected Authentication Response");
2972 		return NULL;
2973 	}
2974 
2975 	auth->waiting_auth_resp = 0;
2976 
2977 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2978 				    &wrapped_data_len);
2979 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
2980 		dpp_auth_fail(auth,
2981 			      "Missing or invalid required Wrapped Data attribute");
2982 		return NULL;
2983 	}
2984 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
2985 		    wrapped_data, wrapped_data_len);
2986 
2987 	attr_len = wrapped_data - 4 - attr_start;
2988 
2989 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
2990 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2991 				   &r_bootstrap_len);
2992 	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2993 		dpp_auth_fail(auth,
2994 			      "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2995 		return NULL;
2996 	}
2997 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
2998 		    r_bootstrap, r_bootstrap_len);
2999 	if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
3000 		      SHA256_MAC_LEN) != 0) {
3001 		dpp_auth_fail(auth,
3002 			      "Unexpected Responder Bootstrapping Key Hash value");
3003 		wpa_hexdump(MSG_DEBUG,
3004 			    "DPP: Expected Responder Bootstrapping Key Hash",
3005 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
3006 		return NULL;
3007 	}
3008 
3009 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
3010 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3011 				   &i_bootstrap_len);
3012 	if (i_bootstrap) {
3013 		if (i_bootstrap_len != SHA256_MAC_LEN) {
3014 			dpp_auth_fail(auth,
3015 				      "Invalid Initiator Bootstrapping Key Hash attribute");
3016 			return NULL;
3017 		}
3018 		wpa_hexdump(MSG_MSGDUMP,
3019 			    "DPP: Initiator Bootstrapping Key Hash",
3020 			    i_bootstrap, i_bootstrap_len);
3021 		if (!auth->own_bi ||
3022 		    os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
3023 			      SHA256_MAC_LEN) != 0) {
3024 			dpp_auth_fail(auth,
3025 				      "Initiator Bootstrapping Key Hash attribute did not match");
3026 			return NULL;
3027 		}
3028 	} else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) {
3029 		/* PKEX bootstrapping mandates use of mutual authentication */
3030 		dpp_auth_fail(auth,
3031 			      "Missing Initiator Bootstrapping Key Hash attribute");
3032 		return NULL;
3033 	}
3034 
3035 	auth->peer_version = 1; /* default to the first version */
3036 
3037 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
3038 			      &status_len);
3039 	if (!status || status_len < 1) {
3040 		dpp_auth_fail(auth,
3041 			      "Missing or invalid required DPP Status attribute");
3042 		return NULL;
3043 	}
3044 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3045 	auth->auth_resp_status = status[0];
3046 	if (status[0] != DPP_STATUS_OK) {
3047 		dpp_auth_resp_rx_status(auth, hdr, attr_start,
3048 					attr_len, wrapped_data,
3049 					wrapped_data_len, status[0]);
3050 		return NULL;
3051 	}
3052 
3053 	if (!i_bootstrap && auth->own_bi) {
3054 		wpa_printf(MSG_DEBUG,
3055 			   "DPP: Responder decided not to use mutual authentication");
3056 		auth->own_bi = NULL;
3057 	}
3058 
3059 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d",
3060 		auth->own_bi != NULL);
3061 
3062 	r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
3063 			       &r_proto_len);
3064 	if (!r_proto) {
3065 		dpp_auth_fail(auth,
3066 			      "Missing required Responder Protocol Key attribute");
3067 		return NULL;
3068 	}
3069 	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
3070 		    r_proto, r_proto_len);
3071 
3072 	/* N = pI * PR */
3073 	pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
3074 	if (!pr) {
3075 		dpp_auth_fail(auth, "Invalid Responder Protocol Key");
3076 		return NULL;
3077 	}
3078 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
3079 
3080 	if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
3081 		dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
3082 		goto fail;
3083 	}
3084 	crypto_ec_free_key(auth->peer_protocol_key);
3085 	auth->peer_protocol_key = pr;
3086 	pr = NULL;
3087 
3088 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
3089 			auth->Nx, auth->secret_len);
3090 	auth->Nx_len = auth->secret_len;
3091 
3092 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
3093 			  auth->curve->hash_len) < 0)
3094 		goto fail;
3095 
3096 	addr[0] = hdr;
3097 	len[0] = DPP_HDR_LEN;
3098 	addr[1] = attr_start;
3099 	len[1] = attr_len;
3100 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3101 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3102 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3103 		    wrapped_data, wrapped_data_len);
3104 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3105 	unwrapped = os_malloc(unwrapped_len);
3106 	if (!unwrapped)
3107 		goto fail;
3108 	if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
3109 			    wrapped_data, wrapped_data_len,
3110 			    2, addr, len, unwrapped) < 0) {
3111 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3112 		goto fail;
3113 	}
3114 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3115 		    unwrapped, unwrapped_len);
3116 
3117 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3118 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3119 		goto fail;
3120 	}
3121 
3122 	r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
3123 			       &r_nonce_len);
3124 	if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
3125 		dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
3126 		goto fail;
3127 	}
3128 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
3129 	os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
3130 
3131 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
3132 			       &i_nonce_len);
3133 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
3134 		dpp_auth_fail(auth, "Missing or invalid I-nonce");
3135 		goto fail;
3136 	}
3137 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
3138 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
3139 		dpp_auth_fail(auth, "I-nonce mismatch");
3140 		goto fail;
3141 	}
3142 
3143 	if (auth->own_bi) {
3144 		/* Mutual authentication */
3145 		if (dpp_auth_derive_l_initiator(auth) < 0)
3146 			goto fail;
3147 	}
3148 
3149 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
3150 			       DPP_ATTR_R_CAPABILITIES,
3151 			       &r_capab_len);
3152 	if (!r_capab || r_capab_len < 1) {
3153 		dpp_auth_fail(auth, "Missing or invalid R-capabilities");
3154 		goto fail;
3155 	}
3156 	auth->r_capab = r_capab[0];
3157 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
3158 	role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
3159 	if ((auth->allowed_roles ==
3160 	     (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) &&
3161 	    (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) {
3162 		/* Peer selected its role, so move from "either role" to the
3163 		 * role that is compatible with peer's selection. */
3164 		auth->configurator = role == DPP_CAPAB_ENROLLEE;
3165 		wpa_printf(MSG_DEBUG, "DPP: Acting as %s",
3166 			   auth->configurator ? "Configurator" : "Enrollee");
3167 	} else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
3168 		   (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
3169 		wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
3170 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
3171 			"Unexpected role in R-capabilities 0x%02x",
3172 			role);
3173 		if (role != DPP_CAPAB_ENROLLEE &&
3174 		    role != DPP_CAPAB_CONFIGURATOR)
3175 			goto fail;
3176 		bin_clear_free(unwrapped, unwrapped_len);
3177 		auth->remove_on_tx_status = 1;
3178 		return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE);
3179 	}
3180 
3181 	wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
3182 				DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
3183 	if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
3184 		dpp_auth_fail(auth,
3185 			      "Missing or invalid Secondary Wrapped Data");
3186 		goto fail;
3187 	}
3188 
3189 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3190 		    wrapped2, wrapped2_len);
3191 
3192 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
3193 		goto fail;
3194 
3195 	unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
3196 	unwrapped2 = os_malloc(unwrapped2_len);
3197 	if (!unwrapped2)
3198 		goto fail;
3199 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3200 			    wrapped2, wrapped2_len,
3201 			    0, NULL, NULL, unwrapped2) < 0) {
3202 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3203 		goto fail;
3204 	}
3205 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3206 		    unwrapped2, unwrapped2_len);
3207 
3208 	if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
3209 		dpp_auth_fail(auth,
3210 			      "Invalid attribute in secondary unwrapped data");
3211 		goto fail;
3212 	}
3213 
3214 	r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
3215 			       &r_auth_len);
3216 	if (!r_auth || r_auth_len != auth->curve->hash_len) {
3217 		dpp_auth_fail(auth,
3218 			      "Missing or invalid Responder Authenticating Tag");
3219 		goto fail;
3220 	}
3221 	wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
3222 		    r_auth, r_auth_len);
3223 	/* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
3224 	if (dpp_gen_r_auth(auth, r_auth2) < 0)
3225 		goto fail;
3226 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
3227 		    r_auth2, r_auth_len);
3228 	if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
3229 		dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag");
3230 		bin_clear_free(unwrapped, unwrapped_len);
3231 		bin_clear_free(unwrapped2, unwrapped2_len);
3232 		auth->remove_on_tx_status = 1;
3233 		return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE);
3234 	}
3235 
3236 	bin_clear_free(unwrapped, unwrapped_len);
3237 	bin_clear_free(unwrapped2, unwrapped2_len);
3238 
3239 #ifdef CONFIG_WPA_TESTING_OPTIONS
3240 	if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) {
3241 		wpa_printf(MSG_INFO,
3242 			   "DPP: TESTING - Authentication Response in place of Confirm");
3243 		if (dpp_auth_build_resp_ok(auth) < 0)
3244 			return NULL;
3245 		return wpabuf_dup(auth->resp_msg);
3246 	}
3247 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3248 
3249 	return dpp_auth_build_conf(auth, DPP_STATUS_OK);
3250 
3251 fail:
3252 	bin_clear_free(unwrapped, unwrapped_len);
3253 	bin_clear_free(unwrapped2, unwrapped2_len);
3254 	crypto_ec_free_key(pr);
3255 	return NULL;
3256 }
3257 
3258 
dpp_auth_conf_rx_failure(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,const u8 * wrapped_data,u16 wrapped_data_len,enum dpp_status_error status)3259 static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth,
3260 				    const u8 *hdr,
3261 				    const u8 *attr_start, size_t attr_len,
3262 				    const u8 *wrapped_data,
3263 				    u16 wrapped_data_len,
3264 				    enum dpp_status_error status)
3265 {
3266 	const u8 *addr[2];
3267 	size_t len[2];
3268 	u8 *unwrapped = NULL;
3269 	size_t unwrapped_len = 0;
3270 	const u8 *r_nonce;
3271 	u16 r_nonce_len;
3272 
3273 	/* Authentication Confirm failure cases are expected to include
3274 	 * {R-nonce}k2 in the Wrapped Data attribute. */
3275 
3276 	addr[0] = hdr;
3277 	len[0] = DPP_HDR_LEN;
3278 	addr[1] = attr_start;
3279 	len[1] = attr_len;
3280 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3281 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3282 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3283 		    wrapped_data, wrapped_data_len);
3284 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3285 	unwrapped = os_malloc(unwrapped_len);
3286 	if (!unwrapped) {
3287 		dpp_auth_fail(auth, "Authentication failed");
3288 		goto fail;
3289 	}
3290 	if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
3291 			    wrapped_data, wrapped_data_len,
3292 			    2, addr, len, unwrapped) < 0) {
3293 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3294 		goto fail;
3295 	}
3296 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3297 		    unwrapped, unwrapped_len);
3298 
3299 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3300 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3301 		goto fail;
3302 	}
3303 
3304 	r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
3305 			       &r_nonce_len);
3306 	if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
3307 		dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
3308 		goto fail;
3309 	}
3310 	if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
3311 		wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce",
3312 			    r_nonce, r_nonce_len);
3313 		wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce",
3314 			    auth->r_nonce, r_nonce_len);
3315 		dpp_auth_fail(auth, "R-nonce mismatch");
3316 		goto fail;
3317 	}
3318 
3319 	if (status == DPP_STATUS_NOT_COMPATIBLE)
3320 		dpp_auth_fail(auth, "Peer reported incompatible R-capab role");
3321 	else if (status == DPP_STATUS_AUTH_FAILURE)
3322 		dpp_auth_fail(auth, "Peer reported authentication failure)");
3323 
3324 fail:
3325 	bin_clear_free(unwrapped, unwrapped_len);
3326 	return -1;
3327 }
3328 
3329 
dpp_auth_conf_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)3330 int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
3331 		     const u8 *attr_start, size_t attr_len)
3332 {
3333 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
3334 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
3335 		i_auth_len;
3336 	const u8 *addr[2];
3337 	size_t len[2];
3338 	u8 *unwrapped = NULL;
3339 	size_t unwrapped_len = 0;
3340 	u8 i_auth2[DPP_MAX_HASH_LEN];
3341 
3342 #ifdef CONFIG_WPA_TESTING_OPTIONS
3343 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
3344 		wpa_printf(MSG_INFO,
3345 			   "DPP: TESTING - stop at Authentication Confirm");
3346 		return -1;
3347 	}
3348 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3349 
3350 	if (auth->initiator || !auth->own_bi) {
3351 		dpp_auth_fail(auth, "Unexpected Authentication Confirm");
3352 		return -1;
3353 	}
3354 
3355 	auth->waiting_auth_conf = 0;
3356 
3357 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3358 				    &wrapped_data_len);
3359 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3360 		dpp_auth_fail(auth,
3361 			      "Missing or invalid required Wrapped Data attribute");
3362 		return -1;
3363 	}
3364 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3365 		    wrapped_data, wrapped_data_len);
3366 
3367 	attr_len = wrapped_data - 4 - attr_start;
3368 
3369 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
3370 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3371 				   &r_bootstrap_len);
3372 	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
3373 		dpp_auth_fail(auth,
3374 			      "Missing or invalid required Responder Bootstrapping Key Hash attribute");
3375 		return -1;
3376 	}
3377 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
3378 		    r_bootstrap, r_bootstrap_len);
3379 	if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
3380 		      SHA256_MAC_LEN) != 0) {
3381 		wpa_hexdump(MSG_DEBUG,
3382 			    "DPP: Expected Responder Bootstrapping Key Hash",
3383 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
3384 		dpp_auth_fail(auth,
3385 			      "Responder Bootstrapping Key Hash mismatch");
3386 		return -1;
3387 	}
3388 
3389 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
3390 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3391 				   &i_bootstrap_len);
3392 	if (i_bootstrap) {
3393 		if (i_bootstrap_len != SHA256_MAC_LEN) {
3394 			dpp_auth_fail(auth,
3395 				      "Invalid Initiator Bootstrapping Key Hash attribute");
3396 			return -1;
3397 		}
3398 		wpa_hexdump(MSG_MSGDUMP,
3399 			    "DPP: Initiator Bootstrapping Key Hash",
3400 			    i_bootstrap, i_bootstrap_len);
3401 		if (!auth->peer_bi ||
3402 		    os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
3403 			      SHA256_MAC_LEN) != 0) {
3404 			dpp_auth_fail(auth,
3405 				      "Initiator Bootstrapping Key Hash mismatch");
3406 			return -1;
3407 		}
3408 	} else if (auth->peer_bi) {
3409 		/* Mutual authentication and peer did not include its
3410 		 * Bootstrapping Key Hash attribute. */
3411 		dpp_auth_fail(auth,
3412 			      "Missing Initiator Bootstrapping Key Hash attribute");
3413 		return -1;
3414 	}
3415 
3416 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
3417 			      &status_len);
3418 	if (!status || status_len < 1) {
3419 		dpp_auth_fail(auth,
3420 			      "Missing or invalid required DPP Status attribute");
3421 		return -1;
3422 	}
3423 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3424 	if (status[0] == DPP_STATUS_NOT_COMPATIBLE ||
3425 	    status[0] == DPP_STATUS_AUTH_FAILURE)
3426 		return dpp_auth_conf_rx_failure(auth, hdr, attr_start,
3427 						attr_len, wrapped_data,
3428 						wrapped_data_len, status[0]);
3429 
3430 	if (status[0] != DPP_STATUS_OK) {
3431 		dpp_auth_fail(auth, "Authentication failed");
3432 		return -1;
3433 	}
3434 
3435 	addr[0] = hdr;
3436 	len[0] = DPP_HDR_LEN;
3437 	addr[1] = attr_start;
3438 	len[1] = attr_len;
3439 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3440 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3441 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3442 		    wrapped_data, wrapped_data_len);
3443 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3444 	unwrapped = os_malloc(unwrapped_len);
3445 	if (!unwrapped)
3446 		return -1;
3447 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3448 			    wrapped_data, wrapped_data_len,
3449 			    2, addr, len, unwrapped) < 0) {
3450 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3451 		goto fail;
3452 	}
3453 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3454 		    unwrapped, unwrapped_len);
3455 
3456 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3457 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3458 		goto fail;
3459 	}
3460 
3461 	i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
3462 			      &i_auth_len);
3463 	if (!i_auth || i_auth_len != auth->curve->hash_len) {
3464 		dpp_auth_fail(auth,
3465 			      "Missing or invalid Initiator Authenticating Tag");
3466 		goto fail;
3467 	}
3468 	wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
3469 		    i_auth, i_auth_len);
3470 	/* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
3471 	if (dpp_gen_i_auth(auth, i_auth2) < 0)
3472 		goto fail;
3473 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
3474 		    i_auth2, i_auth_len);
3475 	if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
3476 		dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag");
3477 		goto fail;
3478 	}
3479 
3480 	bin_clear_free(unwrapped, unwrapped_len);
3481 	dpp_auth_success(auth);
3482 	return 0;
3483 fail:
3484 	bin_clear_free(unwrapped, unwrapped_len);
3485 	return -1;
3486 }
3487 
3488 
bin_str_eq(const char * val,size_t len,const char * cmp)3489 static int bin_str_eq(const char *val, size_t len, const char *cmp)
3490 {
3491 	return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
3492 }
3493 
3494 
dpp_configuration_alloc(const char * type)3495 struct dpp_configuration * dpp_configuration_alloc(const char *type)
3496 {
3497 	struct dpp_configuration *conf;
3498 	const char *end;
3499 	size_t len;
3500 
3501 	conf = os_zalloc(sizeof(*conf));
3502 	if (!conf)
3503 		goto fail;
3504 
3505 	end = os_strchr(type, ' ');
3506 	if (end)
3507 		len = end - type;
3508 	else
3509 		len = os_strlen(type);
3510 
3511 	if (bin_str_eq(type, len, "psk"))
3512 		conf->akm = DPP_AKM_PSK;
3513 	else if (bin_str_eq(type, len, "sae"))
3514 		conf->akm = DPP_AKM_SAE;
3515 	else if (bin_str_eq(type, len, "psk-sae") ||
3516 		 bin_str_eq(type, len, "psk+sae"))
3517 		conf->akm = DPP_AKM_PSK_SAE;
3518 	else if (bin_str_eq(type, len, "sae-dpp") ||
3519 		 bin_str_eq(type, len, "dpp+sae"))
3520 		conf->akm = DPP_AKM_SAE_DPP;
3521 	else if (bin_str_eq(type, len, "psk-sae-dpp") ||
3522 		 bin_str_eq(type, len, "dpp+psk+sae"))
3523 		conf->akm = DPP_AKM_PSK_SAE_DPP;
3524 	else if (bin_str_eq(type, len, "dpp"))
3525 		conf->akm = DPP_AKM_DPP;
3526 	else
3527 		goto fail;
3528 
3529 	return conf;
3530 fail:
3531 	dpp_configuration_free(conf);
3532 	return NULL;
3533 }
3534 
3535 
dpp_akm_psk(enum dpp_akm akm)3536 int dpp_akm_psk(enum dpp_akm akm)
3537 {
3538 	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
3539 		akm == DPP_AKM_PSK_SAE_DPP;
3540 }
3541 
3542 
dpp_akm_sae(enum dpp_akm akm)3543 int dpp_akm_sae(enum dpp_akm akm)
3544 {
3545 	return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE ||
3546 		akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
3547 }
3548 
3549 
dpp_akm_legacy(enum dpp_akm akm)3550 int dpp_akm_legacy(enum dpp_akm akm)
3551 {
3552 	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
3553 		akm == DPP_AKM_SAE;
3554 }
3555 
3556 
dpp_akm_dpp(enum dpp_akm akm)3557 int dpp_akm_dpp(enum dpp_akm akm)
3558 {
3559 	return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP ||
3560 		akm == DPP_AKM_PSK_SAE_DPP;
3561 }
3562 
3563 
dpp_akm_ver2(enum dpp_akm akm)3564 int dpp_akm_ver2(enum dpp_akm akm)
3565 {
3566 	return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
3567 }
3568 
3569 
dpp_configuration_valid(const struct dpp_configuration * conf)3570 int dpp_configuration_valid(const struct dpp_configuration *conf)
3571 {
3572 	if (conf->ssid_len == 0)
3573 		return 0;
3574 	if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
3575 		return 0;
3576 	if (dpp_akm_sae(conf->akm) && !conf->passphrase)
3577 		return 0;
3578 	return 1;
3579 }
3580 
3581 
dpp_configuration_free(struct dpp_configuration * conf)3582 void dpp_configuration_free(struct dpp_configuration *conf)
3583 {
3584 	if (!conf)
3585 		return;
3586 	str_clear_free(conf->passphrase);
3587 	os_free(conf->group_id);
3588 	bin_clear_free(conf, sizeof(*conf));
3589 }
3590 
3591 
dpp_configuration_parse_helper(struct dpp_authentication * auth,const char * cmd,int idx)3592 static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
3593 					  const char *cmd, int idx)
3594 {
3595 	const char *pos, *end;
3596 	struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
3597 	struct dpp_configuration *conf = NULL;
3598 
3599 	pos = os_strstr(cmd, " conf=sta-");
3600 	if (pos) {
3601 		conf_sta = dpp_configuration_alloc(pos + 10);
3602 		if (!conf_sta)
3603 			goto fail;
3604 		conf_sta->netrole = DPP_NETROLE_STA;
3605 		conf = conf_sta;
3606 	}
3607 
3608 	pos = os_strstr(cmd, " conf=ap-");
3609 	if (pos) {
3610 		conf_ap = dpp_configuration_alloc(pos + 9);
3611 		if (!conf_ap)
3612 			goto fail;
3613 		conf_ap->netrole = DPP_NETROLE_AP;
3614 		conf = conf_ap;
3615 	}
3616 
3617 	if (!conf)
3618 		return 0;
3619 
3620 	pos = os_strstr(cmd, " ssid=");
3621 	if (pos) {
3622 		pos += 6;
3623 		end = os_strchr(pos, ' ');
3624 		conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
3625 		conf->ssid_len /= 2;
3626 		if (conf->ssid_len > sizeof(conf->ssid) ||
3627 		    hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0)
3628 			goto fail;
3629 	} else {
3630 #ifdef CONFIG_WPA_TESTING_OPTIONS
3631 		/* use a default SSID for legacy testing reasons */
3632 		os_memcpy(conf->ssid, "test", 4);
3633 		conf->ssid_len = 4;
3634 #else /* CONFIG_WPA_TESTING_OPTIONS */
3635 		goto fail;
3636 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3637 	}
3638 
3639 	pos = os_strstr(cmd, " ssid_charset=");
3640 	if (pos) {
3641 		if (conf_ap) {
3642 			wpa_printf(MSG_INFO,
3643 				   "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee");
3644 			goto fail;
3645 		}
3646 		conf->ssid_charset = atoi(pos + 14);
3647 	}
3648 
3649 	pos = os_strstr(cmd, " pass=");
3650 	if (pos) {
3651 		size_t pass_len;
3652 
3653 		pos += 6;
3654 		end = os_strchr(pos, ' ');
3655 		pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
3656 		pass_len /= 2;
3657 		if (pass_len > 63 || pass_len < 8)
3658 			goto fail;
3659 		conf->passphrase = os_zalloc(pass_len + 1);
3660 		if (!conf->passphrase ||
3661 		    hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
3662 			goto fail;
3663 	}
3664 
3665 	pos = os_strstr(cmd, " psk=");
3666 	if (pos) {
3667 		pos += 5;
3668 		if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0)
3669 			goto fail;
3670 		conf->psk_set = 1;
3671 	}
3672 
3673 	pos = os_strstr(cmd, " group_id=");
3674 	if (pos) {
3675 		size_t group_id_len;
3676 
3677 		pos += 10;
3678 		end = os_strchr(pos, ' ');
3679 		group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
3680 		conf->group_id = os_malloc(group_id_len + 1);
3681 		if (!conf->group_id)
3682 			goto fail;
3683 		os_memcpy(conf->group_id, pos, group_id_len);
3684 		conf->group_id[group_id_len] = '\0';
3685 	}
3686 
3687 	pos = os_strstr(cmd, " expiry=");
3688 	if (pos) {
3689 		long int val;
3690 
3691 		pos += 8;
3692 		val = strtol(pos, NULL, 0);
3693 		if (val <= 0)
3694 			goto fail;
3695 		conf->netaccesskey_expiry = val;
3696 	}
3697 
3698 	if (!dpp_configuration_valid(conf))
3699 		goto fail;
3700 
3701 	if (idx == 0) {
3702 		auth->conf_sta = conf_sta;
3703 		auth->conf_ap = conf_ap;
3704 	} else if (idx == 1) {
3705 		auth->conf2_sta = conf_sta;
3706 		auth->conf2_ap = conf_ap;
3707 	} else {
3708 		goto fail;
3709 	}
3710 	return 0;
3711 
3712 fail:
3713 	dpp_configuration_free(conf_sta);
3714 	dpp_configuration_free(conf_ap);
3715 	return -1;
3716 }
3717 
3718 
dpp_configuration_parse(struct dpp_authentication * auth,const char * cmd)3719 static int dpp_configuration_parse(struct dpp_authentication *auth,
3720 				   const char *cmd)
3721 {
3722 	const char *pos;
3723 	char *tmp;
3724 	size_t len;
3725 	int res;
3726 
3727 	pos = os_strstr(cmd, " @CONF-OBJ-SEP@ ");
3728 	if (!pos)
3729 		return dpp_configuration_parse_helper(auth, cmd, 0);
3730 
3731 	len = pos - cmd;
3732 	tmp = os_malloc(len + 1);
3733 	if (!tmp)
3734 		goto fail;
3735 	os_memcpy(tmp, cmd, len);
3736 	tmp[len] = '\0';
3737 	res = dpp_configuration_parse_helper(auth, cmd, 0);
3738 	str_clear_free(tmp);
3739 	if (res)
3740 		goto fail;
3741 	res = dpp_configuration_parse_helper(auth, cmd + len, 1);
3742 	if (res)
3743 		goto fail;
3744 	return 0;
3745 fail:
3746 	dpp_configuration_free(auth->conf_sta);
3747 	dpp_configuration_free(auth->conf2_sta);
3748 	dpp_configuration_free(auth->conf_ap);
3749 	dpp_configuration_free(auth->conf2_ap);
3750 	return -1;
3751 }
3752 
3753 
3754 static struct dpp_configurator *
dpp_configurator_get_id(struct dpp_global * dpp,unsigned int id)3755 dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id)
3756 {
3757 	struct dpp_configurator *conf;
3758 
3759 	if (!dpp)
3760 		return NULL;
3761 
3762 	dl_list_for_each(conf, &dpp->configurator,
3763 			 struct dpp_configurator, list) {
3764 		if (conf->id == id)
3765 			return conf;
3766 	}
3767 	return NULL;
3768 }
3769 
3770 
dpp_set_configurator(struct dpp_global * dpp,void * msg_ctx,struct dpp_authentication * auth,const char * cmd)3771 int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
3772 			 struct dpp_authentication *auth,
3773 			 const char *cmd)
3774 {
3775 	const char *pos;
3776 
3777 	if (!cmd)
3778 		return 0;
3779 
3780 	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
3781 
3782 	pos = os_strstr(cmd, " configurator=");
3783 	if (pos) {
3784 		pos += 14;
3785 		auth->conf = dpp_configurator_get_id(dpp, atoi(pos));
3786 		if (!auth->conf) {
3787 			wpa_printf(MSG_INFO,
3788 				   "DPP: Could not find the specified configurator");
3789 			return -1;
3790 		}
3791 	}
3792 
3793 	pos = os_strstr(cmd, " conn_status=");
3794 	if (pos) {
3795 		pos += 13;
3796 		auth->send_conn_status = atoi(pos);
3797 	}
3798 
3799 	pos = os_strstr(cmd, " akm_use_selector=");
3800 	if (pos) {
3801 		pos += 18;
3802 		auth->akm_use_selector = atoi(pos);
3803 	}
3804 
3805 	if (dpp_configuration_parse(auth, cmd) < 0) {
3806 		wpa_msg(msg_ctx, MSG_INFO,
3807 			"DPP: Failed to set configurator parameters");
3808 		return -1;
3809 	}
3810 	return 0;
3811 }
3812 
3813 
dpp_auth_deinit(struct dpp_authentication * auth)3814 void dpp_auth_deinit(struct dpp_authentication *auth)
3815 {
3816 	unsigned int i;
3817 
3818 	if (!auth)
3819 		return;
3820 	dpp_configuration_free(auth->conf_ap);
3821 	dpp_configuration_free(auth->conf2_ap);
3822 	dpp_configuration_free(auth->conf_sta);
3823 	dpp_configuration_free(auth->conf2_sta);
3824 	crypto_ec_free_key(auth->own_protocol_key);
3825 	crypto_ec_free_key(auth->peer_protocol_key);
3826 	wpabuf_free(auth->req_msg);
3827 	wpabuf_free(auth->resp_msg);
3828 	wpabuf_free(auth->conf_req);
3829 	for (i = 0; i < auth->num_conf_obj; i++) {
3830 		struct dpp_config_obj *conf = &auth->conf_obj[i];
3831 
3832 		os_free(conf->connector);
3833 		wpabuf_free(conf->c_sign_key);
3834 	}
3835 	wpabuf_free(auth->net_access_key);
3836 	dpp_bootstrap_info_free(auth->tmp_own_bi);
3837 #ifdef CONFIG_WPA_TESTING_OPTIONS
3838 	os_free(auth->config_obj_override);
3839 	os_free(auth->discovery_override);
3840 	os_free(auth->groups_override);
3841 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3842 	bin_clear_free(auth, sizeof(*auth));
3843 }
3844 
3845 
3846 static struct wpabuf *
dpp_build_conf_start(struct dpp_authentication * auth,struct dpp_configuration * conf,size_t tailroom)3847 dpp_build_conf_start(struct dpp_authentication *auth,
3848 		     struct dpp_configuration *conf, size_t tailroom)
3849 {
3850 	struct wpabuf *buf;
3851 
3852 #ifdef CONFIG_WPA_TESTING_OPTIONS
3853 	if (auth->discovery_override)
3854 		tailroom += os_strlen(auth->discovery_override);
3855 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3856 
3857 	buf = wpabuf_alloc(200 + tailroom);
3858 	if (!buf)
3859 		return NULL;
3860 	json_start_object(buf, NULL);
3861 	json_add_string(buf, "wi-fi_tech", "infra");
3862 	json_value_sep(buf);
3863 #ifdef CONFIG_WPA_TESTING_OPTIONS
3864 	if (auth->discovery_override) {
3865 		wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
3866 			   auth->discovery_override);
3867 		wpabuf_put_str(buf, "\"discovery\":");
3868 		wpabuf_put_str(buf, auth->discovery_override);
3869 		json_value_sep(buf);
3870 		return buf;
3871 	}
3872 #endif /* CONFIG_WPA_TESTING_OPTIONS */
3873 	json_start_object(buf, "discovery");
3874 	if (((!conf->ssid_charset || auth->peer_version < 2) &&
3875 	     json_add_string_escape(buf, "ssid", conf->ssid,
3876 				    conf->ssid_len) < 0) ||
3877 	    ((conf->ssid_charset && auth->peer_version >= 2) &&
3878 	     json_add_base64url(buf, "ssid64", conf->ssid,
3879 				conf->ssid_len) < 0)) {
3880 		wpabuf_free(buf);
3881 		return NULL;
3882 	}
3883 	if (conf->ssid_charset > 0) {
3884 		json_value_sep(buf);
3885 		json_add_int(buf, "ssid_charset", conf->ssid_charset);
3886 	}
3887 	json_end_object(buf);
3888 	json_value_sep(buf);
3889 
3890 	return buf;
3891 }
3892 
3893 
dpp_build_jwk(struct wpabuf * buf,const char * name,struct crypto_key * key,const char * kid,const struct dpp_curve_params * curve)3894 static int dpp_build_jwk(struct wpabuf *buf, const char *name, struct crypto_key *key,
3895 			 const char *kid, const struct dpp_curve_params *curve)
3896 {
3897 	struct wpabuf *pub;
3898 	const u8 *pos;
3899 	int ret = -1;
3900 
3901 	pub = dpp_get_pubkey_point(key, 0);
3902 	if (!pub)
3903 		goto fail;
3904 
3905 	json_start_object(buf, name);
3906 	json_add_string(buf, "kty", "EC");
3907 	json_value_sep(buf);
3908 	json_add_string(buf, "crv", curve->jwk_crv);
3909 	json_value_sep(buf);
3910 	pos = wpabuf_head(pub);
3911 	if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0)
3912 		goto fail;
3913 	json_value_sep(buf);
3914 	pos += curve->prime_len;
3915 	if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0)
3916 		goto fail;
3917 	if (kid) {
3918 		json_value_sep(buf);
3919 		json_add_string(buf, "kid", kid);
3920 	}
3921 	json_end_object(buf);
3922 	ret = 0;
3923 fail:
3924 	wpabuf_free(pub);
3925 	return ret;
3926 }
3927 
3928 
dpp_build_legacy_cred_params(struct wpabuf * buf,struct dpp_configuration * conf)3929 static void dpp_build_legacy_cred_params(struct wpabuf *buf,
3930 					 struct dpp_configuration *conf)
3931 {
3932 	if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
3933 		json_add_string_escape(buf, "pass", conf->passphrase,
3934 				       os_strlen(conf->passphrase));
3935 	} else if (conf->psk_set) {
3936 		char psk[2 * sizeof(conf->psk) + 1];
3937 
3938 		wpa_snprintf_hex(psk, sizeof(psk),
3939 				 conf->psk, sizeof(conf->psk));
3940 		json_add_string(buf, "psk_hex", psk);
3941 	    os_memset(psk, 0, sizeof(psk));
3942 	}
3943 }
3944 
3945 
dpp_netrole_str(enum dpp_netrole netrole)3946 static const char * dpp_netrole_str(enum dpp_netrole netrole)
3947 {
3948 	switch (netrole) {
3949 	case DPP_NETROLE_STA:
3950 		return "sta";
3951 	case DPP_NETROLE_AP:
3952 		return "ap";
3953 	case DPP_NETROLE_CONFIGURATOR:
3954 		return "configurator";
3955 	default:
3956 		return "??";
3957 	}
3958 }
3959 
dpp_get_config_obj_hash(char * signed1,size_t signed1_len,char * signed2,size_t signed2_len,unsigned char * hash,int hash_len)3960 int dpp_get_config_obj_hash(char *signed1, size_t signed1_len,
3961 		char *signed2, size_t signed2_len,
3962 		unsigned char *hash, int hash_len)
3963 {
3964 	const char *dot = ".";
3965 	int ret = -1;
3966 	const u8 *addr[3];
3967 	size_t len[3];
3968 
3969 #ifdef ESP_SUPPLICANT
3970 	if (hash_len != SHA256_MAC_LEN)
3971 		return ret;
3972 #endif
3973 	addr[0] = (unsigned char *)signed1;
3974 	len[0] = signed1_len;
3975 	addr[1] = (unsigned char *)dot;
3976 	len[1] = 1;
3977 	addr[2] = (unsigned char *)signed2;
3978 	len[2] = signed2_len;
3979 	ret = sha256_vector(3, addr, len, hash);
3980 
3981 	return ret;
3982 }
3983 
3984 static struct wpabuf *
dpp_build_conf_obj_dpp(struct dpp_authentication * auth,struct dpp_configuration * conf)3985 dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
3986 		       struct dpp_configuration *conf)
3987 {
3988 	struct wpabuf *buf = NULL;
3989 	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
3990 	size_t tailroom;
3991 	const struct dpp_curve_params *curve;
3992 	struct wpabuf *jws_prot_hdr;
3993 	size_t signed1_len, signed2_len, signed3_len;
3994 	struct wpabuf *dppcon = NULL;
3995 	unsigned char *signature = NULL;
3996 	size_t signature_len;
3997 	struct crypto_bignum *r = NULL, *s = NULL;
3998 	size_t extra_len = 1000;
3999 	int incl_legacy;
4000 	enum dpp_akm akm;
4001 	const char *akm_str;
4002 	unsigned char *hash = NULL;
4003 
4004 	if (!auth->conf) {
4005 		wpa_printf(MSG_INFO,
4006 			   "DPP: No configurator specified - cannot generate DPP config object");
4007 		goto fail;
4008 	}
4009 	curve = auth->conf->curve;
4010 	akm = conf->akm;
4011 	if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
4012 		wpa_printf(MSG_DEBUG,
4013 			   "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2");
4014 		akm = DPP_AKM_DPP;
4015 	}
4016 
4017 #ifdef CONFIG_WPA_TESTING_OPTIONS
4018 	if (auth->groups_override)
4019 		extra_len += os_strlen(auth->groups_override);
4020 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4021 
4022 	if (conf->group_id)
4023 		extra_len += os_strlen(conf->group_id);
4024 
4025 	/* Connector (JSON dppCon object) */
4026 	dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3);
4027 	if (!dppcon)
4028 		goto fail;
4029 #ifdef CONFIG_WPA_TESTING_OPTIONS
4030 	if (auth->groups_override) {
4031 		wpabuf_put_u8(dppcon, '{');
4032 		if (auth->groups_override) {
4033 			wpa_printf(MSG_DEBUG,
4034 				   "DPP: TESTING - groups override: '%s'",
4035 				   auth->groups_override);
4036 			wpabuf_put_str(dppcon, "\"groups\":");
4037 			wpabuf_put_str(dppcon, auth->groups_override);
4038 			json_value_sep(dppcon);
4039 		}
4040 		goto skip_groups;
4041 	}
4042 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4043 	json_start_object(dppcon, NULL);
4044 	json_start_array(dppcon, "groups");
4045 	json_start_object(dppcon, NULL);
4046 	json_add_string(dppcon, "groupId",
4047 			conf->group_id ? conf->group_id : "*");
4048 	json_value_sep(dppcon);
4049 	json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole));
4050 	json_end_object(dppcon);
4051 	json_end_array(dppcon);
4052 	json_value_sep(dppcon);
4053 #ifdef CONFIG_WPA_TESTING_OPTIONS
4054 skip_groups:
4055 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4056 	if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
4057 			  auth->curve) < 0) {
4058 		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
4059 		goto fail;
4060 	}
4061 	if (conf->netaccesskey_expiry) {
4062 		struct os_tm tm;
4063 		char expiry[30];
4064 
4065 		if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
4066 			wpa_printf(MSG_DEBUG,
4067 				   "DPP: Failed to generate expiry string");
4068 			goto fail;
4069 		}
4070 		os_snprintf(expiry, sizeof(expiry),
4071 			    "%04u-%02u-%02uT%02u:%02u:%02uZ",
4072 			    tm.year, tm.month, tm.day,
4073 			    tm.hour, tm.min, tm.sec);
4074 		json_value_sep(dppcon);
4075 		json_add_string(dppcon, "expiry", expiry);
4076 	}
4077 	json_end_object(dppcon);
4078 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
4079 		   (const char *) wpabuf_head(dppcon));
4080 
4081 	jws_prot_hdr = wpabuf_alloc(100);
4082 	if (!jws_prot_hdr)
4083 		goto fail;
4084 	json_start_object(jws_prot_hdr, NULL);
4085 	json_add_string(jws_prot_hdr, "typ", "dppCon");
4086 	json_value_sep(jws_prot_hdr);
4087 	json_add_string(jws_prot_hdr, "kid", auth->conf->kid);
4088 	json_value_sep(jws_prot_hdr);
4089 	json_add_string(jws_prot_hdr, "alg", curve->jws_alg);
4090 	json_end_object(jws_prot_hdr);
4091 	signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
4092 				    wpabuf_len(jws_prot_hdr),
4093 				    &signed1_len);
4094 	wpabuf_free(jws_prot_hdr);
4095 	signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
4096 				    &signed2_len);
4097 	if (!signed1 || !signed2)
4098 		goto fail;
4099 
4100 	hash = os_malloc(curve->hash_len);
4101 	if (!hash) {
4102 		goto fail;
4103 	}
4104 	if (dpp_get_config_obj_hash(signed1, signed1_len, signed2, signed1_len, hash, curve->hash_len) < 0)
4105 		goto fail;
4106 
4107 	r = crypto_bignum_init();
4108 	s = crypto_bignum_init();
4109 	if (crypto_ecdsa_get_sign(hash, r, s, auth->conf->csign, curve->hash_len) < 0)
4110 		goto fail;
4111 
4112 	signature = os_malloc(2 * curve->prime_len);
4113 	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
4114 			dpp_bn2bin_pad(s, signature + curve->prime_len,
4115 				curve->prime_len) < 0)
4116 		goto fail;
4117 	signature_len = 2 * curve->prime_len;
4118 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
4119 		    signature, signature_len);
4120 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
4121 	if (!signed3)
4122 		goto fail;
4123 
4124 	incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
4125 	tailroom = 1000;
4126 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
4127 	tailroom += signed1_len + signed2_len + signed3_len;
4128 	if (incl_legacy)
4129 		tailroom += 1000;
4130 	buf = dpp_build_conf_start(auth, conf, tailroom);
4131 	if (!buf)
4132 		goto fail;
4133 
4134 	if (auth->akm_use_selector && dpp_akm_ver2(akm))
4135 		akm_str = dpp_akm_selector_str(akm);
4136 	else
4137 		akm_str = dpp_akm_str(akm);
4138 	json_start_object(buf, "cred");
4139 	json_add_string(buf, "akm", akm_str);
4140 	json_value_sep(buf);
4141 	if (incl_legacy) {
4142 		dpp_build_legacy_cred_params(buf, conf);
4143 		json_value_sep(buf);
4144 	}
4145 	wpabuf_put_str(buf, "\"signedConnector\":\"");
4146 	wpabuf_put_str(buf, signed1);
4147 	wpabuf_put_u8(buf, '.');
4148 	wpabuf_put_str(buf, signed2);
4149 	wpabuf_put_u8(buf, '.');
4150 	wpabuf_put_str(buf, signed3);
4151 	wpabuf_put_str(buf, "\"");
4152 	json_value_sep(buf);
4153 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
4154 			  curve) < 0) {
4155 		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
4156 		goto fail;
4157 	}
4158 
4159 	json_end_object(buf);
4160 	json_end_object(buf);
4161 
4162 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
4163 			      (u8 *)wpabuf_head(buf), wpabuf_len(buf));
4164 
4165 out:
4166 	if (signed1)
4167 		os_free(signed1);
4168 	if (signed2)
4169 		os_free(signed2);
4170 	if (signed3)
4171 		os_free(signed3);
4172 	if (hash)
4173 		os_free(hash);
4174 	if (signature)
4175 		os_free(signature);
4176 	crypto_bignum_deinit(r, 0);
4177 	crypto_bignum_deinit(s, 0);
4178 	wpabuf_free(dppcon);
4179 	return buf;
4180 fail:
4181 	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
4182 	wpabuf_free(buf);
4183 	buf = NULL;
4184 	goto out;
4185 }
4186 
4187 static struct wpabuf *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,struct dpp_configuration * conf)4188 dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
4189 			  struct dpp_configuration *conf)
4190 {
4191 	struct wpabuf *buf;
4192 	const char *akm_str;
4193 
4194 	buf = dpp_build_conf_start(auth, conf, 1000);
4195 	if (!buf)
4196 		return NULL;
4197 
4198 	if (auth->akm_use_selector && dpp_akm_ver2(conf->akm))
4199 		akm_str = dpp_akm_selector_str(conf->akm);
4200 	else
4201 		akm_str = dpp_akm_str(conf->akm);
4202 	json_start_object(buf, "cred");
4203 	json_add_string(buf, "akm", akm_str);
4204 	json_value_sep(buf);
4205 	dpp_build_legacy_cred_params(buf, conf);
4206 	json_end_object(buf);
4207 	json_end_object(buf);
4208 
4209 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
4210 			      (u8 *)wpabuf_head(buf), wpabuf_len(buf));
4211 
4212 	return buf;
4213 }
4214 
4215 
4216 static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication * auth,enum dpp_netrole netrole,int idx)4217 dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
4218 		   int idx)
4219 {
4220 	struct dpp_configuration *conf = NULL;
4221 
4222 #ifdef CONFIG_WPA_TESTING_OPTIONS
4223 	if (auth->config_obj_override) {
4224 		if (idx != 0)
4225 			return NULL;
4226 		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
4227 		return wpabuf_alloc_copy(auth->config_obj_override,
4228 					 os_strlen(auth->config_obj_override));
4229 	}
4230 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4231 
4232 	if (idx == 0) {
4233 		if (netrole == DPP_NETROLE_STA)
4234 			conf = auth->conf_sta;
4235 		else if (netrole == DPP_NETROLE_AP)
4236 			conf = auth->conf_ap;
4237 	} else if (idx == 1) {
4238 		if (netrole == DPP_NETROLE_STA)
4239 			conf = auth->conf2_sta;
4240 		else if (netrole == DPP_NETROLE_AP)
4241 			conf = auth->conf2_ap;
4242 	}
4243 	if (!conf) {
4244 		if (idx == 0)
4245 			wpa_printf(MSG_DEBUG,
4246 				   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
4247 				   dpp_netrole_str(netrole));
4248 		return NULL;
4249 	}
4250 
4251 	if (dpp_akm_dpp(conf->akm))
4252 		return dpp_build_conf_obj_dpp(auth, conf);
4253 	return dpp_build_conf_obj_legacy(auth, conf);
4254 }
4255 
4256 
4257 static struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,enum dpp_netrole netrole)4258 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
4259 		    u16 e_nonce_len, enum dpp_netrole netrole)
4260 {
4261 	struct wpabuf *conf, *conf2 = NULL;
4262 	size_t clear_len, attr_len;
4263 	struct wpabuf *clear = NULL, *msg = NULL;
4264 	u8 *wrapped;
4265 	const u8 *addr[1];
4266 	size_t len[1];
4267 	enum dpp_status_error status;
4268 
4269 	conf = dpp_build_conf_obj(auth, netrole, 0);
4270 	if (conf) {
4271 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
4272 				  (u8 *)wpabuf_head(conf), wpabuf_len(conf));
4273 		conf2 = dpp_build_conf_obj(auth, netrole, 1);
4274 	}
4275 	status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
4276 	auth->conf_resp_status = status;
4277 
4278 	/* { E-nonce, configurationObject[, sendConnStatus]}ke */
4279 	clear_len = 4 + e_nonce_len;
4280 	if (conf)
4281 		clear_len += 4 + wpabuf_len(conf);
4282 	if (conf2)
4283 		clear_len += 4 + wpabuf_len(conf2);
4284 	if (auth->peer_version >= 2 && auth->send_conn_status &&
4285 	    netrole == DPP_NETROLE_STA)
4286 		clear_len += 4;
4287 	clear = wpabuf_alloc(clear_len);
4288 	attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
4289 #ifdef CONFIG_WPA_TESTING_OPTIONS
4290 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
4291 		attr_len += 5;
4292 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4293 	msg = wpabuf_alloc(attr_len);
4294 	if (!clear || !msg)
4295 		goto fail;
4296 
4297 #ifdef CONFIG_WPA_TESTING_OPTIONS
4298 	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
4299 		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
4300 		goto skip_e_nonce;
4301 	}
4302 	if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
4303 		wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
4304 		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4305 		wpabuf_put_le16(clear, e_nonce_len);
4306 		wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
4307 		wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
4308 		goto skip_e_nonce;
4309 	}
4310 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
4311 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
4312 		goto skip_wrapped_data;
4313 	}
4314 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4315 
4316 	/* E-nonce */
4317 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4318 	wpabuf_put_le16(clear, e_nonce_len);
4319 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
4320 
4321 #ifdef CONFIG_WPA_TESTING_OPTIONS
4322 skip_e_nonce:
4323 	if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
4324 		wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
4325 		goto skip_config_obj;
4326 	}
4327 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4328 
4329 	if (conf) {
4330 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
4331 		wpabuf_put_le16(clear, wpabuf_len(conf));
4332 		wpabuf_put_buf(clear, conf);
4333 	}
4334 	if (auth->peer_version >= 2 && conf2) {
4335 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
4336 		wpabuf_put_le16(clear, wpabuf_len(conf2));
4337 		wpabuf_put_buf(clear, conf2);
4338 	} else if (conf2) {
4339 		wpa_printf(MSG_DEBUG,
4340 			   "DPP: Second Config Object available, but peer does not support more than one");
4341 	}
4342 
4343 	if (auth->peer_version >= 2 && auth->send_conn_status &&
4344 	    netrole == DPP_NETROLE_STA) {
4345 		wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
4346 		wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
4347 		wpabuf_put_le16(clear, 0);
4348 	}
4349 
4350 #ifdef CONFIG_WPA_TESTING_OPTIONS
4351 skip_config_obj:
4352 	if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
4353 		wpa_printf(MSG_INFO, "DPP: TESTING - Status");
4354 		goto skip_status;
4355 	}
4356 	if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
4357 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
4358 		status = 255;
4359 	}
4360 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4361 
4362 	/* DPP Status */
4363 	dpp_build_attr_status(msg, status);
4364 
4365 #ifdef CONFIG_WPA_TESTING_OPTIONS
4366 skip_status:
4367 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4368 
4369 	addr[0] = wpabuf_head(msg);
4370 	len[0] = wpabuf_len(msg);
4371 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
4372 
4373 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
4374 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4375 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4376 
4377 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
4378 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
4379 			    wpabuf_head(clear), wpabuf_len(clear),
4380 			    1, addr, len, wrapped) < 0)
4381 		goto fail;
4382 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4383 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
4384 
4385 #ifdef CONFIG_WPA_TESTING_OPTIONS
4386 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) {
4387 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
4388 		dpp_build_attr_status(msg, DPP_STATUS_OK);
4389 	}
4390 skip_wrapped_data:
4391 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4392 
4393 	wpa_hexdump_buf(MSG_DEBUG,
4394 			"DPP: Configuration Response attributes", msg);
4395 out:
4396 	wpabuf_free(conf);
4397 	wpabuf_free(conf2);
4398 	wpabuf_free(clear);
4399 
4400 	return msg;
4401 fail:
4402 	wpabuf_free(msg);
4403 	msg = NULL;
4404 	goto out;
4405 }
4406 
4407 
4408 struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)4409 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
4410 		size_t attr_len)
4411 {
4412 	const u8 *wrapped_data, *e_nonce, *config_attr;
4413 	u16 wrapped_data_len, e_nonce_len, config_attr_len;
4414 	u8 *unwrapped = NULL;
4415 	size_t unwrapped_len = 0;
4416 	struct wpabuf *resp = NULL;
4417 	struct json_token *root = NULL, *token;
4418 	enum dpp_netrole netrole;
4419 
4420 #ifdef CONFIG_WPA_TESTING_OPTIONS
4421 	if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
4422 		wpa_printf(MSG_INFO,
4423 			   "DPP: TESTING - stop at Config Request");
4424 		return NULL;
4425 	}
4426 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4427 
4428 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
4429 		dpp_auth_fail(auth, "Invalid attribute in config request");
4430 		return NULL;
4431 	}
4432 
4433 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
4434 				    &wrapped_data_len);
4435 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
4436 		dpp_auth_fail(auth,
4437 			      "Missing or invalid required Wrapped Data attribute");
4438 		return NULL;
4439 	}
4440 
4441 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4442 		    wrapped_data, wrapped_data_len);
4443 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
4444 	unwrapped = os_malloc(unwrapped_len);
4445 	if (!unwrapped)
4446 		return NULL;
4447 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
4448 			    wrapped_data, wrapped_data_len,
4449 			    0, NULL, NULL, unwrapped) < 0) {
4450 		dpp_auth_fail(auth, "AES-SIV decryption failed");
4451 		goto fail;
4452 	}
4453 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
4454 		    unwrapped, unwrapped_len);
4455 
4456 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
4457 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
4458 		goto fail;
4459 	}
4460 
4461 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
4462 			       DPP_ATTR_ENROLLEE_NONCE,
4463 			       &e_nonce_len);
4464 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
4465 		dpp_auth_fail(auth,
4466 			      "Missing or invalid Enrollee Nonce attribute");
4467 		goto fail;
4468 	}
4469 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
4470 	os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
4471 
4472 	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
4473 				   DPP_ATTR_CONFIG_ATTR_OBJ,
4474 				   &config_attr_len);
4475 	if (!config_attr) {
4476 		dpp_auth_fail(auth,
4477 			      "Missing or invalid Config Attributes attribute");
4478 		goto fail;
4479 	}
4480 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
4481 			  (u8 *)config_attr, config_attr_len);
4482 
4483 	root = json_parse((const char *) config_attr, config_attr_len);
4484 	if (!root) {
4485 		dpp_auth_fail(auth, "Could not parse Config Attributes");
4486 		goto fail;
4487 	}
4488 
4489 	token = json_get_member(root, "name");
4490 	if (!token || token->type != JSON_STRING) {
4491 		dpp_auth_fail(auth, "No Config Attributes - name");
4492 		goto fail;
4493 	}
4494 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
4495 
4496 	token = json_get_member(root, "wi-fi_tech");
4497 	if (!token || token->type != JSON_STRING) {
4498 		dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
4499 		goto fail;
4500 	}
4501 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
4502 	if (os_strcmp(token->string, "infra") != 0) {
4503 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
4504 			   token->string);
4505 		dpp_auth_fail(auth, "Unsupported wi-fi_tech");
4506 		goto fail;
4507 	}
4508 
4509 	token = json_get_member(root, "netRole");
4510 	if (!token || token->type != JSON_STRING) {
4511 		dpp_auth_fail(auth, "No Config Attributes - netRole");
4512 		goto fail;
4513 	}
4514 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
4515 	if (os_strcmp(token->string, "sta") == 0) {
4516 		netrole = DPP_NETROLE_STA;
4517 	} else if (os_strcmp(token->string, "ap") == 0) {
4518 		netrole = DPP_NETROLE_AP;
4519 	} else if (os_strcmp(token->string, "configurator") == 0) {
4520 		netrole = DPP_NETROLE_CONFIGURATOR;
4521 	} else {
4522 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
4523 			   token->string);
4524 		dpp_auth_fail(auth, "Unsupported netRole");
4525 		goto fail;
4526 	}
4527 
4528 	token = json_get_member(root, "mudurl");
4529 	if (token && token->type == JSON_STRING)
4530 		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
4531 
4532 	token = json_get_member(root, "bandSupport");
4533 	if (token && token->type == JSON_ARRAY) {
4534 		wpa_printf(MSG_DEBUG, "DPP: bandSupport");
4535 		token = token->child;
4536 		while (token) {
4537 			if (token->type != JSON_NUMBER)
4538 				wpa_printf(MSG_DEBUG,
4539 					   "DPP: Invalid bandSupport array member type");
4540 			else
4541 				wpa_printf(MSG_DEBUG,
4542 					   "DPP: Supported global operating class: %d",
4543 					   token->number);
4544 			token = token->sibling;
4545 		}
4546 	}
4547 
4548 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole);
4549 fail:
4550 	json_free(root);
4551 	os_free(unwrapped);
4552 	return resp;
4553 }
4554 
4555 
4556 static struct wpabuf *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params * curve,const u8 * prot_hdr,u16 prot_hdr_len)4557 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
4558 		       const u8 *prot_hdr, u16 prot_hdr_len)
4559 {
4560 	struct json_token *root, *token;
4561 	struct wpabuf *kid = NULL;
4562 
4563 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
4564 	if (!root) {
4565 		wpa_printf(MSG_DEBUG,
4566 			   "DPP: JSON parsing failed for JWS Protected Header");
4567 		goto fail;
4568 	}
4569 
4570 	if (root->type != JSON_OBJECT) {
4571 		wpa_printf(MSG_DEBUG,
4572 			   "DPP: JWS Protected Header root is not an object");
4573 		goto fail;
4574 	}
4575 
4576 	token = json_get_member(root, "typ");
4577 	if (!token || token->type != JSON_STRING) {
4578 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
4579 		goto fail;
4580 	}
4581 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
4582 		   token->string);
4583 	if (os_strcmp(token->string, "dppCon") != 0) {
4584 		wpa_printf(MSG_DEBUG,
4585 			   "DPP: Unsupported JWS Protected Header typ=%s",
4586 			   token->string);
4587 		goto fail;
4588 	}
4589 
4590 	token = json_get_member(root, "alg");
4591 	if (!token || token->type != JSON_STRING) {
4592 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
4593 		goto fail;
4594 	}
4595 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
4596 		   token->string);
4597 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
4598 		wpa_printf(MSG_DEBUG,
4599 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
4600 			   token->string, curve->jws_alg);
4601 		goto fail;
4602 	}
4603 
4604 	kid = json_get_member_base64url(root, "kid");
4605 	if (!kid) {
4606 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
4607 		goto fail;
4608 	}
4609 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
4610 			kid);
4611 
4612 fail:
4613 	json_free(root);
4614 	return kid;
4615 }
4616 
4617 
dpp_parse_cred_legacy(struct dpp_config_obj * conf,struct json_token * cred)4618 static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
4619 				 struct json_token *cred)
4620 {
4621 	struct json_token *pass, *psk_hex;
4622 
4623 	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
4624 
4625 	pass = json_get_member(cred, "pass");
4626 	psk_hex = json_get_member(cred, "psk_hex");
4627 
4628 	if (pass && pass->type == JSON_STRING) {
4629 		size_t len = os_strlen(pass->string);
4630 
4631 		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
4632 				      (u8 *)pass->string, len);
4633 		if (len < 8 || len > 63)
4634 			return -1;
4635 		os_strlcpy(conf->passphrase, pass->string,
4636 			   sizeof(conf->passphrase));
4637 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
4638 		if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
4639 			wpa_printf(MSG_DEBUG,
4640 				   "DPP: Unexpected psk_hex with akm=sae");
4641 			return -1;
4642 		}
4643 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
4644 		    hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) {
4645 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
4646 			return -1;
4647 		}
4648 		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
4649 				conf->psk, PMK_LEN);
4650 		conf->psk_set = 1;
4651 	} else {
4652 		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
4653 		return -1;
4654 	}
4655 
4656 	if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) {
4657 		wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
4658 		return -1;
4659 	}
4660 
4661 	return 0;
4662 }
4663 
4664 
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)4665 static struct crypto_key * dpp_parse_jwk(struct json_token *jwk,
4666 				const struct dpp_curve_params **key_curve)
4667 {
4668 	struct json_token *token;
4669 	const struct dpp_curve_params *curve;
4670 	struct wpabuf *x = NULL, *y = NULL, *a = NULL;
4671 	struct crypto_ec_group *group;
4672 	struct crypto_key *pkey = NULL;
4673 	size_t len;
4674 
4675 	token = json_get_member(jwk, "kty");
4676 	if (!token || token->type != JSON_STRING) {
4677 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
4678 		goto fail;
4679 	}
4680 	if (os_strcmp(token->string, "EC") != 0) {
4681 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
4682 			   token->string);
4683 		goto fail;
4684 	}
4685 
4686 	token = json_get_member(jwk, "crv");
4687 	if (!token || token->type != JSON_STRING) {
4688 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
4689 		goto fail;
4690 	}
4691 	curve = dpp_get_curve_jwk_crv(token->string);
4692 	if (!curve) {
4693 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
4694 			   token->string);
4695 		goto fail;
4696 	}
4697 
4698 	x = json_get_member_base64url(jwk, "x");
4699 	if (!x) {
4700 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
4701 		goto fail;
4702 	}
4703 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
4704 	if (wpabuf_len(x) != curve->prime_len) {
4705 		wpa_printf(MSG_DEBUG,
4706 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
4707 			   (unsigned int) wpabuf_len(x),
4708 			   (unsigned int) curve->prime_len, curve->name);
4709 		goto fail;
4710 	}
4711 
4712 	y = json_get_member_base64url(jwk, "y");
4713 	if (!y) {
4714 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
4715 		goto fail;
4716 	}
4717 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
4718 	if (wpabuf_len(y) != curve->prime_len) {
4719 		wpa_printf(MSG_DEBUG,
4720 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
4721 			   (unsigned int) wpabuf_len(y),
4722 			   (unsigned int) curve->prime_len, curve->name);
4723 		goto fail;
4724 	}
4725 
4726 	group = crypto_ec_get_group_byname(curve->name);
4727 	if (!group) {
4728 		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
4729 		goto fail;
4730 	}
4731 
4732 	len = wpabuf_len(x);
4733 	a = wpabuf_concat(x, y);
4734 	pkey = crypto_ec_set_pubkey_point(group, wpabuf_head(a),
4735 					  len);
4736 	crypto_ec_deinit((struct crypto_ec *)group);
4737 	*key_curve = curve;
4738 
4739 fail:
4740 	wpabuf_free(a);
4741 	wpabuf_free(x);
4742 	wpabuf_free(y);
4743 
4744 	return pkey;
4745 }
4746 
4747 
dpp_key_expired(const char * timestamp,os_time_t * expiry)4748 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
4749 {
4750 	struct os_time now;
4751 	unsigned int year, month, day, hour, min, sec;
4752 	os_time_t utime;
4753 	const char *pos;
4754 
4755 	/* ISO 8601 date and time:
4756 	 * <date>T<time>
4757 	 * YYYY-MM-DDTHH:MM:SSZ
4758 	 * YYYY-MM-DDTHH:MM:SS+03:00
4759 	 */
4760 	if (os_strlen(timestamp) < 19) {
4761 		wpa_printf(MSG_DEBUG,
4762 			   "DPP: Too short timestamp - assume expired key");
4763 		return 1;
4764 	}
4765 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
4766 		   &year, &month, &day, &hour, &min, &sec) != 6) {
4767 		wpa_printf(MSG_DEBUG,
4768 			   "DPP: Failed to parse expiration day - assume expired key");
4769 		return 1;
4770 	}
4771 
4772 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
4773 		wpa_printf(MSG_DEBUG,
4774 			   "DPP: Invalid date/time information - assume expired key");
4775 		return 1;
4776 	}
4777 
4778 	pos = timestamp + 19;
4779 	if (*pos == 'Z' || *pos == '\0') {
4780 		/* In UTC - no need to adjust */
4781 	} else if (*pos == '-' || *pos == '+') {
4782 		int items;
4783 
4784 		/* Adjust local time to UTC */
4785 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
4786 		if (items < 1) {
4787 			wpa_printf(MSG_DEBUG,
4788 				   "DPP: Invalid time zone designator (%s) - assume expired key",
4789 				   pos);
4790 			return 1;
4791 		}
4792 		if (*pos == '-')
4793 			utime += 3600 * hour;
4794 		if (*pos == '+')
4795 			utime -= 3600 * hour;
4796 		if (items > 1) {
4797 			if (*pos == '-')
4798 				utime += 60 * min;
4799 			if (*pos == '+')
4800 				utime -= 60 * min;
4801 		}
4802 	} else {
4803 		wpa_printf(MSG_DEBUG,
4804 			   "DPP: Invalid time zone designator (%s) - assume expired key",
4805 			   pos);
4806 		return 1;
4807 	}
4808 	if (expiry)
4809 		*expiry = utime;
4810 
4811 	if (os_get_time(&now) < 0) {
4812 		wpa_printf(MSG_DEBUG,
4813 			   "DPP: Cannot get current time - assume expired key");
4814 		return 1;
4815 	}
4816 
4817 	if (now.sec > utime) {
4818 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
4819 			   utime, now.sec);
4820 		return 1;
4821 	}
4822 
4823 	return 0;
4824 }
4825 
4826 
dpp_parse_connector(struct dpp_authentication * auth,struct dpp_config_obj * conf,const unsigned char * payload,u16 payload_len)4827 static int dpp_parse_connector(struct dpp_authentication *auth,
4828 			       struct dpp_config_obj *conf,
4829 			       const unsigned char *payload,
4830 			       u16 payload_len)
4831 {
4832 	struct json_token *root, *groups, *netkey, *token;
4833 	int ret = -1;
4834 	struct crypto_key *key = NULL;
4835 	const struct dpp_curve_params *curve;
4836 	unsigned int rules = 0;
4837 
4838 	root = json_parse((const char *) payload, payload_len);
4839 	if (!root) {
4840 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4841 		goto fail;
4842 	}
4843 
4844 	groups = json_get_member(root, "groups");
4845 	if (!groups || groups->type != JSON_ARRAY) {
4846 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
4847 		goto skip_groups;
4848 	}
4849 	for (token = groups->child; token; token = token->sibling) {
4850 		struct json_token *id, *role;
4851 
4852 		id = json_get_member(token, "groupId");
4853 		if (!id || id->type != JSON_STRING) {
4854 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
4855 			goto fail;
4856 		}
4857 
4858 		role = json_get_member(token, "netRole");
4859 		if (!role || role->type != JSON_STRING) {
4860 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
4861 			goto fail;
4862 		}
4863 		wpa_printf(MSG_DEBUG,
4864 			   "DPP: connector group: groupId='%s' netRole='%s'",
4865 			   id->string, role->string);
4866 		rules++;
4867 	}
4868 skip_groups:
4869 
4870 	if (!rules) {
4871 		wpa_printf(MSG_DEBUG,
4872 			   "DPP: Connector includes no groups");
4873 		goto fail;
4874 	}
4875 
4876 	token = json_get_member(root, "expiry");
4877 	if (!token || token->type != JSON_STRING) {
4878 		wpa_printf(MSG_DEBUG,
4879 			   "DPP: No expiry string found - connector does not expire");
4880 	} else {
4881 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4882 		if (dpp_key_expired(token->string,
4883 				    &auth->net_access_key_expiry)) {
4884 			wpa_printf(MSG_DEBUG,
4885 				   "DPP: Connector (netAccessKey) has expired");
4886 			goto fail;
4887 		}
4888 	}
4889 
4890 	netkey = json_get_member(root, "netAccessKey");
4891 	if (!netkey || netkey->type != JSON_OBJECT) {
4892 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4893 		goto fail;
4894 	}
4895 
4896 	key = dpp_parse_jwk(netkey, &curve);
4897 	if (!key)
4898 		goto fail;
4899 	dpp_debug_print_key("DPP: Received netAccessKey", key);
4900 
4901 	if (crypto_key_compare(key, auth->own_protocol_key) != 1) {
4902 		wpa_printf(MSG_DEBUG,
4903 			   "DPP: netAccessKey in connector does not match own protocol key");
4904 #ifdef CONFIG_WPA_TESTING_OPTIONS
4905 		if (auth->ignore_netaccesskey_mismatch) {
4906 			wpa_printf(MSG_DEBUG,
4907 				   "DPP: TESTING - skip netAccessKey mismatch");
4908 		} else {
4909 			goto fail;
4910 		}
4911 #else /* CONFIG_WPA_TESTING_OPTIONS */
4912 		goto fail;
4913 #endif /* CONFIG_WPA_TESTING_OPTIONS */
4914 	}
4915 
4916 	ret = 0;
4917 fail:
4918 	crypto_ec_free_key(key);
4919 	json_free(root);
4920 	return ret;
4921 }
4922 
dpp_check_pubkey_match(struct crypto_key * pub,struct wpabuf * r_hash)4923 static int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash)
4924 {
4925 	struct wpabuf *uncomp;
4926 	int res;
4927 	u8 hash[SHA256_MAC_LEN];
4928 	const u8 *addr[1];
4929 	size_t len[1];
4930 
4931 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
4932 		return -1;
4933 	uncomp = dpp_get_pubkey_point(pub, 1);
4934 	if (!uncomp)
4935 		return -1;
4936 	addr[0] = wpabuf_head(uncomp);
4937 	len[0] = wpabuf_len(uncomp);
4938 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
4939 		    addr[0], len[0]);
4940 	res = sha256_vector(1, addr, len, hash);
4941 	wpabuf_free(uncomp);
4942 	if (res < 0)
4943 		return -1;
4944 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
4945 		wpa_printf(MSG_DEBUG,
4946 			   "DPP: Received hash value does not match calculated public key hash value");
4947 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
4948 			    hash, SHA256_MAC_LEN);
4949 		return -1;
4950 	}
4951 	return 0;
4952 }
4953 
4954 
dpp_copy_csign(struct dpp_config_obj * conf,struct crypto_key * csign)4955 static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_key *csign)
4956 {
4957 	unsigned char *der = NULL;
4958 	int der_len;
4959 
4960 	der_len = crypto_write_pubkey_der(csign, &der);
4961 	if (der_len <= 0)
4962 		return;
4963 	wpabuf_free(conf->c_sign_key);
4964 	conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
4965 	crypto_free_buffer(der);
4966 }
4967 
dpp_copy_netaccesskey(struct dpp_authentication * auth,struct dpp_config_obj * conf)4968 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
4969 				  struct dpp_config_obj *conf)
4970 {
4971 	unsigned char *der = NULL;
4972 	int der_len;
4973 
4974 	if (crypto_ec_get_priv_key_der(auth->own_protocol_key, &der, &der_len) < 0)
4975 		return;
4976 	wpabuf_free(auth->net_access_key);
4977 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
4978 	crypto_free_buffer(der);
4979 }
4980 
4981 struct dpp_signed_connector_info {
4982 	unsigned char *payload;
4983 	size_t payload_len;
4984 };
4985 
4986 static enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_key * csign_pub,const char * connector)4987 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
4988 			     struct crypto_key *csign_pub, const char *connector)
4989 {
4990 	enum dpp_status_error ret = 255;
4991 	const char *pos, *end, *signed_start, *signed_end;
4992 	struct wpabuf *kid = NULL;
4993 	unsigned char *prot_hdr = NULL, *signature = NULL;
4994 	size_t prot_hdr_len = 0, signature_len = 0;
4995 	struct crypto_bignum *r = NULL, *s = NULL;
4996 	const struct dpp_curve_params *curve;
4997 	const struct crypto_ec_group *group;
4998 	int id;
4999 
5000 	group = crypto_ec_get_group_from_key(csign_pub);
5001 	if (!group)
5002 		goto fail;
5003 	id = crypto_ec_get_curve_id(group);
5004 	curve = dpp_get_curve_group_id(id);
5005 	if (!curve)
5006 		goto fail;
5007 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
5008 	os_memset(info, 0, sizeof(*info));
5009 
5010 	signed_start = pos = connector;
5011 	end = os_strchr(pos, '.');
5012 	if (!end) {
5013 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
5014 		ret = DPP_STATUS_INVALID_CONNECTOR;
5015 		goto fail;
5016 	}
5017 	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
5018 	if (!prot_hdr) {
5019 		wpa_printf(MSG_DEBUG,
5020 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
5021 		ret = DPP_STATUS_INVALID_CONNECTOR;
5022 		goto fail;
5023 	}
5024 	wpa_hexdump_ascii(MSG_DEBUG,
5025 			  "DPP: signedConnector - JWS Protected Header",
5026 			  (u8 *)prot_hdr, prot_hdr_len);
5027 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len);
5028 	if (!kid) {
5029 		ret = DPP_STATUS_INVALID_CONNECTOR;
5030 		goto fail;
5031 	}
5032 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
5033 		wpa_printf(MSG_DEBUG,
5034 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
5035 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
5036 		ret = DPP_STATUS_INVALID_CONNECTOR;
5037 		goto fail;
5038 	}
5039 
5040 	pos = end + 1;
5041 	end = os_strchr(pos, '.');
5042 	if (!end) {
5043 		wpa_printf(MSG_DEBUG,
5044 			   "DPP: Missing dot(2) in signedConnector");
5045 		ret = DPP_STATUS_INVALID_CONNECTOR;
5046 		goto fail;
5047 	}
5048 	signed_end = end - 1;
5049 	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
5050 	if (!info->payload) {
5051 		wpa_printf(MSG_DEBUG,
5052 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
5053 		ret = DPP_STATUS_INVALID_CONNECTOR;
5054 		goto fail;
5055 	}
5056 	wpa_hexdump_ascii(MSG_DEBUG,
5057 			  "DPP: signedConnector - JWS Payload",
5058 			  (u8 *)info->payload, info->payload_len);
5059 	pos = end + 1;
5060 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5061 	if (!signature) {
5062 		wpa_printf(MSG_DEBUG,
5063 				"DPP: Failed to base64url decode signedConnector signature");
5064 		ret = DPP_STATUS_INVALID_CONNECTOR;
5065 		goto fail;
5066 	}
5067 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
5068 		    signature, signature_len);
5069 
5070 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
5071 		ret = DPP_STATUS_NO_MATCH;
5072 		goto fail;
5073 	}
5074 
5075 	if (signature_len & 0x01) {
5076 		wpa_printf(MSG_DEBUG,
5077 			   "DPP: Unexpected signedConnector signature length (%d)",
5078 			   (int) signature_len);
5079 		ret = DPP_STATUS_INVALID_CONNECTOR;
5080 		goto fail;
5081 	}
5082 
5083 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
5084 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
5085 	r = crypto_bignum_init_set(signature, signature_len / 2);
5086 	s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2);
5087 
5088 	if (!crypto_edcsa_sign_verify((unsigned char *)signed_start, r, s,
5089 				csign_pub, signed_end - signed_start + 1)) {
5090 		goto fail;
5091 	}
5092 
5093 	ret = DPP_STATUS_OK;
5094 fail:
5095 	os_free(prot_hdr);
5096 	wpabuf_free(kid);
5097 	os_free(signature);
5098 	crypto_bignum_deinit(r, 0);
5099 	crypto_bignum_deinit(s, 0);
5100 	return ret;
5101 }
5102 
5103 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)5104 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
5105 			      struct dpp_config_obj *conf,
5106 			      struct json_token *cred)
5107 {
5108 	struct dpp_signed_connector_info info;
5109 	struct json_token *token, *csign;
5110 	int ret = -1;
5111 	struct crypto_key *csign_pub = NULL;
5112 	const struct dpp_curve_params *key_curve = NULL;
5113 	const char *signed_connector;
5114 
5115 	os_memset(&info, 0, sizeof(info));
5116 
5117 	if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
5118 		wpa_printf(MSG_DEBUG,
5119 			   "DPP: Legacy credential included in Connector credential");
5120 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5121 			return -1;
5122 	}
5123 
5124 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
5125 
5126 	csign = json_get_member(cred, "csign");
5127 	if (!csign || csign->type != JSON_OBJECT) {
5128 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
5129 		goto fail;
5130 	}
5131 
5132 	csign_pub = dpp_parse_jwk(csign, &key_curve);
5133 	if (!csign_pub) {
5134 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
5135 		goto fail;
5136 	}
5137 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
5138 
5139 	token = json_get_member(cred, "signedConnector");
5140 	if (!token || token->type != JSON_STRING) {
5141 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
5142 		goto fail;
5143 	}
5144 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
5145 			  (u8 *)token->string, os_strlen(token->string));
5146 	signed_connector = token->string;
5147 
5148 	if (os_strchr(signed_connector, '"') ||
5149 	    os_strchr(signed_connector, '\n')) {
5150 		wpa_printf(MSG_DEBUG,
5151 			   "DPP: Unexpected character in signedConnector");
5152 		goto fail;
5153 	}
5154 
5155 	if (dpp_process_signed_connector(&info, csign_pub,
5156 					 signed_connector) != DPP_STATUS_OK)
5157 		goto fail;
5158 
5159 	if (dpp_parse_connector(auth, conf,
5160 				info.payload, info.payload_len) < 0) {
5161 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
5162 		goto fail;
5163 	}
5164 
5165 	os_free(conf->connector);
5166 	conf->connector = os_strdup(signed_connector);
5167 
5168 	dpp_copy_csign(conf, csign_pub);
5169 	dpp_copy_netaccesskey(auth, conf);
5170 
5171 	ret = 0;
5172 fail:
5173 	crypto_ec_free_key(csign_pub);
5174 	os_free(info.payload);
5175 	return ret;
5176 }
5177 
5178 
dpp_akm_str(enum dpp_akm akm)5179 const char * dpp_akm_str(enum dpp_akm akm)
5180 {
5181 	switch (akm) {
5182 	case DPP_AKM_DPP:
5183 		return "dpp";
5184 	case DPP_AKM_PSK:
5185 		return "psk";
5186 	case DPP_AKM_SAE:
5187 		return "sae";
5188 	case DPP_AKM_PSK_SAE:
5189 		return "psk+sae";
5190 	case DPP_AKM_SAE_DPP:
5191 		return "dpp+sae";
5192 	case DPP_AKM_PSK_SAE_DPP:
5193 		return "dpp+psk+sae";
5194 	default:
5195 		return "??";
5196 	}
5197 }
5198 
5199 
dpp_akm_selector_str(enum dpp_akm akm)5200 const char * dpp_akm_selector_str(enum dpp_akm akm)
5201 {
5202 	switch (akm) {
5203 	case DPP_AKM_DPP:
5204 		return "506F9A02";
5205 	case DPP_AKM_PSK:
5206 		return "000FAC02+000FAC06";
5207 	case DPP_AKM_SAE:
5208 		return "000FAC08";
5209 	case DPP_AKM_PSK_SAE:
5210 		return "000FAC02+000FAC06+000FAC08";
5211 	case DPP_AKM_SAE_DPP:
5212 		return "506F9A02+000FAC08";
5213 	case DPP_AKM_PSK_SAE_DPP:
5214 		return "506F9A02+000FAC08+000FAC02+000FAC06";
5215 	default:
5216 		return "??";
5217 	}
5218 }
5219 
5220 
dpp_akm_from_str(const char * akm)5221 static enum dpp_akm dpp_akm_from_str(const char *akm)
5222 {
5223 	const char *pos;
5224 	int dpp = 0, psk = 0, sae = 0;
5225 
5226 	if (os_strcmp(akm, "psk") == 0)
5227 		return DPP_AKM_PSK;
5228 	if (os_strcmp(akm, "sae") == 0)
5229 		return DPP_AKM_SAE;
5230 	if (os_strcmp(akm, "psk+sae") == 0)
5231 		return DPP_AKM_PSK_SAE;
5232 	if (os_strcmp(akm, "dpp") == 0)
5233 		return DPP_AKM_DPP;
5234 	if (os_strcmp(akm, "dpp+sae") == 0)
5235 		return DPP_AKM_SAE_DPP;
5236 	if (os_strcmp(akm, "dpp+psk+sae") == 0)
5237 		return DPP_AKM_PSK_SAE_DPP;
5238 
5239 	pos = akm;
5240 	while (*pos) {
5241 		if (os_strlen(pos) < 8)
5242 			break;
5243 		if (os_strncasecmp(pos, "506F9A02", 8) == 0)
5244 			dpp = 1;
5245 		else if (os_strncasecmp(pos, "000FAC02", 8) == 0)
5246 			psk = 1;
5247 		else if (os_strncasecmp(pos, "000FAC06", 8) == 0)
5248 			psk = 1;
5249 		else if (os_strncasecmp(pos, "000FAC08", 8) == 0)
5250 			sae = 1;
5251 		pos += 8;
5252 		if (*pos != '+')
5253 			break;
5254 		pos++;
5255 	}
5256 
5257 	if (dpp && psk && sae)
5258 		return DPP_AKM_PSK_SAE_DPP;
5259 	if (dpp && sae)
5260 		return DPP_AKM_SAE_DPP;
5261 	if (dpp)
5262 		return DPP_AKM_DPP;
5263 	if (psk && sae)
5264 		return DPP_AKM_PSK_SAE;
5265 	if (sae)
5266 		return DPP_AKM_SAE;
5267 	if (psk)
5268 		return DPP_AKM_PSK;
5269 
5270 	return DPP_AKM_UNKNOWN;
5271 }
5272 
5273 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)5274 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
5275 			      const u8 *conf_obj, u16 conf_obj_len)
5276 {
5277 	int ret = -1;
5278 	struct json_token *root, *token, *discovery, *cred;
5279 	struct dpp_config_obj *conf;
5280 	struct wpabuf *ssid64 = NULL;
5281 
5282 	root = json_parse((const char *) conf_obj, conf_obj_len);
5283 	if (!root)
5284 		return -1;
5285 	if (root->type != JSON_OBJECT) {
5286 		dpp_auth_fail(auth, "JSON root is not an object");
5287 		goto fail;
5288 	}
5289 
5290 	token = json_get_member(root, "wi-fi_tech");
5291 	if (!token || token->type != JSON_STRING) {
5292 		dpp_auth_fail(auth, "No wi-fi_tech string value found");
5293 		goto fail;
5294 	}
5295 	if (os_strcmp(token->string, "infra") != 0) {
5296 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
5297 			   token->string);
5298 		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
5299 		goto fail;
5300 	}
5301 
5302 	discovery = json_get_member(root, "discovery");
5303 	if (!discovery || discovery->type != JSON_OBJECT) {
5304 		dpp_auth_fail(auth, "No discovery object in JSON");
5305 		goto fail;
5306 	}
5307 
5308 	ssid64 = json_get_member_base64url(discovery, "ssid64");
5309 	if (ssid64) {
5310 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
5311 				  (u8 *)wpabuf_head(ssid64), wpabuf_len(ssid64));
5312 		if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
5313 			dpp_auth_fail(auth, "Too long discovery::ssid64 value");
5314 			goto fail;
5315 		}
5316 	} else {
5317 		token = json_get_member(discovery, "ssid");
5318 		if (!token || token->type != JSON_STRING) {
5319 			dpp_auth_fail(auth,
5320 				      "No discovery::ssid string value found");
5321 			goto fail;
5322 		}
5323 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
5324 				  (u8 *)token->string, os_strlen(token->string));
5325 		if (os_strlen(token->string) > SSID_MAX_LEN) {
5326 			dpp_auth_fail(auth,
5327 				      "Too long discovery::ssid string value");
5328 			goto fail;
5329 		}
5330 	}
5331 
5332 	if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
5333 		wpa_printf(MSG_DEBUG,
5334 			   "DPP: No room for this many Config Objects - ignore this one");
5335 		ret = 0;
5336 		goto fail;
5337 	}
5338 	conf = &auth->conf_obj[auth->num_conf_obj++];
5339 
5340 	if (ssid64) {
5341 		conf->ssid_len = wpabuf_len(ssid64);
5342 		os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
5343 	} else {
5344 		conf->ssid_len = os_strlen(token->string);
5345 		os_memcpy(conf->ssid, token->string, conf->ssid_len);
5346 	}
5347 
5348 	token = json_get_member(discovery, "ssid_charset");
5349 	if (token && token->type == JSON_NUMBER) {
5350 		conf->ssid_charset = token->number;
5351 		wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
5352 			   conf->ssid_charset);
5353 	}
5354 
5355 	cred = json_get_member(root, "cred");
5356 	if (!cred || cred->type != JSON_OBJECT) {
5357 		dpp_auth_fail(auth, "No cred object in JSON");
5358 		goto fail;
5359 	}
5360 
5361 	token = json_get_member(cred, "akm");
5362 	if (!token || token->type != JSON_STRING) {
5363 		dpp_auth_fail(auth, "No cred::akm string value found");
5364 		goto fail;
5365 	}
5366 	conf->akm = dpp_akm_from_str(token->string);
5367 
5368 	if (dpp_akm_legacy(conf->akm)) {
5369 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5370 			goto fail;
5371 	} else if (dpp_akm_dpp(conf->akm)) {
5372 		if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
5373 			goto fail;
5374 	} else {
5375 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
5376 			   token->string);
5377 		dpp_auth_fail(auth, "Unsupported akm");
5378 		goto fail;
5379 	}
5380 
5381 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
5382 	ret = 0;
5383 fail:
5384 	wpabuf_free(ssid64);
5385 	json_free(root);
5386 	return ret;
5387 }
5388 
5389 
dpp_conf_resp_rx(struct dpp_authentication * auth,const uint8_t * resp,uint32_t resp_len)5390 int dpp_conf_resp_rx(struct dpp_authentication *auth,
5391                      const uint8_t *resp, uint32_t resp_len)
5392 {
5393 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
5394 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
5395 	const u8 *addr[1];
5396 	size_t len[1];
5397 	u8 *unwrapped = NULL;
5398 	size_t unwrapped_len = 0;
5399 	int ret = -1;
5400 
5401 	auth->conf_resp_status = 255;
5402 
5403 	if (dpp_check_attrs(resp, resp_len) < 0) {
5404 		dpp_auth_fail(auth, "Invalid attribute in config response");
5405 		return -1;
5406 	}
5407 
5408 	wrapped_data = dpp_get_attr(resp, resp_len,
5409 				    DPP_ATTR_WRAPPED_DATA,
5410 				    &wrapped_data_len);
5411 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5412 		dpp_auth_fail(auth,
5413 			      "Missing or invalid required Wrapped Data attribute");
5414 		return -1;
5415 	}
5416 
5417 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5418 		    wrapped_data, wrapped_data_len);
5419 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5420 	unwrapped = os_malloc(unwrapped_len);
5421 	if (!unwrapped)
5422 		return -1;
5423 
5424 	addr[0] = resp;
5425 	len[0] = wrapped_data - 4 - resp;
5426 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
5427 
5428 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5429 			    wrapped_data, wrapped_data_len,
5430 			    1, addr, len, unwrapped) < 0) {
5431 		dpp_auth_fail(auth, "AES-SIV decryption failed");
5432 		goto fail;
5433 	}
5434 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5435 		    unwrapped, unwrapped_len);
5436 
5437 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5438 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5439 		goto fail;
5440 	}
5441 
5442 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5443 			       DPP_ATTR_ENROLLEE_NONCE,
5444 			       &e_nonce_len);
5445 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5446 		dpp_auth_fail(auth,
5447 			      "Missing or invalid Enrollee Nonce attribute");
5448 		goto fail;
5449 	}
5450 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5451 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
5452 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
5453 		goto fail;
5454 	}
5455 
5456 	status = dpp_get_attr(resp, resp_len,
5457 			      DPP_ATTR_STATUS, &status_len);
5458 	if (!status || status_len < 1) {
5459 		dpp_auth_fail(auth,
5460 			      "Missing or invalid required DPP Status attribute");
5461 		goto fail;
5462 	}
5463 	auth->conf_resp_status = status[0];
5464 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
5465 	if (status[0] != DPP_STATUS_OK) {
5466 		dpp_auth_fail(auth, "Configurator rejected configuration");
5467 		goto fail;
5468 	}
5469 
5470 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
5471 				&conf_obj_len);
5472 	if (!conf_obj) {
5473 		dpp_auth_fail(auth,
5474 			      "Missing required Configuration Object attribute");
5475 		goto fail;
5476 	}
5477 	while (conf_obj) {
5478 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
5479 				  (u8 *)conf_obj, conf_obj_len);
5480 		if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
5481 			goto fail;
5482 		conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
5483 					     DPP_ATTR_CONFIG_OBJ,
5484 					     &conf_obj_len);
5485 	}
5486 
5487 	ret = 0;
5488 
5489 fail:
5490 	os_free(unwrapped);
5491 	return ret;
5492 }
5493 
dpp_configurator_free(struct dpp_configurator * conf)5494 void dpp_configurator_free(struct dpp_configurator *conf)
5495 {
5496 	if (!conf)
5497 		return;
5498 	crypto_ec_free_key(conf->csign);
5499 	os_free(conf->kid);
5500 	os_free(conf);
5501 }
5502 
5503 
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)5504 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
5505 			     size_t buflen)
5506 {
5507 	int keylen, ret = -1;
5508 	unsigned char *key = NULL;
5509 
5510 	if (!conf->csign)
5511 		return ret;
5512 
5513 	crypto_ec_get_priv_key_der(conf->csign, &key, &keylen);
5514 
5515 	if (keylen > 0)
5516 		ret = wpa_snprintf_hex(buf, buflen, key, keylen);
5517 
5518 	crypto_free_buffer(key);
5519 
5520 	return ret;
5521 }
5522 
5523 
5524 struct dpp_configurator *
dpp_keygen_configurator(const char * curve,u8 * privkey,size_t privkey_len)5525 dpp_keygen_configurator(const char *curve, u8 *privkey,
5526 			size_t privkey_len)
5527 {
5528 	struct dpp_configurator *conf;
5529 	struct wpabuf *csign_pub = NULL;
5530 	u8 kid_hash[SHA256_MAC_LEN];
5531 	const u8 *addr[1];
5532 	size_t len[1];
5533 
5534 	conf = os_zalloc(sizeof(*conf));
5535 	if (!conf)
5536 		return NULL;
5537 
5538 	if (!curve) {
5539 		conf->curve = &dpp_curves[0];
5540 	} else {
5541 		conf->curve = dpp_get_curve_name(curve);
5542 		if (!conf->curve) {
5543 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5544 				   curve);
5545 			os_free(conf);
5546 			return NULL;
5547 		}
5548 	}
5549 	if (privkey)
5550 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
5551 					      privkey_len);
5552 	else
5553 		conf->csign = dpp_gen_keypair(conf->curve);
5554 	if (!conf->csign)
5555 		goto fail;
5556 	conf->own = 1;
5557 
5558 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
5559 	if (!csign_pub) {
5560 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
5561 		goto fail;
5562 	}
5563 
5564 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
5565 	addr[0] = wpabuf_head(csign_pub);
5566 	len[0] = wpabuf_len(csign_pub);
5567 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
5568 		wpa_printf(MSG_DEBUG,
5569 			   "DPP: Failed to derive kid for C-sign-key");
5570 		goto fail;
5571 	}
5572 
5573 	conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
5574 	if (!conf->kid)
5575 		goto fail;
5576 out:
5577 	wpabuf_free(csign_pub);
5578 	return conf;
5579 fail:
5580 	dpp_configurator_free(conf);
5581 	conf = NULL;
5582 	goto out;
5583 }
5584 
5585 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)5586 int dpp_configurator_own_config(struct dpp_authentication *auth,
5587 				const char *curve, int ap)
5588 {
5589 	struct wpabuf *conf_obj;
5590 	int ret = -1;
5591 
5592 	if (!auth->conf) {
5593 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
5594 		return -1;
5595 	}
5596 
5597 	if (!curve) {
5598 		auth->curve = &dpp_curves[0];
5599 	} else {
5600 		auth->curve = dpp_get_curve_name(curve);
5601 		if (!auth->curve) {
5602 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5603 				   curve);
5604 			return -1;
5605 		}
5606 	}
5607 	wpa_printf(MSG_DEBUG,
5608 		   "DPP: Building own configuration/connector with curve %s",
5609 		   auth->curve->name);
5610 
5611 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
5612 	if (!auth->own_protocol_key)
5613 		return -1;
5614 	dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
5615 	auth->peer_protocol_key = auth->own_protocol_key;
5616 	dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
5617 
5618 	conf_obj = dpp_build_conf_obj(auth, ap, 0);
5619 	if (!conf_obj) {
5620 		wpabuf_free(auth->conf_obj[0].c_sign_key);
5621 		auth->conf_obj[0].c_sign_key = NULL;
5622 		goto fail;
5623 	}
5624 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
5625 				 wpabuf_len(conf_obj));
5626 fail:
5627 	wpabuf_free(conf_obj);
5628 	auth->peer_protocol_key = NULL;
5629 	return ret;
5630 }
5631 
5632 
dpp_compatible_netrole(const char * role1,const char * role2)5633 static int dpp_compatible_netrole(const char *role1, const char *role2)
5634 {
5635 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
5636 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
5637 }
5638 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role)5639 static int dpp_connector_compatible_group(struct json_token *root,
5640 					  const char *group_id,
5641 					  const char *net_role)
5642 {
5643 	struct json_token *groups, *token;
5644 
5645 	groups = json_get_member(root, "groups");
5646 	if (!groups || groups->type != JSON_ARRAY)
5647 		return 0;
5648 
5649 	for (token = groups->child; token; token = token->sibling) {
5650 		struct json_token *id, *role;
5651 
5652 		id = json_get_member(token, "groupId");
5653 		if (!id || id->type != JSON_STRING)
5654 			continue;
5655 
5656 		role = json_get_member(token, "netRole");
5657 		if (!role || role->type != JSON_STRING)
5658 			continue;
5659 
5660 		if (os_strcmp(id->string, "*") != 0 &&
5661 		    os_strcmp(group_id, "*") != 0 &&
5662 		    os_strcmp(id->string, group_id) != 0)
5663 			continue;
5664 
5665 		if (dpp_compatible_netrole(role->string, net_role))
5666 			return 1;
5667 	}
5668 
5669 	return 0;
5670 }
5671 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root)5672 static int dpp_connector_match_groups(struct json_token *own_root,
5673 				      struct json_token *peer_root)
5674 {
5675 	struct json_token *groups, *token;
5676 
5677 	groups = json_get_member(peer_root, "groups");
5678 	if (!groups || groups->type != JSON_ARRAY) {
5679 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
5680 		return 0;
5681 	}
5682 
5683 	for (token = groups->child; token; token = token->sibling) {
5684 		struct json_token *id, *role;
5685 
5686 		id = json_get_member(token, "groupId");
5687 		if (!id || id->type != JSON_STRING) {
5688 			wpa_printf(MSG_DEBUG,
5689 				   "DPP: Missing peer groupId string");
5690 			continue;
5691 		}
5692 
5693 		role = json_get_member(token, "netRole");
5694 		if (!role || role->type != JSON_STRING) {
5695 			wpa_printf(MSG_DEBUG,
5696 				   "DPP: Missing peer groups::netRole string");
5697 			continue;
5698 		}
5699 		wpa_printf(MSG_DEBUG,
5700 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
5701 			   id->string, role->string);
5702 		if (dpp_connector_compatible_group(own_root, id->string,
5703 						   role->string)) {
5704 			wpa_printf(MSG_DEBUG,
5705 				   "DPP: Compatible group/netRole in own connector");
5706 			return 1;
5707 		}
5708 	}
5709 
5710 	return 0;
5711 }
5712 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)5713 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
5714 			  unsigned int hash_len)
5715 {
5716 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
5717 	const char *info = "DPP PMK";
5718 	int res;
5719 
5720 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5721 
5722 	/* HKDF-Extract(<>, N.x) */
5723 	os_memset(salt, 0, hash_len);
5724 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
5725 		return -1;
5726 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
5727 			prk, hash_len);
5728 
5729 	/* HKDF-Expand(PRK, info, L) */
5730 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
5731 	os_memset(prk, 0, hash_len);
5732 	if (res < 0)
5733 		return -1;
5734 
5735 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
5736 			pmk, hash_len);
5737 	return 0;
5738 }
5739 
5740 
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_key * own_key,struct crypto_key * peer_key,u8 * pmkid)5741 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
5742 			    struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid)
5743 {
5744 	struct wpabuf *nkx, *pkx;
5745 	int ret = -1, res;
5746 	const u8 *addr[2];
5747 	size_t len[2];
5748 	u8 hash[SHA256_MAC_LEN];
5749 
5750 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5751 	nkx = dpp_get_pubkey_point(own_key, 0);
5752 	pkx = dpp_get_pubkey_point(peer_key, 0);
5753 	if (!nkx || !pkx)
5754 		goto fail;
5755 	addr[0] = wpabuf_head(nkx);
5756 	len[0] = wpabuf_len(nkx) / 2;
5757 	addr[1] = wpabuf_head(pkx);
5758 	len[1] = wpabuf_len(pkx) / 2;
5759 	if (len[0] != len[1])
5760 		goto fail;
5761 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
5762 		addr[0] = wpabuf_head(pkx);
5763 		addr[1] = wpabuf_head(nkx);
5764 	}
5765 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
5766 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
5767 	res = sha256_vector(2, addr, len, hash);
5768 	if (res < 0)
5769 		goto fail;
5770 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
5771 	os_memcpy(pmkid, hash, PMKID_LEN);
5772 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
5773 	ret = 0;
5774 fail:
5775 	wpabuf_free(nkx);
5776 	wpabuf_free(pkx);
5777 	return ret;
5778 }
5779 
5780 
5781 enum dpp_status_error
dpp_peer_intro(struct dpp_introduction * intro,const char * own_connector,const u8 * net_access_key,size_t net_access_key_len,const u8 * csign_key,size_t csign_key_len,const u8 * peer_connector,size_t peer_connector_len,os_time_t * expiry)5782 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
5783 	       const u8 *net_access_key, size_t net_access_key_len,
5784 	       const u8 *csign_key, size_t csign_key_len,
5785 	       const u8 *peer_connector, size_t peer_connector_len,
5786 	       os_time_t *expiry)
5787 {
5788 	struct json_token *root = NULL, *netkey, *token;
5789 	struct json_token *own_root = NULL;
5790 	enum dpp_status_error ret = 255, res;
5791 	struct crypto_key *own_key = NULL, *peer_key = NULL;
5792 	struct wpabuf *own_key_pub = NULL;
5793 	const struct dpp_curve_params *curve, *own_curve;
5794 	struct dpp_signed_connector_info info;
5795 	const unsigned char *p;
5796 	struct crypto_key *csign = NULL;
5797 	char *signed_connector = NULL;
5798 	const char *pos, *end;
5799 	unsigned char *own_conn = NULL;
5800 	size_t own_conn_len;
5801 	size_t Nx_len;
5802 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
5803 
5804 	os_memset(intro, 0, sizeof(*intro));
5805 	os_memset(&info, 0, sizeof(info));
5806 	if (expiry)
5807 		*expiry = 0;
5808 
5809 	p = csign_key;
5810 	csign = crypto_ec_parse_subpub_key(p, csign_key_len);
5811 	if (!csign) {
5812 		wpa_printf(MSG_ERROR,
5813 			   "DPP: Failed to parse local C-sign-key information");
5814 		goto fail;
5815 	}
5816 
5817 	own_key = dpp_set_keypair(&own_curve, net_access_key,
5818 				  net_access_key_len);
5819 	if (!own_key) {
5820 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
5821 		goto fail;
5822 	}
5823 
5824 	pos = os_strchr(own_connector, '.');
5825 	if (!pos) {
5826 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
5827 		goto fail;
5828 	}
5829 	pos++;
5830 	end = os_strchr(pos, '.');
5831 	if (!end) {
5832 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
5833 		goto fail;
5834 	}
5835 	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
5836 	if (!own_conn) {
5837 		wpa_printf(MSG_DEBUG,
5838 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
5839 		goto fail;
5840 	}
5841 
5842 	own_root = json_parse((const char *) own_conn, own_conn_len);
5843 	if (!own_root) {
5844 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
5845 		goto fail;
5846 	}
5847 
5848 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
5849 			  (u8 *)peer_connector, peer_connector_len);
5850 	signed_connector = os_malloc(peer_connector_len + 1);
5851 	if (!signed_connector)
5852 		goto fail;
5853 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
5854 	signed_connector[peer_connector_len] = '\0';
5855 
5856 	res = dpp_process_signed_connector(&info, csign, signed_connector);
5857 	if (res != DPP_STATUS_OK) {
5858 		ret = res;
5859 		goto fail;
5860 	}
5861 
5862 	root = json_parse((const char *) info.payload, info.payload_len);
5863 	if (!root) {
5864 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
5865 		ret = DPP_STATUS_INVALID_CONNECTOR;
5866 		goto fail;
5867 	}
5868 
5869 	if (!dpp_connector_match_groups(own_root, root)) {
5870 		wpa_printf(MSG_DEBUG,
5871 			   "DPP: Peer connector does not include compatible group netrole with own connector");
5872 		ret = DPP_STATUS_NO_MATCH;
5873 		goto fail;
5874 	}
5875 
5876 	token = json_get_member(root, "expiry");
5877 	if (!token || token->type != JSON_STRING) {
5878 		wpa_printf(MSG_DEBUG,
5879 			   "DPP: No expiry string found - connector does not expire");
5880 	} else {
5881 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
5882 		if (dpp_key_expired(token->string, expiry)) {
5883 			wpa_printf(MSG_DEBUG,
5884 				   "DPP: Connector (netAccessKey) has expired");
5885 			ret = DPP_STATUS_INVALID_CONNECTOR;
5886 			goto fail;
5887 		}
5888 	}
5889 
5890 	netkey = json_get_member(root, "netAccessKey");
5891 	if (!netkey || netkey->type != JSON_OBJECT) {
5892 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
5893 		ret = DPP_STATUS_INVALID_CONNECTOR;
5894 		goto fail;
5895 	}
5896 
5897 	peer_key = dpp_parse_jwk(netkey, &curve);
5898 	if (!peer_key) {
5899 		ret = DPP_STATUS_INVALID_CONNECTOR;
5900 		goto fail;
5901 	}
5902 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
5903 
5904 	if (own_curve != curve) {
5905 		wpa_printf(MSG_DEBUG,
5906 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
5907 			   own_curve->name, curve->name);
5908 		ret = DPP_STATUS_INVALID_CONNECTOR;
5909 		goto fail;
5910 	}
5911 
5912 	/* ECDH: N = nk * PK */
5913 	if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
5914 		goto fail;
5915 
5916 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
5917 			Nx, Nx_len);
5918 
5919 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5920 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
5921 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
5922 		goto fail;
5923 	}
5924 	intro->pmk_len = curve->hash_len;
5925 
5926 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5927 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
5928 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
5929 		goto fail;
5930 	}
5931 
5932 	ret = DPP_STATUS_OK;
5933 fail:
5934 	if (ret != DPP_STATUS_OK)
5935 		os_memset(intro, 0, sizeof(*intro));
5936 	os_memset(Nx, 0, sizeof(Nx));
5937 	os_free(own_conn);
5938 	os_free(signed_connector);
5939 	os_free(info.payload);
5940 	crypto_ec_free_key(own_key);
5941 	wpabuf_free(own_key_pub);
5942 	crypto_ec_free_key(peer_key);
5943 	crypto_ec_free_key(csign);
5944 	json_free(root);
5945 	json_free(own_root);
5946 	return ret;
5947 }
5948 
5949 #ifdef CONFIG_WPA_TESTING_OPTIONS
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)5950 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
5951 				    const struct dpp_curve_params *curve)
5952 {
5953 	return 0;
5954 }
5955 
dpp_corrupt_connector_signature(const char * connector)5956 char * dpp_corrupt_connector_signature(const char *connector)
5957 {
5958 	char *tmp, *pos, *signed3 = NULL;
5959 	unsigned char *signature = NULL;
5960 	size_t signature_len = 0, signed3_len;
5961 
5962 	tmp = os_zalloc(os_strlen(connector) + 5);
5963 	if (!tmp)
5964 		goto fail;
5965 	os_memcpy(tmp, connector, os_strlen(connector));
5966 
5967 	pos = os_strchr(tmp, '.');
5968 	if (!pos)
5969 		goto fail;
5970 
5971 	pos = os_strchr(pos + 1, '.');
5972 	if (!pos)
5973 		goto fail;
5974 	pos++;
5975 
5976 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
5977 		   pos);
5978 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5979 	if (!signature || signature_len == 0)
5980 		goto fail;
5981 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
5982 		    signature, signature_len);
5983 	signature[signature_len - 1] ^= 0x01;
5984 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
5985 		    signature, signature_len);
5986 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
5987 	if (!signed3)
5988 		goto fail;
5989 	os_memcpy(pos, signed3, signed3_len);
5990 	pos[signed3_len] = '\0';
5991 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
5992 		   pos);
5993 
5994 out:
5995 	os_free(signature);
5996 	os_free(signed3);
5997 	return tmp;
5998 fail:
5999 	os_free(tmp);
6000 	tmp = NULL;
6001 	goto out;
6002 }
6003 #endif /* CONFIG_WPA_TESTING_OPTIONS */
6004 
dpp_next_id(struct dpp_global * dpp)6005 static unsigned int dpp_next_id(struct dpp_global *dpp)
6006 {
6007 	struct dpp_bootstrap_info *bi;
6008 	unsigned int max_id = 0;
6009 
6010 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6011 		if (bi->id > max_id)
6012 			max_id = bi->id;
6013 	}
6014 	return max_id + 1;
6015 }
6016 
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)6017 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
6018 {
6019 	struct dpp_bootstrap_info *bi, *tmp;
6020 	int found = 0;
6021 
6022 	if (!dpp)
6023 		return -1;
6024 
6025 	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
6026 			      struct dpp_bootstrap_info, list) {
6027 		if (id && bi->id != id)
6028 			continue;
6029 		found = 1;
6030 		dl_list_del(&bi->list);
6031 		dpp_bootstrap_info_free(bi);
6032 	}
6033 
6034 	if (id == 0)
6035 		return 0; /* flush succeeds regardless of entries found */
6036 	return found ? 0 : -1;
6037 }
6038 
6039 
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)6040 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
6041 					    const char *uri)
6042 {
6043 	struct dpp_bootstrap_info *bi;
6044 
6045 	if (!dpp)
6046 		return NULL;
6047 
6048 	bi = dpp_parse_uri(uri);
6049 	if (!bi)
6050 		return NULL;
6051 
6052 	bi->type = DPP_BOOTSTRAP_QR_CODE;
6053 	bi->id = dpp_next_id(dpp);
6054 	dl_list_add(&dpp->bootstrap, &bi->list);
6055 	return bi;
6056 }
6057 
6058 
dpp_add_nfc_uri(struct dpp_global * dpp,const char * uri)6059 struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
6060 					    const char *uri)
6061 {
6062 	struct dpp_bootstrap_info *bi;
6063 
6064 	if (!dpp)
6065 		return NULL;
6066 
6067 	bi = dpp_parse_uri(uri);
6068 	if (!bi)
6069 		return NULL;
6070 
6071 	bi->type = DPP_BOOTSTRAP_NFC_URI;
6072 	bi->id = dpp_next_id(dpp);
6073 	dl_list_add(&dpp->bootstrap, &bi->list);
6074 	return bi;
6075 }
6076 
6077 
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)6078 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
6079 {
6080 	char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
6081 	char *key = NULL;
6082 	u8 *privkey = NULL;
6083 	size_t privkey_len = 0;
6084 	size_t len;
6085 	int ret = -1;
6086 	struct dpp_bootstrap_info *bi;
6087 
6088 	bi = os_zalloc(sizeof(*bi));
6089 	if (!bi)
6090 		goto fail;
6091 
6092 	if (os_strstr(cmd, "type=qrcode"))
6093 		bi->type = DPP_BOOTSTRAP_QR_CODE;
6094 	else if (os_strstr(cmd, "type=pkex"))
6095 		bi->type = DPP_BOOTSTRAP_PKEX;
6096 	else if (os_strstr(cmd, "type=nfc-uri"))
6097 		bi->type = DPP_BOOTSTRAP_NFC_URI;
6098 	else
6099 		goto fail;
6100 
6101 	chan = get_param(cmd, " chan=");
6102 	mac = get_param(cmd, " mac=");
6103 	info = get_param(cmd, " info=");
6104 	curve = get_param(cmd, " curve=");
6105 	key = get_param(cmd, " key=");
6106 
6107 	if (key) {
6108 		privkey_len = os_strlen(key) / 2;
6109 		privkey = os_malloc(privkey_len);
6110 		if (!privkey ||
6111 		    hexstr2bin(key, privkey, privkey_len) < 0)
6112 			goto fail;
6113 	}
6114 	wpa_hexdump(MSG_DEBUG, "private key", privkey, privkey_len);
6115 
6116 	pk = dpp_keygen(bi, curve, privkey, privkey_len);
6117 	if (!pk)
6118 		goto fail;
6119 
6120 	len = 4; /* "DPP:" */
6121 	if (chan) {
6122 		if (dpp_parse_uri_chan_list(bi, chan) < 0)
6123 			goto fail;
6124 		len += 3 + os_strlen(chan); /* C:...; */
6125 	}
6126 	if (mac) {
6127 		if (dpp_parse_uri_mac(bi, mac) < 0)
6128 			goto fail;
6129 		len += 3 + os_strlen(mac); /* M:...; */
6130 	}
6131 	if (info) {
6132 		if (dpp_parse_uri_info(bi, info) < 0)
6133 			goto fail;
6134 		len += 3 + os_strlen(info); /* I:...; */
6135 	}
6136 	len += 4 + os_strlen(pk);
6137 	bi->uri = os_malloc(len + 1);
6138 	if (!bi->uri)
6139 		goto fail;
6140 	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
6141 		    chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
6142 		    mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
6143 		    info ? "I:" : "", info ? info : "", info ? ";" : "",
6144 		    pk);
6145 
6146 	bi->id = dpp_next_id(dpp);
6147 	dl_list_add(&dpp->bootstrap, &bi->list);
6148 	ret = bi->id;
6149 	bi = NULL;
6150 fail:
6151 	os_free(curve);
6152 	os_free(pk);
6153 	os_free(chan);
6154 	os_free(mac);
6155 	os_free(info);
6156 	str_clear_free(key);
6157 	bin_clear_free(privkey, privkey_len);
6158 	dpp_bootstrap_info_free(bi);
6159 	return ret;
6160 }
6161 
6162 
6163 struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)6164 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
6165 {
6166 	struct dpp_bootstrap_info *bi;
6167 
6168 	if (!dpp)
6169 		return NULL;
6170 
6171 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6172 		if (bi->id == id)
6173 			return bi;
6174 	}
6175 	return NULL;
6176 }
6177 
6178 
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)6179 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
6180 {
6181 	unsigned int id_val;
6182 
6183 	if (os_strcmp(id, "*") == 0) {
6184 		id_val = 0;
6185 	} else {
6186 		id_val = atoi(id);
6187 		if (id_val == 0)
6188 			return -1;
6189 	}
6190 
6191 	return dpp_bootstrap_del(dpp, id_val);
6192 }
6193 
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)6194 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
6195 {
6196 	struct dpp_bootstrap_info *bi;
6197 
6198 	bi = dpp_bootstrap_get_id(dpp, id);
6199 	if (!bi)
6200 		return NULL;
6201 	return bi->uri;
6202 }
6203 
dpp_get_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)6204 int dpp_get_bootstrap_info(struct dpp_global *dpp, int id,
6205 		       char *reply, int reply_size)
6206 {
6207 	struct dpp_bootstrap_info *bi;
6208 	char pkhash[2 * SHA256_MAC_LEN + 1];
6209 
6210 	bi = dpp_bootstrap_get_id(dpp, id);
6211 	if (!bi)
6212 		return -1;
6213 	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
6214 			 SHA256_MAC_LEN);
6215 	return os_snprintf(reply, reply_size, "type=%s\n"
6216 			   "mac_addr=" MACSTR "\n"
6217 			   "info=%s\n"
6218 			   "num_freq=%u\n"
6219 			   "curve=%s\n"
6220 			   "pkhash=%s\n",
6221 			   dpp_bootstrap_type_txt(bi->type),
6222 			   MAC2STR(bi->mac_addr),
6223 			   bi->info ? bi->info : "",
6224 			   bi->num_freq,
6225 			   bi->curve->name,
6226 			   pkhash);
6227 }
6228 
6229 
dpp_bootstrap_find_pair(struct dpp_global * dpp,const u8 * i_bootstrap,const u8 * r_bootstrap,struct dpp_bootstrap_info ** own_bi,struct dpp_bootstrap_info ** peer_bi)6230 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
6231 			     const u8 *r_bootstrap,
6232 			     struct dpp_bootstrap_info **own_bi,
6233 			     struct dpp_bootstrap_info **peer_bi)
6234 {
6235 	struct dpp_bootstrap_info *bi;
6236 
6237 	*own_bi = NULL;
6238 	*peer_bi = NULL;
6239 	if (!dpp)
6240 		return;
6241 
6242 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6243 		if (!*own_bi && bi->own &&
6244 		    os_memcmp(bi->pubkey_hash, r_bootstrap,
6245 			      SHA256_MAC_LEN) == 0) {
6246 			wpa_printf(MSG_DEBUG,
6247 				   "DPP: Found matching own bootstrapping information");
6248 			*own_bi = bi;
6249 		}
6250 
6251 		if (!*peer_bi && !bi->own &&
6252 		    os_memcmp(bi->pubkey_hash, i_bootstrap,
6253 			      SHA256_MAC_LEN) == 0) {
6254 			wpa_printf(MSG_DEBUG,
6255 				   "DPP: Found matching peer bootstrapping information");
6256 			*peer_bi = bi;
6257 		}
6258 
6259 		if (*own_bi && *peer_bi)
6260 			break;
6261 	}
6262 
6263 }
6264 
6265 
dpp_next_configurator_id(struct dpp_global * dpp)6266 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
6267 {
6268 	struct dpp_configurator *conf;
6269 	unsigned int max_id = 0;
6270 
6271 	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
6272 			 list) {
6273 		if (conf->id > max_id)
6274 			max_id = conf->id;
6275 	}
6276 	return max_id + 1;
6277 }
6278 
6279 
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)6280 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
6281 {
6282 	char *curve = NULL;
6283 	char *key = NULL;
6284 	u8 *privkey = NULL;
6285 	size_t privkey_len = 0;
6286 	int ret = -1;
6287 	struct dpp_configurator *conf = NULL;
6288 
6289 	curve = get_param(cmd, " curve=");
6290 	key = get_param(cmd, " key=");
6291 
6292 	if (key) {
6293 		privkey_len = os_strlen(key) / 2;
6294 		privkey = os_malloc(privkey_len);
6295 		if (!privkey ||
6296 		    hexstr2bin(key, privkey, privkey_len) < 0)
6297 			goto fail;
6298 	}
6299 
6300 	conf = dpp_keygen_configurator(curve, privkey, privkey_len);
6301 	if (!conf)
6302 		goto fail;
6303 
6304 	conf->id = dpp_next_configurator_id(dpp);
6305 	dl_list_add(&dpp->configurator, &conf->list);
6306 	ret = conf->id;
6307 	conf = NULL;
6308 fail:
6309 	os_free(curve);
6310 	str_clear_free(key);
6311 	bin_clear_free(privkey, privkey_len);
6312 	dpp_configurator_free(conf);
6313 	return ret;
6314 }
6315 
6316 
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)6317 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
6318 {
6319 	struct dpp_configurator *conf, *tmp;
6320 	int found = 0;
6321 
6322 	if (!dpp)
6323 		return -1;
6324 
6325 	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
6326 			      struct dpp_configurator, list) {
6327 		if (id && conf->id != id)
6328 			continue;
6329 		found = 1;
6330 		dl_list_del(&conf->list);
6331 		dpp_configurator_free(conf);
6332 	}
6333 
6334 	if (id == 0)
6335 		return 0; /* flush succeeds regardless of entries found */
6336 	return found ? 0 : -1;
6337 }
6338 
6339 
dpp_configurator_remove(struct dpp_global * dpp,const char * id)6340 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
6341 {
6342 	unsigned int id_val;
6343 
6344 	if (os_strcmp(id, "*") == 0) {
6345 		id_val = 0;
6346 	} else {
6347 		id_val = atoi(id);
6348 		if (id_val == 0)
6349 			return -1;
6350 	}
6351 
6352 	return dpp_configurator_del(dpp, id_val);
6353 }
6354 
6355 
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)6356 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
6357 				char *buf, size_t buflen)
6358 {
6359 	struct dpp_configurator *conf;
6360 
6361 	conf = dpp_configurator_get_id(dpp, id);
6362 	if (!conf)
6363 		return -1;
6364 
6365 	return dpp_configurator_get_key(conf, buf, buflen);
6366 }
6367 
dpp_global_init(struct dpp_global_config * config)6368 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
6369 {
6370 	struct dpp_global *dpp;
6371 
6372 	dpp = os_zalloc(sizeof(*dpp));
6373 	if (!dpp)
6374 		return NULL;
6375 	dpp->msg_ctx = config->msg_ctx;
6376 
6377 	dl_list_init(&dpp->bootstrap);
6378 	dl_list_init(&dpp->configurator);
6379 
6380 	return dpp;
6381 }
6382 
6383 
dpp_global_clear(struct dpp_global * dpp)6384 void dpp_global_clear(struct dpp_global *dpp)
6385 {
6386 	if (!dpp)
6387 		return;
6388 
6389 	dpp_bootstrap_del(dpp, 0);
6390 	dpp_configurator_del(dpp, 0);
6391 }
6392 
6393 
dpp_global_deinit(struct dpp_global * dpp)6394 void dpp_global_deinit(struct dpp_global *dpp)
6395 {
6396 	dpp_global_clear(dpp);
6397 	os_free(dpp);
6398 }
6399