1 /* 2 * DPP reconfiguration 3 * Copyright (c) 2020, The Linux Foundation 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #include "utils/common.h" 12 #include "utils/json.h" 13 #include "crypto/crypto.h" 14 #include "crypto/random.h" 15 #include "crypto/aes.h" 16 #include "crypto/aes_siv.h" 17 #include "dpp.h" 18 #include "dpp_i.h" 19 20 21 #ifdef CONFIG_DPP2 22 23 static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) 24 { 25 if (hash) { 26 wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash"); 27 wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH); 28 wpabuf_put_le16(msg, SHA256_MAC_LEN); 29 wpabuf_put_data(msg, hash, SHA256_MAC_LEN); 30 } 31 } 32 33 34 struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, 35 size_t csign_key_len, 36 const u8 *net_access_key, 37 size_t net_access_key_len, 38 struct dpp_reconfig_id *id) 39 { 40 struct wpabuf *msg = NULL; 41 struct crypto_ec_key *csign = NULL; 42 struct wpabuf *uncomp; 43 u8 hash[SHA256_MAC_LEN]; 44 const u8 *addr[1]; 45 size_t len[1]; 46 int res; 47 size_t attr_len; 48 const struct dpp_curve_params *own_curve; 49 struct crypto_ec_key *own_key; 50 struct wpabuf *a_nonce = NULL, *e_id = NULL; 51 52 wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); 53 54 own_key = dpp_set_keypair(&own_curve, net_access_key, 55 net_access_key_len); 56 if (!own_key) { 57 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 58 goto fail; 59 } 60 61 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 62 if (!csign) { 63 wpa_printf(MSG_ERROR, 64 "DPP: Failed to parse local C-sign-key information"); 65 goto fail; 66 } 67 68 uncomp = crypto_ec_key_get_pubkey_point(csign, 1); 69 crypto_ec_key_deinit(csign); 70 if (!uncomp) 71 goto fail; 72 addr[0] = wpabuf_head(uncomp); 73 len[0] = wpabuf_len(uncomp); 74 wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]); 75 res = sha256_vector(1, addr, len, hash); 76 wpabuf_free(uncomp); 77 if (res < 0) 78 goto fail; 79 wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", 80 hash, SHA256_MAC_LEN); 81 82 if (dpp_update_reconfig_id(id) < 0) { 83 wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id"); 84 goto fail; 85 } 86 87 a_nonce = crypto_ec_key_get_pubkey_point(id->a_nonce, 0); 88 e_id = crypto_ec_key_get_pubkey_point(id->e_prime_id, 0); 89 if (!a_nonce || !e_id) 90 goto fail; 91 92 attr_len = 4 + SHA256_MAC_LEN; 93 attr_len += 4 + 2; 94 attr_len += 4 + wpabuf_len(a_nonce); 95 attr_len += 4 + wpabuf_len(e_id); 96 msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len); 97 if (!msg) 98 goto fail; 99 100 /* Configurator C-sign key Hash */ 101 dpp_build_attr_csign_key_hash(msg, hash); 102 103 /* Finite Cyclic Group attribute */ 104 wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", 105 own_curve->ike_group); 106 wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); 107 wpabuf_put_le16(msg, 2); 108 wpabuf_put_le16(msg, own_curve->ike_group); 109 110 /* A-NONCE */ 111 wpabuf_put_le16(msg, DPP_ATTR_A_NONCE); 112 wpabuf_put_le16(msg, wpabuf_len(a_nonce)); 113 wpabuf_put_buf(msg, a_nonce); 114 115 /* E'-id */ 116 wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID); 117 wpabuf_put_le16(msg, wpabuf_len(e_id)); 118 wpabuf_put_buf(msg, e_id); 119 120 wpa_hexdump_buf(MSG_DEBUG, 121 "DPP: Reconfig Announcement frame attributes", msg); 122 fail: 123 wpabuf_free(a_nonce); 124 wpabuf_free(e_id); 125 crypto_ec_key_deinit(own_key); 126 return msg; 127 } 128 129 130 static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) 131 { 132 struct wpabuf *msg; 133 size_t attr_len; 134 135 /* Build DPP Reconfig Authentication Request frame attributes */ 136 attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) + 137 4 + auth->curve->nonce_len; 138 msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_REQ, attr_len); 139 if (!msg) 140 return NULL; 141 142 /* Transaction ID */ 143 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); 144 wpabuf_put_le16(msg, 1); 145 wpabuf_put_u8(msg, auth->transaction_id); 146 147 /* Protocol Version */ 148 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); 149 wpabuf_put_le16(msg, 1); 150 wpabuf_put_u8(msg, DPP_VERSION); 151 152 /* DPP Connector */ 153 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 154 wpabuf_put_le16(msg, os_strlen(auth->conf->connector)); 155 wpabuf_put_str(msg, auth->conf->connector); 156 157 /* C-nonce */ 158 wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE); 159 wpabuf_put_le16(msg, auth->curve->nonce_len); 160 wpabuf_put_data(msg, auth->c_nonce, auth->curve->nonce_len); 161 162 wpa_hexdump_buf(MSG_DEBUG, 163 "DPP: Reconfig Authentication Request frame attributes", 164 msg); 165 166 return msg; 167 } 168 169 170 static int 171 dpp_configurator_build_own_connector(struct dpp_configurator *conf, 172 const struct dpp_curve_params *curve) 173 { 174 struct wpabuf *dppcon = NULL; 175 int ret = -1; 176 177 if (conf->connector) 178 return 0; /* already generated */ 179 180 wpa_printf(MSG_DEBUG, 181 "DPP: Sign own Configurator Connector for reconfiguration with curve %s", 182 conf->curve->name); 183 conf->connector_key = dpp_gen_keypair(curve); 184 if (!conf->connector_key) 185 goto fail; 186 187 /* Connector (JSON dppCon object) */ 188 dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3); 189 if (!dppcon) 190 goto fail; 191 json_start_object(dppcon, NULL); 192 json_start_array(dppcon, "groups"); 193 json_start_object(dppcon, NULL); 194 json_add_string(dppcon, "groupId", "*"); 195 json_value_sep(dppcon); 196 json_add_string(dppcon, "netRole", "configurator"); 197 json_end_object(dppcon); 198 json_end_array(dppcon); 199 json_value_sep(dppcon); 200 if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL, 201 curve) < 0) { 202 wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); 203 goto fail; 204 } 205 json_end_object(dppcon); 206 wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", 207 (const char *) wpabuf_head(dppcon)); 208 209 conf->connector = dpp_sign_connector(conf, dppcon); 210 if (!conf->connector) 211 goto fail; 212 wpa_printf(MSG_DEBUG, "DPP: signedConnector: %s", conf->connector); 213 214 ret = 0; 215 fail: 216 wpabuf_free(dppcon); 217 return ret; 218 } 219 220 221 struct dpp_authentication * 222 dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, 223 struct dpp_configurator *conf, unsigned int freq, u16 group, 224 const u8 *a_nonce_attr, size_t a_nonce_len, 225 const u8 *e_id_attr, size_t e_id_len) 226 { 227 struct dpp_authentication *auth; 228 const struct dpp_curve_params *curve; 229 struct crypto_ec_key *a_nonce, *e_prime_id; 230 struct crypto_ec_point *e_id; 231 232 curve = dpp_get_curve_ike_group(group); 233 if (!curve) { 234 wpa_printf(MSG_DEBUG, 235 "DPP: Unsupported group %u - cannot reconfigure", 236 group); 237 return NULL; 238 } 239 240 if (!a_nonce_attr) { 241 wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute"); 242 return NULL; 243 } 244 wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len); 245 a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len); 246 if (!a_nonce) { 247 wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE"); 248 return NULL; 249 } 250 dpp_debug_print_key("A-NONCE", a_nonce); 251 252 if (!e_id_attr) { 253 wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute"); 254 return NULL; 255 } 256 e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len); 257 if (!e_prime_id) { 258 wpa_printf(MSG_INFO, "DPP: Invalid E'-id"); 259 crypto_ec_key_deinit(a_nonce); 260 return NULL; 261 } 262 dpp_debug_print_key("E'-id", e_prime_id); 263 e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id); 264 crypto_ec_key_deinit(a_nonce); 265 crypto_ec_key_deinit(e_prime_id); 266 if (!e_id) { 267 wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id"); 268 return NULL; 269 } 270 /* TODO: could use E-id to determine whether reconfiguration with this 271 * Enrollee has already been started and is waiting for updated 272 * configuration instead of replying again before such configuration 273 * becomes available */ 274 crypto_ec_point_deinit(e_id, 1); 275 276 auth = dpp_alloc_auth(dpp, msg_ctx); 277 if (!auth) 278 return NULL; 279 280 auth->conf = conf; 281 auth->reconfig = 1; 282 auth->initiator = 1; 283 auth->waiting_auth_resp = 1; 284 auth->allowed_roles = DPP_CAPAB_CONFIGURATOR; 285 auth->configurator = 1; 286 auth->curve = curve; 287 auth->transaction_id = 1; 288 if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) 289 goto fail; 290 291 if (dpp_configurator_build_own_connector(conf, curve) < 0) 292 goto fail; 293 294 if (random_get_bytes(auth->c_nonce, auth->curve->nonce_len)) { 295 wpa_printf(MSG_ERROR, "DPP: Failed to generate C-nonce"); 296 goto fail; 297 } 298 299 auth->reconfig_req_msg = dpp_reconfig_build_req(auth); 300 if (!auth->reconfig_req_msg) 301 goto fail; 302 303 out: 304 return auth; 305 fail: 306 dpp_auth_deinit(auth); 307 auth = NULL; 308 goto out; 309 } 310 311 312 static int dpp_reconfig_build_resp(struct dpp_authentication *auth, 313 const char *own_connector, 314 struct wpabuf *conn_status) 315 { 316 struct wpabuf *msg = NULL, *clear, *pr = NULL; 317 u8 *attr_start, *attr_end; 318 size_t clear_len, attr_len, len[2]; 319 const u8 *addr[2]; 320 u8 *wrapped; 321 int res = -1; 322 323 /* Build DPP Reconfig Authentication Response frame attributes */ 324 clear_len = 4 + auth->curve->nonce_len + 325 4 + wpabuf_len(conn_status); 326 clear = wpabuf_alloc(clear_len); 327 if (!clear) 328 goto fail; 329 330 /* C-nonce (wrapped) */ 331 wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); 332 wpabuf_put_le16(clear, auth->curve->nonce_len); 333 wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); 334 335 /* Connection Status (wrapped) */ 336 wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); 337 wpabuf_put_le16(clear, wpabuf_len(conn_status)); 338 wpabuf_put_buf(clear, conn_status); 339 340 pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 341 if (!pr) 342 goto fail; 343 344 attr_len = 4 + 1 + 4 + 1 + 345 4 + os_strlen(own_connector) + 346 4 + auth->curve->nonce_len + 347 4 + wpabuf_len(pr) + 348 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; 349 msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len); 350 if (!msg) 351 goto fail; 352 353 attr_start = wpabuf_put(msg, 0); 354 355 /* Transaction ID */ 356 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); 357 wpabuf_put_le16(msg, 1); 358 wpabuf_put_u8(msg, auth->transaction_id); 359 360 /* Protocol Version */ 361 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); 362 wpabuf_put_le16(msg, 1); 363 wpabuf_put_u8(msg, DPP_VERSION); 364 365 /* R-Connector */ 366 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 367 wpabuf_put_le16(msg, os_strlen(own_connector)); 368 wpabuf_put_str(msg, own_connector); 369 370 /* E-nonce */ 371 wpabuf_put_le16(msg, DPP_ATTR_ENROLLEE_NONCE); 372 wpabuf_put_le16(msg, auth->curve->nonce_len); 373 wpabuf_put_data(msg, auth->e_nonce, auth->curve->nonce_len); 374 375 /* Responder Protocol Key (Pr) */ 376 wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); 377 wpabuf_put_le16(msg, wpabuf_len(pr)); 378 wpabuf_put_buf(msg, pr); 379 380 attr_end = wpabuf_put(msg, 0); 381 382 /* OUI, OUI type, Crypto Suite, DPP frame type */ 383 addr[0] = wpabuf_head_u8(msg) + 2; 384 len[0] = 3 + 1 + 1 + 1; 385 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 386 387 /* Attributes before Wrapped Data */ 388 addr[1] = attr_start; 389 len[1] = attr_end - attr_start; 390 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 391 392 /* Wrapped Data: {C-nonce, E-nonce, Connection Status}ke */ 393 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 394 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 395 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 396 397 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 398 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 399 wpabuf_head(clear), wpabuf_len(clear), 400 2, addr, len, wrapped) < 0) 401 goto fail; 402 403 wpa_hexdump_buf(MSG_DEBUG, 404 "DPP: Reconfig Authentication Response frame attributes", 405 msg); 406 407 wpabuf_free(auth->reconfig_resp_msg); 408 auth->reconfig_resp_msg = msg; 409 410 res = 0; 411 out: 412 wpabuf_free(clear); 413 wpabuf_free(pr); 414 return res; 415 fail: 416 wpabuf_free(msg); 417 goto out; 418 } 419 420 421 struct dpp_authentication * 422 dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, 423 const char *own_connector, 424 const u8 *net_access_key, size_t net_access_key_len, 425 const u8 *csign_key, size_t csign_key_len, 426 unsigned int freq, const u8 *hdr, 427 const u8 *attr_start, size_t attr_len) 428 { 429 struct dpp_authentication *auth = NULL; 430 const u8 *trans_id, *version, *i_connector, *c_nonce; 431 u16 trans_id_len, version_len, i_connector_len, c_nonce_len; 432 struct dpp_signed_connector_info info; 433 enum dpp_status_error res; 434 struct json_token *root = NULL, *own_root = NULL, *token; 435 unsigned char *own_conn = NULL; 436 struct wpabuf *conn_status = NULL; 437 438 os_memset(&info, 0, sizeof(info)); 439 440 trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, 441 &trans_id_len); 442 if (!trans_id || trans_id_len != 1) { 443 wpa_printf(MSG_DEBUG, 444 "DPP: Peer did not include Transaction ID"); 445 goto fail; 446 } 447 448 version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, 449 &version_len); 450 if (!version || version_len < 1 || version[0] < 2) { 451 wpa_printf(MSG_DEBUG, 452 "DPP: Missing or invalid Protocol Version attribute"); 453 goto fail; 454 } 455 456 i_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, 457 &i_connector_len); 458 if (!i_connector) { 459 wpa_printf(MSG_DEBUG, "DPP: Missing I-Connector attribute"); 460 goto fail; 461 } 462 wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector", 463 i_connector, i_connector_len); 464 465 c_nonce = dpp_get_attr(attr_start, attr_len, 466 DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); 467 if (!c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) { 468 wpa_printf(MSG_DEBUG, 469 "DPP: Missing or invalid C-nonce attribute"); 470 goto fail; 471 } 472 wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); 473 474 res = dpp_check_signed_connector(&info, csign_key, csign_key_len, 475 i_connector, i_connector_len); 476 if (res != DPP_STATUS_OK) { 477 wpa_printf(MSG_DEBUG, "DPP: Invalid I-Connector"); 478 goto fail; 479 } 480 481 root = json_parse((const char *) info.payload, info.payload_len); 482 own_root = dpp_parse_own_connector(own_connector); 483 if (!root || !own_root || 484 !dpp_connector_match_groups(own_root, root, true)) { 485 wpa_printf(MSG_DEBUG, 486 "DPP: I-Connector does not include compatible group netrole with own connector"); 487 goto fail; 488 } 489 490 token = json_get_member(root, "expiry"); 491 if (token && token->type == JSON_STRING && 492 dpp_key_expired(token->string, NULL)) { 493 wpa_printf(MSG_DEBUG, 494 "DPP: I-Connector (netAccessKey) has expired"); 495 goto fail; 496 } 497 498 token = json_get_member(root, "netAccessKey"); 499 if (!token || token->type != JSON_OBJECT) { 500 wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found"); 501 goto fail; 502 } 503 504 auth = dpp_alloc_auth(dpp, msg_ctx); 505 if (!auth) 506 return NULL; 507 508 auth->reconfig = 1; 509 auth->allowed_roles = DPP_CAPAB_ENROLLEE; 510 if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) 511 goto fail; 512 513 auth->transaction_id = trans_id[0]; 514 515 auth->peer_version = version[0]; 516 wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", 517 auth->peer_version); 518 519 os_memcpy(auth->c_nonce, c_nonce, c_nonce_len); 520 521 if (dpp_reconfig_derive_ke_responder(auth, net_access_key, 522 net_access_key_len, token) < 0) 523 goto fail; 524 525 if (c_nonce_len != auth->curve->nonce_len) { 526 wpa_printf(MSG_DEBUG, 527 "DPP: Unexpected C-nonce length %u (curve nonce len %zu)", 528 c_nonce_len, auth->curve->nonce_len); 529 goto fail; 530 } 531 532 /* Build Connection Status object */ 533 /* TODO: Get appropriate result value */ 534 /* TODO: ssid64 and channelList */ 535 conn_status = dpp_build_conn_status(DPP_STATUS_NO_AP, NULL, 0, NULL); 536 if (!conn_status) 537 goto fail; 538 539 if (dpp_reconfig_build_resp(auth, own_connector, conn_status) < 0) 540 goto fail; 541 542 out: 543 os_free(info.payload); 544 os_free(own_conn); 545 json_free(root); 546 json_free(own_root); 547 wpabuf_free(conn_status); 548 return auth; 549 fail: 550 dpp_auth_deinit(auth); 551 auth = NULL; 552 goto out; 553 } 554 555 556 struct wpabuf * 557 dpp_reconfig_build_conf(struct dpp_authentication *auth) 558 { 559 struct wpabuf *msg = NULL, *clear; 560 u8 *attr_start, *attr_end; 561 size_t clear_len, attr_len, len[2]; 562 const u8 *addr[2]; 563 u8 *wrapped; 564 u8 flags; 565 566 /* Build DPP Reconfig Authentication Confirm frame attributes */ 567 clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) + 568 4 + 1; 569 clear = wpabuf_alloc(clear_len); 570 if (!clear) 571 goto fail; 572 573 /* Transaction ID */ 574 wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID); 575 wpabuf_put_le16(clear, 1); 576 wpabuf_put_u8(clear, auth->transaction_id); 577 578 /* Protocol Version */ 579 wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION); 580 wpabuf_put_le16(clear, 1); 581 wpabuf_put_u8(clear, auth->peer_version); 582 583 /* C-nonce (wrapped) */ 584 wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); 585 wpabuf_put_le16(clear, auth->curve->nonce_len); 586 wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); 587 588 /* E-nonce (wrapped) */ 589 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); 590 wpabuf_put_le16(clear, auth->curve->nonce_len); 591 wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len); 592 593 /* Reconfig-Flags (wrapped) */ 594 flags = DPP_CONFIG_REPLACEKEY; 595 wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS); 596 wpabuf_put_le16(clear, 1); 597 wpabuf_put_u8(clear, flags); 598 599 attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; 600 attr_len += 4 + 1; 601 msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len); 602 if (!msg) 603 goto fail; 604 605 attr_start = wpabuf_put(msg, 0); 606 607 /* DPP Status */ 608 dpp_build_attr_status(msg, DPP_STATUS_OK); 609 610 attr_end = wpabuf_put(msg, 0); 611 612 /* OUI, OUI type, Crypto Suite, DPP frame type */ 613 addr[0] = wpabuf_head_u8(msg) + 2; 614 len[0] = 3 + 1 + 1 + 1; 615 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 616 617 /* Attributes before Wrapped Data */ 618 addr[1] = attr_start; 619 len[1] = attr_end - attr_start; 620 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 621 622 /* Wrapped Data */ 623 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); 624 wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 625 wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); 626 627 wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); 628 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, 629 wpabuf_head(clear), wpabuf_len(clear), 630 2, addr, len, wrapped) < 0) 631 goto fail; 632 633 wpa_hexdump_buf(MSG_DEBUG, 634 "DPP: Reconfig Authentication Confirm frame attributes", 635 msg); 636 637 out: 638 wpabuf_free(clear); 639 return msg; 640 fail: 641 wpabuf_free(msg); 642 msg = NULL; 643 goto out; 644 } 645 646 647 struct wpabuf * 648 dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, 649 const u8 *attr_start, size_t attr_len) 650 { 651 const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data, 652 *c_nonce, *e_nonce, *conn_status; 653 u16 trans_id_len, version_len, r_connector_len, r_proto_len, 654 wrapped_data_len, c_nonce_len, e_nonce_len, conn_status_len; 655 struct wpabuf *conf = NULL; 656 char *signed_connector = NULL; 657 struct dpp_signed_connector_info info; 658 enum dpp_status_error res; 659 struct json_token *root = NULL, *token, *conn_status_json = NULL; 660 const u8 *addr[2]; 661 size_t len[2]; 662 u8 *unwrapped = NULL; 663 size_t unwrapped_len = 0; 664 665 os_memset(&info, 0, sizeof(info)); 666 667 if (!auth->reconfig || !auth->configurator) 668 goto fail; 669 670 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, 671 &wrapped_data_len); 672 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 673 dpp_auth_fail(auth, 674 "Missing or invalid required Wrapped Data attribute"); 675 goto fail; 676 } 677 wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", 678 wrapped_data, wrapped_data_len); 679 attr_len = wrapped_data - 4 - attr_start; 680 681 trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, 682 &trans_id_len); 683 if (!trans_id || trans_id_len != 1) { 684 dpp_auth_fail(auth, "Peer did not include Transaction ID"); 685 goto fail; 686 } 687 if (trans_id[0] != auth->transaction_id) { 688 dpp_auth_fail(auth, "Transaction ID mismatch"); 689 goto fail; 690 } 691 692 version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, 693 &version_len); 694 if (!version || version_len < 1 || version[0] < 2) { 695 dpp_auth_fail(auth, 696 "Missing or invalid Protocol Version attribute"); 697 goto fail; 698 } 699 auth->peer_version = version[0]; 700 wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", 701 auth->peer_version); 702 703 r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, 704 &r_connector_len); 705 if (!r_connector) { 706 dpp_auth_fail(auth, " Missing R-Connector attribute"); 707 goto fail; 708 } 709 wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector", 710 r_connector, r_connector_len); 711 712 e_nonce = dpp_get_attr(attr_start, attr_len, 713 DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); 714 if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { 715 dpp_auth_fail(auth, "Missing or invalid E-nonce"); 716 goto fail; 717 } 718 wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); 719 os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); 720 721 r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, 722 &r_proto_len); 723 if (!r_proto) { 724 dpp_auth_fail(auth, 725 "Missing required Responder Protocol Key attribute"); 726 goto fail; 727 } 728 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", 729 r_proto, r_proto_len); 730 731 signed_connector = os_malloc(r_connector_len + 1); 732 if (!signed_connector) 733 goto fail; 734 os_memcpy(signed_connector, r_connector, r_connector_len); 735 signed_connector[r_connector_len] = '\0'; 736 737 res = dpp_process_signed_connector(&info, auth->conf->csign, 738 signed_connector); 739 if (res != DPP_STATUS_OK) { 740 dpp_auth_fail(auth, "Invalid R-Connector"); 741 goto fail; 742 } 743 744 root = json_parse((const char *) info.payload, info.payload_len); 745 if (!root) { 746 dpp_auth_fail(auth, "Invalid Connector payload"); 747 goto fail; 748 } 749 750 /* Do not check netAccessKey expiration for reconfiguration to allow 751 * expired Connector to be updated. */ 752 753 token = json_get_member(root, "netAccessKey"); 754 if (!token || token->type != JSON_OBJECT) { 755 dpp_auth_fail(auth, "No netAccessKey object found"); 756 goto fail; 757 } 758 759 if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len, 760 token) < 0) 761 goto fail; 762 763 addr[0] = hdr; 764 len[0] = DPP_HDR_LEN; 765 addr[1] = attr_start; 766 len[1] = attr_len; 767 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 768 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 769 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 770 wrapped_data, wrapped_data_len); 771 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 772 unwrapped = os_malloc(unwrapped_len); 773 if (!unwrapped) 774 goto fail; 775 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 776 wrapped_data, wrapped_data_len, 777 2, addr, len, unwrapped) < 0) { 778 dpp_auth_fail(auth, "AES-SIV decryption failed"); 779 goto fail; 780 } 781 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 782 unwrapped, unwrapped_len); 783 784 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 785 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 786 goto fail; 787 } 788 789 c_nonce = dpp_get_attr(unwrapped, unwrapped_len, 790 DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); 791 if (!c_nonce || c_nonce_len != auth->curve->nonce_len || 792 os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { 793 dpp_auth_fail(auth, "Missing or invalid C-nonce"); 794 goto fail; 795 } 796 wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); 797 798 conn_status = dpp_get_attr(unwrapped, unwrapped_len, 799 DPP_ATTR_CONN_STATUS, &conn_status_len); 800 if (!conn_status) { 801 dpp_auth_fail(auth, "Missing Connection Status attribute"); 802 goto fail; 803 } 804 wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus", 805 conn_status, conn_status_len); 806 807 conn_status_json = json_parse((const char *) conn_status, 808 conn_status_len); 809 if (!conn_status_json) { 810 dpp_auth_fail(auth, "Could not parse connStatus"); 811 goto fail; 812 } 813 /* TODO: use connStatus information */ 814 815 conf = dpp_reconfig_build_conf(auth); 816 if (conf) 817 auth->reconfig_success = true; 818 819 out: 820 json_free(root); 821 json_free(conn_status_json); 822 bin_clear_free(unwrapped, unwrapped_len); 823 os_free(info.payload); 824 os_free(signed_connector); 825 return conf; 826 fail: 827 wpabuf_free(conf); 828 conf = NULL; 829 goto out; 830 } 831 832 833 int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, 834 const u8 *attr_start, size_t attr_len) 835 { 836 const u8 *trans_id, *version, *wrapped_data, *c_nonce, *e_nonce, 837 *reconfig_flags, *status; 838 u16 trans_id_len, version_len, wrapped_data_len, c_nonce_len, 839 e_nonce_len, reconfig_flags_len, status_len; 840 const u8 *addr[2]; 841 size_t len[2]; 842 u8 *unwrapped = NULL; 843 size_t unwrapped_len = 0; 844 int res = -1; 845 u8 flags; 846 847 if (!auth->reconfig || auth->configurator) 848 goto fail; 849 850 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, 851 &wrapped_data_len); 852 if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { 853 dpp_auth_fail(auth, 854 "Missing or invalid required Wrapped Data attribute"); 855 goto fail; 856 } 857 wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", 858 wrapped_data, wrapped_data_len); 859 attr_len = wrapped_data - 4 - attr_start; 860 861 status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, 862 &status_len); 863 if (!status || status_len < 1) { 864 dpp_auth_fail(auth, 865 "Missing or invalid required DPP Status attribute"); 866 goto fail; 867 } 868 wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); 869 if (status[0] != DPP_STATUS_OK) { 870 dpp_auth_fail(auth, 871 "Reconfiguration did not complete successfully"); 872 goto fail; 873 } 874 875 addr[0] = hdr; 876 len[0] = DPP_HDR_LEN; 877 addr[1] = attr_start; 878 len[1] = attr_len; 879 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); 880 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); 881 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", 882 wrapped_data, wrapped_data_len); 883 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; 884 unwrapped = os_malloc(unwrapped_len); 885 if (!unwrapped) 886 goto fail; 887 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, 888 wrapped_data, wrapped_data_len, 889 2, addr, len, unwrapped) < 0) { 890 dpp_auth_fail(auth, "AES-SIV decryption failed"); 891 goto fail; 892 } 893 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", 894 unwrapped, unwrapped_len); 895 896 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { 897 dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); 898 goto fail; 899 } 900 901 trans_id = dpp_get_attr(unwrapped, unwrapped_len, 902 DPP_ATTR_TRANSACTION_ID, &trans_id_len); 903 if (!trans_id || trans_id_len != 1 || 904 trans_id[0] != auth->transaction_id) { 905 dpp_auth_fail(auth, 906 "Peer did not include valid Transaction ID"); 907 goto fail; 908 } 909 910 version = dpp_get_attr(unwrapped, unwrapped_len, 911 DPP_ATTR_PROTOCOL_VERSION, &version_len); 912 if (!version || version_len < 1 || version[0] != DPP_VERSION) { 913 dpp_auth_fail(auth, 914 "Missing or invalid Protocol Version attribute"); 915 goto fail; 916 } 917 918 c_nonce = dpp_get_attr(unwrapped, unwrapped_len, 919 DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); 920 if (!c_nonce || c_nonce_len != auth->curve->nonce_len || 921 os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { 922 dpp_auth_fail(auth, "Missing or invalid C-nonce"); 923 goto fail; 924 } 925 wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); 926 927 e_nonce = dpp_get_attr(unwrapped, unwrapped_len, 928 DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); 929 if (!e_nonce || e_nonce_len != auth->curve->nonce_len || 930 os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { 931 dpp_auth_fail(auth, "Missing or invalid E-nonce"); 932 goto fail; 933 } 934 wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); 935 936 reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len, 937 DPP_ATTR_RECONFIG_FLAGS, 938 &reconfig_flags_len); 939 if (!reconfig_flags || reconfig_flags_len < 1) { 940 dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags"); 941 goto fail; 942 } 943 flags = reconfig_flags[0] & BIT(0); 944 wpa_printf(MSG_DEBUG, "DPP: Reconfig Flags connectorKey=%u", flags); 945 auth->reconfig_connector_key = flags; 946 947 auth->reconfig_success = true; 948 res = 0; 949 fail: 950 bin_clear_free(unwrapped, unwrapped_len); 951 return res; 952 } 953 954 #endif /* CONFIG_DPP2 */ 955