1  /*
2   * DPP functionality shared between hostapd and wpa_supplicant
3   * Copyright (c) 2017, Qualcomm Atheros, Inc.
4   * Copyright (c) 2018-2020, The Linux Foundation
5   * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
6   *
7   * This software may be distributed under the terms of the BSD license.
8   * See README for more details.
9   */
10  
11  #include "utils/includes.h"
12  
13  #include "utils/common.h"
14  #include "utils/base64.h"
15  #include "utils/json.h"
16  #include "utils/ip_addr.h"
17  #include "common/ieee802_11_common.h"
18  #include "common/wpa_ctrl.h"
19  #include "common/gas.h"
20  #include "eap_common/eap_defs.h"
21  #include "crypto/crypto.h"
22  #include "crypto/random.h"
23  #include "crypto/aes.h"
24  #include "crypto/aes_siv.h"
25  #include "drivers/driver.h"
26  #include "dpp.h"
27  #include "dpp_i.h"
28  
29  
30  #ifdef CONFIG_TESTING_OPTIONS
31  #ifdef CONFIG_DPP3
32  int dpp_version_override = 3;
33  #elif defined(CONFIG_DPP2)
34  int dpp_version_override = 2;
35  #else
36  int dpp_version_override = 1;
37  #endif
38  enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
39  #endif /* CONFIG_TESTING_OPTIONS */
40  
41  
dpp_auth_fail(struct dpp_authentication * auth,const char * txt)42  void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
43  {
44  	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
45  }
46  
47  
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)48  struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
49  			      size_t len)
50  {
51  	struct wpabuf *msg;
52  
53  	msg = wpabuf_alloc(8 + len);
54  	if (!msg)
55  		return NULL;
56  	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
57  	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
58  	wpabuf_put_be24(msg, OUI_WFA);
59  	wpabuf_put_u8(msg, DPP_OUI_TYPE);
60  	wpabuf_put_u8(msg, 1); /* Crypto Suite */
61  	wpabuf_put_u8(msg, type);
62  	return msg;
63  }
64  
65  
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)66  const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
67  {
68  	u16 id, alen;
69  	const u8 *pos = buf, *end = buf + len;
70  
71  	while (end - pos >= 4) {
72  		id = WPA_GET_LE16(pos);
73  		pos += 2;
74  		alen = WPA_GET_LE16(pos);
75  		pos += 2;
76  		if (alen > end - pos)
77  			return NULL;
78  		if (id == req_id) {
79  			*ret_len = alen;
80  			return pos;
81  		}
82  		pos += alen;
83  	}
84  
85  	return NULL;
86  }
87  
88  
dpp_get_attr_next(const u8 * prev,const u8 * buf,size_t len,u16 req_id,u16 * ret_len)89  static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len,
90  				    u16 req_id, u16 *ret_len)
91  {
92  	u16 id, alen;
93  	const u8 *pos, *end = buf + len;
94  
95  	if (!prev)
96  		pos = buf;
97  	else
98  		pos = prev + WPA_GET_LE16(prev - 2);
99  	while (end - pos >= 4) {
100  		id = WPA_GET_LE16(pos);
101  		pos += 2;
102  		alen = WPA_GET_LE16(pos);
103  		pos += 2;
104  		if (alen > end - pos)
105  			return NULL;
106  		if (id == req_id) {
107  			*ret_len = alen;
108  			return pos;
109  		}
110  		pos += alen;
111  	}
112  
113  	return NULL;
114  }
115  
116  
dpp_check_attrs(const u8 * buf,size_t len)117  int dpp_check_attrs(const u8 *buf, size_t len)
118  {
119  	const u8 *pos, *end;
120  	int wrapped_data = 0;
121  
122  	pos = buf;
123  	end = buf + len;
124  	while (end - pos >= 4) {
125  		u16 id, alen;
126  
127  		id = WPA_GET_LE16(pos);
128  		pos += 2;
129  		alen = WPA_GET_LE16(pos);
130  		pos += 2;
131  		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
132  			   id, alen);
133  		if (alen > end - pos) {
134  			wpa_printf(MSG_DEBUG,
135  				   "DPP: Truncated message - not enough room for the attribute - dropped");
136  			return -1;
137  		}
138  		if (wrapped_data) {
139  			wpa_printf(MSG_DEBUG,
140  				   "DPP: An unexpected attribute included after the Wrapped Data attribute");
141  			return -1;
142  		}
143  		if (id == DPP_ATTR_WRAPPED_DATA)
144  			wrapped_data = 1;
145  		pos += alen;
146  	}
147  
148  	if (end != pos) {
149  		wpa_printf(MSG_DEBUG,
150  			   "DPP: Unexpected octets (%d) after the last attribute",
151  			   (int) (end - pos));
152  		return -1;
153  	}
154  
155  	return 0;
156  }
157  
158  
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)159  void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
160  {
161  	if (!info)
162  		return;
163  	os_free(info->uri);
164  	os_free(info->info);
165  	os_free(info->chan);
166  	os_free(info->host);
167  	os_free(info->pk);
168  	crypto_ec_key_deinit(info->pubkey);
169  	str_clear_free(info->configurator_params);
170  	os_free(info);
171  }
172  
173  
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)174  const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
175  {
176  	switch (type) {
177  	case DPP_BOOTSTRAP_QR_CODE:
178  		return "QRCODE";
179  	case DPP_BOOTSTRAP_PKEX:
180  		return "PKEX";
181  	case DPP_BOOTSTRAP_NFC_URI:
182  		return "NFC-URI";
183  	}
184  	return "??";
185  }
186  
187  
dpp_uri_valid_info(const char * info)188  static int dpp_uri_valid_info(const char *info)
189  {
190  	while (*info) {
191  		unsigned char val = *info++;
192  
193  		if (val < 0x20 || val > 0x7e || val == 0x3b)
194  			return 0;
195  	}
196  
197  	return 1;
198  }
199  
200  
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)201  static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
202  {
203  	bi->uri = os_strdup(uri);
204  	return bi->uri ? 0 : -1;
205  }
206  
207  
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)208  int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
209  			    const char *chan_list)
210  {
211  	const char *pos = chan_list, *pos2;
212  	int opclass = -1, channel, freq;
213  
214  	while (pos && *pos && *pos != ';') {
215  		pos2 = pos;
216  		while (*pos2 >= '0' && *pos2 <= '9')
217  			pos2++;
218  		if (*pos2 == '/') {
219  			opclass = atoi(pos);
220  			pos = pos2 + 1;
221  		}
222  		if (opclass <= 0)
223  			goto fail;
224  		channel = atoi(pos);
225  		if (channel <= 0)
226  			goto fail;
227  		while (*pos >= '0' && *pos <= '9')
228  			pos++;
229  		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
230  		wpa_printf(MSG_DEBUG,
231  			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
232  			   opclass, channel, freq);
233  		bi->channels_listed = true;
234  		if (freq < 0) {
235  			wpa_printf(MSG_DEBUG,
236  				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
237  				   opclass, channel);
238  		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
239  			wpa_printf(MSG_DEBUG,
240  				   "DPP: Too many channels in URI channel-list - ignore list");
241  			bi->num_freq = 0;
242  			break;
243  		} else {
244  			bi->freq[bi->num_freq++] = freq;
245  		}
246  
247  		if (*pos == ';' || *pos == '\0')
248  			break;
249  		if (*pos != ',')
250  			goto fail;
251  		pos++;
252  	}
253  
254  	return 0;
255  fail:
256  	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
257  	return -1;
258  }
259  
260  
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)261  int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
262  {
263  	if (!mac)
264  		return 0;
265  
266  	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
267  		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
268  		return -1;
269  	}
270  
271  	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
272  
273  	return 0;
274  }
275  
276  
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)277  int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
278  {
279  	const char *end;
280  
281  	if (!info)
282  		return 0;
283  
284  	end = os_strchr(info, ';');
285  	if (!end)
286  		end = info + os_strlen(info);
287  	bi->info = os_malloc(end - info + 1);
288  	if (!bi->info)
289  		return -1;
290  	os_memcpy(bi->info, info, end - info);
291  	bi->info[end - info] = '\0';
292  	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
293  	if (!dpp_uri_valid_info(bi->info)) {
294  		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
295  		return -1;
296  	}
297  
298  	return 0;
299  }
300  
301  
dpp_parse_uri_version(struct dpp_bootstrap_info * bi,const char * version)302  static int dpp_parse_uri_version(struct dpp_bootstrap_info *bi,
303  				 const char *version)
304  {
305  #ifdef CONFIG_DPP2
306  	if (!version || DPP_VERSION < 2)
307  		return 0;
308  
309  	if (*version == '1')
310  		bi->version = 1;
311  	else if (*version == '2')
312  		bi->version = 2;
313  	else if (*version == '3')
314  		bi->version = 3;
315  	else
316  		wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
317  
318  	wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version);
319  #endif /* CONFIG_DPP2 */
320  
321  	return 0;
322  }
323  
324  
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)325  static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
326  {
327  	u8 *data;
328  	size_t data_len;
329  	int res;
330  	const char *end;
331  
332  	end = os_strchr(info, ';');
333  	if (!end)
334  		return -1;
335  
336  	data = base64_decode(info, end - info, &data_len);
337  	if (!data) {
338  		wpa_printf(MSG_DEBUG,
339  			   "DPP: Invalid base64 encoding on URI public-key");
340  		return -1;
341  	}
342  	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
343  		    data, data_len);
344  
345  	res = dpp_get_subject_public_key(bi, data, data_len);
346  	os_free(data);
347  	return res;
348  }
349  
350  
dpp_parse_uri_supported_curves(struct dpp_bootstrap_info * bi,const char * txt)351  static int dpp_parse_uri_supported_curves(struct dpp_bootstrap_info *bi,
352  					  const char *txt)
353  {
354  	int val;
355  
356  	if (!txt)
357  		return 0;
358  
359  	val = hex2num(txt[0]);
360  	if (val < 0)
361  		return -1;
362  	bi->supported_curves = val;
363  
364  	val = hex2num(txt[1]);
365  	if (val > 0)
366  		bi->supported_curves |= val << 4;
367  
368  	wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
369  		   bi->supported_curves);
370  
371  	return 0;
372  }
373  
374  
dpp_parse_uri_host(struct dpp_bootstrap_info * bi,const char * txt)375  static int dpp_parse_uri_host(struct dpp_bootstrap_info *bi, const char *txt)
376  {
377  	const char *end;
378  	char *port;
379  	struct hostapd_ip_addr addr;
380  	char buf[100], *pos;
381  
382  	if (!txt)
383  		return 0;
384  
385  	end = os_strchr(txt, ';');
386  	if (!end)
387  		end = txt + os_strlen(txt);
388  	if (end - txt > (int) sizeof(buf) - 1)
389  		return -1;
390  	os_memcpy(buf, txt, end - txt);
391  	buf[end - txt] = '\0';
392  
393  	bi->port = DPP_TCP_PORT;
394  
395  	pos = buf;
396  	if (*pos == '[') {
397  		pos = &buf[1];
398  		port = os_strchr(pos, ']');
399  		if (!port)
400  			return -1;
401  		*port++ = '\0';
402  		if (*port == ':')
403  			bi->port = atoi(port + 1);
404  	}
405  
406  	if (hostapd_parse_ip_addr(pos, &addr) < 0) {
407  		if (buf[0] != '[') {
408  			port = os_strrchr(pos, ':');
409  			if (port) {
410  				*port++ = '\0';
411  				bi->port = atoi(port);
412  			}
413  		}
414  		if (hostapd_parse_ip_addr(pos, &addr) < 0) {
415  			wpa_printf(MSG_INFO,
416  				   "DPP: Invalid IP address in URI host entry: %s",
417  				   pos);
418  			return -1;
419  		}
420  	}
421  	os_free(bi->host);
422  	bi->host = os_memdup(&addr, sizeof(addr));
423  	if (!bi->host)
424  		return -1;
425  
426  	wpa_printf(MSG_DEBUG, "DPP: host: %s port: %u",
427  		   hostapd_ip_txt(bi->host, buf, sizeof(buf)), bi->port);
428  
429  	return 0;
430  }
431  
432  
dpp_parse_uri(const char * uri)433  static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
434  {
435  	const char *pos = uri;
436  	const char *end;
437  	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
438  	const char *version = NULL, *supported_curves = NULL, *host = NULL;
439  	struct dpp_bootstrap_info *bi;
440  
441  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
442  
443  	if (os_strncmp(pos, "DPP:", 4) != 0) {
444  		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
445  		return NULL;
446  	}
447  	pos += 4;
448  
449  	for (;;) {
450  		end = os_strchr(pos, ';');
451  		if (!end)
452  			break;
453  
454  		if (end == pos) {
455  			/* Handle terminating ";;" and ignore unexpected ";"
456  			 * for parsing robustness. */
457  			pos++;
458  			continue;
459  		}
460  
461  		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
462  			chan_list = pos + 2;
463  		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
464  			mac = pos + 2;
465  		else if (pos[0] == 'I' && pos[1] == ':' && !info)
466  			info = pos + 2;
467  		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
468  			pk = pos + 2;
469  		else if (pos[0] == 'V' && pos[1] == ':' && !version)
470  			version = pos + 2;
471  		else if (pos[0] == 'B' && pos[1] == ':' && !supported_curves)
472  			supported_curves = pos + 2;
473  		else if (pos[0] == 'H' && pos[1] == ':' && !host)
474  			host = pos + 2;
475  		else
476  			wpa_hexdump_ascii(MSG_DEBUG,
477  					  "DPP: Ignore unrecognized URI parameter",
478  					  pos, end - pos);
479  		pos = end + 1;
480  	}
481  
482  	if (!pk) {
483  		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
484  		return NULL;
485  	}
486  
487  	bi = os_zalloc(sizeof(*bi));
488  	if (!bi)
489  		return NULL;
490  
491  	if (dpp_clone_uri(bi, uri) < 0 ||
492  	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
493  	    dpp_parse_uri_mac(bi, mac) < 0 ||
494  	    dpp_parse_uri_info(bi, info) < 0 ||
495  	    dpp_parse_uri_version(bi, version) < 0 ||
496  	    dpp_parse_uri_supported_curves(bi, supported_curves) < 0 ||
497  	    dpp_parse_uri_host(bi, host) < 0 ||
498  	    dpp_parse_uri_pk(bi, pk) < 0) {
499  		dpp_bootstrap_info_free(bi);
500  		bi = NULL;
501  	}
502  
503  	return bi;
504  }
505  
506  
dpp_build_attr_status(struct wpabuf * msg,enum dpp_status_error status)507  void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status)
508  {
509  	wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
510  	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
511  	wpabuf_put_le16(msg, 1);
512  	wpabuf_put_u8(msg, status);
513  }
514  
515  
dpp_build_attr_r_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)516  void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash)
517  {
518  	if (hash) {
519  		wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash");
520  		wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
521  		wpabuf_put_le16(msg, SHA256_MAC_LEN);
522  		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
523  	}
524  }
525  
526  
dpp_channel_ok_init(struct hostapd_hw_modes * own_modes,u16 num_modes,unsigned int freq)527  static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
528  			       u16 num_modes, unsigned int freq)
529  {
530  	u16 m;
531  	int c, flag;
532  
533  	if (!own_modes || !num_modes)
534  		return 1;
535  
536  	for (m = 0; m < num_modes; m++) {
537  		for (c = 0; c < own_modes[m].num_channels; c++) {
538  			if ((unsigned int) own_modes[m].channels[c].freq !=
539  			    freq)
540  				continue;
541  			flag = own_modes[m].channels[c].flag;
542  			if (!(flag & (HOSTAPD_CHAN_DISABLED |
543  				      HOSTAPD_CHAN_NO_IR |
544  				      HOSTAPD_CHAN_RADAR)))
545  				return 1;
546  		}
547  	}
548  
549  	wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
550  	return 0;
551  }
552  
553  
freq_included(const unsigned int freqs[],unsigned int num,unsigned int freq)554  static int freq_included(const unsigned int freqs[], unsigned int num,
555  			 unsigned int freq)
556  {
557  	while (num > 0) {
558  		if (freqs[--num] == freq)
559  			return 1;
560  	}
561  	return 0;
562  }
563  
564  
freq_to_start(unsigned int freqs[],unsigned int num,unsigned int freq)565  static void freq_to_start(unsigned int freqs[], unsigned int num,
566  			  unsigned int freq)
567  {
568  	unsigned int i;
569  
570  	for (i = 0; i < num; i++) {
571  		if (freqs[i] == freq)
572  			break;
573  	}
574  	if (i == 0 || i >= num)
575  		return;
576  	os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
577  	freqs[0] = freq;
578  }
579  
580  
dpp_channel_intersect(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)581  static int dpp_channel_intersect(struct dpp_authentication *auth,
582  				 struct hostapd_hw_modes *own_modes,
583  				 u16 num_modes)
584  {
585  	struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
586  	unsigned int i, freq;
587  
588  	for (i = 0; i < peer_bi->num_freq; i++) {
589  		freq = peer_bi->freq[i];
590  		if (freq_included(auth->freq, auth->num_freq, freq))
591  			continue;
592  		if (dpp_channel_ok_init(own_modes, num_modes, freq))
593  			auth->freq[auth->num_freq++] = freq;
594  	}
595  	if (!auth->num_freq) {
596  		wpa_printf(MSG_INFO,
597  			   "DPP: No available channels for initiating DPP Authentication");
598  		return -1;
599  	}
600  	auth->curr_freq = auth->freq[0];
601  	return 0;
602  }
603  
604  
dpp_channel_local_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)605  static int dpp_channel_local_list(struct dpp_authentication *auth,
606  				  struct hostapd_hw_modes *own_modes,
607  				  u16 num_modes)
608  {
609  	u16 m;
610  	int c, flag;
611  	unsigned int freq;
612  
613  	auth->num_freq = 0;
614  
615  	if (!own_modes || !num_modes) {
616  		auth->freq[0] = 2412;
617  		auth->freq[1] = 2437;
618  		auth->freq[2] = 2462;
619  		auth->num_freq = 3;
620  		return 0;
621  	}
622  
623  	for (m = 0; m < num_modes; m++) {
624  		for (c = 0; c < own_modes[m].num_channels; c++) {
625  			freq = own_modes[m].channels[c].freq;
626  			flag = own_modes[m].channels[c].flag;
627  			if (flag & (HOSTAPD_CHAN_DISABLED |
628  				    HOSTAPD_CHAN_NO_IR |
629  				    HOSTAPD_CHAN_RADAR))
630  				continue;
631  			if (freq_included(auth->freq, auth->num_freq, freq))
632  				continue;
633  			auth->freq[auth->num_freq++] = freq;
634  			if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
635  				m = num_modes;
636  				break;
637  			}
638  		}
639  	}
640  
641  	return auth->num_freq == 0 ? -1 : 0;
642  }
643  
644  
dpp_prepare_channel_list(struct dpp_authentication * auth,unsigned int neg_freq,struct hostapd_hw_modes * own_modes,u16 num_modes)645  int dpp_prepare_channel_list(struct dpp_authentication *auth,
646  			     unsigned int neg_freq,
647  			     struct hostapd_hw_modes *own_modes, u16 num_modes)
648  {
649  	int res;
650  	char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
651  	unsigned int i;
652  
653  	if (!own_modes) {
654  		if (!neg_freq)
655  			return -1;
656  		auth->num_freq = 1;
657  		auth->freq[0] = neg_freq;
658  		auth->curr_freq = neg_freq;
659  		return 0;
660  	}
661  
662  	if (auth->peer_bi->num_freq > 0)
663  		res = dpp_channel_intersect(auth, own_modes, num_modes);
664  	else
665  		res = dpp_channel_local_list(auth, own_modes, num_modes);
666  	if (res < 0)
667  		return res;
668  
669  	/* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
670  	 * likely channels first. */
671  	freq_to_start(auth->freq, auth->num_freq, 2462);
672  	freq_to_start(auth->freq, auth->num_freq, 2412);
673  	freq_to_start(auth->freq, auth->num_freq, 2437);
674  
675  	auth->freq_idx = 0;
676  	auth->curr_freq = auth->freq[0];
677  
678  	pos = freqs;
679  	end = pos + sizeof(freqs);
680  	for (i = 0; i < auth->num_freq; i++) {
681  		res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
682  		if (os_snprintf_error(end - pos, res))
683  			break;
684  		pos += res;
685  	}
686  	*pos = '\0';
687  	wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
688  		   freqs);
689  
690  	return 0;
691  }
692  
693  
dpp_gen_uri(struct dpp_bootstrap_info * bi)694  int dpp_gen_uri(struct dpp_bootstrap_info *bi)
695  {
696  	char macstr[ETH_ALEN * 2 + 10];
697  	size_t len;
698  	char supp_curves[10];
699  	char host[100];
700  
701  	len = 4; /* "DPP:" */
702  	if (bi->chan)
703  		len += 3 + os_strlen(bi->chan); /* C:...; */
704  	if (is_zero_ether_addr(bi->mac_addr))
705  		macstr[0] = '\0';
706  	else
707  		os_snprintf(macstr, sizeof(macstr), "M:" COMPACT_MACSTR ";",
708  			    MAC2STR(bi->mac_addr));
709  	len += os_strlen(macstr); /* M:...; */
710  	if (bi->info)
711  		len += 3 + os_strlen(bi->info); /* I:...; */
712  #ifdef CONFIG_DPP2
713  	len += 4; /* V:2; */
714  #endif /* CONFIG_DPP2 */
715  	len += 4 + os_strlen(bi->pk); /* K:...;; */
716  
717  	if (bi->supported_curves) {
718  		u8 val = bi->supported_curves;
719  
720  		if (val & 0xf0) {
721  			val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
722  			len += os_snprintf(supp_curves, sizeof(supp_curves),
723  					   "B:%02x;", val);
724  		} else {
725  			len += os_snprintf(supp_curves, sizeof(supp_curves),
726  					   "B:%x;", val);
727  		}
728  	} else {
729  		supp_curves[0] = '\0';
730  	}
731  
732  	host[0] = '\0';
733  	if (bi->host) {
734  		char buf[100];
735  		const char *addr;
736  
737  		addr = hostapd_ip_txt(bi->host, buf, sizeof(buf));
738  		if (!addr)
739  			return -1;
740  		if (bi->port == DPP_TCP_PORT)
741  			len += os_snprintf(host, sizeof(host), "H:%s;", addr);
742  		else if (bi->host->af == AF_INET)
743  			len += os_snprintf(host, sizeof(host), "H:%s:%u;",
744  					   addr, bi->port);
745  		else
746  			len += os_snprintf(host, sizeof(host), "H:[%s]:%u;",
747  					   addr, bi->port);
748  	}
749  
750  	os_free(bi->uri);
751  	bi->uri = os_malloc(len + 1);
752  	if (!bi->uri)
753  		return -1;
754  	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%s%sK:%s;;",
755  		    bi->chan ? "C:" : "", bi->chan ? bi->chan : "",
756  		    bi->chan ? ";" : "",
757  		    macstr,
758  		    bi->info ? "I:" : "", bi->info ? bi->info : "",
759  		    bi->info ? ";" : "",
760  		    DPP_VERSION == 3 ? "V:3;" :
761  		    (DPP_VERSION == 2 ? "V:2;" : ""),
762  		    supp_curves,
763  		    host,
764  		    bi->pk);
765  	return 0;
766  }
767  
768  
769  struct dpp_authentication *
dpp_alloc_auth(struct dpp_global * dpp,void * msg_ctx)770  dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx)
771  {
772  	struct dpp_authentication *auth;
773  
774  	auth = os_zalloc(sizeof(*auth));
775  	if (!auth)
776  		return NULL;
777  	auth->global = dpp;
778  	auth->msg_ctx = msg_ctx;
779  	auth->conf_resp_status = 255;
780  	return auth;
781  }
782  
783  
dpp_build_conf_req_attr(struct dpp_authentication * auth,const char * json)784  static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
785  					       const char *json)
786  {
787  	size_t nonce_len;
788  	size_t json_len, clear_len;
789  	struct wpabuf *clear = NULL, *msg = NULL, *pe = NULL;
790  	u8 *wrapped;
791  	size_t attr_len;
792  #ifdef CONFIG_DPP3
793  	u8 auth_i[DPP_MAX_HASH_LEN];
794  #endif /* CONFIG_DPP3 */
795  
796  	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
797  
798  	nonce_len = auth->curve->nonce_len;
799  	if (random_get_bytes(auth->e_nonce, nonce_len)) {
800  		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
801  		goto fail;
802  	}
803  	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
804  	json_len = os_strlen(json);
805  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configRequest JSON", json, json_len);
806  
807  	/* { E-nonce, configAttrib }ke */
808  	clear_len = 4 + nonce_len + 4 + json_len;
809  #ifdef CONFIG_DPP3
810  	if (auth->waiting_new_key) {
811  		pe = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
812  		if (!pe)
813  			goto fail;
814  		clear_len += 4 + wpabuf_len(pe);
815  
816  		if (dpp_derive_auth_i(auth, auth_i) < 0)
817  			goto fail;
818  		clear_len += 4 + auth->curve->hash_len;
819  	}
820  #endif /* CONFIG_DPP3 */
821  	clear = wpabuf_alloc(clear_len);
822  	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
823  #ifdef CONFIG_TESTING_OPTIONS
824  	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
825  		attr_len += 5;
826  #endif /* CONFIG_TESTING_OPTIONS */
827  	msg = wpabuf_alloc(attr_len);
828  	if (!clear || !msg)
829  		goto fail;
830  
831  #ifdef CONFIG_TESTING_OPTIONS
832  	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) {
833  		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
834  		goto skip_e_nonce;
835  	}
836  	if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) {
837  		wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce");
838  		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
839  		wpabuf_put_le16(clear, nonce_len - 1);
840  		wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1);
841  		goto skip_e_nonce;
842  	}
843  	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) {
844  		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
845  		goto skip_wrapped_data;
846  	}
847  #endif /* CONFIG_TESTING_OPTIONS */
848  
849  	/* E-nonce */
850  	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
851  	wpabuf_put_le16(clear, nonce_len);
852  	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
853  
854  #ifdef CONFIG_TESTING_OPTIONS
855  skip_e_nonce:
856  	if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) {
857  		wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib");
858  		goto skip_conf_attr_obj;
859  	}
860  #endif /* CONFIG_TESTING_OPTIONS */
861  
862  #ifdef CONFIG_DPP3
863  	if (pe) {
864  		wpa_printf(MSG_DEBUG, "DPP: Pe");
865  		wpabuf_put_le16(clear, DPP_ATTR_I_PROTOCOL_KEY);
866  		wpabuf_put_le16(clear, wpabuf_len(pe));
867  		wpabuf_put_buf(clear, pe);
868  	}
869  	if (auth->waiting_new_key) {
870  		wpa_printf(MSG_DEBUG, "DPP: Initiator Authentication Tag");
871  		wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
872  		wpabuf_put_le16(clear, auth->curve->hash_len);
873  		wpabuf_put_data(clear, auth_i, auth->curve->hash_len);
874  	}
875  #endif /* CONFIG_DPP3 */
876  
877  	/* configAttrib */
878  	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
879  	wpabuf_put_le16(clear, json_len);
880  	wpabuf_put_data(clear, json, json_len);
881  
882  #ifdef CONFIG_TESTING_OPTIONS
883  skip_conf_attr_obj:
884  #endif /* CONFIG_TESTING_OPTIONS */
885  
886  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
887  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
888  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
889  
890  	/* No AES-SIV AD */
891  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
892  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
893  			    wpabuf_head(clear), wpabuf_len(clear),
894  			    0, NULL, NULL, wrapped) < 0)
895  		goto fail;
896  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
897  		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
898  
899  #ifdef CONFIG_TESTING_OPTIONS
900  	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) {
901  		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
902  		dpp_build_attr_status(msg, DPP_STATUS_OK);
903  	}
904  skip_wrapped_data:
905  #endif /* CONFIG_TESTING_OPTIONS */
906  
907  	wpa_hexdump_buf(MSG_DEBUG,
908  			"DPP: Configuration Request frame attributes", msg);
909  out:
910  	wpabuf_free(clear);
911  	wpabuf_free(pe);
912  	return msg;
913  
914  fail:
915  	wpabuf_free(msg);
916  	msg = NULL;
917  	goto out;
918  }
919  
920  
dpp_write_adv_proto(struct wpabuf * buf)921  void dpp_write_adv_proto(struct wpabuf *buf)
922  {
923  	/* Advertisement Protocol IE */
924  	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
925  	wpabuf_put_u8(buf, 8); /* Length */
926  	wpabuf_put_u8(buf, 0x7f);
927  	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
928  	wpabuf_put_u8(buf, 5);
929  	wpabuf_put_be24(buf, OUI_WFA);
930  	wpabuf_put_u8(buf, DPP_OUI_TYPE);
931  	wpabuf_put_u8(buf, 0x01);
932  }
933  
934  
dpp_write_gas_query(struct wpabuf * buf,struct wpabuf * query)935  void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
936  {
937  	/* GAS Query */
938  	wpabuf_put_le16(buf, wpabuf_len(query));
939  	wpabuf_put_buf(buf, query);
940  }
941  
942  
dpp_build_conf_req(struct dpp_authentication * auth,const char * json)943  struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
944  				   const char *json)
945  {
946  	struct wpabuf *buf, *conf_req;
947  
948  	conf_req = dpp_build_conf_req_attr(auth, json);
949  	if (!conf_req) {
950  		wpa_printf(MSG_DEBUG,
951  			   "DPP: No configuration request data available");
952  		return NULL;
953  	}
954  
955  	buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
956  	if (!buf) {
957  		wpabuf_free(conf_req);
958  		return NULL;
959  	}
960  
961  	dpp_write_adv_proto(buf);
962  	dpp_write_gas_query(buf, conf_req);
963  	wpabuf_free(conf_req);
964  	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf);
965  
966  	return buf;
967  }
968  
969  
dpp_build_conf_req_helper(struct dpp_authentication * auth,const char * name,enum dpp_netrole netrole,const char * mud_url,int * opclasses,const char * extra_name,const char * extra_value)970  struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
971  					  const char *name,
972  					  enum dpp_netrole netrole,
973  					  const char *mud_url, int *opclasses,
974  					  const char *extra_name,
975  					  const char *extra_value)
976  {
977  	size_t len, name_len;
978  	const char *tech = "infra";
979  	const char *dpp_name;
980  	struct wpabuf *buf = NULL, *json = NULL;
981  	char *csr = NULL;
982  
983  #ifdef CONFIG_TESTING_OPTIONS
984  	if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
985  		static const char *bogus_tech = "knfra";
986  
987  		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
988  		tech = bogus_tech;
989  	}
990  #endif /* CONFIG_TESTING_OPTIONS */
991  
992  	dpp_name = name ? name : "Test";
993  	name_len = os_strlen(dpp_name);
994  
995  	len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
996  	if (mud_url && mud_url[0])
997  		len += 10 + os_strlen(mud_url);
998  	if (extra_name && extra_value && extra_name[0] && extra_value[0])
999  		len += 10 + os_strlen(extra_name) + os_strlen(extra_value);
1000  #ifdef CONFIG_DPP2
1001  	if (auth->csr) {
1002  		size_t csr_len;
1003  
1004  		csr = base64_encode_no_lf(wpabuf_head(auth->csr),
1005  					  wpabuf_len(auth->csr), &csr_len);
1006  		if (!csr)
1007  			goto fail;
1008  		len += 30 + csr_len;
1009  	}
1010  #endif /* CONFIG_DPP2 */
1011  	json = wpabuf_alloc(len);
1012  	if (!json)
1013  		goto fail;
1014  
1015  	json_start_object(json, NULL);
1016  	if (json_add_string_escape(json, "name", dpp_name, name_len) < 0)
1017  		goto fail;
1018  	json_value_sep(json);
1019  	json_add_string(json, "wi-fi_tech", tech);
1020  	json_value_sep(json);
1021  	json_add_string(json, "netRole", dpp_netrole_str(netrole));
1022  	if (mud_url && mud_url[0]) {
1023  		json_value_sep(json);
1024  		json_add_string(json, "mudurl", mud_url);
1025  	}
1026  	if (opclasses) {
1027  		int i;
1028  
1029  		json_value_sep(json);
1030  		json_start_array(json, "bandSupport");
1031  		for (i = 0; opclasses[i]; i++)
1032  			wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
1033  		json_end_array(json);
1034  	}
1035  	if (csr) {
1036  		json_value_sep(json);
1037  		json_add_string(json, "pkcs10", csr);
1038  	}
1039  #ifdef CONFIG_DPP3
1040  	json_value_sep(json);
1041  	json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
1042  #endif /* CONFIG_DPP3 */
1043  	if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
1044  		json_value_sep(json);
1045  		wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
1046  	}
1047  	json_end_object(json);
1048  
1049  	buf = dpp_build_conf_req(auth, wpabuf_head(json));
1050  fail:
1051  	wpabuf_free(json);
1052  	os_free(csr);
1053  
1054  	return buf;
1055  }
1056  
1057  
bin_str_eq(const char * val,size_t len,const char * cmp)1058  static int bin_str_eq(const char *val, size_t len, const char *cmp)
1059  {
1060  	return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
1061  }
1062  
1063  
dpp_configuration_alloc(const char * type)1064  struct dpp_configuration * dpp_configuration_alloc(const char *type)
1065  {
1066  	struct dpp_configuration *conf;
1067  	const char *end;
1068  	size_t len;
1069  
1070  	conf = os_zalloc(sizeof(*conf));
1071  	if (!conf)
1072  		goto fail;
1073  
1074  	end = os_strchr(type, ' ');
1075  	if (end)
1076  		len = end - type;
1077  	else
1078  		len = os_strlen(type);
1079  
1080  	if (bin_str_eq(type, len, "psk"))
1081  		conf->akm = DPP_AKM_PSK;
1082  	else if (bin_str_eq(type, len, "sae"))
1083  		conf->akm = DPP_AKM_SAE;
1084  	else if (bin_str_eq(type, len, "psk-sae") ||
1085  		 bin_str_eq(type, len, "psk+sae"))
1086  		conf->akm = DPP_AKM_PSK_SAE;
1087  	else if (bin_str_eq(type, len, "sae-dpp") ||
1088  		 bin_str_eq(type, len, "dpp+sae"))
1089  		conf->akm = DPP_AKM_SAE_DPP;
1090  	else if (bin_str_eq(type, len, "psk-sae-dpp") ||
1091  		 bin_str_eq(type, len, "dpp+psk+sae"))
1092  		conf->akm = DPP_AKM_PSK_SAE_DPP;
1093  	else if (bin_str_eq(type, len, "dpp"))
1094  		conf->akm = DPP_AKM_DPP;
1095  	else if (bin_str_eq(type, len, "dot1x"))
1096  		conf->akm = DPP_AKM_DOT1X;
1097  	else
1098  		goto fail;
1099  
1100  	return conf;
1101  fail:
1102  	dpp_configuration_free(conf);
1103  	return NULL;
1104  }
1105  
1106  
dpp_akm_psk(enum dpp_akm akm)1107  int dpp_akm_psk(enum dpp_akm akm)
1108  {
1109  	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
1110  		akm == DPP_AKM_PSK_SAE_DPP;
1111  }
1112  
1113  
dpp_akm_sae(enum dpp_akm akm)1114  int dpp_akm_sae(enum dpp_akm akm)
1115  {
1116  	return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE ||
1117  		akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
1118  }
1119  
1120  
dpp_akm_legacy(enum dpp_akm akm)1121  int dpp_akm_legacy(enum dpp_akm akm)
1122  {
1123  	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
1124  		akm == DPP_AKM_SAE;
1125  }
1126  
1127  
dpp_akm_dpp(enum dpp_akm akm)1128  int dpp_akm_dpp(enum dpp_akm akm)
1129  {
1130  	return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP ||
1131  		akm == DPP_AKM_PSK_SAE_DPP;
1132  }
1133  
1134  
dpp_akm_ver2(enum dpp_akm akm)1135  int dpp_akm_ver2(enum dpp_akm akm)
1136  {
1137  	return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
1138  }
1139  
1140  
dpp_configuration_valid(const struct dpp_configuration * conf)1141  int dpp_configuration_valid(const struct dpp_configuration *conf)
1142  {
1143  	if (conf->ssid_len == 0)
1144  		return 0;
1145  	if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
1146  		return 0;
1147  	if (dpp_akm_psk(conf->akm) && conf->passphrase) {
1148  		size_t len = os_strlen(conf->passphrase);
1149  
1150  		if (len > 63 || len < 8)
1151  			return 0;
1152  	}
1153  	if (dpp_akm_sae(conf->akm) && !conf->passphrase)
1154  		return 0;
1155  #ifdef CONFIG_DPP3
1156  	if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
1157  		return 0;
1158  #endif /* CONFIG_DPP3 */
1159  	return 1;
1160  }
1161  
1162  
dpp_configuration_free(struct dpp_configuration * conf)1163  void dpp_configuration_free(struct dpp_configuration *conf)
1164  {
1165  	if (!conf)
1166  		return;
1167  	str_clear_free(conf->passphrase);
1168  #ifdef CONFIG_DPP3
1169  	os_free(conf->idpass);
1170  #endif /* CONFIG_DPP3 */
1171  	os_free(conf->group_id);
1172  	os_free(conf->csrattrs);
1173  	os_free(conf->extra_name);
1174  	os_free(conf->extra_value);
1175  	bin_clear_free(conf, sizeof(*conf));
1176  }
1177  
1178  
dpp_configuration_parse_helper(struct dpp_authentication * auth,const char * cmd,int idx)1179  static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
1180  					  const char *cmd, int idx)
1181  {
1182  	const char *pos, *end;
1183  	struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
1184  	struct dpp_configuration *conf = NULL;
1185  	size_t len;
1186  
1187  	pos = os_strstr(cmd, " conf=sta-");
1188  	if (pos) {
1189  		conf_sta = dpp_configuration_alloc(pos + 10);
1190  		if (!conf_sta)
1191  			goto fail;
1192  		conf_sta->netrole = DPP_NETROLE_STA;
1193  		conf = conf_sta;
1194  	}
1195  
1196  	pos = os_strstr(cmd, " conf=ap-");
1197  	if (pos) {
1198  		conf_ap = dpp_configuration_alloc(pos + 9);
1199  		if (!conf_ap)
1200  			goto fail;
1201  		conf_ap->netrole = DPP_NETROLE_AP;
1202  		conf = conf_ap;
1203  	}
1204  
1205  	pos = os_strstr(cmd, " conf=configurator");
1206  	if (pos)
1207  		auth->provision_configurator = 1;
1208  
1209  	if (!conf)
1210  		return 0;
1211  
1212  	pos = os_strstr(cmd, " ssid=");
1213  	if (pos) {
1214  		pos += 6;
1215  		end = os_strchr(pos, ' ');
1216  		conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
1217  		conf->ssid_len /= 2;
1218  		if (conf->ssid_len > sizeof(conf->ssid) ||
1219  		    hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0)
1220  			goto fail;
1221  	} else {
1222  #ifdef CONFIG_TESTING_OPTIONS
1223  		/* use a default SSID for legacy testing reasons */
1224  		os_memcpy(conf->ssid, "test", 4);
1225  		conf->ssid_len = 4;
1226  #else /* CONFIG_TESTING_OPTIONS */
1227  		goto fail;
1228  #endif /* CONFIG_TESTING_OPTIONS */
1229  	}
1230  
1231  	pos = os_strstr(cmd, " ssid_charset=");
1232  	if (pos) {
1233  		if (conf_ap) {
1234  			wpa_printf(MSG_INFO,
1235  				   "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee");
1236  			goto fail;
1237  		}
1238  		conf->ssid_charset = atoi(pos + 14);
1239  	}
1240  
1241  	pos = os_strstr(cmd, " pass=");
1242  	if (pos) {
1243  		size_t pass_len;
1244  
1245  		pos += 6;
1246  		end = os_strchr(pos, ' ');
1247  		pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
1248  		pass_len /= 2;
1249  		conf->passphrase = os_zalloc(pass_len + 1);
1250  		if (!conf->passphrase ||
1251  		    hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
1252  			goto fail;
1253  	}
1254  
1255  #ifdef CONFIG_DPP3
1256  	pos = os_strstr(cmd, " idpass=");
1257  	if (pos) {
1258  		size_t idpass_len;
1259  
1260  		pos += 8;
1261  		end = os_strchr(pos, ' ');
1262  		idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
1263  		idpass_len /= 2;
1264  		conf->idpass = os_zalloc(idpass_len + 1);
1265  		if (!conf->idpass ||
1266  		    hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
1267  			goto fail;
1268  	}
1269  #endif /* CONFIG_DPP3 */
1270  
1271  	pos = os_strstr(cmd, " psk=");
1272  	if (pos) {
1273  		pos += 5;
1274  		if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0)
1275  			goto fail;
1276  		conf->psk_set = 1;
1277  	}
1278  
1279  	pos = os_strstr(cmd, " group_id=");
1280  	if (pos) {
1281  		size_t group_id_len;
1282  
1283  		pos += 10;
1284  		end = os_strchr(pos, ' ');
1285  		group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
1286  		conf->group_id = os_malloc(group_id_len + 1);
1287  		if (!conf->group_id)
1288  			goto fail;
1289  		os_memcpy(conf->group_id, pos, group_id_len);
1290  		conf->group_id[group_id_len] = '\0';
1291  	}
1292  
1293  	pos = os_strstr(cmd, " expiry=");
1294  	if (pos) {
1295  		long int val;
1296  
1297  		pos += 8;
1298  		val = strtol(pos, NULL, 0);
1299  		if (val <= 0)
1300  			goto fail;
1301  		conf->netaccesskey_expiry = val;
1302  	}
1303  
1304  	pos = os_strstr(cmd, " csrattrs=");
1305  	if (pos) {
1306  		pos += 10;
1307  		end = os_strchr(pos, ' ');
1308  		len = end ? (size_t) (end - pos) : os_strlen(pos);
1309  		conf->csrattrs = os_zalloc(len + 1);
1310  		if (!conf->csrattrs)
1311  			goto fail;
1312  		os_memcpy(conf->csrattrs, pos, len);
1313  	}
1314  
1315  	pos = os_strstr(cmd, " conf_extra_name=");
1316  	if (pos) {
1317  		pos += 17;
1318  		end = os_strchr(pos, ' ');
1319  		len = end ? (size_t) (end - pos) : os_strlen(pos);
1320  		conf->extra_name = os_zalloc(len + 1);
1321  		if (!conf->extra_name)
1322  			goto fail;
1323  		os_memcpy(conf->extra_name, pos, len);
1324  	}
1325  
1326  	pos = os_strstr(cmd, " conf_extra_value=");
1327  	if (pos) {
1328  		pos += 18;
1329  		end = os_strchr(pos, ' ');
1330  		len = end ? (size_t) (end - pos) : os_strlen(pos);
1331  		len /= 2;
1332  		conf->extra_value = os_zalloc(len + 1);
1333  		if (!conf->extra_value ||
1334  		    hexstr2bin(pos, (u8 *) conf->extra_value, len) < 0)
1335  			goto fail;
1336  	}
1337  
1338  	if (!dpp_configuration_valid(conf))
1339  		goto fail;
1340  
1341  	if (idx == 0) {
1342  		auth->conf_sta = conf_sta;
1343  		auth->conf_ap = conf_ap;
1344  	} else if (idx == 1) {
1345  		if (!auth->conf_sta)
1346  			auth->conf_sta = conf_sta;
1347  		else
1348  			auth->conf2_sta = conf_sta;
1349  		if (!auth->conf_ap)
1350  			auth->conf_ap = conf_ap;
1351  		else
1352  			auth->conf2_ap = conf_ap;
1353  	} else {
1354  		goto fail;
1355  	}
1356  	return 0;
1357  
1358  fail:
1359  	dpp_configuration_free(conf_sta);
1360  	dpp_configuration_free(conf_ap);
1361  	return -1;
1362  }
1363  
1364  
dpp_configuration_parse(struct dpp_authentication * auth,const char * cmd)1365  static int dpp_configuration_parse(struct dpp_authentication *auth,
1366  				   const char *cmd)
1367  {
1368  	const char *pos;
1369  	char *tmp;
1370  	size_t len;
1371  	int res;
1372  
1373  	pos = os_strstr(cmd, " @CONF-OBJ-SEP@ ");
1374  	if (!pos)
1375  		return dpp_configuration_parse_helper(auth, cmd, 0);
1376  
1377  	len = pos - cmd;
1378  	tmp = os_malloc(len + 1);
1379  	if (!tmp)
1380  		goto fail;
1381  	os_memcpy(tmp, cmd, len);
1382  	tmp[len] = '\0';
1383  	res = dpp_configuration_parse_helper(auth, tmp, 0);
1384  	str_clear_free(tmp);
1385  	if (res)
1386  		goto fail;
1387  	res = dpp_configuration_parse_helper(auth, cmd + len, 1);
1388  	if (res)
1389  		goto fail;
1390  	return 0;
1391  fail:
1392  	dpp_configuration_free(auth->conf_sta);
1393  	dpp_configuration_free(auth->conf2_sta);
1394  	dpp_configuration_free(auth->conf_ap);
1395  	dpp_configuration_free(auth->conf2_ap);
1396  	return -1;
1397  }
1398  
1399  
1400  static struct dpp_configurator *
dpp_configurator_get_id(struct dpp_global * dpp,unsigned int id)1401  dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id)
1402  {
1403  	struct dpp_configurator *conf;
1404  
1405  	if (!dpp)
1406  		return NULL;
1407  
1408  	dl_list_for_each(conf, &dpp->configurator,
1409  			 struct dpp_configurator, list) {
1410  		if (conf->id == id)
1411  			return conf;
1412  	}
1413  	return NULL;
1414  }
1415  
1416  
dpp_set_configurator(struct dpp_authentication * auth,const char * cmd)1417  int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd)
1418  {
1419  	const char *pos;
1420  	char *tmp = NULL;
1421  	int ret = -1;
1422  
1423  	if (!cmd || auth->configurator_set)
1424  		return 0;
1425  	auth->configurator_set = 1;
1426  
1427  	if (cmd[0] != ' ') {
1428  		size_t len;
1429  
1430  		len = os_strlen(cmd);
1431  		tmp = os_malloc(len + 2);
1432  		if (!tmp)
1433  			goto fail;
1434  		tmp[0] = ' ';
1435  		os_memcpy(tmp + 1, cmd, len + 1);
1436  		cmd = tmp;
1437  	}
1438  
1439  	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
1440  
1441  	if (os_strstr(cmd, " conf=query")) {
1442  		auth->configurator_set = 0;
1443  		auth->use_config_query = true;
1444  		ret = 0;
1445  		goto fail;
1446  	}
1447  
1448  	pos = os_strstr(cmd, " configurator=");
1449  	if (!auth->conf && pos) {
1450  		pos += 14;
1451  		auth->conf = dpp_configurator_get_id(auth->global, atoi(pos));
1452  		if (!auth->conf) {
1453  			wpa_printf(MSG_INFO,
1454  				   "DPP: Could not find the specified configurator");
1455  			goto fail;
1456  		}
1457  	}
1458  
1459  	pos = os_strstr(cmd, " conn_status=");
1460  	if (pos) {
1461  		pos += 13;
1462  		auth->send_conn_status = atoi(pos);
1463  	}
1464  
1465  	pos = os_strstr(cmd, " akm_use_selector=");
1466  	if (pos) {
1467  		pos += 18;
1468  		auth->akm_use_selector = atoi(pos);
1469  	}
1470  
1471  	if (dpp_configuration_parse(auth, cmd) < 0) {
1472  		wpa_msg(auth->msg_ctx, MSG_INFO,
1473  			"DPP: Failed to set configurator parameters");
1474  		goto fail;
1475  	}
1476  	ret = 0;
1477  fail:
1478  	os_free(tmp);
1479  	return ret;
1480  }
1481  
1482  
dpp_auth_deinit(struct dpp_authentication * auth)1483  void dpp_auth_deinit(struct dpp_authentication *auth)
1484  {
1485  	unsigned int i;
1486  
1487  	if (!auth)
1488  		return;
1489  	dpp_configuration_free(auth->conf_ap);
1490  	dpp_configuration_free(auth->conf2_ap);
1491  	dpp_configuration_free(auth->conf_sta);
1492  	dpp_configuration_free(auth->conf2_sta);
1493  	crypto_ec_key_deinit(auth->own_protocol_key);
1494  	crypto_ec_key_deinit(auth->peer_protocol_key);
1495  	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1496  	wpabuf_free(auth->req_msg);
1497  	wpabuf_free(auth->resp_msg);
1498  	wpabuf_free(auth->conf_req);
1499  	wpabuf_free(auth->reconfig_req_msg);
1500  	wpabuf_free(auth->reconfig_resp_msg);
1501  	for (i = 0; i < auth->num_conf_obj; i++) {
1502  		struct dpp_config_obj *conf = &auth->conf_obj[i];
1503  
1504  		os_free(conf->connector);
1505  		wpabuf_free(conf->c_sign_key);
1506  		wpabuf_free(conf->certbag);
1507  		wpabuf_free(conf->certs);
1508  		wpabuf_free(conf->cacert);
1509  		os_free(conf->server_name);
1510  		wpabuf_free(conf->pp_key);
1511  	}
1512  #ifdef CONFIG_DPP2
1513  	dpp_free_asymmetric_key(auth->conf_key_pkg);
1514  	os_free(auth->csrattrs);
1515  	wpabuf_free(auth->csr);
1516  	wpabuf_free(auth->priv_key);
1517  	wpabuf_free(auth->cacert);
1518  	wpabuf_free(auth->certbag);
1519  	os_free(auth->trusted_eap_server_name);
1520  	wpabuf_free(auth->conf_resp_tcp);
1521  #endif /* CONFIG_DPP2 */
1522  	wpabuf_free(auth->net_access_key);
1523  	dpp_bootstrap_info_free(auth->tmp_own_bi);
1524  	if (auth->tmp_peer_bi) {
1525  		dl_list_del(&auth->tmp_peer_bi->list);
1526  		dpp_bootstrap_info_free(auth->tmp_peer_bi);
1527  	}
1528  	os_free(auth->e_name);
1529  	os_free(auth->e_mud_url);
1530  	os_free(auth->e_band_support);
1531  #ifdef CONFIG_TESTING_OPTIONS
1532  	os_free(auth->config_obj_override);
1533  	os_free(auth->discovery_override);
1534  	os_free(auth->groups_override);
1535  #endif /* CONFIG_TESTING_OPTIONS */
1536  	bin_clear_free(auth, sizeof(*auth));
1537  }
1538  
1539  
1540  static struct wpabuf *
dpp_build_conf_start(struct dpp_authentication * auth,struct dpp_configuration * conf,size_t tailroom)1541  dpp_build_conf_start(struct dpp_authentication *auth,
1542  		     struct dpp_configuration *conf, size_t tailroom)
1543  {
1544  	struct wpabuf *buf;
1545  
1546  #ifdef CONFIG_TESTING_OPTIONS
1547  	if (auth->discovery_override)
1548  		tailroom += os_strlen(auth->discovery_override);
1549  #endif /* CONFIG_TESTING_OPTIONS */
1550  
1551  	buf = wpabuf_alloc(200 + tailroom);
1552  	if (!buf)
1553  		return NULL;
1554  	json_start_object(buf, NULL);
1555  	json_add_string(buf, "wi-fi_tech", "infra");
1556  	json_value_sep(buf);
1557  #ifdef CONFIG_TESTING_OPTIONS
1558  	if (auth->discovery_override) {
1559  		wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
1560  			   auth->discovery_override);
1561  		wpabuf_put_str(buf, "\"discovery\":");
1562  		wpabuf_put_str(buf, auth->discovery_override);
1563  		json_value_sep(buf);
1564  		return buf;
1565  	}
1566  #endif /* CONFIG_TESTING_OPTIONS */
1567  	json_start_object(buf, "discovery");
1568  	if (((!conf->ssid_charset || auth->peer_version < 2) &&
1569  	     json_add_string_escape(buf, "ssid", conf->ssid,
1570  				    conf->ssid_len) < 0) ||
1571  	    ((conf->ssid_charset && auth->peer_version >= 2) &&
1572  	     json_add_base64url(buf, "ssid64", conf->ssid,
1573  				conf->ssid_len) < 0)) {
1574  		wpabuf_free(buf);
1575  		return NULL;
1576  	}
1577  	if (conf->ssid_charset > 0) {
1578  		json_value_sep(buf);
1579  		json_add_int(buf, "ssid_charset", conf->ssid_charset);
1580  	}
1581  	json_end_object(buf);
1582  	json_value_sep(buf);
1583  
1584  	return buf;
1585  }
1586  
1587  
dpp_build_jwk(struct wpabuf * buf,const char * name,struct crypto_ec_key * key,const char * kid,const struct dpp_curve_params * curve)1588  int dpp_build_jwk(struct wpabuf *buf, const char *name,
1589  		  struct crypto_ec_key *key, const char *kid,
1590  		  const struct dpp_curve_params *curve)
1591  {
1592  	struct wpabuf *pub;
1593  	const u8 *pos;
1594  	int ret = -1;
1595  
1596  	pub = crypto_ec_key_get_pubkey_point(key, 0);
1597  	if (!pub)
1598  		goto fail;
1599  
1600  	json_start_object(buf, name);
1601  	json_add_string(buf, "kty", "EC");
1602  	json_value_sep(buf);
1603  	json_add_string(buf, "crv", curve->jwk_crv);
1604  	json_value_sep(buf);
1605  	pos = wpabuf_head(pub);
1606  	if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0)
1607  		goto fail;
1608  	json_value_sep(buf);
1609  	pos += curve->prime_len;
1610  	if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0)
1611  		goto fail;
1612  	if (kid) {
1613  		json_value_sep(buf);
1614  		json_add_string(buf, "kid", kid);
1615  	}
1616  	json_end_object(buf);
1617  	ret = 0;
1618  fail:
1619  	wpabuf_free(pub);
1620  	return ret;
1621  }
1622  
1623  
dpp_build_legacy_cred_params(struct wpabuf * buf,struct dpp_configuration * conf)1624  static void dpp_build_legacy_cred_params(struct wpabuf *buf,
1625  					 struct dpp_configuration *conf)
1626  {
1627  	if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
1628  		json_add_string_escape(buf, "pass", conf->passphrase,
1629  				       os_strlen(conf->passphrase));
1630  #ifdef CONFIG_DPP3
1631  		if (conf->idpass) {
1632  			json_value_sep(buf);
1633  			json_add_string_escape(buf, "idpass", conf->idpass,
1634  					       os_strlen(conf->idpass));
1635  		}
1636  #endif /* CONFIG_DPP3 */
1637  	} else if (conf->psk_set) {
1638  		char psk[2 * sizeof(conf->psk) + 1];
1639  
1640  		wpa_snprintf_hex(psk, sizeof(psk),
1641  				 conf->psk, sizeof(conf->psk));
1642  		json_add_string(buf, "psk_hex", psk);
1643  		forced_memzero(psk, sizeof(psk));
1644  	}
1645  }
1646  
1647  
dpp_netrole_str(enum dpp_netrole netrole)1648  const char * dpp_netrole_str(enum dpp_netrole netrole)
1649  {
1650  	switch (netrole) {
1651  	case DPP_NETROLE_STA:
1652  		return "sta";
1653  	case DPP_NETROLE_AP:
1654  		return "ap";
1655  	case DPP_NETROLE_CONFIGURATOR:
1656  		return "configurator";
1657  	default:
1658  		return "??";
1659  	}
1660  }
1661  
1662  
dpp_supports_curve(const char * curve,struct dpp_bootstrap_info * bi)1663  static bool dpp_supports_curve(const char *curve, struct dpp_bootstrap_info *bi)
1664  {
1665  	enum dpp_bootstrap_supported_curves idx;
1666  
1667  	if (!bi || !bi->supported_curves)
1668  		return true; /* no support indication available */
1669  
1670  	if (os_strcmp(curve, "prime256v1") == 0)
1671  		idx = DPP_BOOTSTRAP_CURVE_P_256;
1672  	else if (os_strcmp(curve, "secp384r1") == 0)
1673  		idx = DPP_BOOTSTRAP_CURVE_P_384;
1674  	else if (os_strcmp(curve, "secp521r1") == 0)
1675  		idx = DPP_BOOTSTRAP_CURVE_P_521;
1676  	else if (os_strcmp(curve, "brainpoolP256r1") == 0)
1677  		idx = DPP_BOOTSTRAP_CURVE_BP_256;
1678  	else if (os_strcmp(curve, "brainpoolP384r1") == 0)
1679  		idx = DPP_BOOTSTRAP_CURVE_BP_384;
1680  	else if (os_strcmp(curve, "brainpoolP512r1") == 0)
1681  		idx = DPP_BOOTSTRAP_CURVE_BP_512;
1682  	else
1683  		return true;
1684  
1685  	return bi->supported_curves & BIT(idx);
1686  }
1687  
1688  
1689  static struct wpabuf *
dpp_build_conf_obj_dpp(struct dpp_authentication * auth,struct dpp_configuration * conf)1690  dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
1691  		       struct dpp_configuration *conf)
1692  {
1693  	struct wpabuf *buf = NULL;
1694  	char *signed_conn = NULL;
1695  	size_t tailroom;
1696  	const struct dpp_curve_params *curve; /* C-sign-key curve */
1697  	const struct dpp_curve_params *nak_curve; /* netAccessKey curve */
1698  	struct wpabuf *dppcon = NULL;
1699  	size_t extra_len = 1000;
1700  	int incl_legacy;
1701  	enum dpp_akm akm;
1702  	const char *akm_str;
1703  
1704  	if (!auth->conf) {
1705  		wpa_printf(MSG_INFO,
1706  			   "DPP: No configurator specified - cannot generate DPP config object");
1707  		goto fail;
1708  	}
1709  	curve = auth->conf->curve;
1710  	if (dpp_akm_dpp(conf->akm) &&
1711  	    !dpp_supports_curve(curve->name, auth->peer_bi)) {
1712  		wpa_printf(MSG_DEBUG,
1713  			   "DPP: Enrollee does not support C-sign-key curve (%s) - cannot generate config object",
1714  			   curve->name);
1715  		goto fail;
1716  	}
1717  	if (auth->new_curve && auth->new_key_received)
1718  		nak_curve = auth->new_curve;
1719  	else
1720  		nak_curve = auth->curve;
1721  	if (!dpp_supports_curve(nak_curve->name, auth->peer_bi)) {
1722  		wpa_printf(MSG_DEBUG,
1723  			   "DPP: Enrollee does not support netAccessKey curve (%s) - cannot generate config object",
1724  			   nak_curve->name);
1725  		goto fail;
1726  	}
1727  
1728  	akm = conf->akm;
1729  	if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
1730  		wpa_printf(MSG_DEBUG,
1731  			   "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2");
1732  		akm = DPP_AKM_DPP;
1733  	}
1734  
1735  #ifdef CONFIG_TESTING_OPTIONS
1736  	if (auth->groups_override)
1737  		extra_len += os_strlen(auth->groups_override);
1738  #endif /* CONFIG_TESTING_OPTIONS */
1739  
1740  	if (conf->group_id)
1741  		extra_len += os_strlen(conf->group_id);
1742  
1743  	/* Connector (JSON dppCon object) */
1744  	dppcon = wpabuf_alloc(extra_len + 2 * nak_curve->prime_len * 4 / 3);
1745  	if (!dppcon)
1746  		goto fail;
1747  #ifdef CONFIG_TESTING_OPTIONS
1748  	if (auth->groups_override) {
1749  		wpabuf_put_u8(dppcon, '{');
1750  		if (auth->groups_override) {
1751  			wpa_printf(MSG_DEBUG,
1752  				   "DPP: TESTING - groups override: '%s'",
1753  				   auth->groups_override);
1754  			wpabuf_put_str(dppcon, "\"groups\":");
1755  			wpabuf_put_str(dppcon, auth->groups_override);
1756  			json_value_sep(dppcon);
1757  		}
1758  		goto skip_groups;
1759  	}
1760  #endif /* CONFIG_TESTING_OPTIONS */
1761  	json_start_object(dppcon, NULL);
1762  	json_start_array(dppcon, "groups");
1763  	json_start_object(dppcon, NULL);
1764  	json_add_string(dppcon, "groupId",
1765  			conf->group_id ? conf->group_id : "*");
1766  	json_value_sep(dppcon);
1767  	json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole));
1768  	json_end_object(dppcon);
1769  	json_end_array(dppcon);
1770  	json_value_sep(dppcon);
1771  #ifdef CONFIG_TESTING_OPTIONS
1772  skip_groups:
1773  #endif /* CONFIG_TESTING_OPTIONS */
1774  	if (!auth->peer_protocol_key) {
1775  		wpa_printf(MSG_DEBUG,
1776  			   "DPP: No peer protocol key available to build netAccessKey JWK");
1777  		goto fail;
1778  	}
1779  #ifdef CONFIG_DPP3
1780  	if (auth->conf->net_access_key_curve &&
1781  	    auth->curve != auth->conf->net_access_key_curve &&
1782  	    !auth->new_key_received) {
1783  		if (!dpp_supports_curve(auth->conf->net_access_key_curve->name,
1784  					auth->peer_bi)) {
1785  			wpa_printf(MSG_DEBUG,
1786  				   "DPP: Enrollee does not support the required netAccessKey curve (%s) - cannot generate config object",
1787  				   auth->conf->net_access_key_curve->name);
1788  			goto fail;
1789  		}
1790  		wpa_printf(MSG_DEBUG,
1791  			   "DPP: Peer protocol key curve (%s) does not match the required netAccessKey curve (%s) - %s",
1792  			   auth->curve->name,
1793  			   auth->conf->net_access_key_curve->name,
1794  			   auth->waiting_new_key ?
1795  			   "the required key not received" :
1796  			   "request a new key");
1797  		if (auth->waiting_new_key)
1798  			auth->waiting_new_key = false; /* failed */
1799  		else
1800  			auth->waiting_new_key = true;
1801  		goto fail;
1802  	}
1803  #endif /* CONFIG_DPP3 */
1804  	if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
1805  			  nak_curve) < 0) {
1806  		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
1807  		goto fail;
1808  	}
1809  	if (conf->netaccesskey_expiry) {
1810  		struct os_tm tm;
1811  		char expiry[30];
1812  
1813  		if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
1814  			wpa_printf(MSG_DEBUG,
1815  				   "DPP: Failed to generate expiry string");
1816  			goto fail;
1817  		}
1818  		os_snprintf(expiry, sizeof(expiry),
1819  			    "%04u-%02u-%02uT%02u:%02u:%02uZ",
1820  			    tm.year, tm.month, tm.day,
1821  			    tm.hour, tm.min, tm.sec);
1822  		json_value_sep(dppcon);
1823  		json_add_string(dppcon, "expiry", expiry);
1824  	}
1825  #ifdef CONFIG_DPP3
1826  	json_value_sep(dppcon);
1827  	json_add_int(dppcon, "version", auth->peer_version);
1828  #endif /* CONFIG_DPP3 */
1829  	json_end_object(dppcon);
1830  	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
1831  		   (const char *) wpabuf_head(dppcon));
1832  
1833  	signed_conn = dpp_sign_connector(auth->conf, dppcon);
1834  	if (!signed_conn)
1835  		goto fail;
1836  
1837  	incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
1838  	tailroom = 1000;
1839  	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
1840  	tailroom += os_strlen(signed_conn);
1841  	if (incl_legacy)
1842  		tailroom += 1000;
1843  	if (akm == DPP_AKM_DOT1X) {
1844  		if (auth->certbag)
1845  			tailroom += 2 * wpabuf_len(auth->certbag);
1846  		if (auth->cacert)
1847  			tailroom += 2 * wpabuf_len(auth->cacert);
1848  		if (auth->trusted_eap_server_name)
1849  			tailroom += os_strlen(auth->trusted_eap_server_name);
1850  		tailroom += 1000;
1851  	}
1852  	if (conf->extra_name && conf->extra_value)
1853  		tailroom += 10 + os_strlen(conf->extra_name) +
1854  			os_strlen(conf->extra_value);
1855  	buf = dpp_build_conf_start(auth, conf, tailroom);
1856  	if (!buf)
1857  		goto fail;
1858  
1859  	if (auth->akm_use_selector && dpp_akm_ver2(akm))
1860  		akm_str = dpp_akm_selector_str(akm);
1861  	else
1862  		akm_str = dpp_akm_str(akm);
1863  	json_start_object(buf, "cred");
1864  	json_add_string(buf, "akm", akm_str);
1865  	json_value_sep(buf);
1866  	if (incl_legacy) {
1867  		dpp_build_legacy_cred_params(buf, conf);
1868  		json_value_sep(buf);
1869  	}
1870  	if (akm == DPP_AKM_DOT1X) {
1871  		json_start_object(buf, "entCreds");
1872  		if (!auth->certbag)
1873  			goto fail;
1874  		json_add_base64(buf, "certBag", wpabuf_head(auth->certbag),
1875  				wpabuf_len(auth->certbag));
1876  		if (auth->cacert) {
1877  			json_value_sep(buf);
1878  			json_add_base64(buf, "caCert",
1879  					wpabuf_head(auth->cacert),
1880  					wpabuf_len(auth->cacert));
1881  		}
1882  		if (auth->trusted_eap_server_name) {
1883  			json_value_sep(buf);
1884  			json_add_string(buf, "trustedEapServerName",
1885  					auth->trusted_eap_server_name);
1886  		}
1887  		json_value_sep(buf);
1888  		json_start_array(buf, "eapMethods");
1889  		wpabuf_printf(buf, "%d", EAP_TYPE_TLS);
1890  		json_end_array(buf);
1891  		json_end_object(buf);
1892  		json_value_sep(buf);
1893  	}
1894  	wpabuf_put_str(buf, "\"signedConnector\":\"");
1895  	wpabuf_put_str(buf, signed_conn);
1896  	wpabuf_put_str(buf, "\"");
1897  	json_value_sep(buf);
1898  	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
1899  			  curve) < 0) {
1900  		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
1901  		goto fail;
1902  	}
1903  #ifdef CONFIG_DPP2
1904  	if (auth->peer_version >= 2 && auth->conf->pp_key) {
1905  		json_value_sep(buf);
1906  		if (dpp_build_jwk(buf, "ppKey", auth->conf->pp_key, NULL,
1907  				  curve) < 0) {
1908  			wpa_printf(MSG_DEBUG, "DPP: Failed to build ppKey JWK");
1909  			goto fail;
1910  		}
1911  	}
1912  #endif /* CONFIG_DPP2 */
1913  
1914  	json_end_object(buf);
1915  	if (conf->extra_name && conf->extra_value) {
1916  		json_value_sep(buf);
1917  		wpabuf_printf(buf, "\"%s\":%s", conf->extra_name,
1918  			      conf->extra_value);
1919  	}
1920  	json_end_object(buf);
1921  
1922  	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
1923  			      wpabuf_head(buf), wpabuf_len(buf));
1924  
1925  #ifdef CONFIG_DPP3
1926  	if (!auth->conf->net_access_key_curve) {
1927  		/* All netAccessKey values used in the network will have to be
1928  		 * from the same curve for network introduction to work, so
1929  		 * hardcode the first used netAccessKey curve for consecutive
1930  		 * operations if there was no explicit configuration of which
1931  		 * curve to use. */
1932  		wpa_printf(MSG_DEBUG,
1933  			   "DPP: Update Configurator to require netAccessKey curve %s based on first provisioning",
1934  			   nak_curve->name);
1935  		auth->conf->net_access_key_curve = nak_curve;
1936  	}
1937  #endif /* CONFIG_DPP3 */
1938  
1939  out:
1940  	os_free(signed_conn);
1941  	wpabuf_free(dppcon);
1942  	return buf;
1943  fail:
1944  	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
1945  	wpabuf_free(buf);
1946  	buf = NULL;
1947  	goto out;
1948  }
1949  
1950  
1951  static struct wpabuf *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,struct dpp_configuration * conf)1952  dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
1953  			  struct dpp_configuration *conf)
1954  {
1955  	struct wpabuf *buf;
1956  	const char *akm_str;
1957  	size_t len = 1000;
1958  
1959  
1960  #ifdef CONFIG_DPP3
1961  	if (conf->idpass &&
1962  	    !(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
1963  		wpa_printf(MSG_DEBUG,
1964  			   "DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
1965  		return NULL;
1966  	}
1967  #endif /* CONFIG_DPP3 */
1968  
1969  	if (conf->extra_name && conf->extra_value)
1970  		len += 10 + os_strlen(conf->extra_name) +
1971  			os_strlen(conf->extra_value);
1972  	buf = dpp_build_conf_start(auth, conf, len);
1973  	if (!buf)
1974  		return NULL;
1975  
1976  	if (auth->akm_use_selector && dpp_akm_ver2(conf->akm))
1977  		akm_str = dpp_akm_selector_str(conf->akm);
1978  	else
1979  		akm_str = dpp_akm_str(conf->akm);
1980  	json_start_object(buf, "cred");
1981  	json_add_string(buf, "akm", akm_str);
1982  	json_value_sep(buf);
1983  	dpp_build_legacy_cred_params(buf, conf);
1984  	json_end_object(buf);
1985  	if (conf->extra_name && conf->extra_value) {
1986  		json_value_sep(buf);
1987  		wpabuf_printf(buf, "\"%s\":%s", conf->extra_name,
1988  			      conf->extra_value);
1989  	}
1990  	json_end_object(buf);
1991  
1992  	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
1993  			      wpabuf_head(buf), wpabuf_len(buf));
1994  
1995  	return buf;
1996  }
1997  
1998  
dpp_get_peer_bi_id(struct dpp_authentication * auth)1999  static int dpp_get_peer_bi_id(struct dpp_authentication *auth)
2000  {
2001  	struct dpp_bootstrap_info *bi;
2002  
2003  	if (auth->peer_bi)
2004  		return auth->peer_bi->id;
2005  	if (auth->tmp_peer_bi)
2006  		return auth->tmp_peer_bi->id;
2007  
2008  	bi = os_zalloc(sizeof(*bi));
2009  	if (!bi)
2010  		return -1;
2011  	bi->id = dpp_next_id(auth->global);
2012  	dl_list_add(&auth->global->bootstrap, &bi->list);
2013  	auth->tmp_peer_bi = bi;
2014  	return bi->id;
2015  }
2016  
2017  
2018  static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication * auth,enum dpp_netrole netrole,int idx,bool cert_req)2019  dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
2020  		   int idx, bool cert_req)
2021  {
2022  	struct dpp_configuration *conf = NULL;
2023  
2024  #ifdef CONFIG_TESTING_OPTIONS
2025  	if (auth->config_obj_override) {
2026  		if (idx != 0)
2027  			return NULL;
2028  		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
2029  		return wpabuf_alloc_copy(auth->config_obj_override,
2030  					 os_strlen(auth->config_obj_override));
2031  	}
2032  #endif /* CONFIG_TESTING_OPTIONS */
2033  
2034  	if (idx == 0) {
2035  		if (netrole == DPP_NETROLE_STA)
2036  			conf = auth->conf_sta;
2037  		else if (netrole == DPP_NETROLE_AP)
2038  			conf = auth->conf_ap;
2039  	} else if (idx == 1) {
2040  		if (netrole == DPP_NETROLE_STA)
2041  			conf = auth->conf2_sta;
2042  		else if (netrole == DPP_NETROLE_AP)
2043  			conf = auth->conf2_ap;
2044  	}
2045  	if (!conf) {
2046  		if (idx == 0) {
2047  			if (auth->use_config_query) {
2048  				wpa_printf(MSG_DEBUG,
2049  					   "DPP: No configuration available for Enrollee(%s) - waiting for configuration",
2050  					   dpp_netrole_str(netrole));
2051  				auth->waiting_config = true;
2052  				dpp_get_peer_bi_id(auth);
2053  				return NULL;
2054  			}
2055  			wpa_printf(MSG_DEBUG,
2056  				   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
2057  				   dpp_netrole_str(netrole));
2058  		}
2059  		return NULL;
2060  	}
2061  
2062  	if (conf->akm == DPP_AKM_DOT1X) {
2063  		if (!auth->conf) {
2064  			wpa_printf(MSG_DEBUG,
2065  				   "DPP: No Configurator data available");
2066  			return NULL;
2067  		}
2068  		if (!cert_req && !auth->certbag) {
2069  			wpa_printf(MSG_DEBUG,
2070  				   "DPP: No certificate data available for dot1x configuration");
2071  			return NULL;
2072  		}
2073  		return dpp_build_conf_obj_dpp(auth, conf);
2074  	}
2075  	if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf))
2076  		return dpp_build_conf_obj_dpp(auth, conf);
2077  	return dpp_build_conf_obj_legacy(auth, conf);
2078  }
2079  
2080  
2081  struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,enum dpp_netrole netrole,bool cert_req)2082  dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
2083  		    u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req)
2084  {
2085  	struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL, *pc = NULL;
2086  	size_t clear_len, attr_len;
2087  	struct wpabuf *clear = NULL, *msg = NULL;
2088  	u8 *wrapped;
2089  	const u8 *addr[1];
2090  	size_t len[1];
2091  	enum dpp_status_error status;
2092  
2093  	if (auth->force_conf_resp_status != DPP_STATUS_OK) {
2094  		status = auth->force_conf_resp_status;
2095  		goto forced_status;
2096  	}
2097  
2098  	if (netrole == DPP_NETROLE_CONFIGURATOR) {
2099  #ifdef CONFIG_DPP2
2100  		env_data = dpp_build_enveloped_data(auth);
2101  #endif /* CONFIG_DPP2 */
2102  	} else {
2103  		conf = dpp_build_conf_obj(auth, netrole, 0, cert_req);
2104  		if (conf) {
2105  			wpa_hexdump_ascii(MSG_DEBUG,
2106  					  "DPP: configurationObject JSON",
2107  					  wpabuf_head(conf), wpabuf_len(conf));
2108  			conf2 = dpp_build_conf_obj(auth, netrole, 1, cert_req);
2109  		}
2110  	}
2111  
2112  	if (!conf && auth->waiting_config)
2113  		return NULL;
2114  	if (conf || env_data)
2115  		status = DPP_STATUS_OK;
2116  	else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
2117  		 auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr)
2118  		status = DPP_STATUS_CSR_NEEDED;
2119  #ifdef CONFIG_DPP3
2120  	else if (auth->waiting_new_key)
2121  		status = DPP_STATUS_NEW_KEY_NEEDED;
2122  #endif /* CONFIG_DPP3 */
2123  	else
2124  		status = DPP_STATUS_CONFIGURE_FAILURE;
2125  forced_status:
2126  	auth->conf_resp_status = status;
2127  
2128  	/* { E-nonce, configurationObject[, sendConnStatus]}ke */
2129  	clear_len = 4 + e_nonce_len;
2130  	if (conf)
2131  		clear_len += 4 + wpabuf_len(conf);
2132  	if (conf2)
2133  		clear_len += 4 + wpabuf_len(conf2);
2134  	if (env_data)
2135  		clear_len += 4 + wpabuf_len(env_data);
2136  	if (auth->peer_version >= 2 && auth->send_conn_status &&
2137  	    netrole == DPP_NETROLE_STA)
2138  		clear_len += 4;
2139  	if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta &&
2140  	    auth->conf_sta->csrattrs)
2141  		clear_len += 4 + os_strlen(auth->conf_sta->csrattrs);
2142  #ifdef CONFIG_DPP3
2143  	if (status == DPP_STATUS_NEW_KEY_NEEDED) {
2144  		struct crypto_ec_key *new_pc;
2145  
2146  		clear_len += 6; /* Finite Cyclic Group attribute */
2147  
2148  		wpa_printf(MSG_DEBUG,
2149  			   "DPP: Generate a new own protocol key for the curve %s",
2150  			   auth->conf->net_access_key_curve->name);
2151  		new_pc = dpp_gen_keypair(auth->conf->net_access_key_curve);
2152  		if (!new_pc) {
2153  			wpa_printf(MSG_DEBUG, "DPP: Failed to generate new Pc");
2154  			return NULL;
2155  		}
2156  		pc = crypto_ec_key_get_pubkey_point(new_pc, 0);
2157  		if (!pc) {
2158  			crypto_ec_key_deinit(new_pc);
2159  			return NULL;
2160  		}
2161  		crypto_ec_key_deinit(auth->own_protocol_key);
2162  		auth->own_protocol_key = new_pc;
2163  		auth->new_curve = auth->conf->net_access_key_curve;
2164  		clear_len += 4 + wpabuf_len(pc);
2165  	}
2166  #endif /* CONFIG_DPP3 */
2167  	clear = wpabuf_alloc(clear_len);
2168  	attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
2169  #ifdef CONFIG_TESTING_OPTIONS
2170  	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
2171  		attr_len += 5;
2172  #endif /* CONFIG_TESTING_OPTIONS */
2173  	msg = wpabuf_alloc(attr_len);
2174  	if (!clear || !msg)
2175  		goto fail;
2176  
2177  #ifdef CONFIG_TESTING_OPTIONS
2178  	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
2179  		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
2180  		goto skip_e_nonce;
2181  	}
2182  	if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
2183  		wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
2184  		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2185  		wpabuf_put_le16(clear, e_nonce_len);
2186  		wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
2187  		wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
2188  		goto skip_e_nonce;
2189  	}
2190  	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
2191  		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
2192  		goto skip_wrapped_data;
2193  	}
2194  #endif /* CONFIG_TESTING_OPTIONS */
2195  
2196  	/* E-nonce */
2197  	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2198  	wpabuf_put_le16(clear, e_nonce_len);
2199  	wpabuf_put_data(clear, e_nonce, e_nonce_len);
2200  
2201  #ifdef CONFIG_TESTING_OPTIONS
2202  skip_e_nonce:
2203  	if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
2204  		wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
2205  		goto skip_config_obj;
2206  	}
2207  #endif /* CONFIG_TESTING_OPTIONS */
2208  
2209  	if (conf) {
2210  		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
2211  		wpabuf_put_le16(clear, wpabuf_len(conf));
2212  		wpabuf_put_buf(clear, conf);
2213  	}
2214  	if (auth->peer_version >= 2 && conf2) {
2215  		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
2216  		wpabuf_put_le16(clear, wpabuf_len(conf2));
2217  		wpabuf_put_buf(clear, conf2);
2218  	} else if (conf2) {
2219  		wpa_printf(MSG_DEBUG,
2220  			   "DPP: Second Config Object available, but peer does not support more than one");
2221  	}
2222  	if (env_data) {
2223  		wpabuf_put_le16(clear, DPP_ATTR_ENVELOPED_DATA);
2224  		wpabuf_put_le16(clear, wpabuf_len(env_data));
2225  		wpabuf_put_buf(clear, env_data);
2226  	}
2227  
2228  	if (auth->peer_version >= 2 && auth->send_conn_status &&
2229  	    netrole == DPP_NETROLE_STA && status == DPP_STATUS_OK) {
2230  		wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
2231  		wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
2232  		wpabuf_put_le16(clear, 0);
2233  	}
2234  
2235  	if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta &&
2236  	    auth->conf_sta->csrattrs) {
2237  		auth->waiting_csr = true;
2238  		wpa_printf(MSG_DEBUG, "DPP: CSR Attributes Request");
2239  		wpabuf_put_le16(clear, DPP_ATTR_CSR_ATTR_REQ);
2240  		wpabuf_put_le16(clear, os_strlen(auth->conf_sta->csrattrs));
2241  		wpabuf_put_str(clear, auth->conf_sta->csrattrs);
2242  	}
2243  
2244  #ifdef CONFIG_DPP3
2245  	if (status == DPP_STATUS_NEW_KEY_NEEDED && auth->conf &&
2246  	    auth->conf->net_access_key_curve) {
2247  		u16 ike_group = auth->conf->net_access_key_curve->ike_group;
2248  
2249  		/* Finite Cyclic Group attribute */
2250  		wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u",
2251  			   ike_group);
2252  		wpabuf_put_le16(clear, DPP_ATTR_FINITE_CYCLIC_GROUP);
2253  		wpabuf_put_le16(clear, 2);
2254  		wpabuf_put_le16(clear, ike_group);
2255  
2256  		if (pc) {
2257  			wpa_printf(MSG_DEBUG, "DPP: Pc");
2258  			wpabuf_put_le16(clear, DPP_ATTR_R_PROTOCOL_KEY);
2259  			wpabuf_put_le16(clear, wpabuf_len(pc));
2260  			wpabuf_put_buf(clear, pc);
2261  		}
2262  	}
2263  #endif /* CONFIG_DPP3 */
2264  
2265  #ifdef CONFIG_TESTING_OPTIONS
2266  skip_config_obj:
2267  	if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
2268  		wpa_printf(MSG_INFO, "DPP: TESTING - Status");
2269  		goto skip_status;
2270  	}
2271  	if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
2272  		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
2273  		status = 255;
2274  	}
2275  #endif /* CONFIG_TESTING_OPTIONS */
2276  
2277  	/* DPP Status */
2278  	dpp_build_attr_status(msg, status);
2279  
2280  #ifdef CONFIG_TESTING_OPTIONS
2281  skip_status:
2282  #endif /* CONFIG_TESTING_OPTIONS */
2283  
2284  	addr[0] = wpabuf_head(msg);
2285  	len[0] = wpabuf_len(msg);
2286  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
2287  
2288  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2289  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2290  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2291  
2292  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
2293  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2294  			    wpabuf_head(clear), wpabuf_len(clear),
2295  			    1, addr, len, wrapped) < 0)
2296  		goto fail;
2297  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2298  		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
2299  
2300  #ifdef CONFIG_TESTING_OPTIONS
2301  	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) {
2302  		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
2303  		dpp_build_attr_status(msg, DPP_STATUS_OK);
2304  	}
2305  skip_wrapped_data:
2306  #endif /* CONFIG_TESTING_OPTIONS */
2307  
2308  	wpa_hexdump_buf(MSG_DEBUG,
2309  			"DPP: Configuration Response attributes", msg);
2310  out:
2311  	wpabuf_clear_free(conf);
2312  	wpabuf_clear_free(conf2);
2313  	wpabuf_clear_free(env_data);
2314  	wpabuf_clear_free(clear);
2315  	wpabuf_free(pc);
2316  
2317  	return msg;
2318  fail:
2319  	wpabuf_free(msg);
2320  	msg = NULL;
2321  	goto out;
2322  }
2323  
2324  
2325  struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)2326  dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
2327  		size_t attr_len)
2328  {
2329  	const u8 *wrapped_data, *e_nonce, *config_attr;
2330  	u16 wrapped_data_len, e_nonce_len, config_attr_len;
2331  	u8 *unwrapped = NULL;
2332  	size_t unwrapped_len = 0;
2333  	struct wpabuf *resp = NULL;
2334  	struct json_token *root = NULL, *token;
2335  	enum dpp_netrole netrole;
2336  	struct wpabuf *cert_req = NULL;
2337  #ifdef CONFIG_DPP3
2338  	const u8 *i_proto;
2339  	u16 i_proto_len;
2340  #endif /* CONFIG_DPP3 */
2341  
2342  #ifdef CONFIG_TESTING_OPTIONS
2343  	if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
2344  		wpa_printf(MSG_INFO,
2345  			   "DPP: TESTING - stop at Config Request");
2346  		return NULL;
2347  	}
2348  #endif /* CONFIG_TESTING_OPTIONS */
2349  
2350  	if (dpp_check_attrs(attr_start, attr_len) < 0) {
2351  		dpp_auth_fail(auth, "Invalid attribute in config request");
2352  		return NULL;
2353  	}
2354  
2355  	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2356  				    &wrapped_data_len);
2357  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
2358  		dpp_auth_fail(auth,
2359  			      "Missing or invalid required Wrapped Data attribute");
2360  		return NULL;
2361  	}
2362  
2363  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2364  		    wrapped_data, wrapped_data_len);
2365  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2366  	unwrapped = os_malloc(unwrapped_len);
2367  	if (!unwrapped)
2368  		return NULL;
2369  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2370  			    wrapped_data, wrapped_data_len,
2371  			    0, NULL, NULL, unwrapped) < 0) {
2372  		dpp_auth_fail(auth, "AES-SIV decryption failed");
2373  		goto fail;
2374  	}
2375  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2376  		    unwrapped, unwrapped_len);
2377  
2378  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2379  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
2380  		goto fail;
2381  	}
2382  
2383  	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
2384  			       DPP_ATTR_ENROLLEE_NONCE,
2385  			       &e_nonce_len);
2386  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
2387  		dpp_auth_fail(auth,
2388  			      "Missing or invalid Enrollee Nonce attribute");
2389  		goto fail;
2390  	}
2391  	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
2392  	os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
2393  
2394  #ifdef CONFIG_DPP3
2395  	i_proto = dpp_get_attr(unwrapped, unwrapped_len,
2396  			       DPP_ATTR_I_PROTOCOL_KEY, &i_proto_len);
2397  	if (i_proto && !auth->waiting_new_key) {
2398  		dpp_auth_fail(auth,
2399  			      "Enrollee included a new protocol key even though one was not expected");
2400  		goto fail;
2401  	}
2402  	if (i_proto) {
2403  		struct crypto_ec_key *pe;
2404  		u8 auth_i[DPP_MAX_HASH_LEN];
2405  		const u8 *rx_auth_i;
2406  		u16 rx_auth_i_len;
2407  
2408  		wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key (new Pe)",
2409  			    i_proto, i_proto_len);
2410  
2411  		pe = dpp_set_pubkey_point(auth->own_protocol_key,
2412  					  i_proto, i_proto_len);
2413  		if (!pe) {
2414  			dpp_auth_fail(auth,
2415  				      "Invalid Initiator Protocol Key (Pe)");
2416  			goto fail;
2417  		}
2418  		dpp_debug_print_key("New Peer Protocol Key (Pe)", pe);
2419  		crypto_ec_key_deinit(auth->peer_protocol_key);
2420  		auth->peer_protocol_key = pe;
2421  		auth->new_key_received = true;
2422  		auth->waiting_new_key = false;
2423  
2424  		if (dpp_derive_auth_i(auth, auth_i) < 0)
2425  			goto fail;
2426  
2427  		rx_auth_i = dpp_get_attr(unwrapped, unwrapped_len,
2428  					 DPP_ATTR_I_AUTH_TAG, &rx_auth_i_len);
2429  		if (!rx_auth_i) {
2430  			dpp_auth_fail(auth,
2431  				      "Missing Initiator Authentication Tag");
2432  			goto fail;
2433  		}
2434  		if (rx_auth_i_len != auth->curve->hash_len ||
2435  		    os_memcmp(rx_auth_i, auth_i, auth->curve->hash_len) != 0) {
2436  			dpp_auth_fail(auth,
2437  				      "Mismatch in Initiator Authenticating Tag");
2438  			wpa_hexdump(MSG_DEBUG, "DPP: Received Auth-I",
2439  				    rx_auth_i, rx_auth_i_len);
2440  			wpa_hexdump(MSG_DEBUG, "DPP: Derived Auth-I'",
2441  				    auth_i, auth->curve->hash_len);
2442  			goto fail;
2443  		}
2444  	}
2445  #endif /* CONFIG_DPP3 */
2446  
2447  	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
2448  				   DPP_ATTR_CONFIG_ATTR_OBJ,
2449  				   &config_attr_len);
2450  	if (!config_attr) {
2451  		dpp_auth_fail(auth,
2452  			      "Missing or invalid Config Attributes attribute");
2453  		goto fail;
2454  	}
2455  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
2456  			  config_attr, config_attr_len);
2457  
2458  	root = json_parse((const char *) config_attr, config_attr_len);
2459  	if (!root) {
2460  		dpp_auth_fail(auth, "Could not parse Config Attributes");
2461  		goto fail;
2462  	}
2463  
2464  	token = json_get_member(root, "name");
2465  	if (!token || token->type != JSON_STRING) {
2466  		dpp_auth_fail(auth, "No Config Attributes - name");
2467  		goto fail;
2468  	}
2469  	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
2470  	os_free(auth->e_name);
2471  	auth->e_name = os_strdup(token->string);
2472  
2473  	token = json_get_member(root, "wi-fi_tech");
2474  	if (!token || token->type != JSON_STRING) {
2475  		dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
2476  		goto fail;
2477  	}
2478  	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
2479  	if (os_strcmp(token->string, "infra") != 0) {
2480  		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
2481  			   token->string);
2482  		dpp_auth_fail(auth, "Unsupported wi-fi_tech");
2483  		goto fail;
2484  	}
2485  
2486  	token = json_get_member(root, "netRole");
2487  	if (!token || token->type != JSON_STRING) {
2488  		dpp_auth_fail(auth, "No Config Attributes - netRole");
2489  		goto fail;
2490  	}
2491  	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
2492  	if (os_strcmp(token->string, "sta") == 0) {
2493  		netrole = DPP_NETROLE_STA;
2494  	} else if (os_strcmp(token->string, "ap") == 0) {
2495  		netrole = DPP_NETROLE_AP;
2496  	} else if (os_strcmp(token->string, "configurator") == 0) {
2497  		netrole = DPP_NETROLE_CONFIGURATOR;
2498  	} else {
2499  		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
2500  			   token->string);
2501  		dpp_auth_fail(auth, "Unsupported netRole");
2502  		goto fail;
2503  	}
2504  	auth->e_netrole = netrole;
2505  
2506  	token = json_get_member(root, "mudurl");
2507  	if (token && token->type == JSON_STRING) {
2508  		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
2509  		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s",
2510  			token->string);
2511  		os_free(auth->e_mud_url);
2512  		auth->e_mud_url = os_strdup(token->string);
2513  	}
2514  
2515  	token = json_get_member(root, "bandSupport");
2516  	if (token && token->type == JSON_ARRAY) {
2517  		int *opclass = NULL;
2518  		char txt[200], *pos, *end;
2519  		int i, res;
2520  
2521  		wpa_printf(MSG_DEBUG, "DPP: bandSupport");
2522  		token = token->child;
2523  		while (token) {
2524  			if (token->type != JSON_NUMBER) {
2525  				wpa_printf(MSG_DEBUG,
2526  					   "DPP: Invalid bandSupport array member type");
2527  			} else {
2528  				wpa_printf(MSG_DEBUG,
2529  					   "DPP: Supported global operating class: %d",
2530  					   token->number);
2531  				int_array_add_unique(&opclass, token->number);
2532  			}
2533  			token = token->sibling;
2534  		}
2535  
2536  		txt[0] = '\0';
2537  		pos = txt;
2538  		end = txt + sizeof(txt);
2539  		for (i = 0; opclass && opclass[i]; i++) {
2540  			res = os_snprintf(pos, end - pos, "%s%d",
2541  					  pos == txt ? "" : ",", opclass[i]);
2542  			if (os_snprintf_error(end - pos, res)) {
2543  				*pos = '\0';
2544  				break;
2545  			}
2546  			pos += res;
2547  		}
2548  		os_free(auth->e_band_support);
2549  		auth->e_band_support = opclass;
2550  		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s",
2551  			txt);
2552  	}
2553  
2554  #ifdef CONFIG_DPP2
2555  	cert_req = json_get_member_base64(root, "pkcs10");
2556  	if (cert_req) {
2557  		char *txt;
2558  		int id;
2559  
2560  		wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req);
2561  		if (dpp_validate_csr(auth, cert_req) < 0) {
2562  			wpa_printf(MSG_DEBUG, "DPP: CSR is not valid");
2563  			auth->force_conf_resp_status = DPP_STATUS_CSR_BAD;
2564  			goto cont;
2565  		}
2566  
2567  		id = dpp_get_peer_bi_id(auth);
2568  		if (id < 0)
2569  			goto fail;
2570  
2571  		wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
2572  		txt = base64_encode_no_lf(wpabuf_head(cert_req),
2573  					  wpabuf_len(cert_req), NULL);
2574  		if (!txt)
2575  			goto fail;
2576  
2577  		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s",
2578  			id, txt);
2579  		os_free(txt);
2580  		auth->waiting_csr = false;
2581  		auth->waiting_cert = true;
2582  		goto fail;
2583  	}
2584  cont:
2585  #endif /* CONFIG_DPP2 */
2586  
2587  #ifdef CONFIG_DPP3
2588  	token = json_get_member(root, "capabilities");
2589  	if (token && token->type == JSON_NUMBER) {
2590  		wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
2591  			   token->number);
2592  		wpa_msg(auth->msg_ctx, MSG_INFO,
2593  			DPP_EVENT_ENROLLEE_CAPABILITY "%d",
2594  			token->number);
2595  		auth->enrollee_capabilities = token->number;
2596  	}
2597  #endif /* CONFIG_DPP3 */
2598  
2599  	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
2600  				   cert_req);
2601  
2602  fail:
2603  	wpabuf_free(cert_req);
2604  	json_free(root);
2605  	os_free(unwrapped);
2606  	return resp;
2607  }
2608  
2609  
dpp_parse_cred_legacy(struct dpp_config_obj * conf,struct json_token * cred)2610  static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
2611  				 struct json_token *cred)
2612  {
2613  	struct json_token *pass, *psk_hex;
2614  
2615  	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
2616  
2617  	pass = json_get_member(cred, "pass");
2618  	psk_hex = json_get_member(cred, "psk_hex");
2619  
2620  	if (pass && pass->type == JSON_STRING) {
2621  		size_t len = os_strlen(pass->string);
2622  #ifdef CONFIG_DPP3
2623  		struct json_token *saepi = json_get_member(cred, "idpass");
2624  #endif /* CONFIG_DPP3 */
2625  
2626  		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
2627  				      pass->string, len);
2628  		if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
2629  			wpa_printf(MSG_DEBUG,
2630  				   "DPP: Unexpected pass length %zu for a config object that includes PSK",
2631  				   len);
2632  			return -1;
2633  		}
2634  		os_strlcpy(conf->passphrase, pass->string,
2635  			   sizeof(conf->passphrase));
2636  #ifdef CONFIG_DPP3
2637  		if (saepi && saepi->type == JSON_STRING)
2638  			os_strlcpy(conf->password_id, saepi->string,
2639  				   sizeof(conf->password_id));
2640  #endif /* CONFIG_DPP3 */
2641  	} else if (psk_hex && psk_hex->type == JSON_STRING) {
2642  		if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
2643  			wpa_printf(MSG_DEBUG,
2644  				   "DPP: Unexpected psk_hex with akm=sae");
2645  			return -1;
2646  		}
2647  		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
2648  		    hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) {
2649  			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
2650  			return -1;
2651  		}
2652  		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
2653  				conf->psk, PMK_LEN);
2654  		conf->psk_set = 1;
2655  	} else {
2656  		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
2657  		return -1;
2658  	}
2659  
2660  	if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) {
2661  		wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
2662  		return -1;
2663  	}
2664  
2665  	return 0;
2666  }
2667  
2668  
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)2669  struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
2670  				     const struct dpp_curve_params **key_curve)
2671  {
2672  	struct json_token *token;
2673  	const struct dpp_curve_params *curve;
2674  	struct wpabuf *x = NULL, *y = NULL;
2675  	struct crypto_ec_key *key = NULL;
2676  
2677  	token = json_get_member(jwk, "kty");
2678  	if (!token || token->type != JSON_STRING) {
2679  		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
2680  		goto fail;
2681  	}
2682  	if (os_strcmp(token->string, "EC") != 0) {
2683  		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
2684  			   token->string);
2685  		goto fail;
2686  	}
2687  
2688  	token = json_get_member(jwk, "crv");
2689  	if (!token || token->type != JSON_STRING) {
2690  		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
2691  		goto fail;
2692  	}
2693  	curve = dpp_get_curve_jwk_crv(token->string);
2694  	if (!curve) {
2695  		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
2696  			   token->string);
2697  		goto fail;
2698  	}
2699  
2700  	x = json_get_member_base64url(jwk, "x");
2701  	if (!x) {
2702  		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
2703  		goto fail;
2704  	}
2705  	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
2706  	if (wpabuf_len(x) != curve->prime_len) {
2707  		wpa_printf(MSG_DEBUG,
2708  			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
2709  			   (unsigned int) wpabuf_len(x),
2710  			   (unsigned int) curve->prime_len, curve->name);
2711  		goto fail;
2712  	}
2713  
2714  	y = json_get_member_base64url(jwk, "y");
2715  	if (!y) {
2716  		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
2717  		goto fail;
2718  	}
2719  	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
2720  	if (wpabuf_len(y) != curve->prime_len) {
2721  		wpa_printf(MSG_DEBUG,
2722  			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
2723  			   (unsigned int) wpabuf_len(y),
2724  			   (unsigned int) curve->prime_len, curve->name);
2725  		goto fail;
2726  	}
2727  
2728  	key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x),
2729  				    wpabuf_head(y), wpabuf_len(x));
2730  	if (!key)
2731  		goto fail;
2732  
2733  	*key_curve = curve;
2734  
2735  fail:
2736  	wpabuf_free(x);
2737  	wpabuf_free(y);
2738  
2739  	return key;
2740  }
2741  
2742  
dpp_key_expired(const char * timestamp,os_time_t * expiry)2743  int dpp_key_expired(const char *timestamp, os_time_t *expiry)
2744  {
2745  	struct os_time now;
2746  	unsigned int year, month, day, hour, min, sec;
2747  	os_time_t utime;
2748  	const char *pos;
2749  
2750  	/* ISO 8601 date and time:
2751  	 * <date>T<time>
2752  	 * YYYY-MM-DDTHH:MM:SSZ
2753  	 * YYYY-MM-DDTHH:MM:SS+03:00
2754  	 */
2755  	if (os_strlen(timestamp) < 19) {
2756  		wpa_printf(MSG_DEBUG,
2757  			   "DPP: Too short timestamp - assume expired key");
2758  		return 1;
2759  	}
2760  	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
2761  		   &year, &month, &day, &hour, &min, &sec) != 6) {
2762  		wpa_printf(MSG_DEBUG,
2763  			   "DPP: Failed to parse expiration day - assume expired key");
2764  		return 1;
2765  	}
2766  
2767  	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
2768  		wpa_printf(MSG_DEBUG,
2769  			   "DPP: Invalid date/time information - assume expired key");
2770  		return 1;
2771  	}
2772  
2773  	pos = timestamp + 19;
2774  	if (*pos == 'Z' || *pos == '\0') {
2775  		/* In UTC - no need to adjust */
2776  	} else if (*pos == '-' || *pos == '+') {
2777  		int items;
2778  
2779  		/* Adjust local time to UTC */
2780  		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
2781  		if (items < 1) {
2782  			wpa_printf(MSG_DEBUG,
2783  				   "DPP: Invalid time zone designator (%s) - assume expired key",
2784  				   pos);
2785  			return 1;
2786  		}
2787  		if (*pos == '-')
2788  			utime += 3600 * hour;
2789  		if (*pos == '+')
2790  			utime -= 3600 * hour;
2791  		if (items > 1) {
2792  			if (*pos == '-')
2793  				utime += 60 * min;
2794  			if (*pos == '+')
2795  				utime -= 60 * min;
2796  		}
2797  	} else {
2798  		wpa_printf(MSG_DEBUG,
2799  			   "DPP: Invalid time zone designator (%s) - assume expired key",
2800  			   pos);
2801  		return 1;
2802  	}
2803  	if (expiry)
2804  		*expiry = utime;
2805  
2806  	if (os_get_time(&now) < 0) {
2807  		wpa_printf(MSG_DEBUG,
2808  			   "DPP: Cannot get current time - assume expired key");
2809  		return 1;
2810  	}
2811  
2812  	if (now.sec > utime) {
2813  		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
2814  			   utime, now.sec);
2815  		return 1;
2816  	}
2817  
2818  	return 0;
2819  }
2820  
2821  
dpp_parse_connector(struct dpp_authentication * auth,struct dpp_config_obj * conf,const unsigned char * payload,u16 payload_len)2822  static int dpp_parse_connector(struct dpp_authentication *auth,
2823  			       struct dpp_config_obj *conf,
2824  			       const unsigned char *payload,
2825  			       u16 payload_len)
2826  {
2827  	struct json_token *root, *groups, *netkey, *token;
2828  	int ret = -1;
2829  	struct crypto_ec_key *key = NULL;
2830  	const struct dpp_curve_params *curve;
2831  	unsigned int rules = 0;
2832  
2833  	root = json_parse((const char *) payload, payload_len);
2834  	if (!root) {
2835  		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
2836  		goto fail;
2837  	}
2838  
2839  	groups = json_get_member(root, "groups");
2840  	if (!groups || groups->type != JSON_ARRAY) {
2841  		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
2842  		goto skip_groups;
2843  	}
2844  	for (token = groups->child; token; token = token->sibling) {
2845  		struct json_token *id, *role;
2846  
2847  		id = json_get_member(token, "groupId");
2848  		if (!id || id->type != JSON_STRING) {
2849  			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
2850  			goto fail;
2851  		}
2852  
2853  		role = json_get_member(token, "netRole");
2854  		if (!role || role->type != JSON_STRING) {
2855  			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
2856  			goto fail;
2857  		}
2858  		wpa_printf(MSG_DEBUG,
2859  			   "DPP: connector group: groupId='%s' netRole='%s'",
2860  			   id->string, role->string);
2861  		rules++;
2862  	}
2863  skip_groups:
2864  
2865  	if (!rules) {
2866  		wpa_printf(MSG_DEBUG,
2867  			   "DPP: Connector includes no groups");
2868  		goto fail;
2869  	}
2870  
2871  	token = json_get_member(root, "expiry");
2872  	if (!token || token->type != JSON_STRING) {
2873  		wpa_printf(MSG_DEBUG,
2874  			   "DPP: No expiry string found - connector does not expire");
2875  	} else {
2876  		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
2877  		if (dpp_key_expired(token->string,
2878  				    &auth->net_access_key_expiry)) {
2879  			wpa_printf(MSG_DEBUG,
2880  				   "DPP: Connector (netAccessKey) has expired");
2881  			goto fail;
2882  		}
2883  	}
2884  
2885  	netkey = json_get_member(root, "netAccessKey");
2886  	if (!netkey || netkey->type != JSON_OBJECT) {
2887  		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
2888  		goto fail;
2889  	}
2890  
2891  	key = dpp_parse_jwk(netkey, &curve);
2892  	if (!key)
2893  		goto fail;
2894  	dpp_debug_print_key("DPP: Received netAccessKey", key);
2895  
2896  	if (crypto_ec_key_cmp(key, auth->own_protocol_key)) {
2897  		wpa_printf(MSG_DEBUG,
2898  			   "DPP: netAccessKey in connector does not match own protocol key");
2899  #ifdef CONFIG_TESTING_OPTIONS
2900  		if (auth->ignore_netaccesskey_mismatch) {
2901  			wpa_printf(MSG_DEBUG,
2902  				   "DPP: TESTING - skip netAccessKey mismatch");
2903  		} else {
2904  			goto fail;
2905  		}
2906  #else /* CONFIG_TESTING_OPTIONS */
2907  		goto fail;
2908  #endif /* CONFIG_TESTING_OPTIONS */
2909  	}
2910  
2911  	ret = 0;
2912  fail:
2913  	crypto_ec_key_deinit(key);
2914  	json_free(root);
2915  	return ret;
2916  }
2917  
2918  
dpp_copy_csign(struct dpp_config_obj * conf,struct crypto_ec_key * csign)2919  static void dpp_copy_csign(struct dpp_config_obj *conf,
2920  			   struct crypto_ec_key *csign)
2921  {
2922  	struct wpabuf *c_sign_key;
2923  
2924  	c_sign_key = crypto_ec_key_get_subject_public_key(csign);
2925  	if (!c_sign_key)
2926  		return;
2927  
2928  	wpabuf_free(conf->c_sign_key);
2929  	conf->c_sign_key = c_sign_key;
2930  }
2931  
2932  
dpp_copy_ppkey(struct dpp_config_obj * conf,struct crypto_ec_key * ppkey)2933  static void dpp_copy_ppkey(struct dpp_config_obj *conf,
2934  			   struct crypto_ec_key *ppkey)
2935  {
2936  	struct wpabuf *pp_key;
2937  
2938  	pp_key = crypto_ec_key_get_subject_public_key(ppkey);
2939  	if (!pp_key)
2940  		return;
2941  
2942  	wpabuf_free(conf->pp_key);
2943  	conf->pp_key = pp_key;
2944  }
2945  
2946  
dpp_copy_netaccesskey(struct dpp_authentication * auth,struct dpp_config_obj * conf)2947  static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
2948  				  struct dpp_config_obj *conf)
2949  {
2950  	struct wpabuf *net_access_key;
2951  	struct crypto_ec_key *own_key;
2952  
2953  	own_key = auth->own_protocol_key;
2954  #ifdef CONFIG_DPP2
2955  	if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY &&
2956  	    auth->reconfig_old_protocol_key)
2957  		own_key = auth->reconfig_old_protocol_key;
2958  #endif /* CONFIG_DPP2 */
2959  
2960  	net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
2961  	if (!net_access_key)
2962  		return;
2963  
2964  	wpabuf_free(auth->net_access_key);
2965  	auth->net_access_key = net_access_key;
2966  }
2967  
2968  
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)2969  static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
2970  			      struct dpp_config_obj *conf,
2971  			      struct json_token *cred)
2972  {
2973  	struct dpp_signed_connector_info info;
2974  	struct json_token *token, *csign, *ppkey;
2975  	int ret = -1;
2976  	struct crypto_ec_key *csign_pub = NULL, *pp_pub = NULL;
2977  	const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL;
2978  	const char *signed_connector;
2979  
2980  	os_memset(&info, 0, sizeof(info));
2981  
2982  	if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
2983  		wpa_printf(MSG_DEBUG,
2984  			   "DPP: Legacy credential included in Connector credential");
2985  		if (dpp_parse_cred_legacy(conf, cred) < 0)
2986  			return -1;
2987  	}
2988  
2989  	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
2990  
2991  	csign = json_get_member(cred, "csign");
2992  	if (!csign || csign->type != JSON_OBJECT) {
2993  		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
2994  		goto fail;
2995  	}
2996  
2997  	csign_pub = dpp_parse_jwk(csign, &key_curve);
2998  	if (!csign_pub) {
2999  		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
3000  		goto fail;
3001  	}
3002  	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
3003  
3004  	ppkey = json_get_member(cred, "ppKey");
3005  	if (ppkey && ppkey->type == JSON_OBJECT) {
3006  		pp_pub = dpp_parse_jwk(ppkey, &pp_curve);
3007  		if (!pp_pub) {
3008  			wpa_printf(MSG_DEBUG, "DPP: Failed to parse ppKey JWK");
3009  			goto fail;
3010  		}
3011  		dpp_debug_print_key("DPP: Received ppKey", pp_pub);
3012  		if (key_curve != pp_curve) {
3013  			wpa_printf(MSG_DEBUG,
3014  				   "DPP: C-sign-key and ppKey do not use the same curve");
3015  			goto fail;
3016  		}
3017  	}
3018  
3019  	token = json_get_member(cred, "signedConnector");
3020  	if (!token || token->type != JSON_STRING) {
3021  		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
3022  		goto fail;
3023  	}
3024  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
3025  			  token->string, os_strlen(token->string));
3026  	signed_connector = token->string;
3027  
3028  	if (os_strchr(signed_connector, '"') ||
3029  	    os_strchr(signed_connector, '\n')) {
3030  		wpa_printf(MSG_DEBUG,
3031  			   "DPP: Unexpected character in signedConnector");
3032  		goto fail;
3033  	}
3034  
3035  	if (dpp_process_signed_connector(&info, csign_pub,
3036  					 signed_connector) != DPP_STATUS_OK)
3037  		goto fail;
3038  
3039  	if (dpp_parse_connector(auth, conf,
3040  				info.payload, info.payload_len) < 0) {
3041  		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
3042  		goto fail;
3043  	}
3044  
3045  	os_free(conf->connector);
3046  	conf->connector = os_strdup(signed_connector);
3047  
3048  	dpp_copy_csign(conf, csign_pub);
3049  	if (pp_pub)
3050  		dpp_copy_ppkey(conf, pp_pub);
3051  	if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2)
3052  		dpp_copy_netaccesskey(auth, conf);
3053  
3054  	ret = 0;
3055  fail:
3056  	crypto_ec_key_deinit(csign_pub);
3057  	crypto_ec_key_deinit(pp_pub);
3058  	os_free(info.payload);
3059  	return ret;
3060  }
3061  
3062  
3063  #ifdef CONFIG_DPP2
dpp_parse_cred_dot1x(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)3064  static int dpp_parse_cred_dot1x(struct dpp_authentication *auth,
3065  				struct dpp_config_obj *conf,
3066  				struct json_token *cred)
3067  {
3068  	struct json_token *ent, *name;
3069  
3070  	ent = json_get_member(cred, "entCreds");
3071  	if (!ent || ent->type != JSON_OBJECT) {
3072  		dpp_auth_fail(auth, "No entCreds in JSON");
3073  		return -1;
3074  	}
3075  
3076  	conf->certbag = json_get_member_base64(ent, "certBag");
3077  	if (!conf->certbag) {
3078  		dpp_auth_fail(auth, "No certBag in JSON");
3079  		return -1;
3080  	}
3081  	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag);
3082  	conf->certs = crypto_pkcs7_get_certificates(conf->certbag);
3083  	if (!conf->certs) {
3084  		dpp_auth_fail(auth, "No certificates in certBag");
3085  		return -1;
3086  	}
3087  
3088  	conf->cacert = json_get_member_base64(ent, "caCert");
3089  	if (conf->cacert)
3090  		wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert",
3091  				conf->cacert);
3092  
3093  	name = json_get_member(ent, "trustedEapServerName");
3094  	if (name &&
3095  	    (name->type != JSON_STRING ||
3096  	     has_ctrl_char((const u8 *) name->string,
3097  			   os_strlen(name->string)))) {
3098  		dpp_auth_fail(auth,
3099  			      "Invalid trustedEapServerName type in JSON");
3100  		return -1;
3101  	}
3102  	if (name && name->string) {
3103  		wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s",
3104  			   name->string);
3105  		conf->server_name = os_strdup(name->string);
3106  		if (!conf->server_name)
3107  			return -1;
3108  	}
3109  
3110  	return 0;
3111  }
3112  #endif /* CONFIG_DPP2 */
3113  
3114  
dpp_akm_str(enum dpp_akm akm)3115  const char * dpp_akm_str(enum dpp_akm akm)
3116  {
3117  	switch (akm) {
3118  	case DPP_AKM_DPP:
3119  		return "dpp";
3120  	case DPP_AKM_PSK:
3121  		return "psk";
3122  	case DPP_AKM_SAE:
3123  		return "sae";
3124  	case DPP_AKM_PSK_SAE:
3125  		return "psk+sae";
3126  	case DPP_AKM_SAE_DPP:
3127  		return "dpp+sae";
3128  	case DPP_AKM_PSK_SAE_DPP:
3129  		return "dpp+psk+sae";
3130  	case DPP_AKM_DOT1X:
3131  		return "dot1x";
3132  	default:
3133  		return "??";
3134  	}
3135  }
3136  
3137  
dpp_akm_selector_str(enum dpp_akm akm)3138  const char * dpp_akm_selector_str(enum dpp_akm akm)
3139  {
3140  	switch (akm) {
3141  	case DPP_AKM_DPP:
3142  		return "506F9A02";
3143  	case DPP_AKM_PSK:
3144  		return "000FAC02+000FAC06";
3145  	case DPP_AKM_SAE:
3146  		return "000FAC08";
3147  	case DPP_AKM_PSK_SAE:
3148  		return "000FAC02+000FAC06+000FAC08";
3149  	case DPP_AKM_SAE_DPP:
3150  		return "506F9A02+000FAC08";
3151  	case DPP_AKM_PSK_SAE_DPP:
3152  		return "506F9A02+000FAC08+000FAC02+000FAC06";
3153  	case DPP_AKM_DOT1X:
3154  		return "000FAC01+000FAC05";
3155  	default:
3156  		return "??";
3157  	}
3158  }
3159  
3160  
dpp_akm_from_str(const char * akm)3161  static enum dpp_akm dpp_akm_from_str(const char *akm)
3162  {
3163  	const char *pos;
3164  	int dpp = 0, psk = 0, sae = 0, dot1x = 0;
3165  
3166  	if (os_strcmp(akm, "psk") == 0)
3167  		return DPP_AKM_PSK;
3168  	if (os_strcmp(akm, "sae") == 0)
3169  		return DPP_AKM_SAE;
3170  	if (os_strcmp(akm, "psk+sae") == 0)
3171  		return DPP_AKM_PSK_SAE;
3172  	if (os_strcmp(akm, "dpp") == 0)
3173  		return DPP_AKM_DPP;
3174  	if (os_strcmp(akm, "dpp+sae") == 0)
3175  		return DPP_AKM_SAE_DPP;
3176  	if (os_strcmp(akm, "dpp+psk+sae") == 0)
3177  		return DPP_AKM_PSK_SAE_DPP;
3178  	if (os_strcmp(akm, "dot1x") == 0)
3179  		return DPP_AKM_DOT1X;
3180  
3181  	pos = akm;
3182  	while (*pos) {
3183  		if (os_strlen(pos) < 8)
3184  			break;
3185  		if (os_strncasecmp(pos, "506F9A02", 8) == 0)
3186  			dpp = 1;
3187  		else if (os_strncasecmp(pos, "000FAC02", 8) == 0)
3188  			psk = 1;
3189  		else if (os_strncasecmp(pos, "000FAC06", 8) == 0)
3190  			psk = 1;
3191  		else if (os_strncasecmp(pos, "000FAC08", 8) == 0)
3192  			sae = 1;
3193  		else if (os_strncasecmp(pos, "000FAC01", 8) == 0)
3194  			dot1x = 1;
3195  		else if (os_strncasecmp(pos, "000FAC05", 8) == 0)
3196  			dot1x = 1;
3197  		pos += 8;
3198  		if (*pos != '+')
3199  			break;
3200  		pos++;
3201  	}
3202  
3203  	if (dpp && psk && sae)
3204  		return DPP_AKM_PSK_SAE_DPP;
3205  	if (dpp && sae)
3206  		return DPP_AKM_SAE_DPP;
3207  	if (dpp)
3208  		return DPP_AKM_DPP;
3209  	if (psk && sae)
3210  		return DPP_AKM_PSK_SAE;
3211  	if (sae)
3212  		return DPP_AKM_SAE;
3213  	if (psk)
3214  		return DPP_AKM_PSK;
3215  	if (dot1x)
3216  		return DPP_AKM_DOT1X;
3217  
3218  	return DPP_AKM_UNKNOWN;
3219  }
3220  
3221  
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)3222  static int dpp_parse_conf_obj(struct dpp_authentication *auth,
3223  			      const u8 *conf_obj, u16 conf_obj_len)
3224  {
3225  	int ret = -1;
3226  	struct json_token *root, *token, *discovery, *cred;
3227  	struct dpp_config_obj *conf;
3228  	struct wpabuf *ssid64 = NULL;
3229  	int legacy;
3230  
3231  	root = json_parse((const char *) conf_obj, conf_obj_len);
3232  	if (!root)
3233  		return -1;
3234  	if (root->type != JSON_OBJECT) {
3235  		dpp_auth_fail(auth, "JSON root is not an object");
3236  		goto fail;
3237  	}
3238  
3239  	token = json_get_member(root, "wi-fi_tech");
3240  	if (!token || token->type != JSON_STRING) {
3241  		dpp_auth_fail(auth, "No wi-fi_tech string value found");
3242  		goto fail;
3243  	}
3244  	if (os_strcmp(token->string, "infra") != 0) {
3245  		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
3246  			   token->string);
3247  		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
3248  		goto fail;
3249  	}
3250  
3251  	discovery = json_get_member(root, "discovery");
3252  	if (!discovery || discovery->type != JSON_OBJECT) {
3253  		dpp_auth_fail(auth, "No discovery object in JSON");
3254  		goto fail;
3255  	}
3256  
3257  	ssid64 = json_get_member_base64url(discovery, "ssid64");
3258  	if (ssid64) {
3259  		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
3260  				  wpabuf_head(ssid64), wpabuf_len(ssid64));
3261  		if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
3262  			dpp_auth_fail(auth, "Too long discovery::ssid64 value");
3263  			goto fail;
3264  		}
3265  	} else {
3266  		token = json_get_member(discovery, "ssid");
3267  		if (!token || token->type != JSON_STRING) {
3268  			dpp_auth_fail(auth,
3269  				      "No discovery::ssid string value found");
3270  			goto fail;
3271  		}
3272  		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
3273  				  token->string, os_strlen(token->string));
3274  		if (os_strlen(token->string) > SSID_MAX_LEN) {
3275  			dpp_auth_fail(auth,
3276  				      "Too long discovery::ssid string value");
3277  			goto fail;
3278  		}
3279  	}
3280  
3281  	if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
3282  		wpa_printf(MSG_DEBUG,
3283  			   "DPP: No room for this many Config Objects - ignore this one");
3284  		ret = 0;
3285  		goto fail;
3286  	}
3287  	conf = &auth->conf_obj[auth->num_conf_obj++];
3288  
3289  	if (ssid64) {
3290  		conf->ssid_len = wpabuf_len(ssid64);
3291  		os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
3292  	} else {
3293  		conf->ssid_len = os_strlen(token->string);
3294  		os_memcpy(conf->ssid, token->string, conf->ssid_len);
3295  	}
3296  
3297  	token = json_get_member(discovery, "ssid_charset");
3298  	if (token && token->type == JSON_NUMBER) {
3299  		conf->ssid_charset = token->number;
3300  		wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
3301  			   conf->ssid_charset);
3302  	}
3303  
3304  	cred = json_get_member(root, "cred");
3305  	if (!cred || cred->type != JSON_OBJECT) {
3306  		dpp_auth_fail(auth, "No cred object in JSON");
3307  		goto fail;
3308  	}
3309  
3310  	token = json_get_member(cred, "akm");
3311  	if (!token || token->type != JSON_STRING) {
3312  		dpp_auth_fail(auth, "No cred::akm string value found");
3313  		goto fail;
3314  	}
3315  	conf->akm = dpp_akm_from_str(token->string);
3316  
3317  	legacy = dpp_akm_legacy(conf->akm);
3318  	if (legacy && auth->peer_version >= 2) {
3319  		struct json_token *csign, *s_conn;
3320  
3321  		csign = json_get_member(cred, "csign");
3322  		s_conn = json_get_member(cred, "signedConnector");
3323  		if (csign && csign->type == JSON_OBJECT &&
3324  		    s_conn && s_conn->type == JSON_STRING)
3325  			legacy = 0;
3326  	}
3327  	if (legacy) {
3328  		if (dpp_parse_cred_legacy(conf, cred) < 0)
3329  			goto fail;
3330  	} else if (dpp_akm_dpp(conf->akm) ||
3331  		   (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) {
3332  		if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
3333  			goto fail;
3334  #ifdef CONFIG_DPP2
3335  	} else if (conf->akm == DPP_AKM_DOT1X) {
3336  		if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 ||
3337  		    dpp_parse_cred_dpp(auth, conf, cred) < 0)
3338  			goto fail;
3339  #endif /* CONFIG_DPP2 */
3340  	} else {
3341  		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
3342  			   token->string);
3343  		dpp_auth_fail(auth, "Unsupported akm");
3344  		goto fail;
3345  	}
3346  
3347  	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
3348  	ret = 0;
3349  fail:
3350  	wpabuf_free(ssid64);
3351  	json_free(root);
3352  	return ret;
3353  }
3354  
3355  
3356  #ifdef CONFIG_DPP2
dpp_get_csr_attrs(const u8 * attrs,size_t attrs_len,size_t * len)3357  static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len)
3358  {
3359  	const u8 *b64;
3360  	u16 b64_len;
3361  
3362  	b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len);
3363  	if (!b64)
3364  		return NULL;
3365  	return base64_decode((const char *) b64, b64_len, len);
3366  }
3367  #endif /* CONFIG_DPP2 */
3368  
3369  
dpp_conf_resp_rx(struct dpp_authentication * auth,const struct wpabuf * resp)3370  int dpp_conf_resp_rx(struct dpp_authentication *auth,
3371  		     const struct wpabuf *resp)
3372  {
3373  	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
3374  	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
3375  	const u8 *env_data;
3376  	u16 env_data_len;
3377  	const u8 *addr[1];
3378  	size_t len[1];
3379  	u8 *unwrapped = NULL;
3380  	size_t unwrapped_len = 0;
3381  	int ret = -1;
3382  
3383  	auth->conf_resp_status = 255;
3384  
3385  	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
3386  		dpp_auth_fail(auth, "Invalid attribute in config response");
3387  		return -1;
3388  	}
3389  
3390  	wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
3391  				    DPP_ATTR_WRAPPED_DATA,
3392  				    &wrapped_data_len);
3393  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3394  		dpp_auth_fail(auth,
3395  			      "Missing or invalid required Wrapped Data attribute");
3396  		return -1;
3397  	}
3398  
3399  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3400  		    wrapped_data, wrapped_data_len);
3401  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3402  	unwrapped = os_malloc(unwrapped_len);
3403  	if (!unwrapped)
3404  		return -1;
3405  
3406  	addr[0] = wpabuf_head(resp);
3407  	len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
3408  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
3409  
3410  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3411  			    wrapped_data, wrapped_data_len,
3412  			    1, addr, len, unwrapped) < 0) {
3413  		dpp_auth_fail(auth, "AES-SIV decryption failed");
3414  		goto fail;
3415  	}
3416  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3417  		    unwrapped, unwrapped_len);
3418  
3419  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3420  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3421  		goto fail;
3422  	}
3423  
3424  	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3425  			       DPP_ATTR_ENROLLEE_NONCE,
3426  			       &e_nonce_len);
3427  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3428  		dpp_auth_fail(auth,
3429  			      "Missing or invalid Enrollee Nonce attribute");
3430  		goto fail;
3431  	}
3432  	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3433  	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3434  		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3435  		goto fail;
3436  	}
3437  
3438  	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
3439  			      DPP_ATTR_STATUS, &status_len);
3440  	if (!status || status_len < 1) {
3441  		dpp_auth_fail(auth,
3442  			      "Missing or invalid required DPP Status attribute");
3443  		goto fail;
3444  	}
3445  	auth->conf_resp_status = status[0];
3446  	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3447  #ifdef CONFIG_DPP2
3448  	if (status[0] == DPP_STATUS_CSR_NEEDED) {
3449  		u8 *csrattrs;
3450  		size_t csrattrs_len;
3451  
3452  		wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR");
3453  
3454  		csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len,
3455  					     &csrattrs_len);
3456  		if (!csrattrs) {
3457  			dpp_auth_fail(auth,
3458  				      "Missing or invalid CSR Attributes Request attribute");
3459  			goto fail;
3460  		}
3461  		wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len);
3462  		os_free(auth->csrattrs);
3463  		auth->csrattrs = csrattrs;
3464  		auth->csrattrs_len = csrattrs_len;
3465  		ret = -2;
3466  		goto fail;
3467  	}
3468  #endif /* CONFIG_DPP2 */
3469  #ifdef CONFIG_DPP3
3470  	if (status[0] == DPP_STATUS_NEW_KEY_NEEDED) {
3471  		const u8 *fcgroup, *r_proto;
3472  		u16 fcgroup_len, r_proto_len;
3473  		u16 group;
3474  		const struct dpp_curve_params *curve;
3475  		struct crypto_ec_key *new_pe;
3476  		struct crypto_ec_key *pc;
3477  
3478  		fcgroup = dpp_get_attr(unwrapped, unwrapped_len,
3479  				       DPP_ATTR_FINITE_CYCLIC_GROUP,
3480  				       &fcgroup_len);
3481  		if (!fcgroup || fcgroup_len != 2) {
3482  			dpp_auth_fail(auth,
3483  				      "Missing or invalid required Finite Cyclic Group attribute");
3484  			goto fail;
3485  		}
3486  		group = WPA_GET_LE16(fcgroup);
3487  
3488  		wpa_printf(MSG_DEBUG,
3489  			   "DPP: Configurator requested a new protocol key from group %u",
3490  			   group);
3491  		curve = dpp_get_curve_ike_group(group);
3492  		if (!curve) {
3493  			dpp_auth_fail(auth,
3494  				      "Unsupported group for new protocol key");
3495  			goto fail;
3496  		}
3497  
3498  		new_pe = dpp_gen_keypair(curve);
3499  		if (!new_pe) {
3500  			dpp_auth_fail(auth,
3501  				      "Failed to generate a new protocol key");
3502  			goto fail;
3503  		}
3504  
3505  		crypto_ec_key_deinit(auth->own_protocol_key);
3506  		auth->own_protocol_key = new_pe;
3507  		auth->new_curve = curve;
3508  
3509  		r_proto = dpp_get_attr(unwrapped, unwrapped_len,
3510  				       DPP_ATTR_R_PROTOCOL_KEY,
3511  				       &r_proto_len);
3512  		if (!r_proto) {
3513  			dpp_auth_fail(auth,
3514  				      "Missing required Responder Protocol Key attribute (Pc)");
3515  			goto fail;
3516  		}
3517  		wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key (new Pc)",
3518  			    r_proto, r_proto_len);
3519  
3520  		pc = dpp_set_pubkey_point(new_pe, r_proto, r_proto_len);
3521  		if (!pc) {
3522  			dpp_auth_fail(auth, "Invalid Responder Protocol Key (Pc)");
3523  			goto fail;
3524  		}
3525  		dpp_debug_print_key("New Peer Protocol Key (Pc)", pc);
3526  
3527  		crypto_ec_key_deinit(auth->peer_protocol_key);
3528  		auth->peer_protocol_key = pc;
3529  
3530  		auth->waiting_new_key = true;
3531  		ret = -3;
3532  		goto fail;
3533  	}
3534  #endif /* CONFIG_DPP3 */
3535  	if (status[0] != DPP_STATUS_OK) {
3536  		dpp_auth_fail(auth, "Configurator rejected configuration");
3537  		goto fail;
3538  	}
3539  
3540  	env_data = dpp_get_attr(unwrapped, unwrapped_len,
3541  				DPP_ATTR_ENVELOPED_DATA, &env_data_len);
3542  #ifdef CONFIG_DPP2
3543  	if (env_data &&
3544  	    dpp_conf_resp_env_data(auth, env_data, env_data_len) < 0)
3545  		goto fail;
3546  #endif /* CONFIG_DPP2 */
3547  
3548  	conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
3549  				&conf_obj_len);
3550  	if (!conf_obj && !env_data) {
3551  		dpp_auth_fail(auth,
3552  			      "Missing required Configuration Object attribute");
3553  		goto fail;
3554  	}
3555  	while (conf_obj) {
3556  		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
3557  				  conf_obj, conf_obj_len);
3558  		if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
3559  			goto fail;
3560  		conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
3561  					     DPP_ATTR_CONFIG_OBJ,
3562  					     &conf_obj_len);
3563  	}
3564  
3565  #ifdef CONFIG_DPP2
3566  	status = dpp_get_attr(unwrapped, unwrapped_len,
3567  			      DPP_ATTR_SEND_CONN_STATUS, &status_len);
3568  	if (status) {
3569  		wpa_printf(MSG_DEBUG,
3570  			   "DPP: Configurator requested connection status result");
3571  		auth->conn_status_requested = 1;
3572  	}
3573  #endif /* CONFIG_DPP2 */
3574  
3575  	ret = 0;
3576  
3577  fail:
3578  	os_free(unwrapped);
3579  	return ret;
3580  }
3581  
3582  
3583  #ifdef CONFIG_DPP2
3584  
dpp_conf_result_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)3585  enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
3586  					 const u8 *hdr,
3587  					 const u8 *attr_start, size_t attr_len)
3588  {
3589  	const u8 *wrapped_data, *status, *e_nonce;
3590  	u16 wrapped_data_len, status_len, e_nonce_len;
3591  	const u8 *addr[2];
3592  	size_t len[2];
3593  	u8 *unwrapped = NULL;
3594  	size_t unwrapped_len = 0;
3595  	enum dpp_status_error ret = 256;
3596  
3597  	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3598  				    &wrapped_data_len);
3599  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3600  		dpp_auth_fail(auth,
3601  			      "Missing or invalid required Wrapped Data attribute");
3602  		goto fail;
3603  	}
3604  	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3605  		    wrapped_data, wrapped_data_len);
3606  
3607  	attr_len = wrapped_data - 4 - attr_start;
3608  
3609  	addr[0] = hdr;
3610  	len[0] = DPP_HDR_LEN;
3611  	addr[1] = attr_start;
3612  	len[1] = attr_len;
3613  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3614  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3615  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3616  		    wrapped_data, wrapped_data_len);
3617  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3618  	unwrapped = os_malloc(unwrapped_len);
3619  	if (!unwrapped)
3620  		goto fail;
3621  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3622  			    wrapped_data, wrapped_data_len,
3623  			    2, addr, len, unwrapped) < 0) {
3624  		dpp_auth_fail(auth, "AES-SIV decryption failed");
3625  		goto fail;
3626  	}
3627  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3628  		    unwrapped, unwrapped_len);
3629  
3630  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3631  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3632  		goto fail;
3633  	}
3634  
3635  	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3636  			       DPP_ATTR_ENROLLEE_NONCE,
3637  			       &e_nonce_len);
3638  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3639  		dpp_auth_fail(auth,
3640  			      "Missing or invalid Enrollee Nonce attribute");
3641  		goto fail;
3642  	}
3643  	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3644  	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3645  		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3646  		wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
3647  			    auth->e_nonce, e_nonce_len);
3648  		goto fail;
3649  	}
3650  
3651  	status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS,
3652  			      &status_len);
3653  	if (!status || status_len < 1) {
3654  		dpp_auth_fail(auth,
3655  			      "Missing or invalid required DPP Status attribute");
3656  		goto fail;
3657  	}
3658  	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3659  	ret = status[0];
3660  
3661  fail:
3662  	bin_clear_free(unwrapped, unwrapped_len);
3663  	return ret;
3664  }
3665  
3666  
dpp_build_conf_result(struct dpp_authentication * auth,enum dpp_status_error status)3667  struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
3668  				      enum dpp_status_error status)
3669  {
3670  	struct wpabuf *msg, *clear;
3671  	size_t nonce_len, clear_len, attr_len;
3672  	const u8 *addr[2];
3673  	size_t len[2];
3674  	u8 *wrapped;
3675  
3676  	nonce_len = auth->curve->nonce_len;
3677  	clear_len = 5 + 4 + nonce_len;
3678  	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
3679  	clear = wpabuf_alloc(clear_len);
3680  	msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len);
3681  	if (!clear || !msg)
3682  		goto fail;
3683  
3684  	/* DPP Status */
3685  	dpp_build_attr_status(clear, status);
3686  
3687  	/* E-nonce */
3688  	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
3689  	wpabuf_put_le16(clear, nonce_len);
3690  	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
3691  
3692  	/* OUI, OUI type, Crypto Suite, DPP frame type */
3693  	addr[0] = wpabuf_head_u8(msg) + 2;
3694  	len[0] = 3 + 1 + 1 + 1;
3695  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3696  
3697  	/* Attributes before Wrapped Data (none) */
3698  	addr[1] = wpabuf_put(msg, 0);
3699  	len[1] = 0;
3700  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3701  
3702  	/* Wrapped Data */
3703  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3704  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3705  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3706  
3707  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
3708  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3709  			    wpabuf_head(clear), wpabuf_len(clear),
3710  			    2, addr, len, wrapped) < 0)
3711  		goto fail;
3712  
3713  	wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg);
3714  	wpabuf_free(clear);
3715  	return msg;
3716  fail:
3717  	wpabuf_free(clear);
3718  	wpabuf_free(msg);
3719  	return NULL;
3720  }
3721  
3722  
valid_channel_list(const char * val)3723  static int valid_channel_list(const char *val)
3724  {
3725  	while (*val) {
3726  		if (!((*val >= '0' && *val <= '9') ||
3727  		      *val == '/' || *val == ','))
3728  			return 0;
3729  		val++;
3730  	}
3731  
3732  	return 1;
3733  }
3734  
3735  
dpp_conn_status_result_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,u8 * ssid,size_t * ssid_len,char ** channel_list)3736  enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
3737  						const u8 *hdr,
3738  						const u8 *attr_start,
3739  						size_t attr_len,
3740  						u8 *ssid, size_t *ssid_len,
3741  						char **channel_list)
3742  {
3743  	const u8 *wrapped_data, *status, *e_nonce;
3744  	u16 wrapped_data_len, status_len, e_nonce_len;
3745  	const u8 *addr[2];
3746  	size_t len[2];
3747  	u8 *unwrapped = NULL;
3748  	size_t unwrapped_len = 0;
3749  	enum dpp_status_error ret = 256;
3750  	struct json_token *root = NULL, *token;
3751  	struct wpabuf *ssid64;
3752  
3753  	*ssid_len = 0;
3754  	*channel_list = NULL;
3755  
3756  	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3757  				    &wrapped_data_len);
3758  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3759  		dpp_auth_fail(auth,
3760  			      "Missing or invalid required Wrapped Data attribute");
3761  		goto fail;
3762  	}
3763  	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3764  		    wrapped_data, wrapped_data_len);
3765  
3766  	attr_len = wrapped_data - 4 - attr_start;
3767  
3768  	addr[0] = hdr;
3769  	len[0] = DPP_HDR_LEN;
3770  	addr[1] = attr_start;
3771  	len[1] = attr_len;
3772  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3773  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3774  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3775  		    wrapped_data, wrapped_data_len);
3776  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3777  	unwrapped = os_malloc(unwrapped_len);
3778  	if (!unwrapped)
3779  		goto fail;
3780  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3781  			    wrapped_data, wrapped_data_len,
3782  			    2, addr, len, unwrapped) < 0) {
3783  		dpp_auth_fail(auth, "AES-SIV decryption failed");
3784  		goto fail;
3785  	}
3786  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3787  		    unwrapped, unwrapped_len);
3788  
3789  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3790  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3791  		goto fail;
3792  	}
3793  
3794  	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3795  			       DPP_ATTR_ENROLLEE_NONCE,
3796  			       &e_nonce_len);
3797  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3798  		dpp_auth_fail(auth,
3799  			      "Missing or invalid Enrollee Nonce attribute");
3800  		goto fail;
3801  	}
3802  	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3803  	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3804  		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3805  		wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
3806  			    auth->e_nonce, e_nonce_len);
3807  		goto fail;
3808  	}
3809  
3810  	status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS,
3811  			      &status_len);
3812  	if (!status) {
3813  		dpp_auth_fail(auth,
3814  			      "Missing required DPP Connection Status attribute");
3815  		goto fail;
3816  	}
3817  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
3818  			  status, status_len);
3819  
3820  	root = json_parse((const char *) status, status_len);
3821  	if (!root) {
3822  		dpp_auth_fail(auth, "Could not parse connStatus");
3823  		goto fail;
3824  	}
3825  
3826  	ssid64 = json_get_member_base64url(root, "ssid64");
3827  	if (ssid64 && wpabuf_len(ssid64) <= SSID_MAX_LEN) {
3828  		*ssid_len = wpabuf_len(ssid64);
3829  		os_memcpy(ssid, wpabuf_head(ssid64), *ssid_len);
3830  	}
3831  	wpabuf_free(ssid64);
3832  
3833  	token = json_get_member(root, "channelList");
3834  	if (token && token->type == JSON_STRING &&
3835  	    valid_channel_list(token->string))
3836  		*channel_list = os_strdup(token->string);
3837  
3838  	token = json_get_member(root, "result");
3839  	if (!token || token->type != JSON_NUMBER) {
3840  		dpp_auth_fail(auth, "No connStatus - result");
3841  		goto fail;
3842  	}
3843  	wpa_printf(MSG_DEBUG, "DPP: result %d", token->number);
3844  	ret = token->number;
3845  
3846  fail:
3847  	json_free(root);
3848  	bin_clear_free(unwrapped, unwrapped_len);
3849  	return ret;
3850  }
3851  
3852  
dpp_build_conn_status(enum dpp_status_error result,const u8 * ssid,size_t ssid_len,const char * channel_list)3853  struct wpabuf * dpp_build_conn_status(enum dpp_status_error result,
3854  				      const u8 *ssid, size_t ssid_len,
3855  				      const char *channel_list)
3856  {
3857  	struct wpabuf *json;
3858  
3859  	json = wpabuf_alloc(1000);
3860  	if (!json)
3861  		return NULL;
3862  	json_start_object(json, NULL);
3863  	json_add_int(json, "result", result);
3864  	if (ssid) {
3865  		json_value_sep(json);
3866  		if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) {
3867  			wpabuf_free(json);
3868  			return NULL;
3869  		}
3870  	}
3871  	if (channel_list) {
3872  		json_value_sep(json);
3873  		json_add_string(json, "channelList", channel_list);
3874  	}
3875  	json_end_object(json);
3876  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
3877  			  wpabuf_head(json), wpabuf_len(json));
3878  
3879  	return json;
3880  }
3881  
3882  
dpp_build_conn_status_result(struct dpp_authentication * auth,enum dpp_status_error result,const u8 * ssid,size_t ssid_len,const char * channel_list)3883  struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
3884  					     enum dpp_status_error result,
3885  					     const u8 *ssid, size_t ssid_len,
3886  					     const char *channel_list)
3887  {
3888  	struct wpabuf *msg = NULL, *clear = NULL, *json;
3889  	size_t nonce_len, clear_len, attr_len;
3890  	const u8 *addr[2];
3891  	size_t len[2];
3892  	u8 *wrapped;
3893  
3894  	json = dpp_build_conn_status(result, ssid, ssid_len, channel_list);
3895  	if (!json)
3896  		return NULL;
3897  
3898  	nonce_len = auth->curve->nonce_len;
3899  	clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json);
3900  	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
3901  	clear = wpabuf_alloc(clear_len);
3902  	msg = dpp_alloc_msg(DPP_PA_CONNECTION_STATUS_RESULT, attr_len);
3903  	if (!clear || !msg)
3904  		goto fail;
3905  
3906  	/* E-nonce */
3907  	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
3908  	wpabuf_put_le16(clear, nonce_len);
3909  	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
3910  
3911  	/* DPP Connection Status */
3912  	wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS);
3913  	wpabuf_put_le16(clear, wpabuf_len(json));
3914  	wpabuf_put_buf(clear, json);
3915  
3916  	/* OUI, OUI type, Crypto Suite, DPP frame type */
3917  	addr[0] = wpabuf_head_u8(msg) + 2;
3918  	len[0] = 3 + 1 + 1 + 1;
3919  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3920  
3921  	/* Attributes before Wrapped Data (none) */
3922  	addr[1] = wpabuf_put(msg, 0);
3923  	len[1] = 0;
3924  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3925  
3926  	/* Wrapped Data */
3927  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3928  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3929  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3930  
3931  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
3932  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3933  			    wpabuf_head(clear), wpabuf_len(clear),
3934  			    2, addr, len, wrapped) < 0)
3935  		goto fail;
3936  
3937  	wpa_hexdump_buf(MSG_DEBUG, "DPP: Connection Status Result attributes",
3938  			msg);
3939  	wpabuf_free(json);
3940  	wpabuf_free(clear);
3941  	return msg;
3942  fail:
3943  	wpabuf_free(json);
3944  	wpabuf_free(clear);
3945  	wpabuf_free(msg);
3946  	return NULL;
3947  }
3948  
3949  #endif /* CONFIG_DPP2 */
3950  
3951  
dpp_configurator_free(struct dpp_configurator * conf)3952  void dpp_configurator_free(struct dpp_configurator *conf)
3953  {
3954  	if (!conf)
3955  		return;
3956  	crypto_ec_key_deinit(conf->csign);
3957  	os_free(conf->kid);
3958  	os_free(conf->connector);
3959  	crypto_ec_key_deinit(conf->connector_key);
3960  	crypto_ec_key_deinit(conf->pp_key);
3961  	os_free(conf);
3962  }
3963  
3964  
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)3965  int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
3966  			     size_t buflen)
3967  {
3968  	struct wpabuf *key;
3969  	int ret = -1;
3970  
3971  	if (!conf->csign)
3972  		return -1;
3973  
3974  	key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
3975  	if (!key)
3976  		return -1;
3977  
3978  	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
3979  
3980  	wpabuf_clear_free(key);
3981  	return ret;
3982  }
3983  
3984  
dpp_configurator_gen_kid(struct dpp_configurator * conf)3985  static int dpp_configurator_gen_kid(struct dpp_configurator *conf)
3986  {
3987  	struct wpabuf *csign_pub = NULL;
3988  	const u8 *addr[1];
3989  	size_t len[1];
3990  	int res;
3991  
3992  	csign_pub = crypto_ec_key_get_pubkey_point(conf->csign, 1);
3993  	if (!csign_pub) {
3994  		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
3995  		return -1;
3996  	}
3997  
3998  	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
3999  	addr[0] = wpabuf_head(csign_pub);
4000  	len[0] = wpabuf_len(csign_pub);
4001  	res = sha256_vector(1, addr, len, conf->kid_hash);
4002  	wpabuf_free(csign_pub);
4003  	if (res < 0) {
4004  		wpa_printf(MSG_DEBUG,
4005  			   "DPP: Failed to derive kid for C-sign-key");
4006  		return -1;
4007  	}
4008  
4009  	conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash),
4010  				      NULL);
4011  	return conf->kid ? 0 : -1;
4012  }
4013  
4014  
4015  static struct dpp_configurator *
dpp_keygen_configurator(const char * curve,const u8 * privkey,size_t privkey_len,const u8 * pp_key,size_t pp_key_len)4016  dpp_keygen_configurator(const char *curve, const u8 *privkey,
4017  			size_t privkey_len, const u8 *pp_key, size_t pp_key_len)
4018  {
4019  	struct dpp_configurator *conf;
4020  
4021  	conf = os_zalloc(sizeof(*conf));
4022  	if (!conf)
4023  		return NULL;
4024  
4025  	conf->curve = dpp_get_curve_name(curve);
4026  	if (!conf->curve) {
4027  		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
4028  		os_free(conf);
4029  		return NULL;
4030  	}
4031  
4032  	if (privkey)
4033  		conf->csign = dpp_set_keypair(&conf->curve, privkey,
4034  					      privkey_len);
4035  	else
4036  		conf->csign = dpp_gen_keypair(conf->curve);
4037  	if (pp_key)
4038  		conf->pp_key = dpp_set_keypair(&conf->curve, pp_key,
4039  					       pp_key_len);
4040  	else
4041  		conf->pp_key = dpp_gen_keypair(conf->curve);
4042  	if (!conf->csign || !conf->pp_key)
4043  		goto fail;
4044  	conf->own = 1;
4045  
4046  	if (dpp_configurator_gen_kid(conf) < 0)
4047  		goto fail;
4048  	return conf;
4049  fail:
4050  	dpp_configurator_free(conf);
4051  	return NULL;
4052  }
4053  
4054  
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)4055  int dpp_configurator_own_config(struct dpp_authentication *auth,
4056  				const char *curve, int ap)
4057  {
4058  	struct wpabuf *conf_obj;
4059  	int ret = -1;
4060  
4061  	if (!auth->conf) {
4062  		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
4063  		return -1;
4064  	}
4065  
4066  	auth->curve = dpp_get_curve_name(curve);
4067  	if (!auth->curve) {
4068  		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
4069  		return -1;
4070  	}
4071  
4072  	wpa_printf(MSG_DEBUG,
4073  		   "DPP: Building own configuration/connector with curve %s",
4074  		   auth->curve->name);
4075  
4076  	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
4077  	if (!auth->own_protocol_key)
4078  		return -1;
4079  	dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
4080  	auth->peer_protocol_key = auth->own_protocol_key;
4081  	dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
4082  
4083  	conf_obj = dpp_build_conf_obj(auth, ap, 0, NULL);
4084  	if (!conf_obj) {
4085  		wpabuf_free(auth->conf_obj[0].c_sign_key);
4086  		auth->conf_obj[0].c_sign_key = NULL;
4087  		goto fail;
4088  	}
4089  	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
4090  				 wpabuf_len(conf_obj));
4091  fail:
4092  	wpabuf_free(conf_obj);
4093  	auth->peer_protocol_key = NULL;
4094  	return ret;
4095  }
4096  
4097  
dpp_compatible_netrole(const char * role1,const char * role2)4098  static int dpp_compatible_netrole(const char *role1, const char *role2)
4099  {
4100  	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
4101  		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
4102  }
4103  
4104  
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role,bool reconfig)4105  static int dpp_connector_compatible_group(struct json_token *root,
4106  					  const char *group_id,
4107  					  const char *net_role,
4108  					  bool reconfig)
4109  {
4110  	struct json_token *groups, *token;
4111  
4112  	groups = json_get_member(root, "groups");
4113  	if (!groups || groups->type != JSON_ARRAY)
4114  		return 0;
4115  
4116  	for (token = groups->child; token; token = token->sibling) {
4117  		struct json_token *id, *role;
4118  
4119  		id = json_get_member(token, "groupId");
4120  		if (!id || id->type != JSON_STRING)
4121  			continue;
4122  
4123  		role = json_get_member(token, "netRole");
4124  		if (!role || role->type != JSON_STRING)
4125  			continue;
4126  
4127  		if (os_strcmp(id->string, "*") != 0 &&
4128  		    os_strcmp(group_id, "*") != 0 &&
4129  		    os_strcmp(id->string, group_id) != 0)
4130  			continue;
4131  
4132  		if (reconfig && os_strcmp(net_role, "configurator") == 0)
4133  			return 1;
4134  		if (!reconfig && dpp_compatible_netrole(role->string, net_role))
4135  			return 1;
4136  	}
4137  
4138  	return 0;
4139  }
4140  
4141  
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root,bool reconfig)4142  int dpp_connector_match_groups(struct json_token *own_root,
4143  			       struct json_token *peer_root, bool reconfig)
4144  {
4145  	struct json_token *groups, *token;
4146  
4147  	groups = json_get_member(peer_root, "groups");
4148  	if (!groups || groups->type != JSON_ARRAY) {
4149  		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
4150  		return 0;
4151  	}
4152  
4153  	for (token = groups->child; token; token = token->sibling) {
4154  		struct json_token *id, *role;
4155  
4156  		id = json_get_member(token, "groupId");
4157  		if (!id || id->type != JSON_STRING) {
4158  			wpa_printf(MSG_DEBUG,
4159  				   "DPP: Missing peer groupId string");
4160  			continue;
4161  		}
4162  
4163  		role = json_get_member(token, "netRole");
4164  		if (!role || role->type != JSON_STRING) {
4165  			wpa_printf(MSG_DEBUG,
4166  				   "DPP: Missing peer groups::netRole string");
4167  			continue;
4168  		}
4169  		wpa_printf(MSG_DEBUG,
4170  			   "DPP: peer connector group: groupId='%s' netRole='%s'",
4171  			   id->string, role->string);
4172  		if (dpp_connector_compatible_group(own_root, id->string,
4173  						   role->string, reconfig)) {
4174  			wpa_printf(MSG_DEBUG,
4175  				   "DPP: Compatible group/netRole in own connector");
4176  			return 1;
4177  		}
4178  	}
4179  
4180  	return 0;
4181  }
4182  
4183  
dpp_parse_own_connector(const char * own_connector)4184  struct json_token * dpp_parse_own_connector(const char *own_connector)
4185  {
4186  	unsigned char *own_conn;
4187  	size_t own_conn_len;
4188  	const char *pos, *end;
4189  	struct json_token *own_root;
4190  
4191  	pos = os_strchr(own_connector, '.');
4192  	if (!pos) {
4193  		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
4194  		return NULL;
4195  	}
4196  	pos++;
4197  	end = os_strchr(pos, '.');
4198  	if (!end) {
4199  		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
4200  		return NULL;
4201  	}
4202  	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
4203  	if (!own_conn) {
4204  		wpa_printf(MSG_DEBUG,
4205  			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
4206  		return NULL;
4207  	}
4208  
4209  	own_root = json_parse((const char *) own_conn, own_conn_len);
4210  	os_free(own_conn);
4211  	if (!own_root)
4212  		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
4213  
4214  	return own_root;
4215  }
4216  
4217  
4218  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,u8 * peer_key_hash)4219  dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
4220  	       const u8 *net_access_key, size_t net_access_key_len,
4221  	       const u8 *csign_key, size_t csign_key_len,
4222  	       const u8 *peer_connector, size_t peer_connector_len,
4223  	       os_time_t *expiry, u8 *peer_key_hash)
4224  {
4225  	struct json_token *root = NULL, *netkey, *token;
4226  	struct json_token *own_root = NULL;
4227  	enum dpp_status_error ret = 255, res;
4228  	struct crypto_ec_key *own_key = NULL;
4229  	struct wpabuf *own_key_pub = NULL;
4230  	const struct dpp_curve_params *curve, *own_curve;
4231  	struct dpp_signed_connector_info info;
4232  	size_t Nx_len;
4233  	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
4234  
4235  	os_memset(intro, 0, sizeof(*intro));
4236  	os_memset(&info, 0, sizeof(info));
4237  	if (expiry)
4238  		*expiry = 0;
4239  
4240  	own_key = dpp_set_keypair(&own_curve, net_access_key,
4241  				  net_access_key_len);
4242  	if (!own_key) {
4243  		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
4244  		goto fail;
4245  	}
4246  
4247  	own_root = dpp_parse_own_connector(own_connector);
4248  	if (!own_root)
4249  		goto fail;
4250  
4251  	res = dpp_check_signed_connector(&info, csign_key, csign_key_len,
4252  					 peer_connector, peer_connector_len);
4253  	if (res != DPP_STATUS_OK) {
4254  		ret = res;
4255  		goto fail;
4256  	}
4257  
4258  	root = json_parse((const char *) info.payload, info.payload_len);
4259  	if (!root) {
4260  		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4261  		ret = DPP_STATUS_INVALID_CONNECTOR;
4262  		goto fail;
4263  	}
4264  
4265  	if (!dpp_connector_match_groups(own_root, root, false)) {
4266  		wpa_printf(MSG_DEBUG,
4267  			   "DPP: Peer connector does not include compatible group netrole with own connector");
4268  		ret = DPP_STATUS_NO_MATCH;
4269  		goto fail;
4270  	}
4271  
4272  	token = json_get_member(root, "expiry");
4273  	if (!token || token->type != JSON_STRING) {
4274  		wpa_printf(MSG_DEBUG,
4275  			   "DPP: No expiry string found - connector does not expire");
4276  	} else {
4277  		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4278  		if (dpp_key_expired(token->string, expiry)) {
4279  			wpa_printf(MSG_DEBUG,
4280  				   "DPP: Connector (netAccessKey) has expired");
4281  			ret = DPP_STATUS_INVALID_CONNECTOR;
4282  			goto fail;
4283  		}
4284  	}
4285  
4286  #ifdef CONFIG_DPP3
4287  	token = json_get_member(root, "version");
4288  	if (token && token->type == JSON_NUMBER) {
4289  		wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number);
4290  		intro->peer_version = token->number;
4291  	}
4292  #endif /* CONFIG_DPP3 */
4293  
4294  	netkey = json_get_member(root, "netAccessKey");
4295  	if (!netkey || netkey->type != JSON_OBJECT) {
4296  		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4297  		ret = DPP_STATUS_INVALID_CONNECTOR;
4298  		goto fail;
4299  	}
4300  
4301  	intro->peer_key = dpp_parse_jwk(netkey, &curve);
4302  	if (!intro->peer_key) {
4303  		ret = DPP_STATUS_INVALID_CONNECTOR;
4304  		goto fail;
4305  	}
4306  	dpp_debug_print_key("DPP: Received netAccessKey", intro->peer_key);
4307  
4308  	if (own_curve != curve) {
4309  		wpa_printf(MSG_DEBUG,
4310  			   "DPP: Mismatching netAccessKey curves (%s != %s)",
4311  			   own_curve->name, curve->name);
4312  		ret = DPP_STATUS_INVALID_CONNECTOR;
4313  		goto fail;
4314  	}
4315  
4316  	/* ECDH: N = nk * PK */
4317  	if (dpp_ecdh(own_key, intro->peer_key, Nx, &Nx_len) < 0)
4318  		goto fail;
4319  
4320  	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
4321  			Nx, Nx_len);
4322  
4323  	/* PMK = HKDF(<>, "DPP PMK", N.x) */
4324  	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
4325  		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
4326  		goto fail;
4327  	}
4328  	intro->pmk_len = curve->hash_len;
4329  
4330  	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
4331  	if (dpp_derive_pmkid(curve, own_key, intro->peer_key, intro->pmkid) <
4332  	    0) {
4333  		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
4334  		goto fail;
4335  	}
4336  
4337  #ifdef CONFIG_DPP3
4338  	if (dpp_hpke_suite(curve->ike_group, &intro->kem_id, &intro->kdf_id,
4339  			   &intro->aead_id) < 0) {
4340  		wpa_printf(MSG_ERROR, "DPP: Unsupported group %d",
4341  			   curve->ike_group);
4342  		goto fail;
4343  	}
4344  #endif /* CONFIG_DPP3 */
4345  
4346  	if (peer_key_hash)
4347  		dpp_get_pubkey_hash(intro->peer_key, peer_key_hash);
4348  
4349  	ret = DPP_STATUS_OK;
4350  fail:
4351  	if (ret != DPP_STATUS_OK)
4352  		dpp_peer_intro_deinit(intro);
4353  	os_memset(Nx, 0, sizeof(Nx));
4354  	os_free(info.payload);
4355  	crypto_ec_key_deinit(own_key);
4356  	wpabuf_free(own_key_pub);
4357  	json_free(root);
4358  	json_free(own_root);
4359  	return ret;
4360  }
4361  
4362  
dpp_peer_intro_deinit(struct dpp_introduction * intro)4363  void dpp_peer_intro_deinit(struct dpp_introduction *intro)
4364  {
4365  	if (!intro)
4366  		return;
4367  
4368  	crypto_ec_key_deinit(intro->peer_key);
4369  	os_memset(intro, 0, sizeof(*intro));
4370  }
4371  
4372  
4373  #ifdef CONFIG_DPP3
dpp_get_connector_version(const char * connector)4374  int dpp_get_connector_version(const char *connector)
4375  {
4376  	struct json_token *root, *token;
4377  	int ver = -1;
4378  
4379  	root = dpp_parse_own_connector(connector);
4380  	if (!root)
4381  		return -1;
4382  
4383  	token = json_get_member(root, "version");
4384  	if (token && token->type == JSON_NUMBER)
4385  		ver = token->number;
4386  
4387  	json_free(root);
4388  	return ver;
4389  }
4390  #endif /* CONFIG_DPP3 */
4391  
4392  
dpp_next_id(struct dpp_global * dpp)4393  unsigned int dpp_next_id(struct dpp_global *dpp)
4394  {
4395  	struct dpp_bootstrap_info *bi;
4396  	unsigned int max_id = 0;
4397  
4398  	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4399  		if (bi->id > max_id)
4400  			max_id = bi->id;
4401  	}
4402  	return max_id + 1;
4403  }
4404  
4405  
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)4406  static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
4407  {
4408  	struct dpp_bootstrap_info *bi, *tmp;
4409  	int found = 0;
4410  
4411  	if (!dpp)
4412  		return -1;
4413  
4414  	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
4415  			      struct dpp_bootstrap_info, list) {
4416  		if (id && bi->id != id)
4417  			continue;
4418  		found = 1;
4419  #ifdef CONFIG_DPP2
4420  		if (dpp->remove_bi)
4421  			dpp->remove_bi(dpp->cb_ctx, bi);
4422  #endif /* CONFIG_DPP2 */
4423  		dl_list_del(&bi->list);
4424  		dpp_bootstrap_info_free(bi);
4425  	}
4426  
4427  	if (id == 0)
4428  		return 0; /* flush succeeds regardless of entries found */
4429  	return found ? 0 : -1;
4430  }
4431  
4432  
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)4433  struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
4434  					    const char *uri)
4435  {
4436  	struct dpp_bootstrap_info *bi;
4437  
4438  	if (!dpp)
4439  		return NULL;
4440  
4441  	bi = dpp_parse_uri(uri);
4442  	if (!bi)
4443  		return NULL;
4444  
4445  	bi->type = DPP_BOOTSTRAP_QR_CODE;
4446  	bi->id = dpp_next_id(dpp);
4447  	dl_list_add(&dpp->bootstrap, &bi->list);
4448  	return bi;
4449  }
4450  
4451  
dpp_add_nfc_uri(struct dpp_global * dpp,const char * uri)4452  struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
4453  					    const char *uri)
4454  {
4455  	struct dpp_bootstrap_info *bi;
4456  
4457  	if (!dpp)
4458  		return NULL;
4459  
4460  	bi = dpp_parse_uri(uri);
4461  	if (!bi)
4462  		return NULL;
4463  
4464  	bi->type = DPP_BOOTSTRAP_NFC_URI;
4465  	bi->id = dpp_next_id(dpp);
4466  	dl_list_add(&dpp->bootstrap, &bi->list);
4467  	return bi;
4468  }
4469  
4470  
dpp_parse_supported_curves_list(struct dpp_bootstrap_info * bi,char * txt)4471  static int dpp_parse_supported_curves_list(struct dpp_bootstrap_info *bi,
4472  					   char *txt)
4473  {
4474  	char *token, *context = NULL;
4475  	u8 curves = 0;
4476  
4477  	if (!txt)
4478  		return 0;
4479  
4480  	while ((token = str_token(txt, ":", &context))) {
4481  		if (os_strcmp(token, "P-256") == 0) {
4482  			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_256);
4483  		} else if (os_strcmp(token, "P-384") == 0) {
4484  			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_384);
4485  		} else if (os_strcmp(token, "P-521") == 0) {
4486  			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_521);
4487  		} else if (os_strcmp(token, "BP-256") == 0) {
4488  			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_256);
4489  		} else if (os_strcmp(token, "BP-384") == 0) {
4490  			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_384);
4491  		} else if (os_strcmp(token, "BP-512") == 0) {
4492  			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_512);
4493  		} else {
4494  			wpa_printf(MSG_DEBUG, "DPP: Unsupported curve '%s'",
4495  				   token);
4496  			return -1;
4497  		}
4498  	}
4499  	bi->supported_curves = curves;
4500  
4501  	wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
4502  		   bi->supported_curves);
4503  
4504  	return 0;
4505  }
4506  
4507  
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)4508  int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
4509  {
4510  	char *mac = NULL, *info = NULL, *curve = NULL;
4511  	char *key = NULL, *supported_curves = NULL, *host = NULL;
4512  	u8 *privkey = NULL;
4513  	size_t privkey_len = 0;
4514  	int ret = -1;
4515  	struct dpp_bootstrap_info *bi;
4516  
4517  	if (!dpp)
4518  		return -1;
4519  
4520  	bi = os_zalloc(sizeof(*bi));
4521  	if (!bi)
4522  		goto fail;
4523  
4524  	if (os_strstr(cmd, "type=qrcode"))
4525  		bi->type = DPP_BOOTSTRAP_QR_CODE;
4526  	else if (os_strstr(cmd, "type=pkex"))
4527  		bi->type = DPP_BOOTSTRAP_PKEX;
4528  	else if (os_strstr(cmd, "type=nfc-uri"))
4529  		bi->type = DPP_BOOTSTRAP_NFC_URI;
4530  	else
4531  		goto fail;
4532  
4533  	bi->chan = get_param(cmd, " chan=");
4534  	mac = get_param(cmd, " mac=");
4535  	info = get_param(cmd, " info=");
4536  	curve = get_param(cmd, " curve=");
4537  	key = get_param(cmd, " key=");
4538  	supported_curves = get_param(cmd, " supported_curves=");
4539  	host = get_param(cmd, " host=");
4540  
4541  	if (key) {
4542  		privkey_len = os_strlen(key) / 2;
4543  		privkey = os_malloc(privkey_len);
4544  		if (!privkey ||
4545  		    hexstr2bin(key, privkey, privkey_len) < 0)
4546  			goto fail;
4547  	}
4548  
4549  	if (dpp_keygen(bi, curve, privkey, privkey_len) < 0 ||
4550  	    dpp_parse_uri_chan_list(bi, bi->chan) < 0 ||
4551  	    dpp_parse_uri_mac(bi, mac) < 0 ||
4552  	    dpp_parse_uri_info(bi, info) < 0 ||
4553  	    dpp_parse_supported_curves_list(bi, supported_curves) < 0 ||
4554  	    dpp_parse_uri_host(bi, host) < 0 ||
4555  	    dpp_gen_uri(bi) < 0)
4556  		goto fail;
4557  
4558  	bi->id = dpp_next_id(dpp);
4559  	dl_list_add(&dpp->bootstrap, &bi->list);
4560  	ret = bi->id;
4561  	bi = NULL;
4562  fail:
4563  	os_free(curve);
4564  	os_free(mac);
4565  	os_free(info);
4566  	str_clear_free(key);
4567  	os_free(supported_curves);
4568  	os_free(host);
4569  	bin_clear_free(privkey, privkey_len);
4570  	dpp_bootstrap_info_free(bi);
4571  	return ret;
4572  }
4573  
4574  
4575  struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)4576  dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
4577  {
4578  	struct dpp_bootstrap_info *bi;
4579  
4580  	if (!dpp)
4581  		return NULL;
4582  
4583  	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4584  		if (bi->id == id)
4585  			return bi;
4586  	}
4587  	return NULL;
4588  }
4589  
4590  
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)4591  int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
4592  {
4593  	unsigned int id_val;
4594  
4595  	if (os_strcmp(id, "*") == 0) {
4596  		id_val = 0;
4597  	} else {
4598  		id_val = atoi(id);
4599  		if (id_val == 0)
4600  			return -1;
4601  	}
4602  
4603  	return dpp_bootstrap_del(dpp, id_val);
4604  }
4605  
4606  
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)4607  const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
4608  {
4609  	struct dpp_bootstrap_info *bi;
4610  
4611  	bi = dpp_bootstrap_get_id(dpp, id);
4612  	if (!bi)
4613  		return NULL;
4614  	return bi->uri;
4615  }
4616  
4617  
dpp_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)4618  int dpp_bootstrap_info(struct dpp_global *dpp, int id,
4619  		       char *reply, int reply_size)
4620  {
4621  	struct dpp_bootstrap_info *bi;
4622  	char pkhash[2 * SHA256_MAC_LEN + 1];
4623  	char supp_curves[100];
4624  	char host[100];
4625  	int ret;
4626  
4627  	bi = dpp_bootstrap_get_id(dpp, id);
4628  	if (!bi)
4629  		return -1;
4630  	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
4631  			 SHA256_MAC_LEN);
4632  
4633  	supp_curves[0] = '\0';
4634  	if (bi->supported_curves) {
4635  		size_t i;
4636  		char *pos = supp_curves;
4637  		char *end = &supp_curves[sizeof(supp_curves)];
4638  		const char *curve[6] = { "P-256", "P-384", "P-521",
4639  					 "BP-256", "BP-384", "BP-512" };
4640  
4641  		ret = os_snprintf(pos, end - pos, "supp_curves=");
4642  		if (os_snprintf_error(end - pos, ret))
4643  			return -1;
4644  		pos += ret;
4645  
4646  		for (i = 0; i < ARRAY_SIZE(curve); i++) {
4647  			if (!(bi->supported_curves & BIT(i)))
4648  				continue;
4649  			ret = os_snprintf(pos, end - pos, "%s:", curve[i]);
4650  			if (os_snprintf_error(end - pos, ret))
4651  				return -1;
4652  			pos += ret;
4653  		}
4654  
4655  		if (pos[-1] == ':')
4656  			pos[-1] = '\n';
4657  		else
4658  			supp_curves[0] = '\0';
4659  	}
4660  
4661  	host[0] = '\0';
4662  	if (bi->host) {
4663  		char buf[100];
4664  
4665  		ret = os_snprintf(host, sizeof(host), "host=%s %u\n",
4666  				  hostapd_ip_txt(bi->host, buf, sizeof(buf)),
4667  				  bi->port);
4668  		if (os_snprintf_error(sizeof(host), ret))
4669  			return -1;
4670  	}
4671  
4672  	return os_snprintf(reply, reply_size, "type=%s\n"
4673  			   "mac_addr=" MACSTR "\n"
4674  			   "info=%s\n"
4675  			   "num_freq=%u\n"
4676  			   "use_freq=%u\n"
4677  			   "curve=%s\n"
4678  			   "pkhash=%s\n"
4679  			   "version=%d\n%s%s",
4680  			   dpp_bootstrap_type_txt(bi->type),
4681  			   MAC2STR(bi->mac_addr),
4682  			   bi->info ? bi->info : "",
4683  			   bi->num_freq,
4684  			   bi->num_freq == 1 ? bi->freq[0] : 0,
4685  			   bi->curve->name,
4686  			   pkhash,
4687  			   bi->version,
4688  			   supp_curves,
4689  			   host);
4690  }
4691  
4692  
dpp_bootstrap_set(struct dpp_global * dpp,int id,const char * params)4693  int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params)
4694  {
4695  	struct dpp_bootstrap_info *bi;
4696  
4697  	bi = dpp_bootstrap_get_id(dpp, id);
4698  	if (!bi)
4699  		return -1;
4700  
4701  	str_clear_free(bi->configurator_params);
4702  
4703  	if (params) {
4704  		bi->configurator_params = os_strdup(params);
4705  		return bi->configurator_params ? 0 : -1;
4706  	}
4707  
4708  	bi->configurator_params = NULL;
4709  	return 0;
4710  }
4711  
4712  
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)4713  void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
4714  			     const u8 *r_bootstrap,
4715  			     struct dpp_bootstrap_info **own_bi,
4716  			     struct dpp_bootstrap_info **peer_bi)
4717  {
4718  	struct dpp_bootstrap_info *bi;
4719  
4720  	*own_bi = NULL;
4721  	*peer_bi = NULL;
4722  	if (!dpp)
4723  		return;
4724  
4725  	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4726  		if (!*own_bi && bi->own &&
4727  		    os_memcmp(bi->pubkey_hash, r_bootstrap,
4728  			      SHA256_MAC_LEN) == 0) {
4729  			wpa_printf(MSG_DEBUG,
4730  				   "DPP: Found matching own bootstrapping information");
4731  			*own_bi = bi;
4732  		}
4733  
4734  		if (!*peer_bi && !bi->own &&
4735  		    os_memcmp(bi->pubkey_hash, i_bootstrap,
4736  			      SHA256_MAC_LEN) == 0) {
4737  			wpa_printf(MSG_DEBUG,
4738  				   "DPP: Found matching peer bootstrapping information");
4739  			*peer_bi = bi;
4740  		}
4741  
4742  		if (*own_bi && *peer_bi)
4743  			break;
4744  	}
4745  }
4746  
4747  
4748  #ifdef CONFIG_DPP2
dpp_bootstrap_find_chirp(struct dpp_global * dpp,const u8 * hash)4749  struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp,
4750  						     const u8 *hash)
4751  {
4752  	struct dpp_bootstrap_info *bi;
4753  
4754  	if (!dpp)
4755  		return NULL;
4756  
4757  	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4758  		if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash,
4759  					  SHA256_MAC_LEN) == 0)
4760  			return bi;
4761  	}
4762  
4763  	return NULL;
4764  }
4765  #endif /* CONFIG_DPP2 */
4766  
4767  
dpp_nfc_update_bi_channel(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4768  static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi,
4769  				     struct dpp_bootstrap_info *peer_bi)
4770  {
4771  	unsigned int i, freq = 0;
4772  	enum hostapd_hw_mode mode;
4773  	u8 op_class, channel;
4774  	char chan[20];
4775  
4776  	if (peer_bi->num_freq == 0 && !peer_bi->channels_listed)
4777  		return 0; /* no channel preference/constraint */
4778  
4779  	for (i = 0; i < peer_bi->num_freq; i++) {
4780  		if ((own_bi->num_freq == 0 && !own_bi->channels_listed) ||
4781  		    freq_included(own_bi->freq, own_bi->num_freq,
4782  				  peer_bi->freq[i])) {
4783  			freq = peer_bi->freq[i];
4784  			break;
4785  		}
4786  	}
4787  	if (!freq) {
4788  		wpa_printf(MSG_DEBUG, "DPP: No common channel found");
4789  		return -1;
4790  	}
4791  
4792  	mode = ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, &channel);
4793  	if (mode == NUM_HOSTAPD_MODES) {
4794  		wpa_printf(MSG_DEBUG,
4795  			   "DPP: Could not determine operating class or channel number for %u MHz",
4796  			   freq);
4797  	}
4798  
4799  	wpa_printf(MSG_DEBUG,
4800  		   "DPP: Selected %u MHz (op_class %u channel %u) as the negotiation channel based on information from NFC negotiated handover",
4801  		   freq, op_class, channel);
4802  	os_snprintf(chan, sizeof(chan), "%u/%u", op_class, channel);
4803  	os_free(own_bi->chan);
4804  	own_bi->chan = os_strdup(chan);
4805  	own_bi->freq[0] = freq;
4806  	own_bi->num_freq = 1;
4807  	os_free(peer_bi->chan);
4808  	peer_bi->chan = os_strdup(chan);
4809  	peer_bi->freq[0] = freq;
4810  	peer_bi->num_freq = 1;
4811  
4812  	return dpp_gen_uri(own_bi);
4813  }
4814  
4815  
dpp_nfc_update_bi_key(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4816  static int dpp_nfc_update_bi_key(struct dpp_bootstrap_info *own_bi,
4817  				 struct dpp_bootstrap_info *peer_bi)
4818  {
4819  	if (peer_bi->curve == own_bi->curve)
4820  		return 0;
4821  
4822  	wpa_printf(MSG_DEBUG,
4823  		   "DPP: Update own bootstrapping key to match peer curve from NFC handover");
4824  
4825  	crypto_ec_key_deinit(own_bi->pubkey);
4826  	own_bi->pubkey = NULL;
4827  
4828  	if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 ||
4829  	    dpp_gen_uri(own_bi) < 0)
4830  		goto fail;
4831  
4832  	return 0;
4833  fail:
4834  	dl_list_del(&own_bi->list);
4835  	dpp_bootstrap_info_free(own_bi);
4836  	return -1;
4837  }
4838  
4839  
dpp_nfc_update_bi(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4840  int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
4841  		      struct dpp_bootstrap_info *peer_bi)
4842  {
4843  	if (dpp_nfc_update_bi_channel(own_bi, peer_bi) < 0 ||
4844  	    dpp_nfc_update_bi_key(own_bi, peer_bi) < 0)
4845  		return -1;
4846  	return 0;
4847  }
4848  
4849  
dpp_next_configurator_id(struct dpp_global * dpp)4850  static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
4851  {
4852  	struct dpp_configurator *conf;
4853  	unsigned int max_id = 0;
4854  
4855  	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
4856  			 list) {
4857  		if (conf->id > max_id)
4858  			max_id = conf->id;
4859  	}
4860  	return max_id + 1;
4861  }
4862  
4863  
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)4864  int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
4865  {
4866  	char *curve;
4867  	char *key = NULL, *ppkey = NULL;
4868  	u8 *privkey = NULL, *pp_key = NULL;
4869  	size_t privkey_len = 0, pp_key_len = 0;
4870  	int ret = -1;
4871  	struct dpp_configurator *conf = NULL;
4872  	const struct dpp_curve_params *net_access_key_curve = NULL;
4873  
4874  	curve = get_param(cmd, " net_access_key_curve=");
4875  	if (curve) {
4876  		net_access_key_curve = dpp_get_curve_name(curve);
4877  		if (!net_access_key_curve) {
4878  			wpa_printf(MSG_DEBUG,
4879  				   "DPP: Unsupported net_access_key_curve: %s",
4880  				   curve);
4881  			goto fail;
4882  		}
4883  		os_free(curve);
4884  	}
4885  
4886  	curve = get_param(cmd, " curve=");
4887  	key = get_param(cmd, " key=");
4888  	ppkey = get_param(cmd, " ppkey=");
4889  
4890  	if (key) {
4891  		privkey_len = os_strlen(key) / 2;
4892  		privkey = os_malloc(privkey_len);
4893  		if (!privkey ||
4894  		    hexstr2bin(key, privkey, privkey_len) < 0)
4895  			goto fail;
4896  	}
4897  
4898  	if (ppkey) {
4899  		pp_key_len = os_strlen(ppkey) / 2;
4900  		pp_key = os_malloc(pp_key_len);
4901  		if (!pp_key ||
4902  		    hexstr2bin(ppkey, pp_key, pp_key_len) < 0)
4903  			goto fail;
4904  	}
4905  
4906  	conf = dpp_keygen_configurator(curve, privkey, privkey_len,
4907  				       pp_key, pp_key_len);
4908  	if (!conf)
4909  		goto fail;
4910  
4911  	conf->net_access_key_curve = net_access_key_curve;
4912  	conf->id = dpp_next_configurator_id(dpp);
4913  	dl_list_add(&dpp->configurator, &conf->list);
4914  	ret = conf->id;
4915  	conf = NULL;
4916  fail:
4917  	os_free(curve);
4918  	str_clear_free(key);
4919  	str_clear_free(ppkey);
4920  	bin_clear_free(privkey, privkey_len);
4921  	bin_clear_free(pp_key, pp_key_len);
4922  	dpp_configurator_free(conf);
4923  	return ret;
4924  }
4925  
4926  
dpp_configurator_set(struct dpp_global * dpp,const char * cmd)4927  int dpp_configurator_set(struct dpp_global *dpp, const char *cmd)
4928  {
4929  	unsigned int id;
4930  	struct dpp_configurator *conf;
4931  	char *curve;
4932  
4933  	id = atoi(cmd);
4934  	conf = dpp_configurator_get_id(dpp, id);
4935  	if (!conf)
4936  		return -1;
4937  
4938  	curve = get_param(cmd, " net_access_key_curve=");
4939  	if (curve) {
4940  		const struct dpp_curve_params *net_access_key_curve;
4941  
4942  		net_access_key_curve = dpp_get_curve_name(curve);
4943  		os_free(curve);
4944  		if (!net_access_key_curve)
4945  			return -1;
4946  		conf->net_access_key_curve = net_access_key_curve;
4947  	}
4948  
4949  	return 0;
4950  }
4951  
4952  
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)4953  static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
4954  {
4955  	struct dpp_configurator *conf, *tmp;
4956  	int found = 0;
4957  
4958  	if (!dpp)
4959  		return -1;
4960  
4961  	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
4962  			      struct dpp_configurator, list) {
4963  		if (id && conf->id != id)
4964  			continue;
4965  		found = 1;
4966  		dl_list_del(&conf->list);
4967  		dpp_configurator_free(conf);
4968  	}
4969  
4970  	if (id == 0)
4971  		return 0; /* flush succeeds regardless of entries found */
4972  	return found ? 0 : -1;
4973  }
4974  
4975  
dpp_configurator_remove(struct dpp_global * dpp,const char * id)4976  int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
4977  {
4978  	unsigned int id_val;
4979  
4980  	if (os_strcmp(id, "*") == 0) {
4981  		id_val = 0;
4982  	} else {
4983  		id_val = atoi(id);
4984  		if (id_val == 0)
4985  			return -1;
4986  	}
4987  
4988  	return dpp_configurator_del(dpp, id_val);
4989  }
4990  
4991  
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)4992  int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
4993  				char *buf, size_t buflen)
4994  {
4995  	struct dpp_configurator *conf;
4996  
4997  	conf = dpp_configurator_get_id(dpp, id);
4998  	if (!conf)
4999  		return -1;
5000  
5001  	return dpp_configurator_get_key(conf, buf, buflen);
5002  }
5003  
5004  
5005  #ifdef CONFIG_DPP2
5006  
dpp_configurator_from_backup(struct dpp_global * dpp,struct dpp_asymmetric_key * key)5007  int dpp_configurator_from_backup(struct dpp_global *dpp,
5008  				 struct dpp_asymmetric_key *key)
5009  {
5010  	struct dpp_configurator *conf;
5011  	const struct dpp_curve_params *curve, *curve_pp;
5012  
5013  	if (!key->csign || !key->pp_key)
5014  		return -1;
5015  
5016  	curve = dpp_get_curve_ike_group(crypto_ec_key_group(key->csign));
5017  	if (!curve) {
5018  		wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key");
5019  		return -1;
5020  	}
5021  
5022  	curve_pp = dpp_get_curve_ike_group(crypto_ec_key_group(key->pp_key));
5023  	if (!curve_pp) {
5024  		wpa_printf(MSG_INFO, "DPP: Unsupported group in ppKey");
5025  		return -1;
5026  	}
5027  
5028  	if (curve != curve_pp) {
5029  		wpa_printf(MSG_INFO,
5030  			   "DPP: Mismatch in c-sign-key and ppKey groups");
5031  		return -1;
5032  	}
5033  
5034  	conf = os_zalloc(sizeof(*conf));
5035  	if (!conf)
5036  		return -1;
5037  	conf->curve = curve;
5038  	conf->csign = key->csign;
5039  	key->csign = NULL;
5040  	conf->pp_key = key->pp_key;
5041  	key->pp_key = NULL;
5042  	conf->own = 1;
5043  	if (dpp_configurator_gen_kid(conf) < 0) {
5044  		dpp_configurator_free(conf);
5045  		return -1;
5046  	}
5047  
5048  	conf->id = dpp_next_configurator_id(dpp);
5049  	dl_list_add(&dpp->configurator, &conf->list);
5050  	return conf->id;
5051  }
5052  
5053  
dpp_configurator_find_kid(struct dpp_global * dpp,const u8 * kid)5054  struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp,
5055  						    const u8 *kid)
5056  {
5057  	struct dpp_configurator *conf;
5058  
5059  	if (!dpp)
5060  		return NULL;
5061  
5062  	dl_list_for_each(conf, &dpp->configurator,
5063  			 struct dpp_configurator, list) {
5064  		if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0)
5065  			return conf;
5066  	}
5067  	return NULL;
5068  }
5069  
5070  #endif /* CONFIG_DPP2 */
5071  
5072  
dpp_global_init(struct dpp_global_config * config)5073  struct dpp_global * dpp_global_init(struct dpp_global_config *config)
5074  {
5075  	struct dpp_global *dpp;
5076  
5077  	dpp = os_zalloc(sizeof(*dpp));
5078  	if (!dpp)
5079  		return NULL;
5080  #ifdef CONFIG_DPP2
5081  	dpp->cb_ctx = config->cb_ctx;
5082  	dpp->remove_bi = config->remove_bi;
5083  #endif /* CONFIG_DPP2 */
5084  
5085  	dl_list_init(&dpp->bootstrap);
5086  	dl_list_init(&dpp->configurator);
5087  #ifdef CONFIG_DPP2
5088  	dl_list_init(&dpp->controllers);
5089  	dl_list_init(&dpp->tcp_init);
5090  	dpp->relay_sock = -1;
5091  #endif /* CONFIG_DPP2 */
5092  
5093  	return dpp;
5094  }
5095  
5096  
dpp_global_clear(struct dpp_global * dpp)5097  void dpp_global_clear(struct dpp_global *dpp)
5098  {
5099  	if (!dpp)
5100  		return;
5101  
5102  	dpp_bootstrap_del(dpp, 0);
5103  	dpp_configurator_del(dpp, 0);
5104  #ifdef CONFIG_DPP2
5105  	dpp_tcp_init_flush(dpp);
5106  	dpp_relay_flush_controllers(dpp);
5107  	dpp_controller_stop(dpp);
5108  #endif /* CONFIG_DPP2 */
5109  }
5110  
5111  
dpp_global_deinit(struct dpp_global * dpp)5112  void dpp_global_deinit(struct dpp_global *dpp)
5113  {
5114  	dpp_global_clear(dpp);
5115  	os_free(dpp);
5116  }
5117  
5118  
dpp_notify_auth_success(struct dpp_authentication * auth,int initiator)5119  void dpp_notify_auth_success(struct dpp_authentication *auth, int initiator)
5120  {
5121  	u8 hash[SHA256_MAC_LEN];
5122  	char hex[SHA256_MAC_LEN * 2 + 1];
5123  
5124  	if (auth->peer_protocol_key) {
5125  		dpp_get_pubkey_hash(auth->peer_protocol_key, hash);
5126  		wpa_snprintf_hex(hex, sizeof(hex), hash, sizeof(hash));
5127  	} else {
5128  		hex[0] = '\0';
5129  	}
5130  	wpa_msg(auth->msg_ctx, MSG_INFO,
5131  		DPP_EVENT_AUTH_SUCCESS "init=%d pkhash=%s own=%d peer=%d",
5132  		initiator, hex, auth->own_bi ? (int) auth->own_bi->id : -1,
5133  		auth->peer_bi ? (int) auth->peer_bi->id : -1);
5134  }
5135  
5136  
5137  #ifdef CONFIG_DPP2
5138  
dpp_build_presence_announcement(struct dpp_bootstrap_info * bi)5139  struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi)
5140  {
5141  	struct wpabuf *msg;
5142  
5143  	wpa_printf(MSG_DEBUG, "DPP: Build Presence Announcement frame");
5144  
5145  	msg = dpp_alloc_msg(DPP_PA_PRESENCE_ANNOUNCEMENT, 4 + SHA256_MAC_LEN);
5146  	if (!msg)
5147  		return NULL;
5148  
5149  	/* Responder Bootstrapping Key Hash */
5150  	dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp);
5151  	wpa_hexdump_buf(MSG_DEBUG,
5152  			"DPP: Presence Announcement frame attributes", msg);
5153  	return msg;
5154  }
5155  
5156  
dpp_notify_chirp_received(void * msg_ctx,int id,const u8 * src,unsigned int freq,const u8 * hash)5157  void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
5158  				unsigned int freq, const u8 *hash)
5159  {
5160  	char hex[SHA256_MAC_LEN * 2 + 1];
5161  
5162  	wpa_snprintf_hex(hex, sizeof(hex), hash, SHA256_MAC_LEN);
5163  	wpa_msg(msg_ctx, MSG_INFO,
5164  		DPP_EVENT_CHIRP_RX "id=%d src=" MACSTR " freq=%u hash=%s",
5165  		id, MAC2STR(src), freq, hex);
5166  }
5167  
5168  #endif /* CONFIG_DPP2 */
5169  
5170  
5171  #ifdef CONFIG_DPP3
5172  
dpp_build_pb_announcement(struct dpp_bootstrap_info * bi)5173  struct wpabuf * dpp_build_pb_announcement(struct dpp_bootstrap_info *bi)
5174  {
5175  	struct wpabuf *msg;
5176  	const u8 *r_hash = bi->pubkey_hash_chirp;
5177  #ifdef CONFIG_TESTING_OPTIONS
5178  	u8 test_hash[SHA256_MAC_LEN];
5179  #endif /* CONFIG_TESTING_OPTIONS */
5180  
5181  	wpa_printf(MSG_DEBUG,
5182  		   "DPP: Build Push Button Presence Announcement frame");
5183  
5184  	msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT,
5185  			    4 + SHA256_MAC_LEN);
5186  	if (!msg)
5187  		return NULL;
5188  
5189  #ifdef CONFIG_TESTING_OPTIONS
5190  	if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ) {
5191  		wpa_printf(MSG_INFO,
5192  			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
5193  		os_memcpy(test_hash, r_hash, SHA256_MAC_LEN);
5194  		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5195  		r_hash = test_hash;
5196  	}
5197  #endif /* CONFIG_TESTING_OPTIONS */
5198  
5199  	/* Responder Bootstrapping Key Hash */
5200  	dpp_build_attr_r_bootstrap_key_hash(msg, r_hash);
5201  	wpa_hexdump_buf(MSG_DEBUG,
5202  			"DPP: Push Button Presence Announcement frame attributes",
5203  			msg);
5204  	return msg;
5205  }
5206  
5207  
dpp_build_pb_announcement_resp(struct dpp_bootstrap_info * bi,const u8 * e_hash,const u8 * c_nonce,size_t c_nonce_len)5208  struct wpabuf * dpp_build_pb_announcement_resp(struct dpp_bootstrap_info *bi,
5209  					       const u8 *e_hash,
5210  					       const u8 *c_nonce,
5211  					       size_t c_nonce_len)
5212  {
5213  	struct wpabuf *msg;
5214  	const u8 *i_hash = bi->pubkey_hash_chirp;
5215  #ifdef CONFIG_TESTING_OPTIONS
5216  	u8 test_hash[SHA256_MAC_LEN];
5217  #endif /* CONFIG_TESTING_OPTIONS */
5218  
5219  	wpa_printf(MSG_DEBUG,
5220  		   "DPP: Build Push Button Presence Announcement Response frame");
5221  
5222  	msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP,
5223  			    2 * (4 + SHA256_MAC_LEN) + 4 + c_nonce_len);
5224  	if (!msg)
5225  		return NULL;
5226  
5227  #ifdef CONFIG_TESTING_OPTIONS
5228  	if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_PB_RESP) {
5229  		wpa_printf(MSG_INFO,
5230  			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
5231  		os_memcpy(test_hash, i_hash, SHA256_MAC_LEN);
5232  		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5233  		i_hash = test_hash;
5234  	} else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_RESP) {
5235  		wpa_printf(MSG_INFO,
5236  			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
5237  		os_memcpy(test_hash, e_hash, SHA256_MAC_LEN);
5238  		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5239  		e_hash = test_hash;
5240  	}
5241  #endif /* CONFIG_TESTING_OPTIONS */
5242  
5243  	/* Initiator Bootstrapping Key Hash */
5244  	wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
5245  	wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
5246  	wpabuf_put_le16(msg, SHA256_MAC_LEN);
5247  	wpabuf_put_data(msg, i_hash, SHA256_MAC_LEN);
5248  
5249  	/* Responder Bootstrapping Key Hash */
5250  	dpp_build_attr_r_bootstrap_key_hash(msg, e_hash);
5251  
5252  	/* Configurator Nonce */
5253  	wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE);
5254  	wpabuf_put_le16(msg, c_nonce_len);
5255  	wpabuf_put_data(msg, c_nonce, c_nonce_len);
5256  
5257  	wpa_hexdump_buf(MSG_DEBUG,
5258  			"DPP: Push Button Presence Announcement Response frame attributes",
5259  			msg);
5260  	return msg;
5261  }
5262  
5263  #endif /* CONFIG_DPP3 */
5264