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