1 /* 2 * DPP crypto functionality 3 * Copyright (c) 2017, Qualcomm Atheros, Inc. 4 * Copyright (c) 2018-2020, The Linux Foundation 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10 #include "utils/includes.h" 11 12 #include "utils/common.h" 13 #include "utils/base64.h" 14 #include "utils/json.h" 15 #include "common/ieee802_11_defs.h" 16 #include "crypto/crypto.h" 17 #include "crypto/random.h" 18 #include "crypto/sha384.h" 19 #include "crypto/sha512.h" 20 #include "tls/asn1.h" 21 #include "dpp.h" 22 #include "dpp_i.h" 23 24 25 static const struct dpp_curve_params dpp_curves[] = { 26 /* The mandatory to support and the default NIST P-256 curve needs to 27 * be the first entry on this list. */ 28 { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, 29 { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, 30 { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, 31 { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, 32 { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, 33 { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, 34 { NULL, 0, 0, 0, 0, NULL, 0, NULL } 35 }; 36 37 38 const struct dpp_curve_params * dpp_get_curve_name(const char *name) 39 { 40 int i; 41 42 if (!name) 43 return &dpp_curves[0]; 44 45 for (i = 0; dpp_curves[i].name; i++) { 46 if (os_strcmp(name, dpp_curves[i].name) == 0 || 47 (dpp_curves[i].jwk_crv && 48 os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) 49 return &dpp_curves[i]; 50 } 51 return NULL; 52 } 53 54 55 const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) 56 { 57 int i; 58 59 for (i = 0; dpp_curves[i].name; i++) { 60 if (dpp_curves[i].jwk_crv && 61 os_strcmp(name, dpp_curves[i].jwk_crv) == 0) 62 return &dpp_curves[i]; 63 } 64 return NULL; 65 } 66 67 68 const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) 69 { 70 int i; 71 72 for (i = 0; dpp_curves[i].name; i++) { 73 if (dpp_curves[i].ike_group == group) 74 return &dpp_curves[i]; 75 } 76 return NULL; 77 } 78 79 80 void dpp_debug_print_key(const char *title, struct crypto_ec_key *key) 81 { 82 struct wpabuf *der = NULL; 83 84 crypto_ec_key_debug_print(key, title); 85 86 der = crypto_ec_key_get_ecprivate_key(key, true); 87 if (der) { 88 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der); 89 } else { 90 der = crypto_ec_key_get_subject_public_key(key); 91 if (der) 92 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der); 93 } 94 95 wpabuf_clear_free(der); 96 } 97 98 99 static int dpp_hash_vector(const struct dpp_curve_params *curve, 100 size_t num_elem, const u8 *addr[], const size_t *len, 101 u8 *mac) 102 { 103 if (curve->hash_len == 32) 104 return sha256_vector(num_elem, addr, len, mac); 105 if (curve->hash_len == 48) 106 return sha384_vector(num_elem, addr, len, mac); 107 if (curve->hash_len == 64) 108 return sha512_vector(num_elem, addr, len, mac); 109 return -1; 110 } 111 112 113 int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, 114 const char *label, u8 *out, size_t outlen) 115 { 116 if (hash_len == 32) 117 return hmac_sha256_kdf(secret, secret_len, NULL, 118 (const u8 *) label, os_strlen(label), 119 out, outlen); 120 if (hash_len == 48) 121 return hmac_sha384_kdf(secret, secret_len, NULL, 122 (const u8 *) label, os_strlen(label), 123 out, outlen); 124 if (hash_len == 64) 125 return hmac_sha512_kdf(secret, secret_len, NULL, 126 (const u8 *) label, os_strlen(label), 127 out, outlen); 128 return -1; 129 } 130 131 132 int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, 133 size_t num_elem, const u8 *addr[], const size_t *len, 134 u8 *mac) 135 { 136 if (hash_len == 32) 137 return hmac_sha256_vector(key, key_len, num_elem, addr, len, 138 mac); 139 if (hash_len == 48) 140 return hmac_sha384_vector(key, key_len, num_elem, addr, len, 141 mac); 142 if (hash_len == 64) 143 return hmac_sha512_vector(key, key_len, num_elem, addr, len, 144 mac); 145 return -1; 146 } 147 148 149 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, 150 const u8 *data, size_t data_len, u8 *mac) 151 { 152 if (hash_len == 32) 153 return hmac_sha256(key, key_len, data, data_len, mac); 154 if (hash_len == 48) 155 return hmac_sha384(key, key_len, data, data_len, mac); 156 if (hash_len == 64) 157 return hmac_sha512(key, key_len, data, data_len, mac); 158 return -1; 159 } 160 161 162 #ifdef CONFIG_DPP2 163 164 static int dpp_pbkdf2_f(size_t hash_len, 165 const u8 *password, size_t password_len, 166 const u8 *salt, size_t salt_len, 167 unsigned int iterations, unsigned int count, u8 *digest) 168 { 169 unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; 170 unsigned int i; 171 size_t j; 172 u8 count_buf[4]; 173 const u8 *addr[2]; 174 size_t len[2]; 175 176 addr[0] = salt; 177 len[0] = salt_len; 178 addr[1] = count_buf; 179 len[1] = 4; 180 181 /* F(P, S, c, i) = U1 xor U2 xor ... Uc 182 * U1 = PRF(P, S || i) 183 * U2 = PRF(P, U1) 184 * Uc = PRF(P, Uc-1) 185 */ 186 187 WPA_PUT_BE32(count_buf, count); 188 if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, 189 tmp)) 190 return -1; 191 os_memcpy(digest, tmp, hash_len); 192 193 for (i = 1; i < iterations; i++) { 194 if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, 195 tmp2)) 196 return -1; 197 os_memcpy(tmp, tmp2, hash_len); 198 for (j = 0; j < hash_len; j++) 199 digest[j] ^= tmp2[j]; 200 } 201 202 return 0; 203 } 204 205 206 int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, 207 const u8 *salt, size_t salt_len, unsigned int iterations, 208 u8 *buf, size_t buflen) 209 { 210 unsigned int count = 0; 211 unsigned char *pos = buf; 212 size_t left = buflen, plen; 213 unsigned char digest[DPP_MAX_HASH_LEN]; 214 215 while (left > 0) { 216 count++; 217 if (dpp_pbkdf2_f(hash_len, password, password_len, 218 salt, salt_len, iterations, count, digest)) 219 return -1; 220 plen = left > hash_len ? hash_len : left; 221 os_memcpy(pos, digest, plen); 222 pos += plen; 223 left -= plen; 224 } 225 226 return 0; 227 } 228 229 #endif /* CONFIG_DPP2 */ 230 231 232 struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, 233 const u8 *buf, size_t len) 234 { 235 int ike_group = crypto_ec_key_group(group_key); 236 237 if (len & 1) 238 return NULL; 239 240 if (ike_group < 0) { 241 wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); 242 return NULL; 243 } 244 245 return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2); 246 } 247 248 249 struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) 250 { 251 struct crypto_ec_key *key; 252 253 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); 254 255 key = crypto_ec_key_gen(curve->ike_group); 256 if (key && wpa_debug_show_keys) 257 dpp_debug_print_key("Own generated key", key); 258 259 return key; 260 } 261 262 263 struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, 264 const u8 *privkey, size_t privkey_len) 265 { 266 struct crypto_ec_key *key; 267 int group; 268 269 key = crypto_ec_key_parse_priv(privkey, privkey_len); 270 if (!key) { 271 wpa_printf(MSG_INFO, "DPP: Failed to parse private key"); 272 return NULL; 273 } 274 275 group = crypto_ec_key_group(key); 276 if (group < 0) { 277 crypto_ec_key_deinit(key); 278 return NULL; 279 } 280 281 *curve = dpp_get_curve_ike_group(group); 282 if (!*curve) { 283 wpa_printf(MSG_INFO, 284 "DPP: Unsupported curve (group=%d) in pre-assigned key", 285 group); 286 crypto_ec_key_deinit(key); 287 return NULL; 288 } 289 290 return key; 291 } 292 293 294 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) 295 { 296 struct wpabuf *der; 297 int res; 298 299 der = crypto_ec_key_get_subject_public_key(bi->pubkey); 300 if (!der) 301 return -1; 302 wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 303 der); 304 res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); 305 if (res < 0) 306 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 307 wpabuf_free(der); 308 return res; 309 } 310 311 312 int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, 313 const u8 *privkey, size_t privkey_len) 314 { 315 char *base64 = NULL; 316 char *pos, *end; 317 size_t len; 318 struct wpabuf *der = NULL; 319 320 bi->curve = dpp_get_curve_name(curve); 321 if (!bi->curve) { 322 wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); 323 return -1; 324 } 325 326 if (privkey) 327 bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); 328 else 329 bi->pubkey = dpp_gen_keypair(bi->curve); 330 if (!bi->pubkey) 331 goto fail; 332 bi->own = 1; 333 334 der = crypto_ec_key_get_subject_public_key(bi->pubkey); 335 if (!der) 336 goto fail; 337 wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 338 der); 339 340 if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { 341 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 342 goto fail; 343 } 344 345 base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); 346 wpabuf_free(der); 347 der = NULL; 348 if (!base64) 349 goto fail; 350 pos = base64; 351 end = pos + len; 352 for (;;) { 353 pos = os_strchr(pos, '\n'); 354 if (!pos) 355 break; 356 os_memmove(pos, pos + 1, end - pos); 357 } 358 os_free(bi->pk); 359 bi->pk = base64; 360 return 0; 361 fail: 362 os_free(base64); 363 wpabuf_free(der); 364 return -1; 365 } 366 367 368 int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) 369 { 370 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 371 const char *info = "first intermediate key"; 372 int res; 373 374 /* k1 = HKDF(<>, "first intermediate key", M.x) */ 375 376 /* HKDF-Extract(<>, M.x) */ 377 os_memset(salt, 0, hash_len); 378 if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) 379 return -1; 380 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", 381 prk, hash_len); 382 383 /* HKDF-Expand(PRK, info, L) */ 384 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); 385 os_memset(prk, 0, hash_len); 386 if (res < 0) 387 return -1; 388 389 wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", 390 k1, hash_len); 391 return 0; 392 } 393 394 395 int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) 396 { 397 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 398 const char *info = "second intermediate key"; 399 int res; 400 401 /* k2 = HKDF(<>, "second intermediate key", N.x) */ 402 403 /* HKDF-Extract(<>, N.x) */ 404 os_memset(salt, 0, hash_len); 405 res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); 406 if (res < 0) 407 return -1; 408 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 409 prk, hash_len); 410 411 /* HKDF-Expand(PRK, info, L) */ 412 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); 413 os_memset(prk, 0, hash_len); 414 if (res < 0) 415 return -1; 416 417 wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", 418 k2, hash_len); 419 return 0; 420 } 421 422 423 int dpp_derive_bk_ke(struct dpp_authentication *auth) 424 { 425 unsigned int hash_len = auth->curve->hash_len; 426 size_t nonce_len = auth->curve->nonce_len; 427 u8 nonces[2 * DPP_MAX_NONCE_LEN]; 428 const char *info_ke = "DPP Key"; 429 int res; 430 const u8 *addr[3]; 431 size_t len[3]; 432 size_t num_elem = 0; 433 434 if (!auth->Mx_len || !auth->Nx_len) { 435 wpa_printf(MSG_DEBUG, 436 "DPP: Mx/Nx not available - cannot derive ke"); 437 return -1; 438 } 439 440 /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ 441 os_memcpy(nonces, auth->i_nonce, nonce_len); 442 os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); 443 addr[num_elem] = auth->Mx; 444 len[num_elem] = auth->Mx_len; 445 num_elem++; 446 addr[num_elem] = auth->Nx; 447 len[num_elem] = auth->Nx_len; 448 num_elem++; 449 if (auth->peer_bi && auth->own_bi) { 450 if (!auth->Lx_len) { 451 wpa_printf(MSG_DEBUG, 452 "DPP: Lx not available - cannot derive ke"); 453 return -1; 454 } 455 addr[num_elem] = auth->Lx; 456 len[num_elem] = auth->secret_len; 457 num_elem++; 458 } 459 res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, 460 num_elem, addr, len, auth->bk); 461 if (res < 0) 462 return -1; 463 wpa_hexdump_key(MSG_DEBUG, 464 "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", 465 auth->bk, hash_len); 466 467 /* ke = HKDF-Expand(bk, "DPP Key", length) */ 468 res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, 469 hash_len); 470 if (res < 0) 471 return -1; 472 473 wpa_hexdump_key(MSG_DEBUG, 474 "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", 475 auth->ke, hash_len); 476 477 return 0; 478 } 479 480 481 int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, 482 u8 *secret, size_t *secret_len) 483 { 484 struct crypto_ecdh *ecdh; 485 struct wpabuf *peer_pub, *secret_buf = NULL; 486 int ret = -1; 487 488 *secret_len = 0; 489 490 ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own); 491 if (!ecdh) { 492 wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed"); 493 return -1; 494 } 495 496 peer_pub = crypto_ec_key_get_pubkey_point(peer, 0); 497 if (!peer_pub) { 498 wpa_printf(MSG_ERROR, 499 "DPP: crypto_ec_key_get_pubkey_point() failed"); 500 goto fail; 501 } 502 503 secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub), 504 wpabuf_len(peer_pub)); 505 if (!secret_buf) { 506 wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed"); 507 goto fail; 508 } 509 510 if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) { 511 wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected"); 512 goto fail; 513 } 514 515 *secret_len = wpabuf_len(secret_buf); 516 os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf)); 517 ret = 0; 518 519 fail: 520 wpabuf_clear_free(secret_buf); 521 wpabuf_free(peer_pub); 522 crypto_ecdh_deinit(ecdh); 523 return ret; 524 } 525 526 527 int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, 528 const u8 *data, size_t data_len) 529 { 530 const u8 *addr[2]; 531 size_t len[2]; 532 533 addr[0] = data; 534 len[0] = data_len; 535 if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) 536 return -1; 537 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", 538 bi->pubkey_hash, SHA256_MAC_LEN); 539 540 addr[0] = (const u8 *) "chirp"; 541 len[0] = 5; 542 addr[1] = data; 543 len[1] = data_len; 544 if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) 545 return -1; 546 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", 547 bi->pubkey_hash_chirp, SHA256_MAC_LEN); 548 549 return 0; 550 } 551 552 553 int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, 554 const u8 *data, size_t data_len) 555 { 556 struct crypto_ec_key *key; 557 558 if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { 559 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 560 return -1; 561 } 562 563 key = crypto_ec_key_parse_pub(data, data_len); 564 if (!key) { 565 wpa_printf(MSG_DEBUG, 566 "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); 567 return -1; 568 } 569 570 bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key)); 571 if (!bi->curve) { 572 wpa_printf(MSG_DEBUG, 573 "DPP: Unsupported SubjectPublicKeyInfo curve: group %d", 574 crypto_ec_key_group(key)); 575 goto fail; 576 } 577 578 bi->pubkey = key; 579 return 0; 580 fail: 581 crypto_ec_key_deinit(key); 582 return -1; 583 } 584 585 586 static struct wpabuf * 587 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, 588 const u8 *prot_hdr, u16 prot_hdr_len, 589 int *hash_func) 590 { 591 struct json_token *root, *token; 592 struct wpabuf *kid = NULL; 593 594 root = json_parse((const char *) prot_hdr, prot_hdr_len); 595 if (!root) { 596 wpa_printf(MSG_DEBUG, 597 "DPP: JSON parsing failed for JWS Protected Header"); 598 goto fail; 599 } 600 601 if (root->type != JSON_OBJECT) { 602 wpa_printf(MSG_DEBUG, 603 "DPP: JWS Protected Header root is not an object"); 604 goto fail; 605 } 606 607 token = json_get_member(root, "typ"); 608 if (!token || token->type != JSON_STRING) { 609 wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); 610 goto fail; 611 } 612 wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", 613 token->string); 614 if (os_strcmp(token->string, "dppCon") != 0) { 615 wpa_printf(MSG_DEBUG, 616 "DPP: Unsupported JWS Protected Header typ=%s", 617 token->string); 618 goto fail; 619 } 620 621 token = json_get_member(root, "alg"); 622 if (!token || token->type != JSON_STRING) { 623 wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); 624 goto fail; 625 } 626 wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", 627 token->string); 628 if (os_strcmp(token->string, curve->jws_alg) != 0) { 629 wpa_printf(MSG_DEBUG, 630 "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", 631 token->string, curve->jws_alg); 632 goto fail; 633 } 634 if (os_strcmp(token->string, "ES256") == 0 || 635 os_strcmp(token->string, "BS256") == 0) { 636 *hash_func = CRYPTO_HASH_ALG_SHA256; 637 } else if (os_strcmp(token->string, "ES384") == 0 || 638 os_strcmp(token->string, "BS384") == 0) { 639 *hash_func = CRYPTO_HASH_ALG_SHA384; 640 } else if (os_strcmp(token->string, "ES512") == 0 || 641 os_strcmp(token->string, "BS512") == 0) { 642 *hash_func = CRYPTO_HASH_ALG_SHA512; 643 } else { 644 *hash_func = -1; 645 wpa_printf(MSG_DEBUG, 646 "DPP: Unsupported JWS Protected Header alg=%s", 647 token->string); 648 goto fail; 649 } 650 651 kid = json_get_member_base64url(root, "kid"); 652 if (!kid) { 653 wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); 654 goto fail; 655 } 656 wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", 657 kid); 658 659 fail: 660 json_free(root); 661 return kid; 662 } 663 664 665 static int dpp_check_pubkey_match(struct crypto_ec_key *pub, 666 struct wpabuf *r_hash) 667 { 668 struct wpabuf *uncomp; 669 int res; 670 u8 hash[SHA256_MAC_LEN]; 671 const u8 *addr[1]; 672 size_t len[1]; 673 674 if (wpabuf_len(r_hash) != SHA256_MAC_LEN) 675 return -1; 676 uncomp = crypto_ec_key_get_pubkey_point(pub, 1); 677 if (!uncomp) 678 return -1; 679 addr[0] = wpabuf_head(uncomp); 680 len[0] = wpabuf_len(uncomp); 681 wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", 682 addr[0], len[0]); 683 res = sha256_vector(1, addr, len, hash); 684 wpabuf_free(uncomp); 685 if (res < 0) 686 return -1; 687 if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { 688 wpa_printf(MSG_DEBUG, 689 "DPP: Received hash value does not match calculated public key hash value"); 690 wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", 691 hash, SHA256_MAC_LEN); 692 return -1; 693 } 694 return 0; 695 } 696 697 698 enum dpp_status_error 699 dpp_process_signed_connector(struct dpp_signed_connector_info *info, 700 struct crypto_ec_key *csign_pub, 701 const char *connector) 702 { 703 enum dpp_status_error ret = 255; 704 const char *pos, *end, *signed_start, *signed_end; 705 struct wpabuf *kid = NULL; 706 unsigned char *prot_hdr = NULL, *signature = NULL; 707 size_t prot_hdr_len = 0, signature_len = 0, signed_len; 708 int res, hash_func = -1; 709 const struct dpp_curve_params *curve; 710 u8 *hash = NULL; 711 712 curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub)); 713 if (!curve) 714 goto fail; 715 wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); 716 os_memset(info, 0, sizeof(*info)); 717 718 signed_start = pos = connector; 719 end = os_strchr(pos, '.'); 720 if (!end) { 721 wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); 722 ret = DPP_STATUS_INVALID_CONNECTOR; 723 goto fail; 724 } 725 prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); 726 if (!prot_hdr) { 727 wpa_printf(MSG_DEBUG, 728 "DPP: Failed to base64url decode signedConnector JWS Protected Header"); 729 ret = DPP_STATUS_INVALID_CONNECTOR; 730 goto fail; 731 } 732 wpa_hexdump_ascii(MSG_DEBUG, 733 "DPP: signedConnector - JWS Protected Header", 734 prot_hdr, prot_hdr_len); 735 kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); 736 if (!kid) { 737 ret = DPP_STATUS_INVALID_CONNECTOR; 738 goto fail; 739 } 740 if (wpabuf_len(kid) != SHA256_MAC_LEN) { 741 wpa_printf(MSG_DEBUG, 742 "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", 743 (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); 744 ret = DPP_STATUS_INVALID_CONNECTOR; 745 goto fail; 746 } 747 748 pos = end + 1; 749 end = os_strchr(pos, '.'); 750 if (!end) { 751 wpa_printf(MSG_DEBUG, 752 "DPP: Missing dot(2) in signedConnector"); 753 ret = DPP_STATUS_INVALID_CONNECTOR; 754 goto fail; 755 } 756 signed_end = end - 1; 757 info->payload = base64_url_decode(pos, end - pos, &info->payload_len); 758 if (!info->payload) { 759 wpa_printf(MSG_DEBUG, 760 "DPP: Failed to base64url decode signedConnector JWS Payload"); 761 ret = DPP_STATUS_INVALID_CONNECTOR; 762 goto fail; 763 } 764 wpa_hexdump_ascii(MSG_DEBUG, 765 "DPP: signedConnector - JWS Payload", 766 info->payload, info->payload_len); 767 pos = end + 1; 768 signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 769 if (!signature) { 770 wpa_printf(MSG_DEBUG, 771 "DPP: Failed to base64url decode signedConnector signature"); 772 ret = DPP_STATUS_INVALID_CONNECTOR; 773 goto fail; 774 } 775 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", 776 signature, signature_len); 777 778 if (dpp_check_pubkey_match(csign_pub, kid) < 0) { 779 ret = DPP_STATUS_NO_MATCH; 780 goto fail; 781 } 782 783 if (signature_len & 0x01) { 784 wpa_printf(MSG_DEBUG, 785 "DPP: Unexpected signedConnector signature length (%d)", 786 (int) signature_len); 787 ret = DPP_STATUS_INVALID_CONNECTOR; 788 goto fail; 789 } 790 791 hash = os_malloc(curve->hash_len); 792 if (!hash) 793 goto fail; 794 795 signed_len = signed_end - signed_start + 1; 796 if (hash_func == CRYPTO_HASH_ALG_SHA256) 797 res = sha256_vector(1, (const u8 **) &signed_start, &signed_len, 798 hash); 799 else if (hash_func == CRYPTO_HASH_ALG_SHA384) 800 res = sha384_vector(1, (const u8 **) &signed_start, &signed_len, 801 hash); 802 else if (hash_func == CRYPTO_HASH_ALG_SHA512) 803 res = sha512_vector(1, (const u8 **) &signed_start, &signed_len, 804 hash); 805 else 806 goto fail; 807 808 if (res) 809 goto fail; 810 811 res = crypto_ec_key_verify_signature_r_s(csign_pub, 812 hash, curve->hash_len, 813 signature, signature_len / 2, 814 signature + signature_len / 2, 815 signature_len / 2); 816 if (res != 1) { 817 wpa_printf(MSG_DEBUG, 818 "DPP: signedConnector signature check failed (res=%d)", 819 res); 820 ret = DPP_STATUS_INVALID_CONNECTOR; 821 goto fail; 822 } 823 824 ret = DPP_STATUS_OK; 825 fail: 826 os_free(hash); 827 os_free(prot_hdr); 828 wpabuf_free(kid); 829 os_free(signature); 830 return ret; 831 } 832 833 834 enum dpp_status_error 835 dpp_check_signed_connector(struct dpp_signed_connector_info *info, 836 const u8 *csign_key, size_t csign_key_len, 837 const u8 *peer_connector, size_t peer_connector_len) 838 { 839 struct crypto_ec_key *csign; 840 char *signed_connector = NULL; 841 enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; 842 843 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 844 if (!csign) { 845 wpa_printf(MSG_ERROR, 846 "DPP: Failed to parse local C-sign-key information"); 847 goto fail; 848 } 849 850 wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", 851 peer_connector, peer_connector_len); 852 signed_connector = os_malloc(peer_connector_len + 1); 853 if (!signed_connector) 854 goto fail; 855 os_memcpy(signed_connector, peer_connector, peer_connector_len); 856 signed_connector[peer_connector_len] = '\0'; 857 res = dpp_process_signed_connector(info, csign, signed_connector); 858 fail: 859 os_free(signed_connector); 860 crypto_ec_key_deinit(csign); 861 return res; 862 } 863 864 865 int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) 866 { 867 struct wpabuf *pix, *prx, *bix, *brx; 868 const u8 *addr[7]; 869 size_t len[7]; 870 size_t i, num_elem = 0; 871 size_t nonce_len; 872 u8 zero = 0; 873 int res = -1; 874 875 /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ 876 nonce_len = auth->curve->nonce_len; 877 878 if (auth->initiator) { 879 pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 880 prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 881 0); 882 if (auth->own_bi) 883 bix = crypto_ec_key_get_pubkey_point( 884 auth->own_bi->pubkey, 0); 885 else 886 bix = NULL; 887 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 888 } else { 889 pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 890 0); 891 prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 892 if (auth->peer_bi) 893 bix = crypto_ec_key_get_pubkey_point( 894 auth->peer_bi->pubkey, 0); 895 else 896 bix = NULL; 897 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0); 898 } 899 if (!pix || !prx || !brx) 900 goto fail; 901 902 addr[num_elem] = auth->i_nonce; 903 len[num_elem] = nonce_len; 904 num_elem++; 905 906 addr[num_elem] = auth->r_nonce; 907 len[num_elem] = nonce_len; 908 num_elem++; 909 910 addr[num_elem] = wpabuf_head(pix); 911 len[num_elem] = wpabuf_len(pix) / 2; 912 num_elem++; 913 914 addr[num_elem] = wpabuf_head(prx); 915 len[num_elem] = wpabuf_len(prx) / 2; 916 num_elem++; 917 918 if (bix) { 919 addr[num_elem] = wpabuf_head(bix); 920 len[num_elem] = wpabuf_len(bix) / 2; 921 num_elem++; 922 } 923 924 addr[num_elem] = wpabuf_head(brx); 925 len[num_elem] = wpabuf_len(brx) / 2; 926 num_elem++; 927 928 addr[num_elem] = &zero; 929 len[num_elem] = 1; 930 num_elem++; 931 932 wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); 933 for (i = 0; i < num_elem; i++) 934 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 935 res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); 936 if (res == 0) 937 wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, 938 auth->curve->hash_len); 939 fail: 940 wpabuf_free(pix); 941 wpabuf_free(prx); 942 wpabuf_free(bix); 943 wpabuf_free(brx); 944 return res; 945 } 946 947 948 int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) 949 { 950 struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; 951 const u8 *addr[7]; 952 size_t len[7]; 953 size_t i, num_elem = 0; 954 size_t nonce_len; 955 u8 one = 1; 956 int res = -1; 957 958 /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ 959 nonce_len = auth->curve->nonce_len; 960 961 if (auth->initiator) { 962 pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 963 prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 964 0); 965 if (auth->own_bi) 966 bix = crypto_ec_key_get_pubkey_point( 967 auth->own_bi->pubkey, 0); 968 else 969 bix = NULL; 970 if (!auth->peer_bi) 971 goto fail; 972 brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 973 } else { 974 pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 975 0); 976 prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 977 if (auth->peer_bi) 978 bix = crypto_ec_key_get_pubkey_point( 979 auth->peer_bi->pubkey, 0); 980 else 981 bix = NULL; 982 if (!auth->own_bi) 983 goto fail; 984 brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0); 985 } 986 if (!pix || !prx || !brx) 987 goto fail; 988 989 addr[num_elem] = auth->r_nonce; 990 len[num_elem] = nonce_len; 991 num_elem++; 992 993 addr[num_elem] = auth->i_nonce; 994 len[num_elem] = nonce_len; 995 num_elem++; 996 997 addr[num_elem] = wpabuf_head(prx); 998 len[num_elem] = wpabuf_len(prx) / 2; 999 num_elem++; 1000 1001 addr[num_elem] = wpabuf_head(pix); 1002 len[num_elem] = wpabuf_len(pix) / 2; 1003 num_elem++; 1004 1005 addr[num_elem] = wpabuf_head(brx); 1006 len[num_elem] = wpabuf_len(brx) / 2; 1007 num_elem++; 1008 1009 if (bix) { 1010 addr[num_elem] = wpabuf_head(bix); 1011 len[num_elem] = wpabuf_len(bix) / 2; 1012 num_elem++; 1013 } 1014 1015 addr[num_elem] = &one; 1016 len[num_elem] = 1; 1017 num_elem++; 1018 1019 wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); 1020 for (i = 0; i < num_elem; i++) 1021 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 1022 res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); 1023 if (res == 0) 1024 wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, 1025 auth->curve->hash_len); 1026 fail: 1027 wpabuf_free(pix); 1028 wpabuf_free(prx); 1029 wpabuf_free(bix); 1030 wpabuf_free(brx); 1031 return res; 1032 } 1033 1034 1035 int dpp_auth_derive_l_responder(struct dpp_authentication *auth) 1036 { 1037 struct crypto_ec *ec; 1038 struct crypto_ec_point *L = NULL; 1039 const struct crypto_ec_point *BI; 1040 const struct crypto_bignum *bR, *pR, *q; 1041 struct crypto_bignum *sum = NULL, *lx = NULL; 1042 int ret = -1; 1043 1044 /* L = ((bR + pR) modulo q) * BI */ 1045 1046 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 1047 if (!ec) 1048 goto fail; 1049 1050 q = crypto_ec_get_order(ec); 1051 BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 1052 bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 1053 pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 1054 sum = crypto_bignum_init(); 1055 L = crypto_ec_point_init(ec); 1056 lx = crypto_bignum_init(); 1057 if (!q || !BI || !bR || !pR || !sum || !L || !lx || 1058 crypto_bignum_addmod(bR, pR, q, sum) || 1059 crypto_ec_point_mul(ec, BI, sum, L) || 1060 crypto_ec_point_x(ec, L, lx) || 1061 crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 1062 auth->secret_len) < 0) 1063 goto fail; 1064 1065 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1066 auth->Lx_len = auth->secret_len; 1067 ret = 0; 1068 fail: 1069 crypto_bignum_deinit(lx, 1); 1070 crypto_bignum_deinit(sum, 1); 1071 crypto_ec_point_deinit(L, 1); 1072 crypto_ec_deinit(ec); 1073 return ret; 1074 } 1075 1076 1077 int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) 1078 { 1079 struct crypto_ec *ec; 1080 struct crypto_ec_point *L = NULL, *sum = NULL; 1081 const struct crypto_ec_point *BR, *PR; 1082 const struct crypto_bignum *bI; 1083 struct crypto_bignum *lx = NULL; 1084 int ret = -1; 1085 1086 /* L = bI * (BR + PR) */ 1087 1088 ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 1089 if (!ec) 1090 goto fail; 1091 1092 BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 1093 PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 1094 bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 1095 sum = crypto_ec_point_init(ec); 1096 L = crypto_ec_point_init(ec); 1097 lx = crypto_bignum_init(); 1098 if (!BR || !PR || !bI || !sum || !L || !lx || 1099 crypto_ec_point_add(ec, BR, PR, sum) || 1100 crypto_ec_point_mul(ec, sum, bI, L) || 1101 crypto_ec_point_x(ec, L, lx) || 1102 crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 1103 auth->secret_len) < 0) 1104 goto fail; 1105 1106 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1107 auth->Lx_len = auth->secret_len; 1108 ret = 0; 1109 fail: 1110 crypto_bignum_deinit(lx, 1); 1111 crypto_ec_point_deinit(sum, 1); 1112 crypto_ec_point_deinit(L, 1); 1113 crypto_ec_deinit(ec); 1114 return ret; 1115 } 1116 1117 1118 int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) 1119 { 1120 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1121 const char *info = "DPP PMK"; 1122 int res; 1123 1124 /* PMK = HKDF(<>, "DPP PMK", N.x) */ 1125 1126 /* HKDF-Extract(<>, N.x) */ 1127 os_memset(salt, 0, hash_len); 1128 if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) 1129 return -1; 1130 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 1131 prk, hash_len); 1132 1133 /* HKDF-Expand(PRK, info, L) */ 1134 res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); 1135 os_memset(prk, 0, hash_len); 1136 if (res < 0) 1137 return -1; 1138 1139 wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", 1140 pmk, hash_len); 1141 return 0; 1142 } 1143 1144 1145 int dpp_derive_pmkid(const struct dpp_curve_params *curve, 1146 struct crypto_ec_key *own_key, 1147 struct crypto_ec_key *peer_key, u8 *pmkid) 1148 { 1149 struct wpabuf *nkx, *pkx; 1150 int ret = -1, res; 1151 const u8 *addr[2]; 1152 size_t len[2]; 1153 u8 hash[SHA256_MAC_LEN]; 1154 1155 /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ 1156 nkx = crypto_ec_key_get_pubkey_point(own_key, 0); 1157 pkx = crypto_ec_key_get_pubkey_point(peer_key, 0); 1158 if (!nkx || !pkx) 1159 goto fail; 1160 addr[0] = wpabuf_head(nkx); 1161 len[0] = wpabuf_len(nkx) / 2; 1162 addr[1] = wpabuf_head(pkx); 1163 len[1] = wpabuf_len(pkx) / 2; 1164 if (len[0] != len[1]) 1165 goto fail; 1166 if (os_memcmp(addr[0], addr[1], len[0]) > 0) { 1167 addr[0] = wpabuf_head(pkx); 1168 addr[1] = wpabuf_head(nkx); 1169 } 1170 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); 1171 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); 1172 res = sha256_vector(2, addr, len, hash); 1173 if (res < 0) 1174 goto fail; 1175 wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); 1176 os_memcpy(pmkid, hash, PMKID_LEN); 1177 wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); 1178 ret = 0; 1179 fail: 1180 wpabuf_free(nkx); 1181 wpabuf_free(pkx); 1182 return ret; 1183 } 1184 1185 1186 /* Role-specific elements for PKEX */ 1187 1188 /* NIST P-256 */ 1189 static const u8 pkex_init_x_p256[32] = { 1190 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, 1191 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, 1192 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, 1193 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 1194 }; 1195 static const u8 pkex_init_y_p256[32] = { 1196 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, 1197 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, 1198 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, 1199 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 1200 }; 1201 static const u8 pkex_resp_x_p256[32] = { 1202 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, 1203 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, 1204 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, 1205 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 1206 }; 1207 static const u8 pkex_resp_y_p256[32] = { 1208 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, 1209 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, 1210 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, 1211 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 1212 }; 1213 1214 /* NIST P-384 */ 1215 static const u8 pkex_init_x_p384[48] = { 1216 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, 1217 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, 1218 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, 1219 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, 1220 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, 1221 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 1222 }; 1223 static const u8 pkex_init_y_p384[48] = { 1224 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, 1225 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, 1226 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, 1227 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, 1228 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, 1229 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 1230 }; 1231 static const u8 pkex_resp_x_p384[48] = { 1232 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, 1233 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, 1234 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, 1235 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, 1236 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, 1237 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf 1238 }; 1239 static const u8 pkex_resp_y_p384[48] = { 1240 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, 1241 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, 1242 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, 1243 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, 1244 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, 1245 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 1246 }; 1247 1248 /* NIST P-521 */ 1249 static const u8 pkex_init_x_p521[66] = { 1250 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, 1251 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, 1252 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, 1253 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, 1254 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, 1255 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, 1256 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, 1257 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, 1258 0x97, 0x76 1259 }; 1260 static const u8 pkex_init_y_p521[66] = { 1261 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, 1262 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, 1263 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, 1264 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, 1265 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, 1266 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, 1267 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, 1268 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, 1269 0x03, 0xa8 1270 }; 1271 static const u8 pkex_resp_x_p521[66] = { 1272 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, 1273 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, 1274 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, 1275 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, 1276 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, 1277 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, 1278 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, 1279 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, 1280 0x84, 0xb4 1281 }; 1282 static const u8 pkex_resp_y_p521[66] = { 1283 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, 1284 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, 1285 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, 1286 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, 1287 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, 1288 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, 1289 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, 1290 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, 1291 0xce, 0xe1 1292 }; 1293 1294 /* Brainpool P-256r1 */ 1295 static const u8 pkex_init_x_bp_p256r1[32] = { 1296 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, 1297 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, 1298 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, 1299 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 1300 }; 1301 static const u8 pkex_init_y_bp_p256r1[32] = { 1302 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, 1303 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, 1304 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, 1305 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b 1306 }; 1307 static const u8 pkex_resp_x_bp_p256r1[32] = { 1308 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, 1309 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, 1310 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, 1311 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 1312 }; 1313 static const u8 pkex_resp_y_bp_p256r1[32] = { 1314 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, 1315 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, 1316 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, 1317 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 1318 }; 1319 1320 /* Brainpool P-384r1 */ 1321 static const u8 pkex_init_x_bp_p384r1[48] = { 1322 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, 1323 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, 1324 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, 1325 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, 1326 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, 1327 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe 1328 }; 1329 static const u8 pkex_init_y_bp_p384r1[48] = { 1330 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, 1331 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, 1332 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, 1333 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, 1334 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, 1335 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 1336 }; 1337 static const u8 pkex_resp_x_bp_p384r1[48] = { 1338 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, 1339 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, 1340 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, 1341 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, 1342 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, 1343 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c 1344 }; 1345 static const u8 pkex_resp_y_bp_p384r1[48] = { 1346 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, 1347 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, 1348 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, 1349 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, 1350 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, 1351 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 1352 }; 1353 1354 /* Brainpool P-512r1 */ 1355 static const u8 pkex_init_x_bp_p512r1[64] = { 1356 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, 1357 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, 1358 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, 1359 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, 1360 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, 1361 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, 1362 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, 1363 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f 1364 }; 1365 static const u8 pkex_init_y_bp_p512r1[64] = { 1366 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, 1367 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, 1368 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, 1369 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, 1370 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, 1371 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, 1372 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, 1373 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 1374 }; 1375 static const u8 pkex_resp_x_bp_p512r1[64] = { 1376 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, 1377 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, 1378 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, 1379 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, 1380 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, 1381 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, 1382 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, 1383 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e 1384 }; 1385 static const u8 pkex_resp_y_bp_p512r1[64] = { 1386 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, 1387 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, 1388 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, 1389 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, 1390 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, 1391 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, 1392 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, 1393 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 1394 }; 1395 1396 1397 static struct crypto_ec_key * 1398 dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init) 1399 { 1400 const u8 *x, *y; 1401 1402 switch (curve->ike_group) { 1403 case 19: 1404 x = init ? pkex_init_x_p256 : pkex_resp_x_p256; 1405 y = init ? pkex_init_y_p256 : pkex_resp_y_p256; 1406 break; 1407 case 20: 1408 x = init ? pkex_init_x_p384 : pkex_resp_x_p384; 1409 y = init ? pkex_init_y_p384 : pkex_resp_y_p384; 1410 break; 1411 case 21: 1412 x = init ? pkex_init_x_p521 : pkex_resp_x_p521; 1413 y = init ? pkex_init_y_p521 : pkex_resp_y_p521; 1414 break; 1415 case 28: 1416 x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; 1417 y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; 1418 break; 1419 case 29: 1420 x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; 1421 y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; 1422 break; 1423 case 30: 1424 x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; 1425 y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; 1426 break; 1427 default: 1428 return NULL; 1429 } 1430 1431 return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len); 1432 } 1433 1434 1435 struct crypto_ec_point * 1436 dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init, 1437 const char *code, const char *identifier, 1438 struct crypto_ec **ret_ec) 1439 { 1440 u8 hash[DPP_MAX_HASH_LEN]; 1441 const u8 *addr[3]; 1442 size_t len[3]; 1443 unsigned int num_elem = 0; 1444 struct crypto_ec_point *Qi = NULL; 1445 struct crypto_ec_key *Pi_key = NULL; 1446 const struct crypto_ec_point *Pi = NULL; 1447 struct crypto_bignum *hash_bn = NULL; 1448 struct crypto_ec *ec = NULL; 1449 1450 /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ 1451 1452 wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); 1453 addr[num_elem] = mac_init; 1454 len[num_elem] = ETH_ALEN; 1455 num_elem++; 1456 if (identifier) { 1457 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1458 identifier); 1459 addr[num_elem] = (const u8 *) identifier; 1460 len[num_elem] = os_strlen(identifier); 1461 num_elem++; 1462 } 1463 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1464 addr[num_elem] = (const u8 *) code; 1465 len[num_elem] = os_strlen(code); 1466 num_elem++; 1467 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1468 goto fail; 1469 wpa_hexdump_key(MSG_DEBUG, 1470 "DPP: H(MAC-Initiator | [identifier |] code)", 1471 hash, curve->hash_len); 1472 Pi_key = dpp_pkex_get_role_elem(curve, 1); 1473 if (!Pi_key) 1474 goto fail; 1475 dpp_debug_print_key("DPP: Pi", Pi_key); 1476 1477 ec = crypto_ec_init(curve->ike_group); 1478 if (!ec) 1479 goto fail; 1480 1481 Pi = crypto_ec_key_get_public_key(Pi_key); 1482 Qi = crypto_ec_point_init(ec); 1483 hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 1484 if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi)) 1485 goto fail; 1486 1487 if (crypto_ec_point_is_at_infinity(ec, Qi)) { 1488 wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); 1489 goto fail; 1490 } 1491 crypto_ec_point_debug_print(ec, Qi, "DPP: Qi"); 1492 out: 1493 crypto_ec_key_deinit(Pi_key); 1494 crypto_bignum_deinit(hash_bn, 1); 1495 if (ret_ec && Qi) 1496 *ret_ec = ec; 1497 else 1498 crypto_ec_deinit(ec); 1499 return Qi; 1500 fail: 1501 crypto_ec_point_deinit(Qi, 1); 1502 Qi = NULL; 1503 goto out; 1504 } 1505 1506 1507 struct crypto_ec_point * 1508 dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp, 1509 const char *code, const char *identifier, 1510 struct crypto_ec **ret_ec) 1511 { 1512 u8 hash[DPP_MAX_HASH_LEN]; 1513 const u8 *addr[3]; 1514 size_t len[3]; 1515 unsigned int num_elem = 0; 1516 struct crypto_ec_point *Qr = NULL; 1517 struct crypto_ec_key *Pr_key = NULL; 1518 const struct crypto_ec_point *Pr = NULL; 1519 struct crypto_bignum *hash_bn = NULL; 1520 struct crypto_ec *ec = NULL; 1521 1522 /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ 1523 1524 wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); 1525 addr[num_elem] = mac_resp; 1526 len[num_elem] = ETH_ALEN; 1527 num_elem++; 1528 if (identifier) { 1529 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1530 identifier); 1531 addr[num_elem] = (const u8 *) identifier; 1532 len[num_elem] = os_strlen(identifier); 1533 num_elem++; 1534 } 1535 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1536 addr[num_elem] = (const u8 *) code; 1537 len[num_elem] = os_strlen(code); 1538 num_elem++; 1539 if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1540 goto fail; 1541 wpa_hexdump_key(MSG_DEBUG, 1542 "DPP: H(MAC-Responder | [identifier |] code)", 1543 hash, curve->hash_len); 1544 Pr_key = dpp_pkex_get_role_elem(curve, 0); 1545 if (!Pr_key) 1546 goto fail; 1547 dpp_debug_print_key("DPP: Pr", Pr_key); 1548 1549 ec = crypto_ec_init(curve->ike_group); 1550 if (!ec) 1551 goto fail; 1552 1553 Pr = crypto_ec_key_get_public_key(Pr_key); 1554 Qr = crypto_ec_point_init(ec); 1555 hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 1556 if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) 1557 goto fail; 1558 1559 if (crypto_ec_point_is_at_infinity(ec, Qr)) { 1560 wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); 1561 goto fail; 1562 } 1563 crypto_ec_point_debug_print(ec, Qr, "DPP: Qr"); 1564 1565 out: 1566 crypto_ec_key_deinit(Pr_key); 1567 crypto_bignum_deinit(hash_bn, 1); 1568 if (ret_ec && Qr) 1569 *ret_ec = ec; 1570 else 1571 crypto_ec_deinit(ec); 1572 return Qr; 1573 fail: 1574 crypto_ec_point_deinit(Qr, 1); 1575 Qr = NULL; 1576 goto out; 1577 } 1578 1579 1580 int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, 1581 const u8 *Mx, size_t Mx_len, 1582 const u8 *Nx, size_t Nx_len, 1583 const char *code, 1584 const u8 *Kx, size_t Kx_len, 1585 u8 *z, unsigned int hash_len) 1586 { 1587 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1588 int res; 1589 u8 *info, *pos; 1590 size_t info_len; 1591 1592 /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) 1593 */ 1594 1595 /* HKDF-Extract(<>, IKM=K.x) */ 1596 os_memset(salt, 0, hash_len); 1597 if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) 1598 return -1; 1599 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", 1600 prk, hash_len); 1601 info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); 1602 info = os_malloc(info_len); 1603 if (!info) 1604 return -1; 1605 pos = info; 1606 os_memcpy(pos, mac_init, ETH_ALEN); 1607 pos += ETH_ALEN; 1608 os_memcpy(pos, mac_resp, ETH_ALEN); 1609 pos += ETH_ALEN; 1610 os_memcpy(pos, Mx, Mx_len); 1611 pos += Mx_len; 1612 os_memcpy(pos, Nx, Nx_len); 1613 pos += Nx_len; 1614 os_memcpy(pos, code, os_strlen(code)); 1615 1616 /* HKDF-Expand(PRK, info, L) */ 1617 if (hash_len == 32) 1618 res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, 1619 z, hash_len); 1620 else if (hash_len == 48) 1621 res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, 1622 z, hash_len); 1623 else if (hash_len == 64) 1624 res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, 1625 z, hash_len); 1626 else 1627 res = -1; 1628 os_free(info); 1629 os_memset(prk, 0, hash_len); 1630 if (res < 0) 1631 return -1; 1632 1633 wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", 1634 z, hash_len); 1635 return 0; 1636 } 1637 1638 1639 int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, 1640 const u8 *net_access_key, 1641 size_t net_access_key_len, 1642 struct json_token *peer_net_access_key) 1643 { 1644 struct crypto_ec_key *own_key = NULL, *peer_key = NULL; 1645 struct crypto_bignum *sum = NULL; 1646 const struct crypto_bignum *q, *cR, *pR; 1647 struct crypto_ec *ec = NULL; 1648 struct crypto_ec_point *M = NULL; 1649 const struct crypto_ec_point *CI; 1650 u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1651 u8 prk[DPP_MAX_HASH_LEN]; 1652 const struct dpp_curve_params *curve; 1653 int res = -1; 1654 u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1655 1656 own_key = dpp_set_keypair(&auth->curve, net_access_key, 1657 net_access_key_len); 1658 if (!own_key) { 1659 dpp_auth_fail(auth, "Failed to parse own netAccessKey"); 1660 goto fail; 1661 } 1662 1663 peer_key = dpp_parse_jwk(peer_net_access_key, &curve); 1664 if (!peer_key) 1665 goto fail; 1666 dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1667 1668 if (auth->curve != curve) { 1669 wpa_printf(MSG_DEBUG, 1670 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1671 auth->curve->name, curve->name); 1672 goto fail; 1673 } 1674 1675 auth->own_protocol_key = dpp_gen_keypair(curve); 1676 if (!auth->own_protocol_key) 1677 goto fail; 1678 1679 if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { 1680 wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); 1681 goto fail; 1682 } 1683 wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", 1684 auth->e_nonce, auth->curve->nonce_len); 1685 1686 /* M = { cR + pR } * CI */ 1687 ec = crypto_ec_init(curve->ike_group); 1688 if (!ec) 1689 goto fail; 1690 1691 sum = crypto_bignum_init(); 1692 q = crypto_ec_get_order(ec); 1693 M = crypto_ec_point_init(ec); 1694 cR = crypto_ec_key_get_private_key(own_key); 1695 pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 1696 CI = crypto_ec_key_get_public_key(peer_key); 1697 if (!sum || !q || !M || !cR || !pR || !CI || 1698 crypto_bignum_addmod(cR, pR, q, sum) || 1699 crypto_ec_point_mul(ec, CI, sum, M) || 1700 crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 1701 wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 1702 goto fail; 1703 } 1704 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1705 1706 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1707 1708 /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1709 os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1710 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1711 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1712 Mx, curve->prime_len, prk) < 0) 1713 goto fail; 1714 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1715 1716 /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1717 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1718 "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1719 goto fail; 1720 wpa_hexdump_key(MSG_DEBUG, 1721 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1722 auth->ke, curve->hash_len); 1723 1724 res = 0; 1725 crypto_ec_key_deinit(auth->reconfig_old_protocol_key); 1726 auth->reconfig_old_protocol_key = own_key; 1727 own_key = NULL; 1728 fail: 1729 forced_memzero(prk, sizeof(prk)); 1730 forced_memzero(Mx, sizeof(Mx)); 1731 crypto_ec_point_deinit(M, 1); 1732 crypto_bignum_deinit(sum, 1); 1733 crypto_ec_key_deinit(own_key); 1734 crypto_ec_key_deinit(peer_key); 1735 crypto_ec_deinit(ec); 1736 return res; 1737 } 1738 1739 1740 int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, 1741 const u8 *r_proto, u16 r_proto_len, 1742 struct json_token *net_access_key) 1743 { 1744 struct crypto_ec_key *pr = NULL, *peer_key = NULL; 1745 const struct crypto_ec_point *CR, *PR; 1746 const struct crypto_bignum *cI; 1747 struct crypto_ec *ec = NULL; 1748 struct crypto_ec_point *sum = NULL, *M = NULL; 1749 u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1750 u8 prk[DPP_MAX_HASH_LEN]; 1751 int res = -1; 1752 const struct dpp_curve_params *curve; 1753 u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1754 1755 pr = dpp_set_pubkey_point(auth->conf->connector_key, 1756 r_proto, r_proto_len); 1757 if (!pr) { 1758 dpp_auth_fail(auth, "Invalid Responder Protocol Key"); 1759 goto fail; 1760 } 1761 dpp_debug_print_key("Peer (Responder) Protocol Key", pr); 1762 crypto_ec_key_deinit(auth->peer_protocol_key); 1763 auth->peer_protocol_key = pr; 1764 pr = NULL; 1765 1766 peer_key = dpp_parse_jwk(net_access_key, &curve); 1767 if (!peer_key) 1768 goto fail; 1769 dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1770 if (auth->curve != curve) { 1771 wpa_printf(MSG_DEBUG, 1772 "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1773 auth->curve->name, curve->name); 1774 goto fail; 1775 } 1776 1777 /* M = cI * { CR + PR } */ 1778 ec = crypto_ec_init(curve->ike_group); 1779 if (!ec) 1780 goto fail; 1781 1782 cI = crypto_ec_key_get_private_key(auth->conf->connector_key); 1783 sum = crypto_ec_point_init(ec); 1784 M = crypto_ec_point_init(ec); 1785 CR = crypto_ec_key_get_public_key(peer_key); 1786 PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 1787 if (!cI || !sum || !M || !CR || !PR || 1788 crypto_ec_point_add(ec, CR, PR, sum) || 1789 crypto_ec_point_mul(ec, sum, cI, M) || 1790 crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 1791 wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 1792 goto fail; 1793 } 1794 1795 wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1796 1797 /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1798 1799 /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1800 os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1801 os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1802 if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1803 Mx, curve->prime_len, prk) < 0) 1804 goto fail; 1805 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1806 1807 /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1808 if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1809 "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1810 goto fail; 1811 wpa_hexdump_key(MSG_DEBUG, 1812 "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1813 auth->ke, curve->hash_len); 1814 1815 res = 0; 1816 fail: 1817 forced_memzero(prk, sizeof(prk)); 1818 forced_memzero(Mx, sizeof(Mx)); 1819 crypto_ec_key_deinit(pr); 1820 crypto_ec_key_deinit(peer_key); 1821 crypto_ec_point_deinit(sum, 1); 1822 crypto_ec_point_deinit(M, 1); 1823 crypto_ec_deinit(ec); 1824 return res; 1825 } 1826 1827 1828 static char * 1829 dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) 1830 { 1831 struct wpabuf *jws_prot_hdr; 1832 char *signed1; 1833 1834 jws_prot_hdr = wpabuf_alloc(100); 1835 if (!jws_prot_hdr) 1836 return NULL; 1837 json_start_object(jws_prot_hdr, NULL); 1838 json_add_string(jws_prot_hdr, "typ", "dppCon"); 1839 json_value_sep(jws_prot_hdr); 1840 json_add_string(jws_prot_hdr, "kid", conf->kid); 1841 json_value_sep(jws_prot_hdr); 1842 json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); 1843 json_end_object(jws_prot_hdr); 1844 signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), 1845 wpabuf_len(jws_prot_hdr), 1846 signed1_len); 1847 wpabuf_free(jws_prot_hdr); 1848 return signed1; 1849 } 1850 1851 1852 static char * 1853 dpp_build_conn_signature(struct dpp_configurator *conf, 1854 const char *signed1, size_t signed1_len, 1855 const char *signed2, size_t signed2_len, 1856 size_t *signed3_len) 1857 { 1858 const struct dpp_curve_params *curve; 1859 struct wpabuf *sig = NULL; 1860 char *signed3 = NULL; 1861 char *dot = "."; 1862 const u8 *vector[3]; 1863 size_t vector_len[3]; 1864 u8 *hash; 1865 int ret; 1866 1867 vector[0] = (const u8 *) signed1; 1868 vector[1] = (const u8 *) dot; 1869 vector[2] = (const u8 *) signed2; 1870 vector_len[0] = signed1_len; 1871 vector_len[1] = 1; 1872 vector_len[2] = signed2_len; 1873 1874 curve = conf->curve; 1875 hash = os_malloc(curve->hash_len); 1876 if (!hash) 1877 goto fail; 1878 if (curve->hash_len == SHA256_MAC_LEN) { 1879 ret = sha256_vector(3, vector, vector_len, hash); 1880 } else if (curve->hash_len == SHA384_MAC_LEN) { 1881 ret = sha384_vector(3, vector, vector_len, hash); 1882 } else if (curve->hash_len == SHA512_MAC_LEN) { 1883 ret = sha512_vector(3, vector, vector_len, hash); 1884 } else { 1885 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 1886 goto fail; 1887 } 1888 if (ret) { 1889 wpa_printf(MSG_DEBUG, "DPP: Hash computation failed"); 1890 goto fail; 1891 } 1892 wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature", 1893 hash, curve->hash_len); 1894 1895 sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len); 1896 if (!sig) { 1897 wpa_printf(MSG_ERROR, "DPP: Signature computation failed"); 1898 goto fail; 1899 } 1900 1901 wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", 1902 wpabuf_head(sig), wpabuf_len(sig)); 1903 signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig), 1904 signed3_len); 1905 1906 fail: 1907 os_free(hash); 1908 wpabuf_free(sig); 1909 return signed3; 1910 } 1911 1912 char * dpp_sign_connector(struct dpp_configurator *conf, 1913 const struct wpabuf *dppcon) 1914 { 1915 char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; 1916 char *signed_conn = NULL, *pos; 1917 size_t signed1_len, signed2_len, signed3_len; 1918 1919 signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); 1920 signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), 1921 &signed2_len); 1922 if (!signed1 || !signed2) 1923 goto fail; 1924 1925 signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, 1926 signed2, signed2_len, &signed3_len); 1927 if (!signed3) 1928 goto fail; 1929 1930 signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); 1931 if (!signed_conn) 1932 goto fail; 1933 pos = signed_conn; 1934 os_memcpy(pos, signed1, signed1_len); 1935 pos += signed1_len; 1936 *pos++ = '.'; 1937 os_memcpy(pos, signed2, signed2_len); 1938 pos += signed2_len; 1939 *pos++ = '.'; 1940 os_memcpy(pos, signed3, signed3_len); 1941 pos += signed3_len; 1942 *pos = '\0'; 1943 1944 fail: 1945 os_free(signed1); 1946 os_free(signed2); 1947 os_free(signed3); 1948 return signed_conn; 1949 } 1950 1951 1952 #ifdef CONFIG_DPP2 1953 1954 struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, 1955 size_t net_access_key_len) 1956 { 1957 struct wpabuf *pub = NULL; 1958 struct crypto_ec_key *own_key; 1959 struct dpp_pfs *pfs; 1960 1961 pfs = os_zalloc(sizeof(*pfs)); 1962 if (!pfs) 1963 return NULL; 1964 1965 own_key = dpp_set_keypair(&pfs->curve, net_access_key, 1966 net_access_key_len); 1967 if (!own_key) { 1968 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 1969 goto fail; 1970 } 1971 crypto_ec_key_deinit(own_key); 1972 1973 pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); 1974 if (!pfs->ecdh) 1975 goto fail; 1976 1977 pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); 1978 pub = wpabuf_zeropad(pub, pfs->curve->prime_len); 1979 if (!pub) 1980 goto fail; 1981 1982 pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); 1983 if (!pfs->ie) 1984 goto fail; 1985 wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); 1986 wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); 1987 wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); 1988 wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); 1989 wpabuf_put_buf(pfs->ie, pub); 1990 wpabuf_free(pub); 1991 wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", 1992 pfs->ie); 1993 1994 return pfs; 1995 fail: 1996 wpabuf_free(pub); 1997 dpp_pfs_free(pfs); 1998 return NULL; 1999 } 2000 2001 2002 int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) 2003 { 2004 if (peer_ie_len < 2) 2005 return -1; 2006 if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { 2007 wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); 2008 return -1; 2009 } 2010 2011 pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, 2012 peer_ie_len - 2); 2013 pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); 2014 if (!pfs->secret) { 2015 wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); 2016 return -1; 2017 } 2018 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); 2019 return 0; 2020 } 2021 2022 2023 void dpp_pfs_free(struct dpp_pfs *pfs) 2024 { 2025 if (!pfs) 2026 return; 2027 crypto_ecdh_deinit(pfs->ecdh); 2028 wpabuf_free(pfs->ie); 2029 wpabuf_clear_free(pfs->secret); 2030 os_free(pfs); 2031 } 2032 2033 2034 struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) 2035 { 2036 struct crypto_csr *csr = NULL; 2037 struct wpabuf *buf = NULL; 2038 struct crypto_ec_key *key; 2039 unsigned int hash_len = auth->curve->hash_len; 2040 struct wpabuf *priv_key; 2041 u8 cp[DPP_CP_LEN]; 2042 char *password = NULL; 2043 size_t password_len; 2044 int hash_sign_algo; 2045 2046 /* TODO: use auth->csrattrs */ 2047 2048 /* TODO: support generation of a new private key if csrAttrs requests 2049 * a specific group to be used */ 2050 key = auth->own_protocol_key; 2051 2052 priv_key = crypto_ec_key_get_ecprivate_key(key, true); 2053 if (!priv_key) 2054 goto fail; 2055 wpabuf_free(auth->priv_key); 2056 auth->priv_key = priv_key; 2057 2058 csr = crypto_csr_init(); 2059 if (!csr || crypto_csr_set_ec_public_key(csr, key)) 2060 goto fail; 2061 2062 if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name)) 2063 goto fail; 2064 2065 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2066 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2067 "CSR challengePassword", cp, DPP_CP_LEN) < 0) 2068 goto fail; 2069 wpa_hexdump_key(MSG_DEBUG, 2070 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2071 cp, DPP_CP_LEN); 2072 password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); 2073 forced_memzero(cp, DPP_CP_LEN); 2074 if (!password || 2075 crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 2076 ASN1_TAG_UTF8STRING, (const u8 *) password, 2077 password_len)) 2078 goto fail; 2079 2080 /* TODO: hash func selection based on csrAttrs */ 2081 if (hash_len == SHA256_MAC_LEN) { 2082 hash_sign_algo = CRYPTO_HASH_ALG_SHA256; 2083 } else if (hash_len == SHA384_MAC_LEN) { 2084 hash_sign_algo = CRYPTO_HASH_ALG_SHA384; 2085 } else if (hash_len == SHA512_MAC_LEN) { 2086 hash_sign_algo = CRYPTO_HASH_ALG_SHA512; 2087 } else { 2088 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 2089 goto fail; 2090 } 2091 2092 buf = crypto_csr_sign(csr, key, hash_sign_algo); 2093 if (!buf) 2094 goto fail; 2095 wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); 2096 2097 fail: 2098 bin_clear_free(password, password_len); 2099 crypto_csr_deinit(csr); 2100 return buf; 2101 } 2102 2103 2104 int dpp_validate_csr(struct dpp_authentication *auth, 2105 const struct wpabuf *csrbuf) 2106 { 2107 struct crypto_csr *csr; 2108 const u8 *attr; 2109 size_t attr_len; 2110 int attr_type; 2111 unsigned char *cp = NULL; 2112 size_t cp_len; 2113 u8 exp_cp[DPP_CP_LEN]; 2114 unsigned int hash_len = auth->curve->hash_len; 2115 int ret = -1; 2116 2117 csr = crypto_csr_verify(csrbuf); 2118 if (!csr) { 2119 wpa_printf(MSG_DEBUG, 2120 "DPP: CSR invalid or invalid signature"); 2121 goto fail; 2122 } 2123 2124 attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 2125 &attr_len, &attr_type); 2126 if (!attr) { 2127 wpa_printf(MSG_DEBUG, 2128 "DPP: CSR does not include challengePassword"); 2129 goto fail; 2130 } 2131 /* This is supposed to be UTF8String, but allow other strings as well 2132 * since challengePassword is using ASCII (base64 encoded). */ 2133 if (attr_type != ASN1_TAG_UTF8STRING && 2134 attr_type != ASN1_TAG_PRINTABLESTRING && 2135 attr_type != ASN1_TAG_IA5STRING) { 2136 wpa_printf(MSG_DEBUG, 2137 "DPP: Unexpected challengePassword attribute type %d", 2138 attr_type); 2139 goto fail; 2140 } 2141 2142 cp = base64_decode((const char *) attr, attr_len, &cp_len); 2143 if (!cp) { 2144 wpa_printf(MSG_DEBUG, 2145 "DPP: Could not base64 decode challengePassword"); 2146 goto fail; 2147 } 2148 if (cp_len != DPP_CP_LEN) { 2149 wpa_printf(MSG_DEBUG, 2150 "DPP: Unexpected cp length (%zu) in CSR challengePassword", 2151 cp_len); 2152 goto fail; 2153 } 2154 wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", 2155 cp, cp_len); 2156 2157 /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2158 if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2159 "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) 2160 goto fail; 2161 wpa_hexdump_key(MSG_DEBUG, 2162 "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2163 exp_cp, DPP_CP_LEN); 2164 if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { 2165 wpa_printf(MSG_DEBUG, 2166 "DPP: CSR challengePassword does not match calculated cp"); 2167 goto fail; 2168 } 2169 2170 ret = 0; 2171 fail: 2172 os_free(cp); 2173 crypto_csr_deinit(csr); 2174 return ret; 2175 } 2176 2177 2178 struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, 2179 size_t csign_key_len, 2180 const u8 *pp_key, 2181 size_t pp_key_len) 2182 { 2183 struct crypto_ec_key *csign = NULL, *ppkey = NULL; 2184 struct dpp_reconfig_id *id = NULL; 2185 struct crypto_ec *ec = NULL; 2186 const struct crypto_bignum *q; 2187 struct crypto_bignum *bn = NULL; 2188 struct crypto_ec_point *e_id = NULL; 2189 const struct crypto_ec_point *generator; 2190 2191 csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 2192 if (!csign) 2193 goto fail; 2194 2195 if (!pp_key) 2196 goto fail; 2197 ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len); 2198 if (!ppkey) 2199 goto fail; 2200 2201 ec = crypto_ec_init(crypto_ec_key_group(csign)); 2202 if (!ec) 2203 goto fail; 2204 2205 e_id = crypto_ec_point_init(ec); 2206 bn = crypto_bignum_init(); 2207 q = crypto_ec_get_order(ec); 2208 generator = crypto_ec_get_generator(ec); 2209 if (!e_id || !bn || !q || !generator || 2210 crypto_bignum_rand(bn, q) || 2211 crypto_ec_point_mul(ec, generator, bn, e_id)) 2212 goto fail; 2213 2214 crypto_ec_point_debug_print(ec, e_id, 2215 "DPP: Generated random point E-id"); 2216 2217 id = os_zalloc(sizeof(*id)); 2218 if (!id) 2219 goto fail; 2220 2221 id->ec = ec; 2222 ec = NULL; 2223 id->e_id = e_id; 2224 e_id = NULL; 2225 id->csign = csign; 2226 csign = NULL; 2227 id->pp_key = ppkey; 2228 ppkey = NULL; 2229 fail: 2230 crypto_ec_point_deinit(e_id, 1); 2231 crypto_ec_key_deinit(csign); 2232 crypto_ec_key_deinit(ppkey); 2233 crypto_bignum_deinit(bn, 1); 2234 crypto_ec_deinit(ec); 2235 return id; 2236 } 2237 2238 2239 int dpp_update_reconfig_id(struct dpp_reconfig_id *id) 2240 { 2241 const struct crypto_bignum *q; 2242 struct crypto_bignum *bn; 2243 const struct crypto_ec_point *pp, *generator; 2244 struct crypto_ec_point *e_prime_id, *a_nonce; 2245 int ret = -1; 2246 2247 pp = crypto_ec_key_get_public_key(id->pp_key); 2248 e_prime_id = crypto_ec_point_init(id->ec); 2249 a_nonce = crypto_ec_point_init(id->ec); 2250 bn = crypto_bignum_init(); 2251 q = crypto_ec_get_order(id->ec); 2252 generator = crypto_ec_get_generator(id->ec); 2253 2254 /* Generate random 0 <= a-nonce < q 2255 * A-NONCE = a-nonce * G 2256 * E'-id = E-id + a-nonce * P_pk */ 2257 if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator || 2258 crypto_bignum_rand(bn, q) || /* bn = a-nonce */ 2259 crypto_ec_point_mul(id->ec, generator, bn, a_nonce) || 2260 crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) || 2261 crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id)) 2262 goto fail; 2263 2264 crypto_ec_point_debug_print(id->ec, a_nonce, 2265 "DPP: Generated A-NONCE"); 2266 crypto_ec_point_debug_print(id->ec, e_prime_id, 2267 "DPP: Encrypted E-id to E'-id"); 2268 2269 crypto_ec_key_deinit(id->a_nonce); 2270 crypto_ec_key_deinit(id->e_prime_id); 2271 id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce); 2272 id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id); 2273 if (!id->a_nonce || !id->e_prime_id) 2274 goto fail; 2275 2276 ret = 0; 2277 2278 fail: 2279 crypto_ec_point_deinit(e_prime_id, 1); 2280 crypto_ec_point_deinit(a_nonce, 1); 2281 crypto_bignum_deinit(bn, 1); 2282 return ret; 2283 } 2284 2285 2286 void dpp_free_reconfig_id(struct dpp_reconfig_id *id) 2287 { 2288 if (id) { 2289 crypto_ec_point_deinit(id->e_id, 1); 2290 crypto_ec_key_deinit(id->csign); 2291 crypto_ec_key_deinit(id->a_nonce); 2292 crypto_ec_key_deinit(id->e_prime_id); 2293 crypto_ec_key_deinit(id->pp_key); 2294 crypto_ec_deinit(id->ec); 2295 os_free(id); 2296 } 2297 } 2298 2299 2300 struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey, 2301 struct crypto_ec_key *a_nonce, 2302 struct crypto_ec_key *e_prime_id) 2303 { 2304 struct crypto_ec *ec; 2305 const struct crypto_bignum *pp; 2306 struct crypto_ec_point *e_id = NULL; 2307 const struct crypto_ec_point *a_nonce_point, *e_prime_id_point; 2308 2309 if (!ppkey) 2310 return NULL; 2311 2312 /* E-id = E'-id - s_C * A-NONCE */ 2313 ec = crypto_ec_init(crypto_ec_key_group(ppkey)); 2314 if (!ec) 2315 return NULL; 2316 2317 pp = crypto_ec_key_get_private_key(ppkey); 2318 a_nonce_point = crypto_ec_key_get_public_key(a_nonce); 2319 e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id); 2320 e_id = crypto_ec_point_init(ec); 2321 if (!pp || !a_nonce_point || !e_prime_id_point || !e_id || 2322 crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) || 2323 crypto_ec_point_invert(ec, e_id) || 2324 crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) { 2325 crypto_ec_point_deinit(e_id, 1); 2326 goto fail; 2327 } 2328 2329 crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id"); 2330 2331 fail: 2332 crypto_ec_deinit(ec); 2333 return e_id; 2334 } 2335 2336 #endif /* CONFIG_DPP2 */ 2337 2338 2339 #ifdef CONFIG_TESTING_OPTIONS 2340 2341 int dpp_test_gen_invalid_key(struct wpabuf *msg, 2342 const struct dpp_curve_params *curve) 2343 { 2344 struct crypto_ec *ec; 2345 struct crypto_ec_key *key = NULL; 2346 const struct crypto_ec_point *pub_key; 2347 struct crypto_ec_point *p = NULL; 2348 u8 *x, *y; 2349 int ret = -1; 2350 2351 ec = crypto_ec_init(curve->ike_group); 2352 x = wpabuf_put(msg, curve->prime_len); 2353 y = wpabuf_put(msg, curve->prime_len); 2354 if (!ec) 2355 goto fail; 2356 2357 retry: 2358 /* Generate valid key pair */ 2359 key = crypto_ec_key_gen(curve->ike_group); 2360 if (!key) 2361 goto fail; 2362 2363 /* Retrieve public key coordinates */ 2364 pub_key = crypto_ec_key_get_public_key(key); 2365 if (!pub_key) 2366 goto fail; 2367 2368 crypto_ec_point_to_bin(ec, pub_key, x, y); 2369 2370 /* And corrupt them */ 2371 y[curve->prime_len - 1] ^= 0x01; 2372 p = crypto_ec_point_from_bin(ec, x); 2373 if (p && crypto_ec_point_is_on_curve(ec, p)) { 2374 crypto_ec_point_deinit(p, 0); 2375 p = NULL; 2376 goto retry; 2377 } 2378 2379 ret = 0; 2380 fail: 2381 crypto_ec_point_deinit(p, 0); 2382 crypto_ec_key_deinit(key); 2383 crypto_ec_deinit(ec); 2384 return ret; 2385 } 2386 2387 2388 char * dpp_corrupt_connector_signature(const char *connector) 2389 { 2390 char *tmp, *pos, *signed3 = NULL; 2391 unsigned char *signature = NULL; 2392 size_t signature_len = 0, signed3_len; 2393 2394 tmp = os_zalloc(os_strlen(connector) + 5); 2395 if (!tmp) 2396 goto fail; 2397 os_memcpy(tmp, connector, os_strlen(connector)); 2398 2399 pos = os_strchr(tmp, '.'); 2400 if (!pos) 2401 goto fail; 2402 2403 pos = os_strchr(pos + 1, '.'); 2404 if (!pos) 2405 goto fail; 2406 pos++; 2407 2408 wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", 2409 pos); 2410 signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 2411 if (!signature || signature_len == 0) 2412 goto fail; 2413 wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", 2414 signature, signature_len); 2415 signature[signature_len - 1] ^= 0x01; 2416 wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", 2417 signature, signature_len); 2418 signed3 = base64_url_encode(signature, signature_len, &signed3_len); 2419 if (!signed3) 2420 goto fail; 2421 os_memcpy(pos, signed3, signed3_len); 2422 pos[signed3_len] = '\0'; 2423 wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", 2424 pos); 2425 2426 out: 2427 os_free(signature); 2428 os_free(signed3); 2429 return tmp; 2430 fail: 2431 os_free(tmp); 2432 tmp = NULL; 2433 goto out; 2434 } 2435 2436 #endif /* CONFIG_TESTING_OPTIONS */ 2437