xref: /freebsd/contrib/wpa/src/common/dpp_pkex.c (revision 8165650389ba2d0a68cea6902ac3750055cad9da)
1 /*
2  * DPP PKEX functionality
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2020, The Linux Foundation
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "utils/includes.h"
11 
12 #include "utils/common.h"
13 #include "common/wpa_ctrl.h"
14 #include "crypto/aes.h"
15 #include "crypto/aes_siv.h"
16 #include "crypto/crypto.h"
17 #include "dpp.h"
18 #include "dpp_i.h"
19 
20 
21 #ifdef CONFIG_TESTING_OPTIONS
22 u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
23 u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
24 u8 dpp_pkex_ephemeral_key_override[600];
25 size_t dpp_pkex_ephemeral_key_override_len = 0;
26 #endif /* CONFIG_TESTING_OPTIONS */
27 
28 
29 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex,
30 						   bool v2)
31 {
32 	struct crypto_ec *ec = NULL;
33 	struct crypto_ec_point *Qi = NULL, *M = NULL, *X = NULL;
34 	u8 *Mx, *My;
35 	struct wpabuf *msg = NULL;
36 	size_t attr_len;
37 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
38 
39 	wpa_printf(MSG_DEBUG, "DPP: Build PKEX %sExchange Request",
40 		   v2 ? "" : "Version 1 ");
41 
42 	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
43 	Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
44 				pkex->code_len, pkex->identifier, &ec);
45 	if (!Qi)
46 		goto fail;
47 
48 	/* Generate a random ephemeral keypair x/X */
49 #ifdef CONFIG_TESTING_OPTIONS
50 	if (dpp_pkex_ephemeral_key_override_len) {
51 		const struct dpp_curve_params *tmp_curve;
52 
53 		wpa_printf(MSG_INFO,
54 			   "DPP: TESTING - override ephemeral key x/X");
55 		pkex->x = dpp_set_keypair(&tmp_curve,
56 					  dpp_pkex_ephemeral_key_override,
57 					  dpp_pkex_ephemeral_key_override_len);
58 	} else {
59 		pkex->x = dpp_gen_keypair(curve);
60 	}
61 #else /* CONFIG_TESTING_OPTIONS */
62 	pkex->x = dpp_gen_keypair(curve);
63 #endif /* CONFIG_TESTING_OPTIONS */
64 	if (!pkex->x)
65 		goto fail;
66 
67 	/* M = X + Qi */
68 	X = crypto_ec_key_get_public_key(pkex->x);
69 	M = crypto_ec_point_init(ec);
70 	if (!X || !M)
71 		goto fail;
72 	crypto_ec_point_debug_print(ec, X, "DPP: X");
73 
74 	if (crypto_ec_point_add(ec, X, Qi, M))
75 		goto fail;
76 	crypto_ec_point_debug_print(ec, M, "DPP: M");
77 
78 	/* Initiator -> Responder: group, [identifier,] M */
79 	attr_len = 4 + 2;
80 #ifdef CONFIG_DPP2
81 	if (v2)
82 		attr_len += 4 + 1;
83 #endif /* CONFIG_DPP2 */
84 	if (pkex->identifier)
85 		attr_len += 4 + os_strlen(pkex->identifier);
86 	attr_len += 4 + 2 * curve->prime_len;
87 	msg = dpp_alloc_msg(v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
88 			    DPP_PA_PKEX_V1_EXCHANGE_REQ, attr_len);
89 	if (!msg)
90 		goto fail;
91 
92 #ifdef CONFIG_DPP2
93 	if (v2) {
94 		/* Protocol Version */
95 		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
96 		wpabuf_put_le16(msg, 1);
97 		wpabuf_put_u8(msg, DPP_VERSION);
98 	}
99 #endif /* CONFIG_DPP2 */
100 
101 #ifdef CONFIG_TESTING_OPTIONS
102 	if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
103 		wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
104 		goto skip_finite_cyclic_group;
105 	}
106 #endif /* CONFIG_TESTING_OPTIONS */
107 
108 	/* Finite Cyclic Group attribute */
109 	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
110 	wpabuf_put_le16(msg, 2);
111 	wpabuf_put_le16(msg, curve->ike_group);
112 
113 #ifdef CONFIG_TESTING_OPTIONS
114 skip_finite_cyclic_group:
115 #endif /* CONFIG_TESTING_OPTIONS */
116 
117 	/* Code Identifier attribute */
118 	if (pkex->identifier) {
119 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
120 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
121 		wpabuf_put_str(msg, pkex->identifier);
122 	}
123 
124 #ifdef CONFIG_TESTING_OPTIONS
125 	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
126 		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
127 		goto out;
128 	}
129 #endif /* CONFIG_TESTING_OPTIONS */
130 
131 	/* M in Encrypted Key attribute */
132 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
133 	wpabuf_put_le16(msg, 2 * curve->prime_len);
134 
135 #ifdef CONFIG_TESTING_OPTIONS
136 	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
137 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
138 		if (dpp_test_gen_invalid_key(msg, curve) < 0)
139 			goto fail;
140 		goto out;
141 	}
142 #endif /* CONFIG_TESTING_OPTIONS */
143 
144 	Mx = wpabuf_put(msg, curve->prime_len);
145 	My = wpabuf_put(msg, curve->prime_len);
146 	if (crypto_ec_point_to_bin(ec, M, Mx, My))
147 		goto fail;
148 	wpabuf_free(pkex->enc_key);
149 	pkex->enc_key = wpabuf_alloc_copy(Mx, 2 * curve->prime_len);
150 
151 	os_memcpy(pkex->Mx, Mx, curve->prime_len);
152 
153 out:
154 	crypto_ec_point_deinit(X, 1);
155 	crypto_ec_point_deinit(M, 1);
156 	crypto_ec_point_deinit(Qi, 1);
157 	crypto_ec_deinit(ec);
158 	return msg;
159 fail:
160 	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
161 	wpabuf_free(msg);
162 	msg = NULL;
163 	goto out;
164 }
165 
166 
167 static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
168 {
169 	wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
170 }
171 
172 
173 struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
174 				const u8 *own_mac,
175 				const char *identifier, const char *code,
176 				size_t code_len, bool v2)
177 {
178 	struct dpp_pkex *pkex;
179 
180 #ifdef CONFIG_TESTING_OPTIONS
181 	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
182 		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
183 			   MAC2STR(dpp_pkex_own_mac_override));
184 		own_mac = dpp_pkex_own_mac_override;
185 	}
186 #endif /* CONFIG_TESTING_OPTIONS */
187 
188 	pkex = os_zalloc(sizeof(*pkex));
189 	if (!pkex)
190 		return NULL;
191 	pkex->msg_ctx = msg_ctx;
192 	pkex->initiator = 1;
193 	pkex->v2 = v2;
194 	pkex->own_bi = bi;
195 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
196 	if (identifier) {
197 		pkex->identifier = os_strdup(identifier);
198 		if (!pkex->identifier)
199 			goto fail;
200 	}
201 	pkex->code = os_memdup(code, code_len);
202 	if (!pkex->code)
203 		goto fail;
204 	pkex->code_len = code_len;
205 	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex, v2);
206 	if (!pkex->exchange_req)
207 		goto fail;
208 	return pkex;
209 fail:
210 	dpp_pkex_free(pkex);
211 	return NULL;
212 }
213 
214 
215 static struct wpabuf *
216 dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
217 			     enum dpp_status_error status,
218 			     const u8 *Nx, const u8 *Ny)
219 {
220 	struct wpabuf *msg = NULL;
221 	size_t attr_len;
222 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
223 
224 	/* Initiator -> Responder: DPP Status, [Protocol Version,] [identifier,]
225 	 * N */
226 	attr_len = 4 + 1;
227 #ifdef CONFIG_DPP2
228 	if (pkex->v2)
229 		attr_len += 4 + 1;
230 #endif /* CONFIG_DPP2 */
231 	if (pkex->identifier)
232 		attr_len += 4 + os_strlen(pkex->identifier);
233 	attr_len += 4 + 2 * curve->prime_len;
234 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
235 	if (!msg)
236 		goto fail;
237 
238 #ifdef CONFIG_TESTING_OPTIONS
239 	if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) {
240 		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
241 		goto skip_status;
242 	}
243 
244 	if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) {
245 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
246 		status = 255;
247 	}
248 #endif /* CONFIG_TESTING_OPTIONS */
249 
250 	/* DPP Status */
251 	dpp_build_attr_status(msg, status);
252 
253 #ifdef CONFIG_TESTING_OPTIONS
254 skip_status:
255 #endif /* CONFIG_TESTING_OPTIONS */
256 
257 #ifdef CONFIG_DPP2
258 	if (pkex->v2) {
259 		/* Protocol Version */
260 		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
261 		wpabuf_put_le16(msg, 1);
262 		wpabuf_put_u8(msg, DPP_VERSION);
263 	}
264 #endif /* CONFIG_DPP2 */
265 
266 	/* Code Identifier attribute */
267 	if (pkex->identifier) {
268 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
269 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
270 		wpabuf_put_str(msg, pkex->identifier);
271 	}
272 
273 	if (status != DPP_STATUS_OK)
274 		goto skip_encrypted_key;
275 
276 #ifdef CONFIG_TESTING_OPTIONS
277 	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
278 		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
279 		goto skip_encrypted_key;
280 	}
281 #endif /* CONFIG_TESTING_OPTIONS */
282 
283 	/* N in Encrypted Key attribute */
284 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
285 	wpabuf_put_le16(msg, 2 * curve->prime_len);
286 
287 #ifdef CONFIG_TESTING_OPTIONS
288 	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
289 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
290 		if (dpp_test_gen_invalid_key(msg, curve) < 0)
291 			goto fail;
292 		goto skip_encrypted_key;
293 	}
294 #endif /* CONFIG_TESTING_OPTIONS */
295 
296 	wpabuf_put_data(msg, Nx, curve->prime_len);
297 	wpabuf_put_data(msg, Ny, curve->prime_len);
298 	os_memcpy(pkex->Nx, Nx, curve->prime_len);
299 
300 skip_encrypted_key:
301 	if (status == DPP_STATUS_BAD_GROUP) {
302 		/* Finite Cyclic Group attribute */
303 		wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
304 		wpabuf_put_le16(msg, 2);
305 		wpabuf_put_le16(msg, curve->ike_group);
306 	}
307 
308 	return msg;
309 fail:
310 	wpabuf_free(msg);
311 	return NULL;
312 }
313 
314 
315 static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len,
316 				     const char *identifier)
317 {
318 	if (!attr_id && identifier) {
319 		wpa_printf(MSG_DEBUG,
320 			   "DPP: No PKEX code identifier received, but expected one");
321 		return 0;
322 	}
323 
324 	if (attr_id && !identifier) {
325 		wpa_printf(MSG_DEBUG,
326 			   "DPP: PKEX code identifier received, but not expecting one");
327 		return 0;
328 	}
329 
330 	if (attr_id && identifier &&
331 	    (os_strlen(identifier) != attr_id_len ||
332 	     os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
333 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
334 		return 0;
335 	}
336 
337 	return 1;
338 }
339 
340 
341 struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
342 					   struct dpp_bootstrap_info *bi,
343 					   const u8 *own_mac,
344 					   const u8 *peer_mac,
345 					   const char *identifier,
346 					   const char *code, size_t code_len,
347 					   const u8 *buf, size_t len, bool v2)
348 {
349 	const u8 *attr_group, *attr_id, *attr_key;
350 	u16 attr_group_len, attr_id_len, attr_key_len;
351 	const struct dpp_curve_params *curve = bi->curve;
352 	u16 ike_group;
353 	struct dpp_pkex *pkex = NULL;
354 	struct crypto_ec_point *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL,
355 		*N = NULL, *Y = NULL;
356 	struct crypto_ec *ec = NULL;
357 	u8 *x_coord = NULL, *y_coord = NULL;
358 	u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
359 	size_t Kx_len;
360 	int res;
361 	u8 peer_version = 0;
362 
363 	if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
364 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
365 			"PKEX counter t limit reached - ignore message");
366 		return NULL;
367 	}
368 
369 #ifdef CONFIG_DPP2
370 	if (v2) {
371 		const u8 *version;
372 		u16 version_len;
373 
374 		version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
375 				       &version_len);
376 		if (!version || version_len < 1 || version[0] == 0) {
377 			wpa_msg(msg_ctx, MSG_INFO,
378 				"Missing or invalid Protocol Version attribute");
379 			return NULL;
380 		}
381 		peer_version = version[0];
382 		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
383 			   peer_version);
384 	}
385 #endif /* CONFIG_DPP2 */
386 
387 #ifdef CONFIG_TESTING_OPTIONS
388 	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
389 		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
390 			   MAC2STR(dpp_pkex_peer_mac_override));
391 		peer_mac = dpp_pkex_peer_mac_override;
392 	}
393 	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
394 		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
395 			   MAC2STR(dpp_pkex_own_mac_override));
396 		own_mac = dpp_pkex_own_mac_override;
397 	}
398 #endif /* CONFIG_TESTING_OPTIONS */
399 
400 	attr_id_len = 0;
401 	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
402 			       &attr_id_len);
403 	if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier))
404 		return NULL;
405 
406 	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
407 				  &attr_group_len);
408 	if (!attr_group || attr_group_len != 2) {
409 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
410 			"Missing or invalid Finite Cyclic Group attribute");
411 		return NULL;
412 	}
413 	ike_group = WPA_GET_LE16(attr_group);
414 	if (ike_group != curve->ike_group) {
415 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
416 			"Mismatching PKEX curve: peer=%u own=%u",
417 			ike_group, curve->ike_group);
418 		pkex = os_zalloc(sizeof(*pkex));
419 		if (!pkex)
420 			goto fail;
421 		pkex->v2 = v2;
422 		pkex->peer_version = peer_version;
423 		pkex->own_bi = bi;
424 		pkex->failed = 1;
425 		pkex->exchange_resp = dpp_pkex_build_exchange_resp(
426 			pkex, DPP_STATUS_BAD_GROUP, NULL, NULL);
427 		if (!pkex->exchange_resp)
428 			goto fail;
429 		return pkex;
430 	}
431 
432 	/* M in Encrypted Key attribute */
433 	attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
434 				&attr_key_len);
435 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
436 	    attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
437 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
438 			"Missing Encrypted Key attribute");
439 		return NULL;
440 	}
441 
442 	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
443 	Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, code_len,
444 				identifier, &ec);
445 	if (!Qi)
446 		goto fail;
447 
448 	/* X' = M - Qi */
449 	X = crypto_ec_point_init(ec);
450 	M = crypto_ec_point_from_bin(ec, attr_key);
451 	if (!X || !M ||
452 	    crypto_ec_point_is_at_infinity(ec, M) ||
453 	    !crypto_ec_point_is_on_curve(ec, M) ||
454 	    crypto_ec_point_invert(ec, Qi) ||
455 	    crypto_ec_point_add(ec, M, Qi, X) ||
456 	    crypto_ec_point_is_at_infinity(ec, X) ||
457 	    !crypto_ec_point_is_on_curve(ec, X)) {
458 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
459 			"Invalid Encrypted Key value");
460 		bi->pkex_t++;
461 		goto fail;
462 	}
463 	crypto_ec_point_debug_print(ec, M, "DPP: M");
464 	crypto_ec_point_debug_print(ec, X, "DPP: X'");
465 
466 	pkex = os_zalloc(sizeof(*pkex));
467 	if (!pkex)
468 		goto fail;
469 	pkex->v2 = v2;
470 	pkex->peer_version = peer_version;
471 	pkex->t = bi->pkex_t;
472 	pkex->msg_ctx = msg_ctx;
473 	pkex->own_bi = bi;
474 	if (own_mac)
475 		os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
476 	if (peer_mac)
477 		os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
478 	if (identifier) {
479 		pkex->identifier = os_strdup(identifier);
480 		if (!pkex->identifier)
481 			goto fail;
482 	}
483 	pkex->code = os_memdup(code, code_len);
484 	if (!pkex->code)
485 		goto fail;
486 	pkex->code_len = code_len;
487 
488 	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
489 
490 	x_coord = os_malloc(curve->prime_len);
491 	y_coord = os_malloc(curve->prime_len);
492 	if (!x_coord || !y_coord ||
493 	    crypto_ec_point_to_bin(ec, X, x_coord, y_coord))
494 		goto fail;
495 
496 	pkex->x = crypto_ec_key_set_pub(curve->ike_group, x_coord,
497 					y_coord, crypto_ec_prime_len(ec));
498 	if (!pkex->x)
499 		goto fail;
500 
501 	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
502 	Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, code_len,
503 				identifier, NULL);
504 	if (!Qr)
505 		goto fail;
506 
507 	/* Generate a random ephemeral keypair y/Y */
508 #ifdef CONFIG_TESTING_OPTIONS
509 	if (dpp_pkex_ephemeral_key_override_len) {
510 		const struct dpp_curve_params *tmp_curve;
511 
512 		wpa_printf(MSG_INFO,
513 			   "DPP: TESTING - override ephemeral key y/Y");
514 		pkex->y = dpp_set_keypair(&tmp_curve,
515 					  dpp_pkex_ephemeral_key_override,
516 					  dpp_pkex_ephemeral_key_override_len);
517 	} else {
518 		pkex->y = dpp_gen_keypair(curve);
519 	}
520 #else /* CONFIG_TESTING_OPTIONS */
521 	pkex->y = dpp_gen_keypair(curve);
522 #endif /* CONFIG_TESTING_OPTIONS */
523 	if (!pkex->y)
524 		goto fail;
525 
526 	/* N = Y + Qr */
527 	Y = crypto_ec_key_get_public_key(pkex->y);
528 	if (!Y)
529 		goto fail;
530 	crypto_ec_point_debug_print(ec, Y, "DPP: Y");
531 
532 	N = crypto_ec_point_init(ec);
533 	if (!N ||
534 	    crypto_ec_point_add(ec, Y, Qr, N) ||
535 	    crypto_ec_point_to_bin(ec, N, x_coord, y_coord))
536 		goto fail;
537 	crypto_ec_point_debug_print(ec, N, "DPP: N");
538 
539 	pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
540 							   x_coord, y_coord);
541 	if (!pkex->exchange_resp)
542 		goto fail;
543 
544 	/* K = y * X' */
545 	if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0)
546 		goto fail;
547 
548 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
549 			Kx, Kx_len);
550 
551 	/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
552 	res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac,
553 				pkex->v2 ? NULL : pkex->own_mac,
554 				pkex->peer_version, DPP_VERSION,
555 				pkex->Mx, curve->prime_len,
556 				pkex->Nx, curve->prime_len, pkex->code,
557 				pkex->code_len,	Kx, Kx_len, pkex->z,
558 				curve->hash_len);
559 	os_memset(Kx, 0, Kx_len);
560 	if (res < 0)
561 		goto fail;
562 
563 	pkex->exchange_done = 1;
564 
565 out:
566 	os_free(x_coord);
567 	os_free(y_coord);
568 	crypto_ec_point_deinit(Qi, 1);
569 	crypto_ec_point_deinit(Qr, 1);
570 	crypto_ec_point_deinit(M, 1);
571 	crypto_ec_point_deinit(N, 1);
572 	crypto_ec_point_deinit(X, 1);
573 	crypto_ec_point_deinit(Y, 1);
574 	crypto_ec_deinit(ec);
575 	return pkex;
576 fail:
577 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
578 	dpp_pkex_free(pkex);
579 	pkex = NULL;
580 	goto out;
581 }
582 
583 
584 static struct wpabuf *
585 dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
586 				 const struct wpabuf *A_pub, const u8 *u)
587 {
588 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
589 	struct wpabuf *msg = NULL;
590 	size_t clear_len, attr_len;
591 	struct wpabuf *clear = NULL;
592 	u8 *wrapped;
593 	u8 octet;
594 	const u8 *addr[2];
595 	size_t len[2];
596 
597 	/* {A, u, [bootstrapping info]}z */
598 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
599 	clear = wpabuf_alloc(clear_len);
600 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
601 #ifdef CONFIG_TESTING_OPTIONS
602 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ)
603 		attr_len += 5;
604 #endif /* CONFIG_TESTING_OPTIONS */
605 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len);
606 	if (!clear || !msg)
607 		goto fail;
608 
609 #ifdef CONFIG_TESTING_OPTIONS
610 	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) {
611 		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
612 		goto skip_bootstrap_key;
613 	}
614 	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) {
615 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
616 		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
617 		wpabuf_put_le16(clear, 2 * curve->prime_len);
618 		if (dpp_test_gen_invalid_key(clear, curve) < 0)
619 			goto fail;
620 		goto skip_bootstrap_key;
621 	}
622 #endif /* CONFIG_TESTING_OPTIONS */
623 
624 	/* A in Bootstrap Key attribute */
625 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
626 	wpabuf_put_le16(clear, wpabuf_len(A_pub));
627 	wpabuf_put_buf(clear, A_pub);
628 
629 #ifdef CONFIG_TESTING_OPTIONS
630 skip_bootstrap_key:
631 	if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) {
632 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag");
633 		goto skip_i_auth_tag;
634 	}
635 	if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) {
636 		wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch");
637 		wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
638 		wpabuf_put_le16(clear, curve->hash_len);
639 		wpabuf_put_data(clear, u, curve->hash_len - 1);
640 		wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01);
641 		goto skip_i_auth_tag;
642 	}
643 #endif /* CONFIG_TESTING_OPTIONS */
644 
645 	/* u in I-Auth tag attribute */
646 	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
647 	wpabuf_put_le16(clear, curve->hash_len);
648 	wpabuf_put_data(clear, u, curve->hash_len);
649 
650 #ifdef CONFIG_TESTING_OPTIONS
651 skip_i_auth_tag:
652 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) {
653 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
654 		goto skip_wrapped_data;
655 	}
656 #endif /* CONFIG_TESTING_OPTIONS */
657 
658 	addr[0] = wpabuf_head_u8(msg) + 2;
659 	len[0] = DPP_HDR_LEN;
660 	octet = 0;
661 	addr[1] = &octet;
662 	len[1] = sizeof(octet);
663 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
664 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
665 
666 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
667 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
668 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
669 
670 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
671 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
672 			    wpabuf_head(clear), wpabuf_len(clear),
673 			    2, addr, len, wrapped) < 0)
674 		goto fail;
675 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
676 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
677 
678 #ifdef CONFIG_TESTING_OPTIONS
679 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) {
680 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
681 		dpp_build_attr_status(msg, DPP_STATUS_OK);
682 	}
683 skip_wrapped_data:
684 #endif /* CONFIG_TESTING_OPTIONS */
685 
686 out:
687 	wpabuf_free(clear);
688 	return msg;
689 
690 fail:
691 	wpabuf_free(msg);
692 	msg = NULL;
693 	goto out;
694 }
695 
696 
697 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
698 					  const u8 *peer_mac,
699 					  const u8 *buf, size_t buflen)
700 {
701 	const u8 *attr_status, *attr_id, *attr_key, *attr_group;
702 	u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
703 	struct crypto_ec *ec = NULL;
704 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
705 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
706 	struct crypto_ec_point *Qr = NULL, *Y = NULL, *N = NULL;
707 	u8 *x_coord = NULL, *y_coord = NULL;
708 	size_t Jx_len, Kx_len;
709 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
710 	const u8 *addr[4];
711 	size_t len[4];
712 	size_t num_elem;
713 	u8 u[DPP_MAX_HASH_LEN];
714 	int res;
715 
716 	if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
717 		return NULL;
718 
719 #ifdef CONFIG_TESTING_OPTIONS
720 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) {
721 		wpa_printf(MSG_INFO,
722 			   "DPP: TESTING - stop at PKEX Exchange Response");
723 		pkex->failed = 1;
724 		return NULL;
725 	}
726 
727 	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
728 		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
729 			   MAC2STR(dpp_pkex_peer_mac_override));
730 		peer_mac = dpp_pkex_peer_mac_override;
731 	}
732 #endif /* CONFIG_TESTING_OPTIONS */
733 
734 #ifdef CONFIG_DPP2
735 	if (pkex->v2) {
736 		const u8 *version;
737 		u16 version_len;
738 
739 		version = dpp_get_attr(buf, buflen, DPP_ATTR_PROTOCOL_VERSION,
740 				       &version_len);
741 		if (!version || version_len < 1 || version[0] == 0) {
742 		dpp_pkex_fail(pkex,
743 			      "Missing or invalid Protocol Version attribute");
744 			return NULL;
745 		}
746 		pkex->peer_version = version[0];
747 		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
748 			   pkex->peer_version);
749 	}
750 #endif /* CONFIG_DPP2 */
751 
752 	if (peer_mac)
753 		os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
754 
755 	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
756 				   &attr_status_len);
757 	if (!attr_status || attr_status_len != 1) {
758 		dpp_pkex_fail(pkex, "No DPP Status attribute");
759 		return NULL;
760 	}
761 	wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
762 
763 	if (attr_status[0] == DPP_STATUS_BAD_GROUP) {
764 		attr_group = dpp_get_attr(buf, buflen,
765 					  DPP_ATTR_FINITE_CYCLIC_GROUP,
766 					  &attr_group_len);
767 		if (attr_group && attr_group_len == 2) {
768 			wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
769 				"Peer indicated mismatching PKEX group - proposed %u",
770 				WPA_GET_LE16(attr_group));
771 			return NULL;
772 		}
773 	}
774 
775 	if (attr_status[0] != DPP_STATUS_OK) {
776 		dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)");
777 		return NULL;
778 	}
779 
780 	attr_id_len = 0;
781 	attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
782 			       &attr_id_len);
783 	if (!dpp_pkex_identifier_match(attr_id, attr_id_len,
784 				       pkex->identifier)) {
785 		dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
786 		return NULL;
787 	}
788 
789 	/* N in Encrypted Key attribute */
790 	attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
791 				&attr_key_len);
792 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
793 		dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
794 		return NULL;
795 	}
796 
797 	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
798 	Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
799 				pkex->code, pkex->code_len, pkex->identifier,
800 				&ec);
801 	if (!Qr)
802 		goto fail;
803 
804 	/* Y' = N - Qr */
805 	Y = crypto_ec_point_init(ec);
806 	N = crypto_ec_point_from_bin(ec, attr_key);
807 	if (!Y || !N ||
808 	    crypto_ec_point_is_at_infinity(ec, N) ||
809 	    !crypto_ec_point_is_on_curve(ec, N) ||
810 	    crypto_ec_point_invert(ec, Qr) ||
811 	    crypto_ec_point_add(ec, N, Qr, Y) ||
812 	    crypto_ec_point_is_at_infinity(ec, Y) ||
813 	    !crypto_ec_point_is_on_curve(ec, Y)) {
814 		dpp_pkex_fail(pkex, "Invalid Encrypted Key value");
815 		pkex->t++;
816 		goto fail;
817 	}
818 	crypto_ec_point_debug_print(ec, N, "DPP: N");
819 	crypto_ec_point_debug_print(ec, Y, "DPP: Y'");
820 
821 	pkex->exchange_done = 1;
822 
823 	/* ECDH: J = a * Y' */
824 	x_coord = os_malloc(curve->prime_len);
825 	y_coord = os_malloc(curve->prime_len);
826 	if (!x_coord || !y_coord ||
827 	    crypto_ec_point_to_bin(ec, Y, x_coord, y_coord))
828 		goto fail;
829 	pkex->y = crypto_ec_key_set_pub(curve->ike_group, x_coord, y_coord,
830 					curve->prime_len);
831 	if (!pkex->y)
832 		goto fail;
833 	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
834 		goto fail;
835 
836 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
837 			Jx, Jx_len);
838 
839 	/* u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x) */
840 	A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
841 	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
842 	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
843 	if (!A_pub || !Y_pub || !X_pub)
844 		goto fail;
845 	num_elem = 0;
846 	if (!pkex->v2) {
847 		addr[num_elem] = pkex->own_mac;
848 		len[num_elem] = ETH_ALEN;
849 		num_elem++;
850 	}
851 	addr[num_elem] = wpabuf_head(A_pub);
852 	len[num_elem] = wpabuf_len(A_pub) / 2;
853 	num_elem++;
854 	addr[num_elem] = wpabuf_head(Y_pub);
855 	len[num_elem] = wpabuf_len(Y_pub) / 2;
856 	num_elem++;
857 	addr[num_elem] = wpabuf_head(X_pub);
858 	len[num_elem] = wpabuf_len(X_pub) / 2;
859 	num_elem++;
860 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
861 	    < 0)
862 		goto fail;
863 	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
864 
865 	/* K = x * Y' */
866 	if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0)
867 		goto fail;
868 
869 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
870 			Kx, Kx_len);
871 
872 	/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
873 	res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac,
874 				pkex->v2 ? NULL : pkex->peer_mac,
875 				DPP_VERSION, pkex->peer_version,
876 				pkex->Mx, curve->prime_len,
877 				attr_key /* N.x */, attr_key_len / 2,
878 				pkex->code, pkex->code_len, Kx, Kx_len,
879 				pkex->z, curve->hash_len);
880 	os_memset(Kx, 0, Kx_len);
881 	if (res < 0)
882 		goto fail;
883 
884 	msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u);
885 	if (!msg)
886 		goto fail;
887 
888 out:
889 	wpabuf_free(A_pub);
890 	wpabuf_free(X_pub);
891 	wpabuf_free(Y_pub);
892 	os_free(x_coord);
893 	os_free(y_coord);
894 	crypto_ec_point_deinit(Qr, 1);
895 	crypto_ec_point_deinit(Y, 1);
896 	crypto_ec_point_deinit(N, 1);
897 	crypto_ec_deinit(ec);
898 	return msg;
899 fail:
900 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
901 	goto out;
902 }
903 
904 
905 static struct wpabuf *
906 dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex,
907 				  const struct wpabuf *B_pub, const u8 *v)
908 {
909 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
910 	struct wpabuf *msg = NULL;
911 	const u8 *addr[2];
912 	size_t len[2];
913 	u8 octet;
914 	u8 *wrapped;
915 	struct wpabuf *clear = NULL;
916 	size_t clear_len, attr_len;
917 
918 	/* {B, v [bootstrapping info]}z */
919 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
920 	clear = wpabuf_alloc(clear_len);
921 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
922 #ifdef CONFIG_TESTING_OPTIONS
923 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP)
924 		attr_len += 5;
925 #endif /* CONFIG_TESTING_OPTIONS */
926 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len);
927 	if (!clear || !msg)
928 		goto fail;
929 
930 #ifdef CONFIG_TESTING_OPTIONS
931 	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) {
932 		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
933 		goto skip_bootstrap_key;
934 	}
935 	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) {
936 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
937 		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
938 		wpabuf_put_le16(clear, 2 * curve->prime_len);
939 		if (dpp_test_gen_invalid_key(clear, curve) < 0)
940 			goto fail;
941 		goto skip_bootstrap_key;
942 	}
943 #endif /* CONFIG_TESTING_OPTIONS */
944 
945 	/* B in Bootstrap Key attribute */
946 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
947 	wpabuf_put_le16(clear, wpabuf_len(B_pub));
948 	wpabuf_put_buf(clear, B_pub);
949 
950 #ifdef CONFIG_TESTING_OPTIONS
951 skip_bootstrap_key:
952 	if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) {
953 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag");
954 		goto skip_r_auth_tag;
955 	}
956 	if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) {
957 		wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch");
958 		wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
959 		wpabuf_put_le16(clear, curve->hash_len);
960 		wpabuf_put_data(clear, v, curve->hash_len - 1);
961 		wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01);
962 		goto skip_r_auth_tag;
963 	}
964 #endif /* CONFIG_TESTING_OPTIONS */
965 
966 	/* v in R-Auth tag attribute */
967 	wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
968 	wpabuf_put_le16(clear, curve->hash_len);
969 	wpabuf_put_data(clear, v, curve->hash_len);
970 
971 #ifdef CONFIG_TESTING_OPTIONS
972 skip_r_auth_tag:
973 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) {
974 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
975 		goto skip_wrapped_data;
976 	}
977 #endif /* CONFIG_TESTING_OPTIONS */
978 
979 	addr[0] = wpabuf_head_u8(msg) + 2;
980 	len[0] = DPP_HDR_LEN;
981 	octet = 1;
982 	addr[1] = &octet;
983 	len[1] = sizeof(octet);
984 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
985 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
986 
987 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
988 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
989 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
990 
991 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
992 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
993 			    wpabuf_head(clear), wpabuf_len(clear),
994 			    2, addr, len, wrapped) < 0)
995 		goto fail;
996 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
997 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
998 
999 #ifdef CONFIG_TESTING_OPTIONS
1000 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) {
1001 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1002 		dpp_build_attr_status(msg, DPP_STATUS_OK);
1003 	}
1004 skip_wrapped_data:
1005 #endif /* CONFIG_TESTING_OPTIONS */
1006 
1007 out:
1008 	wpabuf_free(clear);
1009 	return msg;
1010 
1011 fail:
1012 	wpabuf_free(msg);
1013 	msg = NULL;
1014 	goto out;
1015 }
1016 
1017 
1018 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
1019 					      const u8 *hdr,
1020 					      const u8 *buf, size_t buflen)
1021 {
1022 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
1023 	size_t Jx_len, Lx_len;
1024 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
1025 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
1026 	const u8 *wrapped_data, *b_key, *peer_u;
1027 	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
1028 	const u8 *addr[4];
1029 	size_t len[4];
1030 	size_t num_elem;
1031 	u8 octet;
1032 	u8 *unwrapped = NULL;
1033 	size_t unwrapped_len = 0;
1034 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
1035 	struct wpabuf *B_pub = NULL;
1036 	u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
1037 
1038 #ifdef CONFIG_TESTING_OPTIONS
1039 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) {
1040 		wpa_printf(MSG_INFO,
1041 			   "DPP: TESTING - stop at PKEX CR Request");
1042 		pkex->failed = 1;
1043 		return NULL;
1044 	}
1045 #endif /* CONFIG_TESTING_OPTIONS */
1046 
1047 	if (!pkex->exchange_done || pkex->failed ||
1048 	    pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator)
1049 		goto fail;
1050 
1051 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
1052 				    &wrapped_data_len);
1053 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
1054 		dpp_pkex_fail(pkex,
1055 			      "Missing or invalid required Wrapped Data attribute");
1056 		goto fail;
1057 	}
1058 
1059 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1060 		    wrapped_data, wrapped_data_len);
1061 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1062 	unwrapped = os_malloc(unwrapped_len);
1063 	if (!unwrapped)
1064 		goto fail;
1065 
1066 	addr[0] = hdr;
1067 	len[0] = DPP_HDR_LEN;
1068 	octet = 0;
1069 	addr[1] = &octet;
1070 	len[1] = sizeof(octet);
1071 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1072 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1073 
1074 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
1075 			    wrapped_data, wrapped_data_len,
1076 			    2, addr, len, unwrapped) < 0) {
1077 		dpp_pkex_fail(pkex,
1078 			      "AES-SIV decryption failed - possible PKEX code mismatch");
1079 		pkex->failed = 1;
1080 		pkex->t++;
1081 		goto fail;
1082 	}
1083 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1084 		    unwrapped, unwrapped_len);
1085 
1086 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1087 		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
1088 		goto fail;
1089 	}
1090 
1091 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
1092 			     &b_key_len);
1093 	if (!b_key || b_key_len != 2 * curve->prime_len) {
1094 		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
1095 		goto fail;
1096 	}
1097 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
1098 							b_key_len);
1099 	if (!pkex->peer_bootstrap_key) {
1100 		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
1101 		goto fail;
1102 	}
1103 	dpp_debug_print_key("DPP: Peer bootstrap public key",
1104 			    pkex->peer_bootstrap_key);
1105 
1106 	/* ECDH: J' = y * A' */
1107 	if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0)
1108 		goto fail;
1109 
1110 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
1111 			Jx, Jx_len);
1112 
1113 	/* u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) */
1114 	A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
1115 	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
1116 	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
1117 	if (!A_pub || !Y_pub || !X_pub)
1118 		goto fail;
1119 	num_elem = 0;
1120 	if (!pkex->v2) {
1121 		addr[num_elem] = pkex->peer_mac;
1122 		len[num_elem] = ETH_ALEN;
1123 		num_elem++;
1124 	}
1125 	addr[num_elem] = wpabuf_head(A_pub);
1126 	len[num_elem] = wpabuf_len(A_pub) / 2;
1127 	num_elem++;
1128 	addr[num_elem] = wpabuf_head(Y_pub);
1129 	len[num_elem] = wpabuf_len(Y_pub) / 2;
1130 	num_elem++;
1131 	addr[num_elem] = wpabuf_head(X_pub);
1132 	len[num_elem] = wpabuf_len(X_pub) / 2;
1133 	num_elem++;
1134 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
1135 	    < 0)
1136 		goto fail;
1137 
1138 	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
1139 			      &peer_u_len);
1140 	if (!peer_u || peer_u_len != curve->hash_len ||
1141 	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
1142 		dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found");
1143 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
1144 			    u, curve->hash_len);
1145 		wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
1146 		pkex->t++;
1147 		goto fail;
1148 	}
1149 	wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
1150 
1151 	/* ECDH: L = b * X' */
1152 	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0)
1153 		goto fail;
1154 
1155 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
1156 			Lx, Lx_len);
1157 
1158 	/* v = HMAC(L.x, [MAC-Responder |] B.x | X'.x | Y.x) */
1159 	B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
1160 	if (!B_pub)
1161 		goto fail;
1162 	num_elem = 0;
1163 	if (!pkex->v2) {
1164 		addr[num_elem] = pkex->own_mac;
1165 		len[num_elem] = ETH_ALEN;
1166 		num_elem++;
1167 	}
1168 	addr[num_elem] = wpabuf_head(B_pub);
1169 	len[num_elem] = wpabuf_len(B_pub) / 2;
1170 	num_elem++;
1171 	addr[num_elem] = wpabuf_head(X_pub);
1172 	len[num_elem] = wpabuf_len(X_pub) / 2;
1173 	num_elem++;
1174 	addr[num_elem] = wpabuf_head(Y_pub);
1175 	len[num_elem] = wpabuf_len(Y_pub) / 2;
1176 	num_elem++;
1177 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
1178 	    < 0)
1179 		goto fail;
1180 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
1181 
1182 	msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v);
1183 	if (!msg)
1184 		goto fail;
1185 
1186 out:
1187 	os_free(unwrapped);
1188 	wpabuf_free(A_pub);
1189 	wpabuf_free(B_pub);
1190 	wpabuf_free(X_pub);
1191 	wpabuf_free(Y_pub);
1192 	return msg;
1193 fail:
1194 	wpa_printf(MSG_DEBUG,
1195 		   "DPP: PKEX Commit-Reveal Request processing failed");
1196 	goto out;
1197 }
1198 
1199 
1200 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
1201 				   const u8 *buf, size_t buflen)
1202 {
1203 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
1204 	const u8 *wrapped_data, *b_key, *peer_v;
1205 	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
1206 	const u8 *addr[4];
1207 	size_t len[4];
1208 	size_t num_elem;
1209 	u8 octet;
1210 	u8 *unwrapped = NULL;
1211 	size_t unwrapped_len = 0;
1212 	int ret = -1;
1213 	u8 v[DPP_MAX_HASH_LEN];
1214 	size_t Lx_len;
1215 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
1216 	struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
1217 
1218 #ifdef CONFIG_TESTING_OPTIONS
1219 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) {
1220 		wpa_printf(MSG_INFO,
1221 			   "DPP: TESTING - stop at PKEX CR Response");
1222 		pkex->failed = 1;
1223 		goto fail;
1224 	}
1225 #endif /* CONFIG_TESTING_OPTIONS */
1226 
1227 	if (!pkex->exchange_done || pkex->failed ||
1228 	    pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
1229 		goto fail;
1230 
1231 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
1232 				    &wrapped_data_len);
1233 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
1234 		dpp_pkex_fail(pkex,
1235 			      "Missing or invalid required Wrapped Data attribute");
1236 		goto fail;
1237 	}
1238 
1239 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1240 		    wrapped_data, wrapped_data_len);
1241 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1242 	unwrapped = os_malloc(unwrapped_len);
1243 	if (!unwrapped)
1244 		goto fail;
1245 
1246 	addr[0] = hdr;
1247 	len[0] = DPP_HDR_LEN;
1248 	octet = 1;
1249 	addr[1] = &octet;
1250 	len[1] = sizeof(octet);
1251 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1252 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1253 
1254 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
1255 			    wrapped_data, wrapped_data_len,
1256 			    2, addr, len, unwrapped) < 0) {
1257 		dpp_pkex_fail(pkex,
1258 			      "AES-SIV decryption failed - possible PKEX code mismatch");
1259 		pkex->t++;
1260 		goto fail;
1261 	}
1262 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1263 		    unwrapped, unwrapped_len);
1264 
1265 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1266 		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
1267 		goto fail;
1268 	}
1269 
1270 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
1271 			     &b_key_len);
1272 	if (!b_key || b_key_len != 2 * curve->prime_len) {
1273 		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
1274 		goto fail;
1275 	}
1276 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
1277 							b_key_len);
1278 	if (!pkex->peer_bootstrap_key) {
1279 		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
1280 		goto fail;
1281 	}
1282 	dpp_debug_print_key("DPP: Peer bootstrap public key",
1283 			    pkex->peer_bootstrap_key);
1284 
1285 	/* ECDH: L' = x * B' */
1286 	if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0)
1287 		goto fail;
1288 
1289 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
1290 			Lx, Lx_len);
1291 
1292 	/* v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x) */
1293 	B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
1294 	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
1295 	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
1296 	if (!B_pub || !X_pub || !Y_pub)
1297 		goto fail;
1298 	num_elem = 0;
1299 	if (!pkex->v2) {
1300 		addr[num_elem] = pkex->peer_mac;
1301 		len[num_elem] = ETH_ALEN;
1302 		num_elem++;
1303 	}
1304 	addr[num_elem] = wpabuf_head(B_pub);
1305 	len[num_elem] = wpabuf_len(B_pub) / 2;
1306 	num_elem++;
1307 	addr[num_elem] = wpabuf_head(X_pub);
1308 	len[num_elem] = wpabuf_len(X_pub) / 2;
1309 	num_elem++;
1310 	addr[num_elem] = wpabuf_head(Y_pub);
1311 	len[num_elem] = wpabuf_len(Y_pub) / 2;
1312 	num_elem++;
1313 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
1314 	    < 0)
1315 		goto fail;
1316 
1317 	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
1318 			      &peer_v_len);
1319 	if (!peer_v || peer_v_len != curve->hash_len ||
1320 	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
1321 		dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found");
1322 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
1323 			    v, curve->hash_len);
1324 		wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
1325 		pkex->t++;
1326 		goto fail;
1327 	}
1328 	wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
1329 
1330 	ret = 0;
1331 out:
1332 	wpabuf_free(B_pub);
1333 	wpabuf_free(X_pub);
1334 	wpabuf_free(Y_pub);
1335 	os_free(unwrapped);
1336 	return ret;
1337 fail:
1338 	goto out;
1339 }
1340 
1341 
1342 struct dpp_bootstrap_info *
1343 dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
1344 		unsigned int freq)
1345 {
1346 	struct dpp_bootstrap_info *bi;
1347 
1348 	bi = os_zalloc(sizeof(*bi));
1349 	if (!bi)
1350 		return NULL;
1351 	bi->id = dpp_next_id(dpp);
1352 	bi->type = DPP_BOOTSTRAP_PKEX;
1353 	if (peer)
1354 		os_memcpy(bi->mac_addr, peer, ETH_ALEN);
1355 	if (freq) {
1356 		bi->num_freq = 1;
1357 		bi->freq[0] = freq;
1358 	}
1359 	bi->curve = pkex->own_bi->curve;
1360 	bi->pubkey = pkex->peer_bootstrap_key;
1361 	pkex->peer_bootstrap_key = NULL;
1362 	if (dpp_bootstrap_key_hash(bi) < 0) {
1363 		dpp_bootstrap_info_free(bi);
1364 		return NULL;
1365 	}
1366 	os_memcpy(pkex->own_bi->peer_pubkey_hash, bi->pubkey_hash,
1367 		  SHA256_MAC_LEN);
1368 	dpp_pkex_free(pkex);
1369 	dl_list_add(&dpp->bootstrap, &bi->list);
1370 	return bi;
1371 }
1372 
1373 
1374 void dpp_pkex_free(struct dpp_pkex *pkex)
1375 {
1376 	if (!pkex)
1377 		return;
1378 
1379 	os_free(pkex->identifier);
1380 	os_free(pkex->code);
1381 	crypto_ec_key_deinit(pkex->x);
1382 	crypto_ec_key_deinit(pkex->y);
1383 	crypto_ec_key_deinit(pkex->peer_bootstrap_key);
1384 	wpabuf_free(pkex->exchange_req);
1385 	wpabuf_free(pkex->exchange_resp);
1386 	wpabuf_free(pkex->enc_key);
1387 	os_free(pkex);
1388 }
1389