1 /* 2 * DPP configurator backup 3 * Copyright (c) 2019-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 #include <openssl/opensslv.h> 11 #include <openssl/err.h> 12 13 #include "utils/common.h" 14 #include "crypto/aes.h" 15 #include "crypto/aes_siv.h" 16 #include "tls/asn1.h" 17 #include "dpp.h" 18 #include "dpp_i.h" 19 20 #ifdef CONFIG_DPP2 21 22 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 23 (defined(LIBRESSL_VERSION_NUMBER) && \ 24 LIBRESSL_VERSION_NUMBER < 0x20700000L) 25 /* Compatibility wrappers for older versions. */ 26 27 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) 28 { 29 if (pkey->type != EVP_PKEY_EC) 30 return NULL; 31 return pkey->pkey.ec; 32 } 33 34 #endif 35 36 37 void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) 38 { 39 while (key) { 40 struct dpp_asymmetric_key *next = key->next; 41 42 EVP_PKEY_free(key->csign); 43 EVP_PKEY_free(key->pp_key); 44 str_clear_free(key->config_template); 45 str_clear_free(key->connector_template); 46 os_free(key); 47 key = next; 48 } 49 } 50 51 52 static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf) 53 { 54 struct wpabuf *buf, *priv_key = NULL; 55 size_t len; 56 /* TODO: proper template values */ 57 const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; 58 const char *connector_template = NULL; 59 EC_KEY *eckey; 60 unsigned char *der = NULL; 61 int der_len; 62 63 if (!conf->pp_key) 64 return NULL; 65 eckey = EVP_PKEY_get0_EC_KEY(conf->pp_key); 66 if (!eckey) 67 return NULL; 68 69 EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); 70 der_len = i2d_ECPrivateKey(eckey, &der); 71 if (der_len > 0) 72 priv_key = wpabuf_alloc_copy(der, der_len); 73 OPENSSL_free(der); 74 if (!priv_key) 75 goto fail; 76 77 len = 100 + os_strlen(conf_template); 78 if (connector_template) 79 len += os_strlen(connector_template); 80 if (priv_key) 81 len += wpabuf_len(priv_key); 82 buf = wpabuf_alloc(len); 83 if (!buf) 84 goto fail; 85 86 /* 87 * DPPConfigurationParameters ::= SEQUENCE { 88 * privacyProtectionKey PrivateKey, 89 * configurationTemplate UTF8String, 90 * connectorTemplate UTF8String OPTIONAL} 91 */ 92 93 /* PrivateKey ::= OCTET STRING */ 94 asn1_put_octet_string(buf, priv_key); 95 96 asn1_put_utf8string(buf, conf_template); 97 if (connector_template) 98 asn1_put_utf8string(buf, connector_template); 99 wpabuf_clear_free(priv_key); 100 return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 101 fail: 102 wpabuf_clear_free(priv_key); 103 return NULL; 104 } 105 106 107 static struct wpabuf * dpp_build_attribute(struct dpp_configurator *conf) 108 { 109 struct wpabuf *conf_params, *attr; 110 111 /* 112 * aa-DPPConfigurationParameters ATTRIBUTE ::= 113 * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } 114 * 115 * Attribute ::= SEQUENCE { 116 * type OBJECT IDENTIFIER, 117 * values SET SIZE(1..MAX) OF Type 118 */ 119 conf_params = dpp_build_conf_params(conf); 120 conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, 121 ASN1_TAG_SET); 122 if (!conf_params) 123 return NULL; 124 125 attr = wpabuf_alloc(100 + wpabuf_len(conf_params)); 126 if (!attr) { 127 wpabuf_clear_free(conf_params); 128 return NULL; 129 } 130 131 asn1_put_oid(attr, &asn1_dpp_config_params_oid); 132 wpabuf_put_buf(attr, conf_params); 133 wpabuf_clear_free(conf_params); 134 135 return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 136 } 137 138 139 static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve) 140 { 141 const struct asn1_oid *oid; 142 struct wpabuf *params, *res; 143 144 switch (curve->ike_group) { 145 case 19: 146 oid = &asn1_prime256v1_oid; 147 break; 148 case 20: 149 oid = &asn1_secp384r1_oid; 150 break; 151 case 21: 152 oid = &asn1_secp521r1_oid; 153 break; 154 case 28: 155 oid = &asn1_brainpoolP256r1_oid; 156 break; 157 case 29: 158 oid = &asn1_brainpoolP384r1_oid; 159 break; 160 case 30: 161 oid = &asn1_brainpoolP512r1_oid; 162 break; 163 default: 164 return NULL; 165 } 166 167 params = wpabuf_alloc(20); 168 if (!params) 169 return NULL; 170 asn1_put_oid(params, oid); /* namedCurve */ 171 172 res = asn1_build_alg_id(&asn1_ec_public_key_oid, params); 173 wpabuf_free(params); 174 return res; 175 } 176 177 178 static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) 179 { 180 struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; 181 EC_KEY *eckey; 182 unsigned char *der = NULL; 183 int der_len; 184 185 eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign); 186 if (!eckey) 187 return NULL; 188 189 EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); 190 der_len = i2d_ECPrivateKey(eckey, &der); 191 if (der_len > 0) 192 priv_key = wpabuf_alloc_copy(der, der_len); 193 OPENSSL_free(der); 194 195 alg = dpp_build_key_alg(auth->conf->curve); 196 197 /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ 198 attr = dpp_build_attribute(auth->conf); 199 attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); 200 if (!priv_key || !attr || !alg) 201 goto fail; 202 203 /* 204 * OneAsymmetricKey ::= SEQUENCE { 205 * version Version, 206 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 207 * privateKey PrivateKey, 208 * attributes [0] Attributes OPTIONAL, 209 * ..., 210 * [[2: publicKey [1] BIT STRING OPTIONAL ]], 211 * ... 212 * } 213 */ 214 215 key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) + 216 wpabuf_len(attr)); 217 if (!key) 218 goto fail; 219 220 asn1_put_integer(key, 0); /* version = v1(0) */ 221 222 /* PrivateKeyAlgorithmIdentifier */ 223 wpabuf_put_buf(key, alg); 224 225 /* PrivateKey ::= OCTET STRING */ 226 asn1_put_octet_string(key, priv_key); 227 228 /* [0] Attributes OPTIONAL */ 229 asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr)); 230 wpabuf_put_buf(key, attr); 231 232 fail: 233 wpabuf_clear_free(attr); 234 wpabuf_clear_free(priv_key); 235 wpabuf_free(alg); 236 237 /* 238 * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage 239 * 240 * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey 241 * 242 * OneAsymmetricKey ::= SEQUENCE 243 */ 244 return asn1_encaps(asn1_encaps(key, 245 ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), 246 ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 247 } 248 249 250 static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt, 251 size_t hash_len) 252 { 253 struct wpabuf *params = NULL, *buf = NULL, *prf = NULL; 254 const struct asn1_oid *oid; 255 256 /* 257 * PBKDF2-params ::= SEQUENCE { 258 * salt CHOICE { 259 * specified OCTET STRING, 260 * otherSource AlgorithmIdentifier} 261 * iterationCount INTEGER (1..MAX), 262 * keyLength INTEGER (1..MAX), 263 * prf AlgorithmIdentifier} 264 * 265 * salt is an 64 octet value, iterationCount is 1000, keyLength is based 266 * on Configurator signing key length, prf is 267 * id-hmacWithSHA{256,384,512} based on Configurator signing key. 268 */ 269 270 if (hash_len == 32) 271 oid = &asn1_pbkdf2_hmac_sha256_oid; 272 else if (hash_len == 48) 273 oid = &asn1_pbkdf2_hmac_sha384_oid; 274 else if (hash_len == 64) 275 oid = &asn1_pbkdf2_hmac_sha512_oid; 276 else 277 goto fail; 278 prf = asn1_build_alg_id(oid, NULL); 279 if (!prf) 280 goto fail; 281 params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf)); 282 if (!params) 283 goto fail; 284 asn1_put_octet_string(params, salt); /* salt.specified */ 285 asn1_put_integer(params, 1000); /* iterationCount */ 286 asn1_put_integer(params, hash_len); /* keyLength */ 287 wpabuf_put_buf(params, prf); 288 params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 289 if (!params) 290 goto fail; 291 buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params); 292 fail: 293 wpabuf_free(params); 294 wpabuf_free(prf); 295 return buf; 296 } 297 298 299 static struct wpabuf * 300 dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, 301 const struct wpabuf *cont_enc_key) 302 { 303 struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, 304 *key_enc_alg = NULL, *salt; 305 u8 kek[DPP_MAX_HASH_LEN]; 306 u8 key[DPP_MAX_HASH_LEN]; 307 size_t key_len; 308 int res; 309 310 salt = wpabuf_alloc(64); 311 if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) 312 goto fail; 313 wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); 314 315 key_len = auth->curve->hash_len; 316 /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ 317 res = dpp_hkdf_expand(key_len, auth->bk, key_len, 318 "Enveloped Data Password", key, key_len); 319 if (res < 0) 320 goto fail; 321 wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); 322 323 if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, 324 kek, hash_len)) { 325 wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); 326 goto fail; 327 } 328 wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", 329 kek, hash_len); 330 331 enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE); 332 if (!enc_key || 333 aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key), 334 wpabuf_len(cont_enc_key), 0, NULL, NULL, 335 wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0) 336 goto fail; 337 wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key); 338 339 /* 340 * PasswordRecipientInfo ::= SEQUENCE { 341 * version CMSVersion, 342 * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, 343 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, 344 * encryptedKey EncryptedKey} 345 * 346 * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the 347 * parameters contains PBKDF2-params SEQUENCE. 348 */ 349 350 key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len); 351 key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL); 352 if (!key_der_alg || !key_enc_alg) 353 goto fail; 354 pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) + 355 wpabuf_len(key_enc_alg) + wpabuf_len(enc_key)); 356 if (!pwri) 357 goto fail; 358 359 /* version = 0 */ 360 asn1_put_integer(pwri, 0); 361 362 /* [0] KeyDerivationAlgorithmIdentifier */ 363 asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, 364 wpabuf_len(key_der_alg)); 365 wpabuf_put_buf(pwri, key_der_alg); 366 367 /* KeyEncryptionAlgorithmIdentifier */ 368 wpabuf_put_buf(pwri, key_enc_alg); 369 370 /* EncryptedKey ::= OCTET STRING */ 371 asn1_put_octet_string(pwri, enc_key); 372 373 fail: 374 wpabuf_clear_free(key_der_alg); 375 wpabuf_free(key_enc_alg); 376 wpabuf_free(enc_key); 377 wpabuf_free(salt); 378 forced_memzero(kek, sizeof(kek)); 379 return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 380 } 381 382 383 static struct wpabuf * 384 dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len, 385 const struct wpabuf *cont_enc_key) 386 { 387 struct wpabuf *pwri; 388 389 /* 390 * RecipientInfo ::= CHOICE { 391 * ktri KeyTransRecipientInfo, 392 * kari [1] KeyAgreeRecipientInfo, 393 * kekri [2] KEKRecipientInfo, 394 * pwri [3] PasswordRecipientInfo, 395 * ori [4] OtherRecipientInfo} 396 * 397 * Shall always use the pwri CHOICE. 398 */ 399 400 pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key); 401 return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3); 402 } 403 404 405 static struct wpabuf * 406 dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len, 407 const struct wpabuf *cont_enc_key) 408 { 409 struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL, 410 *enc_alg; 411 const struct asn1_oid *oid; 412 size_t enc_cont_len; 413 414 /* 415 * EncryptedContentInfo ::= SEQUENCE { 416 * contentType ContentType, 417 * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, 418 * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} 419 */ 420 421 if (hash_len == 32) 422 oid = &asn1_aes_siv_cmac_aead_256_oid; 423 else if (hash_len == 48) 424 oid = &asn1_aes_siv_cmac_aead_384_oid; 425 else if (hash_len == 64) 426 oid = &asn1_aes_siv_cmac_aead_512_oid; 427 else 428 return NULL; 429 430 key_pkg = dpp_build_key_pkg(auth); 431 enc_alg = asn1_build_alg_id(oid, NULL); 432 if (!key_pkg || !enc_alg) 433 goto fail; 434 435 wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", 436 key_pkg); 437 438 enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE; 439 enc_cont = wpabuf_alloc(enc_cont_len); 440 if (!enc_cont || 441 aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key), 442 wpabuf_head(key_pkg), wpabuf_len(key_pkg), 443 0, NULL, NULL, 444 wpabuf_put(enc_cont, enc_cont_len)) < 0) 445 goto fail; 446 447 enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) + 448 wpabuf_len(enc_cont)); 449 if (!enc_cont_info) 450 goto fail; 451 452 /* ContentType ::= OBJECT IDENTIFIER */ 453 asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid); 454 455 /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ 456 wpabuf_put_buf(enc_cont_info, enc_alg); 457 458 /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL 459 * EncryptedContent ::= OCTET STRING */ 460 asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0, 461 wpabuf_len(enc_cont)); 462 wpabuf_put_buf(enc_cont_info, enc_cont); 463 464 fail: 465 wpabuf_clear_free(key_pkg); 466 wpabuf_free(enc_cont); 467 wpabuf_free(enc_alg); 468 return enc_cont_info; 469 } 470 471 472 static struct wpabuf * dpp_gen_random(size_t len) 473 { 474 struct wpabuf *key; 475 476 key = wpabuf_alloc(len); 477 if (!key || os_get_random(wpabuf_put(key, len), len) < 0) { 478 wpabuf_free(key); 479 key = NULL; 480 } 481 wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key); 482 return key; 483 } 484 485 486 struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth) 487 { 488 struct wpabuf *env = NULL; 489 struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL; 490 struct wpabuf *cont_enc_key = NULL; 491 size_t hash_len; 492 493 if (!auth->conf) { 494 wpa_printf(MSG_DEBUG, 495 "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData"); 496 return NULL; 497 } 498 499 if (!auth->provision_configurator) { 500 wpa_printf(MSG_DEBUG, 501 "DPP: Configurator provisioning not allowed"); 502 return NULL; 503 } 504 505 wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData"); 506 507 hash_len = auth->conf->curve->hash_len; 508 cont_enc_key = dpp_gen_random(hash_len); 509 if (!cont_enc_key) 510 goto fail; 511 recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key); 512 enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key); 513 if (!recipient_info || !enc_cont_info) 514 goto fail; 515 516 env = wpabuf_alloc(wpabuf_len(recipient_info) + 517 wpabuf_len(enc_cont_info) + 518 100); 519 if (!env) 520 goto fail; 521 522 /* 523 * DPPEnvelopedData ::= EnvelopedData 524 * 525 * EnvelopedData ::= SEQUENCE { 526 * version CMSVersion, 527 * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, 528 * recipientInfos RecipientInfos, 529 * encryptedContentInfo EncryptedContentInfo, 530 * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} 531 * 532 * For DPP, version is 3, both originatorInfo and 533 * unprotectedAttrs are omitted, and recipientInfos contains a single 534 * RecipientInfo. 535 */ 536 537 /* EnvelopedData.version = 3 */ 538 asn1_put_integer(env, 3); 539 540 /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */ 541 asn1_put_set(env, recipient_info); 542 543 /* EncryptedContentInfo ::= SEQUENCE */ 544 asn1_put_sequence(env, enc_cont_info); 545 546 env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 547 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env); 548 out: 549 wpabuf_clear_free(cont_enc_key); 550 wpabuf_clear_free(recipient_info); 551 wpabuf_free(enc_cont_info); 552 return env; 553 fail: 554 wpabuf_free(env); 555 env = NULL; 556 goto out; 557 } 558 559 560 struct dpp_enveloped_data { 561 const u8 *enc_cont; 562 size_t enc_cont_len; 563 const u8 *enc_key; 564 size_t enc_key_len; 565 const u8 *salt; 566 size_t pbkdf2_key_len; 567 size_t prf_hash_len; 568 }; 569 570 571 static int dpp_parse_recipient_infos(const u8 *pos, size_t len, 572 struct dpp_enveloped_data *data) 573 { 574 struct asn1_hdr hdr; 575 const u8 *end = pos + len; 576 const u8 *next, *e_end; 577 struct asn1_oid oid; 578 int val; 579 const u8 *params; 580 size_t params_len; 581 582 wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len); 583 584 /* 585 * RecipientInfo ::= CHOICE { 586 * ktri KeyTransRecipientInfo, 587 * kari [1] KeyAgreeRecipientInfo, 588 * kekri [2] KEKRecipientInfo, 589 * pwri [3] PasswordRecipientInfo, 590 * ori [4] OtherRecipientInfo} 591 * 592 * Shall always use the pwri CHOICE. 593 */ 594 595 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed || 596 !asn1_is_cs_tag(&hdr, 3)) { 597 asn1_unexpected(&hdr, "DPP: Expected CHOICE [3] (pwri)"); 598 return -1; 599 } 600 wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo", 601 hdr.payload, hdr.length); 602 pos = hdr.payload; 603 end = pos + hdr.length; 604 605 /* 606 * PasswordRecipientInfo ::= SEQUENCE { 607 * version CMSVersion, 608 * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, 609 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, 610 * encryptedKey EncryptedKey} 611 * 612 * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the 613 * parameters contains PBKDF2-params SEQUENCE. 614 */ 615 616 if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) 617 return -1; 618 pos = hdr.payload; 619 620 if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) 621 return -1; 622 if (val != 0) { 623 wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0"); 624 return -1; 625 } 626 627 wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version", 628 pos, end - pos); 629 630 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed || 631 !asn1_is_cs_tag(&hdr, 0)) { 632 asn1_unexpected(&hdr, 633 "DPP: Expected keyDerivationAlgorithm [0]"); 634 return -1; 635 } 636 pos = hdr.payload; 637 e_end = pos + hdr.length; 638 639 /* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */ 640 if (asn1_get_alg_id(pos, e_end - pos, &oid, ¶ms, ¶ms_len, 641 &next) < 0) 642 return -1; 643 if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) { 644 char buf[80]; 645 646 asn1_oid_to_str(&oid, buf, sizeof(buf)); 647 wpa_printf(MSG_DEBUG, 648 "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s", 649 buf); 650 return -1; 651 } 652 653 /* 654 * PBKDF2-params ::= SEQUENCE { 655 * salt CHOICE { 656 * specified OCTET STRING, 657 * otherSource AlgorithmIdentifier} 658 * iterationCount INTEGER (1..MAX), 659 * keyLength INTEGER (1..MAX), 660 * prf AlgorithmIdentifier} 661 * 662 * salt is an 64 octet value, iterationCount is 1000, keyLength is based 663 * on Configurator signing key length, prf is 664 * id-hmacWithSHA{256,384,512} based on Configurator signing key. 665 */ 666 if (!params || 667 asn1_get_sequence(params, params_len, &hdr, &e_end) < 0) 668 return -1; 669 pos = hdr.payload; 670 671 if (asn1_get_next(pos, e_end - pos, &hdr) < 0 || 672 !asn1_is_octetstring(&hdr)) { 673 asn1_unexpected(&hdr, 674 "DPP: Expected OCTETSTRING (salt.specified)"); 675 return -1; 676 } 677 wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified", 678 hdr.payload, hdr.length); 679 if (hdr.length != 64) { 680 wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u", 681 hdr.length); 682 return -1; 683 } 684 data->salt = hdr.payload; 685 pos = hdr.payload + hdr.length; 686 687 if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) 688 return -1; 689 if (val != 1000) { 690 wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val); 691 return -1; 692 } 693 694 if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) 695 return -1; 696 if (val != 32 && val != 48 && val != 64) { 697 wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val); 698 return -1; 699 } 700 data->pbkdf2_key_len = val; 701 702 if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 || 703 asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) { 704 wpa_printf(MSG_DEBUG, "DPP: Could not parse prf"); 705 return -1; 706 } 707 if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) { 708 data->prf_hash_len = 32; 709 } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) { 710 data->prf_hash_len = 48; 711 } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) { 712 data->prf_hash_len = 64; 713 } else { 714 char buf[80]; 715 716 asn1_oid_to_str(&oid, buf, sizeof(buf)); 717 wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s", 718 buf); 719 return -1; 720 } 721 722 pos = next; 723 724 /* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier 725 * 726 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 727 * 728 * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or 729 * id-alg-AES-SIV-CMAC-aed-512. */ 730 if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) 731 return -1; 732 if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && 733 !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && 734 !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { 735 char buf[80]; 736 737 asn1_oid_to_str(&oid, buf, sizeof(buf)); 738 wpa_printf(MSG_DEBUG, 739 "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s", 740 buf); 741 return -1; 742 } 743 744 /* 745 * encryptedKey EncryptedKey 746 * 747 * EncryptedKey ::= OCTET STRING 748 */ 749 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 750 !asn1_is_octetstring(&hdr)) { 751 asn1_unexpected(&hdr, 752 "DPP: Expected OCTETSTRING (pwri.encryptedKey)"); 753 return -1; 754 } 755 wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey", 756 hdr.payload, hdr.length); 757 data->enc_key = hdr.payload; 758 data->enc_key_len = hdr.length; 759 760 return 0; 761 } 762 763 764 static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end, 765 struct dpp_enveloped_data *data) 766 { 767 struct asn1_hdr hdr; 768 struct asn1_oid oid; 769 770 /* 771 * EncryptedContentInfo ::= SEQUENCE { 772 * contentType ContentType, 773 * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, 774 * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} 775 */ 776 if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) 777 return -1; 778 wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo", 779 hdr.payload, hdr.length); 780 if (pos < end) { 781 wpa_hexdump(MSG_DEBUG, 782 "DPP: Unexpected extra data after EncryptedContentInfo", 783 pos, end - pos); 784 return -1; 785 } 786 787 end = pos; 788 pos = hdr.payload; 789 790 /* ContentType ::= OBJECT IDENTIFIER */ 791 if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { 792 wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType"); 793 return -1; 794 } 795 if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) { 796 char buf[80]; 797 798 asn1_oid_to_str(&oid, buf, sizeof(buf)); 799 wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf); 800 return -1; 801 } 802 803 /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ 804 if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) 805 return -1; 806 if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && 807 !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && 808 !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { 809 char buf[80]; 810 811 asn1_oid_to_str(&oid, buf, sizeof(buf)); 812 wpa_printf(MSG_DEBUG, 813 "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s", 814 buf); 815 return -1; 816 } 817 /* ignore optional parameters */ 818 819 /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL 820 * EncryptedContent ::= OCTET STRING */ 821 if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed || 822 !asn1_is_cs_tag(&hdr, 0)) { 823 asn1_unexpected(&hdr, 824 "DPP: Expected [0] IMPLICIT (EncryptedContent)"); 825 return -1; 826 } 827 wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent", 828 hdr.payload, hdr.length); 829 data->enc_cont = hdr.payload; 830 data->enc_cont_len = hdr.length; 831 return 0; 832 } 833 834 835 static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len, 836 struct dpp_enveloped_data *data) 837 { 838 struct asn1_hdr hdr; 839 const u8 *pos, *end; 840 int val; 841 842 os_memset(data, 0, sizeof(*data)); 843 844 /* 845 * DPPEnvelopedData ::= EnvelopedData 846 * 847 * EnvelopedData ::= SEQUENCE { 848 * version CMSVersion, 849 * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, 850 * recipientInfos RecipientInfos, 851 * encryptedContentInfo EncryptedContentInfo, 852 * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} 853 * 854 * CMSVersion ::= INTEGER 855 * 856 * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo 857 * 858 * For DPP, version is 3, both originatorInfo and 859 * unprotectedAttrs are omitted, and recipientInfos contains a single 860 * RecipientInfo. 861 */ 862 if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0) 863 return -1; 864 pos = hdr.payload; 865 if (end < env_data + env_data_len) { 866 wpa_hexdump(MSG_DEBUG, 867 "DPP: Unexpected extra data after DPPEnvelopedData", 868 end, env_data + env_data_len - end); 869 return -1; 870 } 871 872 if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) 873 return -1; 874 if (val != 3) { 875 wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3"); 876 return -1; 877 } 878 879 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) { 880 asn1_unexpected(&hdr, 881 "DPP: Expected SET (RecipientInfos)"); 882 return -1; 883 } 884 885 if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0) 886 return -1; 887 return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end, 888 data); 889 } 890 891 892 static struct dpp_asymmetric_key * 893 dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) 894 { 895 struct asn1_hdr hdr; 896 const u8 *pos = buf, *end = buf + len, *next; 897 int val; 898 const u8 *params; 899 size_t params_len; 900 struct asn1_oid oid; 901 char txt[80]; 902 struct dpp_asymmetric_key *key; 903 EC_KEY *eckey; 904 905 wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len); 906 907 key = os_zalloc(sizeof(*key)); 908 if (!key) 909 return NULL; 910 911 /* 912 * OneAsymmetricKey ::= SEQUENCE { 913 * version Version, 914 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 915 * privateKey PrivateKey, 916 * attributes [0] Attributes OPTIONAL, 917 * ..., 918 * [[2: publicKey [1] BIT STRING OPTIONAL ]], 919 * ... 920 * } 921 */ 922 if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) 923 goto fail; 924 pos = hdr.payload; 925 926 /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ 927 if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) 928 goto fail; 929 if (val != 0 && val != 1) { 930 wpa_printf(MSG_DEBUG, 931 "DPP: Unsupported DPPAsymmetricKeyPackage version %d", 932 val); 933 goto fail; 934 } 935 936 /* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */ 937 if (asn1_get_alg_id(pos, end - pos, &oid, ¶ms, ¶ms_len, 938 &pos) < 0) 939 goto fail; 940 if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) { 941 asn1_oid_to_str(&oid, txt, sizeof(txt)); 942 wpa_printf(MSG_DEBUG, 943 "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s", 944 txt); 945 goto fail; 946 } 947 wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params", 948 params, params_len); 949 /* 950 * ECParameters ::= CHOICE { 951 * namedCurve OBJECT IDENTIFIER 952 * -- implicitCurve NULL 953 * -- specifiedCurve SpecifiedECDomain} 954 */ 955 if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) { 956 wpa_printf(MSG_DEBUG, 957 "DPP: Could not parse ECParameters.namedCurve"); 958 goto fail; 959 } 960 asn1_oid_to_str(&oid, txt, sizeof(txt)); 961 wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt); 962 /* Assume the curve is identified within ECPrivateKey, so that this 963 * separate indication is not really needed. */ 964 965 /* 966 * PrivateKey ::= OCTET STRING 967 * (Contains DER encoding of ECPrivateKey) 968 */ 969 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 970 !asn1_is_octetstring(&hdr)) { 971 asn1_unexpected(&hdr, 972 "DPP: Expected OCTETSTRING (PrivateKey)"); 973 goto fail; 974 } 975 wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey", 976 hdr.payload, hdr.length); 977 pos = hdr.payload + hdr.length; 978 eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); 979 if (!eckey) { 980 wpa_printf(MSG_INFO, 981 "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", 982 ERR_error_string(ERR_get_error(), NULL)); 983 goto fail; 984 } 985 key->csign = EVP_PKEY_new(); 986 if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) { 987 EC_KEY_free(eckey); 988 goto fail; 989 } 990 if (wpa_debug_show_keys) 991 dpp_debug_print_key("DPP: Received c-sign-key", key->csign); 992 993 /* 994 * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } 995 * 996 * Exactly one instance of type Attribute in OneAsymmetricKey. 997 */ 998 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed || 999 !asn1_is_cs_tag(&hdr, 0)) { 1000 asn1_unexpected(&hdr, "DPP: Expected [0] Attributes"); 1001 goto fail; 1002 } 1003 wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes", 1004 hdr.payload, hdr.length); 1005 if (hdr.payload + hdr.length < end) { 1006 wpa_hexdump_key(MSG_MSGDUMP, 1007 "DPP: Ignore additional data at the end of OneAsymmetricKey", 1008 hdr.payload + hdr.length, 1009 end - (hdr.payload + hdr.length)); 1010 } 1011 pos = hdr.payload; 1012 end = hdr.payload + hdr.length; 1013 1014 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) { 1015 asn1_unexpected(&hdr, "DPP: Expected SET (Attributes)"); 1016 goto fail; 1017 } 1018 if (hdr.payload + hdr.length < end) { 1019 wpa_hexdump_key(MSG_MSGDUMP, 1020 "DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)", 1021 hdr.payload + hdr.length, 1022 end - (hdr.payload + hdr.length)); 1023 } 1024 pos = hdr.payload; 1025 end = hdr.payload + hdr.length; 1026 1027 /* 1028 * OneAsymmetricKeyAttributes ATTRIBUTE ::= { 1029 * aa-DPPConfigurationParameters, 1030 * ... -- For local profiles 1031 * } 1032 * 1033 * aa-DPPConfigurationParameters ATTRIBUTE ::= 1034 * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } 1035 * 1036 * Attribute ::= SEQUENCE { 1037 * type OBJECT IDENTIFIER, 1038 * values SET SIZE(1..MAX) OF Type 1039 * 1040 * Exactly one instance of ATTRIBUTE in attrValues. 1041 */ 1042 if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) 1043 goto fail; 1044 if (pos < end) { 1045 wpa_hexdump_key(MSG_MSGDUMP, 1046 "DPP: Ignore additional data at the end of ATTRIBUTE", 1047 pos, end - pos); 1048 } 1049 end = pos; 1050 pos = hdr.payload; 1051 1052 if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) 1053 goto fail; 1054 if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) { 1055 asn1_oid_to_str(&oid, txt, sizeof(txt)); 1056 wpa_printf(MSG_DEBUG, 1057 "DPP: Unexpected Attribute identifier %s", txt); 1058 goto fail; 1059 } 1060 1061 if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) { 1062 asn1_unexpected(&hdr, "DPP: Expected SET (Attribute)"); 1063 goto fail; 1064 } 1065 pos = hdr.payload; 1066 end = hdr.payload + hdr.length; 1067 1068 /* 1069 * DPPConfigurationParameters ::= SEQUENCE { 1070 * privacyProtectionKey PrivateKey, 1071 * configurationTemplate UTF8String, 1072 * connectorTemplate UTF8String OPTIONAL} 1073 */ 1074 1075 wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters", 1076 pos, end - pos); 1077 if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) 1078 goto fail; 1079 if (pos < end) { 1080 wpa_hexdump_key(MSG_MSGDUMP, 1081 "DPP: Ignore additional data after DPPConfigurationParameters", 1082 pos, end - pos); 1083 } 1084 end = pos; 1085 pos = hdr.payload; 1086 1087 /* 1088 * PrivateKey ::= OCTET STRING 1089 * (Contains DER encoding of ECPrivateKey) 1090 */ 1091 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1092 !asn1_is_octetstring(&hdr)) { 1093 asn1_unexpected(&hdr, "DPP: Expected OCTETSTRING (PrivateKey)"); 1094 goto fail; 1095 } 1096 wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey", 1097 hdr.payload, hdr.length); 1098 pos = hdr.payload + hdr.length; 1099 eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); 1100 if (!eckey) { 1101 wpa_printf(MSG_INFO, 1102 "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", 1103 ERR_error_string(ERR_get_error(), NULL)); 1104 goto fail; 1105 } 1106 key->pp_key = EVP_PKEY_new(); 1107 if (!key->pp_key || EVP_PKEY_assign_EC_KEY(key->pp_key, eckey) != 1) { 1108 EC_KEY_free(eckey); 1109 goto fail; 1110 } 1111 if (wpa_debug_show_keys) 1112 dpp_debug_print_key("DPP: Received privacyProtectionKey", 1113 key->pp_key); 1114 1115 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1116 !asn1_is_utf8string(&hdr)) { 1117 asn1_unexpected(&hdr, 1118 "DPP: Expected UTF8STRING (configurationTemplate)"); 1119 goto fail; 1120 } 1121 wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate", 1122 hdr.payload, hdr.length); 1123 key->config_template = os_zalloc(hdr.length + 1); 1124 if (!key->config_template) 1125 goto fail; 1126 os_memcpy(key->config_template, hdr.payload, hdr.length); 1127 1128 pos = hdr.payload + hdr.length; 1129 1130 if (pos < end) { 1131 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1132 !asn1_is_utf8string(&hdr)) { 1133 asn1_unexpected(&hdr, 1134 "DPP: Expected UTF8STRING (connectorTemplate)"); 1135 goto fail; 1136 } 1137 wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate", 1138 hdr.payload, hdr.length); 1139 key->connector_template = os_zalloc(hdr.length + 1); 1140 if (!key->connector_template) 1141 goto fail; 1142 os_memcpy(key->connector_template, hdr.payload, hdr.length); 1143 } 1144 1145 return key; 1146 fail: 1147 wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey"); 1148 dpp_free_asymmetric_key(key); 1149 return NULL; 1150 } 1151 1152 1153 static struct dpp_asymmetric_key * 1154 dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) 1155 { 1156 struct asn1_hdr hdr; 1157 const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len; 1158 struct dpp_asymmetric_key *first = NULL, *last = NULL, *key; 1159 1160 wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", 1161 key_pkg, key_pkg_len); 1162 1163 /* 1164 * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage 1165 * 1166 * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey 1167 */ 1168 while (pos < end) { 1169 if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 || 1170 !(key = dpp_parse_one_asymmetric_key(hdr.payload, 1171 hdr.length))) { 1172 dpp_free_asymmetric_key(first); 1173 return NULL; 1174 } 1175 if (!last) { 1176 first = last = key; 1177 } else { 1178 last->next = key; 1179 last = key; 1180 } 1181 } 1182 1183 return first; 1184 } 1185 1186 1187 int dpp_conf_resp_env_data(struct dpp_authentication *auth, 1188 const u8 *env_data, size_t env_data_len) 1189 { 1190 u8 key[DPP_MAX_HASH_LEN]; 1191 size_t key_len; 1192 u8 kek[DPP_MAX_HASH_LEN]; 1193 u8 cont_encr_key[DPP_MAX_HASH_LEN]; 1194 size_t cont_encr_key_len; 1195 int res; 1196 u8 *key_pkg; 1197 size_t key_pkg_len; 1198 struct dpp_enveloped_data data; 1199 struct dpp_asymmetric_key *keys; 1200 1201 wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len); 1202 1203 if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) 1204 return -1; 1205 1206 key_len = auth->curve->hash_len; 1207 /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ 1208 res = dpp_hkdf_expand(key_len, auth->bk, key_len, 1209 "Enveloped Data Password", key, key_len); 1210 if (res < 0) 1211 return -1; 1212 wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); 1213 1214 if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, 1215 kek, data.pbkdf2_key_len)) { 1216 wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); 1217 return -1; 1218 } 1219 wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", 1220 kek, data.pbkdf2_key_len); 1221 1222 if (data.enc_key_len < AES_BLOCK_SIZE || 1223 data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) { 1224 wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length"); 1225 return -1; 1226 } 1227 res = aes_siv_decrypt(kek, data.pbkdf2_key_len, 1228 data.enc_key, data.enc_key_len, 1229 0, NULL, NULL, cont_encr_key); 1230 forced_memzero(kek, data.pbkdf2_key_len); 1231 if (res < 0) { 1232 wpa_printf(MSG_DEBUG, 1233 "DPP: AES-SIV decryption of encryptedKey failed"); 1234 return -1; 1235 } 1236 cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE; 1237 wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key", 1238 cont_encr_key, cont_encr_key_len); 1239 1240 if (data.enc_cont_len < AES_BLOCK_SIZE) 1241 return -1; 1242 key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE; 1243 key_pkg = os_malloc(key_pkg_len); 1244 if (!key_pkg) 1245 return -1; 1246 res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len, 1247 data.enc_cont, data.enc_cont_len, 1248 0, NULL, NULL, key_pkg); 1249 forced_memzero(cont_encr_key, cont_encr_key_len); 1250 if (res < 0) { 1251 bin_clear_free(key_pkg, key_pkg_len); 1252 wpa_printf(MSG_DEBUG, 1253 "DPP: AES-SIV decryption of encryptedContent failed"); 1254 return -1; 1255 } 1256 1257 keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len); 1258 bin_clear_free(key_pkg, key_pkg_len); 1259 dpp_free_asymmetric_key(auth->conf_key_pkg); 1260 auth->conf_key_pkg = keys; 1261 1262 return keys != NULL; 1263 } 1264 1265 #endif /* CONFIG_DPP2 */ 1266