1 /* 2 * DPP functionality shared between hostapd and wpa_supplicant 3 * Copyright (c) 2017, Qualcomm Atheros, Inc. 4 * Copyright (c) 2018-2020, The Linux Foundation 5 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "utils/includes.h" 12 13 #include "utils/common.h" 14 #include "utils/base64.h" 15 #include "utils/json.h" 16 #include "utils/ip_addr.h" 17 #include "common/ieee802_11_common.h" 18 #include "common/wpa_ctrl.h" 19 #include "common/gas.h" 20 #include "eap_common/eap_defs.h" 21 #include "crypto/crypto.h" 22 #include "crypto/random.h" 23 #include "crypto/aes.h" 24 #include "crypto/aes_siv.h" 25 #include "drivers/driver.h" 26 #include "dpp.h" 27 #include "dpp_i.h" 28 29 30 #ifdef CONFIG_TESTING_OPTIONS 31 #ifdef CONFIG_DPP3 32 int dpp_version_override = 3; 33 #elif defined(CONFIG_DPP2) 34 int dpp_version_override = 2; 35 #else 36 int dpp_version_override = 1; 37 #endif 38 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; 39 #endif /* CONFIG_TESTING_OPTIONS */ 40 41 42 void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) 43 { 44 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); 45 } 46 47 48 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, 49 size_t len) 50 { 51 struct wpabuf *msg; 52 53 msg = wpabuf_alloc(8 + len); 54 if (!msg) 55 return NULL; 56 wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC); 57 wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); 58 wpabuf_put_be24(msg, OUI_WFA); 59 wpabuf_put_u8(msg, DPP_OUI_TYPE); 60 wpabuf_put_u8(msg, 1); /* Crypto Suite */ 61 wpabuf_put_u8(msg, type); 62 return msg; 63 } 64 65 66 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len) 67 { 68 u16 id, alen; 69 const u8 *pos = buf, *end = buf + len; 70 71 while (end - pos >= 4) { 72 id = WPA_GET_LE16(pos); 73 pos += 2; 74 alen = WPA_GET_LE16(pos); 75 pos += 2; 76 if (alen > end - pos) 77 return NULL; 78 if (id == req_id) { 79 *ret_len = alen; 80 return pos; 81 } 82 pos += alen; 83 } 84 85 return NULL; 86 } 87 88 89 static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len, 90 u16 req_id, u16 *ret_len) 91 { 92 u16 id, alen; 93 const u8 *pos, *end = buf + len; 94 95 if (!prev) 96 pos = buf; 97 else 98 pos = prev + WPA_GET_LE16(prev - 2); 99 while (end - pos >= 4) { 100 id = WPA_GET_LE16(pos); 101 pos += 2; 102 alen = WPA_GET_LE16(pos); 103 pos += 2; 104 if (alen > end - pos) 105 return NULL; 106 if (id == req_id) { 107 *ret_len = alen; 108 return pos; 109 } 110 pos += alen; 111 } 112 113 return NULL; 114 } 115 116 117 int dpp_check_attrs(const u8 *buf, size_t len) 118 { 119 const u8 *pos, *end; 120 int wrapped_data = 0; 121 122 pos = buf; 123 end = buf + len; 124 while (end - pos >= 4) { 125 u16 id, alen; 126 127 id = WPA_GET_LE16(pos); 128 pos += 2; 129 alen = WPA_GET_LE16(pos); 130 pos += 2; 131 wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u", 132 id, alen); 133 if (alen > end - pos) { 134 wpa_printf(MSG_DEBUG, 135 "DPP: Truncated message - not enough room for the attribute - dropped"); 136 return -1; 137 } 138 if (wrapped_data) { 139 wpa_printf(MSG_DEBUG, 140 "DPP: An unexpected attribute included after the Wrapped Data attribute"); 141 return -1; 142 } 143 if (id == DPP_ATTR_WRAPPED_DATA) 144 wrapped_data = 1; 145 pos += alen; 146 } 147 148 if (end != pos) { 149 wpa_printf(MSG_DEBUG, 150 "DPP: Unexpected octets (%d) after the last attribute", 151 (int) (end - pos)); 152 return -1; 153 } 154 155 return 0; 156 } 157 158 159 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) 160 { 161 if (!info) 162 return; 163 os_free(info->uri); 164 os_free(info->info); 165 os_free(info->chan); 166 os_free(info->host); 167 os_free(info->pk); 168 crypto_ec_key_deinit(info->pubkey); 169 str_clear_free(info->configurator_params); 170 os_free(info); 171 } 172 173 174 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type) 175 { 176 switch (type) { 177 case DPP_BOOTSTRAP_QR_CODE: 178 return "QRCODE"; 179 case DPP_BOOTSTRAP_PKEX: 180 return "PKEX"; 181 case DPP_BOOTSTRAP_NFC_URI: 182 return "NFC-URI"; 183 } 184 return "??"; 185 } 186 187 188 static int dpp_uri_valid_info(const char *info) 189 { 190 while (*info) { 191 unsigned char val = *info++; 192 193 if (val < 0x20 || val > 0x7e || val == 0x3b) 194 return 0; 195 } 196 197 return 1; 198 } 199 200 201 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri) 202 { 203 bi->uri = os_strdup(uri); 204 return bi->uri ? 0 : -1; 205 } 206 207 208 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, 209 const char *chan_list) 210 { 211 const char *pos = chan_list, *pos2; 212 int opclass = -1, channel, freq; 213 214 while (pos && *pos && *pos != ';') { 215 pos2 = pos; 216 while (*pos2 >= '0' && *pos2 <= '9') 217 pos2++; 218 if (*pos2 == '/') { 219 opclass = atoi(pos); 220 pos = pos2 + 1; 221 } 222 if (opclass <= 0) 223 goto fail; 224 channel = atoi(pos); 225 if (channel <= 0) 226 goto fail; 227 while (*pos >= '0' && *pos <= '9') 228 pos++; 229 freq = ieee80211_chan_to_freq(NULL, opclass, channel); 230 wpa_printf(MSG_DEBUG, 231 "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d", 232 opclass, channel, freq); 233 bi->channels_listed = true; 234 if (freq < 0) { 235 wpa_printf(MSG_DEBUG, 236 "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)", 237 opclass, channel); 238 } else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) { 239 wpa_printf(MSG_DEBUG, 240 "DPP: Too many channels in URI channel-list - ignore list"); 241 bi->num_freq = 0; 242 break; 243 } else { 244 bi->freq[bi->num_freq++] = freq; 245 } 246 247 if (*pos == ';' || *pos == '\0') 248 break; 249 if (*pos != ',') 250 goto fail; 251 pos++; 252 } 253 254 return 0; 255 fail: 256 wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list"); 257 return -1; 258 } 259 260 261 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac) 262 { 263 if (!mac) 264 return 0; 265 266 if (hwaddr_aton2(mac, bi->mac_addr) < 0) { 267 wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac"); 268 return -1; 269 } 270 271 wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr)); 272 273 return 0; 274 } 275 276 277 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info) 278 { 279 const char *end; 280 281 if (!info) 282 return 0; 283 284 end = os_strchr(info, ';'); 285 if (!end) 286 end = info + os_strlen(info); 287 bi->info = os_malloc(end - info + 1); 288 if (!bi->info) 289 return -1; 290 os_memcpy(bi->info, info, end - info); 291 bi->info[end - info] = '\0'; 292 wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info); 293 if (!dpp_uri_valid_info(bi->info)) { 294 wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload"); 295 return -1; 296 } 297 298 return 0; 299 } 300 301 302 int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version) 303 { 304 #ifdef CONFIG_DPP2 305 if (!version || DPP_VERSION < 2) 306 return 0; 307 308 if (*version == '1') 309 bi->version = 1; 310 else if (*version == '2') 311 bi->version = 2; 312 else if (*version == '3') 313 bi->version = 3; 314 else 315 wpa_printf(MSG_DEBUG, "DPP: Unknown URI version"); 316 317 wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version); 318 #endif /* CONFIG_DPP2 */ 319 320 return 0; 321 } 322 323 324 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) 325 { 326 u8 *data; 327 size_t data_len; 328 int res; 329 const char *end; 330 331 end = os_strchr(info, ';'); 332 if (!end) 333 return -1; 334 335 data = base64_decode(info, end - info, &data_len); 336 if (!data) { 337 wpa_printf(MSG_DEBUG, 338 "DPP: Invalid base64 encoding on URI public-key"); 339 return -1; 340 } 341 wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", 342 data, data_len); 343 344 res = dpp_get_subject_public_key(bi, data, data_len); 345 os_free(data); 346 return res; 347 } 348 349 350 static int dpp_parse_uri_supported_curves(struct dpp_bootstrap_info *bi, 351 const char *txt) 352 { 353 int val; 354 355 if (!txt) 356 return 0; 357 358 val = hex2num(txt[0]); 359 if (val < 0) 360 return -1; 361 bi->supported_curves = val; 362 363 val = hex2num(txt[1]); 364 if (val > 0) 365 bi->supported_curves |= val << 4; 366 367 wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x", 368 bi->supported_curves); 369 370 return 0; 371 } 372 373 374 static int dpp_parse_uri_host(struct dpp_bootstrap_info *bi, const char *txt) 375 { 376 const char *end; 377 char *port; 378 struct hostapd_ip_addr addr; 379 char buf[100], *pos; 380 381 if (!txt) 382 return 0; 383 384 end = os_strchr(txt, ';'); 385 if (!end) 386 end = txt + os_strlen(txt); 387 if (end - txt > (int) sizeof(buf) - 1) 388 return -1; 389 os_memcpy(buf, txt, end - txt); 390 buf[end - txt] = '\0'; 391 392 bi->port = DPP_TCP_PORT; 393 394 pos = buf; 395 if (*pos == '[') { 396 pos = &buf[1]; 397 port = os_strchr(pos, ']'); 398 if (!port) 399 return -1; 400 *port++ = '\0'; 401 if (*port == ':') 402 bi->port = atoi(port + 1); 403 } 404 405 if (hostapd_parse_ip_addr(pos, &addr) < 0) { 406 if (buf[0] != '[') { 407 port = os_strrchr(pos, ':'); 408 if (port) { 409 *port++ = '\0'; 410 bi->port = atoi(port); 411 } 412 } 413 if (hostapd_parse_ip_addr(pos, &addr) < 0) { 414 wpa_printf(MSG_INFO, 415 "DPP: Invalid IP address in URI host entry: %s", 416 pos); 417 return -1; 418 } 419 } 420 os_free(bi->host); 421 bi->host = os_memdup(&addr, sizeof(addr)); 422 if (!bi->host) 423 return -1; 424 425 wpa_printf(MSG_DEBUG, "DPP: host: %s port: %u", 426 hostapd_ip_txt(bi->host, buf, sizeof(buf)), bi->port); 427 428 return 0; 429 } 430 431 432 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) 433 { 434 const char *pos = uri; 435 const char *end; 436 const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL; 437 const char *version = NULL, *supported_curves = NULL, *host = NULL; 438 struct dpp_bootstrap_info *bi; 439 440 wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri)); 441 442 if (os_strncmp(pos, "DPP:", 4) != 0) { 443 wpa_printf(MSG_INFO, "DPP: Not a DPP URI"); 444 return NULL; 445 } 446 pos += 4; 447 448 for (;;) { 449 end = os_strchr(pos, ';'); 450 if (!end) 451 break; 452 453 if (end == pos) { 454 /* Handle terminating ";;" and ignore unexpected ";" 455 * for parsing robustness. */ 456 pos++; 457 continue; 458 } 459 460 if (pos[0] == 'C' && pos[1] == ':' && !chan_list) 461 chan_list = pos + 2; 462 else if (pos[0] == 'M' && pos[1] == ':' && !mac) 463 mac = pos + 2; 464 else if (pos[0] == 'I' && pos[1] == ':' && !info) 465 info = pos + 2; 466 else if (pos[0] == 'K' && pos[1] == ':' && !pk) 467 pk = pos + 2; 468 else if (pos[0] == 'V' && pos[1] == ':' && !version) 469 version = pos + 2; 470 else if (pos[0] == 'B' && pos[1] == ':' && !supported_curves) 471 supported_curves = pos + 2; 472 else if (pos[0] == 'H' && pos[1] == ':' && !host) 473 host = pos + 2; 474 else 475 wpa_hexdump_ascii(MSG_DEBUG, 476 "DPP: Ignore unrecognized URI parameter", 477 pos, end - pos); 478 pos = end + 1; 479 } 480 481 if (!pk) { 482 wpa_printf(MSG_INFO, "DPP: URI missing public-key"); 483 return NULL; 484 } 485 486 bi = os_zalloc(sizeof(*bi)); 487 if (!bi) 488 return NULL; 489 490 if (dpp_clone_uri(bi, uri) < 0 || 491 dpp_parse_uri_chan_list(bi, chan_list) < 0 || 492 dpp_parse_uri_mac(bi, mac) < 0 || 493 dpp_parse_uri_info(bi, info) < 0 || 494 dpp_parse_uri_version(bi, version) < 0 || 495 dpp_parse_uri_supported_curves(bi, supported_curves) < 0 || 496 dpp_parse_uri_host(bi, host) < 0 || 497 dpp_parse_uri_pk(bi, pk) < 0) { 498 dpp_bootstrap_info_free(bi); 499 bi = NULL; 500 } 501 502 return bi; 503 } 504 505 506 void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) 507 { 508 wpa_printf(MSG_DEBUG, "DPP: Status %d", status); 509 wpabuf_put_le16(msg, DPP_ATTR_STATUS); 510 wpabuf_put_le16(msg, 1); 511 wpabuf_put_u8(msg, status); 512 } 513 514 515 void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash) 516 { 517 if (hash) { 518 wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash"); 519 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH); 520 wpabuf_put_le16(msg, SHA256_MAC_LEN); 521 wpabuf_put_data(msg, hash, SHA256_MAC_LEN); 522 } 523 } 524 525 526 static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, 527 u16 num_modes, unsigned int freq) 528 { 529 u16 m; 530 int c, flag; 531 532 if (!own_modes || !num_modes) 533 return 1; 534 535 for (m = 0; m < num_modes; m++) { 536 for (c = 0; c < own_modes[m].num_channels; c++) { 537 if ((unsigned int) own_modes[m].channels[c].freq != 538 freq) 539 continue; 540 flag = own_modes[m].channels[c].flag; 541 if (!(flag & (HOSTAPD_CHAN_DISABLED | 542 HOSTAPD_CHAN_NO_IR | 543 HOSTAPD_CHAN_RADAR))) 544 return 1; 545 } 546 } 547 548 wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq); 549 return 0; 550 } 551 552 553 static int freq_included(const unsigned int freqs[], unsigned int num, 554 unsigned int freq) 555 { 556 while (num > 0) { 557 if (freqs[--num] == freq) 558 return 1; 559 } 560 return 0; 561 } 562 563 564 static void freq_to_start(unsigned int freqs[], unsigned int num, 565 unsigned int freq) 566 { 567 unsigned int i; 568 569 for (i = 0; i < num; i++) { 570 if (freqs[i] == freq) 571 break; 572 } 573 if (i == 0 || i >= num) 574 return; 575 os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0])); 576 freqs[0] = freq; 577 } 578 579 580 static int dpp_channel_intersect(struct dpp_authentication *auth, 581 struct hostapd_hw_modes *own_modes, 582 u16 num_modes) 583 { 584 struct dpp_bootstrap_info *peer_bi = auth->peer_bi; 585 unsigned int i, freq; 586 587 for (i = 0; i < peer_bi->num_freq; i++) { 588 freq = peer_bi->freq[i]; 589 if (freq_included(auth->freq, auth->num_freq, freq)) 590 continue; 591 if (dpp_channel_ok_init(own_modes, num_modes, freq)) 592 auth->freq[auth->num_freq++] = freq; 593 } 594 if (!auth->num_freq) { 595 wpa_printf(MSG_INFO, 596 "DPP: No available channels for initiating DPP Authentication"); 597 return -1; 598 } 599 auth->curr_freq = auth->freq[0]; 600 return 0; 601 } 602 603 604 static int dpp_channel_local_list(struct dpp_authentication *auth, 605 struct hostapd_hw_modes *own_modes, 606 u16 num_modes) 607 { 608 u16 m; 609 int c, flag; 610 unsigned int freq; 611 612 auth->num_freq = 0; 613 614 if (!own_modes || !num_modes) { 615 auth->freq[0] = 2412; 616 auth->freq[1] = 2437; 617 auth->freq[2] = 2462; 618 auth->num_freq = 3; 619 return 0; 620 } 621 622 for (m = 0; m < num_modes; m++) { 623 for (c = 0; c < own_modes[m].num_channels; c++) { 624 freq = own_modes[m].channels[c].freq; 625 flag = own_modes[m].channels[c].flag; 626 if (flag & (HOSTAPD_CHAN_DISABLED | 627 HOSTAPD_CHAN_NO_IR | 628 HOSTAPD_CHAN_RADAR)) 629 continue; 630 if (freq_included(auth->freq, auth->num_freq, freq)) 631 continue; 632 auth->freq[auth->num_freq++] = freq; 633 if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) { 634 m = num_modes; 635 break; 636 } 637 } 638 } 639 640 return auth->num_freq == 0 ? -1 : 0; 641 } 642 643 644 int dpp_prepare_channel_list(struct dpp_authentication *auth, 645 unsigned int neg_freq, 646 struct hostapd_hw_modes *own_modes, u16 num_modes) 647 { 648 int res; 649 char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; 650 unsigned int i; 651 652 if (!own_modes) { 653 if (!neg_freq) 654 return -1; 655 auth->num_freq = 1; 656 auth->freq[0] = neg_freq; 657 auth->curr_freq = neg_freq; 658 return 0; 659 } 660 661 if (auth->peer_bi->num_freq > 0) 662 res = dpp_channel_intersect(auth, own_modes, num_modes); 663 else 664 res = dpp_channel_local_list(auth, own_modes, num_modes); 665 if (res < 0) 666 return res; 667 668 /* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most 669 * likely channels first. */ 670 freq_to_start(auth->freq, auth->num_freq, 2462); 671 freq_to_start(auth->freq, auth->num_freq, 2412); 672 freq_to_start(auth->freq, auth->num_freq, 2437); 673 674 auth->freq_idx = 0; 675 auth->curr_freq = auth->freq[0]; 676 677 pos = freqs; 678 end = pos + sizeof(freqs); 679 for (i = 0; i < auth->num_freq; i++) { 680 res = os_snprintf(pos, end - pos, " %u", auth->freq[i]); 681 if (os_snprintf_error(end - pos, res)) 682 break; 683 pos += res; 684 } 685 *pos = '\0'; 686 wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s", 687 freqs); 688 689 return 0; 690 } 691 692 693 int dpp_gen_uri(struct dpp_bootstrap_info *bi) 694 { 695 char macstr[ETH_ALEN * 2 + 10]; 696 size_t len; 697 char supp_curves[10]; 698 char host[100]; 699 700 len = 4; /* "DPP:" */ 701 if (bi->chan) 702 len += 3 + os_strlen(bi->chan); /* C:...; */ 703 if (is_zero_ether_addr(bi->mac_addr)) 704 macstr[0] = '\0'; 705 else 706 os_snprintf(macstr, sizeof(macstr), "M:" COMPACT_MACSTR ";", 707 MAC2STR(bi->mac_addr)); 708 len += os_strlen(macstr); /* M:...; */ 709 if (bi->info) 710 len += 3 + os_strlen(bi->info); /* I:...; */ 711 #ifdef CONFIG_DPP2 712 len += 4; /* V:2; */ 713 #endif /* CONFIG_DPP2 */ 714 len += 4 + os_strlen(bi->pk); /* K:...;; */ 715 716 if (bi->supported_curves) { 717 u8 val = bi->supported_curves; 718 719 if (val & 0xf0) { 720 val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); 721 len += os_snprintf(supp_curves, sizeof(supp_curves), 722 "B:%02x;", val); 723 } else { 724 len += os_snprintf(supp_curves, sizeof(supp_curves), 725 "B:%x;", val); 726 } 727 } else { 728 supp_curves[0] = '\0'; 729 } 730 731 host[0] = '\0'; 732 if (bi->host) { 733 char buf[100]; 734 const char *addr; 735 736 addr = hostapd_ip_txt(bi->host, buf, sizeof(buf)); 737 if (!addr) 738 return -1; 739 if (bi->port == DPP_TCP_PORT) 740 len += os_snprintf(host, sizeof(host), "H:%s;", addr); 741 else if (bi->host->af == AF_INET) 742 len += os_snprintf(host, sizeof(host), "H:%s:%u;", 743 addr, bi->port); 744 else 745 len += os_snprintf(host, sizeof(host), "H:[%s]:%u;", 746 addr, bi->port); 747 } 748 749 os_free(bi->uri); 750 bi->uri = os_malloc(len + 1); 751 if (!bi->uri) 752 return -1; 753 os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%s%sK:%s;;", 754 bi->chan ? "C:" : "", bi->chan ? bi->chan : "", 755 bi->chan ? ";" : "", 756 macstr, 757 bi->info ? "I:" : "", bi->info ? bi->info : "", 758 bi->info ? ";" : "", 759 DPP_VERSION == 3 ? "V:3;" : 760 (DPP_VERSION == 2 ? "V:2;" : ""), 761 supp_curves, 762 host, 763 bi->pk); 764 return 0; 765 } 766 767 768 struct dpp_authentication * 769 dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx) 770 { 771 struct dpp_authentication *auth; 772 773 auth = os_zalloc(sizeof(*auth)); 774 if (!auth) 775 return NULL; 776 auth->global = dpp; 777 auth->msg_ctx = msg_ctx; 778 auth->conf_resp_status = 255; 779 return auth; 780 } 781 782 783 static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth, 784 const char *json) 785 { 786 size_t nonce_len; 787 size_t json_len, clear_len; 788 struct wpabuf *clear = NULL, *msg = NULL, *pe = NULL; 789 u8 *wrapped; 790 size_t attr_len; 791 #ifdef CONFIG_DPP3 792 u8 auth_i[DPP_MAX_HASH_LEN]; 793 #endif /* CONFIG_DPP3 */ 794 795 wpa_printf(MSG_DEBUG, "DPP: Build configuration request"); 796 797 nonce_len = auth->curve->nonce_len; 798 if (random_get_bytes(auth->e_nonce, nonce_len)) { 799 wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); 800 goto fail; 801 } 802 wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len); 803 json_len = os_strlen(json); 804 wpa_hexdump_ascii(MSG_DEBUG, "DPP: configRequest JSON", json, json_len); 805 806 /* { E-nonce, configAttrib }ke */ 807 clear_len = 4 + nonce_len + 4 + json_len; 808 #ifdef CONFIG_DPP3 809 if (auth->waiting_new_key) { 810 pe = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 811 if (!pe) 812 goto fail; 813 clear_len += 4 + wpabuf_len(pe); 814 815 if (dpp_derive_auth_i(auth, auth_i) < 0) 816 goto fail; 817 clear_len += 4 + auth->curve->hash_len; 818 } 819 #endif /* CONFIG_DPP3 */ 820 clear = wpabuf_alloc(clear_len); 821 attr_len = 4 + clear_len + AES_BLOCK_SIZE; 822 #ifdef CONFIG_TESTING_OPTIONS 823 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) 824 attr_len += 5; 825 #endif /* CONFIG_TESTING_OPTIONS */ 826 msg = wpabuf_alloc(attr_len); 827 if (!clear || !msg) 828 goto fail; 829 830 #ifdef CONFIG_TESTING_OPTIONS 831 if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) { 832 wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce"); 833 goto skip_e_nonce; 834 } 835 if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) { 836 wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce"); 837 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 838 wpabuf_put_le16(clear, nonce_len - 1); 839 wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1); 840 goto skip_e_nonce; 841 } 842 if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) { 843 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); 844 goto skip_wrapped_data; 845 } 846 #endif /* CONFIG_TESTING_OPTIONS */ 847 848 /* E-nonce */ 849 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 850 wpabuf_put_le16(clear, nonce_len); 851 wpabuf_put_data(clear, auth->e_nonce, nonce_len); 852 853 #ifdef CONFIG_TESTING_OPTIONS 854 skip_e_nonce: 855 if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) { 856 wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib"); 857 goto skip_conf_attr_obj; 858 } 859 #endif /* CONFIG_TESTING_OPTIONS */ 860 861 #ifdef CONFIG_DPP3 862 if (pe) { 863 wpa_printf(MSG_DEBUG, "DPP: Pe"); 864 wpabuf_put_le16(clear, DPP_ATTR_I_PROTOCOL_KEY); 865 wpabuf_put_le16(clear, wpabuf_len(pe)); 866 wpabuf_put_buf(clear, pe); 867 } 868 if (auth->waiting_new_key) { 869 wpa_printf(MSG_DEBUG, "DPP: Initiator Authentication Tag"); 870 wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); 871 wpabuf_put_le16(clear, auth->curve->hash_len); 872 wpabuf_put_data(clear, auth_i, auth->curve->hash_len); 873 } 874 #endif /* CONFIG_DPP3 */ 875 876 /* configAttrib */ 877 wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ); 878 wpabuf_put_le16(clear, json_len); 879 wpabuf_put_data(clear, json, json_len); 880 881 #ifdef CONFIG_TESTING_OPTIONS 882 skip_conf_attr_obj: 883 #endif /* CONFIG_TESTING_OPTIONS */ 884 885 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 886 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 887 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 888 889 /* No AES-SIV AD */ 890 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 891 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 892 wpabuf_head(clear), wpabuf_len(clear), 893 0, NULL, NULL, wrapped) < 0) 894 goto fail; 895 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 896 wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); 897 898 #ifdef CONFIG_TESTING_OPTIONS 899 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) { 900 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); 901 dpp_build_attr_status(msg, DPP_STATUS_OK); 902 } 903 skip_wrapped_data: 904 #endif /* CONFIG_TESTING_OPTIONS */ 905 906 wpa_hexdump_buf(MSG_DEBUG, 907 "DPP: Configuration Request frame attributes", msg); 908 out: 909 wpabuf_free(clear); 910 wpabuf_free(pe); 911 return msg; 912 913 fail: 914 wpabuf_free(msg); 915 msg = NULL; 916 goto out; 917 } 918 919 920 void dpp_write_adv_proto(struct wpabuf *buf) 921 { 922 /* Advertisement Protocol IE */ 923 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 924 wpabuf_put_u8(buf, 8); /* Length */ 925 wpabuf_put_u8(buf, 0x7f); 926 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 927 wpabuf_put_u8(buf, 5); 928 wpabuf_put_be24(buf, OUI_WFA); 929 wpabuf_put_u8(buf, DPP_OUI_TYPE); 930 wpabuf_put_u8(buf, 0x01); 931 } 932 933 934 void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) 935 { 936 /* GAS Query */ 937 wpabuf_put_le16(buf, wpabuf_len(query)); 938 wpabuf_put_buf(buf, query); 939 } 940 941 942 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, 943 const char *json) 944 { 945 struct wpabuf *buf, *conf_req; 946 947 conf_req = dpp_build_conf_req_attr(auth, json); 948 if (!conf_req) { 949 wpa_printf(MSG_DEBUG, 950 "DPP: No configuration request data available"); 951 return NULL; 952 } 953 954 buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req)); 955 if (!buf) { 956 wpabuf_free(conf_req); 957 return NULL; 958 } 959 960 dpp_write_adv_proto(buf); 961 dpp_write_gas_query(buf, conf_req); 962 wpabuf_free(conf_req); 963 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf); 964 965 return buf; 966 } 967 968 969 struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, 970 const char *name, 971 enum dpp_netrole netrole, 972 const char *mud_url, int *opclasses, 973 const char *extra_name, 974 const char *extra_value) 975 { 976 size_t len, name_len; 977 const char *tech = "infra"; 978 const char *dpp_name; 979 struct wpabuf *buf = NULL, *json = NULL; 980 char *csr = NULL; 981 982 #ifdef CONFIG_TESTING_OPTIONS 983 if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) { 984 static const char *bogus_tech = "knfra"; 985 986 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr"); 987 tech = bogus_tech; 988 } 989 #endif /* CONFIG_TESTING_OPTIONS */ 990 991 dpp_name = name ? name : "Test"; 992 name_len = os_strlen(dpp_name); 993 994 len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4; 995 if (mud_url && mud_url[0]) 996 len += 10 + os_strlen(mud_url); 997 if (extra_name && extra_value && extra_name[0] && extra_value[0]) 998 len += 10 + os_strlen(extra_name) + os_strlen(extra_value); 999 #ifdef CONFIG_DPP2 1000 if (auth->csr) { 1001 size_t csr_len; 1002 1003 csr = base64_encode_no_lf(wpabuf_head(auth->csr), 1004 wpabuf_len(auth->csr), &csr_len); 1005 if (!csr) 1006 goto fail; 1007 len += 30 + csr_len; 1008 } 1009 #endif /* CONFIG_DPP2 */ 1010 json = wpabuf_alloc(len); 1011 if (!json) 1012 goto fail; 1013 1014 json_start_object(json, NULL); 1015 if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) 1016 goto fail; 1017 json_value_sep(json); 1018 json_add_string(json, "wi-fi_tech", tech); 1019 json_value_sep(json); 1020 json_add_string(json, "netRole", dpp_netrole_str(netrole)); 1021 if (mud_url && mud_url[0]) { 1022 json_value_sep(json); 1023 json_add_string(json, "mudurl", mud_url); 1024 } 1025 if (opclasses) { 1026 int i; 1027 1028 json_value_sep(json); 1029 json_start_array(json, "bandSupport"); 1030 for (i = 0; opclasses[i]; i++) 1031 wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]); 1032 json_end_array(json); 1033 } 1034 if (csr) { 1035 json_value_sep(json); 1036 json_add_string(json, "pkcs10", csr); 1037 } 1038 if (extra_name && extra_value && extra_name[0] && extra_value[0]) { 1039 json_value_sep(json); 1040 wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value); 1041 } 1042 json_end_object(json); 1043 1044 buf = dpp_build_conf_req(auth, wpabuf_head(json)); 1045 fail: 1046 wpabuf_free(json); 1047 os_free(csr); 1048 1049 return buf; 1050 } 1051 1052 1053 static int bin_str_eq(const char *val, size_t len, const char *cmp) 1054 { 1055 return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0; 1056 } 1057 1058 1059 struct dpp_configuration * dpp_configuration_alloc(const char *type) 1060 { 1061 struct dpp_configuration *conf; 1062 const char *end; 1063 size_t len; 1064 1065 conf = os_zalloc(sizeof(*conf)); 1066 if (!conf) 1067 goto fail; 1068 1069 end = os_strchr(type, ' '); 1070 if (end) 1071 len = end - type; 1072 else 1073 len = os_strlen(type); 1074 1075 if (bin_str_eq(type, len, "psk")) 1076 conf->akm = DPP_AKM_PSK; 1077 else if (bin_str_eq(type, len, "sae")) 1078 conf->akm = DPP_AKM_SAE; 1079 else if (bin_str_eq(type, len, "psk-sae") || 1080 bin_str_eq(type, len, "psk+sae")) 1081 conf->akm = DPP_AKM_PSK_SAE; 1082 else if (bin_str_eq(type, len, "sae-dpp") || 1083 bin_str_eq(type, len, "dpp+sae")) 1084 conf->akm = DPP_AKM_SAE_DPP; 1085 else if (bin_str_eq(type, len, "psk-sae-dpp") || 1086 bin_str_eq(type, len, "dpp+psk+sae")) 1087 conf->akm = DPP_AKM_PSK_SAE_DPP; 1088 else if (bin_str_eq(type, len, "dpp")) 1089 conf->akm = DPP_AKM_DPP; 1090 else if (bin_str_eq(type, len, "dot1x")) 1091 conf->akm = DPP_AKM_DOT1X; 1092 else 1093 goto fail; 1094 1095 return conf; 1096 fail: 1097 dpp_configuration_free(conf); 1098 return NULL; 1099 } 1100 1101 1102 int dpp_akm_psk(enum dpp_akm akm) 1103 { 1104 return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || 1105 akm == DPP_AKM_PSK_SAE_DPP; 1106 } 1107 1108 1109 int dpp_akm_sae(enum dpp_akm akm) 1110 { 1111 return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE || 1112 akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; 1113 } 1114 1115 1116 int dpp_akm_legacy(enum dpp_akm akm) 1117 { 1118 return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || 1119 akm == DPP_AKM_SAE; 1120 } 1121 1122 1123 int dpp_akm_dpp(enum dpp_akm akm) 1124 { 1125 return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP || 1126 akm == DPP_AKM_PSK_SAE_DPP; 1127 } 1128 1129 1130 int dpp_akm_ver2(enum dpp_akm akm) 1131 { 1132 return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; 1133 } 1134 1135 1136 int dpp_configuration_valid(const struct dpp_configuration *conf) 1137 { 1138 if (conf->ssid_len == 0) 1139 return 0; 1140 if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set) 1141 return 0; 1142 if (dpp_akm_sae(conf->akm) && !conf->passphrase) 1143 return 0; 1144 return 1; 1145 } 1146 1147 1148 void dpp_configuration_free(struct dpp_configuration *conf) 1149 { 1150 if (!conf) 1151 return; 1152 str_clear_free(conf->passphrase); 1153 os_free(conf->group_id); 1154 os_free(conf->csrattrs); 1155 os_free(conf->extra_name); 1156 os_free(conf->extra_value); 1157 bin_clear_free(conf, sizeof(*conf)); 1158 } 1159 1160 1161 static int dpp_configuration_parse_helper(struct dpp_authentication *auth, 1162 const char *cmd, int idx) 1163 { 1164 const char *pos, *end; 1165 struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL; 1166 struct dpp_configuration *conf = NULL; 1167 size_t len; 1168 1169 pos = os_strstr(cmd, " conf=sta-"); 1170 if (pos) { 1171 conf_sta = dpp_configuration_alloc(pos + 10); 1172 if (!conf_sta) 1173 goto fail; 1174 conf_sta->netrole = DPP_NETROLE_STA; 1175 conf = conf_sta; 1176 } 1177 1178 pos = os_strstr(cmd, " conf=ap-"); 1179 if (pos) { 1180 conf_ap = dpp_configuration_alloc(pos + 9); 1181 if (!conf_ap) 1182 goto fail; 1183 conf_ap->netrole = DPP_NETROLE_AP; 1184 conf = conf_ap; 1185 } 1186 1187 pos = os_strstr(cmd, " conf=configurator"); 1188 if (pos) 1189 auth->provision_configurator = 1; 1190 1191 if (!conf) 1192 return 0; 1193 1194 pos = os_strstr(cmd, " ssid="); 1195 if (pos) { 1196 pos += 6; 1197 end = os_strchr(pos, ' '); 1198 conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos); 1199 conf->ssid_len /= 2; 1200 if (conf->ssid_len > sizeof(conf->ssid) || 1201 hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0) 1202 goto fail; 1203 } else { 1204 #ifdef CONFIG_TESTING_OPTIONS 1205 /* use a default SSID for legacy testing reasons */ 1206 os_memcpy(conf->ssid, "test", 4); 1207 conf->ssid_len = 4; 1208 #else /* CONFIG_TESTING_OPTIONS */ 1209 goto fail; 1210 #endif /* CONFIG_TESTING_OPTIONS */ 1211 } 1212 1213 pos = os_strstr(cmd, " ssid_charset="); 1214 if (pos) { 1215 if (conf_ap) { 1216 wpa_printf(MSG_INFO, 1217 "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee"); 1218 goto fail; 1219 } 1220 conf->ssid_charset = atoi(pos + 14); 1221 } 1222 1223 pos = os_strstr(cmd, " pass="); 1224 if (pos) { 1225 size_t pass_len; 1226 1227 pos += 6; 1228 end = os_strchr(pos, ' '); 1229 pass_len = end ? (size_t) (end - pos) : os_strlen(pos); 1230 pass_len /= 2; 1231 if (pass_len > 63 || pass_len < 8) 1232 goto fail; 1233 conf->passphrase = os_zalloc(pass_len + 1); 1234 if (!conf->passphrase || 1235 hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0) 1236 goto fail; 1237 } 1238 1239 pos = os_strstr(cmd, " psk="); 1240 if (pos) { 1241 pos += 5; 1242 if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0) 1243 goto fail; 1244 conf->psk_set = 1; 1245 } 1246 1247 pos = os_strstr(cmd, " group_id="); 1248 if (pos) { 1249 size_t group_id_len; 1250 1251 pos += 10; 1252 end = os_strchr(pos, ' '); 1253 group_id_len = end ? (size_t) (end - pos) : os_strlen(pos); 1254 conf->group_id = os_malloc(group_id_len + 1); 1255 if (!conf->group_id) 1256 goto fail; 1257 os_memcpy(conf->group_id, pos, group_id_len); 1258 conf->group_id[group_id_len] = '\0'; 1259 } 1260 1261 pos = os_strstr(cmd, " expiry="); 1262 if (pos) { 1263 long int val; 1264 1265 pos += 8; 1266 val = strtol(pos, NULL, 0); 1267 if (val <= 0) 1268 goto fail; 1269 conf->netaccesskey_expiry = val; 1270 } 1271 1272 pos = os_strstr(cmd, " csrattrs="); 1273 if (pos) { 1274 pos += 10; 1275 end = os_strchr(pos, ' '); 1276 len = end ? (size_t) (end - pos) : os_strlen(pos); 1277 conf->csrattrs = os_zalloc(len + 1); 1278 if (!conf->csrattrs) 1279 goto fail; 1280 os_memcpy(conf->csrattrs, pos, len); 1281 } 1282 1283 pos = os_strstr(cmd, " conf_extra_name="); 1284 if (pos) { 1285 pos += 17; 1286 end = os_strchr(pos, ' '); 1287 len = end ? (size_t) (end - pos) : os_strlen(pos); 1288 conf->extra_name = os_zalloc(len + 1); 1289 if (!conf->extra_name) 1290 goto fail; 1291 os_memcpy(conf->extra_name, pos, len); 1292 } 1293 1294 pos = os_strstr(cmd, " conf_extra_value="); 1295 if (pos) { 1296 pos += 18; 1297 end = os_strchr(pos, ' '); 1298 len = end ? (size_t) (end - pos) : os_strlen(pos); 1299 len /= 2; 1300 conf->extra_value = os_zalloc(len + 1); 1301 if (!conf->extra_value || 1302 hexstr2bin(pos, (u8 *) conf->extra_value, len) < 0) 1303 goto fail; 1304 } 1305 1306 if (!dpp_configuration_valid(conf)) 1307 goto fail; 1308 1309 if (idx == 0) { 1310 auth->conf_sta = conf_sta; 1311 auth->conf_ap = conf_ap; 1312 } else if (idx == 1) { 1313 if (!auth->conf_sta) 1314 auth->conf_sta = conf_sta; 1315 else 1316 auth->conf2_sta = conf_sta; 1317 if (!auth->conf_ap) 1318 auth->conf_ap = conf_ap; 1319 else 1320 auth->conf2_ap = conf_ap; 1321 } else { 1322 goto fail; 1323 } 1324 return 0; 1325 1326 fail: 1327 dpp_configuration_free(conf_sta); 1328 dpp_configuration_free(conf_ap); 1329 return -1; 1330 } 1331 1332 1333 static int dpp_configuration_parse(struct dpp_authentication *auth, 1334 const char *cmd) 1335 { 1336 const char *pos; 1337 char *tmp; 1338 size_t len; 1339 int res; 1340 1341 pos = os_strstr(cmd, " @CONF-OBJ-SEP@ "); 1342 if (!pos) 1343 return dpp_configuration_parse_helper(auth, cmd, 0); 1344 1345 len = pos - cmd; 1346 tmp = os_malloc(len + 1); 1347 if (!tmp) 1348 goto fail; 1349 os_memcpy(tmp, cmd, len); 1350 tmp[len] = '\0'; 1351 res = dpp_configuration_parse_helper(auth, tmp, 0); 1352 str_clear_free(tmp); 1353 if (res) 1354 goto fail; 1355 res = dpp_configuration_parse_helper(auth, cmd + len, 1); 1356 if (res) 1357 goto fail; 1358 return 0; 1359 fail: 1360 dpp_configuration_free(auth->conf_sta); 1361 dpp_configuration_free(auth->conf2_sta); 1362 dpp_configuration_free(auth->conf_ap); 1363 dpp_configuration_free(auth->conf2_ap); 1364 return -1; 1365 } 1366 1367 1368 static struct dpp_configurator * 1369 dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) 1370 { 1371 struct dpp_configurator *conf; 1372 1373 if (!dpp) 1374 return NULL; 1375 1376 dl_list_for_each(conf, &dpp->configurator, 1377 struct dpp_configurator, list) { 1378 if (conf->id == id) 1379 return conf; 1380 } 1381 return NULL; 1382 } 1383 1384 1385 int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd) 1386 { 1387 const char *pos; 1388 char *tmp = NULL; 1389 int ret = -1; 1390 1391 if (!cmd || auth->configurator_set) 1392 return 0; 1393 auth->configurator_set = 1; 1394 1395 if (cmd[0] != ' ') { 1396 size_t len; 1397 1398 len = os_strlen(cmd); 1399 tmp = os_malloc(len + 2); 1400 if (!tmp) 1401 goto fail; 1402 tmp[0] = ' '; 1403 os_memcpy(tmp + 1, cmd, len + 1); 1404 cmd = tmp; 1405 } 1406 1407 wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd); 1408 1409 if (os_strstr(cmd, " conf=query")) { 1410 auth->configurator_set = 0; 1411 auth->use_config_query = true; 1412 ret = 0; 1413 goto fail; 1414 } 1415 1416 pos = os_strstr(cmd, " configurator="); 1417 if (!auth->conf && pos) { 1418 pos += 14; 1419 auth->conf = dpp_configurator_get_id(auth->global, atoi(pos)); 1420 if (!auth->conf) { 1421 wpa_printf(MSG_INFO, 1422 "DPP: Could not find the specified configurator"); 1423 goto fail; 1424 } 1425 } 1426 1427 pos = os_strstr(cmd, " conn_status="); 1428 if (pos) { 1429 pos += 13; 1430 auth->send_conn_status = atoi(pos); 1431 } 1432 1433 pos = os_strstr(cmd, " akm_use_selector="); 1434 if (pos) { 1435 pos += 18; 1436 auth->akm_use_selector = atoi(pos); 1437 } 1438 1439 if (dpp_configuration_parse(auth, cmd) < 0) { 1440 wpa_msg(auth->msg_ctx, MSG_INFO, 1441 "DPP: Failed to set configurator parameters"); 1442 goto fail; 1443 } 1444 ret = 0; 1445 fail: 1446 os_free(tmp); 1447 return ret; 1448 } 1449 1450 1451 void dpp_auth_deinit(struct dpp_authentication *auth) 1452 { 1453 unsigned int i; 1454 1455 if (!auth) 1456 return; 1457 dpp_configuration_free(auth->conf_ap); 1458 dpp_configuration_free(auth->conf2_ap); 1459 dpp_configuration_free(auth->conf_sta); 1460 dpp_configuration_free(auth->conf2_sta); 1461 crypto_ec_key_deinit(auth->own_protocol_key); 1462 crypto_ec_key_deinit(auth->peer_protocol_key); 1463 crypto_ec_key_deinit(auth->reconfig_old_protocol_key); 1464 wpabuf_free(auth->req_msg); 1465 wpabuf_free(auth->resp_msg); 1466 wpabuf_free(auth->conf_req); 1467 wpabuf_free(auth->reconfig_req_msg); 1468 wpabuf_free(auth->reconfig_resp_msg); 1469 for (i = 0; i < auth->num_conf_obj; i++) { 1470 struct dpp_config_obj *conf = &auth->conf_obj[i]; 1471 1472 os_free(conf->connector); 1473 wpabuf_free(conf->c_sign_key); 1474 wpabuf_free(conf->certbag); 1475 wpabuf_free(conf->certs); 1476 wpabuf_free(conf->cacert); 1477 os_free(conf->server_name); 1478 wpabuf_free(conf->pp_key); 1479 } 1480 #ifdef CONFIG_DPP2 1481 dpp_free_asymmetric_key(auth->conf_key_pkg); 1482 os_free(auth->csrattrs); 1483 wpabuf_free(auth->csr); 1484 wpabuf_free(auth->priv_key); 1485 wpabuf_free(auth->cacert); 1486 wpabuf_free(auth->certbag); 1487 os_free(auth->trusted_eap_server_name); 1488 wpabuf_free(auth->conf_resp_tcp); 1489 #endif /* CONFIG_DPP2 */ 1490 wpabuf_free(auth->net_access_key); 1491 dpp_bootstrap_info_free(auth->tmp_own_bi); 1492 if (auth->tmp_peer_bi) { 1493 dl_list_del(&auth->tmp_peer_bi->list); 1494 dpp_bootstrap_info_free(auth->tmp_peer_bi); 1495 } 1496 os_free(auth->e_name); 1497 os_free(auth->e_mud_url); 1498 os_free(auth->e_band_support); 1499 #ifdef CONFIG_TESTING_OPTIONS 1500 os_free(auth->config_obj_override); 1501 os_free(auth->discovery_override); 1502 os_free(auth->groups_override); 1503 #endif /* CONFIG_TESTING_OPTIONS */ 1504 bin_clear_free(auth, sizeof(*auth)); 1505 } 1506 1507 1508 static struct wpabuf * 1509 dpp_build_conf_start(struct dpp_authentication *auth, 1510 struct dpp_configuration *conf, size_t tailroom) 1511 { 1512 struct wpabuf *buf; 1513 1514 #ifdef CONFIG_TESTING_OPTIONS 1515 if (auth->discovery_override) 1516 tailroom += os_strlen(auth->discovery_override); 1517 #endif /* CONFIG_TESTING_OPTIONS */ 1518 1519 buf = wpabuf_alloc(200 + tailroom); 1520 if (!buf) 1521 return NULL; 1522 json_start_object(buf, NULL); 1523 json_add_string(buf, "wi-fi_tech", "infra"); 1524 json_value_sep(buf); 1525 #ifdef CONFIG_TESTING_OPTIONS 1526 if (auth->discovery_override) { 1527 wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'", 1528 auth->discovery_override); 1529 wpabuf_put_str(buf, "\"discovery\":"); 1530 wpabuf_put_str(buf, auth->discovery_override); 1531 json_value_sep(buf); 1532 return buf; 1533 } 1534 #endif /* CONFIG_TESTING_OPTIONS */ 1535 json_start_object(buf, "discovery"); 1536 if (((!conf->ssid_charset || auth->peer_version < 2) && 1537 json_add_string_escape(buf, "ssid", conf->ssid, 1538 conf->ssid_len) < 0) || 1539 ((conf->ssid_charset && auth->peer_version >= 2) && 1540 json_add_base64url(buf, "ssid64", conf->ssid, 1541 conf->ssid_len) < 0)) { 1542 wpabuf_free(buf); 1543 return NULL; 1544 } 1545 if (conf->ssid_charset > 0) { 1546 json_value_sep(buf); 1547 json_add_int(buf, "ssid_charset", conf->ssid_charset); 1548 } 1549 json_end_object(buf); 1550 json_value_sep(buf); 1551 1552 return buf; 1553 } 1554 1555 1556 int dpp_build_jwk(struct wpabuf *buf, const char *name, 1557 struct crypto_ec_key *key, const char *kid, 1558 const struct dpp_curve_params *curve) 1559 { 1560 struct wpabuf *pub; 1561 const u8 *pos; 1562 int ret = -1; 1563 1564 pub = crypto_ec_key_get_pubkey_point(key, 0); 1565 if (!pub) 1566 goto fail; 1567 1568 json_start_object(buf, name); 1569 json_add_string(buf, "kty", "EC"); 1570 json_value_sep(buf); 1571 json_add_string(buf, "crv", curve->jwk_crv); 1572 json_value_sep(buf); 1573 pos = wpabuf_head(pub); 1574 if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0) 1575 goto fail; 1576 json_value_sep(buf); 1577 pos += curve->prime_len; 1578 if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0) 1579 goto fail; 1580 if (kid) { 1581 json_value_sep(buf); 1582 json_add_string(buf, "kid", kid); 1583 } 1584 json_end_object(buf); 1585 ret = 0; 1586 fail: 1587 wpabuf_free(pub); 1588 return ret; 1589 } 1590 1591 1592 static void dpp_build_legacy_cred_params(struct wpabuf *buf, 1593 struct dpp_configuration *conf) 1594 { 1595 if (conf->passphrase && os_strlen(conf->passphrase) < 64) { 1596 json_add_string_escape(buf, "pass", conf->passphrase, 1597 os_strlen(conf->passphrase)); 1598 } else if (conf->psk_set) { 1599 char psk[2 * sizeof(conf->psk) + 1]; 1600 1601 wpa_snprintf_hex(psk, sizeof(psk), 1602 conf->psk, sizeof(conf->psk)); 1603 json_add_string(buf, "psk_hex", psk); 1604 forced_memzero(psk, sizeof(psk)); 1605 } 1606 } 1607 1608 1609 const char * dpp_netrole_str(enum dpp_netrole netrole) 1610 { 1611 switch (netrole) { 1612 case DPP_NETROLE_STA: 1613 return "sta"; 1614 case DPP_NETROLE_AP: 1615 return "ap"; 1616 case DPP_NETROLE_CONFIGURATOR: 1617 return "configurator"; 1618 default: 1619 return "??"; 1620 } 1621 } 1622 1623 1624 static bool dpp_supports_curve(const char *curve, struct dpp_bootstrap_info *bi) 1625 { 1626 enum dpp_bootstrap_supported_curves idx; 1627 1628 if (!bi || !bi->supported_curves) 1629 return true; /* no support indication available */ 1630 1631 if (os_strcmp(curve, "prime256v1") == 0) 1632 idx = DPP_BOOTSTRAP_CURVE_P_256; 1633 else if (os_strcmp(curve, "secp384r1") == 0) 1634 idx = DPP_BOOTSTRAP_CURVE_P_384; 1635 else if (os_strcmp(curve, "secp521r1") == 0) 1636 idx = DPP_BOOTSTRAP_CURVE_P_521; 1637 else if (os_strcmp(curve, "brainpoolP256r1") == 0) 1638 idx = DPP_BOOTSTRAP_CURVE_BP_256; 1639 else if (os_strcmp(curve, "brainpoolP384r1") == 0) 1640 idx = DPP_BOOTSTRAP_CURVE_BP_384; 1641 else if (os_strcmp(curve, "brainpoolP512r1") == 0) 1642 idx = DPP_BOOTSTRAP_CURVE_BP_512; 1643 else 1644 return true; 1645 1646 return bi->supported_curves & BIT(idx); 1647 } 1648 1649 1650 static struct wpabuf * 1651 dpp_build_conf_obj_dpp(struct dpp_authentication *auth, 1652 struct dpp_configuration *conf) 1653 { 1654 struct wpabuf *buf = NULL; 1655 char *signed_conn = NULL; 1656 size_t tailroom; 1657 const struct dpp_curve_params *curve; /* C-sign-key curve */ 1658 const struct dpp_curve_params *nak_curve; /* netAccessKey curve */ 1659 struct wpabuf *dppcon = NULL; 1660 size_t extra_len = 1000; 1661 int incl_legacy; 1662 enum dpp_akm akm; 1663 const char *akm_str; 1664 1665 if (!auth->conf) { 1666 wpa_printf(MSG_INFO, 1667 "DPP: No configurator specified - cannot generate DPP config object"); 1668 goto fail; 1669 } 1670 curve = auth->conf->curve; 1671 if (dpp_akm_dpp(conf->akm) && 1672 !dpp_supports_curve(curve->name, auth->peer_bi)) { 1673 wpa_printf(MSG_DEBUG, 1674 "DPP: Enrollee does not support C-sign-key curve (%s) - cannot generate config object", 1675 curve->name); 1676 goto fail; 1677 } 1678 if (auth->new_curve && auth->new_key_received) 1679 nak_curve = auth->new_curve; 1680 else 1681 nak_curve = auth->curve; 1682 if (!dpp_supports_curve(nak_curve->name, auth->peer_bi)) { 1683 wpa_printf(MSG_DEBUG, 1684 "DPP: Enrollee does not support netAccessKey curve (%s) - cannot generate config object", 1685 nak_curve->name); 1686 goto fail; 1687 } 1688 1689 akm = conf->akm; 1690 if (dpp_akm_ver2(akm) && auth->peer_version < 2) { 1691 wpa_printf(MSG_DEBUG, 1692 "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2"); 1693 akm = DPP_AKM_DPP; 1694 } 1695 1696 #ifdef CONFIG_TESTING_OPTIONS 1697 if (auth->groups_override) 1698 extra_len += os_strlen(auth->groups_override); 1699 #endif /* CONFIG_TESTING_OPTIONS */ 1700 1701 if (conf->group_id) 1702 extra_len += os_strlen(conf->group_id); 1703 1704 /* Connector (JSON dppCon object) */ 1705 dppcon = wpabuf_alloc(extra_len + 2 * nak_curve->prime_len * 4 / 3); 1706 if (!dppcon) 1707 goto fail; 1708 #ifdef CONFIG_TESTING_OPTIONS 1709 if (auth->groups_override) { 1710 wpabuf_put_u8(dppcon, '{'); 1711 if (auth->groups_override) { 1712 wpa_printf(MSG_DEBUG, 1713 "DPP: TESTING - groups override: '%s'", 1714 auth->groups_override); 1715 wpabuf_put_str(dppcon, "\"groups\":"); 1716 wpabuf_put_str(dppcon, auth->groups_override); 1717 json_value_sep(dppcon); 1718 } 1719 goto skip_groups; 1720 } 1721 #endif /* CONFIG_TESTING_OPTIONS */ 1722 json_start_object(dppcon, NULL); 1723 json_start_array(dppcon, "groups"); 1724 json_start_object(dppcon, NULL); 1725 json_add_string(dppcon, "groupId", 1726 conf->group_id ? conf->group_id : "*"); 1727 json_value_sep(dppcon); 1728 json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole)); 1729 json_end_object(dppcon); 1730 json_end_array(dppcon); 1731 json_value_sep(dppcon); 1732 #ifdef CONFIG_TESTING_OPTIONS 1733 skip_groups: 1734 #endif /* CONFIG_TESTING_OPTIONS */ 1735 if (!auth->peer_protocol_key) { 1736 wpa_printf(MSG_DEBUG, 1737 "DPP: No peer protocol key available to build netAccessKey JWK"); 1738 goto fail; 1739 } 1740 #ifdef CONFIG_DPP3 1741 if (auth->conf->net_access_key_curve && 1742 auth->curve != auth->conf->net_access_key_curve && 1743 !auth->new_key_received) { 1744 if (!dpp_supports_curve(auth->conf->net_access_key_curve->name, 1745 auth->peer_bi)) { 1746 wpa_printf(MSG_DEBUG, 1747 "DPP: Enrollee does not support the required netAccessKey curve (%s) - cannot generate config object", 1748 auth->conf->net_access_key_curve->name); 1749 goto fail; 1750 } 1751 wpa_printf(MSG_DEBUG, 1752 "DPP: Peer protocol key curve (%s) does not match the required netAccessKey curve (%s) - %s", 1753 auth->curve->name, 1754 auth->conf->net_access_key_curve->name, 1755 auth->waiting_new_key ? 1756 "the required key not received" : 1757 "request a new key"); 1758 if (auth->waiting_new_key) 1759 auth->waiting_new_key = false; /* failed */ 1760 else 1761 auth->waiting_new_key = true; 1762 goto fail; 1763 } 1764 #endif /* CONFIG_DPP3 */ 1765 if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, 1766 nak_curve) < 0) { 1767 wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); 1768 goto fail; 1769 } 1770 if (conf->netaccesskey_expiry) { 1771 struct os_tm tm; 1772 char expiry[30]; 1773 1774 if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) { 1775 wpa_printf(MSG_DEBUG, 1776 "DPP: Failed to generate expiry string"); 1777 goto fail; 1778 } 1779 os_snprintf(expiry, sizeof(expiry), 1780 "%04u-%02u-%02uT%02u:%02u:%02uZ", 1781 tm.year, tm.month, tm.day, 1782 tm.hour, tm.min, tm.sec); 1783 json_value_sep(dppcon); 1784 json_add_string(dppcon, "expiry", expiry); 1785 } 1786 #ifdef CONFIG_DPP3 1787 json_value_sep(dppcon); 1788 json_add_int(dppcon, "version", auth->peer_version); 1789 #endif /* CONFIG_DPP3 */ 1790 json_end_object(dppcon); 1791 wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", 1792 (const char *) wpabuf_head(dppcon)); 1793 1794 signed_conn = dpp_sign_connector(auth->conf, dppcon); 1795 if (!signed_conn) 1796 goto fail; 1797 1798 incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm); 1799 tailroom = 1000; 1800 tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid); 1801 tailroom += os_strlen(signed_conn); 1802 if (incl_legacy) 1803 tailroom += 1000; 1804 if (akm == DPP_AKM_DOT1X) { 1805 if (auth->certbag) 1806 tailroom += 2 * wpabuf_len(auth->certbag); 1807 if (auth->cacert) 1808 tailroom += 2 * wpabuf_len(auth->cacert); 1809 if (auth->trusted_eap_server_name) 1810 tailroom += os_strlen(auth->trusted_eap_server_name); 1811 tailroom += 1000; 1812 } 1813 if (conf->extra_name && conf->extra_value) 1814 tailroom += 10 + os_strlen(conf->extra_name) + 1815 os_strlen(conf->extra_value); 1816 buf = dpp_build_conf_start(auth, conf, tailroom); 1817 if (!buf) 1818 goto fail; 1819 1820 if (auth->akm_use_selector && dpp_akm_ver2(akm)) 1821 akm_str = dpp_akm_selector_str(akm); 1822 else 1823 akm_str = dpp_akm_str(akm); 1824 json_start_object(buf, "cred"); 1825 json_add_string(buf, "akm", akm_str); 1826 json_value_sep(buf); 1827 if (incl_legacy) { 1828 dpp_build_legacy_cred_params(buf, conf); 1829 json_value_sep(buf); 1830 } 1831 if (akm == DPP_AKM_DOT1X) { 1832 json_start_object(buf, "entCreds"); 1833 if (!auth->certbag) 1834 goto fail; 1835 json_add_base64(buf, "certBag", wpabuf_head(auth->certbag), 1836 wpabuf_len(auth->certbag)); 1837 if (auth->cacert) { 1838 json_value_sep(buf); 1839 json_add_base64(buf, "caCert", 1840 wpabuf_head(auth->cacert), 1841 wpabuf_len(auth->cacert)); 1842 } 1843 if (auth->trusted_eap_server_name) { 1844 json_value_sep(buf); 1845 json_add_string(buf, "trustedEapServerName", 1846 auth->trusted_eap_server_name); 1847 } 1848 json_value_sep(buf); 1849 json_start_array(buf, "eapMethods"); 1850 wpabuf_printf(buf, "%d", EAP_TYPE_TLS); 1851 json_end_array(buf); 1852 json_end_object(buf); 1853 json_value_sep(buf); 1854 } 1855 wpabuf_put_str(buf, "\"signedConnector\":\""); 1856 wpabuf_put_str(buf, signed_conn); 1857 wpabuf_put_str(buf, "\""); 1858 json_value_sep(buf); 1859 if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid, 1860 curve) < 0) { 1861 wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK"); 1862 goto fail; 1863 } 1864 #ifdef CONFIG_DPP2 1865 if (auth->peer_version >= 2 && auth->conf->pp_key) { 1866 json_value_sep(buf); 1867 if (dpp_build_jwk(buf, "ppKey", auth->conf->pp_key, NULL, 1868 curve) < 0) { 1869 wpa_printf(MSG_DEBUG, "DPP: Failed to build ppKey JWK"); 1870 goto fail; 1871 } 1872 } 1873 #endif /* CONFIG_DPP2 */ 1874 1875 json_end_object(buf); 1876 if (conf->extra_name && conf->extra_value) { 1877 json_value_sep(buf); 1878 wpabuf_printf(buf, "\"%s\":%s", conf->extra_name, 1879 conf->extra_value); 1880 } 1881 json_end_object(buf); 1882 1883 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object", 1884 wpabuf_head(buf), wpabuf_len(buf)); 1885 1886 #ifdef CONFIG_DPP3 1887 if (!auth->conf->net_access_key_curve) { 1888 /* All netAccessKey values used in the network will have to be 1889 * from the same curve for network introduction to work, so 1890 * hardcode the first used netAccessKey curve for consecutive 1891 * operations if there was no explicit configuration of which 1892 * curve to use. */ 1893 wpa_printf(MSG_DEBUG, 1894 "DPP: Update Configurator to require netAccessKey curve %s based on first provisioning", 1895 nak_curve->name); 1896 auth->conf->net_access_key_curve = nak_curve; 1897 } 1898 #endif /* CONFIG_DPP3 */ 1899 1900 out: 1901 os_free(signed_conn); 1902 wpabuf_free(dppcon); 1903 return buf; 1904 fail: 1905 wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object"); 1906 wpabuf_free(buf); 1907 buf = NULL; 1908 goto out; 1909 } 1910 1911 1912 static struct wpabuf * 1913 dpp_build_conf_obj_legacy(struct dpp_authentication *auth, 1914 struct dpp_configuration *conf) 1915 { 1916 struct wpabuf *buf; 1917 const char *akm_str; 1918 size_t len = 1000; 1919 1920 if (conf->extra_name && conf->extra_value) 1921 len += 10 + os_strlen(conf->extra_name) + 1922 os_strlen(conf->extra_value); 1923 buf = dpp_build_conf_start(auth, conf, len); 1924 if (!buf) 1925 return NULL; 1926 1927 if (auth->akm_use_selector && dpp_akm_ver2(conf->akm)) 1928 akm_str = dpp_akm_selector_str(conf->akm); 1929 else 1930 akm_str = dpp_akm_str(conf->akm); 1931 json_start_object(buf, "cred"); 1932 json_add_string(buf, "akm", akm_str); 1933 json_value_sep(buf); 1934 dpp_build_legacy_cred_params(buf, conf); 1935 json_end_object(buf); 1936 if (conf->extra_name && conf->extra_value) { 1937 json_value_sep(buf); 1938 wpabuf_printf(buf, "\"%s\":%s", conf->extra_name, 1939 conf->extra_value); 1940 } 1941 json_end_object(buf); 1942 1943 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)", 1944 wpabuf_head(buf), wpabuf_len(buf)); 1945 1946 return buf; 1947 } 1948 1949 1950 static int dpp_get_peer_bi_id(struct dpp_authentication *auth) 1951 { 1952 struct dpp_bootstrap_info *bi; 1953 1954 if (auth->peer_bi) 1955 return auth->peer_bi->id; 1956 if (auth->tmp_peer_bi) 1957 return auth->tmp_peer_bi->id; 1958 1959 bi = os_zalloc(sizeof(*bi)); 1960 if (!bi) 1961 return -1; 1962 bi->id = dpp_next_id(auth->global); 1963 dl_list_add(&auth->global->bootstrap, &bi->list); 1964 auth->tmp_peer_bi = bi; 1965 return bi->id; 1966 } 1967 1968 1969 static struct wpabuf * 1970 dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, 1971 int idx, bool cert_req) 1972 { 1973 struct dpp_configuration *conf = NULL; 1974 1975 #ifdef CONFIG_TESTING_OPTIONS 1976 if (auth->config_obj_override) { 1977 if (idx != 0) 1978 return NULL; 1979 wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override"); 1980 return wpabuf_alloc_copy(auth->config_obj_override, 1981 os_strlen(auth->config_obj_override)); 1982 } 1983 #endif /* CONFIG_TESTING_OPTIONS */ 1984 1985 if (idx == 0) { 1986 if (netrole == DPP_NETROLE_STA) 1987 conf = auth->conf_sta; 1988 else if (netrole == DPP_NETROLE_AP) 1989 conf = auth->conf_ap; 1990 } else if (idx == 1) { 1991 if (netrole == DPP_NETROLE_STA) 1992 conf = auth->conf2_sta; 1993 else if (netrole == DPP_NETROLE_AP) 1994 conf = auth->conf2_ap; 1995 } 1996 if (!conf) { 1997 if (idx == 0) { 1998 if (auth->use_config_query) { 1999 wpa_printf(MSG_DEBUG, 2000 "DPP: No configuration available for Enrollee(%s) - waiting for configuration", 2001 dpp_netrole_str(netrole)); 2002 auth->waiting_config = true; 2003 dpp_get_peer_bi_id(auth); 2004 return NULL; 2005 } 2006 wpa_printf(MSG_DEBUG, 2007 "DPP: No configuration available for Enrollee(%s) - reject configuration request", 2008 dpp_netrole_str(netrole)); 2009 } 2010 return NULL; 2011 } 2012 2013 if (conf->akm == DPP_AKM_DOT1X) { 2014 if (!auth->conf) { 2015 wpa_printf(MSG_DEBUG, 2016 "DPP: No Configurator data available"); 2017 return NULL; 2018 } 2019 if (!cert_req && !auth->certbag) { 2020 wpa_printf(MSG_DEBUG, 2021 "DPP: No certificate data available for dot1x configuration"); 2022 return NULL; 2023 } 2024 return dpp_build_conf_obj_dpp(auth, conf); 2025 } 2026 if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf)) 2027 return dpp_build_conf_obj_dpp(auth, conf); 2028 return dpp_build_conf_obj_legacy(auth, conf); 2029 } 2030 2031 2032 struct wpabuf * 2033 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, 2034 u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req) 2035 { 2036 struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL, *pc = NULL; 2037 size_t clear_len, attr_len; 2038 struct wpabuf *clear = NULL, *msg = NULL; 2039 u8 *wrapped; 2040 const u8 *addr[1]; 2041 size_t len[1]; 2042 enum dpp_status_error status; 2043 2044 if (auth->force_conf_resp_status != DPP_STATUS_OK) { 2045 status = auth->force_conf_resp_status; 2046 goto forced_status; 2047 } 2048 2049 if (netrole == DPP_NETROLE_CONFIGURATOR) { 2050 #ifdef CONFIG_DPP2 2051 env_data = dpp_build_enveloped_data(auth); 2052 #endif /* CONFIG_DPP2 */ 2053 } else { 2054 conf = dpp_build_conf_obj(auth, netrole, 0, cert_req); 2055 if (conf) { 2056 wpa_hexdump_ascii(MSG_DEBUG, 2057 "DPP: configurationObject JSON", 2058 wpabuf_head(conf), wpabuf_len(conf)); 2059 conf2 = dpp_build_conf_obj(auth, netrole, 1, cert_req); 2060 } 2061 } 2062 2063 if (!conf && auth->waiting_config) 2064 return NULL; 2065 if (conf || env_data) 2066 status = DPP_STATUS_OK; 2067 else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta && 2068 auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr) 2069 status = DPP_STATUS_CSR_NEEDED; 2070 #ifdef CONFIG_DPP3 2071 else if (auth->waiting_new_key) 2072 status = DPP_STATUS_NEW_KEY_NEEDED; 2073 #endif /* CONFIG_DPP3 */ 2074 else 2075 status = DPP_STATUS_CONFIGURE_FAILURE; 2076 forced_status: 2077 auth->conf_resp_status = status; 2078 2079 /* { E-nonce, configurationObject[, sendConnStatus]}ke */ 2080 clear_len = 4 + e_nonce_len; 2081 if (conf) 2082 clear_len += 4 + wpabuf_len(conf); 2083 if (conf2) 2084 clear_len += 4 + wpabuf_len(conf2); 2085 if (env_data) 2086 clear_len += 4 + wpabuf_len(env_data); 2087 if (auth->peer_version >= 2 && auth->send_conn_status && 2088 netrole == DPP_NETROLE_STA) 2089 clear_len += 4; 2090 if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && 2091 auth->conf_sta->csrattrs) 2092 clear_len += 4 + os_strlen(auth->conf_sta->csrattrs); 2093 #ifdef CONFIG_DPP3 2094 if (status == DPP_STATUS_NEW_KEY_NEEDED) { 2095 struct crypto_ec_key *new_pc; 2096 2097 clear_len += 6; /* Finite Cyclic Group attribute */ 2098 2099 wpa_printf(MSG_DEBUG, 2100 "DPP: Generate a new own protocol key for the curve %s", 2101 auth->conf->net_access_key_curve->name); 2102 new_pc = dpp_gen_keypair(auth->conf->net_access_key_curve); 2103 if (!new_pc) { 2104 wpa_printf(MSG_DEBUG, "DPP: Failed to generate new Pc"); 2105 return NULL; 2106 } 2107 pc = crypto_ec_key_get_pubkey_point(new_pc, 0); 2108 if (!pc) { 2109 crypto_ec_key_deinit(new_pc); 2110 return NULL; 2111 } 2112 crypto_ec_key_deinit(auth->own_protocol_key); 2113 auth->own_protocol_key = new_pc; 2114 auth->new_curve = auth->conf->net_access_key_curve; 2115 clear_len += 4 + wpabuf_len(pc); 2116 } 2117 #endif /* CONFIG_DPP3 */ 2118 clear = wpabuf_alloc(clear_len); 2119 attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE; 2120 #ifdef CONFIG_TESTING_OPTIONS 2121 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) 2122 attr_len += 5; 2123 #endif /* CONFIG_TESTING_OPTIONS */ 2124 msg = wpabuf_alloc(attr_len); 2125 if (!clear || !msg) 2126 goto fail; 2127 2128 #ifdef CONFIG_TESTING_OPTIONS 2129 if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) { 2130 wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce"); 2131 goto skip_e_nonce; 2132 } 2133 if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) { 2134 wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch"); 2135 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 2136 wpabuf_put_le16(clear, e_nonce_len); 2137 wpabuf_put_data(clear, e_nonce, e_nonce_len - 1); 2138 wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01); 2139 goto skip_e_nonce; 2140 } 2141 if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) { 2142 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); 2143 goto skip_wrapped_data; 2144 } 2145 #endif /* CONFIG_TESTING_OPTIONS */ 2146 2147 /* E-nonce */ 2148 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 2149 wpabuf_put_le16(clear, e_nonce_len); 2150 wpabuf_put_data(clear, e_nonce, e_nonce_len); 2151 2152 #ifdef CONFIG_TESTING_OPTIONS 2153 skip_e_nonce: 2154 if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) { 2155 wpa_printf(MSG_INFO, "DPP: TESTING - Config Object"); 2156 goto skip_config_obj; 2157 } 2158 #endif /* CONFIG_TESTING_OPTIONS */ 2159 2160 if (conf) { 2161 wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ); 2162 wpabuf_put_le16(clear, wpabuf_len(conf)); 2163 wpabuf_put_buf(clear, conf); 2164 } 2165 if (auth->peer_version >= 2 && conf2) { 2166 wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ); 2167 wpabuf_put_le16(clear, wpabuf_len(conf2)); 2168 wpabuf_put_buf(clear, conf2); 2169 } else if (conf2) { 2170 wpa_printf(MSG_DEBUG, 2171 "DPP: Second Config Object available, but peer does not support more than one"); 2172 } 2173 if (env_data) { 2174 wpabuf_put_le16(clear, DPP_ATTR_ENVELOPED_DATA); 2175 wpabuf_put_le16(clear, wpabuf_len(env_data)); 2176 wpabuf_put_buf(clear, env_data); 2177 } 2178 2179 if (auth->peer_version >= 2 && auth->send_conn_status && 2180 netrole == DPP_NETROLE_STA && status == DPP_STATUS_OK) { 2181 wpa_printf(MSG_DEBUG, "DPP: sendConnStatus"); 2182 wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS); 2183 wpabuf_put_le16(clear, 0); 2184 } 2185 2186 if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && 2187 auth->conf_sta->csrattrs) { 2188 auth->waiting_csr = true; 2189 wpa_printf(MSG_DEBUG, "DPP: CSR Attributes Request"); 2190 wpabuf_put_le16(clear, DPP_ATTR_CSR_ATTR_REQ); 2191 wpabuf_put_le16(clear, os_strlen(auth->conf_sta->csrattrs)); 2192 wpabuf_put_str(clear, auth->conf_sta->csrattrs); 2193 } 2194 2195 #ifdef CONFIG_DPP3 2196 if (status == DPP_STATUS_NEW_KEY_NEEDED && auth->conf && 2197 auth->conf->net_access_key_curve) { 2198 u16 ike_group = auth->conf->net_access_key_curve->ike_group; 2199 2200 /* Finite Cyclic Group attribute */ 2201 wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", 2202 ike_group); 2203 wpabuf_put_le16(clear, DPP_ATTR_FINITE_CYCLIC_GROUP); 2204 wpabuf_put_le16(clear, 2); 2205 wpabuf_put_le16(clear, ike_group); 2206 2207 if (pc) { 2208 wpa_printf(MSG_DEBUG, "DPP: Pc"); 2209 wpabuf_put_le16(clear, DPP_ATTR_R_PROTOCOL_KEY); 2210 wpabuf_put_le16(clear, wpabuf_len(pc)); 2211 wpabuf_put_buf(clear, pc); 2212 } 2213 } 2214 #endif /* CONFIG_DPP3 */ 2215 2216 #ifdef CONFIG_TESTING_OPTIONS 2217 skip_config_obj: 2218 if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) { 2219 wpa_printf(MSG_INFO, "DPP: TESTING - Status"); 2220 goto skip_status; 2221 } 2222 if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) { 2223 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); 2224 status = 255; 2225 } 2226 #endif /* CONFIG_TESTING_OPTIONS */ 2227 2228 /* DPP Status */ 2229 dpp_build_attr_status(msg, status); 2230 2231 #ifdef CONFIG_TESTING_OPTIONS 2232 skip_status: 2233 #endif /* CONFIG_TESTING_OPTIONS */ 2234 2235 addr[0] = wpabuf_head(msg); 2236 len[0] = wpabuf_len(msg); 2237 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); 2238 2239 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 2240 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 2241 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 2242 2243 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 2244 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 2245 wpabuf_head(clear), wpabuf_len(clear), 2246 1, addr, len, wrapped) < 0) 2247 goto fail; 2248 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 2249 wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); 2250 2251 #ifdef CONFIG_TESTING_OPTIONS 2252 if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) { 2253 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); 2254 dpp_build_attr_status(msg, DPP_STATUS_OK); 2255 } 2256 skip_wrapped_data: 2257 #endif /* CONFIG_TESTING_OPTIONS */ 2258 2259 wpa_hexdump_buf(MSG_DEBUG, 2260 "DPP: Configuration Response attributes", msg); 2261 out: 2262 wpabuf_clear_free(conf); 2263 wpabuf_clear_free(conf2); 2264 wpabuf_clear_free(env_data); 2265 wpabuf_clear_free(clear); 2266 wpabuf_free(pc); 2267 2268 return msg; 2269 fail: 2270 wpabuf_free(msg); 2271 msg = NULL; 2272 goto out; 2273 } 2274 2275 2276 struct wpabuf * 2277 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, 2278 size_t attr_len) 2279 { 2280 const u8 *wrapped_data, *e_nonce, *config_attr; 2281 u16 wrapped_data_len, e_nonce_len, config_attr_len; 2282 u8 *unwrapped = NULL; 2283 size_t unwrapped_len = 0; 2284 struct wpabuf *resp = NULL; 2285 struct json_token *root = NULL, *token; 2286 enum dpp_netrole netrole; 2287 struct wpabuf *cert_req = NULL; 2288 #ifdef CONFIG_DPP3 2289 const u8 *i_proto; 2290 u16 i_proto_len; 2291 #endif /* CONFIG_DPP3 */ 2292 2293 #ifdef CONFIG_TESTING_OPTIONS 2294 if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) { 2295 wpa_printf(MSG_INFO, 2296 "DPP: TESTING - stop at Config Request"); 2297 return NULL; 2298 } 2299 #endif /* CONFIG_TESTING_OPTIONS */ 2300 2301 if (dpp_check_attrs(attr_start, attr_len) < 0) { 2302 dpp_auth_fail(auth, "Invalid attribute in config request"); 2303 return NULL; 2304 } 2305 2306 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, 2307 &wrapped_data_len); 2308 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 2309 dpp_auth_fail(auth, 2310 "Missing or invalid required Wrapped Data attribute"); 2311 return NULL; 2312 } 2313 2314 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 2315 wrapped_data, wrapped_data_len); 2316 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 2317 unwrapped = os_malloc(unwrapped_len); 2318 if (!unwrapped) 2319 return NULL; 2320 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 2321 wrapped_data, wrapped_data_len, 2322 0, NULL, NULL, unwrapped) < 0) { 2323 dpp_auth_fail(auth, "AES-SIV decryption failed"); 2324 goto fail; 2325 } 2326 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 2327 unwrapped, unwrapped_len); 2328 2329 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 2330 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 2331 goto fail; 2332 } 2333 2334 e_nonce = dpp_get_attr(unwrapped, unwrapped_len, 2335 DPP_ATTR_ENROLLEE_NONCE, 2336 &e_nonce_len); 2337 if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { 2338 dpp_auth_fail(auth, 2339 "Missing or invalid Enrollee Nonce attribute"); 2340 goto fail; 2341 } 2342 wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); 2343 os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); 2344 2345 #ifdef CONFIG_DPP3 2346 i_proto = dpp_get_attr(unwrapped, unwrapped_len, 2347 DPP_ATTR_I_PROTOCOL_KEY, &i_proto_len); 2348 if (i_proto && !auth->waiting_new_key) { 2349 dpp_auth_fail(auth, 2350 "Enrollee included a new protocol key even though one was not expected"); 2351 goto fail; 2352 } 2353 if (i_proto) { 2354 struct crypto_ec_key *pe; 2355 u8 auth_i[DPP_MAX_HASH_LEN]; 2356 const u8 *rx_auth_i; 2357 u16 rx_auth_i_len; 2358 2359 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key (new Pe)", 2360 i_proto, i_proto_len); 2361 2362 pe = dpp_set_pubkey_point(auth->own_protocol_key, 2363 i_proto, i_proto_len); 2364 if (!pe) { 2365 dpp_auth_fail(auth, 2366 "Invalid Initiator Protocol Key (Pe)"); 2367 goto fail; 2368 } 2369 dpp_debug_print_key("New Peer Protocol Key (Pe)", pe); 2370 crypto_ec_key_deinit(auth->peer_protocol_key); 2371 auth->peer_protocol_key = pe; 2372 auth->new_key_received = true; 2373 auth->waiting_new_key = false; 2374 2375 if (dpp_derive_auth_i(auth, auth_i) < 0) 2376 goto fail; 2377 2378 rx_auth_i = dpp_get_attr(unwrapped, unwrapped_len, 2379 DPP_ATTR_I_AUTH_TAG, &rx_auth_i_len); 2380 if (!rx_auth_i) { 2381 dpp_auth_fail(auth, 2382 "Missing Initiator Authentication Tag"); 2383 goto fail; 2384 } 2385 if (rx_auth_i_len != auth->curve->hash_len || 2386 os_memcmp(rx_auth_i, auth_i, auth->curve->hash_len) != 0) { 2387 dpp_auth_fail(auth, 2388 "Mismatch in Initiator Authenticating Tag"); 2389 wpa_hexdump(MSG_DEBUG, "DPP: Received Auth-I", 2390 rx_auth_i, rx_auth_i_len); 2391 wpa_hexdump(MSG_DEBUG, "DPP: Derived Auth-I'", 2392 auth_i, auth->curve->hash_len); 2393 goto fail; 2394 } 2395 } 2396 #endif /* CONFIG_DPP3 */ 2397 2398 config_attr = dpp_get_attr(unwrapped, unwrapped_len, 2399 DPP_ATTR_CONFIG_ATTR_OBJ, 2400 &config_attr_len); 2401 if (!config_attr) { 2402 dpp_auth_fail(auth, 2403 "Missing or invalid Config Attributes attribute"); 2404 goto fail; 2405 } 2406 wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes", 2407 config_attr, config_attr_len); 2408 2409 root = json_parse((const char *) config_attr, config_attr_len); 2410 if (!root) { 2411 dpp_auth_fail(auth, "Could not parse Config Attributes"); 2412 goto fail; 2413 } 2414 2415 token = json_get_member(root, "name"); 2416 if (!token || token->type != JSON_STRING) { 2417 dpp_auth_fail(auth, "No Config Attributes - name"); 2418 goto fail; 2419 } 2420 wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string); 2421 os_free(auth->e_name); 2422 auth->e_name = os_strdup(token->string); 2423 2424 token = json_get_member(root, "wi-fi_tech"); 2425 if (!token || token->type != JSON_STRING) { 2426 dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech"); 2427 goto fail; 2428 } 2429 wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string); 2430 if (os_strcmp(token->string, "infra") != 0) { 2431 wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'", 2432 token->string); 2433 dpp_auth_fail(auth, "Unsupported wi-fi_tech"); 2434 goto fail; 2435 } 2436 2437 token = json_get_member(root, "netRole"); 2438 if (!token || token->type != JSON_STRING) { 2439 dpp_auth_fail(auth, "No Config Attributes - netRole"); 2440 goto fail; 2441 } 2442 wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string); 2443 if (os_strcmp(token->string, "sta") == 0) { 2444 netrole = DPP_NETROLE_STA; 2445 } else if (os_strcmp(token->string, "ap") == 0) { 2446 netrole = DPP_NETROLE_AP; 2447 } else if (os_strcmp(token->string, "configurator") == 0) { 2448 netrole = DPP_NETROLE_CONFIGURATOR; 2449 } else { 2450 wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'", 2451 token->string); 2452 dpp_auth_fail(auth, "Unsupported netRole"); 2453 goto fail; 2454 } 2455 auth->e_netrole = netrole; 2456 2457 token = json_get_member(root, "mudurl"); 2458 if (token && token->type == JSON_STRING) { 2459 wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string); 2460 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s", 2461 token->string); 2462 os_free(auth->e_mud_url); 2463 auth->e_mud_url = os_strdup(token->string); 2464 } 2465 2466 token = json_get_member(root, "bandSupport"); 2467 if (token && token->type == JSON_ARRAY) { 2468 int *opclass = NULL; 2469 char txt[200], *pos, *end; 2470 int i, res; 2471 2472 wpa_printf(MSG_DEBUG, "DPP: bandSupport"); 2473 token = token->child; 2474 while (token) { 2475 if (token->type != JSON_NUMBER) { 2476 wpa_printf(MSG_DEBUG, 2477 "DPP: Invalid bandSupport array member type"); 2478 } else { 2479 wpa_printf(MSG_DEBUG, 2480 "DPP: Supported global operating class: %d", 2481 token->number); 2482 int_array_add_unique(&opclass, token->number); 2483 } 2484 token = token->sibling; 2485 } 2486 2487 txt[0] = '\0'; 2488 pos = txt; 2489 end = txt + sizeof(txt); 2490 for (i = 0; opclass && opclass[i]; i++) { 2491 res = os_snprintf(pos, end - pos, "%s%d", 2492 pos == txt ? "" : ",", opclass[i]); 2493 if (os_snprintf_error(end - pos, res)) { 2494 *pos = '\0'; 2495 break; 2496 } 2497 pos += res; 2498 } 2499 os_free(auth->e_band_support); 2500 auth->e_band_support = opclass; 2501 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s", 2502 txt); 2503 } 2504 2505 #ifdef CONFIG_DPP2 2506 cert_req = json_get_member_base64(root, "pkcs10"); 2507 if (cert_req) { 2508 char *txt; 2509 int id; 2510 2511 wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req); 2512 if (dpp_validate_csr(auth, cert_req) < 0) { 2513 wpa_printf(MSG_DEBUG, "DPP: CSR is not valid"); 2514 auth->force_conf_resp_status = DPP_STATUS_CSR_BAD; 2515 goto cont; 2516 } 2517 2518 id = dpp_get_peer_bi_id(auth); 2519 if (id < 0) 2520 goto fail; 2521 2522 wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA"); 2523 txt = base64_encode_no_lf(wpabuf_head(cert_req), 2524 wpabuf_len(cert_req), NULL); 2525 if (!txt) 2526 goto fail; 2527 2528 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s", 2529 id, txt); 2530 os_free(txt); 2531 auth->waiting_csr = false; 2532 auth->waiting_cert = true; 2533 goto fail; 2534 } 2535 cont: 2536 #endif /* CONFIG_DPP2 */ 2537 2538 resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole, 2539 cert_req); 2540 2541 fail: 2542 wpabuf_free(cert_req); 2543 json_free(root); 2544 os_free(unwrapped); 2545 return resp; 2546 } 2547 2548 2549 static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, 2550 struct json_token *cred) 2551 { 2552 struct json_token *pass, *psk_hex; 2553 2554 wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential"); 2555 2556 pass = json_get_member(cred, "pass"); 2557 psk_hex = json_get_member(cred, "psk_hex"); 2558 2559 if (pass && pass->type == JSON_STRING) { 2560 size_t len = os_strlen(pass->string); 2561 2562 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase", 2563 pass->string, len); 2564 if (len < 8 || len > 63) 2565 return -1; 2566 os_strlcpy(conf->passphrase, pass->string, 2567 sizeof(conf->passphrase)); 2568 } else if (psk_hex && psk_hex->type == JSON_STRING) { 2569 if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) { 2570 wpa_printf(MSG_DEBUG, 2571 "DPP: Unexpected psk_hex with akm=sae"); 2572 return -1; 2573 } 2574 if (os_strlen(psk_hex->string) != PMK_LEN * 2 || 2575 hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) { 2576 wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding"); 2577 return -1; 2578 } 2579 wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK", 2580 conf->psk, PMK_LEN); 2581 conf->psk_set = 1; 2582 } else { 2583 wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found"); 2584 return -1; 2585 } 2586 2587 if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) { 2588 wpa_printf(MSG_DEBUG, "DPP: No pass for sae found"); 2589 return -1; 2590 } 2591 2592 return 0; 2593 } 2594 2595 2596 struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk, 2597 const struct dpp_curve_params **key_curve) 2598 { 2599 struct json_token *token; 2600 const struct dpp_curve_params *curve; 2601 struct wpabuf *x = NULL, *y = NULL; 2602 struct crypto_ec_key *key = NULL; 2603 2604 token = json_get_member(jwk, "kty"); 2605 if (!token || token->type != JSON_STRING) { 2606 wpa_printf(MSG_DEBUG, "DPP: No kty in JWK"); 2607 goto fail; 2608 } 2609 if (os_strcmp(token->string, "EC") != 0) { 2610 wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'", 2611 token->string); 2612 goto fail; 2613 } 2614 2615 token = json_get_member(jwk, "crv"); 2616 if (!token || token->type != JSON_STRING) { 2617 wpa_printf(MSG_DEBUG, "DPP: No crv in JWK"); 2618 goto fail; 2619 } 2620 curve = dpp_get_curve_jwk_crv(token->string); 2621 if (!curve) { 2622 wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'", 2623 token->string); 2624 goto fail; 2625 } 2626 2627 x = json_get_member_base64url(jwk, "x"); 2628 if (!x) { 2629 wpa_printf(MSG_DEBUG, "DPP: No x in JWK"); 2630 goto fail; 2631 } 2632 wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x); 2633 if (wpabuf_len(x) != curve->prime_len) { 2634 wpa_printf(MSG_DEBUG, 2635 "DPP: Unexpected JWK x length %u (expected %u for curve %s)", 2636 (unsigned int) wpabuf_len(x), 2637 (unsigned int) curve->prime_len, curve->name); 2638 goto fail; 2639 } 2640 2641 y = json_get_member_base64url(jwk, "y"); 2642 if (!y) { 2643 wpa_printf(MSG_DEBUG, "DPP: No y in JWK"); 2644 goto fail; 2645 } 2646 wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y); 2647 if (wpabuf_len(y) != curve->prime_len) { 2648 wpa_printf(MSG_DEBUG, 2649 "DPP: Unexpected JWK y length %u (expected %u for curve %s)", 2650 (unsigned int) wpabuf_len(y), 2651 (unsigned int) curve->prime_len, curve->name); 2652 goto fail; 2653 } 2654 2655 key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x), 2656 wpabuf_head(y), wpabuf_len(x)); 2657 if (!key) 2658 goto fail; 2659 2660 *key_curve = curve; 2661 2662 fail: 2663 wpabuf_free(x); 2664 wpabuf_free(y); 2665 2666 return key; 2667 } 2668 2669 2670 int dpp_key_expired(const char *timestamp, os_time_t *expiry) 2671 { 2672 struct os_time now; 2673 unsigned int year, month, day, hour, min, sec; 2674 os_time_t utime; 2675 const char *pos; 2676 2677 /* ISO 8601 date and time: 2678 * <date>T<time> 2679 * YYYY-MM-DDTHH:MM:SSZ 2680 * YYYY-MM-DDTHH:MM:SS+03:00 2681 */ 2682 if (os_strlen(timestamp) < 19) { 2683 wpa_printf(MSG_DEBUG, 2684 "DPP: Too short timestamp - assume expired key"); 2685 return 1; 2686 } 2687 if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u", 2688 &year, &month, &day, &hour, &min, &sec) != 6) { 2689 wpa_printf(MSG_DEBUG, 2690 "DPP: Failed to parse expiration day - assume expired key"); 2691 return 1; 2692 } 2693 2694 if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) { 2695 wpa_printf(MSG_DEBUG, 2696 "DPP: Invalid date/time information - assume expired key"); 2697 return 1; 2698 } 2699 2700 pos = timestamp + 19; 2701 if (*pos == 'Z' || *pos == '\0') { 2702 /* In UTC - no need to adjust */ 2703 } else if (*pos == '-' || *pos == '+') { 2704 int items; 2705 2706 /* Adjust local time to UTC */ 2707 items = sscanf(pos + 1, "%02u:%02u", &hour, &min); 2708 if (items < 1) { 2709 wpa_printf(MSG_DEBUG, 2710 "DPP: Invalid time zone designator (%s) - assume expired key", 2711 pos); 2712 return 1; 2713 } 2714 if (*pos == '-') 2715 utime += 3600 * hour; 2716 if (*pos == '+') 2717 utime -= 3600 * hour; 2718 if (items > 1) { 2719 if (*pos == '-') 2720 utime += 60 * min; 2721 if (*pos == '+') 2722 utime -= 60 * min; 2723 } 2724 } else { 2725 wpa_printf(MSG_DEBUG, 2726 "DPP: Invalid time zone designator (%s) - assume expired key", 2727 pos); 2728 return 1; 2729 } 2730 if (expiry) 2731 *expiry = utime; 2732 2733 if (os_get_time(&now) < 0) { 2734 wpa_printf(MSG_DEBUG, 2735 "DPP: Cannot get current time - assume expired key"); 2736 return 1; 2737 } 2738 2739 if (now.sec > utime) { 2740 wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)", 2741 utime, now.sec); 2742 return 1; 2743 } 2744 2745 return 0; 2746 } 2747 2748 2749 static int dpp_parse_connector(struct dpp_authentication *auth, 2750 struct dpp_config_obj *conf, 2751 const unsigned char *payload, 2752 u16 payload_len) 2753 { 2754 struct json_token *root, *groups, *netkey, *token; 2755 int ret = -1; 2756 struct crypto_ec_key *key = NULL; 2757 const struct dpp_curve_params *curve; 2758 unsigned int rules = 0; 2759 2760 root = json_parse((const char *) payload, payload_len); 2761 if (!root) { 2762 wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed"); 2763 goto fail; 2764 } 2765 2766 groups = json_get_member(root, "groups"); 2767 if (!groups || groups->type != JSON_ARRAY) { 2768 wpa_printf(MSG_DEBUG, "DPP: No groups array found"); 2769 goto skip_groups; 2770 } 2771 for (token = groups->child; token; token = token->sibling) { 2772 struct json_token *id, *role; 2773 2774 id = json_get_member(token, "groupId"); 2775 if (!id || id->type != JSON_STRING) { 2776 wpa_printf(MSG_DEBUG, "DPP: Missing groupId string"); 2777 goto fail; 2778 } 2779 2780 role = json_get_member(token, "netRole"); 2781 if (!role || role->type != JSON_STRING) { 2782 wpa_printf(MSG_DEBUG, "DPP: Missing netRole string"); 2783 goto fail; 2784 } 2785 wpa_printf(MSG_DEBUG, 2786 "DPP: connector group: groupId='%s' netRole='%s'", 2787 id->string, role->string); 2788 rules++; 2789 } 2790 skip_groups: 2791 2792 if (!rules) { 2793 wpa_printf(MSG_DEBUG, 2794 "DPP: Connector includes no groups"); 2795 goto fail; 2796 } 2797 2798 token = json_get_member(root, "expiry"); 2799 if (!token || token->type != JSON_STRING) { 2800 wpa_printf(MSG_DEBUG, 2801 "DPP: No expiry string found - connector does not expire"); 2802 } else { 2803 wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string); 2804 if (dpp_key_expired(token->string, 2805 &auth->net_access_key_expiry)) { 2806 wpa_printf(MSG_DEBUG, 2807 "DPP: Connector (netAccessKey) has expired"); 2808 goto fail; 2809 } 2810 } 2811 2812 netkey = json_get_member(root, "netAccessKey"); 2813 if (!netkey || netkey->type != JSON_OBJECT) { 2814 wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found"); 2815 goto fail; 2816 } 2817 2818 key = dpp_parse_jwk(netkey, &curve); 2819 if (!key) 2820 goto fail; 2821 dpp_debug_print_key("DPP: Received netAccessKey", key); 2822 2823 if (crypto_ec_key_cmp(key, auth->own_protocol_key)) { 2824 wpa_printf(MSG_DEBUG, 2825 "DPP: netAccessKey in connector does not match own protocol key"); 2826 #ifdef CONFIG_TESTING_OPTIONS 2827 if (auth->ignore_netaccesskey_mismatch) { 2828 wpa_printf(MSG_DEBUG, 2829 "DPP: TESTING - skip netAccessKey mismatch"); 2830 } else { 2831 goto fail; 2832 } 2833 #else /* CONFIG_TESTING_OPTIONS */ 2834 goto fail; 2835 #endif /* CONFIG_TESTING_OPTIONS */ 2836 } 2837 2838 ret = 0; 2839 fail: 2840 crypto_ec_key_deinit(key); 2841 json_free(root); 2842 return ret; 2843 } 2844 2845 2846 static void dpp_copy_csign(struct dpp_config_obj *conf, 2847 struct crypto_ec_key *csign) 2848 { 2849 struct wpabuf *c_sign_key; 2850 2851 c_sign_key = crypto_ec_key_get_subject_public_key(csign); 2852 if (!c_sign_key) 2853 return; 2854 2855 wpabuf_free(conf->c_sign_key); 2856 conf->c_sign_key = c_sign_key; 2857 } 2858 2859 2860 static void dpp_copy_ppkey(struct dpp_config_obj *conf, 2861 struct crypto_ec_key *ppkey) 2862 { 2863 struct wpabuf *pp_key; 2864 2865 pp_key = crypto_ec_key_get_subject_public_key(ppkey); 2866 if (!pp_key) 2867 return; 2868 2869 wpabuf_free(conf->pp_key); 2870 conf->pp_key = pp_key; 2871 } 2872 2873 2874 static void dpp_copy_netaccesskey(struct dpp_authentication *auth, 2875 struct dpp_config_obj *conf) 2876 { 2877 struct wpabuf *net_access_key; 2878 struct crypto_ec_key *own_key; 2879 2880 own_key = auth->own_protocol_key; 2881 #ifdef CONFIG_DPP2 2882 if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY && 2883 auth->reconfig_old_protocol_key) 2884 own_key = auth->reconfig_old_protocol_key; 2885 #endif /* CONFIG_DPP2 */ 2886 2887 net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true); 2888 if (!net_access_key) 2889 return; 2890 2891 wpabuf_free(auth->net_access_key); 2892 auth->net_access_key = net_access_key; 2893 } 2894 2895 2896 static int dpp_parse_cred_dpp(struct dpp_authentication *auth, 2897 struct dpp_config_obj *conf, 2898 struct json_token *cred) 2899 { 2900 struct dpp_signed_connector_info info; 2901 struct json_token *token, *csign, *ppkey; 2902 int ret = -1; 2903 struct crypto_ec_key *csign_pub = NULL, *pp_pub = NULL; 2904 const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL; 2905 const char *signed_connector; 2906 2907 os_memset(&info, 0, sizeof(info)); 2908 2909 if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) { 2910 wpa_printf(MSG_DEBUG, 2911 "DPP: Legacy credential included in Connector credential"); 2912 if (dpp_parse_cred_legacy(conf, cred) < 0) 2913 return -1; 2914 } 2915 2916 wpa_printf(MSG_DEBUG, "DPP: Connector credential"); 2917 2918 csign = json_get_member(cred, "csign"); 2919 if (!csign || csign->type != JSON_OBJECT) { 2920 wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON"); 2921 goto fail; 2922 } 2923 2924 csign_pub = dpp_parse_jwk(csign, &key_curve); 2925 if (!csign_pub) { 2926 wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK"); 2927 goto fail; 2928 } 2929 dpp_debug_print_key("DPP: Received C-sign-key", csign_pub); 2930 2931 ppkey = json_get_member(cred, "ppKey"); 2932 if (ppkey && ppkey->type == JSON_OBJECT) { 2933 pp_pub = dpp_parse_jwk(ppkey, &pp_curve); 2934 if (!pp_pub) { 2935 wpa_printf(MSG_DEBUG, "DPP: Failed to parse ppKey JWK"); 2936 goto fail; 2937 } 2938 dpp_debug_print_key("DPP: Received ppKey", pp_pub); 2939 if (key_curve != pp_curve) { 2940 wpa_printf(MSG_DEBUG, 2941 "DPP: C-sign-key and ppKey do not use the same curve"); 2942 goto fail; 2943 } 2944 } 2945 2946 token = json_get_member(cred, "signedConnector"); 2947 if (!token || token->type != JSON_STRING) { 2948 wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found"); 2949 goto fail; 2950 } 2951 wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector", 2952 token->string, os_strlen(token->string)); 2953 signed_connector = token->string; 2954 2955 if (os_strchr(signed_connector, '"') || 2956 os_strchr(signed_connector, '\n')) { 2957 wpa_printf(MSG_DEBUG, 2958 "DPP: Unexpected character in signedConnector"); 2959 goto fail; 2960 } 2961 2962 if (dpp_process_signed_connector(&info, csign_pub, 2963 signed_connector) != DPP_STATUS_OK) 2964 goto fail; 2965 2966 if (dpp_parse_connector(auth, conf, 2967 info.payload, info.payload_len) < 0) { 2968 wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector"); 2969 goto fail; 2970 } 2971 2972 os_free(conf->connector); 2973 conf->connector = os_strdup(signed_connector); 2974 2975 dpp_copy_csign(conf, csign_pub); 2976 if (pp_pub) 2977 dpp_copy_ppkey(conf, pp_pub); 2978 if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2) 2979 dpp_copy_netaccesskey(auth, conf); 2980 2981 ret = 0; 2982 fail: 2983 crypto_ec_key_deinit(csign_pub); 2984 crypto_ec_key_deinit(pp_pub); 2985 os_free(info.payload); 2986 return ret; 2987 } 2988 2989 2990 #ifdef CONFIG_DPP2 2991 static int dpp_parse_cred_dot1x(struct dpp_authentication *auth, 2992 struct dpp_config_obj *conf, 2993 struct json_token *cred) 2994 { 2995 struct json_token *ent, *name; 2996 2997 ent = json_get_member(cred, "entCreds"); 2998 if (!ent || ent->type != JSON_OBJECT) { 2999 dpp_auth_fail(auth, "No entCreds in JSON"); 3000 return -1; 3001 } 3002 3003 conf->certbag = json_get_member_base64(ent, "certBag"); 3004 if (!conf->certbag) { 3005 dpp_auth_fail(auth, "No certBag in JSON"); 3006 return -1; 3007 } 3008 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag); 3009 conf->certs = crypto_pkcs7_get_certificates(conf->certbag); 3010 if (!conf->certs) { 3011 dpp_auth_fail(auth, "No certificates in certBag"); 3012 return -1; 3013 } 3014 3015 conf->cacert = json_get_member_base64(ent, "caCert"); 3016 if (conf->cacert) 3017 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert", 3018 conf->cacert); 3019 3020 name = json_get_member(ent, "trustedEapServerName"); 3021 if (name && 3022 (name->type != JSON_STRING || 3023 has_ctrl_char((const u8 *) name->string, 3024 os_strlen(name->string)))) { 3025 dpp_auth_fail(auth, 3026 "Invalid trustedEapServerName type in JSON"); 3027 return -1; 3028 } 3029 if (name && name->string) { 3030 wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s", 3031 name->string); 3032 conf->server_name = os_strdup(name->string); 3033 if (!conf->server_name) 3034 return -1; 3035 } 3036 3037 return 0; 3038 } 3039 #endif /* CONFIG_DPP2 */ 3040 3041 3042 const char * dpp_akm_str(enum dpp_akm akm) 3043 { 3044 switch (akm) { 3045 case DPP_AKM_DPP: 3046 return "dpp"; 3047 case DPP_AKM_PSK: 3048 return "psk"; 3049 case DPP_AKM_SAE: 3050 return "sae"; 3051 case DPP_AKM_PSK_SAE: 3052 return "psk+sae"; 3053 case DPP_AKM_SAE_DPP: 3054 return "dpp+sae"; 3055 case DPP_AKM_PSK_SAE_DPP: 3056 return "dpp+psk+sae"; 3057 case DPP_AKM_DOT1X: 3058 return "dot1x"; 3059 default: 3060 return "??"; 3061 } 3062 } 3063 3064 3065 const char * dpp_akm_selector_str(enum dpp_akm akm) 3066 { 3067 switch (akm) { 3068 case DPP_AKM_DPP: 3069 return "506F9A02"; 3070 case DPP_AKM_PSK: 3071 return "000FAC02+000FAC06"; 3072 case DPP_AKM_SAE: 3073 return "000FAC08"; 3074 case DPP_AKM_PSK_SAE: 3075 return "000FAC02+000FAC06+000FAC08"; 3076 case DPP_AKM_SAE_DPP: 3077 return "506F9A02+000FAC08"; 3078 case DPP_AKM_PSK_SAE_DPP: 3079 return "506F9A02+000FAC08+000FAC02+000FAC06"; 3080 case DPP_AKM_DOT1X: 3081 return "000FAC01+000FAC05"; 3082 default: 3083 return "??"; 3084 } 3085 } 3086 3087 3088 static enum dpp_akm dpp_akm_from_str(const char *akm) 3089 { 3090 const char *pos; 3091 int dpp = 0, psk = 0, sae = 0, dot1x = 0; 3092 3093 if (os_strcmp(akm, "psk") == 0) 3094 return DPP_AKM_PSK; 3095 if (os_strcmp(akm, "sae") == 0) 3096 return DPP_AKM_SAE; 3097 if (os_strcmp(akm, "psk+sae") == 0) 3098 return DPP_AKM_PSK_SAE; 3099 if (os_strcmp(akm, "dpp") == 0) 3100 return DPP_AKM_DPP; 3101 if (os_strcmp(akm, "dpp+sae") == 0) 3102 return DPP_AKM_SAE_DPP; 3103 if (os_strcmp(akm, "dpp+psk+sae") == 0) 3104 return DPP_AKM_PSK_SAE_DPP; 3105 if (os_strcmp(akm, "dot1x") == 0) 3106 return DPP_AKM_DOT1X; 3107 3108 pos = akm; 3109 while (*pos) { 3110 if (os_strlen(pos) < 8) 3111 break; 3112 if (os_strncasecmp(pos, "506F9A02", 8) == 0) 3113 dpp = 1; 3114 else if (os_strncasecmp(pos, "000FAC02", 8) == 0) 3115 psk = 1; 3116 else if (os_strncasecmp(pos, "000FAC06", 8) == 0) 3117 psk = 1; 3118 else if (os_strncasecmp(pos, "000FAC08", 8) == 0) 3119 sae = 1; 3120 else if (os_strncasecmp(pos, "000FAC01", 8) == 0) 3121 dot1x = 1; 3122 else if (os_strncasecmp(pos, "000FAC05", 8) == 0) 3123 dot1x = 1; 3124 pos += 8; 3125 if (*pos != '+') 3126 break; 3127 pos++; 3128 } 3129 3130 if (dpp && psk && sae) 3131 return DPP_AKM_PSK_SAE_DPP; 3132 if (dpp && sae) 3133 return DPP_AKM_SAE_DPP; 3134 if (dpp) 3135 return DPP_AKM_DPP; 3136 if (psk && sae) 3137 return DPP_AKM_PSK_SAE; 3138 if (sae) 3139 return DPP_AKM_SAE; 3140 if (psk) 3141 return DPP_AKM_PSK; 3142 if (dot1x) 3143 return DPP_AKM_DOT1X; 3144 3145 return DPP_AKM_UNKNOWN; 3146 } 3147 3148 3149 static int dpp_parse_conf_obj(struct dpp_authentication *auth, 3150 const u8 *conf_obj, u16 conf_obj_len) 3151 { 3152 int ret = -1; 3153 struct json_token *root, *token, *discovery, *cred; 3154 struct dpp_config_obj *conf; 3155 struct wpabuf *ssid64 = NULL; 3156 int legacy; 3157 3158 root = json_parse((const char *) conf_obj, conf_obj_len); 3159 if (!root) 3160 return -1; 3161 if (root->type != JSON_OBJECT) { 3162 dpp_auth_fail(auth, "JSON root is not an object"); 3163 goto fail; 3164 } 3165 3166 token = json_get_member(root, "wi-fi_tech"); 3167 if (!token || token->type != JSON_STRING) { 3168 dpp_auth_fail(auth, "No wi-fi_tech string value found"); 3169 goto fail; 3170 } 3171 if (os_strcmp(token->string, "infra") != 0) { 3172 wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'", 3173 token->string); 3174 dpp_auth_fail(auth, "Unsupported wi-fi_tech value"); 3175 goto fail; 3176 } 3177 3178 discovery = json_get_member(root, "discovery"); 3179 if (!discovery || discovery->type != JSON_OBJECT) { 3180 dpp_auth_fail(auth, "No discovery object in JSON"); 3181 goto fail; 3182 } 3183 3184 ssid64 = json_get_member_base64url(discovery, "ssid64"); 3185 if (ssid64) { 3186 wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64", 3187 wpabuf_head(ssid64), wpabuf_len(ssid64)); 3188 if (wpabuf_len(ssid64) > SSID_MAX_LEN) { 3189 dpp_auth_fail(auth, "Too long discovery::ssid64 value"); 3190 goto fail; 3191 } 3192 } else { 3193 token = json_get_member(discovery, "ssid"); 3194 if (!token || token->type != JSON_STRING) { 3195 dpp_auth_fail(auth, 3196 "No discovery::ssid string value found"); 3197 goto fail; 3198 } 3199 wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid", 3200 token->string, os_strlen(token->string)); 3201 if (os_strlen(token->string) > SSID_MAX_LEN) { 3202 dpp_auth_fail(auth, 3203 "Too long discovery::ssid string value"); 3204 goto fail; 3205 } 3206 } 3207 3208 if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) { 3209 wpa_printf(MSG_DEBUG, 3210 "DPP: No room for this many Config Objects - ignore this one"); 3211 ret = 0; 3212 goto fail; 3213 } 3214 conf = &auth->conf_obj[auth->num_conf_obj++]; 3215 3216 if (ssid64) { 3217 conf->ssid_len = wpabuf_len(ssid64); 3218 os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len); 3219 } else { 3220 conf->ssid_len = os_strlen(token->string); 3221 os_memcpy(conf->ssid, token->string, conf->ssid_len); 3222 } 3223 3224 token = json_get_member(discovery, "ssid_charset"); 3225 if (token && token->type == JSON_NUMBER) { 3226 conf->ssid_charset = token->number; 3227 wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d", 3228 conf->ssid_charset); 3229 } 3230 3231 cred = json_get_member(root, "cred"); 3232 if (!cred || cred->type != JSON_OBJECT) { 3233 dpp_auth_fail(auth, "No cred object in JSON"); 3234 goto fail; 3235 } 3236 3237 token = json_get_member(cred, "akm"); 3238 if (!token || token->type != JSON_STRING) { 3239 dpp_auth_fail(auth, "No cred::akm string value found"); 3240 goto fail; 3241 } 3242 conf->akm = dpp_akm_from_str(token->string); 3243 3244 legacy = dpp_akm_legacy(conf->akm); 3245 if (legacy && auth->peer_version >= 2) { 3246 struct json_token *csign, *s_conn; 3247 3248 csign = json_get_member(cred, "csign"); 3249 s_conn = json_get_member(cred, "signedConnector"); 3250 if (csign && csign->type == JSON_OBJECT && 3251 s_conn && s_conn->type == JSON_STRING) 3252 legacy = 0; 3253 } 3254 if (legacy) { 3255 if (dpp_parse_cred_legacy(conf, cred) < 0) 3256 goto fail; 3257 } else if (dpp_akm_dpp(conf->akm) || 3258 (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) { 3259 if (dpp_parse_cred_dpp(auth, conf, cred) < 0) 3260 goto fail; 3261 #ifdef CONFIG_DPP2 3262 } else if (conf->akm == DPP_AKM_DOT1X) { 3263 if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 || 3264 dpp_parse_cred_dpp(auth, conf, cred) < 0) 3265 goto fail; 3266 #endif /* CONFIG_DPP2 */ 3267 } else { 3268 wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s", 3269 token->string); 3270 dpp_auth_fail(auth, "Unsupported akm"); 3271 goto fail; 3272 } 3273 3274 wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully"); 3275 ret = 0; 3276 fail: 3277 wpabuf_free(ssid64); 3278 json_free(root); 3279 return ret; 3280 } 3281 3282 3283 #ifdef CONFIG_DPP2 3284 static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len) 3285 { 3286 const u8 *b64; 3287 u16 b64_len; 3288 3289 b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len); 3290 if (!b64) 3291 return NULL; 3292 return base64_decode((const char *) b64, b64_len, len); 3293 } 3294 #endif /* CONFIG_DPP2 */ 3295 3296 3297 int dpp_conf_resp_rx(struct dpp_authentication *auth, 3298 const struct wpabuf *resp) 3299 { 3300 const u8 *wrapped_data, *e_nonce, *status, *conf_obj; 3301 u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len; 3302 const u8 *env_data; 3303 u16 env_data_len; 3304 const u8 *addr[1]; 3305 size_t len[1]; 3306 u8 *unwrapped = NULL; 3307 size_t unwrapped_len = 0; 3308 int ret = -1; 3309 3310 auth->conf_resp_status = 255; 3311 3312 if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) { 3313 dpp_auth_fail(auth, "Invalid attribute in config response"); 3314 return -1; 3315 } 3316 3317 wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp), 3318 DPP_ATTR_WRAPPED_DATA, 3319 &wrapped_data_len); 3320 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 3321 dpp_auth_fail(auth, 3322 "Missing or invalid required Wrapped Data attribute"); 3323 return -1; 3324 } 3325 3326 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 3327 wrapped_data, wrapped_data_len); 3328 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 3329 unwrapped = os_malloc(unwrapped_len); 3330 if (!unwrapped) 3331 return -1; 3332 3333 addr[0] = wpabuf_head(resp); 3334 len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp); 3335 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); 3336 3337 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 3338 wrapped_data, wrapped_data_len, 3339 1, addr, len, unwrapped) < 0) { 3340 dpp_auth_fail(auth, "AES-SIV decryption failed"); 3341 goto fail; 3342 } 3343 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 3344 unwrapped, unwrapped_len); 3345 3346 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 3347 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 3348 goto fail; 3349 } 3350 3351 e_nonce = dpp_get_attr(unwrapped, unwrapped_len, 3352 DPP_ATTR_ENROLLEE_NONCE, 3353 &e_nonce_len); 3354 if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { 3355 dpp_auth_fail(auth, 3356 "Missing or invalid Enrollee Nonce attribute"); 3357 goto fail; 3358 } 3359 wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); 3360 if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { 3361 dpp_auth_fail(auth, "Enrollee Nonce mismatch"); 3362 goto fail; 3363 } 3364 3365 status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp), 3366 DPP_ATTR_STATUS, &status_len); 3367 if (!status || status_len < 1) { 3368 dpp_auth_fail(auth, 3369 "Missing or invalid required DPP Status attribute"); 3370 goto fail; 3371 } 3372 auth->conf_resp_status = status[0]; 3373 wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); 3374 #ifdef CONFIG_DPP2 3375 if (status[0] == DPP_STATUS_CSR_NEEDED) { 3376 u8 *csrattrs; 3377 size_t csrattrs_len; 3378 3379 wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR"); 3380 3381 csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len, 3382 &csrattrs_len); 3383 if (!csrattrs) { 3384 dpp_auth_fail(auth, 3385 "Missing or invalid CSR Attributes Request attribute"); 3386 goto fail; 3387 } 3388 wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len); 3389 os_free(auth->csrattrs); 3390 auth->csrattrs = csrattrs; 3391 auth->csrattrs_len = csrattrs_len; 3392 ret = -2; 3393 goto fail; 3394 } 3395 #endif /* CONFIG_DPP2 */ 3396 #ifdef CONFIG_DPP3 3397 if (status[0] == DPP_STATUS_NEW_KEY_NEEDED) { 3398 const u8 *fcgroup, *r_proto; 3399 u16 fcgroup_len, r_proto_len; 3400 u16 group; 3401 const struct dpp_curve_params *curve; 3402 struct crypto_ec_key *new_pe; 3403 struct crypto_ec_key *pc; 3404 3405 fcgroup = dpp_get_attr(unwrapped, unwrapped_len, 3406 DPP_ATTR_FINITE_CYCLIC_GROUP, 3407 &fcgroup_len); 3408 if (!fcgroup || fcgroup_len != 2) { 3409 dpp_auth_fail(auth, 3410 "Missing or invalid required Finite Cyclic Group attribute"); 3411 goto fail; 3412 } 3413 group = WPA_GET_LE16(fcgroup); 3414 3415 wpa_printf(MSG_DEBUG, 3416 "DPP: Configurator requested a new protocol key from group %u", 3417 group); 3418 curve = dpp_get_curve_ike_group(group); 3419 if (!curve) { 3420 dpp_auth_fail(auth, 3421 "Unsupported group for new protocol key"); 3422 goto fail; 3423 } 3424 3425 new_pe = dpp_gen_keypair(curve); 3426 if (!new_pe) { 3427 dpp_auth_fail(auth, 3428 "Failed to generate a new protocol key"); 3429 goto fail; 3430 } 3431 3432 crypto_ec_key_deinit(auth->own_protocol_key); 3433 auth->own_protocol_key = new_pe; 3434 auth->new_curve = curve; 3435 3436 r_proto = dpp_get_attr(unwrapped, unwrapped_len, 3437 DPP_ATTR_R_PROTOCOL_KEY, 3438 &r_proto_len); 3439 if (!r_proto) { 3440 dpp_auth_fail(auth, 3441 "Missing required Responder Protocol Key attribute (Pc)"); 3442 goto fail; 3443 } 3444 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key (new Pc)", 3445 r_proto, r_proto_len); 3446 3447 pc = dpp_set_pubkey_point(new_pe, r_proto, r_proto_len); 3448 if (!pc) { 3449 dpp_auth_fail(auth, "Invalid Responder Protocol Key (Pc)"); 3450 goto fail; 3451 } 3452 dpp_debug_print_key("New Peer Protocol Key (Pc)", pc); 3453 3454 crypto_ec_key_deinit(auth->peer_protocol_key); 3455 auth->peer_protocol_key = pc; 3456 3457 auth->waiting_new_key = true; 3458 ret = -3; 3459 goto fail; 3460 } 3461 #endif /* CONFIG_DPP3 */ 3462 if (status[0] != DPP_STATUS_OK) { 3463 dpp_auth_fail(auth, "Configurator rejected configuration"); 3464 goto fail; 3465 } 3466 3467 env_data = dpp_get_attr(unwrapped, unwrapped_len, 3468 DPP_ATTR_ENVELOPED_DATA, &env_data_len); 3469 #ifdef CONFIG_DPP2 3470 if (env_data && 3471 dpp_conf_resp_env_data(auth, env_data, env_data_len) < 0) 3472 goto fail; 3473 #endif /* CONFIG_DPP2 */ 3474 3475 conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ, 3476 &conf_obj_len); 3477 if (!conf_obj && !env_data) { 3478 dpp_auth_fail(auth, 3479 "Missing required Configuration Object attribute"); 3480 goto fail; 3481 } 3482 while (conf_obj) { 3483 wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON", 3484 conf_obj, conf_obj_len); 3485 if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0) 3486 goto fail; 3487 conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len, 3488 DPP_ATTR_CONFIG_OBJ, 3489 &conf_obj_len); 3490 } 3491 3492 #ifdef CONFIG_DPP2 3493 status = dpp_get_attr(unwrapped, unwrapped_len, 3494 DPP_ATTR_SEND_CONN_STATUS, &status_len); 3495 if (status) { 3496 wpa_printf(MSG_DEBUG, 3497 "DPP: Configurator requested connection status result"); 3498 auth->conn_status_requested = 1; 3499 } 3500 #endif /* CONFIG_DPP2 */ 3501 3502 ret = 0; 3503 3504 fail: 3505 os_free(unwrapped); 3506 return ret; 3507 } 3508 3509 3510 #ifdef CONFIG_DPP2 3511 3512 enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth, 3513 const u8 *hdr, 3514 const u8 *attr_start, size_t attr_len) 3515 { 3516 const u8 *wrapped_data, *status, *e_nonce; 3517 u16 wrapped_data_len, status_len, e_nonce_len; 3518 const u8 *addr[2]; 3519 size_t len[2]; 3520 u8 *unwrapped = NULL; 3521 size_t unwrapped_len = 0; 3522 enum dpp_status_error ret = 256; 3523 3524 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, 3525 &wrapped_data_len); 3526 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 3527 dpp_auth_fail(auth, 3528 "Missing or invalid required Wrapped Data attribute"); 3529 goto fail; 3530 } 3531 wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", 3532 wrapped_data, wrapped_data_len); 3533 3534 attr_len = wrapped_data - 4 - attr_start; 3535 3536 addr[0] = hdr; 3537 len[0] = DPP_HDR_LEN; 3538 addr[1] = attr_start; 3539 len[1] = attr_len; 3540 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 3541 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 3542 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 3543 wrapped_data, wrapped_data_len); 3544 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 3545 unwrapped = os_malloc(unwrapped_len); 3546 if (!unwrapped) 3547 goto fail; 3548 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 3549 wrapped_data, wrapped_data_len, 3550 2, addr, len, unwrapped) < 0) { 3551 dpp_auth_fail(auth, "AES-SIV decryption failed"); 3552 goto fail; 3553 } 3554 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 3555 unwrapped, unwrapped_len); 3556 3557 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 3558 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 3559 goto fail; 3560 } 3561 3562 e_nonce = dpp_get_attr(unwrapped, unwrapped_len, 3563 DPP_ATTR_ENROLLEE_NONCE, 3564 &e_nonce_len); 3565 if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { 3566 dpp_auth_fail(auth, 3567 "Missing or invalid Enrollee Nonce attribute"); 3568 goto fail; 3569 } 3570 wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); 3571 if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { 3572 dpp_auth_fail(auth, "Enrollee Nonce mismatch"); 3573 wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce", 3574 auth->e_nonce, e_nonce_len); 3575 goto fail; 3576 } 3577 3578 status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS, 3579 &status_len); 3580 if (!status || status_len < 1) { 3581 dpp_auth_fail(auth, 3582 "Missing or invalid required DPP Status attribute"); 3583 goto fail; 3584 } 3585 wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); 3586 ret = status[0]; 3587 3588 fail: 3589 bin_clear_free(unwrapped, unwrapped_len); 3590 return ret; 3591 } 3592 3593 3594 struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth, 3595 enum dpp_status_error status) 3596 { 3597 struct wpabuf *msg, *clear; 3598 size_t nonce_len, clear_len, attr_len; 3599 const u8 *addr[2]; 3600 size_t len[2]; 3601 u8 *wrapped; 3602 3603 nonce_len = auth->curve->nonce_len; 3604 clear_len = 5 + 4 + nonce_len; 3605 attr_len = 4 + clear_len + AES_BLOCK_SIZE; 3606 clear = wpabuf_alloc(clear_len); 3607 msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len); 3608 if (!clear || !msg) 3609 goto fail; 3610 3611 /* DPP Status */ 3612 dpp_build_attr_status(clear, status); 3613 3614 /* E-nonce */ 3615 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 3616 wpabuf_put_le16(clear, nonce_len); 3617 wpabuf_put_data(clear, auth->e_nonce, nonce_len); 3618 3619 /* OUI, OUI type, Crypto Suite, DPP frame type */ 3620 addr[0] = wpabuf_head_u8(msg) + 2; 3621 len[0] = 3 + 1 + 1 + 1; 3622 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 3623 3624 /* Attributes before Wrapped Data (none) */ 3625 addr[1] = wpabuf_put(msg, 0); 3626 len[1] = 0; 3627 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 3628 3629 /* Wrapped Data */ 3630 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 3631 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 3632 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 3633 3634 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 3635 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 3636 wpabuf_head(clear), wpabuf_len(clear), 3637 2, addr, len, wrapped) < 0) 3638 goto fail; 3639 3640 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg); 3641 wpabuf_free(clear); 3642 return msg; 3643 fail: 3644 wpabuf_free(clear); 3645 wpabuf_free(msg); 3646 return NULL; 3647 } 3648 3649 3650 static int valid_channel_list(const char *val) 3651 { 3652 while (*val) { 3653 if (!((*val >= '0' && *val <= '9') || 3654 *val == '/' || *val == ',')) 3655 return 0; 3656 val++; 3657 } 3658 3659 return 1; 3660 } 3661 3662 3663 enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth, 3664 const u8 *hdr, 3665 const u8 *attr_start, 3666 size_t attr_len, 3667 u8 *ssid, size_t *ssid_len, 3668 char **channel_list) 3669 { 3670 const u8 *wrapped_data, *status, *e_nonce; 3671 u16 wrapped_data_len, status_len, e_nonce_len; 3672 const u8 *addr[2]; 3673 size_t len[2]; 3674 u8 *unwrapped = NULL; 3675 size_t unwrapped_len = 0; 3676 enum dpp_status_error ret = 256; 3677 struct json_token *root = NULL, *token; 3678 struct wpabuf *ssid64; 3679 3680 *ssid_len = 0; 3681 *channel_list = NULL; 3682 3683 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, 3684 &wrapped_data_len); 3685 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 3686 dpp_auth_fail(auth, 3687 "Missing or invalid required Wrapped Data attribute"); 3688 goto fail; 3689 } 3690 wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", 3691 wrapped_data, wrapped_data_len); 3692 3693 attr_len = wrapped_data - 4 - attr_start; 3694 3695 addr[0] = hdr; 3696 len[0] = DPP_HDR_LEN; 3697 addr[1] = attr_start; 3698 len[1] = attr_len; 3699 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 3700 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 3701 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 3702 wrapped_data, wrapped_data_len); 3703 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 3704 unwrapped = os_malloc(unwrapped_len); 3705 if (!unwrapped) 3706 goto fail; 3707 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 3708 wrapped_data, wrapped_data_len, 3709 2, addr, len, unwrapped) < 0) { 3710 dpp_auth_fail(auth, "AES-SIV decryption failed"); 3711 goto fail; 3712 } 3713 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 3714 unwrapped, unwrapped_len); 3715 3716 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 3717 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 3718 goto fail; 3719 } 3720 3721 e_nonce = dpp_get_attr(unwrapped, unwrapped_len, 3722 DPP_ATTR_ENROLLEE_NONCE, 3723 &e_nonce_len); 3724 if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { 3725 dpp_auth_fail(auth, 3726 "Missing or invalid Enrollee Nonce attribute"); 3727 goto fail; 3728 } 3729 wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); 3730 if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { 3731 dpp_auth_fail(auth, "Enrollee Nonce mismatch"); 3732 wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce", 3733 auth->e_nonce, e_nonce_len); 3734 goto fail; 3735 } 3736 3737 status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS, 3738 &status_len); 3739 if (!status) { 3740 dpp_auth_fail(auth, 3741 "Missing required DPP Connection Status attribute"); 3742 goto fail; 3743 } 3744 wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", 3745 status, status_len); 3746 3747 root = json_parse((const char *) status, status_len); 3748 if (!root) { 3749 dpp_auth_fail(auth, "Could not parse connStatus"); 3750 goto fail; 3751 } 3752 3753 ssid64 = json_get_member_base64url(root, "ssid64"); 3754 if (ssid64 && wpabuf_len(ssid64) <= SSID_MAX_LEN) { 3755 *ssid_len = wpabuf_len(ssid64); 3756 os_memcpy(ssid, wpabuf_head(ssid64), *ssid_len); 3757 } 3758 wpabuf_free(ssid64); 3759 3760 token = json_get_member(root, "channelList"); 3761 if (token && token->type == JSON_STRING && 3762 valid_channel_list(token->string)) 3763 *channel_list = os_strdup(token->string); 3764 3765 token = json_get_member(root, "result"); 3766 if (!token || token->type != JSON_NUMBER) { 3767 dpp_auth_fail(auth, "No connStatus - result"); 3768 goto fail; 3769 } 3770 wpa_printf(MSG_DEBUG, "DPP: result %d", token->number); 3771 ret = token->number; 3772 3773 fail: 3774 json_free(root); 3775 bin_clear_free(unwrapped, unwrapped_len); 3776 return ret; 3777 } 3778 3779 3780 struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, 3781 const u8 *ssid, size_t ssid_len, 3782 const char *channel_list) 3783 { 3784 struct wpabuf *json; 3785 3786 json = wpabuf_alloc(1000); 3787 if (!json) 3788 return NULL; 3789 json_start_object(json, NULL); 3790 json_add_int(json, "result", result); 3791 if (ssid) { 3792 json_value_sep(json); 3793 if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) { 3794 wpabuf_free(json); 3795 return NULL; 3796 } 3797 } 3798 if (channel_list) { 3799 json_value_sep(json); 3800 json_add_string(json, "channelList", channel_list); 3801 } 3802 json_end_object(json); 3803 wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", 3804 wpabuf_head(json), wpabuf_len(json)); 3805 3806 return json; 3807 } 3808 3809 3810 struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, 3811 enum dpp_status_error result, 3812 const u8 *ssid, size_t ssid_len, 3813 const char *channel_list) 3814 { 3815 struct wpabuf *msg = NULL, *clear = NULL, *json; 3816 size_t nonce_len, clear_len, attr_len; 3817 const u8 *addr[2]; 3818 size_t len[2]; 3819 u8 *wrapped; 3820 3821 json = dpp_build_conn_status(result, ssid, ssid_len, channel_list); 3822 if (!json) 3823 return NULL; 3824 3825 nonce_len = auth->curve->nonce_len; 3826 clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json); 3827 attr_len = 4 + clear_len + AES_BLOCK_SIZE; 3828 clear = wpabuf_alloc(clear_len); 3829 msg = dpp_alloc_msg(DPP_PA_CONNECTION_STATUS_RESULT, attr_len); 3830 if (!clear || !msg) 3831 goto fail; 3832 3833 /* E-nonce */ 3834 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 3835 wpabuf_put_le16(clear, nonce_len); 3836 wpabuf_put_data(clear, auth->e_nonce, nonce_len); 3837 3838 /* DPP Connection Status */ 3839 wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); 3840 wpabuf_put_le16(clear, wpabuf_len(json)); 3841 wpabuf_put_buf(clear, json); 3842 3843 /* OUI, OUI type, Crypto Suite, DPP frame type */ 3844 addr[0] = wpabuf_head_u8(msg) + 2; 3845 len[0] = 3 + 1 + 1 + 1; 3846 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 3847 3848 /* Attributes before Wrapped Data (none) */ 3849 addr[1] = wpabuf_put(msg, 0); 3850 len[1] = 0; 3851 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 3852 3853 /* Wrapped Data */ 3854 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 3855 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 3856 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 3857 3858 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 3859 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 3860 wpabuf_head(clear), wpabuf_len(clear), 3861 2, addr, len, wrapped) < 0) 3862 goto fail; 3863 3864 wpa_hexdump_buf(MSG_DEBUG, "DPP: Connection Status Result attributes", 3865 msg); 3866 wpabuf_free(json); 3867 wpabuf_free(clear); 3868 return msg; 3869 fail: 3870 wpabuf_free(json); 3871 wpabuf_free(clear); 3872 wpabuf_free(msg); 3873 return NULL; 3874 } 3875 3876 #endif /* CONFIG_DPP2 */ 3877 3878 3879 void dpp_configurator_free(struct dpp_configurator *conf) 3880 { 3881 if (!conf) 3882 return; 3883 crypto_ec_key_deinit(conf->csign); 3884 os_free(conf->kid); 3885 os_free(conf->connector); 3886 crypto_ec_key_deinit(conf->connector_key); 3887 crypto_ec_key_deinit(conf->pp_key); 3888 os_free(conf); 3889 } 3890 3891 3892 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, 3893 size_t buflen) 3894 { 3895 struct wpabuf *key; 3896 int ret = -1; 3897 3898 if (!conf->csign) 3899 return -1; 3900 3901 key = crypto_ec_key_get_ecprivate_key(conf->csign, true); 3902 if (!key) 3903 return -1; 3904 3905 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key)); 3906 3907 wpabuf_clear_free(key); 3908 return ret; 3909 } 3910 3911 3912 static int dpp_configurator_gen_kid(struct dpp_configurator *conf) 3913 { 3914 struct wpabuf *csign_pub = NULL; 3915 const u8 *addr[1]; 3916 size_t len[1]; 3917 int res; 3918 3919 csign_pub = crypto_ec_key_get_pubkey_point(conf->csign, 1); 3920 if (!csign_pub) { 3921 wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key"); 3922 return -1; 3923 } 3924 3925 /* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */ 3926 addr[0] = wpabuf_head(csign_pub); 3927 len[0] = wpabuf_len(csign_pub); 3928 res = sha256_vector(1, addr, len, conf->kid_hash); 3929 wpabuf_free(csign_pub); 3930 if (res < 0) { 3931 wpa_printf(MSG_DEBUG, 3932 "DPP: Failed to derive kid for C-sign-key"); 3933 return -1; 3934 } 3935 3936 conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash), 3937 NULL); 3938 return conf->kid ? 0 : -1; 3939 } 3940 3941 3942 static struct dpp_configurator * 3943 dpp_keygen_configurator(const char *curve, const u8 *privkey, 3944 size_t privkey_len, const u8 *pp_key, size_t pp_key_len) 3945 { 3946 struct dpp_configurator *conf; 3947 3948 conf = os_zalloc(sizeof(*conf)); 3949 if (!conf) 3950 return NULL; 3951 3952 conf->curve = dpp_get_curve_name(curve); 3953 if (!conf->curve) { 3954 wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); 3955 os_free(conf); 3956 return NULL; 3957 } 3958 3959 if (privkey) 3960 conf->csign = dpp_set_keypair(&conf->curve, privkey, 3961 privkey_len); 3962 else 3963 conf->csign = dpp_gen_keypair(conf->curve); 3964 if (pp_key) 3965 conf->pp_key = dpp_set_keypair(&conf->curve, pp_key, 3966 pp_key_len); 3967 else 3968 conf->pp_key = dpp_gen_keypair(conf->curve); 3969 if (!conf->csign || !conf->pp_key) 3970 goto fail; 3971 conf->own = 1; 3972 3973 if (dpp_configurator_gen_kid(conf) < 0) 3974 goto fail; 3975 return conf; 3976 fail: 3977 dpp_configurator_free(conf); 3978 return NULL; 3979 } 3980 3981 3982 int dpp_configurator_own_config(struct dpp_authentication *auth, 3983 const char *curve, int ap) 3984 { 3985 struct wpabuf *conf_obj; 3986 int ret = -1; 3987 3988 if (!auth->conf) { 3989 wpa_printf(MSG_DEBUG, "DPP: No configurator specified"); 3990 return -1; 3991 } 3992 3993 auth->curve = dpp_get_curve_name(curve); 3994 if (!auth->curve) { 3995 wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); 3996 return -1; 3997 } 3998 3999 wpa_printf(MSG_DEBUG, 4000 "DPP: Building own configuration/connector with curve %s", 4001 auth->curve->name); 4002 4003 auth->own_protocol_key = dpp_gen_keypair(auth->curve); 4004 if (!auth->own_protocol_key) 4005 return -1; 4006 dpp_copy_netaccesskey(auth, &auth->conf_obj[0]); 4007 auth->peer_protocol_key = auth->own_protocol_key; 4008 dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign); 4009 4010 conf_obj = dpp_build_conf_obj(auth, ap, 0, NULL); 4011 if (!conf_obj) { 4012 wpabuf_free(auth->conf_obj[0].c_sign_key); 4013 auth->conf_obj[0].c_sign_key = NULL; 4014 goto fail; 4015 } 4016 ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj), 4017 wpabuf_len(conf_obj)); 4018 fail: 4019 wpabuf_free(conf_obj); 4020 auth->peer_protocol_key = NULL; 4021 return ret; 4022 } 4023 4024 4025 static int dpp_compatible_netrole(const char *role1, const char *role2) 4026 { 4027 return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) || 4028 (os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0); 4029 } 4030 4031 4032 static int dpp_connector_compatible_group(struct json_token *root, 4033 const char *group_id, 4034 const char *net_role, 4035 bool reconfig) 4036 { 4037 struct json_token *groups, *token; 4038 4039 groups = json_get_member(root, "groups"); 4040 if (!groups || groups->type != JSON_ARRAY) 4041 return 0; 4042 4043 for (token = groups->child; token; token = token->sibling) { 4044 struct json_token *id, *role; 4045 4046 id = json_get_member(token, "groupId"); 4047 if (!id || id->type != JSON_STRING) 4048 continue; 4049 4050 role = json_get_member(token, "netRole"); 4051 if (!role || role->type != JSON_STRING) 4052 continue; 4053 4054 if (os_strcmp(id->string, "*") != 0 && 4055 os_strcmp(group_id, "*") != 0 && 4056 os_strcmp(id->string, group_id) != 0) 4057 continue; 4058 4059 if (reconfig && os_strcmp(net_role, "configurator") == 0) 4060 return 1; 4061 if (!reconfig && dpp_compatible_netrole(role->string, net_role)) 4062 return 1; 4063 } 4064 4065 return 0; 4066 } 4067 4068 4069 int dpp_connector_match_groups(struct json_token *own_root, 4070 struct json_token *peer_root, bool reconfig) 4071 { 4072 struct json_token *groups, *token; 4073 4074 groups = json_get_member(peer_root, "groups"); 4075 if (!groups || groups->type != JSON_ARRAY) { 4076 wpa_printf(MSG_DEBUG, "DPP: No peer groups array found"); 4077 return 0; 4078 } 4079 4080 for (token = groups->child; token; token = token->sibling) { 4081 struct json_token *id, *role; 4082 4083 id = json_get_member(token, "groupId"); 4084 if (!id || id->type != JSON_STRING) { 4085 wpa_printf(MSG_DEBUG, 4086 "DPP: Missing peer groupId string"); 4087 continue; 4088 } 4089 4090 role = json_get_member(token, "netRole"); 4091 if (!role || role->type != JSON_STRING) { 4092 wpa_printf(MSG_DEBUG, 4093 "DPP: Missing peer groups::netRole string"); 4094 continue; 4095 } 4096 wpa_printf(MSG_DEBUG, 4097 "DPP: peer connector group: groupId='%s' netRole='%s'", 4098 id->string, role->string); 4099 if (dpp_connector_compatible_group(own_root, id->string, 4100 role->string, reconfig)) { 4101 wpa_printf(MSG_DEBUG, 4102 "DPP: Compatible group/netRole in own connector"); 4103 return 1; 4104 } 4105 } 4106 4107 return 0; 4108 } 4109 4110 4111 struct json_token * dpp_parse_own_connector(const char *own_connector) 4112 { 4113 unsigned char *own_conn; 4114 size_t own_conn_len; 4115 const char *pos, *end; 4116 struct json_token *own_root; 4117 4118 pos = os_strchr(own_connector, '.'); 4119 if (!pos) { 4120 wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); 4121 return NULL; 4122 } 4123 pos++; 4124 end = os_strchr(pos, '.'); 4125 if (!end) { 4126 wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); 4127 return NULL; 4128 } 4129 own_conn = base64_url_decode(pos, end - pos, &own_conn_len); 4130 if (!own_conn) { 4131 wpa_printf(MSG_DEBUG, 4132 "DPP: Failed to base64url decode own signedConnector JWS Payload"); 4133 return NULL; 4134 } 4135 4136 own_root = json_parse((const char *) own_conn, own_conn_len); 4137 os_free(own_conn); 4138 if (!own_root) 4139 wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); 4140 4141 return own_root; 4142 } 4143 4144 4145 enum dpp_status_error 4146 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, 4147 const u8 *net_access_key, size_t net_access_key_len, 4148 const u8 *csign_key, size_t csign_key_len, 4149 const u8 *peer_connector, size_t peer_connector_len, 4150 os_time_t *expiry, u8 *peer_key_hash) 4151 { 4152 struct json_token *root = NULL, *netkey, *token; 4153 struct json_token *own_root = NULL; 4154 enum dpp_status_error ret = 255, res; 4155 struct crypto_ec_key *own_key = NULL; 4156 struct wpabuf *own_key_pub = NULL; 4157 const struct dpp_curve_params *curve, *own_curve; 4158 struct dpp_signed_connector_info info; 4159 size_t Nx_len; 4160 u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; 4161 4162 os_memset(intro, 0, sizeof(*intro)); 4163 os_memset(&info, 0, sizeof(info)); 4164 if (expiry) 4165 *expiry = 0; 4166 4167 own_key = dpp_set_keypair(&own_curve, net_access_key, 4168 net_access_key_len); 4169 if (!own_key) { 4170 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 4171 goto fail; 4172 } 4173 4174 own_root = dpp_parse_own_connector(own_connector); 4175 if (!own_root) 4176 goto fail; 4177 4178 res = dpp_check_signed_connector(&info, csign_key, csign_key_len, 4179 peer_connector, peer_connector_len); 4180 if (res != DPP_STATUS_OK) { 4181 ret = res; 4182 goto fail; 4183 } 4184 4185 root = json_parse((const char *) info.payload, info.payload_len); 4186 if (!root) { 4187 wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed"); 4188 ret = DPP_STATUS_INVALID_CONNECTOR; 4189 goto fail; 4190 } 4191 4192 if (!dpp_connector_match_groups(own_root, root, false)) { 4193 wpa_printf(MSG_DEBUG, 4194 "DPP: Peer connector does not include compatible group netrole with own connector"); 4195 ret = DPP_STATUS_NO_MATCH; 4196 goto fail; 4197 } 4198 4199 token = json_get_member(root, "expiry"); 4200 if (!token || token->type != JSON_STRING) { 4201 wpa_printf(MSG_DEBUG, 4202 "DPP: No expiry string found - connector does not expire"); 4203 } else { 4204 wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string); 4205 if (dpp_key_expired(token->string, expiry)) { 4206 wpa_printf(MSG_DEBUG, 4207 "DPP: Connector (netAccessKey) has expired"); 4208 ret = DPP_STATUS_INVALID_CONNECTOR; 4209 goto fail; 4210 } 4211 } 4212 4213 #ifdef CONFIG_DPP3 4214 token = json_get_member(root, "version"); 4215 if (token && token->type == JSON_NUMBER) { 4216 wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number); 4217 intro->peer_version = token->number; 4218 } 4219 #endif /* CONFIG_DPP3 */ 4220 4221 netkey = json_get_member(root, "netAccessKey"); 4222 if (!netkey || netkey->type != JSON_OBJECT) { 4223 wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found"); 4224 ret = DPP_STATUS_INVALID_CONNECTOR; 4225 goto fail; 4226 } 4227 4228 intro->peer_key = dpp_parse_jwk(netkey, &curve); 4229 if (!intro->peer_key) { 4230 ret = DPP_STATUS_INVALID_CONNECTOR; 4231 goto fail; 4232 } 4233 dpp_debug_print_key("DPP: Received netAccessKey", intro->peer_key); 4234 4235 if (own_curve != curve) { 4236 wpa_printf(MSG_DEBUG, 4237 "DPP: Mismatching netAccessKey curves (%s != %s)", 4238 own_curve->name, curve->name); 4239 ret = DPP_STATUS_INVALID_CONNECTOR; 4240 goto fail; 4241 } 4242 4243 /* ECDH: N = nk * PK */ 4244 if (dpp_ecdh(own_key, intro->peer_key, Nx, &Nx_len) < 0) 4245 goto fail; 4246 4247 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", 4248 Nx, Nx_len); 4249 4250 /* PMK = HKDF(<>, "DPP PMK", N.x) */ 4251 if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) { 4252 wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK"); 4253 goto fail; 4254 } 4255 intro->pmk_len = curve->hash_len; 4256 4257 /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ 4258 if (dpp_derive_pmkid(curve, own_key, intro->peer_key, intro->pmkid) < 4259 0) { 4260 wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID"); 4261 goto fail; 4262 } 4263 4264 #ifdef CONFIG_DPP3 4265 if (dpp_hpke_suite(curve->ike_group, &intro->kem_id, &intro->kdf_id, 4266 &intro->aead_id) < 0) { 4267 wpa_printf(MSG_ERROR, "DPP: Unsupported group %d", 4268 curve->ike_group); 4269 goto fail; 4270 } 4271 #endif /* CONFIG_DPP3 */ 4272 4273 if (peer_key_hash) 4274 dpp_get_pubkey_hash(intro->peer_key, peer_key_hash); 4275 4276 ret = DPP_STATUS_OK; 4277 fail: 4278 if (ret != DPP_STATUS_OK) 4279 dpp_peer_intro_deinit(intro); 4280 os_memset(Nx, 0, sizeof(Nx)); 4281 os_free(info.payload); 4282 crypto_ec_key_deinit(own_key); 4283 wpabuf_free(own_key_pub); 4284 json_free(root); 4285 json_free(own_root); 4286 return ret; 4287 } 4288 4289 4290 void dpp_peer_intro_deinit(struct dpp_introduction *intro) 4291 { 4292 if (!intro) 4293 return; 4294 4295 crypto_ec_key_deinit(intro->peer_key); 4296 os_memset(intro, 0, sizeof(*intro)); 4297 } 4298 4299 4300 #ifdef CONFIG_DPP3 4301 int dpp_get_connector_version(const char *connector) 4302 { 4303 struct json_token *root, *token; 4304 int ver = -1; 4305 4306 root = dpp_parse_own_connector(connector); 4307 if (!root) 4308 return -1; 4309 4310 token = json_get_member(root, "version"); 4311 if (token && token->type == JSON_NUMBER) 4312 ver = token->number; 4313 4314 json_free(root); 4315 return ver; 4316 } 4317 #endif /* CONFIG_DPP3 */ 4318 4319 4320 unsigned int dpp_next_id(struct dpp_global *dpp) 4321 { 4322 struct dpp_bootstrap_info *bi; 4323 unsigned int max_id = 0; 4324 4325 dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { 4326 if (bi->id > max_id) 4327 max_id = bi->id; 4328 } 4329 return max_id + 1; 4330 } 4331 4332 4333 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id) 4334 { 4335 struct dpp_bootstrap_info *bi, *tmp; 4336 int found = 0; 4337 4338 if (!dpp) 4339 return -1; 4340 4341 dl_list_for_each_safe(bi, tmp, &dpp->bootstrap, 4342 struct dpp_bootstrap_info, list) { 4343 if (id && bi->id != id) 4344 continue; 4345 found = 1; 4346 #ifdef CONFIG_DPP2 4347 if (dpp->remove_bi) 4348 dpp->remove_bi(dpp->cb_ctx, bi); 4349 #endif /* CONFIG_DPP2 */ 4350 dl_list_del(&bi->list); 4351 dpp_bootstrap_info_free(bi); 4352 } 4353 4354 if (id == 0) 4355 return 0; /* flush succeeds regardless of entries found */ 4356 return found ? 0 : -1; 4357 } 4358 4359 4360 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, 4361 const char *uri) 4362 { 4363 struct dpp_bootstrap_info *bi; 4364 4365 if (!dpp) 4366 return NULL; 4367 4368 bi = dpp_parse_uri(uri); 4369 if (!bi) 4370 return NULL; 4371 4372 bi->type = DPP_BOOTSTRAP_QR_CODE; 4373 bi->id = dpp_next_id(dpp); 4374 dl_list_add(&dpp->bootstrap, &bi->list); 4375 return bi; 4376 } 4377 4378 4379 struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, 4380 const char *uri) 4381 { 4382 struct dpp_bootstrap_info *bi; 4383 4384 if (!dpp) 4385 return NULL; 4386 4387 bi = dpp_parse_uri(uri); 4388 if (!bi) 4389 return NULL; 4390 4391 bi->type = DPP_BOOTSTRAP_NFC_URI; 4392 bi->id = dpp_next_id(dpp); 4393 dl_list_add(&dpp->bootstrap, &bi->list); 4394 return bi; 4395 } 4396 4397 4398 static int dpp_parse_supported_curves_list(struct dpp_bootstrap_info *bi, 4399 char *txt) 4400 { 4401 char *token, *context = NULL; 4402 u8 curves = 0; 4403 4404 if (!txt) 4405 return 0; 4406 4407 while ((token = str_token(txt, ":", &context))) { 4408 if (os_strcmp(token, "P-256") == 0) { 4409 curves |= BIT(DPP_BOOTSTRAP_CURVE_P_256); 4410 } else if (os_strcmp(token, "P-384") == 0) { 4411 curves |= BIT(DPP_BOOTSTRAP_CURVE_P_384); 4412 } else if (os_strcmp(token, "P-521") == 0) { 4413 curves |= BIT(DPP_BOOTSTRAP_CURVE_P_521); 4414 } else if (os_strcmp(token, "BP-256") == 0) { 4415 curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_256); 4416 } else if (os_strcmp(token, "BP-384") == 0) { 4417 curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_384); 4418 } else if (os_strcmp(token, "BP-512") == 0) { 4419 curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_512); 4420 } else { 4421 wpa_printf(MSG_DEBUG, "DPP: Unsupported curve '%s'", 4422 token); 4423 return -1; 4424 } 4425 } 4426 bi->supported_curves = curves; 4427 4428 wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x", 4429 bi->supported_curves); 4430 4431 return 0; 4432 } 4433 4434 4435 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) 4436 { 4437 char *mac = NULL, *info = NULL, *curve = NULL; 4438 char *key = NULL, *supported_curves = NULL, *host = NULL; 4439 u8 *privkey = NULL; 4440 size_t privkey_len = 0; 4441 int ret = -1; 4442 struct dpp_bootstrap_info *bi; 4443 4444 if (!dpp) 4445 return -1; 4446 4447 bi = os_zalloc(sizeof(*bi)); 4448 if (!bi) 4449 goto fail; 4450 4451 if (os_strstr(cmd, "type=qrcode")) 4452 bi->type = DPP_BOOTSTRAP_QR_CODE; 4453 else if (os_strstr(cmd, "type=pkex")) 4454 bi->type = DPP_BOOTSTRAP_PKEX; 4455 else if (os_strstr(cmd, "type=nfc-uri")) 4456 bi->type = DPP_BOOTSTRAP_NFC_URI; 4457 else 4458 goto fail; 4459 4460 bi->chan = get_param(cmd, " chan="); 4461 mac = get_param(cmd, " mac="); 4462 info = get_param(cmd, " info="); 4463 curve = get_param(cmd, " curve="); 4464 key = get_param(cmd, " key="); 4465 supported_curves = get_param(cmd, " supported_curves="); 4466 host = get_param(cmd, " host="); 4467 4468 if (key) { 4469 privkey_len = os_strlen(key) / 2; 4470 privkey = os_malloc(privkey_len); 4471 if (!privkey || 4472 hexstr2bin(key, privkey, privkey_len) < 0) 4473 goto fail; 4474 } 4475 4476 if (dpp_keygen(bi, curve, privkey, privkey_len) < 0 || 4477 dpp_parse_uri_chan_list(bi, bi->chan) < 0 || 4478 dpp_parse_uri_mac(bi, mac) < 0 || 4479 dpp_parse_uri_info(bi, info) < 0 || 4480 dpp_parse_supported_curves_list(bi, supported_curves) < 0 || 4481 dpp_parse_uri_host(bi, host) < 0 || 4482 dpp_gen_uri(bi) < 0) 4483 goto fail; 4484 4485 bi->id = dpp_next_id(dpp); 4486 dl_list_add(&dpp->bootstrap, &bi->list); 4487 ret = bi->id; 4488 bi = NULL; 4489 fail: 4490 os_free(curve); 4491 os_free(mac); 4492 os_free(info); 4493 str_clear_free(key); 4494 os_free(supported_curves); 4495 os_free(host); 4496 bin_clear_free(privkey, privkey_len); 4497 dpp_bootstrap_info_free(bi); 4498 return ret; 4499 } 4500 4501 4502 struct dpp_bootstrap_info * 4503 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id) 4504 { 4505 struct dpp_bootstrap_info *bi; 4506 4507 if (!dpp) 4508 return NULL; 4509 4510 dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { 4511 if (bi->id == id) 4512 return bi; 4513 } 4514 return NULL; 4515 } 4516 4517 4518 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id) 4519 { 4520 unsigned int id_val; 4521 4522 if (os_strcmp(id, "*") == 0) { 4523 id_val = 0; 4524 } else { 4525 id_val = atoi(id); 4526 if (id_val == 0) 4527 return -1; 4528 } 4529 4530 return dpp_bootstrap_del(dpp, id_val); 4531 } 4532 4533 4534 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id) 4535 { 4536 struct dpp_bootstrap_info *bi; 4537 4538 bi = dpp_bootstrap_get_id(dpp, id); 4539 if (!bi) 4540 return NULL; 4541 return bi->uri; 4542 } 4543 4544 4545 int dpp_bootstrap_info(struct dpp_global *dpp, int id, 4546 char *reply, int reply_size) 4547 { 4548 struct dpp_bootstrap_info *bi; 4549 char pkhash[2 * SHA256_MAC_LEN + 1]; 4550 char supp_curves[100]; 4551 char host[100]; 4552 int ret; 4553 4554 bi = dpp_bootstrap_get_id(dpp, id); 4555 if (!bi) 4556 return -1; 4557 wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash, 4558 SHA256_MAC_LEN); 4559 4560 supp_curves[0] = '\0'; 4561 if (bi->supported_curves) { 4562 size_t i; 4563 char *pos = supp_curves; 4564 char *end = &supp_curves[sizeof(supp_curves)]; 4565 const char *curve[6] = { "P-256", "P-384", "P-521", 4566 "BP-256", "BP-384", "BP-512" }; 4567 4568 ret = os_snprintf(pos, end - pos, "supp_curves="); 4569 if (os_snprintf_error(end - pos, ret)) 4570 return -1; 4571 pos += ret; 4572 4573 for (i = 0; i < ARRAY_SIZE(curve); i++) { 4574 if (!(bi->supported_curves & BIT(i))) 4575 continue; 4576 ret = os_snprintf(pos, end - pos, "%s:", curve[i]); 4577 if (os_snprintf_error(end - pos, ret)) 4578 return -1; 4579 pos += ret; 4580 } 4581 4582 if (pos[-1] == ':') 4583 pos[-1] = '\n'; 4584 else 4585 supp_curves[0] = '\0'; 4586 } 4587 4588 host[0] = '\0'; 4589 if (bi->host) { 4590 char buf[100]; 4591 4592 ret = os_snprintf(host, sizeof(host), "host=%s %u\n", 4593 hostapd_ip_txt(bi->host, buf, sizeof(buf)), 4594 bi->port); 4595 if (os_snprintf_error(sizeof(host), ret)) 4596 return -1; 4597 } 4598 4599 return os_snprintf(reply, reply_size, "type=%s\n" 4600 "mac_addr=" MACSTR "\n" 4601 "info=%s\n" 4602 "num_freq=%u\n" 4603 "use_freq=%u\n" 4604 "curve=%s\n" 4605 "pkhash=%s\n" 4606 "version=%d\n%s%s", 4607 dpp_bootstrap_type_txt(bi->type), 4608 MAC2STR(bi->mac_addr), 4609 bi->info ? bi->info : "", 4610 bi->num_freq, 4611 bi->num_freq == 1 ? bi->freq[0] : 0, 4612 bi->curve->name, 4613 pkhash, 4614 bi->version, 4615 supp_curves, 4616 host); 4617 } 4618 4619 4620 int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params) 4621 { 4622 struct dpp_bootstrap_info *bi; 4623 4624 bi = dpp_bootstrap_get_id(dpp, id); 4625 if (!bi) 4626 return -1; 4627 4628 str_clear_free(bi->configurator_params); 4629 4630 if (params) { 4631 bi->configurator_params = os_strdup(params); 4632 return bi->configurator_params ? 0 : -1; 4633 } 4634 4635 bi->configurator_params = NULL; 4636 return 0; 4637 } 4638 4639 4640 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, 4641 const u8 *r_bootstrap, 4642 struct dpp_bootstrap_info **own_bi, 4643 struct dpp_bootstrap_info **peer_bi) 4644 { 4645 struct dpp_bootstrap_info *bi; 4646 4647 *own_bi = NULL; 4648 *peer_bi = NULL; 4649 if (!dpp) 4650 return; 4651 4652 dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { 4653 if (!*own_bi && bi->own && 4654 os_memcmp(bi->pubkey_hash, r_bootstrap, 4655 SHA256_MAC_LEN) == 0) { 4656 wpa_printf(MSG_DEBUG, 4657 "DPP: Found matching own bootstrapping information"); 4658 *own_bi = bi; 4659 } 4660 4661 if (!*peer_bi && !bi->own && 4662 os_memcmp(bi->pubkey_hash, i_bootstrap, 4663 SHA256_MAC_LEN) == 0) { 4664 wpa_printf(MSG_DEBUG, 4665 "DPP: Found matching peer bootstrapping information"); 4666 *peer_bi = bi; 4667 } 4668 4669 if (*own_bi && *peer_bi) 4670 break; 4671 } 4672 } 4673 4674 4675 #ifdef CONFIG_DPP2 4676 struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, 4677 const u8 *hash) 4678 { 4679 struct dpp_bootstrap_info *bi; 4680 4681 if (!dpp) 4682 return NULL; 4683 4684 dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { 4685 if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash, 4686 SHA256_MAC_LEN) == 0) 4687 return bi; 4688 } 4689 4690 return NULL; 4691 } 4692 #endif /* CONFIG_DPP2 */ 4693 4694 4695 static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, 4696 struct dpp_bootstrap_info *peer_bi) 4697 { 4698 unsigned int i, freq = 0; 4699 enum hostapd_hw_mode mode; 4700 u8 op_class, channel; 4701 char chan[20]; 4702 4703 if (peer_bi->num_freq == 0 && !peer_bi->channels_listed) 4704 return 0; /* no channel preference/constraint */ 4705 4706 for (i = 0; i < peer_bi->num_freq; i++) { 4707 if ((own_bi->num_freq == 0 && !own_bi->channels_listed) || 4708 freq_included(own_bi->freq, own_bi->num_freq, 4709 peer_bi->freq[i])) { 4710 freq = peer_bi->freq[i]; 4711 break; 4712 } 4713 } 4714 if (!freq) { 4715 wpa_printf(MSG_DEBUG, "DPP: No common channel found"); 4716 return -1; 4717 } 4718 4719 mode = ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, &channel); 4720 if (mode == NUM_HOSTAPD_MODES) { 4721 wpa_printf(MSG_DEBUG, 4722 "DPP: Could not determine operating class or channel number for %u MHz", 4723 freq); 4724 } 4725 4726 wpa_printf(MSG_DEBUG, 4727 "DPP: Selected %u MHz (op_class %u channel %u) as the negotiation channel based on information from NFC negotiated handover", 4728 freq, op_class, channel); 4729 os_snprintf(chan, sizeof(chan), "%u/%u", op_class, channel); 4730 os_free(own_bi->chan); 4731 own_bi->chan = os_strdup(chan); 4732 own_bi->freq[0] = freq; 4733 own_bi->num_freq = 1; 4734 os_free(peer_bi->chan); 4735 peer_bi->chan = os_strdup(chan); 4736 peer_bi->freq[0] = freq; 4737 peer_bi->num_freq = 1; 4738 4739 return dpp_gen_uri(own_bi); 4740 } 4741 4742 4743 static int dpp_nfc_update_bi_key(struct dpp_bootstrap_info *own_bi, 4744 struct dpp_bootstrap_info *peer_bi) 4745 { 4746 if (peer_bi->curve == own_bi->curve) 4747 return 0; 4748 4749 wpa_printf(MSG_DEBUG, 4750 "DPP: Update own bootstrapping key to match peer curve from NFC handover"); 4751 4752 crypto_ec_key_deinit(own_bi->pubkey); 4753 own_bi->pubkey = NULL; 4754 4755 if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 || 4756 dpp_gen_uri(own_bi) < 0) 4757 goto fail; 4758 4759 return 0; 4760 fail: 4761 dl_list_del(&own_bi->list); 4762 dpp_bootstrap_info_free(own_bi); 4763 return -1; 4764 } 4765 4766 4767 int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi, 4768 struct dpp_bootstrap_info *peer_bi) 4769 { 4770 if (dpp_nfc_update_bi_channel(own_bi, peer_bi) < 0 || 4771 dpp_nfc_update_bi_key(own_bi, peer_bi) < 0) 4772 return -1; 4773 return 0; 4774 } 4775 4776 4777 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) 4778 { 4779 struct dpp_configurator *conf; 4780 unsigned int max_id = 0; 4781 4782 dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator, 4783 list) { 4784 if (conf->id > max_id) 4785 max_id = conf->id; 4786 } 4787 return max_id + 1; 4788 } 4789 4790 4791 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) 4792 { 4793 char *curve; 4794 char *key = NULL, *ppkey = NULL; 4795 u8 *privkey = NULL, *pp_key = NULL; 4796 size_t privkey_len = 0, pp_key_len = 0; 4797 int ret = -1; 4798 struct dpp_configurator *conf = NULL; 4799 const struct dpp_curve_params *net_access_key_curve = NULL; 4800 4801 curve = get_param(cmd, " net_access_key_curve="); 4802 if (curve) { 4803 net_access_key_curve = dpp_get_curve_name(curve); 4804 if (!net_access_key_curve) { 4805 wpa_printf(MSG_DEBUG, 4806 "DPP: Unsupported net_access_key_curve: %s", 4807 curve); 4808 goto fail; 4809 } 4810 os_free(curve); 4811 } 4812 4813 curve = get_param(cmd, " curve="); 4814 key = get_param(cmd, " key="); 4815 ppkey = get_param(cmd, " ppkey="); 4816 4817 if (key) { 4818 privkey_len = os_strlen(key) / 2; 4819 privkey = os_malloc(privkey_len); 4820 if (!privkey || 4821 hexstr2bin(key, privkey, privkey_len) < 0) 4822 goto fail; 4823 } 4824 4825 if (ppkey) { 4826 pp_key_len = os_strlen(ppkey) / 2; 4827 pp_key = os_malloc(pp_key_len); 4828 if (!pp_key || 4829 hexstr2bin(ppkey, pp_key, pp_key_len) < 0) 4830 goto fail; 4831 } 4832 4833 conf = dpp_keygen_configurator(curve, privkey, privkey_len, 4834 pp_key, pp_key_len); 4835 if (!conf) 4836 goto fail; 4837 4838 conf->net_access_key_curve = net_access_key_curve; 4839 conf->id = dpp_next_configurator_id(dpp); 4840 dl_list_add(&dpp->configurator, &conf->list); 4841 ret = conf->id; 4842 conf = NULL; 4843 fail: 4844 os_free(curve); 4845 str_clear_free(key); 4846 str_clear_free(ppkey); 4847 bin_clear_free(privkey, privkey_len); 4848 bin_clear_free(pp_key, pp_key_len); 4849 dpp_configurator_free(conf); 4850 return ret; 4851 } 4852 4853 4854 int dpp_configurator_set(struct dpp_global *dpp, const char *cmd) 4855 { 4856 unsigned int id; 4857 struct dpp_configurator *conf; 4858 char *curve; 4859 4860 id = atoi(cmd); 4861 conf = dpp_configurator_get_id(dpp, id); 4862 if (!conf) 4863 return -1; 4864 4865 curve = get_param(cmd, " net_access_key_curve="); 4866 if (curve) { 4867 const struct dpp_curve_params *net_access_key_curve; 4868 4869 net_access_key_curve = dpp_get_curve_name(curve); 4870 os_free(curve); 4871 if (!net_access_key_curve) 4872 return -1; 4873 conf->net_access_key_curve = net_access_key_curve; 4874 } 4875 4876 return 0; 4877 } 4878 4879 4880 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id) 4881 { 4882 struct dpp_configurator *conf, *tmp; 4883 int found = 0; 4884 4885 if (!dpp) 4886 return -1; 4887 4888 dl_list_for_each_safe(conf, tmp, &dpp->configurator, 4889 struct dpp_configurator, list) { 4890 if (id && conf->id != id) 4891 continue; 4892 found = 1; 4893 dl_list_del(&conf->list); 4894 dpp_configurator_free(conf); 4895 } 4896 4897 if (id == 0) 4898 return 0; /* flush succeeds regardless of entries found */ 4899 return found ? 0 : -1; 4900 } 4901 4902 4903 int dpp_configurator_remove(struct dpp_global *dpp, const char *id) 4904 { 4905 unsigned int id_val; 4906 4907 if (os_strcmp(id, "*") == 0) { 4908 id_val = 0; 4909 } else { 4910 id_val = atoi(id); 4911 if (id_val == 0) 4912 return -1; 4913 } 4914 4915 return dpp_configurator_del(dpp, id_val); 4916 } 4917 4918 4919 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, 4920 char *buf, size_t buflen) 4921 { 4922 struct dpp_configurator *conf; 4923 4924 conf = dpp_configurator_get_id(dpp, id); 4925 if (!conf) 4926 return -1; 4927 4928 return dpp_configurator_get_key(conf, buf, buflen); 4929 } 4930 4931 4932 #ifdef CONFIG_DPP2 4933 4934 int dpp_configurator_from_backup(struct dpp_global *dpp, 4935 struct dpp_asymmetric_key *key) 4936 { 4937 struct dpp_configurator *conf; 4938 const struct dpp_curve_params *curve, *curve_pp; 4939 4940 if (!key->csign || !key->pp_key) 4941 return -1; 4942 4943 curve = dpp_get_curve_ike_group(crypto_ec_key_group(key->csign)); 4944 if (!curve) { 4945 wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key"); 4946 return -1; 4947 } 4948 4949 curve_pp = dpp_get_curve_ike_group(crypto_ec_key_group(key->pp_key)); 4950 if (!curve_pp) { 4951 wpa_printf(MSG_INFO, "DPP: Unsupported group in ppKey"); 4952 return -1; 4953 } 4954 4955 if (curve != curve_pp) { 4956 wpa_printf(MSG_INFO, 4957 "DPP: Mismatch in c-sign-key and ppKey groups"); 4958 return -1; 4959 } 4960 4961 conf = os_zalloc(sizeof(*conf)); 4962 if (!conf) 4963 return -1; 4964 conf->curve = curve; 4965 conf->csign = key->csign; 4966 key->csign = NULL; 4967 conf->pp_key = key->pp_key; 4968 key->pp_key = NULL; 4969 conf->own = 1; 4970 if (dpp_configurator_gen_kid(conf) < 0) { 4971 dpp_configurator_free(conf); 4972 return -1; 4973 } 4974 4975 conf->id = dpp_next_configurator_id(dpp); 4976 dl_list_add(&dpp->configurator, &conf->list); 4977 return conf->id; 4978 } 4979 4980 4981 struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, 4982 const u8 *kid) 4983 { 4984 struct dpp_configurator *conf; 4985 4986 if (!dpp) 4987 return NULL; 4988 4989 dl_list_for_each(conf, &dpp->configurator, 4990 struct dpp_configurator, list) { 4991 if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0) 4992 return conf; 4993 } 4994 return NULL; 4995 } 4996 4997 #endif /* CONFIG_DPP2 */ 4998 4999 5000 struct dpp_global * dpp_global_init(struct dpp_global_config *config) 5001 { 5002 struct dpp_global *dpp; 5003 5004 dpp = os_zalloc(sizeof(*dpp)); 5005 if (!dpp) 5006 return NULL; 5007 #ifdef CONFIG_DPP2 5008 dpp->cb_ctx = config->cb_ctx; 5009 dpp->remove_bi = config->remove_bi; 5010 #endif /* CONFIG_DPP2 */ 5011 5012 dl_list_init(&dpp->bootstrap); 5013 dl_list_init(&dpp->configurator); 5014 #ifdef CONFIG_DPP2 5015 dl_list_init(&dpp->controllers); 5016 dl_list_init(&dpp->tcp_init); 5017 dpp->relay_sock = -1; 5018 #endif /* CONFIG_DPP2 */ 5019 5020 return dpp; 5021 } 5022 5023 5024 void dpp_global_clear(struct dpp_global *dpp) 5025 { 5026 if (!dpp) 5027 return; 5028 5029 dpp_bootstrap_del(dpp, 0); 5030 dpp_configurator_del(dpp, 0); 5031 #ifdef CONFIG_DPP2 5032 dpp_tcp_init_flush(dpp); 5033 dpp_relay_flush_controllers(dpp); 5034 dpp_controller_stop(dpp); 5035 #endif /* CONFIG_DPP2 */ 5036 } 5037 5038 5039 void dpp_global_deinit(struct dpp_global *dpp) 5040 { 5041 dpp_global_clear(dpp); 5042 os_free(dpp); 5043 } 5044 5045 5046 void dpp_notify_auth_success(struct dpp_authentication *auth, int initiator) 5047 { 5048 u8 hash[SHA256_MAC_LEN]; 5049 char hex[SHA256_MAC_LEN * 2 + 1]; 5050 5051 if (auth->peer_protocol_key) { 5052 dpp_get_pubkey_hash(auth->peer_protocol_key, hash); 5053 wpa_snprintf_hex(hex, sizeof(hex), hash, sizeof(hash)); 5054 } else { 5055 hex[0] = '\0'; 5056 } 5057 wpa_msg(auth->msg_ctx, MSG_INFO, 5058 DPP_EVENT_AUTH_SUCCESS "init=%d pkhash=%s own=%d peer=%d", 5059 initiator, hex, auth->own_bi ? (int) auth->own_bi->id : -1, 5060 auth->peer_bi ? (int) auth->peer_bi->id : -1); 5061 } 5062 5063 5064 #ifdef CONFIG_DPP2 5065 5066 struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) 5067 { 5068 struct wpabuf *msg; 5069 5070 wpa_printf(MSG_DEBUG, "DPP: Build Presence Announcement frame"); 5071 5072 msg = dpp_alloc_msg(DPP_PA_PRESENCE_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); 5073 if (!msg) 5074 return NULL; 5075 5076 /* Responder Bootstrapping Key Hash */ 5077 dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp); 5078 wpa_hexdump_buf(MSG_DEBUG, 5079 "DPP: Presence Announcement frame attributes", msg); 5080 return msg; 5081 } 5082 5083 5084 void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, 5085 unsigned int freq, const u8 *hash) 5086 { 5087 char hex[SHA256_MAC_LEN * 2 + 1]; 5088 5089 wpa_snprintf_hex(hex, sizeof(hex), hash, SHA256_MAC_LEN); 5090 wpa_msg(msg_ctx, MSG_INFO, 5091 DPP_EVENT_CHIRP_RX "id=%d src=" MACSTR " freq=%u hash=%s", 5092 id, MAC2STR(src), freq, hex); 5093 } 5094 5095 #endif /* CONFIG_DPP2 */ 5096 5097 5098 #ifdef CONFIG_DPP3 5099 5100 struct wpabuf * dpp_build_pb_announcement(struct dpp_bootstrap_info *bi) 5101 { 5102 struct wpabuf *msg; 5103 const u8 *r_hash = bi->pubkey_hash_chirp; 5104 #ifdef CONFIG_TESTING_OPTIONS 5105 u8 test_hash[SHA256_MAC_LEN]; 5106 #endif /* CONFIG_TESTING_OPTIONS */ 5107 5108 wpa_printf(MSG_DEBUG, 5109 "DPP: Build Push Button Presence Announcement frame"); 5110 5111 msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT, 5112 4 + SHA256_MAC_LEN); 5113 if (!msg) 5114 return NULL; 5115 5116 #ifdef CONFIG_TESTING_OPTIONS 5117 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ) { 5118 wpa_printf(MSG_INFO, 5119 "DPP: TESTING - invalid R-Bootstrap Key Hash"); 5120 os_memcpy(test_hash, r_hash, SHA256_MAC_LEN); 5121 test_hash[SHA256_MAC_LEN - 1] ^= 0x01; 5122 r_hash = test_hash; 5123 } 5124 #endif /* CONFIG_TESTING_OPTIONS */ 5125 5126 /* Responder Bootstrapping Key Hash */ 5127 dpp_build_attr_r_bootstrap_key_hash(msg, r_hash); 5128 wpa_hexdump_buf(MSG_DEBUG, 5129 "DPP: Push Button Presence Announcement frame attributes", 5130 msg); 5131 return msg; 5132 } 5133 5134 5135 struct wpabuf * dpp_build_pb_announcement_resp(struct dpp_bootstrap_info *bi, 5136 const u8 *e_hash, 5137 const u8 *c_nonce, 5138 size_t c_nonce_len) 5139 { 5140 struct wpabuf *msg; 5141 const u8 *i_hash = bi->pubkey_hash_chirp; 5142 #ifdef CONFIG_TESTING_OPTIONS 5143 u8 test_hash[SHA256_MAC_LEN]; 5144 #endif /* CONFIG_TESTING_OPTIONS */ 5145 5146 wpa_printf(MSG_DEBUG, 5147 "DPP: Build Push Button Presence Announcement Response frame"); 5148 5149 msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP, 5150 2 * (4 + SHA256_MAC_LEN) + 4 + c_nonce_len); 5151 if (!msg) 5152 return NULL; 5153 5154 #ifdef CONFIG_TESTING_OPTIONS 5155 if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_PB_RESP) { 5156 wpa_printf(MSG_INFO, 5157 "DPP: TESTING - invalid I-Bootstrap Key Hash"); 5158 os_memcpy(test_hash, i_hash, SHA256_MAC_LEN); 5159 test_hash[SHA256_MAC_LEN - 1] ^= 0x01; 5160 i_hash = test_hash; 5161 } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_RESP) { 5162 wpa_printf(MSG_INFO, 5163 "DPP: TESTING - invalid R-Bootstrap Key Hash"); 5164 os_memcpy(test_hash, e_hash, SHA256_MAC_LEN); 5165 test_hash[SHA256_MAC_LEN - 1] ^= 0x01; 5166 e_hash = test_hash; 5167 } 5168 #endif /* CONFIG_TESTING_OPTIONS */ 5169 5170 /* Initiator Bootstrapping Key Hash */ 5171 wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); 5172 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); 5173 wpabuf_put_le16(msg, SHA256_MAC_LEN); 5174 wpabuf_put_data(msg, i_hash, SHA256_MAC_LEN); 5175 5176 /* Responder Bootstrapping Key Hash */ 5177 dpp_build_attr_r_bootstrap_key_hash(msg, e_hash); 5178 5179 /* Configurator Nonce */ 5180 wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE); 5181 wpabuf_put_le16(msg, c_nonce_len); 5182 wpabuf_put_data(msg, c_nonce, c_nonce_len); 5183 5184 wpa_hexdump_buf(MSG_DEBUG, 5185 "DPP: Push Button Presence Announcement Response frame attributes", 5186 msg); 5187 return msg; 5188 } 5189 5190 #endif /* CONFIG_DPP3 */ 5191