1  /*
2   * DPP reconfiguration
3   * Copyright (c) 2020, The Linux Foundation
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "utils/includes.h"
10  
11  #include "utils/common.h"
12  #include "utils/json.h"
13  #include "crypto/crypto.h"
14  #include "crypto/random.h"
15  #include "crypto/aes.h"
16  #include "crypto/aes_siv.h"
17  #include "dpp.h"
18  #include "dpp_i.h"
19  
20  
21  #ifdef CONFIG_DPP2
22  
dpp_build_attr_csign_key_hash(struct wpabuf * msg,const u8 * hash)23  static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash)
24  {
25  	if (hash) {
26  		wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash");
27  		wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH);
28  		wpabuf_put_le16(msg, SHA256_MAC_LEN);
29  		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
30  	}
31  }
32  
33  
dpp_build_reconfig_announcement(const u8 * csign_key,size_t csign_key_len,const u8 * net_access_key,size_t net_access_key_len,struct dpp_reconfig_id * id)34  struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
35  						size_t csign_key_len,
36  						const u8 *net_access_key,
37  						size_t net_access_key_len,
38  						struct dpp_reconfig_id *id)
39  {
40  	struct wpabuf *msg = NULL;
41  	struct crypto_ec_key *csign = NULL;
42  	struct wpabuf *uncomp;
43  	u8 hash[SHA256_MAC_LEN];
44  	const u8 *addr[1];
45  	size_t len[1];
46  	int res;
47  	size_t attr_len;
48  	const struct dpp_curve_params *own_curve;
49  	struct crypto_ec_key *own_key;
50  	struct wpabuf *a_nonce = NULL, *e_id = NULL;
51  
52  	wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
53  
54  	own_key = dpp_set_keypair(&own_curve, net_access_key,
55  				  net_access_key_len);
56  	if (!own_key) {
57  		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
58  		goto fail;
59  	}
60  
61  	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
62  	if (!csign) {
63  		wpa_printf(MSG_ERROR,
64  			   "DPP: Failed to parse local C-sign-key information");
65  		goto fail;
66  	}
67  
68  	uncomp = crypto_ec_key_get_pubkey_point(csign, 1);
69  	crypto_ec_key_deinit(csign);
70  	if (!uncomp)
71  		goto fail;
72  	addr[0] = wpabuf_head(uncomp);
73  	len[0] = wpabuf_len(uncomp);
74  	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]);
75  	res = sha256_vector(1, addr, len, hash);
76  	wpabuf_free(uncomp);
77  	if (res < 0)
78  		goto fail;
79  	wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)",
80  		    hash, SHA256_MAC_LEN);
81  
82  	if (dpp_update_reconfig_id(id) < 0) {
83  		wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id");
84  		goto fail;
85  	}
86  
87  	a_nonce = crypto_ec_key_get_pubkey_point(id->a_nonce, 0);
88  	e_id = crypto_ec_key_get_pubkey_point(id->e_prime_id, 0);
89  	if (!a_nonce || !e_id)
90  		goto fail;
91  
92  	attr_len = 4 + SHA256_MAC_LEN;
93  	attr_len += 4 + 2;
94  	attr_len += 4 + wpabuf_len(a_nonce);
95  	attr_len += 4 + wpabuf_len(e_id);
96  	msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len);
97  	if (!msg)
98  		goto fail;
99  
100  	/* Configurator C-sign key Hash */
101  	dpp_build_attr_csign_key_hash(msg, hash);
102  
103  	/* Finite Cyclic Group attribute */
104  	wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u",
105  		   own_curve->ike_group);
106  	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
107  	wpabuf_put_le16(msg, 2);
108  	wpabuf_put_le16(msg, own_curve->ike_group);
109  
110  	/* A-NONCE */
111  	wpabuf_put_le16(msg, DPP_ATTR_A_NONCE);
112  	wpabuf_put_le16(msg, wpabuf_len(a_nonce));
113  	wpabuf_put_buf(msg, a_nonce);
114  
115  	/* E'-id */
116  	wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID);
117  	wpabuf_put_le16(msg, wpabuf_len(e_id));
118  	wpabuf_put_buf(msg, e_id);
119  
120  	wpa_hexdump_buf(MSG_DEBUG,
121  			"DPP: Reconfig Announcement frame attributes", msg);
122  fail:
123  	wpabuf_free(a_nonce);
124  	wpabuf_free(e_id);
125  	crypto_ec_key_deinit(own_key);
126  	return msg;
127  }
128  
129  
dpp_reconfig_build_req(struct dpp_authentication * auth)130  static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth)
131  {
132  	struct wpabuf *msg;
133  	size_t attr_len;
134  	u8 ver = DPP_VERSION;
135  
136  	/* Build DPP Reconfig Authentication Request frame attributes */
137  	attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) +
138  		4 + auth->curve->nonce_len;
139  	msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_REQ, attr_len);
140  	if (!msg)
141  		return NULL;
142  
143  	/* Transaction ID */
144  	wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
145  	wpabuf_put_le16(msg, 1);
146  	wpabuf_put_u8(msg, auth->transaction_id);
147  
148  #ifdef CONFIG_TESTING_OPTIONS
149  	if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_RECONFIG_AUTH_REQ) {
150  		wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
151  		goto skip_proto_ver;
152  	}
153  	if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_RECONFIG_AUTH_REQ) {
154  		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
155  		ver = 1;
156  	}
157  #endif /* CONFIG_TESTING_OPTIONS */
158  
159  	/* Protocol Version */
160  	wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
161  	wpabuf_put_le16(msg, 1);
162  	wpabuf_put_u8(msg, ver);
163  
164  #ifdef CONFIG_TESTING_OPTIONS
165  skip_proto_ver:
166  #endif /* CONFIG_TESTING_OPTIONS */
167  
168  	/* DPP Connector */
169  	wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
170  	wpabuf_put_le16(msg, os_strlen(auth->conf->connector));
171  	wpabuf_put_str(msg, auth->conf->connector);
172  
173  	/* C-nonce */
174  	wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE);
175  	wpabuf_put_le16(msg, auth->curve->nonce_len);
176  	wpabuf_put_data(msg, auth->c_nonce, auth->curve->nonce_len);
177  
178  	wpa_hexdump_buf(MSG_DEBUG,
179  			"DPP: Reconfig Authentication Request frame attributes",
180  			msg);
181  
182  	return msg;
183  }
184  
185  
186  static int
dpp_configurator_build_own_connector(struct dpp_configurator * conf,const struct dpp_curve_params * curve)187  dpp_configurator_build_own_connector(struct dpp_configurator *conf,
188  				     const struct dpp_curve_params *curve)
189  {
190  	struct wpabuf *dppcon = NULL;
191  	int ret = -1;
192  
193  	if (conf->connector)
194  		return 0; /* already generated */
195  
196  	wpa_printf(MSG_DEBUG,
197  		   "DPP: Sign own Configurator Connector for reconfiguration with curve %s",
198  		   conf->curve->name);
199  	conf->connector_key = dpp_gen_keypair(curve);
200  	if (!conf->connector_key)
201  		goto fail;
202  
203  	/* Connector (JSON dppCon object) */
204  	dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3);
205  	if (!dppcon)
206  		goto fail;
207  	json_start_object(dppcon, NULL);
208  	json_start_array(dppcon, "groups");
209  	json_start_object(dppcon, NULL);
210  	json_add_string(dppcon, "groupId", "*");
211  	json_value_sep(dppcon);
212  	json_add_string(dppcon, "netRole", "configurator");
213  	json_end_object(dppcon);
214  	json_end_array(dppcon);
215  	json_value_sep(dppcon);
216  	if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL,
217  			  curve) < 0) {
218  		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
219  		goto fail;
220  	}
221  	json_end_object(dppcon);
222  	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
223  		   (const char *) wpabuf_head(dppcon));
224  
225  	conf->connector = dpp_sign_connector(conf, dppcon);
226  	if (!conf->connector)
227  		goto fail;
228  	wpa_printf(MSG_DEBUG, "DPP: signedConnector: %s", conf->connector);
229  
230  	ret = 0;
231  fail:
232  	wpabuf_free(dppcon);
233  	return ret;
234  }
235  
236  
237  struct dpp_authentication *
dpp_reconfig_init(struct dpp_global * dpp,void * msg_ctx,struct dpp_configurator * conf,unsigned int freq,u16 group,const u8 * a_nonce_attr,size_t a_nonce_len,const u8 * e_id_attr,size_t e_id_len)238  dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
239  		  struct dpp_configurator *conf, unsigned int freq, u16 group,
240  		  const u8 *a_nonce_attr, size_t a_nonce_len,
241  		  const u8 *e_id_attr, size_t e_id_len)
242  {
243  	struct dpp_authentication *auth;
244  	const struct dpp_curve_params *curve;
245  	struct crypto_ec_key *a_nonce, *e_prime_id;
246  	struct crypto_ec_point *e_id;
247  
248  	curve = dpp_get_curve_ike_group(group);
249  	if (!curve) {
250  		wpa_printf(MSG_DEBUG,
251  			   "DPP: Unsupported group %u - cannot reconfigure",
252  			   group);
253  		return NULL;
254  	}
255  
256  	if (!a_nonce_attr) {
257  		wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute");
258  		return NULL;
259  	}
260  	wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len);
261  	a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len);
262  	if (!a_nonce) {
263  		wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE");
264  		return NULL;
265  	}
266  	dpp_debug_print_key("A-NONCE", a_nonce);
267  
268  	if (!e_id_attr) {
269  		wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute");
270  		return NULL;
271  	}
272  	e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len);
273  	if (!e_prime_id) {
274  		wpa_printf(MSG_INFO, "DPP: Invalid E'-id");
275  		crypto_ec_key_deinit(a_nonce);
276  		return NULL;
277  	}
278  	dpp_debug_print_key("E'-id", e_prime_id);
279  	e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id);
280  	crypto_ec_key_deinit(a_nonce);
281  	crypto_ec_key_deinit(e_prime_id);
282  	if (!e_id) {
283  		wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id");
284  		return NULL;
285  	}
286  	/* TODO: could use E-id to determine whether reconfiguration with this
287  	 * Enrollee has already been started and is waiting for updated
288  	 * configuration instead of replying again before such configuration
289  	 * becomes available */
290  	crypto_ec_point_deinit(e_id, 1);
291  
292  	auth = dpp_alloc_auth(dpp, msg_ctx);
293  	if (!auth)
294  		return NULL;
295  
296  	auth->conf = conf;
297  	auth->reconfig = 1;
298  	auth->initiator = 1;
299  	auth->waiting_auth_resp = 1;
300  	auth->allowed_roles = DPP_CAPAB_CONFIGURATOR;
301  	auth->configurator = 1;
302  	auth->curve = curve;
303  	auth->transaction_id = 1;
304  	if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0)
305  		goto fail;
306  
307  	if (dpp_configurator_build_own_connector(conf, curve) < 0)
308  		goto fail;
309  
310  	if (random_get_bytes(auth->c_nonce, auth->curve->nonce_len)) {
311  		wpa_printf(MSG_ERROR, "DPP: Failed to generate C-nonce");
312  		goto fail;
313  	}
314  
315  	auth->reconfig_req_msg = dpp_reconfig_build_req(auth);
316  	if (!auth->reconfig_req_msg)
317  		goto fail;
318  
319  out:
320  	return auth;
321  fail:
322  	dpp_auth_deinit(auth);
323  	auth = NULL;
324  	goto out;
325  }
326  
327  
dpp_reconfig_build_resp(struct dpp_authentication * auth,const char * own_connector,struct wpabuf * conn_status)328  static int dpp_reconfig_build_resp(struct dpp_authentication *auth,
329  				   const char *own_connector,
330  				   struct wpabuf *conn_status)
331  {
332  	struct wpabuf *msg = NULL, *clear, *pr = NULL;
333  	u8 *attr_start, *attr_end;
334  	size_t clear_len, attr_len, len[2];
335  	const u8 *addr[2];
336  	u8 *wrapped;
337  	int res = -1;
338  
339  	/* Build DPP Reconfig Authentication Response frame attributes */
340  	clear_len = 4 + auth->curve->nonce_len +
341  		4 + wpabuf_len(conn_status);
342  	clear = wpabuf_alloc(clear_len);
343  	if (!clear)
344  		goto fail;
345  
346  	/* C-nonce (wrapped) */
347  	wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE);
348  	wpabuf_put_le16(clear, auth->curve->nonce_len);
349  	wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len);
350  
351  	/* Connection Status (wrapped) */
352  	wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS);
353  	wpabuf_put_le16(clear, wpabuf_len(conn_status));
354  	wpabuf_put_buf(clear, conn_status);
355  
356  	pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
357  	if (!pr)
358  		goto fail;
359  
360  	attr_len = 4 + 1 + 4 + 1 +
361  		4 + os_strlen(own_connector) +
362  		4 + auth->curve->nonce_len +
363  		4 + wpabuf_len(pr) +
364  		4 + wpabuf_len(clear) + AES_BLOCK_SIZE;
365  	msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len);
366  	if (!msg)
367  		goto fail;
368  
369  	attr_start = wpabuf_put(msg, 0);
370  
371  	/* Transaction ID */
372  	wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
373  	wpabuf_put_le16(msg, 1);
374  	wpabuf_put_u8(msg, auth->transaction_id);
375  
376  	/* Protocol Version */
377  	wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
378  	wpabuf_put_le16(msg, 1);
379  	wpabuf_put_u8(msg, DPP_VERSION);
380  
381  	/* R-Connector */
382  	wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
383  	wpabuf_put_le16(msg, os_strlen(own_connector));
384  	wpabuf_put_str(msg, own_connector);
385  
386  	/* E-nonce */
387  	wpabuf_put_le16(msg, DPP_ATTR_ENROLLEE_NONCE);
388  	wpabuf_put_le16(msg, auth->curve->nonce_len);
389  	wpabuf_put_data(msg, auth->e_nonce, auth->curve->nonce_len);
390  
391  	/* Responder Protocol Key (Pr) */
392  	wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
393  	wpabuf_put_le16(msg, wpabuf_len(pr));
394  	wpabuf_put_buf(msg, pr);
395  
396  	attr_end = wpabuf_put(msg, 0);
397  
398  	/* OUI, OUI type, Crypto Suite, DPP frame type */
399  	addr[0] = wpabuf_head_u8(msg) + 2;
400  	len[0] = 3 + 1 + 1 + 1;
401  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
402  
403  	/* Attributes before Wrapped Data */
404  	addr[1] = attr_start;
405  	len[1] = attr_end - attr_start;
406  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
407  
408  	/* Wrapped Data: {C-nonce, E-nonce, Connection Status}ke */
409  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
410  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
411  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
412  
413  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
414  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
415  			    wpabuf_head(clear), wpabuf_len(clear),
416  			    2, addr, len, wrapped) < 0)
417  		goto fail;
418  
419  	wpa_hexdump_buf(MSG_DEBUG,
420  			"DPP: Reconfig Authentication Response frame attributes",
421  			msg);
422  
423  	wpabuf_free(auth->reconfig_resp_msg);
424  	auth->reconfig_resp_msg = msg;
425  
426  	res = 0;
427  out:
428  	wpabuf_free(clear);
429  	wpabuf_free(pr);
430  	return res;
431  fail:
432  	wpabuf_free(msg);
433  	goto out;
434  }
435  
436  
437  struct dpp_authentication *
dpp_reconfig_auth_req_rx(struct dpp_global * dpp,void * msg_ctx,const char * own_connector,const u8 * net_access_key,size_t net_access_key_len,const u8 * csign_key,size_t csign_key_len,unsigned int freq,const u8 * hdr,const u8 * attr_start,size_t attr_len)438  dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
439  			 const char *own_connector,
440  			 const u8 *net_access_key, size_t net_access_key_len,
441  			 const u8 *csign_key, size_t csign_key_len,
442  			 unsigned int freq, const u8 *hdr,
443  			 const u8 *attr_start, size_t attr_len)
444  {
445  	struct dpp_authentication *auth = NULL;
446  	const u8 *trans_id, *version, *i_connector, *c_nonce;
447  	u16 trans_id_len, version_len, i_connector_len, c_nonce_len;
448  	struct dpp_signed_connector_info info;
449  	enum dpp_status_error res;
450  	struct json_token *root = NULL, *own_root = NULL, *token;
451  	unsigned char *own_conn = NULL;
452  	struct wpabuf *conn_status = NULL;
453  
454  	os_memset(&info, 0, sizeof(info));
455  
456  	trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID,
457  			       &trans_id_len);
458  	if (!trans_id || trans_id_len != 1) {
459  		wpa_printf(MSG_DEBUG,
460  			   "DPP: Peer did not include Transaction ID");
461  		goto fail;
462  	}
463  
464  	version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
465  			       &version_len);
466  	if (!version || version_len < 1 || version[0] < 2) {
467  		wpa_printf(MSG_DEBUG,
468  			   "DPP: Missing or invalid Protocol Version attribute");
469  		goto fail;
470  	}
471  
472  	i_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR,
473  			       &i_connector_len);
474  	if (!i_connector) {
475  		wpa_printf(MSG_DEBUG, "DPP: Missing I-Connector attribute");
476  		goto fail;
477  	}
478  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector",
479  			  i_connector, i_connector_len);
480  
481  	c_nonce = dpp_get_attr(attr_start, attr_len,
482  			       DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
483  	if (!c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
484  		wpa_printf(MSG_DEBUG,
485  			   "DPP: Missing or invalid C-nonce attribute");
486  		goto fail;
487  	}
488  	wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
489  
490  	res = dpp_check_signed_connector(&info, csign_key, csign_key_len,
491  					 i_connector, i_connector_len);
492  	if (res != DPP_STATUS_OK) {
493  		wpa_printf(MSG_DEBUG, "DPP: Invalid I-Connector");
494  		goto fail;
495  	}
496  
497  	root = json_parse((const char *) info.payload, info.payload_len);
498  	own_root = dpp_parse_own_connector(own_connector);
499  	if (!root || !own_root ||
500  	    !dpp_connector_match_groups(own_root, root, true)) {
501  		wpa_printf(MSG_DEBUG,
502  			   "DPP: I-Connector does not include compatible group netrole with own connector");
503  		goto fail;
504  	}
505  
506  	token = json_get_member(root, "expiry");
507  	if (token && token->type == JSON_STRING &&
508  	    dpp_key_expired(token->string, NULL)) {
509  		wpa_printf(MSG_DEBUG,
510  			   "DPP: I-Connector (netAccessKey) has expired");
511  		goto fail;
512  	}
513  
514  	token = json_get_member(root, "netAccessKey");
515  	if (!token || token->type != JSON_OBJECT) {
516  		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
517  		goto fail;
518  	}
519  
520  	auth = dpp_alloc_auth(dpp, msg_ctx);
521  	if (!auth)
522  		return NULL;
523  
524  	auth->reconfig = 1;
525  	auth->allowed_roles = DPP_CAPAB_ENROLLEE;
526  	if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0)
527  		goto fail;
528  
529  	auth->transaction_id = trans_id[0];
530  
531  	auth->peer_version = version[0];
532  	wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
533  		   auth->peer_version);
534  
535  	os_memcpy(auth->c_nonce, c_nonce, c_nonce_len);
536  
537  	if (dpp_reconfig_derive_ke_responder(auth, net_access_key,
538  					     net_access_key_len, token) < 0)
539  		goto fail;
540  
541  	if (c_nonce_len != auth->curve->nonce_len) {
542  		wpa_printf(MSG_DEBUG,
543  			   "DPP: Unexpected C-nonce length %u (curve nonce len %zu)",
544  			   c_nonce_len, auth->curve->nonce_len);
545  		goto fail;
546  	}
547  
548  	/* Build Connection Status object */
549  	/* TODO: Get appropriate result value */
550  	/* TODO: ssid64 and channelList */
551  	conn_status = dpp_build_conn_status(DPP_STATUS_NO_AP, NULL, 0, NULL);
552  	if (!conn_status)
553  		goto fail;
554  
555  	if (dpp_reconfig_build_resp(auth, own_connector, conn_status) < 0)
556  		goto fail;
557  
558  out:
559  	os_free(info.payload);
560  	os_free(own_conn);
561  	json_free(root);
562  	json_free(own_root);
563  	wpabuf_free(conn_status);
564  	return auth;
565  fail:
566  	dpp_auth_deinit(auth);
567  	auth = NULL;
568  	goto out;
569  }
570  
571  
572  static struct wpabuf *
dpp_reconfig_build_conf(struct dpp_authentication * auth)573  dpp_reconfig_build_conf(struct dpp_authentication *auth)
574  {
575  	struct wpabuf *msg = NULL, *clear;
576  	u8 *attr_start, *attr_end;
577  	size_t clear_len, attr_len, len[2];
578  	const u8 *addr[2];
579  	u8 *wrapped;
580  	u8 flags;
581  
582  	/* Build DPP Reconfig Authentication Confirm frame attributes */
583  	clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) +
584  		4 + 1;
585  	clear = wpabuf_alloc(clear_len);
586  	if (!clear)
587  		goto fail;
588  
589  	/* Transaction ID */
590  	wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID);
591  	wpabuf_put_le16(clear, 1);
592  	wpabuf_put_u8(clear, auth->transaction_id);
593  
594  	/* Protocol Version */
595  	wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION);
596  	wpabuf_put_le16(clear, 1);
597  	wpabuf_put_u8(clear, auth->peer_version);
598  
599  	/* C-nonce (wrapped) */
600  	wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE);
601  	wpabuf_put_le16(clear, auth->curve->nonce_len);
602  	wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len);
603  
604  	/* E-nonce (wrapped) */
605  	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
606  	wpabuf_put_le16(clear, auth->curve->nonce_len);
607  	wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len);
608  
609  	/* Reconfig-Flags (wrapped) */
610  	flags = DPP_CONFIG_REPLACEKEY;
611  	wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS);
612  	wpabuf_put_le16(clear, 1);
613  	wpabuf_put_u8(clear, flags);
614  
615  	attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE;
616  	attr_len += 4 + 1;
617  	msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len);
618  	if (!msg)
619  		goto fail;
620  
621  	attr_start = wpabuf_put(msg, 0);
622  
623  	/* DPP Status */
624  	dpp_build_attr_status(msg, DPP_STATUS_OK);
625  
626  	attr_end = wpabuf_put(msg, 0);
627  
628  	/* OUI, OUI type, Crypto Suite, DPP frame type */
629  	addr[0] = wpabuf_head_u8(msg) + 2;
630  	len[0] = 3 + 1 + 1 + 1;
631  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
632  
633  	/* Attributes before Wrapped Data */
634  	addr[1] = attr_start;
635  	len[1] = attr_end - attr_start;
636  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
637  
638  	/* Wrapped Data */
639  	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
640  	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
641  	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
642  
643  	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
644  	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
645  			    wpabuf_head(clear), wpabuf_len(clear),
646  			    2, addr, len, wrapped) < 0)
647  		goto fail;
648  
649  	wpa_hexdump_buf(MSG_DEBUG,
650  			"DPP: Reconfig Authentication Confirm frame attributes",
651  			msg);
652  
653  out:
654  	wpabuf_free(clear);
655  	return msg;
656  fail:
657  	wpabuf_free(msg);
658  	msg = NULL;
659  	goto out;
660  }
661  
662  
663  struct wpabuf *
dpp_reconfig_auth_resp_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)664  dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
665  			 const u8 *attr_start, size_t attr_len)
666  {
667  	const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data,
668  		*c_nonce, *e_nonce, *conn_status;
669  	u16 trans_id_len, version_len, r_connector_len, r_proto_len,
670  		wrapped_data_len, c_nonce_len, e_nonce_len, conn_status_len;
671  	struct wpabuf *conf = NULL;
672  	char *signed_connector = NULL;
673  	struct dpp_signed_connector_info info;
674  	enum dpp_status_error res;
675  	struct json_token *root = NULL, *token, *conn_status_json = NULL;
676  	const u8 *addr[2];
677  	size_t len[2];
678  	u8 *unwrapped = NULL;
679  	size_t unwrapped_len = 0;
680  
681  	os_memset(&info, 0, sizeof(info));
682  
683  	if (!auth->reconfig || !auth->configurator)
684  		goto fail;
685  
686  	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
687  				    &wrapped_data_len);
688  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
689  		dpp_auth_fail(auth,
690  			      "Missing or invalid required Wrapped Data attribute");
691  		goto fail;
692  	}
693  	wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
694  		    wrapped_data, wrapped_data_len);
695  	attr_len = wrapped_data - 4 - attr_start;
696  
697  	trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID,
698  			       &trans_id_len);
699  	if (!trans_id || trans_id_len != 1) {
700  		dpp_auth_fail(auth, "Peer did not include Transaction ID");
701  		goto fail;
702  	}
703  	if (trans_id[0] != auth->transaction_id) {
704  		dpp_auth_fail(auth, "Transaction ID mismatch");
705  		goto fail;
706  	}
707  
708  	version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
709  			       &version_len);
710  	if (!version || version_len < 1 || version[0] < 2) {
711  		dpp_auth_fail(auth,
712  			      "Missing or invalid Protocol Version attribute");
713  		goto fail;
714  	}
715  	auth->peer_version = version[0];
716  	wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
717  		   auth->peer_version);
718  
719  	r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR,
720  				   &r_connector_len);
721  	if (!r_connector) {
722  		dpp_auth_fail(auth, " Missing R-Connector attribute");
723  		goto fail;
724  	}
725  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector",
726  			  r_connector, r_connector_len);
727  
728  	e_nonce = dpp_get_attr(attr_start, attr_len,
729  			       DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len);
730  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
731  		dpp_auth_fail(auth, "Missing or invalid E-nonce");
732  		goto fail;
733  	}
734  	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len);
735  	os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
736  
737  	r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
738  			       &r_proto_len);
739  	if (!r_proto) {
740  		dpp_auth_fail(auth,
741  			      "Missing required Responder Protocol Key attribute");
742  		goto fail;
743  	}
744  	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
745  		    r_proto, r_proto_len);
746  
747  	signed_connector = os_malloc(r_connector_len + 1);
748  	if (!signed_connector)
749  		goto fail;
750  	os_memcpy(signed_connector, r_connector, r_connector_len);
751  	signed_connector[r_connector_len] = '\0';
752  
753  	res = dpp_process_signed_connector(&info, auth->conf->csign,
754  					   signed_connector);
755  	if (res != DPP_STATUS_OK) {
756  		dpp_auth_fail(auth, "Invalid R-Connector");
757  		goto fail;
758  	}
759  
760  	root = json_parse((const char *) info.payload, info.payload_len);
761  	if (!root) {
762  		dpp_auth_fail(auth, "Invalid Connector payload");
763  		goto fail;
764  	}
765  
766  	/* Do not check netAccessKey expiration for reconfiguration to allow
767  	 * expired Connector to be updated. */
768  
769  	token = json_get_member(root, "netAccessKey");
770  	if (!token || token->type != JSON_OBJECT) {
771  		dpp_auth_fail(auth, "No netAccessKey object found");
772  		goto fail;
773  	}
774  
775  	if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len,
776  					     token) < 0)
777  		goto fail;
778  
779  	addr[0] = hdr;
780  	len[0] = DPP_HDR_LEN;
781  	addr[1] = attr_start;
782  	len[1] = attr_len;
783  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
784  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
785  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
786  		    wrapped_data, wrapped_data_len);
787  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
788  	unwrapped = os_malloc(unwrapped_len);
789  	if (!unwrapped)
790  		goto fail;
791  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
792  			    wrapped_data, wrapped_data_len,
793  			    2, addr, len, unwrapped) < 0) {
794  		dpp_auth_fail(auth, "AES-SIV decryption failed");
795  		goto fail;
796  	}
797  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
798  		    unwrapped, unwrapped_len);
799  
800  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
801  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
802  		goto fail;
803  	}
804  
805  	c_nonce = dpp_get_attr(unwrapped, unwrapped_len,
806  			       DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
807  	if (!c_nonce || c_nonce_len != auth->curve->nonce_len ||
808  	    os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) {
809  		dpp_auth_fail(auth, "Missing or invalid C-nonce");
810  		goto fail;
811  	}
812  	wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
813  
814  	conn_status = dpp_get_attr(unwrapped, unwrapped_len,
815  				   DPP_ATTR_CONN_STATUS, &conn_status_len);
816  	if (!conn_status) {
817  		dpp_auth_fail(auth, "Missing Connection Status attribute");
818  		goto fail;
819  	}
820  	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus",
821  			  conn_status, conn_status_len);
822  
823  	conn_status_json = json_parse((const char *) conn_status,
824  				      conn_status_len);
825  	if (!conn_status_json) {
826  		dpp_auth_fail(auth, "Could not parse connStatus");
827  		goto fail;
828  	}
829  	/* TODO: use connStatus information */
830  
831  	conf = dpp_reconfig_build_conf(auth);
832  	if (conf)
833  		auth->reconfig_success = true;
834  
835  out:
836  	json_free(root);
837  	json_free(conn_status_json);
838  	bin_clear_free(unwrapped, unwrapped_len);
839  	os_free(info.payload);
840  	os_free(signed_connector);
841  	return conf;
842  fail:
843  	wpabuf_free(conf);
844  	conf = NULL;
845  	goto out;
846  }
847  
848  
dpp_reconfig_auth_conf_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)849  int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
850  			      const u8 *attr_start, size_t attr_len)
851  {
852  	const u8 *trans_id, *version, *wrapped_data, *c_nonce, *e_nonce,
853  		*reconfig_flags, *status;
854  	u16 trans_id_len, version_len, wrapped_data_len, c_nonce_len,
855  		e_nonce_len, reconfig_flags_len, status_len;
856  	const u8 *addr[2];
857  	size_t len[2];
858  	u8 *unwrapped = NULL;
859  	size_t unwrapped_len = 0;
860  	int res = -1;
861  	u8 flags;
862  
863  	if (!auth->reconfig || auth->configurator)
864  		goto fail;
865  
866  	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
867  				    &wrapped_data_len);
868  	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
869  		dpp_auth_fail(auth,
870  			      "Missing or invalid required Wrapped Data attribute");
871  		goto fail;
872  	}
873  	wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
874  		    wrapped_data, wrapped_data_len);
875  	attr_len = wrapped_data - 4 - attr_start;
876  
877  	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
878  			      &status_len);
879  	if (!status || status_len < 1) {
880  		dpp_auth_fail(auth,
881  			      "Missing or invalid required DPP Status attribute");
882  		goto fail;
883  	}
884  	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
885  	if (status[0] != DPP_STATUS_OK) {
886  		dpp_auth_fail(auth,
887  			      "Reconfiguration did not complete successfully");
888  		goto fail;
889  	}
890  
891  	addr[0] = hdr;
892  	len[0] = DPP_HDR_LEN;
893  	addr[1] = attr_start;
894  	len[1] = attr_len;
895  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
896  	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
897  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
898  		    wrapped_data, wrapped_data_len);
899  	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
900  	unwrapped = os_malloc(unwrapped_len);
901  	if (!unwrapped)
902  		goto fail;
903  	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
904  			    wrapped_data, wrapped_data_len,
905  			    2, addr, len, unwrapped) < 0) {
906  		dpp_auth_fail(auth, "AES-SIV decryption failed");
907  		goto fail;
908  	}
909  	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
910  		    unwrapped, unwrapped_len);
911  
912  	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
913  		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
914  		goto fail;
915  	}
916  
917  	trans_id = dpp_get_attr(unwrapped, unwrapped_len,
918  				DPP_ATTR_TRANSACTION_ID, &trans_id_len);
919  	if (!trans_id || trans_id_len != 1 ||
920  	    trans_id[0] != auth->transaction_id) {
921  		dpp_auth_fail(auth,
922  			      "Peer did not include valid Transaction ID");
923  		goto fail;
924  	}
925  
926  	version = dpp_get_attr(unwrapped, unwrapped_len,
927  			       DPP_ATTR_PROTOCOL_VERSION, &version_len);
928  	if (!version || version_len < 1 || version[0] != DPP_VERSION) {
929  		dpp_auth_fail(auth,
930  			      "Missing or invalid Protocol Version attribute");
931  		goto fail;
932  	}
933  
934  	c_nonce = dpp_get_attr(unwrapped, unwrapped_len,
935  			       DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
936  	if (!c_nonce || c_nonce_len != auth->curve->nonce_len ||
937  	    os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) {
938  		dpp_auth_fail(auth, "Missing or invalid C-nonce");
939  		goto fail;
940  	}
941  	wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
942  
943  	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
944  			       DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len);
945  	if (!e_nonce || e_nonce_len != auth->curve->nonce_len ||
946  	    os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
947  		dpp_auth_fail(auth, "Missing or invalid E-nonce");
948  		goto fail;
949  	}
950  	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len);
951  
952  	reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len,
953  				      DPP_ATTR_RECONFIG_FLAGS,
954  				      &reconfig_flags_len);
955  	if (!reconfig_flags || reconfig_flags_len < 1) {
956  		dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags");
957  		goto fail;
958  	}
959  	flags = reconfig_flags[0] & BIT(0);
960  	wpa_printf(MSG_DEBUG, "DPP: Reconfig Flags connectorKey=%u", flags);
961  	auth->reconfig_connector_key = flags;
962  
963  	auth->reconfig_success = true;
964  	res = 0;
965  fail:
966  	bin_clear_free(unwrapped, unwrapped_len);
967  	return res;
968  }
969  
970  #endif /* CONFIG_DPP2 */
971