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