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