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_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_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 	{ "secp256r1", 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", __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 	forced_memzero(prk, 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 	forced_memzero(prk, 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 	forced_memzero(prk, 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_TESTING_OPTIONS
1004 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
1005 		attr_len += 5;
1006 #endif /* CONFIG_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_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_TESTING_OPTIONS */
1043 
1044 	/* Wrapped data ({I-nonce, I-capabilities}k1) */
1045 	pos = clear;
1046 
1047 #ifdef CONFIG_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_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_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_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_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_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_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_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_TESTING_OPTIONS
1164 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP)
1165 		attr_len += 5;
1166 #endif /* CONFIG_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_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_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_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_TESTING_OPTIONS */
1225 		pos += nonce_len;
1226 	}
1227 
1228 #ifdef CONFIG_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_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_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_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_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_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_TESTING_OPTIONS
1527 	u8 test_hash[SHA256_MAC_LEN];
1528 #endif /* CONFIG_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_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_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_TESTING_OPTIONS */
1566 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
1567 
1568 #ifdef CONFIG_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_TESTING_OPTIONS */
1581 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1582 #endif /* CONFIG_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_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_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_TESTING_OPTIONS
1679 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
1680 		attr_len += 5;
1681 #endif /* CONFIG_TESTING_OPTIONS */
1682 	msg = wpabuf_alloc(attr_len);
1683 	if (!clear || !msg)
1684 		goto fail;
1685 
1686 #ifdef CONFIG_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_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_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_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_TESTING_OPTIONS
1723 skip_conf_attr_obj:
1724 #endif /* CONFIG_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_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_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_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_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_TESTING_OPTIONS
2155 	u8 test_hash[SHA256_MAC_LEN];
2156 #endif /* CONFIG_TESTING_OPTIONS */
2157 
2158 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
2159 	if (!auth->own_bi)
2160 		return -1;
2161 
2162 #ifdef CONFIG_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_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_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_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_TESTING_OPTIONS */
2198 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2199 #endif /* CONFIG_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_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_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_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_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_TESTING_OPTIONS
2333 	u8 test_hash[SHA256_MAC_LEN];
2334 #endif /* CONFIG_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_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_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_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_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_TESTING_OPTIONS
2683 	u8 test_hash[SHA256_MAC_LEN];
2684 #endif /* CONFIG_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_TESTING_OPTIONS
2694 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF)
2695 		attr_len += 5;
2696 #endif /* CONFIG_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_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_TESTING_OPTIONS */
2718 
2719 	/* DPP Status */
2720 	dpp_build_attr_status(msg, status);
2721 
2722 #ifdef CONFIG_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_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_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_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_TESTING_OPTIONS
2782 		if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
2783 			goto skip_i_auth;
2784 #endif /* CONFIG_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_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_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_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_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_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_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_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_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_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_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_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_TESTING_OPTIONS */
3635 		goto fail;
3636 #endif /* CONFIG_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_TESTING_OPTIONS
3838 	os_free(auth->config_obj_override);
3839 	os_free(auth->discovery_override);
3840 	os_free(auth->groups_override);
3841 #endif /* CONFIG_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_TESTING_OPTIONS
3853 	if (auth->discovery_override)
3854 		tailroom += os_strlen(auth->discovery_override);
3855 #endif /* CONFIG_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_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_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 		forced_memzero(psk, 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_TESTING_OPTIONS
4018 	if (auth->groups_override)
4019 		extra_len += os_strlen(auth->groups_override);
4020 #endif /* CONFIG_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_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_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_TESTING_OPTIONS
4054 skip_groups:
4055 #endif /* CONFIG_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 (!signature)
4114 		goto fail;
4115 	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
4116 			dpp_bn2bin_pad(s, signature + curve->prime_len,
4117 				curve->prime_len) < 0)
4118 		goto fail;
4119 	signature_len = 2 * curve->prime_len;
4120 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
4121 		    signature, signature_len);
4122 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
4123 	if (!signed3)
4124 		goto fail;
4125 
4126 	incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
4127 	tailroom = 1000;
4128 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
4129 	tailroom += signed1_len + signed2_len + signed3_len;
4130 	if (incl_legacy)
4131 		tailroom += 1000;
4132 	buf = dpp_build_conf_start(auth, conf, tailroom);
4133 	if (!buf)
4134 		goto fail;
4135 
4136 	if (auth->akm_use_selector && dpp_akm_ver2(akm))
4137 		akm_str = dpp_akm_selector_str(akm);
4138 	else
4139 		akm_str = dpp_akm_str(akm);
4140 	json_start_object(buf, "cred");
4141 	json_add_string(buf, "akm", akm_str);
4142 	json_value_sep(buf);
4143 	if (incl_legacy) {
4144 		dpp_build_legacy_cred_params(buf, conf);
4145 		json_value_sep(buf);
4146 	}
4147 	wpabuf_put_str(buf, "\"signedConnector\":\"");
4148 	wpabuf_put_str(buf, signed1);
4149 	wpabuf_put_u8(buf, '.');
4150 	wpabuf_put_str(buf, signed2);
4151 	wpabuf_put_u8(buf, '.');
4152 	wpabuf_put_str(buf, signed3);
4153 	wpabuf_put_str(buf, "\"");
4154 	json_value_sep(buf);
4155 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
4156 			  curve) < 0) {
4157 		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
4158 		goto fail;
4159 	}
4160 
4161 	json_end_object(buf);
4162 	json_end_object(buf);
4163 
4164 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
4165 			      (u8 *)wpabuf_head(buf), wpabuf_len(buf));
4166 
4167 out:
4168 	if (signed1)
4169 		os_free(signed1);
4170 	if (signed2)
4171 		os_free(signed2);
4172 	if (signed3)
4173 		os_free(signed3);
4174 	if (hash)
4175 		os_free(hash);
4176 	if (signature)
4177 		os_free(signature);
4178 	crypto_bignum_deinit(r, 0);
4179 	crypto_bignum_deinit(s, 0);
4180 	wpabuf_free(dppcon);
4181 	return buf;
4182 fail:
4183 	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
4184 	wpabuf_free(buf);
4185 	buf = NULL;
4186 	goto out;
4187 }
4188 
4189 static struct wpabuf *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,struct dpp_configuration * conf)4190 dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
4191 			  struct dpp_configuration *conf)
4192 {
4193 	struct wpabuf *buf;
4194 	const char *akm_str;
4195 
4196 	buf = dpp_build_conf_start(auth, conf, 1000);
4197 	if (!buf)
4198 		return NULL;
4199 
4200 	if (auth->akm_use_selector && dpp_akm_ver2(conf->akm))
4201 		akm_str = dpp_akm_selector_str(conf->akm);
4202 	else
4203 		akm_str = dpp_akm_str(conf->akm);
4204 	json_start_object(buf, "cred");
4205 	json_add_string(buf, "akm", akm_str);
4206 	json_value_sep(buf);
4207 	dpp_build_legacy_cred_params(buf, conf);
4208 	json_end_object(buf);
4209 	json_end_object(buf);
4210 
4211 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
4212 			      (u8 *)wpabuf_head(buf), wpabuf_len(buf));
4213 
4214 	return buf;
4215 }
4216 
4217 
4218 static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication * auth,enum dpp_netrole netrole,int idx)4219 dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
4220 		   int idx)
4221 {
4222 	struct dpp_configuration *conf = NULL;
4223 
4224 #ifdef CONFIG_TESTING_OPTIONS
4225 	if (auth->config_obj_override) {
4226 		if (idx != 0)
4227 			return NULL;
4228 		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
4229 		return wpabuf_alloc_copy(auth->config_obj_override,
4230 					 os_strlen(auth->config_obj_override));
4231 	}
4232 #endif /* CONFIG_TESTING_OPTIONS */
4233 
4234 	if (idx == 0) {
4235 		if (netrole == DPP_NETROLE_STA)
4236 			conf = auth->conf_sta;
4237 		else if (netrole == DPP_NETROLE_AP)
4238 			conf = auth->conf_ap;
4239 	} else if (idx == 1) {
4240 		if (netrole == DPP_NETROLE_STA)
4241 			conf = auth->conf2_sta;
4242 		else if (netrole == DPP_NETROLE_AP)
4243 			conf = auth->conf2_ap;
4244 	}
4245 	if (!conf) {
4246 		if (idx == 0)
4247 			wpa_printf(MSG_DEBUG,
4248 				   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
4249 				   dpp_netrole_str(netrole));
4250 		return NULL;
4251 	}
4252 
4253 	if (dpp_akm_dpp(conf->akm))
4254 		return dpp_build_conf_obj_dpp(auth, conf);
4255 	return dpp_build_conf_obj_legacy(auth, conf);
4256 }
4257 
4258 
4259 static struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,enum dpp_netrole netrole)4260 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
4261 		    u16 e_nonce_len, enum dpp_netrole netrole)
4262 {
4263 	struct wpabuf *conf, *conf2 = NULL;
4264 	size_t clear_len, attr_len;
4265 	struct wpabuf *clear = NULL, *msg = NULL;
4266 	u8 *wrapped;
4267 	const u8 *addr[1];
4268 	size_t len[1];
4269 	enum dpp_status_error status;
4270 
4271 	conf = dpp_build_conf_obj(auth, netrole, 0);
4272 	if (conf) {
4273 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
4274 				  (u8 *)wpabuf_head(conf), wpabuf_len(conf));
4275 		conf2 = dpp_build_conf_obj(auth, netrole, 1);
4276 	}
4277 	status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
4278 	auth->conf_resp_status = status;
4279 
4280 	/* { E-nonce, configurationObject[, sendConnStatus]}ke */
4281 	clear_len = 4 + e_nonce_len;
4282 	if (conf)
4283 		clear_len += 4 + wpabuf_len(conf);
4284 	if (conf2)
4285 		clear_len += 4 + wpabuf_len(conf2);
4286 	if (auth->peer_version >= 2 && auth->send_conn_status &&
4287 	    netrole == DPP_NETROLE_STA)
4288 		clear_len += 4;
4289 	clear = wpabuf_alloc(clear_len);
4290 	attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
4291 #ifdef CONFIG_TESTING_OPTIONS
4292 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
4293 		attr_len += 5;
4294 #endif /* CONFIG_TESTING_OPTIONS */
4295 	msg = wpabuf_alloc(attr_len);
4296 	if (!clear || !msg)
4297 		goto fail;
4298 
4299 #ifdef CONFIG_TESTING_OPTIONS
4300 	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
4301 		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
4302 		goto skip_e_nonce;
4303 	}
4304 	if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
4305 		wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
4306 		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4307 		wpabuf_put_le16(clear, e_nonce_len);
4308 		wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
4309 		wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
4310 		goto skip_e_nonce;
4311 	}
4312 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
4313 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
4314 		goto skip_wrapped_data;
4315 	}
4316 #endif /* CONFIG_TESTING_OPTIONS */
4317 
4318 	/* E-nonce */
4319 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4320 	wpabuf_put_le16(clear, e_nonce_len);
4321 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
4322 
4323 #ifdef CONFIG_TESTING_OPTIONS
4324 skip_e_nonce:
4325 	if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
4326 		wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
4327 		goto skip_config_obj;
4328 	}
4329 #endif /* CONFIG_TESTING_OPTIONS */
4330 
4331 	if (conf) {
4332 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
4333 		wpabuf_put_le16(clear, wpabuf_len(conf));
4334 		wpabuf_put_buf(clear, conf);
4335 	}
4336 	if (auth->peer_version >= 2 && conf2) {
4337 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
4338 		wpabuf_put_le16(clear, wpabuf_len(conf2));
4339 		wpabuf_put_buf(clear, conf2);
4340 	} else if (conf2) {
4341 		wpa_printf(MSG_DEBUG,
4342 			   "DPP: Second Config Object available, but peer does not support more than one");
4343 	}
4344 
4345 	if (auth->peer_version >= 2 && auth->send_conn_status &&
4346 	    netrole == DPP_NETROLE_STA) {
4347 		wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
4348 		wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
4349 		wpabuf_put_le16(clear, 0);
4350 	}
4351 
4352 #ifdef CONFIG_TESTING_OPTIONS
4353 skip_config_obj:
4354 	if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
4355 		wpa_printf(MSG_INFO, "DPP: TESTING - Status");
4356 		goto skip_status;
4357 	}
4358 	if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
4359 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
4360 		status = 255;
4361 	}
4362 #endif /* CONFIG_TESTING_OPTIONS */
4363 
4364 	/* DPP Status */
4365 	dpp_build_attr_status(msg, status);
4366 
4367 #ifdef CONFIG_TESTING_OPTIONS
4368 skip_status:
4369 #endif /* CONFIG_TESTING_OPTIONS */
4370 
4371 	addr[0] = wpabuf_head(msg);
4372 	len[0] = wpabuf_len(msg);
4373 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
4374 
4375 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
4376 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4377 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4378 
4379 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
4380 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
4381 			    wpabuf_head(clear), wpabuf_len(clear),
4382 			    1, addr, len, wrapped) < 0)
4383 		goto fail;
4384 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4385 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
4386 
4387 #ifdef CONFIG_TESTING_OPTIONS
4388 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) {
4389 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
4390 		dpp_build_attr_status(msg, DPP_STATUS_OK);
4391 	}
4392 skip_wrapped_data:
4393 #endif /* CONFIG_TESTING_OPTIONS */
4394 
4395 	wpa_hexdump_buf(MSG_DEBUG,
4396 			"DPP: Configuration Response attributes", msg);
4397 out:
4398 	wpabuf_free(conf);
4399 	wpabuf_free(conf2);
4400 	wpabuf_free(clear);
4401 
4402 	return msg;
4403 fail:
4404 	wpabuf_free(msg);
4405 	msg = NULL;
4406 	goto out;
4407 }
4408 
4409 
4410 struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)4411 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
4412 		size_t attr_len)
4413 {
4414 	const u8 *wrapped_data, *e_nonce, *config_attr;
4415 	u16 wrapped_data_len, e_nonce_len, config_attr_len;
4416 	u8 *unwrapped = NULL;
4417 	size_t unwrapped_len = 0;
4418 	struct wpabuf *resp = NULL;
4419 	struct json_token *root = NULL, *token;
4420 	enum dpp_netrole netrole;
4421 
4422 #ifdef CONFIG_TESTING_OPTIONS
4423 	if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
4424 		wpa_printf(MSG_INFO,
4425 			   "DPP: TESTING - stop at Config Request");
4426 		return NULL;
4427 	}
4428 #endif /* CONFIG_TESTING_OPTIONS */
4429 
4430 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
4431 		dpp_auth_fail(auth, "Invalid attribute in config request");
4432 		return NULL;
4433 	}
4434 
4435 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
4436 				    &wrapped_data_len);
4437 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
4438 		dpp_auth_fail(auth,
4439 			      "Missing or invalid required Wrapped Data attribute");
4440 		return NULL;
4441 	}
4442 
4443 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4444 		    wrapped_data, wrapped_data_len);
4445 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
4446 	unwrapped = os_malloc(unwrapped_len);
4447 	if (!unwrapped)
4448 		return NULL;
4449 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
4450 			    wrapped_data, wrapped_data_len,
4451 			    0, NULL, NULL, unwrapped) < 0) {
4452 		dpp_auth_fail(auth, "AES-SIV decryption failed");
4453 		goto fail;
4454 	}
4455 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
4456 		    unwrapped, unwrapped_len);
4457 
4458 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
4459 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
4460 		goto fail;
4461 	}
4462 
4463 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
4464 			       DPP_ATTR_ENROLLEE_NONCE,
4465 			       &e_nonce_len);
4466 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
4467 		dpp_auth_fail(auth,
4468 			      "Missing or invalid Enrollee Nonce attribute");
4469 		goto fail;
4470 	}
4471 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
4472 	os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
4473 
4474 	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
4475 				   DPP_ATTR_CONFIG_ATTR_OBJ,
4476 				   &config_attr_len);
4477 	if (!config_attr) {
4478 		dpp_auth_fail(auth,
4479 			      "Missing or invalid Config Attributes attribute");
4480 		goto fail;
4481 	}
4482 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
4483 			  (u8 *)config_attr, config_attr_len);
4484 
4485 	root = json_parse((const char *) config_attr, config_attr_len);
4486 	if (!root) {
4487 		dpp_auth_fail(auth, "Could not parse Config Attributes");
4488 		goto fail;
4489 	}
4490 
4491 	token = json_get_member(root, "name");
4492 	if (!token || token->type != JSON_STRING) {
4493 		dpp_auth_fail(auth, "No Config Attributes - name");
4494 		goto fail;
4495 	}
4496 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
4497 
4498 	token = json_get_member(root, "wi-fi_tech");
4499 	if (!token || token->type != JSON_STRING) {
4500 		dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
4501 		goto fail;
4502 	}
4503 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
4504 	if (os_strcmp(token->string, "infra") != 0) {
4505 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
4506 			   token->string);
4507 		dpp_auth_fail(auth, "Unsupported wi-fi_tech");
4508 		goto fail;
4509 	}
4510 
4511 	token = json_get_member(root, "netRole");
4512 	if (!token || token->type != JSON_STRING) {
4513 		dpp_auth_fail(auth, "No Config Attributes - netRole");
4514 		goto fail;
4515 	}
4516 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
4517 	if (os_strcmp(token->string, "sta") == 0) {
4518 		netrole = DPP_NETROLE_STA;
4519 	} else if (os_strcmp(token->string, "ap") == 0) {
4520 		netrole = DPP_NETROLE_AP;
4521 	} else if (os_strcmp(token->string, "configurator") == 0) {
4522 		netrole = DPP_NETROLE_CONFIGURATOR;
4523 	} else {
4524 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
4525 			   token->string);
4526 		dpp_auth_fail(auth, "Unsupported netRole");
4527 		goto fail;
4528 	}
4529 
4530 	token = json_get_member(root, "mudurl");
4531 	if (token && token->type == JSON_STRING)
4532 		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
4533 
4534 	token = json_get_member(root, "bandSupport");
4535 	if (token && token->type == JSON_ARRAY) {
4536 		wpa_printf(MSG_DEBUG, "DPP: bandSupport");
4537 		token = token->child;
4538 		while (token) {
4539 			if (token->type != JSON_NUMBER)
4540 				wpa_printf(MSG_DEBUG,
4541 					   "DPP: Invalid bandSupport array member type");
4542 			else
4543 				wpa_printf(MSG_DEBUG,
4544 					   "DPP: Supported global operating class: %d",
4545 					   token->number);
4546 			token = token->sibling;
4547 		}
4548 	}
4549 
4550 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole);
4551 fail:
4552 	json_free(root);
4553 	os_free(unwrapped);
4554 	return resp;
4555 }
4556 
4557 
4558 static struct wpabuf *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params * curve,const u8 * prot_hdr,u16 prot_hdr_len)4559 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
4560 		       const u8 *prot_hdr, u16 prot_hdr_len)
4561 {
4562 	struct json_token *root, *token;
4563 	struct wpabuf *kid = NULL;
4564 
4565 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
4566 	if (!root) {
4567 		wpa_printf(MSG_DEBUG,
4568 			   "DPP: JSON parsing failed for JWS Protected Header");
4569 		goto fail;
4570 	}
4571 
4572 	if (root->type != JSON_OBJECT) {
4573 		wpa_printf(MSG_DEBUG,
4574 			   "DPP: JWS Protected Header root is not an object");
4575 		goto fail;
4576 	}
4577 
4578 	token = json_get_member(root, "typ");
4579 	if (!token || token->type != JSON_STRING) {
4580 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
4581 		goto fail;
4582 	}
4583 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
4584 		   token->string);
4585 	if (os_strcmp(token->string, "dppCon") != 0) {
4586 		wpa_printf(MSG_DEBUG,
4587 			   "DPP: Unsupported JWS Protected Header typ=%s",
4588 			   token->string);
4589 		goto fail;
4590 	}
4591 
4592 	token = json_get_member(root, "alg");
4593 	if (!token || token->type != JSON_STRING) {
4594 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
4595 		goto fail;
4596 	}
4597 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
4598 		   token->string);
4599 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
4600 		wpa_printf(MSG_DEBUG,
4601 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
4602 			   token->string, curve->jws_alg);
4603 		goto fail;
4604 	}
4605 
4606 	kid = json_get_member_base64url(root, "kid");
4607 	if (!kid) {
4608 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
4609 		goto fail;
4610 	}
4611 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
4612 			kid);
4613 
4614 fail:
4615 	json_free(root);
4616 	return kid;
4617 }
4618 
4619 
dpp_parse_cred_legacy(struct dpp_config_obj * conf,struct json_token * cred)4620 static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
4621 				 struct json_token *cred)
4622 {
4623 	struct json_token *pass, *psk_hex;
4624 
4625 	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
4626 
4627 	pass = json_get_member(cred, "pass");
4628 	psk_hex = json_get_member(cred, "psk_hex");
4629 
4630 	if (pass && pass->type == JSON_STRING) {
4631 		size_t len = os_strlen(pass->string);
4632 
4633 		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
4634 				      (u8 *)pass->string, len);
4635 		if (len < 8 || len > 63)
4636 			return -1;
4637 		os_strlcpy(conf->passphrase, pass->string,
4638 			   sizeof(conf->passphrase));
4639 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
4640 		if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
4641 			wpa_printf(MSG_DEBUG,
4642 				   "DPP: Unexpected psk_hex with akm=sae");
4643 			return -1;
4644 		}
4645 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
4646 		    hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) {
4647 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
4648 			return -1;
4649 		}
4650 		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
4651 				conf->psk, PMK_LEN);
4652 		conf->psk_set = 1;
4653 	} else {
4654 		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
4655 		return -1;
4656 	}
4657 
4658 	if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) {
4659 		wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
4660 		return -1;
4661 	}
4662 
4663 	return 0;
4664 }
4665 
4666 
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)4667 static struct crypto_key * dpp_parse_jwk(struct json_token *jwk,
4668 				const struct dpp_curve_params **key_curve)
4669 {
4670 	struct json_token *token;
4671 	const struct dpp_curve_params *curve;
4672 	struct wpabuf *x = NULL, *y = NULL;
4673 	unsigned char *a = NULL;
4674 	struct crypto_ec_group *group;
4675 	struct crypto_key *pkey = NULL;
4676 	size_t len;
4677 
4678 	token = json_get_member(jwk, "kty");
4679 	if (!token || token->type != JSON_STRING) {
4680 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
4681 		goto fail;
4682 	}
4683 	if (os_strcmp(token->string, "EC") != 0) {
4684 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
4685 			   token->string);
4686 		goto fail;
4687 	}
4688 
4689 	token = json_get_member(jwk, "crv");
4690 	if (!token || token->type != JSON_STRING) {
4691 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
4692 		goto fail;
4693 	}
4694 	curve = dpp_get_curve_jwk_crv(token->string);
4695 	if (!curve) {
4696 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
4697 			   token->string);
4698 		goto fail;
4699 	}
4700 
4701 	x = json_get_member_base64url(jwk, "x");
4702 	if (!x) {
4703 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
4704 		goto fail;
4705 	}
4706 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
4707 	if (wpabuf_len(x) != curve->prime_len) {
4708 		wpa_printf(MSG_DEBUG,
4709 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
4710 			   (unsigned int) wpabuf_len(x),
4711 			   (unsigned int) curve->prime_len, curve->name);
4712 		goto fail;
4713 	}
4714 
4715 	y = json_get_member_base64url(jwk, "y");
4716 	if (!y) {
4717 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
4718 		goto fail;
4719 	}
4720 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
4721 	if (wpabuf_len(y) != curve->prime_len) {
4722 		wpa_printf(MSG_DEBUG,
4723 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
4724 			   (unsigned int) wpabuf_len(y),
4725 			   (unsigned int) curve->prime_len, curve->name);
4726 		goto fail;
4727 	}
4728 
4729 	group = crypto_ec_get_group_byname(curve->name);
4730 	if (!group) {
4731 		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
4732 		goto fail;
4733 	}
4734 
4735 	len = wpabuf_len(x) + wpabuf_len(y);
4736 	a = os_zalloc(len);
4737 	os_memcpy(a, wpabuf_head(x), wpabuf_len(x));
4738 	os_memcpy(a + wpabuf_len(x), wpabuf_head(y), wpabuf_len(y));
4739 	pkey = crypto_ec_set_pubkey_point(group, a, len);
4740 
4741 	crypto_ec_deinit((struct crypto_ec *)group);
4742 	*key_curve = curve;
4743 
4744 fail:
4745 	wpabuf_free(x);
4746 	wpabuf_free(y);
4747 	os_free(a);
4748 
4749 	return pkey;
4750 }
4751 
4752 
dpp_key_expired(const char * timestamp,os_time_t * expiry)4753 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
4754 {
4755 	struct os_time now;
4756 	unsigned int year, month, day, hour, min, sec;
4757 	os_time_t utime;
4758 	const char *pos;
4759 
4760 	/* ISO 8601 date and time:
4761 	 * <date>T<time>
4762 	 * YYYY-MM-DDTHH:MM:SSZ
4763 	 * YYYY-MM-DDTHH:MM:SS+03:00
4764 	 */
4765 	if (os_strlen(timestamp) < 19) {
4766 		wpa_printf(MSG_DEBUG,
4767 			   "DPP: Too short timestamp - assume expired key");
4768 		return 1;
4769 	}
4770 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
4771 		   &year, &month, &day, &hour, &min, &sec) != 6) {
4772 		wpa_printf(MSG_DEBUG,
4773 			   "DPP: Failed to parse expiration day - assume expired key");
4774 		return 1;
4775 	}
4776 
4777 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
4778 		wpa_printf(MSG_DEBUG,
4779 			   "DPP: Invalid date/time information - assume expired key");
4780 		return 1;
4781 	}
4782 
4783 	pos = timestamp + 19;
4784 	if (*pos == 'Z' || *pos == '\0') {
4785 		/* In UTC - no need to adjust */
4786 	} else if (*pos == '-' || *pos == '+') {
4787 		int items;
4788 
4789 		/* Adjust local time to UTC */
4790 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
4791 		if (items < 1) {
4792 			wpa_printf(MSG_DEBUG,
4793 				   "DPP: Invalid time zone designator (%s) - assume expired key",
4794 				   pos);
4795 			return 1;
4796 		}
4797 		if (*pos == '-')
4798 			utime += 3600 * hour;
4799 		if (*pos == '+')
4800 			utime -= 3600 * hour;
4801 		if (items > 1) {
4802 			if (*pos == '-')
4803 				utime += 60 * min;
4804 			if (*pos == '+')
4805 				utime -= 60 * min;
4806 		}
4807 	} else {
4808 		wpa_printf(MSG_DEBUG,
4809 			   "DPP: Invalid time zone designator (%s) - assume expired key",
4810 			   pos);
4811 		return 1;
4812 	}
4813 	if (expiry)
4814 		*expiry = utime;
4815 
4816 	if (os_get_time(&now) < 0) {
4817 		wpa_printf(MSG_DEBUG,
4818 			   "DPP: Cannot get current time - assume expired key");
4819 		return 1;
4820 	}
4821 
4822 	if (now.sec > utime) {
4823 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
4824 			   utime, now.sec);
4825 		return 1;
4826 	}
4827 
4828 	return 0;
4829 }
4830 
4831 
dpp_parse_connector(struct dpp_authentication * auth,struct dpp_config_obj * conf,const unsigned char * payload,u16 payload_len)4832 static int dpp_parse_connector(struct dpp_authentication *auth,
4833 			       struct dpp_config_obj *conf,
4834 			       const unsigned char *payload,
4835 			       u16 payload_len)
4836 {
4837 	struct json_token *root, *groups, *netkey, *token;
4838 	int ret = -1;
4839 	struct crypto_key *key = NULL;
4840 	const struct dpp_curve_params *curve;
4841 	unsigned int rules = 0;
4842 
4843 	root = json_parse((const char *) payload, payload_len);
4844 	if (!root) {
4845 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4846 		goto fail;
4847 	}
4848 
4849 	groups = json_get_member(root, "groups");
4850 	if (!groups || groups->type != JSON_ARRAY) {
4851 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
4852 		goto skip_groups;
4853 	}
4854 	for (token = groups->child; token; token = token->sibling) {
4855 		struct json_token *id, *role;
4856 
4857 		id = json_get_member(token, "groupId");
4858 		if (!id || id->type != JSON_STRING) {
4859 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
4860 			goto fail;
4861 		}
4862 
4863 		role = json_get_member(token, "netRole");
4864 		if (!role || role->type != JSON_STRING) {
4865 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
4866 			goto fail;
4867 		}
4868 		wpa_printf(MSG_DEBUG,
4869 			   "DPP: connector group: groupId='%s' netRole='%s'",
4870 			   id->string, role->string);
4871 		rules++;
4872 	}
4873 skip_groups:
4874 
4875 	if (!rules) {
4876 		wpa_printf(MSG_DEBUG,
4877 			   "DPP: Connector includes no groups");
4878 		goto fail;
4879 	}
4880 
4881 	token = json_get_member(root, "expiry");
4882 	if (!token || token->type != JSON_STRING) {
4883 		wpa_printf(MSG_DEBUG,
4884 			   "DPP: No expiry string found - connector does not expire");
4885 	} else {
4886 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4887 		if (dpp_key_expired(token->string,
4888 				    &auth->net_access_key_expiry)) {
4889 			wpa_printf(MSG_DEBUG,
4890 				   "DPP: Connector (netAccessKey) has expired");
4891 			goto fail;
4892 		}
4893 	}
4894 
4895 	netkey = json_get_member(root, "netAccessKey");
4896 	if (!netkey || netkey->type != JSON_OBJECT) {
4897 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4898 		goto fail;
4899 	}
4900 
4901 	key = dpp_parse_jwk(netkey, &curve);
4902 	if (!key)
4903 		goto fail;
4904 	dpp_debug_print_key("DPP: Received netAccessKey", key);
4905 
4906 	if (crypto_key_compare(key, auth->own_protocol_key) != 1) {
4907 		wpa_printf(MSG_DEBUG,
4908 			   "DPP: netAccessKey in connector does not match own protocol key");
4909 #ifdef CONFIG_TESTING_OPTIONS
4910 		if (auth->ignore_netaccesskey_mismatch) {
4911 			wpa_printf(MSG_DEBUG,
4912 				   "DPP: TESTING - skip netAccessKey mismatch");
4913 		} else {
4914 			goto fail;
4915 		}
4916 #else /* CONFIG_TESTING_OPTIONS */
4917 		goto fail;
4918 #endif /* CONFIG_TESTING_OPTIONS */
4919 	}
4920 
4921 	ret = 0;
4922 fail:
4923 	crypto_ec_free_key(key);
4924 	json_free(root);
4925 	return ret;
4926 }
4927 
dpp_check_pubkey_match(struct crypto_key * pub,struct wpabuf * r_hash)4928 static int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash)
4929 {
4930 	struct wpabuf *uncomp;
4931 	int res;
4932 	u8 hash[SHA256_MAC_LEN];
4933 	const u8 *addr[1];
4934 	size_t len[1];
4935 
4936 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
4937 		return -1;
4938 	uncomp = dpp_get_pubkey_point(pub, 1);
4939 	if (!uncomp)
4940 		return -1;
4941 	addr[0] = wpabuf_head(uncomp);
4942 	len[0] = wpabuf_len(uncomp);
4943 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
4944 		    addr[0], len[0]);
4945 	res = sha256_vector(1, addr, len, hash);
4946 	wpabuf_free(uncomp);
4947 	if (res < 0)
4948 		return -1;
4949 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
4950 		wpa_printf(MSG_DEBUG,
4951 			   "DPP: Received hash value does not match calculated public key hash value");
4952 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
4953 			    hash, SHA256_MAC_LEN);
4954 		return -1;
4955 	}
4956 	return 0;
4957 }
4958 
4959 
dpp_copy_csign(struct dpp_config_obj * conf,struct crypto_key * csign)4960 static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_key *csign)
4961 {
4962 	unsigned char *der = NULL;
4963 	int der_len;
4964 
4965 	der_len = crypto_write_pubkey_der(csign, &der);
4966 	if (der_len <= 0)
4967 		return;
4968 	wpabuf_free(conf->c_sign_key);
4969 	conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
4970 	crypto_free_buffer(der);
4971 }
4972 
dpp_copy_netaccesskey(struct dpp_authentication * auth,struct dpp_config_obj * conf)4973 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
4974 				  struct dpp_config_obj *conf)
4975 {
4976 	unsigned char *der = NULL;
4977 	int der_len;
4978 
4979 	if (crypto_ec_get_priv_key_der(auth->own_protocol_key, &der, &der_len) < 0)
4980 		return;
4981 	wpabuf_free(auth->net_access_key);
4982 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
4983 	crypto_free_buffer(der);
4984 }
4985 
4986 struct dpp_signed_connector_info {
4987 	unsigned char *payload;
4988 	size_t payload_len;
4989 };
4990 
4991 static enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_key * csign_pub,const char * connector)4992 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
4993 			     struct crypto_key *csign_pub, const char *connector)
4994 {
4995 	enum dpp_status_error ret = 255;
4996 	const char *pos, *end, *signed_start, *signed_end;
4997 	struct wpabuf *kid = NULL;
4998 	unsigned char *prot_hdr = NULL, *signature = NULL;
4999 	size_t prot_hdr_len = 0, signature_len = 0;
5000 	struct crypto_bignum *r = NULL, *s = NULL;
5001 	const struct dpp_curve_params *curve;
5002 	const struct crypto_ec_group *group;
5003 	int id;
5004 
5005 	group = crypto_ec_get_group_from_key(csign_pub);
5006 	if (!group)
5007 		goto fail;
5008 	id = crypto_ec_get_curve_id(group);
5009 	curve = dpp_get_curve_group_id(id);
5010 	if (!curve)
5011 		goto fail;
5012 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
5013 	os_memset(info, 0, sizeof(*info));
5014 
5015 	signed_start = pos = connector;
5016 	end = os_strchr(pos, '.');
5017 	if (!end) {
5018 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
5019 		ret = DPP_STATUS_INVALID_CONNECTOR;
5020 		goto fail;
5021 	}
5022 	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
5023 	if (!prot_hdr) {
5024 		wpa_printf(MSG_DEBUG,
5025 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
5026 		ret = DPP_STATUS_INVALID_CONNECTOR;
5027 		goto fail;
5028 	}
5029 	wpa_hexdump_ascii(MSG_DEBUG,
5030 			  "DPP: signedConnector - JWS Protected Header",
5031 			  (u8 *)prot_hdr, prot_hdr_len);
5032 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len);
5033 	if (!kid) {
5034 		ret = DPP_STATUS_INVALID_CONNECTOR;
5035 		goto fail;
5036 	}
5037 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
5038 		wpa_printf(MSG_DEBUG,
5039 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
5040 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
5041 		ret = DPP_STATUS_INVALID_CONNECTOR;
5042 		goto fail;
5043 	}
5044 
5045 	pos = end + 1;
5046 	end = os_strchr(pos, '.');
5047 	if (!end) {
5048 		wpa_printf(MSG_DEBUG,
5049 			   "DPP: Missing dot(2) in signedConnector");
5050 		ret = DPP_STATUS_INVALID_CONNECTOR;
5051 		goto fail;
5052 	}
5053 	signed_end = end - 1;
5054 	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
5055 	if (!info->payload) {
5056 		wpa_printf(MSG_DEBUG,
5057 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
5058 		ret = DPP_STATUS_INVALID_CONNECTOR;
5059 		goto fail;
5060 	}
5061 	wpa_hexdump_ascii(MSG_DEBUG,
5062 			  "DPP: signedConnector - JWS Payload",
5063 			  (u8 *)info->payload, info->payload_len);
5064 	pos = end + 1;
5065 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5066 	if (!signature) {
5067 		wpa_printf(MSG_DEBUG,
5068 				"DPP: Failed to base64url decode signedConnector signature");
5069 		ret = DPP_STATUS_INVALID_CONNECTOR;
5070 		goto fail;
5071 	}
5072 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
5073 		    signature, signature_len);
5074 
5075 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
5076 		ret = DPP_STATUS_NO_MATCH;
5077 		goto fail;
5078 	}
5079 
5080 	if (signature_len & 0x01) {
5081 		wpa_printf(MSG_DEBUG,
5082 			   "DPP: Unexpected signedConnector signature length (%d)",
5083 			   (int) signature_len);
5084 		ret = DPP_STATUS_INVALID_CONNECTOR;
5085 		goto fail;
5086 	}
5087 
5088 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
5089 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
5090 	r = crypto_bignum_init_set(signature, signature_len / 2);
5091 	s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2);
5092 
5093 	if (!crypto_edcsa_sign_verify((unsigned char *)signed_start, r, s,
5094 				csign_pub, signed_end - signed_start + 1)) {
5095 		goto fail;
5096 	}
5097 
5098 	ret = DPP_STATUS_OK;
5099 fail:
5100 	os_free(prot_hdr);
5101 	wpabuf_free(kid);
5102 	os_free(signature);
5103 	crypto_bignum_deinit(r, 0);
5104 	crypto_bignum_deinit(s, 0);
5105 	return ret;
5106 }
5107 
5108 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)5109 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
5110 			      struct dpp_config_obj *conf,
5111 			      struct json_token *cred)
5112 {
5113 	struct dpp_signed_connector_info info;
5114 	struct json_token *token, *csign;
5115 	int ret = -1;
5116 	struct crypto_key *csign_pub = NULL;
5117 	const struct dpp_curve_params *key_curve = NULL;
5118 	const char *signed_connector;
5119 
5120 	os_memset(&info, 0, sizeof(info));
5121 
5122 	if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
5123 		wpa_printf(MSG_DEBUG,
5124 			   "DPP: Legacy credential included in Connector credential");
5125 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5126 			return -1;
5127 	}
5128 
5129 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
5130 
5131 	csign = json_get_member(cred, "csign");
5132 	if (!csign || csign->type != JSON_OBJECT) {
5133 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
5134 		goto fail;
5135 	}
5136 
5137 	csign_pub = dpp_parse_jwk(csign, &key_curve);
5138 	if (!csign_pub) {
5139 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
5140 		goto fail;
5141 	}
5142 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
5143 
5144 	token = json_get_member(cred, "signedConnector");
5145 	if (!token || token->type != JSON_STRING) {
5146 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
5147 		goto fail;
5148 	}
5149 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
5150 			  (u8 *)token->string, os_strlen(token->string));
5151 	signed_connector = token->string;
5152 
5153 	if (os_strchr(signed_connector, '"') ||
5154 	    os_strchr(signed_connector, '\n')) {
5155 		wpa_printf(MSG_DEBUG,
5156 			   "DPP: Unexpected character in signedConnector");
5157 		goto fail;
5158 	}
5159 
5160 	if (dpp_process_signed_connector(&info, csign_pub,
5161 					 signed_connector) != DPP_STATUS_OK)
5162 		goto fail;
5163 
5164 	if (dpp_parse_connector(auth, conf,
5165 				info.payload, info.payload_len) < 0) {
5166 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
5167 		goto fail;
5168 	}
5169 
5170 	os_free(conf->connector);
5171 	conf->connector = os_strdup(signed_connector);
5172 
5173 	dpp_copy_csign(conf, csign_pub);
5174 	dpp_copy_netaccesskey(auth, conf);
5175 
5176 	ret = 0;
5177 fail:
5178 	crypto_ec_free_key(csign_pub);
5179 	os_free(info.payload);
5180 	return ret;
5181 }
5182 
5183 
dpp_akm_str(enum dpp_akm akm)5184 const char * dpp_akm_str(enum dpp_akm akm)
5185 {
5186 	switch (akm) {
5187 	case DPP_AKM_DPP:
5188 		return "dpp";
5189 	case DPP_AKM_PSK:
5190 		return "psk";
5191 	case DPP_AKM_SAE:
5192 		return "sae";
5193 	case DPP_AKM_PSK_SAE:
5194 		return "psk+sae";
5195 	case DPP_AKM_SAE_DPP:
5196 		return "dpp+sae";
5197 	case DPP_AKM_PSK_SAE_DPP:
5198 		return "dpp+psk+sae";
5199 	default:
5200 		return "??";
5201 	}
5202 }
5203 
5204 
dpp_akm_selector_str(enum dpp_akm akm)5205 const char * dpp_akm_selector_str(enum dpp_akm akm)
5206 {
5207 	switch (akm) {
5208 	case DPP_AKM_DPP:
5209 		return "506F9A02";
5210 	case DPP_AKM_PSK:
5211 		return "000FAC02+000FAC06";
5212 	case DPP_AKM_SAE:
5213 		return "000FAC08";
5214 	case DPP_AKM_PSK_SAE:
5215 		return "000FAC02+000FAC06+000FAC08";
5216 	case DPP_AKM_SAE_DPP:
5217 		return "506F9A02+000FAC08";
5218 	case DPP_AKM_PSK_SAE_DPP:
5219 		return "506F9A02+000FAC08+000FAC02+000FAC06";
5220 	default:
5221 		return "??";
5222 	}
5223 }
5224 
5225 
dpp_akm_from_str(const char * akm)5226 static enum dpp_akm dpp_akm_from_str(const char *akm)
5227 {
5228 	const char *pos;
5229 	int dpp = 0, psk = 0, sae = 0;
5230 
5231 	if (os_strcmp(akm, "psk") == 0)
5232 		return DPP_AKM_PSK;
5233 	if (os_strcmp(akm, "sae") == 0)
5234 		return DPP_AKM_SAE;
5235 	if (os_strcmp(akm, "psk+sae") == 0)
5236 		return DPP_AKM_PSK_SAE;
5237 	if (os_strcmp(akm, "dpp") == 0)
5238 		return DPP_AKM_DPP;
5239 	if (os_strcmp(akm, "dpp+sae") == 0)
5240 		return DPP_AKM_SAE_DPP;
5241 	if (os_strcmp(akm, "dpp+psk+sae") == 0)
5242 		return DPP_AKM_PSK_SAE_DPP;
5243 
5244 	pos = akm;
5245 	while (*pos) {
5246 		if (os_strlen(pos) < 8)
5247 			break;
5248 		if (os_strncasecmp(pos, "506F9A02", 8) == 0)
5249 			dpp = 1;
5250 		else if (os_strncasecmp(pos, "000FAC02", 8) == 0)
5251 			psk = 1;
5252 		else if (os_strncasecmp(pos, "000FAC06", 8) == 0)
5253 			psk = 1;
5254 		else if (os_strncasecmp(pos, "000FAC08", 8) == 0)
5255 			sae = 1;
5256 		pos += 8;
5257 		if (*pos != '+')
5258 			break;
5259 		pos++;
5260 	}
5261 
5262 	if (dpp && psk && sae)
5263 		return DPP_AKM_PSK_SAE_DPP;
5264 	if (dpp && sae)
5265 		return DPP_AKM_SAE_DPP;
5266 	if (dpp)
5267 		return DPP_AKM_DPP;
5268 	if (psk && sae)
5269 		return DPP_AKM_PSK_SAE;
5270 	if (sae)
5271 		return DPP_AKM_SAE;
5272 	if (psk)
5273 		return DPP_AKM_PSK;
5274 
5275 	return DPP_AKM_UNKNOWN;
5276 }
5277 
5278 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)5279 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
5280 			      const u8 *conf_obj, u16 conf_obj_len)
5281 {
5282 	int ret = -1;
5283 	struct json_token *root, *token, *discovery, *cred;
5284 	struct dpp_config_obj *conf;
5285 	struct wpabuf *ssid64 = NULL;
5286 
5287 	root = json_parse((const char *) conf_obj, conf_obj_len);
5288 	if (!root)
5289 		return -1;
5290 	if (root->type != JSON_OBJECT) {
5291 		dpp_auth_fail(auth, "JSON root is not an object");
5292 		goto fail;
5293 	}
5294 
5295 	token = json_get_member(root, "wi-fi_tech");
5296 	if (!token || token->type != JSON_STRING) {
5297 		dpp_auth_fail(auth, "No wi-fi_tech string value found");
5298 		goto fail;
5299 	}
5300 	if (os_strcmp(token->string, "infra") != 0) {
5301 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
5302 			   token->string);
5303 		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
5304 		goto fail;
5305 	}
5306 
5307 	discovery = json_get_member(root, "discovery");
5308 	if (!discovery || discovery->type != JSON_OBJECT) {
5309 		dpp_auth_fail(auth, "No discovery object in JSON");
5310 		goto fail;
5311 	}
5312 
5313 	ssid64 = json_get_member_base64url(discovery, "ssid64");
5314 	if (ssid64) {
5315 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
5316 				  (u8 *)wpabuf_head(ssid64), wpabuf_len(ssid64));
5317 		if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
5318 			dpp_auth_fail(auth, "Too long discovery::ssid64 value");
5319 			goto fail;
5320 		}
5321 	} else {
5322 		token = json_get_member(discovery, "ssid");
5323 		if (!token || token->type != JSON_STRING) {
5324 			dpp_auth_fail(auth,
5325 				      "No discovery::ssid string value found");
5326 			goto fail;
5327 		}
5328 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
5329 				  (u8 *)token->string, os_strlen(token->string));
5330 		if (os_strlen(token->string) > SSID_MAX_LEN) {
5331 			dpp_auth_fail(auth,
5332 				      "Too long discovery::ssid string value");
5333 			goto fail;
5334 		}
5335 	}
5336 
5337 	if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
5338 		wpa_printf(MSG_DEBUG,
5339 			   "DPP: No room for this many Config Objects - ignore this one");
5340 		ret = 0;
5341 		goto fail;
5342 	}
5343 	conf = &auth->conf_obj[auth->num_conf_obj++];
5344 
5345 	if (ssid64) {
5346 		conf->ssid_len = wpabuf_len(ssid64);
5347 		os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
5348 	} else {
5349 		conf->ssid_len = os_strlen(token->string);
5350 		os_memcpy(conf->ssid, token->string, conf->ssid_len);
5351 	}
5352 
5353 	token = json_get_member(discovery, "ssid_charset");
5354 	if (token && token->type == JSON_NUMBER) {
5355 		conf->ssid_charset = token->number;
5356 		wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
5357 			   conf->ssid_charset);
5358 	}
5359 
5360 	cred = json_get_member(root, "cred");
5361 	if (!cred || cred->type != JSON_OBJECT) {
5362 		dpp_auth_fail(auth, "No cred object in JSON");
5363 		goto fail;
5364 	}
5365 
5366 	token = json_get_member(cred, "akm");
5367 	if (!token || token->type != JSON_STRING) {
5368 		dpp_auth_fail(auth, "No cred::akm string value found");
5369 		goto fail;
5370 	}
5371 	conf->akm = dpp_akm_from_str(token->string);
5372 
5373 	if (dpp_akm_legacy(conf->akm)) {
5374 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5375 			goto fail;
5376 	} else if (dpp_akm_dpp(conf->akm)) {
5377 		if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
5378 			goto fail;
5379 	} else {
5380 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
5381 			   token->string);
5382 		dpp_auth_fail(auth, "Unsupported akm");
5383 		goto fail;
5384 	}
5385 
5386 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
5387 	ret = 0;
5388 fail:
5389 	wpabuf_free(ssid64);
5390 	json_free(root);
5391 	return ret;
5392 }
5393 
5394 
dpp_conf_resp_rx(struct dpp_authentication * auth,const uint8_t * resp,uint32_t resp_len)5395 int dpp_conf_resp_rx(struct dpp_authentication *auth,
5396                      const uint8_t *resp, uint32_t resp_len)
5397 {
5398 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
5399 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
5400 	const u8 *addr[1];
5401 	size_t len[1];
5402 	u8 *unwrapped = NULL;
5403 	size_t unwrapped_len = 0;
5404 	int ret = -1;
5405 
5406 	auth->conf_resp_status = 255;
5407 
5408 	if (dpp_check_attrs(resp, resp_len) < 0) {
5409 		dpp_auth_fail(auth, "Invalid attribute in config response");
5410 		return -1;
5411 	}
5412 
5413 	wrapped_data = dpp_get_attr(resp, resp_len,
5414 				    DPP_ATTR_WRAPPED_DATA,
5415 				    &wrapped_data_len);
5416 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5417 		dpp_auth_fail(auth,
5418 			      "Missing or invalid required Wrapped Data attribute");
5419 		return -1;
5420 	}
5421 
5422 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5423 		    wrapped_data, wrapped_data_len);
5424 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5425 	unwrapped = os_malloc(unwrapped_len);
5426 	if (!unwrapped)
5427 		return -1;
5428 
5429 	addr[0] = resp;
5430 	len[0] = wrapped_data - 4 - resp;
5431 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
5432 
5433 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5434 			    wrapped_data, wrapped_data_len,
5435 			    1, addr, len, unwrapped) < 0) {
5436 		dpp_auth_fail(auth, "AES-SIV decryption failed");
5437 		goto fail;
5438 	}
5439 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5440 		    unwrapped, unwrapped_len);
5441 
5442 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5443 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5444 		goto fail;
5445 	}
5446 
5447 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5448 			       DPP_ATTR_ENROLLEE_NONCE,
5449 			       &e_nonce_len);
5450 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5451 		dpp_auth_fail(auth,
5452 			      "Missing or invalid Enrollee Nonce attribute");
5453 		goto fail;
5454 	}
5455 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5456 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
5457 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
5458 		goto fail;
5459 	}
5460 
5461 	status = dpp_get_attr(resp, resp_len,
5462 			      DPP_ATTR_STATUS, &status_len);
5463 	if (!status || status_len < 1) {
5464 		dpp_auth_fail(auth,
5465 			      "Missing or invalid required DPP Status attribute");
5466 		goto fail;
5467 	}
5468 	auth->conf_resp_status = status[0];
5469 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
5470 	if (status[0] != DPP_STATUS_OK) {
5471 		dpp_auth_fail(auth, "Configurator rejected configuration");
5472 		goto fail;
5473 	}
5474 
5475 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
5476 				&conf_obj_len);
5477 	if (!conf_obj) {
5478 		dpp_auth_fail(auth,
5479 			      "Missing required Configuration Object attribute");
5480 		goto fail;
5481 	}
5482 	while (conf_obj) {
5483 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
5484 				  (u8 *)conf_obj, conf_obj_len);
5485 		if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
5486 			goto fail;
5487 		conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
5488 					     DPP_ATTR_CONFIG_OBJ,
5489 					     &conf_obj_len);
5490 	}
5491 
5492 	ret = 0;
5493 
5494 fail:
5495 	os_free(unwrapped);
5496 	return ret;
5497 }
5498 
dpp_configurator_free(struct dpp_configurator * conf)5499 void dpp_configurator_free(struct dpp_configurator *conf)
5500 {
5501 	if (!conf)
5502 		return;
5503 	crypto_ec_free_key(conf->csign);
5504 	os_free(conf->kid);
5505 	os_free(conf);
5506 }
5507 
5508 
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)5509 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
5510 			     size_t buflen)
5511 {
5512 	int keylen, ret = -1;
5513 	unsigned char *key = NULL;
5514 
5515 	if (!conf->csign)
5516 		return ret;
5517 
5518 	crypto_ec_get_priv_key_der(conf->csign, &key, &keylen);
5519 
5520 	if (keylen > 0)
5521 		ret = wpa_snprintf_hex(buf, buflen, key, keylen);
5522 
5523 	crypto_free_buffer(key);
5524 
5525 	return ret;
5526 }
5527 
5528 
5529 struct dpp_configurator *
dpp_keygen_configurator(const char * curve,u8 * privkey,size_t privkey_len)5530 dpp_keygen_configurator(const char *curve, u8 *privkey,
5531 			size_t privkey_len)
5532 {
5533 	struct dpp_configurator *conf;
5534 	struct wpabuf *csign_pub = NULL;
5535 	u8 kid_hash[SHA256_MAC_LEN];
5536 	const u8 *addr[1];
5537 	size_t len[1];
5538 
5539 	conf = os_zalloc(sizeof(*conf));
5540 	if (!conf)
5541 		return NULL;
5542 
5543 	if (!curve) {
5544 		conf->curve = &dpp_curves[0];
5545 	} else {
5546 		conf->curve = dpp_get_curve_name(curve);
5547 		if (!conf->curve) {
5548 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5549 				   curve);
5550 			os_free(conf);
5551 			return NULL;
5552 		}
5553 	}
5554 	if (privkey)
5555 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
5556 					      privkey_len);
5557 	else
5558 		conf->csign = dpp_gen_keypair(conf->curve);
5559 	if (!conf->csign)
5560 		goto fail;
5561 	conf->own = 1;
5562 
5563 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
5564 	if (!csign_pub) {
5565 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
5566 		goto fail;
5567 	}
5568 
5569 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
5570 	addr[0] = wpabuf_head(csign_pub);
5571 	len[0] = wpabuf_len(csign_pub);
5572 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
5573 		wpa_printf(MSG_DEBUG,
5574 			   "DPP: Failed to derive kid for C-sign-key");
5575 		goto fail;
5576 	}
5577 
5578 	conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
5579 	if (!conf->kid)
5580 		goto fail;
5581 out:
5582 	wpabuf_free(csign_pub);
5583 	return conf;
5584 fail:
5585 	dpp_configurator_free(conf);
5586 	conf = NULL;
5587 	goto out;
5588 }
5589 
5590 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)5591 int dpp_configurator_own_config(struct dpp_authentication *auth,
5592 				const char *curve, int ap)
5593 {
5594 	struct wpabuf *conf_obj;
5595 	int ret = -1;
5596 
5597 	if (!auth->conf) {
5598 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
5599 		return -1;
5600 	}
5601 
5602 	if (!curve) {
5603 		auth->curve = &dpp_curves[0];
5604 	} else {
5605 		auth->curve = dpp_get_curve_name(curve);
5606 		if (!auth->curve) {
5607 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5608 				   curve);
5609 			return -1;
5610 		}
5611 	}
5612 	wpa_printf(MSG_DEBUG,
5613 		   "DPP: Building own configuration/connector with curve %s",
5614 		   auth->curve->name);
5615 
5616 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
5617 	if (!auth->own_protocol_key)
5618 		return -1;
5619 	dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
5620 	auth->peer_protocol_key = auth->own_protocol_key;
5621 	dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
5622 
5623 	conf_obj = dpp_build_conf_obj(auth, ap, 0);
5624 	if (!conf_obj) {
5625 		wpabuf_free(auth->conf_obj[0].c_sign_key);
5626 		auth->conf_obj[0].c_sign_key = NULL;
5627 		goto fail;
5628 	}
5629 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
5630 				 wpabuf_len(conf_obj));
5631 fail:
5632 	wpabuf_free(conf_obj);
5633 	auth->peer_protocol_key = NULL;
5634 	return ret;
5635 }
5636 
5637 
dpp_compatible_netrole(const char * role1,const char * role2)5638 static int dpp_compatible_netrole(const char *role1, const char *role2)
5639 {
5640 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
5641 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
5642 }
5643 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role)5644 static int dpp_connector_compatible_group(struct json_token *root,
5645 					  const char *group_id,
5646 					  const char *net_role)
5647 {
5648 	struct json_token *groups, *token;
5649 
5650 	groups = json_get_member(root, "groups");
5651 	if (!groups || groups->type != JSON_ARRAY)
5652 		return 0;
5653 
5654 	for (token = groups->child; token; token = token->sibling) {
5655 		struct json_token *id, *role;
5656 
5657 		id = json_get_member(token, "groupId");
5658 		if (!id || id->type != JSON_STRING)
5659 			continue;
5660 
5661 		role = json_get_member(token, "netRole");
5662 		if (!role || role->type != JSON_STRING)
5663 			continue;
5664 
5665 		if (os_strcmp(id->string, "*") != 0 &&
5666 		    os_strcmp(group_id, "*") != 0 &&
5667 		    os_strcmp(id->string, group_id) != 0)
5668 			continue;
5669 
5670 		if (dpp_compatible_netrole(role->string, net_role))
5671 			return 1;
5672 	}
5673 
5674 	return 0;
5675 }
5676 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root)5677 static int dpp_connector_match_groups(struct json_token *own_root,
5678 				      struct json_token *peer_root)
5679 {
5680 	struct json_token *groups, *token;
5681 
5682 	groups = json_get_member(peer_root, "groups");
5683 	if (!groups || groups->type != JSON_ARRAY) {
5684 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
5685 		return 0;
5686 	}
5687 
5688 	for (token = groups->child; token; token = token->sibling) {
5689 		struct json_token *id, *role;
5690 
5691 		id = json_get_member(token, "groupId");
5692 		if (!id || id->type != JSON_STRING) {
5693 			wpa_printf(MSG_DEBUG,
5694 				   "DPP: Missing peer groupId string");
5695 			continue;
5696 		}
5697 
5698 		role = json_get_member(token, "netRole");
5699 		if (!role || role->type != JSON_STRING) {
5700 			wpa_printf(MSG_DEBUG,
5701 				   "DPP: Missing peer groups::netRole string");
5702 			continue;
5703 		}
5704 		wpa_printf(MSG_DEBUG,
5705 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
5706 			   id->string, role->string);
5707 		if (dpp_connector_compatible_group(own_root, id->string,
5708 						   role->string)) {
5709 			wpa_printf(MSG_DEBUG,
5710 				   "DPP: Compatible group/netRole in own connector");
5711 			return 1;
5712 		}
5713 	}
5714 
5715 	return 0;
5716 }
5717 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)5718 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
5719 			  unsigned int hash_len)
5720 {
5721 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
5722 	const char *info = "DPP PMK";
5723 	int res;
5724 
5725 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5726 
5727 	/* HKDF-Extract(<>, N.x) */
5728 	os_memset(salt, 0, hash_len);
5729 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
5730 		return -1;
5731 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
5732 			prk, hash_len);
5733 
5734 	/* HKDF-Expand(PRK, info, L) */
5735 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
5736 	forced_memzero(prk, hash_len);
5737 	if (res < 0)
5738 		return -1;
5739 
5740 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
5741 			pmk, hash_len);
5742 	return 0;
5743 }
5744 
5745 
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_key * own_key,struct crypto_key * peer_key,u8 * pmkid)5746 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
5747 			    struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid)
5748 {
5749 	struct wpabuf *nkx, *pkx;
5750 	int ret = -1, res;
5751 	const u8 *addr[2];
5752 	size_t len[2];
5753 	u8 hash[SHA256_MAC_LEN];
5754 
5755 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5756 	nkx = dpp_get_pubkey_point(own_key, 0);
5757 	pkx = dpp_get_pubkey_point(peer_key, 0);
5758 	if (!nkx || !pkx)
5759 		goto fail;
5760 	addr[0] = wpabuf_head(nkx);
5761 	len[0] = wpabuf_len(nkx) / 2;
5762 	addr[1] = wpabuf_head(pkx);
5763 	len[1] = wpabuf_len(pkx) / 2;
5764 	if (len[0] != len[1])
5765 		goto fail;
5766 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
5767 		addr[0] = wpabuf_head(pkx);
5768 		addr[1] = wpabuf_head(nkx);
5769 	}
5770 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
5771 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
5772 	res = sha256_vector(2, addr, len, hash);
5773 	if (res < 0)
5774 		goto fail;
5775 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
5776 	os_memcpy(pmkid, hash, PMKID_LEN);
5777 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
5778 	ret = 0;
5779 fail:
5780 	wpabuf_free(nkx);
5781 	wpabuf_free(pkx);
5782 	return ret;
5783 }
5784 
5785 
5786 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)5787 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
5788 	       const u8 *net_access_key, size_t net_access_key_len,
5789 	       const u8 *csign_key, size_t csign_key_len,
5790 	       const u8 *peer_connector, size_t peer_connector_len,
5791 	       os_time_t *expiry)
5792 {
5793 	struct json_token *root = NULL, *netkey, *token;
5794 	struct json_token *own_root = NULL;
5795 	enum dpp_status_error ret = 255, res;
5796 	struct crypto_key *own_key = NULL, *peer_key = NULL;
5797 	struct wpabuf *own_key_pub = NULL;
5798 	const struct dpp_curve_params *curve, *own_curve;
5799 	struct dpp_signed_connector_info info;
5800 	const unsigned char *p;
5801 	struct crypto_key *csign = NULL;
5802 	char *signed_connector = NULL;
5803 	const char *pos, *end;
5804 	unsigned char *own_conn = NULL;
5805 	size_t own_conn_len;
5806 	size_t Nx_len;
5807 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
5808 
5809 	os_memset(intro, 0, sizeof(*intro));
5810 	os_memset(&info, 0, sizeof(info));
5811 	if (expiry)
5812 		*expiry = 0;
5813 
5814 	p = csign_key;
5815 	csign = crypto_ec_parse_subpub_key(p, csign_key_len);
5816 	if (!csign) {
5817 		wpa_printf(MSG_ERROR,
5818 			   "DPP: Failed to parse local C-sign-key information");
5819 		goto fail;
5820 	}
5821 
5822 	own_key = dpp_set_keypair(&own_curve, net_access_key,
5823 				  net_access_key_len);
5824 	if (!own_key) {
5825 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
5826 		goto fail;
5827 	}
5828 
5829 	pos = os_strchr(own_connector, '.');
5830 	if (!pos) {
5831 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
5832 		goto fail;
5833 	}
5834 	pos++;
5835 	end = os_strchr(pos, '.');
5836 	if (!end) {
5837 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
5838 		goto fail;
5839 	}
5840 	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
5841 	if (!own_conn) {
5842 		wpa_printf(MSG_DEBUG,
5843 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
5844 		goto fail;
5845 	}
5846 
5847 	own_root = json_parse((const char *) own_conn, own_conn_len);
5848 	if (!own_root) {
5849 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
5850 		goto fail;
5851 	}
5852 
5853 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
5854 			  (u8 *)peer_connector, peer_connector_len);
5855 	signed_connector = os_malloc(peer_connector_len + 1);
5856 	if (!signed_connector)
5857 		goto fail;
5858 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
5859 	signed_connector[peer_connector_len] = '\0';
5860 
5861 	res = dpp_process_signed_connector(&info, csign, signed_connector);
5862 	if (res != DPP_STATUS_OK) {
5863 		ret = res;
5864 		goto fail;
5865 	}
5866 
5867 	root = json_parse((const char *) info.payload, info.payload_len);
5868 	if (!root) {
5869 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
5870 		ret = DPP_STATUS_INVALID_CONNECTOR;
5871 		goto fail;
5872 	}
5873 
5874 	if (!dpp_connector_match_groups(own_root, root)) {
5875 		wpa_printf(MSG_DEBUG,
5876 			   "DPP: Peer connector does not include compatible group netrole with own connector");
5877 		ret = DPP_STATUS_NO_MATCH;
5878 		goto fail;
5879 	}
5880 
5881 	token = json_get_member(root, "expiry");
5882 	if (!token || token->type != JSON_STRING) {
5883 		wpa_printf(MSG_DEBUG,
5884 			   "DPP: No expiry string found - connector does not expire");
5885 	} else {
5886 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
5887 		if (dpp_key_expired(token->string, expiry)) {
5888 			wpa_printf(MSG_DEBUG,
5889 				   "DPP: Connector (netAccessKey) has expired");
5890 			ret = DPP_STATUS_INVALID_CONNECTOR;
5891 			goto fail;
5892 		}
5893 	}
5894 
5895 	netkey = json_get_member(root, "netAccessKey");
5896 	if (!netkey || netkey->type != JSON_OBJECT) {
5897 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
5898 		ret = DPP_STATUS_INVALID_CONNECTOR;
5899 		goto fail;
5900 	}
5901 
5902 	peer_key = dpp_parse_jwk(netkey, &curve);
5903 	if (!peer_key) {
5904 		ret = DPP_STATUS_INVALID_CONNECTOR;
5905 		goto fail;
5906 	}
5907 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
5908 
5909 	if (own_curve != curve) {
5910 		wpa_printf(MSG_DEBUG,
5911 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
5912 			   own_curve->name, curve->name);
5913 		ret = DPP_STATUS_INVALID_CONNECTOR;
5914 		goto fail;
5915 	}
5916 
5917 	/* ECDH: N = nk * PK */
5918 	if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
5919 		goto fail;
5920 
5921 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
5922 			Nx, Nx_len);
5923 
5924 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5925 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
5926 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
5927 		goto fail;
5928 	}
5929 	intro->pmk_len = curve->hash_len;
5930 
5931 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5932 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
5933 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
5934 		goto fail;
5935 	}
5936 
5937 	ret = DPP_STATUS_OK;
5938 fail:
5939 	if (ret != DPP_STATUS_OK)
5940 		os_memset(intro, 0, sizeof(*intro));
5941 	forced_memzero(Nx, sizeof(Nx));
5942 	os_free(own_conn);
5943 	os_free(signed_connector);
5944 	os_free(info.payload);
5945 	crypto_ec_free_key(own_key);
5946 	wpabuf_free(own_key_pub);
5947 	crypto_ec_free_key(peer_key);
5948 	crypto_ec_free_key(csign);
5949 	json_free(root);
5950 	json_free(own_root);
5951 	return ret;
5952 }
5953 
5954 #ifdef CONFIG_TESTING_OPTIONS
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)5955 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
5956 				    const struct dpp_curve_params *curve)
5957 {
5958 	return 0;
5959 }
5960 
dpp_corrupt_connector_signature(const char * connector)5961 char * dpp_corrupt_connector_signature(const char *connector)
5962 {
5963 	char *tmp, *pos, *signed3 = NULL;
5964 	unsigned char *signature = NULL;
5965 	size_t signature_len = 0, signed3_len;
5966 
5967 	tmp = os_zalloc(os_strlen(connector) + 5);
5968 	if (!tmp)
5969 		goto fail;
5970 	os_memcpy(tmp, connector, os_strlen(connector));
5971 
5972 	pos = os_strchr(tmp, '.');
5973 	if (!pos)
5974 		goto fail;
5975 
5976 	pos = os_strchr(pos + 1, '.');
5977 	if (!pos)
5978 		goto fail;
5979 	pos++;
5980 
5981 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
5982 		   pos);
5983 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5984 	if (!signature || signature_len == 0)
5985 		goto fail;
5986 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
5987 		    signature, signature_len);
5988 	signature[signature_len - 1] ^= 0x01;
5989 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
5990 		    signature, signature_len);
5991 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
5992 	if (!signed3)
5993 		goto fail;
5994 	os_memcpy(pos, signed3, signed3_len);
5995 	pos[signed3_len] = '\0';
5996 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
5997 		   pos);
5998 
5999 out:
6000 	os_free(signature);
6001 	os_free(signed3);
6002 	return tmp;
6003 fail:
6004 	os_free(tmp);
6005 	tmp = NULL;
6006 	goto out;
6007 }
6008 #endif /* CONFIG_TESTING_OPTIONS */
6009 
dpp_next_id(struct dpp_global * dpp)6010 static unsigned int dpp_next_id(struct dpp_global *dpp)
6011 {
6012 	struct dpp_bootstrap_info *bi;
6013 	unsigned int max_id = 0;
6014 
6015 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6016 		if (bi->id > max_id)
6017 			max_id = bi->id;
6018 	}
6019 	return max_id + 1;
6020 }
6021 
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)6022 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
6023 {
6024 	struct dpp_bootstrap_info *bi, *tmp;
6025 	int found = 0;
6026 
6027 	if (!dpp)
6028 		return -1;
6029 
6030 	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
6031 			      struct dpp_bootstrap_info, list) {
6032 		if (id && bi->id != id)
6033 			continue;
6034 		found = 1;
6035 		dl_list_del(&bi->list);
6036 		dpp_bootstrap_info_free(bi);
6037 	}
6038 
6039 	if (id == 0)
6040 		return 0; /* flush succeeds regardless of entries found */
6041 	return found ? 0 : -1;
6042 }
6043 
6044 
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)6045 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
6046 					    const char *uri)
6047 {
6048 	struct dpp_bootstrap_info *bi;
6049 
6050 	if (!dpp)
6051 		return NULL;
6052 
6053 	bi = dpp_parse_uri(uri);
6054 	if (!bi)
6055 		return NULL;
6056 
6057 	bi->type = DPP_BOOTSTRAP_QR_CODE;
6058 	bi->id = dpp_next_id(dpp);
6059 	dl_list_add(&dpp->bootstrap, &bi->list);
6060 	return bi;
6061 }
6062 
6063 
dpp_add_nfc_uri(struct dpp_global * dpp,const char * uri)6064 struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
6065 					    const char *uri)
6066 {
6067 	struct dpp_bootstrap_info *bi;
6068 
6069 	if (!dpp)
6070 		return NULL;
6071 
6072 	bi = dpp_parse_uri(uri);
6073 	if (!bi)
6074 		return NULL;
6075 
6076 	bi->type = DPP_BOOTSTRAP_NFC_URI;
6077 	bi->id = dpp_next_id(dpp);
6078 	dl_list_add(&dpp->bootstrap, &bi->list);
6079 	return bi;
6080 }
6081 
6082 
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)6083 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
6084 {
6085 	char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
6086 	char *key = NULL;
6087 	u8 *privkey = NULL;
6088 	size_t privkey_len = 0;
6089 	size_t len;
6090 	int ret = -1;
6091 	struct dpp_bootstrap_info *bi;
6092 
6093 	bi = os_zalloc(sizeof(*bi));
6094 	if (!bi)
6095 		goto fail;
6096 
6097 	if (os_strstr(cmd, "type=qrcode"))
6098 		bi->type = DPP_BOOTSTRAP_QR_CODE;
6099 	else if (os_strstr(cmd, "type=pkex"))
6100 		bi->type = DPP_BOOTSTRAP_PKEX;
6101 	else if (os_strstr(cmd, "type=nfc-uri"))
6102 		bi->type = DPP_BOOTSTRAP_NFC_URI;
6103 	else
6104 		goto fail;
6105 
6106 	chan = get_param(cmd, " chan=");
6107 	mac = get_param(cmd, " mac=");
6108 	info = get_param(cmd, " info=");
6109 	curve = get_param(cmd, " curve=");
6110 	key = get_param(cmd, " key=");
6111 
6112 	if (key) {
6113 		privkey_len = os_strlen(key) / 2;
6114 		privkey = os_malloc(privkey_len);
6115 		if (!privkey ||
6116 		    hexstr2bin(key, privkey, privkey_len) < 0)
6117 			goto fail;
6118 	}
6119 	wpa_hexdump(MSG_DEBUG, "private key", privkey, privkey_len);
6120 
6121 	pk = dpp_keygen(bi, curve, privkey, privkey_len);
6122 	if (!pk)
6123 		goto fail;
6124 
6125 	len = 4; /* "DPP:" */
6126 	if (chan) {
6127 		if (dpp_parse_uri_chan_list(bi, chan) < 0)
6128 			goto fail;
6129 		len += 3 + os_strlen(chan); /* C:...; */
6130 	}
6131 	if (mac) {
6132 		if (dpp_parse_uri_mac(bi, mac) < 0)
6133 			goto fail;
6134 		len += 3 + os_strlen(mac); /* M:...; */
6135 	}
6136 	if (info) {
6137 		if (dpp_parse_uri_info(bi, info) < 0)
6138 			goto fail;
6139 		len += 3 + os_strlen(info); /* I:...; */
6140 	}
6141 	len += 4 + os_strlen(pk);
6142 	bi->uri = os_malloc(len + 1);
6143 	if (!bi->uri)
6144 		goto fail;
6145 	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
6146 		    chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
6147 		    mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
6148 		    info ? "I:" : "", info ? info : "", info ? ";" : "",
6149 		    pk);
6150 
6151 	bi->id = dpp_next_id(dpp);
6152 	dl_list_add(&dpp->bootstrap, &bi->list);
6153 	ret = bi->id;
6154 	bi = NULL;
6155 fail:
6156 	os_free(curve);
6157 	os_free(pk);
6158 	os_free(chan);
6159 	os_free(mac);
6160 	os_free(info);
6161 	str_clear_free(key);
6162 	bin_clear_free(privkey, privkey_len);
6163 	dpp_bootstrap_info_free(bi);
6164 	return ret;
6165 }
6166 
6167 
6168 struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)6169 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
6170 {
6171 	struct dpp_bootstrap_info *bi;
6172 
6173 	if (!dpp)
6174 		return NULL;
6175 
6176 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6177 		if (bi->id == id)
6178 			return bi;
6179 	}
6180 	return NULL;
6181 }
6182 
6183 
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)6184 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
6185 {
6186 	unsigned int id_val;
6187 
6188 	if (os_strcmp(id, "*") == 0) {
6189 		id_val = 0;
6190 	} else {
6191 		id_val = atoi(id);
6192 		if (id_val == 0)
6193 			return -1;
6194 	}
6195 
6196 	return dpp_bootstrap_del(dpp, id_val);
6197 }
6198 
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)6199 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
6200 {
6201 	struct dpp_bootstrap_info *bi;
6202 
6203 	bi = dpp_bootstrap_get_id(dpp, id);
6204 	if (!bi)
6205 		return NULL;
6206 	return bi->uri;
6207 }
6208 
dpp_get_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)6209 int dpp_get_bootstrap_info(struct dpp_global *dpp, int id,
6210 		       char *reply, int reply_size)
6211 {
6212 	struct dpp_bootstrap_info *bi;
6213 	char pkhash[2 * SHA256_MAC_LEN + 1];
6214 
6215 	bi = dpp_bootstrap_get_id(dpp, id);
6216 	if (!bi)
6217 		return -1;
6218 	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
6219 			 SHA256_MAC_LEN);
6220 	return os_snprintf(reply, reply_size, "type=%s\n"
6221 			   "mac_addr=" MACSTR "\n"
6222 			   "info=%s\n"
6223 			   "num_freq=%u\n"
6224 			   "curve=%s\n"
6225 			   "pkhash=%s\n",
6226 			   dpp_bootstrap_type_txt(bi->type),
6227 			   MAC2STR(bi->mac_addr),
6228 			   bi->info ? bi->info : "",
6229 			   bi->num_freq,
6230 			   bi->curve->name,
6231 			   pkhash);
6232 }
6233 
6234 
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)6235 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
6236 			     const u8 *r_bootstrap,
6237 			     struct dpp_bootstrap_info **own_bi,
6238 			     struct dpp_bootstrap_info **peer_bi)
6239 {
6240 	struct dpp_bootstrap_info *bi;
6241 
6242 	*own_bi = NULL;
6243 	*peer_bi = NULL;
6244 	if (!dpp)
6245 		return;
6246 
6247 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6248 		if (!*own_bi && bi->own &&
6249 		    os_memcmp(bi->pubkey_hash, r_bootstrap,
6250 			      SHA256_MAC_LEN) == 0) {
6251 			wpa_printf(MSG_DEBUG,
6252 				   "DPP: Found matching own bootstrapping information");
6253 			*own_bi = bi;
6254 		}
6255 
6256 		if (!*peer_bi && !bi->own &&
6257 		    os_memcmp(bi->pubkey_hash, i_bootstrap,
6258 			      SHA256_MAC_LEN) == 0) {
6259 			wpa_printf(MSG_DEBUG,
6260 				   "DPP: Found matching peer bootstrapping information");
6261 			*peer_bi = bi;
6262 		}
6263 
6264 		if (*own_bi && *peer_bi)
6265 			break;
6266 	}
6267 
6268 }
6269 
6270 
dpp_next_configurator_id(struct dpp_global * dpp)6271 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
6272 {
6273 	struct dpp_configurator *conf;
6274 	unsigned int max_id = 0;
6275 
6276 	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
6277 			 list) {
6278 		if (conf->id > max_id)
6279 			max_id = conf->id;
6280 	}
6281 	return max_id + 1;
6282 }
6283 
6284 
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)6285 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
6286 {
6287 	char *curve = NULL;
6288 	char *key = NULL;
6289 	u8 *privkey = NULL;
6290 	size_t privkey_len = 0;
6291 	int ret = -1;
6292 	struct dpp_configurator *conf = NULL;
6293 
6294 	curve = get_param(cmd, " curve=");
6295 	key = get_param(cmd, " key=");
6296 
6297 	if (key) {
6298 		privkey_len = os_strlen(key) / 2;
6299 		privkey = os_malloc(privkey_len);
6300 		if (!privkey ||
6301 		    hexstr2bin(key, privkey, privkey_len) < 0)
6302 			goto fail;
6303 	}
6304 
6305 	conf = dpp_keygen_configurator(curve, privkey, privkey_len);
6306 	if (!conf)
6307 		goto fail;
6308 
6309 	conf->id = dpp_next_configurator_id(dpp);
6310 	dl_list_add(&dpp->configurator, &conf->list);
6311 	ret = conf->id;
6312 	conf = NULL;
6313 fail:
6314 	os_free(curve);
6315 	str_clear_free(key);
6316 	bin_clear_free(privkey, privkey_len);
6317 	dpp_configurator_free(conf);
6318 	return ret;
6319 }
6320 
6321 
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)6322 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
6323 {
6324 	struct dpp_configurator *conf, *tmp;
6325 	int found = 0;
6326 
6327 	if (!dpp)
6328 		return -1;
6329 
6330 	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
6331 			      struct dpp_configurator, list) {
6332 		if (id && conf->id != id)
6333 			continue;
6334 		found = 1;
6335 		dl_list_del(&conf->list);
6336 		dpp_configurator_free(conf);
6337 	}
6338 
6339 	if (id == 0)
6340 		return 0; /* flush succeeds regardless of entries found */
6341 	return found ? 0 : -1;
6342 }
6343 
6344 
dpp_configurator_remove(struct dpp_global * dpp,const char * id)6345 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
6346 {
6347 	unsigned int id_val;
6348 
6349 	if (os_strcmp(id, "*") == 0) {
6350 		id_val = 0;
6351 	} else {
6352 		id_val = atoi(id);
6353 		if (id_val == 0)
6354 			return -1;
6355 	}
6356 
6357 	return dpp_configurator_del(dpp, id_val);
6358 }
6359 
6360 
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)6361 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
6362 				char *buf, size_t buflen)
6363 {
6364 	struct dpp_configurator *conf;
6365 
6366 	conf = dpp_configurator_get_id(dpp, id);
6367 	if (!conf)
6368 		return -1;
6369 
6370 	return dpp_configurator_get_key(conf, buf, buflen);
6371 }
6372 
dpp_global_init(struct dpp_global_config * config)6373 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
6374 {
6375 	struct dpp_global *dpp;
6376 
6377 	dpp = os_zalloc(sizeof(*dpp));
6378 	if (!dpp)
6379 		return NULL;
6380 	dpp->msg_ctx = config->msg_ctx;
6381 
6382 	dl_list_init(&dpp->bootstrap);
6383 	dl_list_init(&dpp->configurator);
6384 
6385 	return dpp;
6386 }
6387 
6388 
dpp_global_clear(struct dpp_global * dpp)6389 void dpp_global_clear(struct dpp_global *dpp)
6390 {
6391 	if (!dpp)
6392 		return;
6393 
6394 	dpp_bootstrap_del(dpp, 0);
6395 	dpp_configurator_del(dpp, 0);
6396 }
6397 
6398 
dpp_global_deinit(struct dpp_global * dpp)6399 void dpp_global_deinit(struct dpp_global *dpp)
6400 {
6401 	dpp_global_clear(dpp);
6402 	os_free(dpp);
6403 }
6404