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
20void 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
35static 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);
74fail:
75	wpabuf_clear_free(priv_key);
76	return NULL;
77}
78
79
80static 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
112static 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
151static 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 (!priv_key || !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
196fail:
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
214static 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);
256fail:
257	wpabuf_free(params);
258	wpabuf_free(prf);
259	return buf;
260}
261
262
263static struct wpabuf *
264dpp_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
337fail:
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
347static struct wpabuf *
348dpp_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
369static struct wpabuf *
370dpp_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
428fail:
429	wpabuf_clear_free(key_pkg);
430	wpabuf_free(enc_cont);
431	wpabuf_free(enc_alg);
432	return enc_cont_info;
433}
434
435
436static 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
450struct 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);
512out:
513	wpabuf_clear_free(cont_enc_key);
514	wpabuf_clear_free(recipient_info);
515	wpabuf_free(enc_cont_info);
516	return env;
517fail:
518	wpabuf_free(env);
519	env = NULL;
520	goto out;
521}
522
523
524struct dpp_enveloped_data {
525	const u8 *enc_cont;
526	size_t enc_cont_len;
527	const u8 *enc_key;
528	size_t enc_key_len;
529	const u8 *salt;
530	size_t pbkdf2_key_len;
531	size_t prf_hash_len;
532};
533
534
535static int dpp_parse_recipient_infos(const u8 *pos, size_t len,
536				     struct dpp_enveloped_data *data)
537{
538	struct asn1_hdr hdr;
539	const u8 *end = pos + len;
540	const u8 *next, *e_end;
541	struct asn1_oid oid;
542	int val;
543	const u8 *params;
544	size_t params_len;
545
546	wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len);
547
548	/*
549	 * RecipientInfo ::= CHOICE {
550	 *    ktri		KeyTransRecipientInfo,
551	 *    kari	[1]	KeyAgreeRecipientInfo,
552	 *    kekri	[2]	KEKRecipientInfo,
553	 *    pwri	[3]	PasswordRecipientInfo,
554	 *    ori	[4]	OtherRecipientInfo}
555	 *
556	 * Shall always use the pwri CHOICE.
557	 */
558
559	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
560	    !asn1_is_cs_tag(&hdr, 3)) {
561		asn1_unexpected(&hdr, "DPP: Expected CHOICE [3] (pwri)");
562		return -1;
563	}
564	wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo",
565		    hdr.payload, hdr.length);
566	pos = hdr.payload;
567	end = pos + hdr.length;
568
569	/*
570	 * PasswordRecipientInfo ::= SEQUENCE {
571	 *    version			CMSVersion,
572	 *    keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL,
573	 *    keyEncryptionAlgorithm	KeyEncryptionAlgorithmIdentifier,
574	 *    encryptedKey		EncryptedKey}
575	 *
576	 * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the
577	 * parameters contains PBKDF2-params SEQUENCE.
578	 */
579
580	if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0)
581		return -1;
582	pos = hdr.payload;
583
584	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
585		return -1;
586	if (val != 0) {
587		wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0");
588		return -1;
589	}
590
591	wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version",
592		    pos, end - pos);
593
594	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
595	    !asn1_is_cs_tag(&hdr, 0)) {
596		asn1_unexpected(&hdr,
597				"DPP: Expected keyDerivationAlgorithm [0]");
598		return -1;
599	}
600	pos = hdr.payload;
601	e_end = pos + hdr.length;
602
603	/* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */
604	if (asn1_get_alg_id(pos, e_end - pos, &oid, &params, &params_len,
605			    &next) < 0)
606		return -1;
607	if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) {
608		char buf[80];
609
610		asn1_oid_to_str(&oid, buf, sizeof(buf));
611		wpa_printf(MSG_DEBUG,
612			   "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s",
613			   buf);
614		return -1;
615	}
616
617	/*
618	 * PBKDF2-params ::= SEQUENCE {
619	 *    salt CHOICE {
620	 *       specified OCTET STRING,
621	 *       otherSource AlgorithmIdentifier}
622	 *    iterationCount INTEGER (1..MAX),
623	 *    keyLength INTEGER (1..MAX),
624	 *    prf AlgorithmIdentifier}
625	 *
626	 * salt is an 64 octet value, iterationCount is 1000, keyLength is based
627	 * on Configurator signing key length, prf is
628	 * id-hmacWithSHA{256,384,512} based on Configurator signing key.
629	 */
630	if (!params ||
631	    asn1_get_sequence(params, params_len, &hdr, &e_end) < 0)
632		return -1;
633	pos = hdr.payload;
634
635	if (asn1_get_next(pos, e_end - pos, &hdr) < 0 ||
636	    !asn1_is_octetstring(&hdr)) {
637		asn1_unexpected(&hdr,
638				"DPP: Expected OCTETSTRING (salt.specified)");
639		return -1;
640	}
641	wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified",
642		    hdr.payload, hdr.length);
643	if (hdr.length != 64) {
644		wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u",
645			   hdr.length);
646		return -1;
647	}
648	data->salt = hdr.payload;
649	pos = hdr.payload + hdr.length;
650
651	if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0)
652		return -1;
653	if (val != 1000) {
654		wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val);
655		return -1;
656	}
657
658	if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0)
659		return -1;
660	if (val != 32 && val != 48 && val != 64) {
661		wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val);
662		return -1;
663	}
664	data->pbkdf2_key_len = val;
665
666	if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 ||
667	    asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) {
668		wpa_printf(MSG_DEBUG, "DPP: Could not parse prf");
669		return -1;
670	}
671	if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) {
672		data->prf_hash_len = 32;
673	} else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) {
674		data->prf_hash_len = 48;
675	} else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) {
676		data->prf_hash_len = 64;
677	} else {
678		char buf[80];
679
680		asn1_oid_to_str(&oid, buf, sizeof(buf));
681		wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s",
682			   buf);
683		return -1;
684	}
685
686	pos = next;
687
688	/* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier
689	 *
690	 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
691	 *
692	 * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or
693	 * id-alg-AES-SIV-CMAC-aed-512. */
694	if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0)
695		return -1;
696	if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) &&
697	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) &&
698	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) {
699		char buf[80];
700
701		asn1_oid_to_str(&oid, buf, sizeof(buf));
702		wpa_printf(MSG_DEBUG,
703			   "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s",
704			   buf);
705		return -1;
706	}
707
708	/*
709	 * encryptedKey EncryptedKey
710	 *
711	 * EncryptedKey ::= OCTET STRING
712	 */
713	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
714	    !asn1_is_octetstring(&hdr)) {
715		asn1_unexpected(&hdr,
716				"DPP: Expected OCTETSTRING (pwri.encryptedKey)");
717		return -1;
718	}
719	wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey",
720		    hdr.payload, hdr.length);
721	data->enc_key = hdr.payload;
722	data->enc_key_len = hdr.length;
723
724	return 0;
725}
726
727
728static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end,
729					    struct dpp_enveloped_data *data)
730{
731	struct asn1_hdr hdr;
732	struct asn1_oid oid;
733
734	/*
735	 * EncryptedContentInfo ::= SEQUENCE {
736	 *    contentType			ContentType,
737	 *    contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
738	 *    encryptedContent	[0] IMPLICIT	EncryptedContent OPTIONAL}
739	 */
740	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
741		return -1;
742	wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo",
743		    hdr.payload, hdr.length);
744	if (pos < end) {
745		wpa_hexdump(MSG_DEBUG,
746			    "DPP: Unexpected extra data after EncryptedContentInfo",
747			    pos, end - pos);
748		return -1;
749	}
750
751	end = pos;
752	pos = hdr.payload;
753
754	/* ContentType ::= OBJECT IDENTIFIER */
755	if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) {
756		wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType");
757		return -1;
758	}
759	if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) {
760		char buf[80];
761
762		asn1_oid_to_str(&oid, buf, sizeof(buf));
763		wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf);
764		return -1;
765	}
766
767	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
768	if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0)
769		return -1;
770	if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) &&
771	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) &&
772	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) {
773		char buf[80];
774
775		asn1_oid_to_str(&oid, buf, sizeof(buf));
776		wpa_printf(MSG_DEBUG,
777			   "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s",
778			   buf);
779		return -1;
780	}
781	/* ignore optional parameters */
782
783	/* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
784	 * EncryptedContent ::= OCTET STRING */
785	if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
786	    !asn1_is_cs_tag(&hdr, 0)) {
787		asn1_unexpected(&hdr,
788				"DPP: Expected [0] IMPLICIT (EncryptedContent)");
789		return -1;
790	}
791	wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent",
792		    hdr.payload, hdr.length);
793	data->enc_cont = hdr.payload;
794	data->enc_cont_len = hdr.length;
795	return 0;
796}
797
798
799static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len,
800				    struct dpp_enveloped_data *data)
801{
802	struct asn1_hdr hdr;
803	const u8 *pos, *end;
804	int val;
805
806	os_memset(data, 0, sizeof(*data));
807
808	/*
809	 * DPPEnvelopedData ::= EnvelopedData
810	 *
811	 * EnvelopedData ::= SEQUENCE {
812	 *    version			CMSVersion,
813	 *    originatorInfo	[0]	IMPLICIT OriginatorInfo OPTIONAL,
814	 *    recipientInfos		RecipientInfos,
815	 *    encryptedContentInfo	EncryptedContentInfo,
816	 *    unprotectedAttrs  [1] IMPLICIT	UnprotectedAttributes OPTIONAL}
817	 *
818	 * CMSVersion ::= INTEGER
819	 *
820	 * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo
821	 *
822	 * For DPP, version is 3, both originatorInfo and
823	 * unprotectedAttrs are omitted, and recipientInfos contains a single
824	 * RecipientInfo.
825	 */
826	if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0)
827		return -1;
828	pos = hdr.payload;
829	if (end < env_data + env_data_len) {
830		wpa_hexdump(MSG_DEBUG,
831			    "DPP: Unexpected extra data after DPPEnvelopedData",
832			    end, env_data + env_data_len - end);
833		return -1;
834	}
835
836	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
837		return -1;
838	if (val != 3) {
839		wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3");
840		return -1;
841	}
842
843	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
844		asn1_unexpected(&hdr,
845				"DPP: Expected SET (RecipientInfos)");
846		return -1;
847	}
848
849	if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0)
850		return -1;
851	return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end,
852						data);
853}
854
855
856static struct dpp_asymmetric_key *
857dpp_parse_one_asymmetric_key(const u8 *buf, size_t len)
858{
859	struct asn1_hdr hdr;
860	const u8 *pos = buf, *end = buf + len, *next;
861	int val;
862	const u8 *params;
863	size_t params_len;
864	struct asn1_oid oid;
865	char txt[80];
866	struct dpp_asymmetric_key *key;
867
868	wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len);
869
870	key = os_zalloc(sizeof(*key));
871	if (!key)
872		return NULL;
873
874	/*
875	 * OneAsymmetricKey ::= SEQUENCE {
876	 *    version			Version,
877	 *    privateKeyAlgorithm	PrivateKeyAlgorithmIdentifier,
878	 *    privateKey		PrivateKey,
879	 *    attributes		[0] Attributes OPTIONAL,
880	 *    ...,
881	 *    [[2: publicKey		[1] BIT STRING OPTIONAL ]],
882	 *    ...
883	 * }
884	 */
885	if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0)
886		goto fail;
887	pos = hdr.payload;
888
889	/* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */
890	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
891		goto fail;
892	if (val != 0 && val != 1) {
893		wpa_printf(MSG_DEBUG,
894			   "DPP: Unsupported DPPAsymmetricKeyPackage version %d",
895			   val);
896		goto fail;
897	}
898
899	/* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */
900	if (asn1_get_alg_id(pos, end - pos, &oid, &params, &params_len,
901			    &pos) < 0)
902		goto fail;
903	if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) {
904		asn1_oid_to_str(&oid, txt, sizeof(txt));
905		wpa_printf(MSG_DEBUG,
906			   "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s",
907			   txt);
908		goto fail;
909	}
910	wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params",
911		    params, params_len);
912	/*
913	 * ECParameters ::= CHOICE {
914	 *    namedCurve	OBJECT IDENTIFIER
915	 *    -- implicitCurve	NULL
916	 *    -- specifiedCurve	SpecifiedECDomain}
917	 */
918	if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) {
919		wpa_printf(MSG_DEBUG,
920			   "DPP: Could not parse ECParameters.namedCurve");
921		goto fail;
922	}
923	asn1_oid_to_str(&oid, txt, sizeof(txt));
924	wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt);
925	/* Assume the curve is identified within ECPrivateKey, so that this
926	 * separate indication is not really needed. */
927
928	/*
929	 * PrivateKey ::= OCTET STRING
930	 *    (Contains DER encoding of ECPrivateKey)
931	 */
932	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
933	    !asn1_is_octetstring(&hdr)) {
934		asn1_unexpected(&hdr,
935				"DPP: Expected OCTETSTRING (PrivateKey)");
936		goto fail;
937	}
938	wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey",
939			hdr.payload, hdr.length);
940	pos = hdr.payload + hdr.length;
941	key->csign = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
942	if (!key->csign)
943		goto fail;
944	if (wpa_debug_show_keys)
945		dpp_debug_print_key("DPP: Received c-sign-key", key->csign);
946
947	/*
948	 * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } }
949	 *
950	 * Exactly one instance of type Attribute in OneAsymmetricKey.
951	 */
952	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
953	    !asn1_is_cs_tag(&hdr, 0)) {
954		asn1_unexpected(&hdr, "DPP: Expected [0] Attributes");
955		goto fail;
956	}
957	wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes",
958			hdr.payload, hdr.length);
959	if (hdr.payload + hdr.length < end) {
960		wpa_hexdump_key(MSG_MSGDUMP,
961				"DPP: Ignore additional data at the end of OneAsymmetricKey",
962				hdr.payload + hdr.length,
963				end - (hdr.payload + hdr.length));
964	}
965	pos = hdr.payload;
966	end = hdr.payload + hdr.length;
967
968	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
969		asn1_unexpected(&hdr, "DPP: Expected SET (Attributes)");
970		goto fail;
971	}
972	if (hdr.payload + hdr.length < end) {
973		wpa_hexdump_key(MSG_MSGDUMP,
974				"DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)",
975				hdr.payload + hdr.length,
976				end - (hdr.payload + hdr.length));
977	}
978	pos = hdr.payload;
979	end = hdr.payload + hdr.length;
980
981	/*
982	 * OneAsymmetricKeyAttributes ATTRIBUTE ::= {
983	 *    aa-DPPConfigurationParameters,
984	 *    ... -- For local profiles
985	 * }
986	 *
987	 * aa-DPPConfigurationParameters ATTRIBUTE ::=
988	 * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams }
989	 *
990	 * Attribute ::= SEQUENCE {
991	 *    type OBJECT IDENTIFIER,
992	 *    values SET SIZE(1..MAX) OF Type
993	 *
994	 * Exactly one instance of ATTRIBUTE in attrValues.
995	 */
996	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
997		goto fail;
998	if (pos < end) {
999		wpa_hexdump_key(MSG_MSGDUMP,
1000				"DPP: Ignore additional data at the end of ATTRIBUTE",
1001				pos, end - pos);
1002	}
1003	end = pos;
1004	pos = hdr.payload;
1005
1006	if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0)
1007		goto fail;
1008	if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) {
1009		asn1_oid_to_str(&oid, txt, sizeof(txt));
1010		wpa_printf(MSG_DEBUG,
1011			   "DPP: Unexpected Attribute identifier %s", txt);
1012		goto fail;
1013	}
1014
1015	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
1016		asn1_unexpected(&hdr, "DPP: Expected SET (Attribute)");
1017		goto fail;
1018	}
1019	pos = hdr.payload;
1020	end = hdr.payload + hdr.length;
1021
1022	/*
1023	 * DPPConfigurationParameters ::= SEQUENCE {
1024	 *    privacyProtectionKey      PrivateKey,
1025	 *    configurationTemplate	UTF8String,
1026	 *    connectorTemplate		UTF8String OPTIONAL}
1027	 */
1028
1029	wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters",
1030			pos, end - pos);
1031	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
1032		goto fail;
1033	if (pos < end) {
1034		wpa_hexdump_key(MSG_MSGDUMP,
1035				"DPP: Ignore additional data after DPPConfigurationParameters",
1036				pos, end - pos);
1037	}
1038	end = pos;
1039	pos = hdr.payload;
1040
1041	/*
1042	 * PrivateKey ::= OCTET STRING
1043	 *    (Contains DER encoding of ECPrivateKey)
1044	 */
1045	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1046	    !asn1_is_octetstring(&hdr)) {
1047		asn1_unexpected(&hdr, "DPP: Expected OCTETSTRING (PrivateKey)");
1048		goto fail;
1049	}
1050	wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey",
1051			hdr.payload, hdr.length);
1052	pos = hdr.payload + hdr.length;
1053	key->pp_key = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
1054	if (!key->pp_key)
1055		goto fail;
1056	if (wpa_debug_show_keys)
1057		dpp_debug_print_key("DPP: Received privacyProtectionKey",
1058				    key->pp_key);
1059
1060	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1061	    !asn1_is_utf8string(&hdr)) {
1062		asn1_unexpected(&hdr,
1063				"DPP: Expected UTF8STRING (configurationTemplate)");
1064		goto fail;
1065	}
1066	wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate",
1067			      hdr.payload, hdr.length);
1068	key->config_template = os_zalloc(hdr.length + 1);
1069	if (!key->config_template)
1070		goto fail;
1071	os_memcpy(key->config_template, hdr.payload, hdr.length);
1072
1073	pos = hdr.payload + hdr.length;
1074
1075	if (pos < end) {
1076		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1077		    !asn1_is_utf8string(&hdr)) {
1078			asn1_unexpected(&hdr,
1079					"DPP: Expected UTF8STRING (connectorTemplate)");
1080			goto fail;
1081		}
1082		wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate",
1083				      hdr.payload, hdr.length);
1084		key->connector_template = os_zalloc(hdr.length + 1);
1085		if (!key->connector_template)
1086			goto fail;
1087		os_memcpy(key->connector_template, hdr.payload, hdr.length);
1088	}
1089
1090	return key;
1091fail:
1092	wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey");
1093	dpp_free_asymmetric_key(key);
1094	return NULL;
1095}
1096
1097
1098static struct dpp_asymmetric_key *
1099dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len)
1100{
1101	struct asn1_hdr hdr;
1102	const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len;
1103	struct dpp_asymmetric_key *first = NULL, *last = NULL, *key;
1104
1105	wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage",
1106			key_pkg, key_pkg_len);
1107
1108	/*
1109	 * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage
1110	 *
1111	 * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey
1112	 */
1113	while (pos < end) {
1114		if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 ||
1115		    !(key = dpp_parse_one_asymmetric_key(hdr.payload,
1116							 hdr.length))) {
1117			dpp_free_asymmetric_key(first);
1118			return NULL;
1119		}
1120		if (!last) {
1121			first = last = key;
1122		} else {
1123			last->next = key;
1124			last = key;
1125		}
1126	}
1127
1128	return first;
1129}
1130
1131
1132int dpp_conf_resp_env_data(struct dpp_authentication *auth,
1133			   const u8 *env_data, size_t env_data_len)
1134{
1135	u8 key[DPP_MAX_HASH_LEN];
1136	size_t key_len;
1137	u8 kek[DPP_MAX_HASH_LEN];
1138	u8 cont_encr_key[DPP_MAX_HASH_LEN];
1139	size_t cont_encr_key_len;
1140	int res;
1141	u8 *key_pkg;
1142	size_t key_pkg_len;
1143	struct dpp_enveloped_data data;
1144	struct dpp_asymmetric_key *keys;
1145
1146	wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len);
1147
1148	if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0)
1149		return -1;
1150
1151	key_len = auth->curve->hash_len;
1152	/* password = HKDF-Expand(bk, "Enveloped Data Password", length) */
1153	res = dpp_hkdf_expand(key_len, auth->bk, key_len,
1154			      "Enveloped Data Password", key, key_len);
1155	if (res < 0)
1156		return -1;
1157	wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len);
1158
1159	if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000,
1160		       kek, data.pbkdf2_key_len)) {
1161		wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed");
1162		return -1;
1163	}
1164	wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2",
1165			kek, data.pbkdf2_key_len);
1166
1167	if (data.enc_key_len < AES_BLOCK_SIZE ||
1168	    data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) {
1169		wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length");
1170		return -1;
1171	}
1172	res = aes_siv_decrypt(kek, data.pbkdf2_key_len,
1173			      data.enc_key, data.enc_key_len,
1174			      0, NULL, NULL, cont_encr_key);
1175	forced_memzero(kek, data.pbkdf2_key_len);
1176	if (res < 0) {
1177		wpa_printf(MSG_DEBUG,
1178			   "DPP: AES-SIV decryption of encryptedKey failed");
1179		return -1;
1180	}
1181	cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE;
1182	wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key",
1183			cont_encr_key, cont_encr_key_len);
1184
1185	if (data.enc_cont_len < AES_BLOCK_SIZE)
1186		return -1;
1187	key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE;
1188	key_pkg = os_malloc(key_pkg_len);
1189	if (!key_pkg)
1190		return -1;
1191	res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len,
1192			      data.enc_cont, data.enc_cont_len,
1193			      0, NULL, NULL, key_pkg);
1194	forced_memzero(cont_encr_key, cont_encr_key_len);
1195	if (res < 0) {
1196		bin_clear_free(key_pkg, key_pkg_len);
1197		wpa_printf(MSG_DEBUG,
1198			   "DPP: AES-SIV decryption of encryptedContent failed");
1199		return -1;
1200	}
1201
1202	keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len);
1203	bin_clear_free(key_pkg, key_pkg_len);
1204	dpp_free_asymmetric_key(auth->conf_key_pkg);
1205	auth->conf_key_pkg = keys;
1206
1207	return keys != NULL;
1208}
1209
1210#endif /* CONFIG_DPP2 */
1211