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