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