Home | History | Annotate | Line # | Download | only in common
      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