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