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