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 	{ "sec256r1", 32, 32, 16, 32, "P-256", 19, "ES256" },
47 	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
48 	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
49 	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
50 	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
51 	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
52 	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
53 };
54 
55 static struct wpabuf *
gas_build_req(u8 action,u8 dialog_token,size_t size)56 gas_build_req(u8 action, u8 dialog_token, size_t size)
57 {
58     struct wpabuf *buf;
59 
60     buf = wpabuf_alloc(100 + size);
61     if (buf == NULL)
62         return NULL;
63 
64     wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
65     wpabuf_put_u8(buf, action);
66     wpabuf_put_u8(buf, dialog_token);
67 
68     return buf;
69 }
70 
71 
gas_build_initial_req(u8 dialog_token,size_t size)72 struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
73 {
74     return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
75                  size);
76 }
77 
dpp_debug_print_key(const char * title,struct crypto_key * key)78 static void dpp_debug_print_key(const char *title, struct crypto_key *key)
79 {
80     crypto_debug_print_ec_key(title, key);
81 }
82 
dpp_debug_print_point(const char * title,struct crypto_ec * e,const struct crypto_ec_point * point)83 void dpp_debug_print_point(const char *title, struct crypto_ec *e,
84 				  const struct crypto_ec_point *point)
85 {
86 	u8 x[64], y[64];
87 
88 	if (crypto_ec_point_to_bin(e, point, x, y) < 0) {
89 		printf("error: failed to get corrdinates\n");
90 		return;
91 	}
92 
93 	wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x, y);
94 }
95 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)96 static int dpp_hash_vector(const struct dpp_curve_params *curve,
97 			   size_t num_elem, const u8 *addr[], const size_t *len,
98 			   u8 *mac)
99 {
100 	if (curve->hash_len == 32)
101 		return sha256_vector(num_elem, addr, len, mac);
102 #ifndef ESP_SUPPLICANT
103 	if (curve->hash_len == 48)
104 		return sha384_vector(num_elem, addr, len, mac);
105 	if (curve->hash_len == 64)
106 		return sha512_vector(num_elem, addr, len, mac);
107 #endif
108 	return -1;
109 }
110 
111 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)112 static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
113 			   const char *label, u8 *out, size_t outlen)
114 {
115 	if (hash_len == 32)
116 		return hmac_sha256_kdf(secret, secret_len, NULL,
117 				       (const u8 *) label, os_strlen(label),
118 				       out, outlen);
119 #ifndef ESP_SUPPLICANT
120 	if (hash_len == 48)
121 		return hmac_sha384_kdf(secret, secret_len, NULL,
122 				       (const u8 *) label, os_strlen(label),
123 				       out, outlen);
124 	if (hash_len == 64)
125 		return hmac_sha512_kdf(secret, secret_len, NULL,
126 				       (const u8 *) label, os_strlen(label),
127 				       out, outlen);
128 #endif
129 	return -1;
130 }
131 
132 
dpp_hmac_vector(size_t hash_len,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)133 static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
134 			   size_t num_elem, const u8 *addr[],
135 			   const size_t *len, u8 *mac)
136 {
137 	if (hash_len == 32)
138 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
139 					  mac);
140 #ifndef ESP_SUPPLICANT
141 	if (hash_len == 48)
142 		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
143 					  mac);
144 	if (hash_len == 64)
145 		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
146 					  mac);
147 #endif
148 	return -1;
149 }
150 
151 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)152 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
153 		    const u8 *data, size_t data_len, u8 *mac)
154 {
155 	if (hash_len == 32)
156 		return hmac_sha256(key, key_len, data, data_len, mac);
157 #ifndef ESP_SUPPLICANT
158 	if (hash_len == 48)
159 		return hmac_sha384(key, key_len, data, data_len, mac);
160 	if (hash_len == 64)
161 		return hmac_sha512(key, key_len, data, data_len, mac);
162 #endif
163 	return -1;
164 }
165 
166 
dpp_bn2bin_pad(const struct crypto_bignum * bn,u8 * pos,size_t len)167 static int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len)
168 {
169 	if (crypto_bignum_to_bin(bn, pos, len, 0) < 0)
170 		return -1;
171 
172 	return 0;
173 }
174 
dpp_get_pubkey_point(struct crypto_key * pkey,int prefix)175 static struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix)
176 {
177 	int len, res;
178 	struct wpabuf *buf;
179 	unsigned char *pos = NULL;
180 
181 	len = crypto_ec_get_publickey_buf(pkey, pos, 0);
182 	if (len <= 0) {
183 		wpa_printf(MSG_ERROR,
184 			   "DDP: Failed to determine public key encoding length");
185 		return NULL;
186 	}
187 
188 	buf = wpabuf_alloc(len);
189 	if (!buf) {
190 		return NULL;
191 	}
192 
193 	pos = wpabuf_put(buf, len);
194 
195 	res = crypto_ec_get_publickey_buf(pkey, pos, len);
196 	if (res != len) {
197 		wpa_printf(MSG_ERROR,
198 			   "DDP: Failed to encode public key (res=%d/%d)",
199 			   res, len);
200 		wpabuf_free(buf);
201 		return NULL;
202 	}
203 
204 	if (!prefix) {
205 		/* Remove 0x04 prefix to match DPP definition */
206 		pos = wpabuf_mhead(buf);
207 		os_memmove(pos, pos + 1, len - 1);
208 		buf->used--;
209 	}
210 
211 	return buf;
212 }
213 
dpp_set_pubkey_point(struct crypto_key * group_key,const u8 * buf,size_t len)214 static struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key,
215 				       const u8 *buf, size_t len)
216 {
217 	const struct crypto_ec_group *group;
218 	struct crypto_key *pkey = NULL;
219 
220 	if (len & 1)
221 		return NULL;
222 
223 	group = crypto_ec_get_group_from_key(group_key);
224 	if (group)
225 		pkey = crypto_ec_set_pubkey_point(group, buf,
226 						  len);
227 	else
228 		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
229 
230 	return pkey;
231 }
232 
dpp_ecdh(struct crypto_key * own,struct crypto_key * peer,u8 * secret,size_t * secret_len)233 static int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer,
234 		    u8 *secret, size_t *secret_len)
235 {
236     return crypto_ecdh(own, peer, secret, secret_len);
237 }
238 
239 
dpp_auth_fail(struct dpp_authentication * auth,const char * txt)240 static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
241 {
242 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
243 }
244 
245 
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)246 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
247 			      size_t len)
248 {
249 	struct wpabuf *msg;
250 
251 	msg = wpabuf_alloc(8 + len);
252 	if (!msg)
253 		return NULL;
254 	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
255 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
256 	wpabuf_put_be24(msg, OUI_WFA);
257 	wpabuf_put_u8(msg, DPP_OUI_TYPE);
258 	wpabuf_put_u8(msg, 1); /* Crypto Suite */
259 	wpabuf_put_u8(msg, type);
260 	return msg;
261 }
262 
263 
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)264 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
265 {
266 	u16 id, alen;
267 	const u8 *pos = buf, *end = buf + len;
268 
269 	while (end - pos >= 4) {
270 		id = WPA_GET_LE16(pos);
271 		pos += 2;
272 		alen = WPA_GET_LE16(pos);
273 		pos += 2;
274 		if (alen > end - pos)
275 			return NULL;
276 		if (id == req_id) {
277 			*ret_len = alen;
278 			return pos;
279 		}
280 		pos += alen;
281 	}
282 
283 	return NULL;
284 }
285 
286 
dpp_get_attr_next(const u8 * prev,const u8 * buf,size_t len,u16 req_id,u16 * ret_len)287 static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len,
288 				    u16 req_id, u16 *ret_len)
289 {
290 	u16 id, alen;
291 	const u8 *pos, *end = buf + len;
292 
293 	if (!prev)
294 		pos = buf;
295 	else
296 		pos = prev + WPA_GET_LE16(prev - 2);
297 	while (end - pos >= 4) {
298 		id = WPA_GET_LE16(pos);
299 		pos += 2;
300 		alen = WPA_GET_LE16(pos);
301 		pos += 2;
302 		if (alen > end - pos)
303 			return NULL;
304 		if (id == req_id) {
305 			*ret_len = alen;
306 			return pos;
307 		}
308 		pos += alen;
309 	}
310 
311 	return NULL;
312 }
313 
314 
dpp_check_attrs(const u8 * buf,size_t len)315 int dpp_check_attrs(const u8 *buf, size_t len)
316 {
317 	const u8 *pos, *end;
318 	int wrapped_data = 0;
319 
320 	pos = buf;
321 	end = buf + len;
322 	while (end - pos >= 4) {
323 		u16 id, alen;
324 
325 		id = WPA_GET_LE16(pos);
326 		pos += 2;
327 		alen = WPA_GET_LE16(pos);
328 		pos += 2;
329 		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
330 			   id, alen);
331 		if (alen > end - pos) {
332 			wpa_printf(MSG_DEBUG,
333 				   "DPP: Truncated message - not enough room for the attribute - dropped");
334 			return -1;
335 		}
336 		if (wrapped_data) {
337 			wpa_printf(MSG_DEBUG,
338 				   "DPP: An unexpected attribute included after the Wrapped Data attribute");
339 			return -1;
340 		}
341 		if (id == DPP_ATTR_WRAPPED_DATA)
342 			wrapped_data = 1;
343 		pos += alen;
344 	}
345 
346 	if (end != pos) {
347 		wpa_printf(MSG_DEBUG,
348 			   "DPP: Unexpected octets (%d) after the last attribute",
349 			   (int) (end - pos));
350 		return -1;
351 	}
352 
353 	return 0;
354 }
355 
356 
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)357 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
358 {
359 	if (!info)
360 		return;
361 	os_free(info->uri);
362 	os_free(info->info);
363 	crypto_ec_free_key(info->pubkey);
364 	os_free(info);
365 }
366 
367 
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)368 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
369 {
370 	switch (type) {
371 	case DPP_BOOTSTRAP_QR_CODE:
372 		return "QRCODE";
373 	case DPP_BOOTSTRAP_PKEX:
374 		return "PKEX";
375 	case DPP_BOOTSTRAP_NFC_URI:
376 		return "NFC-URI";
377 	}
378 	return "??";
379 }
380 
381 
dpp_uri_valid_info(const char * info)382 static int dpp_uri_valid_info(const char *info)
383 {
384 	while (*info) {
385 		unsigned char val = *info++;
386 
387 		if (val < 0x20 || val > 0x7e || val == 0x3b)
388 			return 0;
389 	}
390 
391 	return 1;
392 }
393 
394 
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)395 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
396 {
397 	bi->uri = os_strdup(uri);
398 	return bi->uri ? 0 : -1;
399 }
400 
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)401 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
402 			    const char *chan_list)
403 {
404 #ifndef ESP_SUPPLICANT
405 	const char *pos = chan_list, *pos2;
406 	int opclass = -1, channel, freq;
407 
408 	while (pos && *pos && *pos != ';') {
409 		pos2 = pos;
410 		while (*pos2 >= '0' && *pos2 <= '9')
411 			pos2++;
412 		if (*pos2 == '/') {
413 			opclass = atoi(pos);
414 			pos = pos2 + 1;
415 		}
416 		if (opclass <= 0)
417 			goto fail;
418 		channel = atoi(pos);
419 		if (channel <= 0)
420 			goto fail;
421 		while (*pos >= '0' && *pos <= '9')
422 			pos++;
423 		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
424 		wpa_printf(MSG_DEBUG,
425 			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
426 			   opclass, channel, freq);
427 		if (freq < 0) {
428 			wpa_printf(MSG_DEBUG,
429 				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
430 				   opclass, channel);
431 		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
432 			wpa_printf(MSG_DEBUG,
433 				   "DPP: Too many channels in URI channel-list - ignore list");
434 			bi->num_freq = 0;
435 			break;
436 		} else {
437 			bi->freq[bi->num_freq++] = freq;
438 		}
439 
440 		if (*pos == ';' || *pos == '\0')
441 			break;
442 		if (*pos != ',')
443 			goto fail;
444 		pos++;
445 	}
446 
447 	return 0;
448 fail:
449 	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
450 	return -1;
451 #endif
452 	return 0;
453 }
454 
455 
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)456 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
457 {
458 	if (!mac)
459 		return 0;
460 
461 	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
462 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
463 		return -1;
464 	}
465 
466 	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
467 
468 	return 0;
469 }
470 
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)471 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
472 {
473 	const char *end;
474 
475 	if (!info)
476 		return 0;
477 
478 	end = os_strchr(info, ';');
479 	if (!end)
480 		end = info + os_strlen(info);
481 	bi->info = os_malloc(end - info + 1);
482 	if (!bi->info)
483 		return -1;
484 	os_memcpy(bi->info, info, end - info);
485 	bi->info[end - info] = '\0';
486 	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
487 	if (!dpp_uri_valid_info(bi->info)) {
488 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
489 		return -1;
490 	}
491 
492 	return 0;
493 }
494 
dpp_get_curve_group_id(int group_id)495 static const struct dpp_curve_params * dpp_get_curve_group_id(int group_id)
496 {
497 	unsigned int i;
498 
499 	if (!group_id)
500 		return NULL;
501 
502 	for (i = 0; dpp_curves[i].ike_group; i++) {
503         if (group_id == dpp_curves[i].ike_group)
504 			return &dpp_curves[i];
505 	}
506 	return NULL;
507 }
508 
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)509 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
510 {
511 	const char *end;
512 	u8 *data;
513 	size_t data_len;
514 	struct crypto_key *pkey;
515 	const unsigned char *p;
516 	struct crypto_ec_group *group;
517 	int id;
518 
519 	end = os_strchr(info, ';');
520 	if (!end)
521 		return -1;
522 
523 	data = (unsigned char *)base64_decode(info, end - info, &data_len);
524 	if (!data) {
525 		wpa_printf(MSG_DEBUG,
526 			   "DPP: Invalid base64 encoding on URI public-key");
527 		return -1;
528 	}
529 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
530 		    data, data_len);
531 
532 	if (sha256_vector(1, (const u8 **) &data, &data_len,
533 			  bi->pubkey_hash) < 0) {
534 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
535 		os_free(data);
536 		return -1;
537 	}
538 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
539 		    bi->pubkey_hash, SHA256_MAC_LEN);
540 
541 	/* DER encoded ASN.1 SubjectPublicKeyInfo
542 	 *
543 	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
544 	 *      algorithm            AlgorithmIdentifier,
545 	 *      subjectPublicKey     BIT STRING  }
546 	 *
547 	 * AlgorithmIdentifier  ::=  SEQUENCE  {
548 	 *      algorithm               OBJECT IDENTIFIER,
549 	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
550 	 *
551 	 * subjectPublicKey = compressed format public key per ANSI X9.63
552 	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
553 	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
554 	 *       prime256v1 (1.2.840.10045.3.1.7)
555 	 */
556 
557 	p = data;
558 
559 	pkey = crypto_ec_parse_subpub_key((unsigned char *)p, data_len);
560 	os_free(data);
561 
562 	if (!pkey) {
563 		wpa_printf(MSG_DEBUG,
564 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
565 		return -1;
566 	}
567 
568 	if (!crypto_is_ec_key(pkey)) {
569 		wpa_printf(MSG_DEBUG,
570 				"DPP: SubjectPublicKeyInfo does not describe an EC key");
571 		crypto_ec_free_key(pkey);
572 		return -1;
573 	}
574 
575 	group = crypto_ec_get_group_from_key(pkey);
576 	if (!group) {
577 		return -1;
578 	}
579 	id = crypto_ec_get_curve_id(group);
580 	bi->curve = dpp_get_curve_group_id(id);
581 	if (!bi->curve) {
582 		wpa_printf(MSG_DEBUG,
583 			   "DPP: Unsupported SubjectPublicKeyInfo curve");
584 		goto fail;
585 	}
586 
587 	bi->pubkey = pkey;
588 	return 0;
589 fail:
590 	crypto_ec_free_key(pkey);
591 	return -1;
592 }
593 
594 
dpp_parse_uri(const char * uri)595 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
596 {
597 	const char *pos = uri;
598 	const char *end;
599 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
600 	struct dpp_bootstrap_info *bi;
601 
602 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", (u8 *)uri, os_strlen(uri));
603 
604 	if (os_strncmp(pos, "DPP:", 4) != 0) {
605 		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
606 		return NULL;
607 	}
608 	pos += 4;
609 
610 	for (;;) {
611 		end = os_strchr(pos, ';');
612 		if (!end)
613 			break;
614 
615 		if (end == pos) {
616 			/* Handle terminating ";;" and ignore unexpected ";"
617 			 * for parsing robustness. */
618 			pos++;
619 			continue;
620 		}
621 
622 		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
623 			chan_list = pos + 2;
624 		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
625 			mac = pos + 2;
626 		else if (pos[0] == 'I' && pos[1] == ':' && !info)
627 			info = pos + 2;
628 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
629 			pk = pos + 2;
630 		else
631 			wpa_hexdump_ascii(MSG_DEBUG,
632 					  "DPP: Ignore unrecognized URI parameter",
633 					  (u8 *)pos, end - pos);
634 		pos = end + 1;
635 	}
636 
637 	if (!pk) {
638 		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
639 		return NULL;
640 	}
641 
642 	bi = os_zalloc(sizeof(*bi));
643 	if (!bi)
644 		return NULL;
645 
646 	if (dpp_clone_uri(bi, uri) < 0 ||
647 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
648 	    dpp_parse_uri_mac(bi, mac) < 0 ||
649 	    dpp_parse_uri_info(bi, info) < 0 ||
650 	    dpp_parse_uri_pk(bi, pk) < 0) {
651 		dpp_bootstrap_info_free(bi);
652 		bi = NULL;
653 	}
654 
655 	return bi;
656 }
657 
658 
dpp_gen_keypair(const struct dpp_curve_params * curve)659 static struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
660 {
661 	struct crypto_key *key = crypto_ec_gen_keypair(curve->ike_group);
662 
663 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
664 	dpp_debug_print_key("Own generated key", key);
665 
666 	return key;
667 }
668 
dpp_get_curve_name(const char * name)669 static const struct dpp_curve_params *dpp_get_curve_name(const char *name)
670 {
671 	int i;
672 
673 	for (i = 0; dpp_curves[i].name; i++) {
674 		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
675 		    (dpp_curves[i].jwk_crv &&
676 		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
677 			return &dpp_curves[i];
678 	}
679 	return NULL;
680 }
681 
682 
dpp_get_curve_jwk_crv(const char * name)683 static const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name)
684 {
685 	int i;
686 
687 	for (i = 0; dpp_curves[i].name; i++) {
688 		if (dpp_curves[i].jwk_crv &&
689 		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
690 			return &dpp_curves[i];
691 	}
692 
693 	return NULL;
694 }
695 
696 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)697 static struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve,
698 					   const u8 *privkey, size_t privkey_len)
699 {
700 	struct crypto_ec_group *group;
701 	struct crypto_key *pkey = crypto_ec_get_key(privkey, privkey_len);
702 	int id;
703 
704 	if (!pkey) {
705 		wpa_printf(MSG_ERROR, "%s: failed to get pkey", __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, *a = NULL;
4673 	struct crypto_ec_group *group;
4674 	struct crypto_key *pkey = NULL;
4675 	size_t len;
4676 
4677 	token = json_get_member(jwk, "kty");
4678 	if (!token || token->type != JSON_STRING) {
4679 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
4680 		goto fail;
4681 	}
4682 	if (os_strcmp(token->string, "EC") != 0) {
4683 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
4684 			   token->string);
4685 		goto fail;
4686 	}
4687 
4688 	token = json_get_member(jwk, "crv");
4689 	if (!token || token->type != JSON_STRING) {
4690 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
4691 		goto fail;
4692 	}
4693 	curve = dpp_get_curve_jwk_crv(token->string);
4694 	if (!curve) {
4695 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
4696 			   token->string);
4697 		goto fail;
4698 	}
4699 
4700 	x = json_get_member_base64url(jwk, "x");
4701 	if (!x) {
4702 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
4703 		goto fail;
4704 	}
4705 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
4706 	if (wpabuf_len(x) != curve->prime_len) {
4707 		wpa_printf(MSG_DEBUG,
4708 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
4709 			   (unsigned int) wpabuf_len(x),
4710 			   (unsigned int) curve->prime_len, curve->name);
4711 		goto fail;
4712 	}
4713 
4714 	y = json_get_member_base64url(jwk, "y");
4715 	if (!y) {
4716 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
4717 		goto fail;
4718 	}
4719 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
4720 	if (wpabuf_len(y) != curve->prime_len) {
4721 		wpa_printf(MSG_DEBUG,
4722 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
4723 			   (unsigned int) wpabuf_len(y),
4724 			   (unsigned int) curve->prime_len, curve->name);
4725 		goto fail;
4726 	}
4727 
4728 	group = crypto_ec_get_group_byname(curve->name);
4729 	if (!group) {
4730 		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
4731 		goto fail;
4732 	}
4733 
4734 	len = wpabuf_len(x);
4735 	a = wpabuf_concat(x, y);
4736 	pkey = crypto_ec_set_pubkey_point(group, wpabuf_head(a),
4737 					  len);
4738 	crypto_ec_deinit((struct crypto_ec *)group);
4739 	*key_curve = curve;
4740 
4741 fail:
4742 	wpabuf_free(a);
4743 	wpabuf_free(x);
4744 	wpabuf_free(y);
4745 
4746 	return pkey;
4747 }
4748 
4749 
dpp_key_expired(const char * timestamp,os_time_t * expiry)4750 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
4751 {
4752 	struct os_time now;
4753 	unsigned int year, month, day, hour, min, sec;
4754 	os_time_t utime;
4755 	const char *pos;
4756 
4757 	/* ISO 8601 date and time:
4758 	 * <date>T<time>
4759 	 * YYYY-MM-DDTHH:MM:SSZ
4760 	 * YYYY-MM-DDTHH:MM:SS+03:00
4761 	 */
4762 	if (os_strlen(timestamp) < 19) {
4763 		wpa_printf(MSG_DEBUG,
4764 			   "DPP: Too short timestamp - assume expired key");
4765 		return 1;
4766 	}
4767 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
4768 		   &year, &month, &day, &hour, &min, &sec) != 6) {
4769 		wpa_printf(MSG_DEBUG,
4770 			   "DPP: Failed to parse expiration day - assume expired key");
4771 		return 1;
4772 	}
4773 
4774 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
4775 		wpa_printf(MSG_DEBUG,
4776 			   "DPP: Invalid date/time information - assume expired key");
4777 		return 1;
4778 	}
4779 
4780 	pos = timestamp + 19;
4781 	if (*pos == 'Z' || *pos == '\0') {
4782 		/* In UTC - no need to adjust */
4783 	} else if (*pos == '-' || *pos == '+') {
4784 		int items;
4785 
4786 		/* Adjust local time to UTC */
4787 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
4788 		if (items < 1) {
4789 			wpa_printf(MSG_DEBUG,
4790 				   "DPP: Invalid time zone designator (%s) - assume expired key",
4791 				   pos);
4792 			return 1;
4793 		}
4794 		if (*pos == '-')
4795 			utime += 3600 * hour;
4796 		if (*pos == '+')
4797 			utime -= 3600 * hour;
4798 		if (items > 1) {
4799 			if (*pos == '-')
4800 				utime += 60 * min;
4801 			if (*pos == '+')
4802 				utime -= 60 * min;
4803 		}
4804 	} else {
4805 		wpa_printf(MSG_DEBUG,
4806 			   "DPP: Invalid time zone designator (%s) - assume expired key",
4807 			   pos);
4808 		return 1;
4809 	}
4810 	if (expiry)
4811 		*expiry = utime;
4812 
4813 	if (os_get_time(&now) < 0) {
4814 		wpa_printf(MSG_DEBUG,
4815 			   "DPP: Cannot get current time - assume expired key");
4816 		return 1;
4817 	}
4818 
4819 	if (now.sec > utime) {
4820 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
4821 			   utime, now.sec);
4822 		return 1;
4823 	}
4824 
4825 	return 0;
4826 }
4827 
4828 
dpp_parse_connector(struct dpp_authentication * auth,struct dpp_config_obj * conf,const unsigned char * payload,u16 payload_len)4829 static int dpp_parse_connector(struct dpp_authentication *auth,
4830 			       struct dpp_config_obj *conf,
4831 			       const unsigned char *payload,
4832 			       u16 payload_len)
4833 {
4834 	struct json_token *root, *groups, *netkey, *token;
4835 	int ret = -1;
4836 	struct crypto_key *key = NULL;
4837 	const struct dpp_curve_params *curve;
4838 	unsigned int rules = 0;
4839 
4840 	root = json_parse((const char *) payload, payload_len);
4841 	if (!root) {
4842 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4843 		goto fail;
4844 	}
4845 
4846 	groups = json_get_member(root, "groups");
4847 	if (!groups || groups->type != JSON_ARRAY) {
4848 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
4849 		goto skip_groups;
4850 	}
4851 	for (token = groups->child; token; token = token->sibling) {
4852 		struct json_token *id, *role;
4853 
4854 		id = json_get_member(token, "groupId");
4855 		if (!id || id->type != JSON_STRING) {
4856 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
4857 			goto fail;
4858 		}
4859 
4860 		role = json_get_member(token, "netRole");
4861 		if (!role || role->type != JSON_STRING) {
4862 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
4863 			goto fail;
4864 		}
4865 		wpa_printf(MSG_DEBUG,
4866 			   "DPP: connector group: groupId='%s' netRole='%s'",
4867 			   id->string, role->string);
4868 		rules++;
4869 	}
4870 skip_groups:
4871 
4872 	if (!rules) {
4873 		wpa_printf(MSG_DEBUG,
4874 			   "DPP: Connector includes no groups");
4875 		goto fail;
4876 	}
4877 
4878 	token = json_get_member(root, "expiry");
4879 	if (!token || token->type != JSON_STRING) {
4880 		wpa_printf(MSG_DEBUG,
4881 			   "DPP: No expiry string found - connector does not expire");
4882 	} else {
4883 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4884 		if (dpp_key_expired(token->string,
4885 				    &auth->net_access_key_expiry)) {
4886 			wpa_printf(MSG_DEBUG,
4887 				   "DPP: Connector (netAccessKey) has expired");
4888 			goto fail;
4889 		}
4890 	}
4891 
4892 	netkey = json_get_member(root, "netAccessKey");
4893 	if (!netkey || netkey->type != JSON_OBJECT) {
4894 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4895 		goto fail;
4896 	}
4897 
4898 	key = dpp_parse_jwk(netkey, &curve);
4899 	if (!key)
4900 		goto fail;
4901 	dpp_debug_print_key("DPP: Received netAccessKey", key);
4902 
4903 	if (crypto_key_compare(key, auth->own_protocol_key) != 1) {
4904 		wpa_printf(MSG_DEBUG,
4905 			   "DPP: netAccessKey in connector does not match own protocol key");
4906 #ifdef CONFIG_TESTING_OPTIONS
4907 		if (auth->ignore_netaccesskey_mismatch) {
4908 			wpa_printf(MSG_DEBUG,
4909 				   "DPP: TESTING - skip netAccessKey mismatch");
4910 		} else {
4911 			goto fail;
4912 		}
4913 #else /* CONFIG_TESTING_OPTIONS */
4914 		goto fail;
4915 #endif /* CONFIG_TESTING_OPTIONS */
4916 	}
4917 
4918 	ret = 0;
4919 fail:
4920 	crypto_ec_free_key(key);
4921 	json_free(root);
4922 	return ret;
4923 }
4924 
dpp_check_pubkey_match(struct crypto_key * pub,struct wpabuf * r_hash)4925 static int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash)
4926 {
4927 	struct wpabuf *uncomp;
4928 	int res;
4929 	u8 hash[SHA256_MAC_LEN];
4930 	const u8 *addr[1];
4931 	size_t len[1];
4932 
4933 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
4934 		return -1;
4935 	uncomp = dpp_get_pubkey_point(pub, 1);
4936 	if (!uncomp)
4937 		return -1;
4938 	addr[0] = wpabuf_head(uncomp);
4939 	len[0] = wpabuf_len(uncomp);
4940 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
4941 		    addr[0], len[0]);
4942 	res = sha256_vector(1, addr, len, hash);
4943 	wpabuf_free(uncomp);
4944 	if (res < 0)
4945 		return -1;
4946 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
4947 		wpa_printf(MSG_DEBUG,
4948 			   "DPP: Received hash value does not match calculated public key hash value");
4949 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
4950 			    hash, SHA256_MAC_LEN);
4951 		return -1;
4952 	}
4953 	return 0;
4954 }
4955 
4956 
dpp_copy_csign(struct dpp_config_obj * conf,struct crypto_key * csign)4957 static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_key *csign)
4958 {
4959 	unsigned char *der = NULL;
4960 	int der_len;
4961 
4962 	der_len = crypto_write_pubkey_der(csign, &der);
4963 	if (der_len <= 0)
4964 		return;
4965 	wpabuf_free(conf->c_sign_key);
4966 	conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
4967 	crypto_free_buffer(der);
4968 }
4969 
dpp_copy_netaccesskey(struct dpp_authentication * auth,struct dpp_config_obj * conf)4970 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
4971 				  struct dpp_config_obj *conf)
4972 {
4973 	unsigned char *der = NULL;
4974 	int der_len;
4975 
4976 	if (crypto_ec_get_priv_key_der(auth->own_protocol_key, &der, &der_len) < 0)
4977 		return;
4978 	wpabuf_free(auth->net_access_key);
4979 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
4980 	crypto_free_buffer(der);
4981 }
4982 
4983 struct dpp_signed_connector_info {
4984 	unsigned char *payload;
4985 	size_t payload_len;
4986 };
4987 
4988 static enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_key * csign_pub,const char * connector)4989 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
4990 			     struct crypto_key *csign_pub, const char *connector)
4991 {
4992 	enum dpp_status_error ret = 255;
4993 	const char *pos, *end, *signed_start, *signed_end;
4994 	struct wpabuf *kid = NULL;
4995 	unsigned char *prot_hdr = NULL, *signature = NULL;
4996 	size_t prot_hdr_len = 0, signature_len = 0;
4997 	struct crypto_bignum *r = NULL, *s = NULL;
4998 	const struct dpp_curve_params *curve;
4999 	const struct crypto_ec_group *group;
5000 	int id;
5001 
5002 	group = crypto_ec_get_group_from_key(csign_pub);
5003 	if (!group)
5004 		goto fail;
5005 	id = crypto_ec_get_curve_id(group);
5006 	curve = dpp_get_curve_group_id(id);
5007 	if (!curve)
5008 		goto fail;
5009 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
5010 	os_memset(info, 0, sizeof(*info));
5011 
5012 	signed_start = pos = connector;
5013 	end = os_strchr(pos, '.');
5014 	if (!end) {
5015 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
5016 		ret = DPP_STATUS_INVALID_CONNECTOR;
5017 		goto fail;
5018 	}
5019 	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
5020 	if (!prot_hdr) {
5021 		wpa_printf(MSG_DEBUG,
5022 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
5023 		ret = DPP_STATUS_INVALID_CONNECTOR;
5024 		goto fail;
5025 	}
5026 	wpa_hexdump_ascii(MSG_DEBUG,
5027 			  "DPP: signedConnector - JWS Protected Header",
5028 			  (u8 *)prot_hdr, prot_hdr_len);
5029 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len);
5030 	if (!kid) {
5031 		ret = DPP_STATUS_INVALID_CONNECTOR;
5032 		goto fail;
5033 	}
5034 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
5035 		wpa_printf(MSG_DEBUG,
5036 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
5037 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
5038 		ret = DPP_STATUS_INVALID_CONNECTOR;
5039 		goto fail;
5040 	}
5041 
5042 	pos = end + 1;
5043 	end = os_strchr(pos, '.');
5044 	if (!end) {
5045 		wpa_printf(MSG_DEBUG,
5046 			   "DPP: Missing dot(2) in signedConnector");
5047 		ret = DPP_STATUS_INVALID_CONNECTOR;
5048 		goto fail;
5049 	}
5050 	signed_end = end - 1;
5051 	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
5052 	if (!info->payload) {
5053 		wpa_printf(MSG_DEBUG,
5054 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
5055 		ret = DPP_STATUS_INVALID_CONNECTOR;
5056 		goto fail;
5057 	}
5058 	wpa_hexdump_ascii(MSG_DEBUG,
5059 			  "DPP: signedConnector - JWS Payload",
5060 			  (u8 *)info->payload, info->payload_len);
5061 	pos = end + 1;
5062 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5063 	if (!signature) {
5064 		wpa_printf(MSG_DEBUG,
5065 				"DPP: Failed to base64url decode signedConnector signature");
5066 		ret = DPP_STATUS_INVALID_CONNECTOR;
5067 		goto fail;
5068 	}
5069 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
5070 		    signature, signature_len);
5071 
5072 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
5073 		ret = DPP_STATUS_NO_MATCH;
5074 		goto fail;
5075 	}
5076 
5077 	if (signature_len & 0x01) {
5078 		wpa_printf(MSG_DEBUG,
5079 			   "DPP: Unexpected signedConnector signature length (%d)",
5080 			   (int) signature_len);
5081 		ret = DPP_STATUS_INVALID_CONNECTOR;
5082 		goto fail;
5083 	}
5084 
5085 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
5086 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
5087 	r = crypto_bignum_init_set(signature, signature_len / 2);
5088 	s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2);
5089 
5090 	if (!crypto_edcsa_sign_verify((unsigned char *)signed_start, r, s,
5091 				csign_pub, signed_end - signed_start + 1)) {
5092 		goto fail;
5093 	}
5094 
5095 	ret = DPP_STATUS_OK;
5096 fail:
5097 	os_free(prot_hdr);
5098 	wpabuf_free(kid);
5099 	os_free(signature);
5100 	crypto_bignum_deinit(r, 0);
5101 	crypto_bignum_deinit(s, 0);
5102 	return ret;
5103 }
5104 
5105 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)5106 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
5107 			      struct dpp_config_obj *conf,
5108 			      struct json_token *cred)
5109 {
5110 	struct dpp_signed_connector_info info;
5111 	struct json_token *token, *csign;
5112 	int ret = -1;
5113 	struct crypto_key *csign_pub = NULL;
5114 	const struct dpp_curve_params *key_curve = NULL;
5115 	const char *signed_connector;
5116 
5117 	os_memset(&info, 0, sizeof(info));
5118 
5119 	if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
5120 		wpa_printf(MSG_DEBUG,
5121 			   "DPP: Legacy credential included in Connector credential");
5122 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5123 			return -1;
5124 	}
5125 
5126 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
5127 
5128 	csign = json_get_member(cred, "csign");
5129 	if (!csign || csign->type != JSON_OBJECT) {
5130 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
5131 		goto fail;
5132 	}
5133 
5134 	csign_pub = dpp_parse_jwk(csign, &key_curve);
5135 	if (!csign_pub) {
5136 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
5137 		goto fail;
5138 	}
5139 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
5140 
5141 	token = json_get_member(cred, "signedConnector");
5142 	if (!token || token->type != JSON_STRING) {
5143 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
5144 		goto fail;
5145 	}
5146 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
5147 			  (u8 *)token->string, os_strlen(token->string));
5148 	signed_connector = token->string;
5149 
5150 	if (os_strchr(signed_connector, '"') ||
5151 	    os_strchr(signed_connector, '\n')) {
5152 		wpa_printf(MSG_DEBUG,
5153 			   "DPP: Unexpected character in signedConnector");
5154 		goto fail;
5155 	}
5156 
5157 	if (dpp_process_signed_connector(&info, csign_pub,
5158 					 signed_connector) != DPP_STATUS_OK)
5159 		goto fail;
5160 
5161 	if (dpp_parse_connector(auth, conf,
5162 				info.payload, info.payload_len) < 0) {
5163 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
5164 		goto fail;
5165 	}
5166 
5167 	os_free(conf->connector);
5168 	conf->connector = os_strdup(signed_connector);
5169 
5170 	dpp_copy_csign(conf, csign_pub);
5171 	dpp_copy_netaccesskey(auth, conf);
5172 
5173 	ret = 0;
5174 fail:
5175 	crypto_ec_free_key(csign_pub);
5176 	os_free(info.payload);
5177 	return ret;
5178 }
5179 
5180 
dpp_akm_str(enum dpp_akm akm)5181 const char * dpp_akm_str(enum dpp_akm akm)
5182 {
5183 	switch (akm) {
5184 	case DPP_AKM_DPP:
5185 		return "dpp";
5186 	case DPP_AKM_PSK:
5187 		return "psk";
5188 	case DPP_AKM_SAE:
5189 		return "sae";
5190 	case DPP_AKM_PSK_SAE:
5191 		return "psk+sae";
5192 	case DPP_AKM_SAE_DPP:
5193 		return "dpp+sae";
5194 	case DPP_AKM_PSK_SAE_DPP:
5195 		return "dpp+psk+sae";
5196 	default:
5197 		return "??";
5198 	}
5199 }
5200 
5201 
dpp_akm_selector_str(enum dpp_akm akm)5202 const char * dpp_akm_selector_str(enum dpp_akm akm)
5203 {
5204 	switch (akm) {
5205 	case DPP_AKM_DPP:
5206 		return "506F9A02";
5207 	case DPP_AKM_PSK:
5208 		return "000FAC02+000FAC06";
5209 	case DPP_AKM_SAE:
5210 		return "000FAC08";
5211 	case DPP_AKM_PSK_SAE:
5212 		return "000FAC02+000FAC06+000FAC08";
5213 	case DPP_AKM_SAE_DPP:
5214 		return "506F9A02+000FAC08";
5215 	case DPP_AKM_PSK_SAE_DPP:
5216 		return "506F9A02+000FAC08+000FAC02+000FAC06";
5217 	default:
5218 		return "??";
5219 	}
5220 }
5221 
5222 
dpp_akm_from_str(const char * akm)5223 static enum dpp_akm dpp_akm_from_str(const char *akm)
5224 {
5225 	const char *pos;
5226 	int dpp = 0, psk = 0, sae = 0;
5227 
5228 	if (os_strcmp(akm, "psk") == 0)
5229 		return DPP_AKM_PSK;
5230 	if (os_strcmp(akm, "sae") == 0)
5231 		return DPP_AKM_SAE;
5232 	if (os_strcmp(akm, "psk+sae") == 0)
5233 		return DPP_AKM_PSK_SAE;
5234 	if (os_strcmp(akm, "dpp") == 0)
5235 		return DPP_AKM_DPP;
5236 	if (os_strcmp(akm, "dpp+sae") == 0)
5237 		return DPP_AKM_SAE_DPP;
5238 	if (os_strcmp(akm, "dpp+psk+sae") == 0)
5239 		return DPP_AKM_PSK_SAE_DPP;
5240 
5241 	pos = akm;
5242 	while (*pos) {
5243 		if (os_strlen(pos) < 8)
5244 			break;
5245 		if (os_strncasecmp(pos, "506F9A02", 8) == 0)
5246 			dpp = 1;
5247 		else if (os_strncasecmp(pos, "000FAC02", 8) == 0)
5248 			psk = 1;
5249 		else if (os_strncasecmp(pos, "000FAC06", 8) == 0)
5250 			psk = 1;
5251 		else if (os_strncasecmp(pos, "000FAC08", 8) == 0)
5252 			sae = 1;
5253 		pos += 8;
5254 		if (*pos != '+')
5255 			break;
5256 		pos++;
5257 	}
5258 
5259 	if (dpp && psk && sae)
5260 		return DPP_AKM_PSK_SAE_DPP;
5261 	if (dpp && sae)
5262 		return DPP_AKM_SAE_DPP;
5263 	if (dpp)
5264 		return DPP_AKM_DPP;
5265 	if (psk && sae)
5266 		return DPP_AKM_PSK_SAE;
5267 	if (sae)
5268 		return DPP_AKM_SAE;
5269 	if (psk)
5270 		return DPP_AKM_PSK;
5271 
5272 	return DPP_AKM_UNKNOWN;
5273 }
5274 
5275 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)5276 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
5277 			      const u8 *conf_obj, u16 conf_obj_len)
5278 {
5279 	int ret = -1;
5280 	struct json_token *root, *token, *discovery, *cred;
5281 	struct dpp_config_obj *conf;
5282 	struct wpabuf *ssid64 = NULL;
5283 
5284 	root = json_parse((const char *) conf_obj, conf_obj_len);
5285 	if (!root)
5286 		return -1;
5287 	if (root->type != JSON_OBJECT) {
5288 		dpp_auth_fail(auth, "JSON root is not an object");
5289 		goto fail;
5290 	}
5291 
5292 	token = json_get_member(root, "wi-fi_tech");
5293 	if (!token || token->type != JSON_STRING) {
5294 		dpp_auth_fail(auth, "No wi-fi_tech string value found");
5295 		goto fail;
5296 	}
5297 	if (os_strcmp(token->string, "infra") != 0) {
5298 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
5299 			   token->string);
5300 		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
5301 		goto fail;
5302 	}
5303 
5304 	discovery = json_get_member(root, "discovery");
5305 	if (!discovery || discovery->type != JSON_OBJECT) {
5306 		dpp_auth_fail(auth, "No discovery object in JSON");
5307 		goto fail;
5308 	}
5309 
5310 	ssid64 = json_get_member_base64url(discovery, "ssid64");
5311 	if (ssid64) {
5312 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
5313 				  (u8 *)wpabuf_head(ssid64), wpabuf_len(ssid64));
5314 		if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
5315 			dpp_auth_fail(auth, "Too long discovery::ssid64 value");
5316 			goto fail;
5317 		}
5318 	} else {
5319 		token = json_get_member(discovery, "ssid");
5320 		if (!token || token->type != JSON_STRING) {
5321 			dpp_auth_fail(auth,
5322 				      "No discovery::ssid string value found");
5323 			goto fail;
5324 		}
5325 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
5326 				  (u8 *)token->string, os_strlen(token->string));
5327 		if (os_strlen(token->string) > SSID_MAX_LEN) {
5328 			dpp_auth_fail(auth,
5329 				      "Too long discovery::ssid string value");
5330 			goto fail;
5331 		}
5332 	}
5333 
5334 	if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
5335 		wpa_printf(MSG_DEBUG,
5336 			   "DPP: No room for this many Config Objects - ignore this one");
5337 		ret = 0;
5338 		goto fail;
5339 	}
5340 	conf = &auth->conf_obj[auth->num_conf_obj++];
5341 
5342 	if (ssid64) {
5343 		conf->ssid_len = wpabuf_len(ssid64);
5344 		os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
5345 	} else {
5346 		conf->ssid_len = os_strlen(token->string);
5347 		os_memcpy(conf->ssid, token->string, conf->ssid_len);
5348 	}
5349 
5350 	token = json_get_member(discovery, "ssid_charset");
5351 	if (token && token->type == JSON_NUMBER) {
5352 		conf->ssid_charset = token->number;
5353 		wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
5354 			   conf->ssid_charset);
5355 	}
5356 
5357 	cred = json_get_member(root, "cred");
5358 	if (!cred || cred->type != JSON_OBJECT) {
5359 		dpp_auth_fail(auth, "No cred object in JSON");
5360 		goto fail;
5361 	}
5362 
5363 	token = json_get_member(cred, "akm");
5364 	if (!token || token->type != JSON_STRING) {
5365 		dpp_auth_fail(auth, "No cred::akm string value found");
5366 		goto fail;
5367 	}
5368 	conf->akm = dpp_akm_from_str(token->string);
5369 
5370 	if (dpp_akm_legacy(conf->akm)) {
5371 		if (dpp_parse_cred_legacy(conf, cred) < 0)
5372 			goto fail;
5373 	} else if (dpp_akm_dpp(conf->akm)) {
5374 		if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
5375 			goto fail;
5376 	} else {
5377 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
5378 			   token->string);
5379 		dpp_auth_fail(auth, "Unsupported akm");
5380 		goto fail;
5381 	}
5382 
5383 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
5384 	ret = 0;
5385 fail:
5386 	wpabuf_free(ssid64);
5387 	json_free(root);
5388 	return ret;
5389 }
5390 
5391 
dpp_conf_resp_rx(struct dpp_authentication * auth,const uint8_t * resp,uint32_t resp_len)5392 int dpp_conf_resp_rx(struct dpp_authentication *auth,
5393                      const uint8_t *resp, uint32_t resp_len)
5394 {
5395 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
5396 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
5397 	const u8 *addr[1];
5398 	size_t len[1];
5399 	u8 *unwrapped = NULL;
5400 	size_t unwrapped_len = 0;
5401 	int ret = -1;
5402 
5403 	auth->conf_resp_status = 255;
5404 
5405 	if (dpp_check_attrs(resp, resp_len) < 0) {
5406 		dpp_auth_fail(auth, "Invalid attribute in config response");
5407 		return -1;
5408 	}
5409 
5410 	wrapped_data = dpp_get_attr(resp, resp_len,
5411 				    DPP_ATTR_WRAPPED_DATA,
5412 				    &wrapped_data_len);
5413 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5414 		dpp_auth_fail(auth,
5415 			      "Missing or invalid required Wrapped Data attribute");
5416 		return -1;
5417 	}
5418 
5419 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5420 		    wrapped_data, wrapped_data_len);
5421 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5422 	unwrapped = os_malloc(unwrapped_len);
5423 	if (!unwrapped)
5424 		return -1;
5425 
5426 	addr[0] = resp;
5427 	len[0] = wrapped_data - 4 - resp;
5428 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
5429 
5430 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5431 			    wrapped_data, wrapped_data_len,
5432 			    1, addr, len, unwrapped) < 0) {
5433 		dpp_auth_fail(auth, "AES-SIV decryption failed");
5434 		goto fail;
5435 	}
5436 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5437 		    unwrapped, unwrapped_len);
5438 
5439 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5440 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5441 		goto fail;
5442 	}
5443 
5444 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5445 			       DPP_ATTR_ENROLLEE_NONCE,
5446 			       &e_nonce_len);
5447 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5448 		dpp_auth_fail(auth,
5449 			      "Missing or invalid Enrollee Nonce attribute");
5450 		goto fail;
5451 	}
5452 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5453 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
5454 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
5455 		goto fail;
5456 	}
5457 
5458 	status = dpp_get_attr(resp, resp_len,
5459 			      DPP_ATTR_STATUS, &status_len);
5460 	if (!status || status_len < 1) {
5461 		dpp_auth_fail(auth,
5462 			      "Missing or invalid required DPP Status attribute");
5463 		goto fail;
5464 	}
5465 	auth->conf_resp_status = status[0];
5466 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
5467 	if (status[0] != DPP_STATUS_OK) {
5468 		dpp_auth_fail(auth, "Configurator rejected configuration");
5469 		goto fail;
5470 	}
5471 
5472 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
5473 				&conf_obj_len);
5474 	if (!conf_obj) {
5475 		dpp_auth_fail(auth,
5476 			      "Missing required Configuration Object attribute");
5477 		goto fail;
5478 	}
5479 	while (conf_obj) {
5480 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
5481 				  (u8 *)conf_obj, conf_obj_len);
5482 		if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
5483 			goto fail;
5484 		conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
5485 					     DPP_ATTR_CONFIG_OBJ,
5486 					     &conf_obj_len);
5487 	}
5488 
5489 	ret = 0;
5490 
5491 fail:
5492 	os_free(unwrapped);
5493 	return ret;
5494 }
5495 
dpp_configurator_free(struct dpp_configurator * conf)5496 void dpp_configurator_free(struct dpp_configurator *conf)
5497 {
5498 	if (!conf)
5499 		return;
5500 	crypto_ec_free_key(conf->csign);
5501 	os_free(conf->kid);
5502 	os_free(conf);
5503 }
5504 
5505 
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)5506 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
5507 			     size_t buflen)
5508 {
5509 	int keylen, ret = -1;
5510 	unsigned char *key = NULL;
5511 
5512 	if (!conf->csign)
5513 		return ret;
5514 
5515 	crypto_ec_get_priv_key_der(conf->csign, &key, &keylen);
5516 
5517 	if (keylen > 0)
5518 		ret = wpa_snprintf_hex(buf, buflen, key, keylen);
5519 
5520 	crypto_free_buffer(key);
5521 
5522 	return ret;
5523 }
5524 
5525 
5526 struct dpp_configurator *
dpp_keygen_configurator(const char * curve,u8 * privkey,size_t privkey_len)5527 dpp_keygen_configurator(const char *curve, u8 *privkey,
5528 			size_t privkey_len)
5529 {
5530 	struct dpp_configurator *conf;
5531 	struct wpabuf *csign_pub = NULL;
5532 	u8 kid_hash[SHA256_MAC_LEN];
5533 	const u8 *addr[1];
5534 	size_t len[1];
5535 
5536 	conf = os_zalloc(sizeof(*conf));
5537 	if (!conf)
5538 		return NULL;
5539 
5540 	if (!curve) {
5541 		conf->curve = &dpp_curves[0];
5542 	} else {
5543 		conf->curve = dpp_get_curve_name(curve);
5544 		if (!conf->curve) {
5545 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5546 				   curve);
5547 			os_free(conf);
5548 			return NULL;
5549 		}
5550 	}
5551 	if (privkey)
5552 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
5553 					      privkey_len);
5554 	else
5555 		conf->csign = dpp_gen_keypair(conf->curve);
5556 	if (!conf->csign)
5557 		goto fail;
5558 	conf->own = 1;
5559 
5560 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
5561 	if (!csign_pub) {
5562 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
5563 		goto fail;
5564 	}
5565 
5566 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
5567 	addr[0] = wpabuf_head(csign_pub);
5568 	len[0] = wpabuf_len(csign_pub);
5569 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
5570 		wpa_printf(MSG_DEBUG,
5571 			   "DPP: Failed to derive kid for C-sign-key");
5572 		goto fail;
5573 	}
5574 
5575 	conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
5576 	if (!conf->kid)
5577 		goto fail;
5578 out:
5579 	wpabuf_free(csign_pub);
5580 	return conf;
5581 fail:
5582 	dpp_configurator_free(conf);
5583 	conf = NULL;
5584 	goto out;
5585 }
5586 
5587 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)5588 int dpp_configurator_own_config(struct dpp_authentication *auth,
5589 				const char *curve, int ap)
5590 {
5591 	struct wpabuf *conf_obj;
5592 	int ret = -1;
5593 
5594 	if (!auth->conf) {
5595 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
5596 		return -1;
5597 	}
5598 
5599 	if (!curve) {
5600 		auth->curve = &dpp_curves[0];
5601 	} else {
5602 		auth->curve = dpp_get_curve_name(curve);
5603 		if (!auth->curve) {
5604 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
5605 				   curve);
5606 			return -1;
5607 		}
5608 	}
5609 	wpa_printf(MSG_DEBUG,
5610 		   "DPP: Building own configuration/connector with curve %s",
5611 		   auth->curve->name);
5612 
5613 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
5614 	if (!auth->own_protocol_key)
5615 		return -1;
5616 	dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
5617 	auth->peer_protocol_key = auth->own_protocol_key;
5618 	dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
5619 
5620 	conf_obj = dpp_build_conf_obj(auth, ap, 0);
5621 	if (!conf_obj) {
5622 		wpabuf_free(auth->conf_obj[0].c_sign_key);
5623 		auth->conf_obj[0].c_sign_key = NULL;
5624 		goto fail;
5625 	}
5626 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
5627 				 wpabuf_len(conf_obj));
5628 fail:
5629 	wpabuf_free(conf_obj);
5630 	auth->peer_protocol_key = NULL;
5631 	return ret;
5632 }
5633 
5634 
dpp_compatible_netrole(const char * role1,const char * role2)5635 static int dpp_compatible_netrole(const char *role1, const char *role2)
5636 {
5637 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
5638 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
5639 }
5640 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role)5641 static int dpp_connector_compatible_group(struct json_token *root,
5642 					  const char *group_id,
5643 					  const char *net_role)
5644 {
5645 	struct json_token *groups, *token;
5646 
5647 	groups = json_get_member(root, "groups");
5648 	if (!groups || groups->type != JSON_ARRAY)
5649 		return 0;
5650 
5651 	for (token = groups->child; token; token = token->sibling) {
5652 		struct json_token *id, *role;
5653 
5654 		id = json_get_member(token, "groupId");
5655 		if (!id || id->type != JSON_STRING)
5656 			continue;
5657 
5658 		role = json_get_member(token, "netRole");
5659 		if (!role || role->type != JSON_STRING)
5660 			continue;
5661 
5662 		if (os_strcmp(id->string, "*") != 0 &&
5663 		    os_strcmp(group_id, "*") != 0 &&
5664 		    os_strcmp(id->string, group_id) != 0)
5665 			continue;
5666 
5667 		if (dpp_compatible_netrole(role->string, net_role))
5668 			return 1;
5669 	}
5670 
5671 	return 0;
5672 }
5673 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root)5674 static int dpp_connector_match_groups(struct json_token *own_root,
5675 				      struct json_token *peer_root)
5676 {
5677 	struct json_token *groups, *token;
5678 
5679 	groups = json_get_member(peer_root, "groups");
5680 	if (!groups || groups->type != JSON_ARRAY) {
5681 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
5682 		return 0;
5683 	}
5684 
5685 	for (token = groups->child; token; token = token->sibling) {
5686 		struct json_token *id, *role;
5687 
5688 		id = json_get_member(token, "groupId");
5689 		if (!id || id->type != JSON_STRING) {
5690 			wpa_printf(MSG_DEBUG,
5691 				   "DPP: Missing peer groupId string");
5692 			continue;
5693 		}
5694 
5695 		role = json_get_member(token, "netRole");
5696 		if (!role || role->type != JSON_STRING) {
5697 			wpa_printf(MSG_DEBUG,
5698 				   "DPP: Missing peer groups::netRole string");
5699 			continue;
5700 		}
5701 		wpa_printf(MSG_DEBUG,
5702 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
5703 			   id->string, role->string);
5704 		if (dpp_connector_compatible_group(own_root, id->string,
5705 						   role->string)) {
5706 			wpa_printf(MSG_DEBUG,
5707 				   "DPP: Compatible group/netRole in own connector");
5708 			return 1;
5709 		}
5710 	}
5711 
5712 	return 0;
5713 }
5714 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)5715 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
5716 			  unsigned int hash_len)
5717 {
5718 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
5719 	const char *info = "DPP PMK";
5720 	int res;
5721 
5722 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5723 
5724 	/* HKDF-Extract(<>, N.x) */
5725 	os_memset(salt, 0, hash_len);
5726 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
5727 		return -1;
5728 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
5729 			prk, hash_len);
5730 
5731 	/* HKDF-Expand(PRK, info, L) */
5732 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
5733 	forced_memzero(prk, hash_len);
5734 	if (res < 0)
5735 		return -1;
5736 
5737 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
5738 			pmk, hash_len);
5739 	return 0;
5740 }
5741 
5742 
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_key * own_key,struct crypto_key * peer_key,u8 * pmkid)5743 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
5744 			    struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid)
5745 {
5746 	struct wpabuf *nkx, *pkx;
5747 	int ret = -1, res;
5748 	const u8 *addr[2];
5749 	size_t len[2];
5750 	u8 hash[SHA256_MAC_LEN];
5751 
5752 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5753 	nkx = dpp_get_pubkey_point(own_key, 0);
5754 	pkx = dpp_get_pubkey_point(peer_key, 0);
5755 	if (!nkx || !pkx)
5756 		goto fail;
5757 	addr[0] = wpabuf_head(nkx);
5758 	len[0] = wpabuf_len(nkx) / 2;
5759 	addr[1] = wpabuf_head(pkx);
5760 	len[1] = wpabuf_len(pkx) / 2;
5761 	if (len[0] != len[1])
5762 		goto fail;
5763 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
5764 		addr[0] = wpabuf_head(pkx);
5765 		addr[1] = wpabuf_head(nkx);
5766 	}
5767 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
5768 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
5769 	res = sha256_vector(2, addr, len, hash);
5770 	if (res < 0)
5771 		goto fail;
5772 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
5773 	os_memcpy(pmkid, hash, PMKID_LEN);
5774 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
5775 	ret = 0;
5776 fail:
5777 	wpabuf_free(nkx);
5778 	wpabuf_free(pkx);
5779 	return ret;
5780 }
5781 
5782 
5783 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)5784 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
5785 	       const u8 *net_access_key, size_t net_access_key_len,
5786 	       const u8 *csign_key, size_t csign_key_len,
5787 	       const u8 *peer_connector, size_t peer_connector_len,
5788 	       os_time_t *expiry)
5789 {
5790 	struct json_token *root = NULL, *netkey, *token;
5791 	struct json_token *own_root = NULL;
5792 	enum dpp_status_error ret = 255, res;
5793 	struct crypto_key *own_key = NULL, *peer_key = NULL;
5794 	struct wpabuf *own_key_pub = NULL;
5795 	const struct dpp_curve_params *curve, *own_curve;
5796 	struct dpp_signed_connector_info info;
5797 	const unsigned char *p;
5798 	struct crypto_key *csign = NULL;
5799 	char *signed_connector = NULL;
5800 	const char *pos, *end;
5801 	unsigned char *own_conn = NULL;
5802 	size_t own_conn_len;
5803 	size_t Nx_len;
5804 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
5805 
5806 	os_memset(intro, 0, sizeof(*intro));
5807 	os_memset(&info, 0, sizeof(info));
5808 	if (expiry)
5809 		*expiry = 0;
5810 
5811 	p = csign_key;
5812 	csign = crypto_ec_parse_subpub_key(p, csign_key_len);
5813 	if (!csign) {
5814 		wpa_printf(MSG_ERROR,
5815 			   "DPP: Failed to parse local C-sign-key information");
5816 		goto fail;
5817 	}
5818 
5819 	own_key = dpp_set_keypair(&own_curve, net_access_key,
5820 				  net_access_key_len);
5821 	if (!own_key) {
5822 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
5823 		goto fail;
5824 	}
5825 
5826 	pos = os_strchr(own_connector, '.');
5827 	if (!pos) {
5828 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
5829 		goto fail;
5830 	}
5831 	pos++;
5832 	end = os_strchr(pos, '.');
5833 	if (!end) {
5834 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
5835 		goto fail;
5836 	}
5837 	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
5838 	if (!own_conn) {
5839 		wpa_printf(MSG_DEBUG,
5840 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
5841 		goto fail;
5842 	}
5843 
5844 	own_root = json_parse((const char *) own_conn, own_conn_len);
5845 	if (!own_root) {
5846 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
5847 		goto fail;
5848 	}
5849 
5850 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
5851 			  (u8 *)peer_connector, peer_connector_len);
5852 	signed_connector = os_malloc(peer_connector_len + 1);
5853 	if (!signed_connector)
5854 		goto fail;
5855 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
5856 	signed_connector[peer_connector_len] = '\0';
5857 
5858 	res = dpp_process_signed_connector(&info, csign, signed_connector);
5859 	if (res != DPP_STATUS_OK) {
5860 		ret = res;
5861 		goto fail;
5862 	}
5863 
5864 	root = json_parse((const char *) info.payload, info.payload_len);
5865 	if (!root) {
5866 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
5867 		ret = DPP_STATUS_INVALID_CONNECTOR;
5868 		goto fail;
5869 	}
5870 
5871 	if (!dpp_connector_match_groups(own_root, root)) {
5872 		wpa_printf(MSG_DEBUG,
5873 			   "DPP: Peer connector does not include compatible group netrole with own connector");
5874 		ret = DPP_STATUS_NO_MATCH;
5875 		goto fail;
5876 	}
5877 
5878 	token = json_get_member(root, "expiry");
5879 	if (!token || token->type != JSON_STRING) {
5880 		wpa_printf(MSG_DEBUG,
5881 			   "DPP: No expiry string found - connector does not expire");
5882 	} else {
5883 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
5884 		if (dpp_key_expired(token->string, expiry)) {
5885 			wpa_printf(MSG_DEBUG,
5886 				   "DPP: Connector (netAccessKey) has expired");
5887 			ret = DPP_STATUS_INVALID_CONNECTOR;
5888 			goto fail;
5889 		}
5890 	}
5891 
5892 	netkey = json_get_member(root, "netAccessKey");
5893 	if (!netkey || netkey->type != JSON_OBJECT) {
5894 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
5895 		ret = DPP_STATUS_INVALID_CONNECTOR;
5896 		goto fail;
5897 	}
5898 
5899 	peer_key = dpp_parse_jwk(netkey, &curve);
5900 	if (!peer_key) {
5901 		ret = DPP_STATUS_INVALID_CONNECTOR;
5902 		goto fail;
5903 	}
5904 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
5905 
5906 	if (own_curve != curve) {
5907 		wpa_printf(MSG_DEBUG,
5908 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
5909 			   own_curve->name, curve->name);
5910 		ret = DPP_STATUS_INVALID_CONNECTOR;
5911 		goto fail;
5912 	}
5913 
5914 	/* ECDH: N = nk * PK */
5915 	if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
5916 		goto fail;
5917 
5918 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
5919 			Nx, Nx_len);
5920 
5921 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
5922 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
5923 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
5924 		goto fail;
5925 	}
5926 	intro->pmk_len = curve->hash_len;
5927 
5928 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
5929 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
5930 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
5931 		goto fail;
5932 	}
5933 
5934 	ret = DPP_STATUS_OK;
5935 fail:
5936 	if (ret != DPP_STATUS_OK)
5937 		os_memset(intro, 0, sizeof(*intro));
5938 	forced_memzero(Nx, sizeof(Nx));
5939 	os_free(own_conn);
5940 	os_free(signed_connector);
5941 	os_free(info.payload);
5942 	crypto_ec_free_key(own_key);
5943 	wpabuf_free(own_key_pub);
5944 	crypto_ec_free_key(peer_key);
5945 	crypto_ec_free_key(csign);
5946 	json_free(root);
5947 	json_free(own_root);
5948 	return ret;
5949 }
5950 
5951 #ifdef CONFIG_TESTING_OPTIONS
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)5952 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
5953 				    const struct dpp_curve_params *curve)
5954 {
5955 	return 0;
5956 }
5957 
dpp_corrupt_connector_signature(const char * connector)5958 char * dpp_corrupt_connector_signature(const char *connector)
5959 {
5960 	char *tmp, *pos, *signed3 = NULL;
5961 	unsigned char *signature = NULL;
5962 	size_t signature_len = 0, signed3_len;
5963 
5964 	tmp = os_zalloc(os_strlen(connector) + 5);
5965 	if (!tmp)
5966 		goto fail;
5967 	os_memcpy(tmp, connector, os_strlen(connector));
5968 
5969 	pos = os_strchr(tmp, '.');
5970 	if (!pos)
5971 		goto fail;
5972 
5973 	pos = os_strchr(pos + 1, '.');
5974 	if (!pos)
5975 		goto fail;
5976 	pos++;
5977 
5978 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
5979 		   pos);
5980 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
5981 	if (!signature || signature_len == 0)
5982 		goto fail;
5983 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
5984 		    signature, signature_len);
5985 	signature[signature_len - 1] ^= 0x01;
5986 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
5987 		    signature, signature_len);
5988 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
5989 	if (!signed3)
5990 		goto fail;
5991 	os_memcpy(pos, signed3, signed3_len);
5992 	pos[signed3_len] = '\0';
5993 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
5994 		   pos);
5995 
5996 out:
5997 	os_free(signature);
5998 	os_free(signed3);
5999 	return tmp;
6000 fail:
6001 	os_free(tmp);
6002 	tmp = NULL;
6003 	goto out;
6004 }
6005 #endif /* CONFIG_TESTING_OPTIONS */
6006 
dpp_next_id(struct dpp_global * dpp)6007 static unsigned int dpp_next_id(struct dpp_global *dpp)
6008 {
6009 	struct dpp_bootstrap_info *bi;
6010 	unsigned int max_id = 0;
6011 
6012 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6013 		if (bi->id > max_id)
6014 			max_id = bi->id;
6015 	}
6016 	return max_id + 1;
6017 }
6018 
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)6019 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
6020 {
6021 	struct dpp_bootstrap_info *bi, *tmp;
6022 	int found = 0;
6023 
6024 	if (!dpp)
6025 		return -1;
6026 
6027 	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
6028 			      struct dpp_bootstrap_info, list) {
6029 		if (id && bi->id != id)
6030 			continue;
6031 		found = 1;
6032 		dl_list_del(&bi->list);
6033 		dpp_bootstrap_info_free(bi);
6034 	}
6035 
6036 	if (id == 0)
6037 		return 0; /* flush succeeds regardless of entries found */
6038 	return found ? 0 : -1;
6039 }
6040 
6041 
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)6042 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
6043 					    const char *uri)
6044 {
6045 	struct dpp_bootstrap_info *bi;
6046 
6047 	if (!dpp)
6048 		return NULL;
6049 
6050 	bi = dpp_parse_uri(uri);
6051 	if (!bi)
6052 		return NULL;
6053 
6054 	bi->type = DPP_BOOTSTRAP_QR_CODE;
6055 	bi->id = dpp_next_id(dpp);
6056 	dl_list_add(&dpp->bootstrap, &bi->list);
6057 	return bi;
6058 }
6059 
6060 
dpp_add_nfc_uri(struct dpp_global * dpp,const char * uri)6061 struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
6062 					    const char *uri)
6063 {
6064 	struct dpp_bootstrap_info *bi;
6065 
6066 	if (!dpp)
6067 		return NULL;
6068 
6069 	bi = dpp_parse_uri(uri);
6070 	if (!bi)
6071 		return NULL;
6072 
6073 	bi->type = DPP_BOOTSTRAP_NFC_URI;
6074 	bi->id = dpp_next_id(dpp);
6075 	dl_list_add(&dpp->bootstrap, &bi->list);
6076 	return bi;
6077 }
6078 
6079 
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)6080 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
6081 {
6082 	char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
6083 	char *key = NULL;
6084 	u8 *privkey = NULL;
6085 	size_t privkey_len = 0;
6086 	size_t len;
6087 	int ret = -1;
6088 	struct dpp_bootstrap_info *bi;
6089 
6090 	bi = os_zalloc(sizeof(*bi));
6091 	if (!bi)
6092 		goto fail;
6093 
6094 	if (os_strstr(cmd, "type=qrcode"))
6095 		bi->type = DPP_BOOTSTRAP_QR_CODE;
6096 	else if (os_strstr(cmd, "type=pkex"))
6097 		bi->type = DPP_BOOTSTRAP_PKEX;
6098 	else if (os_strstr(cmd, "type=nfc-uri"))
6099 		bi->type = DPP_BOOTSTRAP_NFC_URI;
6100 	else
6101 		goto fail;
6102 
6103 	chan = get_param(cmd, " chan=");
6104 	mac = get_param(cmd, " mac=");
6105 	info = get_param(cmd, " info=");
6106 	curve = get_param(cmd, " curve=");
6107 	key = get_param(cmd, " key=");
6108 
6109 	if (key) {
6110 		privkey_len = os_strlen(key) / 2;
6111 		privkey = os_malloc(privkey_len);
6112 		if (!privkey ||
6113 		    hexstr2bin(key, privkey, privkey_len) < 0)
6114 			goto fail;
6115 	}
6116 	wpa_hexdump(MSG_DEBUG, "private key", privkey, privkey_len);
6117 
6118 	pk = dpp_keygen(bi, curve, privkey, privkey_len);
6119 	if (!pk)
6120 		goto fail;
6121 
6122 	len = 4; /* "DPP:" */
6123 	if (chan) {
6124 		if (dpp_parse_uri_chan_list(bi, chan) < 0)
6125 			goto fail;
6126 		len += 3 + os_strlen(chan); /* C:...; */
6127 	}
6128 	if (mac) {
6129 		if (dpp_parse_uri_mac(bi, mac) < 0)
6130 			goto fail;
6131 		len += 3 + os_strlen(mac); /* M:...; */
6132 	}
6133 	if (info) {
6134 		if (dpp_parse_uri_info(bi, info) < 0)
6135 			goto fail;
6136 		len += 3 + os_strlen(info); /* I:...; */
6137 	}
6138 	len += 4 + os_strlen(pk);
6139 	bi->uri = os_malloc(len + 1);
6140 	if (!bi->uri)
6141 		goto fail;
6142 	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
6143 		    chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
6144 		    mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
6145 		    info ? "I:" : "", info ? info : "", info ? ";" : "",
6146 		    pk);
6147 
6148 	bi->id = dpp_next_id(dpp);
6149 	dl_list_add(&dpp->bootstrap, &bi->list);
6150 	ret = bi->id;
6151 	bi = NULL;
6152 fail:
6153 	os_free(curve);
6154 	os_free(pk);
6155 	os_free(chan);
6156 	os_free(mac);
6157 	os_free(info);
6158 	str_clear_free(key);
6159 	bin_clear_free(privkey, privkey_len);
6160 	dpp_bootstrap_info_free(bi);
6161 	return ret;
6162 }
6163 
6164 
6165 struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)6166 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
6167 {
6168 	struct dpp_bootstrap_info *bi;
6169 
6170 	if (!dpp)
6171 		return NULL;
6172 
6173 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6174 		if (bi->id == id)
6175 			return bi;
6176 	}
6177 	return NULL;
6178 }
6179 
6180 
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)6181 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
6182 {
6183 	unsigned int id_val;
6184 
6185 	if (os_strcmp(id, "*") == 0) {
6186 		id_val = 0;
6187 	} else {
6188 		id_val = atoi(id);
6189 		if (id_val == 0)
6190 			return -1;
6191 	}
6192 
6193 	return dpp_bootstrap_del(dpp, id_val);
6194 }
6195 
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)6196 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
6197 {
6198 	struct dpp_bootstrap_info *bi;
6199 
6200 	bi = dpp_bootstrap_get_id(dpp, id);
6201 	if (!bi)
6202 		return NULL;
6203 	return bi->uri;
6204 }
6205 
dpp_get_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)6206 int dpp_get_bootstrap_info(struct dpp_global *dpp, int id,
6207 		       char *reply, int reply_size)
6208 {
6209 	struct dpp_bootstrap_info *bi;
6210 	char pkhash[2 * SHA256_MAC_LEN + 1];
6211 
6212 	bi = dpp_bootstrap_get_id(dpp, id);
6213 	if (!bi)
6214 		return -1;
6215 	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
6216 			 SHA256_MAC_LEN);
6217 	return os_snprintf(reply, reply_size, "type=%s\n"
6218 			   "mac_addr=" MACSTR "\n"
6219 			   "info=%s\n"
6220 			   "num_freq=%u\n"
6221 			   "curve=%s\n"
6222 			   "pkhash=%s\n",
6223 			   dpp_bootstrap_type_txt(bi->type),
6224 			   MAC2STR(bi->mac_addr),
6225 			   bi->info ? bi->info : "",
6226 			   bi->num_freq,
6227 			   bi->curve->name,
6228 			   pkhash);
6229 }
6230 
6231 
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)6232 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
6233 			     const u8 *r_bootstrap,
6234 			     struct dpp_bootstrap_info **own_bi,
6235 			     struct dpp_bootstrap_info **peer_bi)
6236 {
6237 	struct dpp_bootstrap_info *bi;
6238 
6239 	*own_bi = NULL;
6240 	*peer_bi = NULL;
6241 	if (!dpp)
6242 		return;
6243 
6244 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
6245 		if (!*own_bi && bi->own &&
6246 		    os_memcmp(bi->pubkey_hash, r_bootstrap,
6247 			      SHA256_MAC_LEN) == 0) {
6248 			wpa_printf(MSG_DEBUG,
6249 				   "DPP: Found matching own bootstrapping information");
6250 			*own_bi = bi;
6251 		}
6252 
6253 		if (!*peer_bi && !bi->own &&
6254 		    os_memcmp(bi->pubkey_hash, i_bootstrap,
6255 			      SHA256_MAC_LEN) == 0) {
6256 			wpa_printf(MSG_DEBUG,
6257 				   "DPP: Found matching peer bootstrapping information");
6258 			*peer_bi = bi;
6259 		}
6260 
6261 		if (*own_bi && *peer_bi)
6262 			break;
6263 	}
6264 
6265 }
6266 
6267 
dpp_next_configurator_id(struct dpp_global * dpp)6268 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
6269 {
6270 	struct dpp_configurator *conf;
6271 	unsigned int max_id = 0;
6272 
6273 	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
6274 			 list) {
6275 		if (conf->id > max_id)
6276 			max_id = conf->id;
6277 	}
6278 	return max_id + 1;
6279 }
6280 
6281 
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)6282 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
6283 {
6284 	char *curve = NULL;
6285 	char *key = NULL;
6286 	u8 *privkey = NULL;
6287 	size_t privkey_len = 0;
6288 	int ret = -1;
6289 	struct dpp_configurator *conf = NULL;
6290 
6291 	curve = get_param(cmd, " curve=");
6292 	key = get_param(cmd, " key=");
6293 
6294 	if (key) {
6295 		privkey_len = os_strlen(key) / 2;
6296 		privkey = os_malloc(privkey_len);
6297 		if (!privkey ||
6298 		    hexstr2bin(key, privkey, privkey_len) < 0)
6299 			goto fail;
6300 	}
6301 
6302 	conf = dpp_keygen_configurator(curve, privkey, privkey_len);
6303 	if (!conf)
6304 		goto fail;
6305 
6306 	conf->id = dpp_next_configurator_id(dpp);
6307 	dl_list_add(&dpp->configurator, &conf->list);
6308 	ret = conf->id;
6309 	conf = NULL;
6310 fail:
6311 	os_free(curve);
6312 	str_clear_free(key);
6313 	bin_clear_free(privkey, privkey_len);
6314 	dpp_configurator_free(conf);
6315 	return ret;
6316 }
6317 
6318 
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)6319 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
6320 {
6321 	struct dpp_configurator *conf, *tmp;
6322 	int found = 0;
6323 
6324 	if (!dpp)
6325 		return -1;
6326 
6327 	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
6328 			      struct dpp_configurator, list) {
6329 		if (id && conf->id != id)
6330 			continue;
6331 		found = 1;
6332 		dl_list_del(&conf->list);
6333 		dpp_configurator_free(conf);
6334 	}
6335 
6336 	if (id == 0)
6337 		return 0; /* flush succeeds regardless of entries found */
6338 	return found ? 0 : -1;
6339 }
6340 
6341 
dpp_configurator_remove(struct dpp_global * dpp,const char * id)6342 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
6343 {
6344 	unsigned int id_val;
6345 
6346 	if (os_strcmp(id, "*") == 0) {
6347 		id_val = 0;
6348 	} else {
6349 		id_val = atoi(id);
6350 		if (id_val == 0)
6351 			return -1;
6352 	}
6353 
6354 	return dpp_configurator_del(dpp, id_val);
6355 }
6356 
6357 
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)6358 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
6359 				char *buf, size_t buflen)
6360 {
6361 	struct dpp_configurator *conf;
6362 
6363 	conf = dpp_configurator_get_id(dpp, id);
6364 	if (!conf)
6365 		return -1;
6366 
6367 	return dpp_configurator_get_key(conf, buf, buflen);
6368 }
6369 
dpp_global_init(struct dpp_global_config * config)6370 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
6371 {
6372 	struct dpp_global *dpp;
6373 
6374 	dpp = os_zalloc(sizeof(*dpp));
6375 	if (!dpp)
6376 		return NULL;
6377 	dpp->msg_ctx = config->msg_ctx;
6378 
6379 	dl_list_init(&dpp->bootstrap);
6380 	dl_list_init(&dpp->configurator);
6381 
6382 	return dpp;
6383 }
6384 
6385 
dpp_global_clear(struct dpp_global * dpp)6386 void dpp_global_clear(struct dpp_global *dpp)
6387 {
6388 	if (!dpp)
6389 		return;
6390 
6391 	dpp_bootstrap_del(dpp, 0);
6392 	dpp_configurator_del(dpp, 0);
6393 }
6394 
6395 
dpp_global_deinit(struct dpp_global * dpp)6396 void dpp_global_deinit(struct dpp_global *dpp)
6397 {
6398 	dpp_global_clear(dpp);
6399 	os_free(dpp);
6400 }
6401