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 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 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 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 * 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 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 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 os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); 473 os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); 474 if (identifier) { 475 pkex->identifier = os_strdup(identifier); 476 if (!pkex->identifier) 477 goto fail; 478 } 479 pkex->code = os_strdup(code); 480 if (!pkex->code) 481 goto fail; 482 483 os_memcpy(pkex->Mx, attr_key, attr_key_len / 2); 484 485 x_coord = os_malloc(curve->prime_len); 486 y_coord = os_malloc(curve->prime_len); 487 if (!x_coord || !y_coord || 488 crypto_ec_point_to_bin(ec, X, x_coord, y_coord)) 489 goto fail; 490 491 pkex->x = crypto_ec_key_set_pub(curve->ike_group, x_coord, 492 y_coord, crypto_ec_prime_len(ec)); 493 if (!pkex->x) 494 goto fail; 495 496 /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */ 497 Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier, 498 NULL); 499 if (!Qr) 500 goto fail; 501 502 /* Generate a random ephemeral keypair y/Y */ 503 #ifdef CONFIG_TESTING_OPTIONS 504 if (dpp_pkex_ephemeral_key_override_len) { 505 const struct dpp_curve_params *tmp_curve; 506 507 wpa_printf(MSG_INFO, 508 "DPP: TESTING - override ephemeral key y/Y"); 509 pkex->y = dpp_set_keypair(&tmp_curve, 510 dpp_pkex_ephemeral_key_override, 511 dpp_pkex_ephemeral_key_override_len); 512 } else { 513 pkex->y = dpp_gen_keypair(curve); 514 } 515 #else /* CONFIG_TESTING_OPTIONS */ 516 pkex->y = dpp_gen_keypair(curve); 517 #endif /* CONFIG_TESTING_OPTIONS */ 518 if (!pkex->y) 519 goto fail; 520 521 /* N = Y + Qr */ 522 Y = crypto_ec_key_get_public_key(pkex->y); 523 if (!Y) 524 goto fail; 525 crypto_ec_point_debug_print(ec, Y, "DPP: Y"); 526 527 N = crypto_ec_point_init(ec); 528 if (!N || 529 crypto_ec_point_add(ec, Y, Qr, N) || 530 crypto_ec_point_to_bin(ec, N, x_coord, y_coord)) 531 goto fail; 532 crypto_ec_point_debug_print(ec, N, "DPP: N"); 533 534 pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK, 535 x_coord, y_coord); 536 if (!pkex->exchange_resp) 537 goto fail; 538 539 /* K = y * X' */ 540 if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0) 541 goto fail; 542 543 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", 544 Kx, Kx_len); 545 546 /* z = HKDF(<>, info | M.x | N.x | code, K.x) */ 547 res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac, 548 pkex->v2 ? NULL : pkex->own_mac, 549 pkex->peer_version, DPP_VERSION, 550 pkex->Mx, curve->prime_len, 551 pkex->Nx, curve->prime_len, pkex->code, 552 Kx, Kx_len, pkex->z, curve->hash_len); 553 os_memset(Kx, 0, Kx_len); 554 if (res < 0) 555 goto fail; 556 557 pkex->exchange_done = 1; 558 559 out: 560 os_free(x_coord); 561 os_free(y_coord); 562 crypto_ec_point_deinit(Qi, 1); 563 crypto_ec_point_deinit(Qr, 1); 564 crypto_ec_point_deinit(M, 1); 565 crypto_ec_point_deinit(N, 1); 566 crypto_ec_point_deinit(X, 1); 567 crypto_ec_deinit(ec); 568 return pkex; 569 fail: 570 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed"); 571 dpp_pkex_free(pkex); 572 pkex = NULL; 573 goto out; 574 } 575 576 577 static struct wpabuf * 578 dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, 579 const struct wpabuf *A_pub, const u8 *u) 580 { 581 const struct dpp_curve_params *curve = pkex->own_bi->curve; 582 struct wpabuf *msg = NULL; 583 size_t clear_len, attr_len; 584 struct wpabuf *clear = NULL; 585 u8 *wrapped; 586 u8 octet; 587 const u8 *addr[2]; 588 size_t len[2]; 589 590 /* {A, u, [bootstrapping info]}z */ 591 clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; 592 clear = wpabuf_alloc(clear_len); 593 attr_len = 4 + clear_len + AES_BLOCK_SIZE; 594 #ifdef CONFIG_TESTING_OPTIONS 595 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) 596 attr_len += 5; 597 #endif /* CONFIG_TESTING_OPTIONS */ 598 msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len); 599 if (!clear || !msg) 600 goto fail; 601 602 #ifdef CONFIG_TESTING_OPTIONS 603 if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) { 604 wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); 605 goto skip_bootstrap_key; 606 } 607 if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) { 608 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); 609 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); 610 wpabuf_put_le16(clear, 2 * curve->prime_len); 611 if (dpp_test_gen_invalid_key(clear, curve) < 0) 612 goto fail; 613 goto skip_bootstrap_key; 614 } 615 #endif /* CONFIG_TESTING_OPTIONS */ 616 617 /* A in Bootstrap Key attribute */ 618 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); 619 wpabuf_put_le16(clear, wpabuf_len(A_pub)); 620 wpabuf_put_buf(clear, A_pub); 621 622 #ifdef CONFIG_TESTING_OPTIONS 623 skip_bootstrap_key: 624 if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) { 625 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag"); 626 goto skip_i_auth_tag; 627 } 628 if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) { 629 wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch"); 630 wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); 631 wpabuf_put_le16(clear, curve->hash_len); 632 wpabuf_put_data(clear, u, curve->hash_len - 1); 633 wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01); 634 goto skip_i_auth_tag; 635 } 636 #endif /* CONFIG_TESTING_OPTIONS */ 637 638 /* u in I-Auth tag attribute */ 639 wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); 640 wpabuf_put_le16(clear, curve->hash_len); 641 wpabuf_put_data(clear, u, curve->hash_len); 642 643 #ifdef CONFIG_TESTING_OPTIONS 644 skip_i_auth_tag: 645 if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) { 646 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); 647 goto skip_wrapped_data; 648 } 649 #endif /* CONFIG_TESTING_OPTIONS */ 650 651 addr[0] = wpabuf_head_u8(msg) + 2; 652 len[0] = DPP_HDR_LEN; 653 octet = 0; 654 addr[1] = &octet; 655 len[1] = sizeof(octet); 656 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 657 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 658 659 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 660 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 661 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 662 663 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 664 if (aes_siv_encrypt(pkex->z, curve->hash_len, 665 wpabuf_head(clear), wpabuf_len(clear), 666 2, addr, len, wrapped) < 0) 667 goto fail; 668 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 669 wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); 670 671 #ifdef CONFIG_TESTING_OPTIONS 672 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) { 673 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); 674 dpp_build_attr_status(msg, DPP_STATUS_OK); 675 } 676 skip_wrapped_data: 677 #endif /* CONFIG_TESTING_OPTIONS */ 678 679 out: 680 wpabuf_free(clear); 681 return msg; 682 683 fail: 684 wpabuf_free(msg); 685 msg = NULL; 686 goto out; 687 } 688 689 690 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, 691 const u8 *peer_mac, 692 const u8 *buf, size_t buflen) 693 { 694 const u8 *attr_status, *attr_id, *attr_key, *attr_group; 695 u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len; 696 struct crypto_ec *ec = NULL; 697 struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; 698 const struct dpp_curve_params *curve = pkex->own_bi->curve; 699 struct crypto_ec_point *Qr = NULL, *Y = NULL, *N = NULL; 700 u8 *x_coord = NULL, *y_coord = NULL; 701 size_t Jx_len, Kx_len; 702 u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; 703 const u8 *addr[4]; 704 size_t len[4]; 705 size_t num_elem; 706 u8 u[DPP_MAX_HASH_LEN]; 707 int res; 708 709 if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) 710 return NULL; 711 712 #ifdef CONFIG_TESTING_OPTIONS 713 if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) { 714 wpa_printf(MSG_INFO, 715 "DPP: TESTING - stop at PKEX Exchange Response"); 716 pkex->failed = 1; 717 return NULL; 718 } 719 720 if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { 721 wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, 722 MAC2STR(dpp_pkex_peer_mac_override)); 723 peer_mac = dpp_pkex_peer_mac_override; 724 } 725 #endif /* CONFIG_TESTING_OPTIONS */ 726 727 #ifdef CONFIG_DPP2 728 if (pkex->v2) { 729 const u8 *version; 730 u16 version_len; 731 732 version = dpp_get_attr(buf, buflen, DPP_ATTR_PROTOCOL_VERSION, 733 &version_len); 734 if (!version || version_len < 1 || version[0] == 0) { 735 dpp_pkex_fail(pkex, 736 "Missing or invalid Protocol Version attribute"); 737 return NULL; 738 } 739 pkex->peer_version = version[0]; 740 wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", 741 pkex->peer_version); 742 } 743 #endif /* CONFIG_DPP2 */ 744 745 os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); 746 747 attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, 748 &attr_status_len); 749 if (!attr_status || attr_status_len != 1) { 750 dpp_pkex_fail(pkex, "No DPP Status attribute"); 751 return NULL; 752 } 753 wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]); 754 755 if (attr_status[0] == DPP_STATUS_BAD_GROUP) { 756 attr_group = dpp_get_attr(buf, buflen, 757 DPP_ATTR_FINITE_CYCLIC_GROUP, 758 &attr_group_len); 759 if (attr_group && attr_group_len == 2) { 760 wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL 761 "Peer indicated mismatching PKEX group - proposed %u", 762 WPA_GET_LE16(attr_group)); 763 return NULL; 764 } 765 } 766 767 if (attr_status[0] != DPP_STATUS_OK) { 768 dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)"); 769 return NULL; 770 } 771 772 attr_id_len = 0; 773 attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER, 774 &attr_id_len); 775 if (!dpp_pkex_identifier_match(attr_id, attr_id_len, 776 pkex->identifier)) { 777 dpp_pkex_fail(pkex, "PKEX code identifier mismatch"); 778 return NULL; 779 } 780 781 /* N in Encrypted Key attribute */ 782 attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY, 783 &attr_key_len); 784 if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) { 785 dpp_pkex_fail(pkex, "Missing Encrypted Key attribute"); 786 return NULL; 787 } 788 789 /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */ 790 Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac, 791 pkex->code, pkex->identifier, &ec); 792 if (!Qr) 793 goto fail; 794 795 /* Y' = N - Qr */ 796 Y = crypto_ec_point_init(ec); 797 N = crypto_ec_point_from_bin(ec, attr_key); 798 if (!Y || !N || 799 crypto_ec_point_is_at_infinity(ec, N) || 800 !crypto_ec_point_is_on_curve(ec, N) || 801 crypto_ec_point_invert(ec, Qr) || 802 crypto_ec_point_add(ec, N, Qr, Y) || 803 crypto_ec_point_is_at_infinity(ec, Y) || 804 !crypto_ec_point_is_on_curve(ec, Y)) { 805 dpp_pkex_fail(pkex, "Invalid Encrypted Key value"); 806 pkex->t++; 807 goto fail; 808 } 809 crypto_ec_point_debug_print(ec, N, "DPP: N"); 810 crypto_ec_point_debug_print(ec, Y, "DPP: Y'"); 811 812 pkex->exchange_done = 1; 813 814 /* ECDH: J = a * Y' */ 815 x_coord = os_malloc(curve->prime_len); 816 y_coord = os_malloc(curve->prime_len); 817 if (!x_coord || !y_coord || 818 crypto_ec_point_to_bin(ec, Y, x_coord, y_coord)) 819 goto fail; 820 pkex->y = crypto_ec_key_set_pub(curve->ike_group, x_coord, y_coord, 821 curve->prime_len); 822 if (!pkex->y) 823 goto fail; 824 if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0) 825 goto fail; 826 827 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", 828 Jx, Jx_len); 829 830 /* u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x) */ 831 A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0); 832 Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0); 833 X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0); 834 if (!A_pub || !Y_pub || !X_pub) 835 goto fail; 836 num_elem = 0; 837 if (!pkex->v2) { 838 addr[num_elem] = pkex->own_mac; 839 len[num_elem] = ETH_ALEN; 840 num_elem++; 841 } 842 addr[num_elem] = wpabuf_head(A_pub); 843 len[num_elem] = wpabuf_len(A_pub) / 2; 844 num_elem++; 845 addr[num_elem] = wpabuf_head(Y_pub); 846 len[num_elem] = wpabuf_len(Y_pub) / 2; 847 num_elem++; 848 addr[num_elem] = wpabuf_head(X_pub); 849 len[num_elem] = wpabuf_len(X_pub) / 2; 850 num_elem++; 851 if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u) 852 < 0) 853 goto fail; 854 wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len); 855 856 /* K = x * Y' */ 857 if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0) 858 goto fail; 859 860 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", 861 Kx, Kx_len); 862 863 /* z = HKDF(<>, info | M.x | N.x | code, K.x) */ 864 res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac, 865 pkex->v2 ? NULL : pkex->peer_mac, 866 DPP_VERSION, pkex->peer_version, 867 pkex->Mx, curve->prime_len, 868 attr_key /* N.x */, attr_key_len / 2, 869 pkex->code, Kx, Kx_len, 870 pkex->z, curve->hash_len); 871 os_memset(Kx, 0, Kx_len); 872 if (res < 0) 873 goto fail; 874 875 msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u); 876 if (!msg) 877 goto fail; 878 879 out: 880 wpabuf_free(A_pub); 881 wpabuf_free(X_pub); 882 wpabuf_free(Y_pub); 883 os_free(x_coord); 884 os_free(y_coord); 885 crypto_ec_point_deinit(Qr, 1); 886 crypto_ec_point_deinit(Y, 1); 887 crypto_ec_point_deinit(N, 1); 888 crypto_ec_deinit(ec); 889 return msg; 890 fail: 891 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed"); 892 goto out; 893 } 894 895 896 static struct wpabuf * 897 dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex, 898 const struct wpabuf *B_pub, const u8 *v) 899 { 900 const struct dpp_curve_params *curve = pkex->own_bi->curve; 901 struct wpabuf *msg = NULL; 902 const u8 *addr[2]; 903 size_t len[2]; 904 u8 octet; 905 u8 *wrapped; 906 struct wpabuf *clear = NULL; 907 size_t clear_len, attr_len; 908 909 /* {B, v [bootstrapping info]}z */ 910 clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; 911 clear = wpabuf_alloc(clear_len); 912 attr_len = 4 + clear_len + AES_BLOCK_SIZE; 913 #ifdef CONFIG_TESTING_OPTIONS 914 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) 915 attr_len += 5; 916 #endif /* CONFIG_TESTING_OPTIONS */ 917 msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len); 918 if (!clear || !msg) 919 goto fail; 920 921 #ifdef CONFIG_TESTING_OPTIONS 922 if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) { 923 wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); 924 goto skip_bootstrap_key; 925 } 926 if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) { 927 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); 928 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); 929 wpabuf_put_le16(clear, 2 * curve->prime_len); 930 if (dpp_test_gen_invalid_key(clear, curve) < 0) 931 goto fail; 932 goto skip_bootstrap_key; 933 } 934 #endif /* CONFIG_TESTING_OPTIONS */ 935 936 /* B in Bootstrap Key attribute */ 937 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); 938 wpabuf_put_le16(clear, wpabuf_len(B_pub)); 939 wpabuf_put_buf(clear, B_pub); 940 941 #ifdef CONFIG_TESTING_OPTIONS 942 skip_bootstrap_key: 943 if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) { 944 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag"); 945 goto skip_r_auth_tag; 946 } 947 if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) { 948 wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch"); 949 wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); 950 wpabuf_put_le16(clear, curve->hash_len); 951 wpabuf_put_data(clear, v, curve->hash_len - 1); 952 wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01); 953 goto skip_r_auth_tag; 954 } 955 #endif /* CONFIG_TESTING_OPTIONS */ 956 957 /* v in R-Auth tag attribute */ 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); 961 962 #ifdef CONFIG_TESTING_OPTIONS 963 skip_r_auth_tag: 964 if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) { 965 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); 966 goto skip_wrapped_data; 967 } 968 #endif /* CONFIG_TESTING_OPTIONS */ 969 970 addr[0] = wpabuf_head_u8(msg) + 2; 971 len[0] = DPP_HDR_LEN; 972 octet = 1; 973 addr[1] = &octet; 974 len[1] = sizeof(octet); 975 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 976 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 977 978 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 979 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 980 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 981 982 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 983 if (aes_siv_encrypt(pkex->z, curve->hash_len, 984 wpabuf_head(clear), wpabuf_len(clear), 985 2, addr, len, wrapped) < 0) 986 goto fail; 987 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 988 wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); 989 990 #ifdef CONFIG_TESTING_OPTIONS 991 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) { 992 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); 993 dpp_build_attr_status(msg, DPP_STATUS_OK); 994 } 995 skip_wrapped_data: 996 #endif /* CONFIG_TESTING_OPTIONS */ 997 998 out: 999 wpabuf_free(clear); 1000 return msg; 1001 1002 fail: 1003 wpabuf_free(msg); 1004 msg = NULL; 1005 goto out; 1006 } 1007 1008 1009 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, 1010 const u8 *hdr, 1011 const u8 *buf, size_t buflen) 1012 { 1013 const struct dpp_curve_params *curve = pkex->own_bi->curve; 1014 size_t Jx_len, Lx_len; 1015 u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; 1016 u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; 1017 const u8 *wrapped_data, *b_key, *peer_u; 1018 u16 wrapped_data_len, b_key_len, peer_u_len = 0; 1019 const u8 *addr[4]; 1020 size_t len[4]; 1021 size_t num_elem; 1022 u8 octet; 1023 u8 *unwrapped = NULL; 1024 size_t unwrapped_len = 0; 1025 struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; 1026 struct wpabuf *B_pub = NULL; 1027 u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; 1028 1029 #ifdef CONFIG_TESTING_OPTIONS 1030 if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) { 1031 wpa_printf(MSG_INFO, 1032 "DPP: TESTING - stop at PKEX CR Request"); 1033 pkex->failed = 1; 1034 return NULL; 1035 } 1036 #endif /* CONFIG_TESTING_OPTIONS */ 1037 1038 if (!pkex->exchange_done || pkex->failed || 1039 pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator) 1040 goto fail; 1041 1042 wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, 1043 &wrapped_data_len); 1044 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 1045 dpp_pkex_fail(pkex, 1046 "Missing or invalid required Wrapped Data attribute"); 1047 goto fail; 1048 } 1049 1050 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 1051 wrapped_data, wrapped_data_len); 1052 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 1053 unwrapped = os_malloc(unwrapped_len); 1054 if (!unwrapped) 1055 goto fail; 1056 1057 addr[0] = hdr; 1058 len[0] = DPP_HDR_LEN; 1059 octet = 0; 1060 addr[1] = &octet; 1061 len[1] = sizeof(octet); 1062 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 1063 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 1064 1065 if (aes_siv_decrypt(pkex->z, curve->hash_len, 1066 wrapped_data, wrapped_data_len, 1067 2, addr, len, unwrapped) < 0) { 1068 dpp_pkex_fail(pkex, 1069 "AES-SIV decryption failed - possible PKEX code mismatch"); 1070 pkex->failed = 1; 1071 pkex->t++; 1072 goto fail; 1073 } 1074 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 1075 unwrapped, unwrapped_len); 1076 1077 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 1078 dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); 1079 goto fail; 1080 } 1081 1082 b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, 1083 &b_key_len); 1084 if (!b_key || b_key_len != 2 * curve->prime_len) { 1085 dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); 1086 goto fail; 1087 } 1088 pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, 1089 b_key_len); 1090 if (!pkex->peer_bootstrap_key) { 1091 dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); 1092 goto fail; 1093 } 1094 dpp_debug_print_key("DPP: Peer bootstrap public key", 1095 pkex->peer_bootstrap_key); 1096 1097 /* ECDH: J' = y * A' */ 1098 if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0) 1099 goto fail; 1100 1101 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", 1102 Jx, Jx_len); 1103 1104 /* u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) */ 1105 A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0); 1106 Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0); 1107 X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0); 1108 if (!A_pub || !Y_pub || !X_pub) 1109 goto fail; 1110 num_elem = 0; 1111 if (!pkex->v2) { 1112 addr[num_elem] = pkex->peer_mac; 1113 len[num_elem] = ETH_ALEN; 1114 num_elem++; 1115 } 1116 addr[num_elem] = wpabuf_head(A_pub); 1117 len[num_elem] = wpabuf_len(A_pub) / 2; 1118 num_elem++; 1119 addr[num_elem] = wpabuf_head(Y_pub); 1120 len[num_elem] = wpabuf_len(Y_pub) / 2; 1121 num_elem++; 1122 addr[num_elem] = wpabuf_head(X_pub); 1123 len[num_elem] = wpabuf_len(X_pub) / 2; 1124 num_elem++; 1125 if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u) 1126 < 0) 1127 goto fail; 1128 1129 peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, 1130 &peer_u_len); 1131 if (!peer_u || peer_u_len != curve->hash_len || 1132 os_memcmp(peer_u, u, curve->hash_len) != 0) { 1133 dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found"); 1134 wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'", 1135 u, curve->hash_len); 1136 wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len); 1137 pkex->t++; 1138 goto fail; 1139 } 1140 wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received"); 1141 1142 /* ECDH: L = b * X' */ 1143 if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0) 1144 goto fail; 1145 1146 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", 1147 Lx, Lx_len); 1148 1149 /* v = HMAC(L.x, [MAC-Responder |] B.x | X'.x | Y.x) */ 1150 B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0); 1151 if (!B_pub) 1152 goto fail; 1153 num_elem = 0; 1154 if (!pkex->v2) { 1155 addr[num_elem] = pkex->own_mac; 1156 len[num_elem] = ETH_ALEN; 1157 num_elem++; 1158 } 1159 addr[num_elem] = wpabuf_head(B_pub); 1160 len[num_elem] = wpabuf_len(B_pub) / 2; 1161 num_elem++; 1162 addr[num_elem] = wpabuf_head(X_pub); 1163 len[num_elem] = wpabuf_len(X_pub) / 2; 1164 num_elem++; 1165 addr[num_elem] = wpabuf_head(Y_pub); 1166 len[num_elem] = wpabuf_len(Y_pub) / 2; 1167 num_elem++; 1168 if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v) 1169 < 0) 1170 goto fail; 1171 wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len); 1172 1173 msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v); 1174 if (!msg) 1175 goto fail; 1176 1177 out: 1178 os_free(unwrapped); 1179 wpabuf_free(A_pub); 1180 wpabuf_free(B_pub); 1181 wpabuf_free(X_pub); 1182 wpabuf_free(Y_pub); 1183 return msg; 1184 fail: 1185 wpa_printf(MSG_DEBUG, 1186 "DPP: PKEX Commit-Reveal Request processing failed"); 1187 goto out; 1188 } 1189 1190 1191 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, 1192 const u8 *buf, size_t buflen) 1193 { 1194 const struct dpp_curve_params *curve = pkex->own_bi->curve; 1195 const u8 *wrapped_data, *b_key, *peer_v; 1196 u16 wrapped_data_len, b_key_len, peer_v_len = 0; 1197 const u8 *addr[4]; 1198 size_t len[4]; 1199 size_t num_elem; 1200 u8 octet; 1201 u8 *unwrapped = NULL; 1202 size_t unwrapped_len = 0; 1203 int ret = -1; 1204 u8 v[DPP_MAX_HASH_LEN]; 1205 size_t Lx_len; 1206 u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; 1207 struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL; 1208 1209 #ifdef CONFIG_TESTING_OPTIONS 1210 if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) { 1211 wpa_printf(MSG_INFO, 1212 "DPP: TESTING - stop at PKEX CR Response"); 1213 pkex->failed = 1; 1214 goto fail; 1215 } 1216 #endif /* CONFIG_TESTING_OPTIONS */ 1217 1218 if (!pkex->exchange_done || pkex->failed || 1219 pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) 1220 goto fail; 1221 1222 wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, 1223 &wrapped_data_len); 1224 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 1225 dpp_pkex_fail(pkex, 1226 "Missing or invalid required Wrapped Data attribute"); 1227 goto fail; 1228 } 1229 1230 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 1231 wrapped_data, wrapped_data_len); 1232 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 1233 unwrapped = os_malloc(unwrapped_len); 1234 if (!unwrapped) 1235 goto fail; 1236 1237 addr[0] = hdr; 1238 len[0] = DPP_HDR_LEN; 1239 octet = 1; 1240 addr[1] = &octet; 1241 len[1] = sizeof(octet); 1242 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 1243 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 1244 1245 if (aes_siv_decrypt(pkex->z, curve->hash_len, 1246 wrapped_data, wrapped_data_len, 1247 2, addr, len, unwrapped) < 0) { 1248 dpp_pkex_fail(pkex, 1249 "AES-SIV decryption failed - possible PKEX code mismatch"); 1250 pkex->t++; 1251 goto fail; 1252 } 1253 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 1254 unwrapped, unwrapped_len); 1255 1256 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 1257 dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); 1258 goto fail; 1259 } 1260 1261 b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, 1262 &b_key_len); 1263 if (!b_key || b_key_len != 2 * curve->prime_len) { 1264 dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); 1265 goto fail; 1266 } 1267 pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, 1268 b_key_len); 1269 if (!pkex->peer_bootstrap_key) { 1270 dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); 1271 goto fail; 1272 } 1273 dpp_debug_print_key("DPP: Peer bootstrap public key", 1274 pkex->peer_bootstrap_key); 1275 1276 /* ECDH: L' = x * B' */ 1277 if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0) 1278 goto fail; 1279 1280 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", 1281 Lx, Lx_len); 1282 1283 /* v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x) */ 1284 B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0); 1285 X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0); 1286 Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0); 1287 if (!B_pub || !X_pub || !Y_pub) 1288 goto fail; 1289 num_elem = 0; 1290 if (!pkex->v2) { 1291 addr[num_elem] = pkex->peer_mac; 1292 len[num_elem] = ETH_ALEN; 1293 num_elem++; 1294 } 1295 addr[num_elem] = wpabuf_head(B_pub); 1296 len[num_elem] = wpabuf_len(B_pub) / 2; 1297 num_elem++; 1298 addr[num_elem] = wpabuf_head(X_pub); 1299 len[num_elem] = wpabuf_len(X_pub) / 2; 1300 num_elem++; 1301 addr[num_elem] = wpabuf_head(Y_pub); 1302 len[num_elem] = wpabuf_len(Y_pub) / 2; 1303 num_elem++; 1304 if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v) 1305 < 0) 1306 goto fail; 1307 1308 peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG, 1309 &peer_v_len); 1310 if (!peer_v || peer_v_len != curve->hash_len || 1311 os_memcmp(peer_v, v, curve->hash_len) != 0) { 1312 dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found"); 1313 wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'", 1314 v, curve->hash_len); 1315 wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len); 1316 pkex->t++; 1317 goto fail; 1318 } 1319 wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received"); 1320 1321 ret = 0; 1322 out: 1323 wpabuf_free(B_pub); 1324 wpabuf_free(X_pub); 1325 wpabuf_free(Y_pub); 1326 os_free(unwrapped); 1327 return ret; 1328 fail: 1329 goto out; 1330 } 1331 1332 1333 struct dpp_bootstrap_info * 1334 dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, 1335 unsigned int freq) 1336 { 1337 struct dpp_bootstrap_info *bi; 1338 1339 bi = os_zalloc(sizeof(*bi)); 1340 if (!bi) 1341 return NULL; 1342 bi->id = dpp_next_id(dpp); 1343 bi->type = DPP_BOOTSTRAP_PKEX; 1344 os_memcpy(bi->mac_addr, peer, ETH_ALEN); 1345 bi->num_freq = 1; 1346 bi->freq[0] = freq; 1347 bi->curve = pkex->own_bi->curve; 1348 bi->pubkey = pkex->peer_bootstrap_key; 1349 pkex->peer_bootstrap_key = NULL; 1350 if (dpp_bootstrap_key_hash(bi) < 0) { 1351 dpp_bootstrap_info_free(bi); 1352 return NULL; 1353 } 1354 dpp_pkex_free(pkex); 1355 dl_list_add(&dpp->bootstrap, &bi->list); 1356 return bi; 1357 } 1358 1359 1360 void dpp_pkex_free(struct dpp_pkex *pkex) 1361 { 1362 if (!pkex) 1363 return; 1364 1365 os_free(pkex->identifier); 1366 os_free(pkex->code); 1367 crypto_ec_key_deinit(pkex->x); 1368 crypto_ec_key_deinit(pkex->y); 1369 crypto_ec_key_deinit(pkex->peer_bootstrap_key); 1370 wpabuf_free(pkex->exchange_req); 1371 wpabuf_free(pkex->exchange_resp); 1372 os_free(pkex); 1373 } 1374