1 /*
2  * DPP configurator backup
3  * Copyright (c) 2019-2020, The Linux Foundation
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "crypto/aes.h"
13 #include "crypto/aes_siv.h"
14 #include "tls/asn1.h"
15 #include "dpp.h"
16 #include "dpp_i.h"
17 
18 #ifdef CONFIG_DPP2
19 
dpp_free_asymmetric_key(struct dpp_asymmetric_key * key)20 void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
21 {
22           while (key) {
23                     struct dpp_asymmetric_key *next = key->next;
24 
25                     crypto_ec_key_deinit(key->csign);
26                     crypto_ec_key_deinit(key->pp_key);
27                     str_clear_free(key->config_template);
28                     str_clear_free(key->connector_template);
29                     os_free(key);
30                     key = next;
31           }
32 }
33 
34 
dpp_build_conf_params(struct dpp_configurator * conf)35 static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf)
36 {
37           struct wpabuf *buf, *priv_key = NULL;
38           size_t len;
39           /* TODO: proper template values */
40           const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
41           const char *connector_template = NULL;
42 
43           if (!conf->pp_key)
44                     return NULL;
45 
46           priv_key = crypto_ec_key_get_ecprivate_key(conf->pp_key, false);
47           if (!priv_key)
48                     return NULL;
49 
50           len = 100 + os_strlen(conf_template);
51           if (connector_template)
52                     len += os_strlen(connector_template);
53           if (priv_key)
54                     len += wpabuf_len(priv_key);
55           buf = wpabuf_alloc(len);
56           if (!buf)
57                     goto fail;
58 
59           /*
60            * DPPConfigurationParameters ::= SEQUENCE {
61            *    privacyProtectionKey      PrivateKey,
62            *    configurationTemplate   UTF8String,
63            *    connectorTemplate                 UTF8String OPTIONAL}
64            */
65 
66           /* PrivateKey ::= OCTET STRING */
67           asn1_put_octet_string(buf, priv_key);
68 
69           asn1_put_utf8string(buf, conf_template);
70           if (connector_template)
71                     asn1_put_utf8string(buf, connector_template);
72           wpabuf_clear_free(priv_key);
73           return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
74 fail:
75           wpabuf_clear_free(priv_key);
76           return NULL;
77 }
78 
79 
dpp_build_attribute(struct dpp_configurator * conf)80 static struct wpabuf * dpp_build_attribute(struct dpp_configurator *conf)
81 {
82           struct wpabuf *conf_params, *attr;
83 
84           /*
85            * aa-DPPConfigurationParameters ATTRIBUTE ::=
86            * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams }
87            *
88            * Attribute ::= SEQUENCE {
89            *    type OBJECT IDENTIFIER,
90            *    values SET SIZE(1..MAX) OF Type
91            */
92           conf_params = dpp_build_conf_params(conf);
93           conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL,
94                                           ASN1_TAG_SET);
95           if (!conf_params)
96                     return NULL;
97 
98           attr = wpabuf_alloc(100 + wpabuf_len(conf_params));
99           if (!attr) {
100                     wpabuf_clear_free(conf_params);
101                     return NULL;
102           }
103 
104           asn1_put_oid(attr, &asn1_dpp_config_params_oid);
105           wpabuf_put_buf(attr, conf_params);
106           wpabuf_clear_free(conf_params);
107 
108           return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
109 }
110 
111 
dpp_build_key_alg(const struct dpp_curve_params * curve)112 static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve)
113 {
114           const struct asn1_oid *oid;
115           struct wpabuf *params, *res;
116 
117           switch (curve->ike_group) {
118           case 19:
119                     oid = &asn1_prime256v1_oid;
120                     break;
121           case 20:
122                     oid = &asn1_secp384r1_oid;
123                     break;
124           case 21:
125                     oid = &asn1_secp521r1_oid;
126                     break;
127           case 28:
128                     oid = &asn1_brainpoolP256r1_oid;
129                     break;
130           case 29:
131                     oid = &asn1_brainpoolP384r1_oid;
132                     break;
133           case 30:
134                     oid = &asn1_brainpoolP512r1_oid;
135                     break;
136           default:
137                     return NULL;
138           }
139 
140           params = wpabuf_alloc(20);
141           if (!params)
142                     return NULL;
143           asn1_put_oid(params, oid); /* namedCurve */
144 
145           res = asn1_build_alg_id(&asn1_ec_public_key_oid, params);
146           wpabuf_free(params);
147           return res;
148 }
149 
150 
dpp_build_key_pkg(struct dpp_authentication * auth)151 static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
152 {
153           struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL;
154 
155           priv_key = crypto_ec_key_get_ecprivate_key(auth->conf->csign, false);
156           if (!priv_key)
157                     return NULL;
158 
159           alg = dpp_build_key_alg(auth->conf->curve);
160 
161           /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
162           attr = dpp_build_attribute(auth->conf);
163           attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET);
164           if (!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 
196 fail:
197           wpabuf_clear_free(attr);
198           wpabuf_clear_free(priv_key);
199           wpabuf_free(alg);
200 
201           /*
202            * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage
203            *
204            * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey
205            *
206            * OneAsymmetricKey ::= SEQUENCE
207            */
208           return asn1_encaps(asn1_encaps(key,
209                                                ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE),
210                                  ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
211 }
212 
213 
dpp_build_pbkdf2_alg_id(const struct wpabuf * salt,size_t hash_len)214 static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt,
215                                                          size_t hash_len)
216 {
217           struct wpabuf *params = NULL, *buf = NULL, *prf = NULL;
218           const struct asn1_oid *oid;
219 
220           /*
221            * PBKDF2-params ::= SEQUENCE {
222            *    salt CHOICE {
223            *       specified OCTET STRING,
224            *       otherSource AlgorithmIdentifier}
225            *    iterationCount INTEGER (1..MAX),
226            *    keyLength INTEGER (1..MAX),
227            *    prf AlgorithmIdentifier}
228            *
229            * salt is an 64 octet value, iterationCount is 1000, keyLength is based
230            * on Configurator signing key length, prf is
231            * id-hmacWithSHA{256,384,512} based on Configurator signing key.
232            */
233 
234           if (hash_len == 32)
235                     oid = &asn1_pbkdf2_hmac_sha256_oid;
236           else if (hash_len == 48)
237                     oid = &asn1_pbkdf2_hmac_sha384_oid;
238           else if (hash_len == 64)
239                     oid = &asn1_pbkdf2_hmac_sha512_oid;
240           else
241                     goto fail;
242           prf = asn1_build_alg_id(oid, NULL);
243           if (!prf)
244                     goto fail;
245           params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf));
246           if (!params)
247                     goto fail;
248           asn1_put_octet_string(params, salt); /* salt.specified */
249           asn1_put_integer(params, 1000); /* iterationCount */
250           asn1_put_integer(params, hash_len); /* keyLength */
251           wpabuf_put_buf(params, prf);
252           params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
253           if (!params)
254                     goto fail;
255           buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params);
256 fail:
257           wpabuf_free(params);
258           wpabuf_free(prf);
259           return buf;
260 }
261 
262 
263 static struct wpabuf *
dpp_build_pw_recipient_info(struct dpp_authentication * auth,size_t hash_len,const struct wpabuf * cont_enc_key)264 dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len,
265                                   const struct wpabuf *cont_enc_key)
266 {
267           struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL,
268                     *key_enc_alg = NULL, *salt;
269           u8 kek[DPP_MAX_HASH_LEN];
270           u8 key[DPP_MAX_HASH_LEN];
271           size_t key_len;
272           int res;
273 
274           salt = wpabuf_alloc(64);
275           if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0)
276                     goto fail;
277           wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt);
278 
279           key_len = auth->curve->hash_len;
280           /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */
281           res = dpp_hkdf_expand(key_len, auth->bk, key_len,
282                                     "Enveloped Data Password", key, key_len);
283           if (res < 0)
284                     goto fail;
285           wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len);
286 
287           if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000,
288                            kek, hash_len)) {
289                     wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed");
290                     goto fail;
291           }
292           wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2",
293                               kek, hash_len);
294 
295           enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE);
296           if (!enc_key ||
297               aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key),
298                                   wpabuf_len(cont_enc_key), 0, NULL, NULL,
299                                   wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0)
300                     goto fail;
301           wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key);
302 
303           /*
304            * PasswordRecipientInfo ::= SEQUENCE {
305            *    version                           CMSVersion,
306            *    keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL,
307            *    keyEncryptionAlgorithm  KeyEncryptionAlgorithmIdentifier,
308            *    encryptedKey            EncryptedKey}
309            *
310            * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the
311            * parameters contains PBKDF2-params SEQUENCE.
312            */
313 
314           key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len);
315           key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL);
316           if (!key_der_alg || !key_enc_alg)
317                     goto fail;
318           pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) +
319                                   wpabuf_len(key_enc_alg) + wpabuf_len(enc_key));
320           if (!pwri)
321                     goto fail;
322 
323           /* version = 0 */
324           asn1_put_integer(pwri, 0);
325 
326           /* [0] KeyDerivationAlgorithmIdentifier */
327           asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0,
328                          wpabuf_len(key_der_alg));
329           wpabuf_put_buf(pwri, key_der_alg);
330 
331           /* KeyEncryptionAlgorithmIdentifier */
332           wpabuf_put_buf(pwri, key_enc_alg);
333 
334           /* EncryptedKey ::= OCTET STRING */
335           asn1_put_octet_string(pwri, enc_key);
336 
337 fail:
338           wpabuf_clear_free(key_der_alg);
339           wpabuf_free(key_enc_alg);
340           wpabuf_free(enc_key);
341           wpabuf_free(salt);
342           forced_memzero(kek, sizeof(kek));
343           return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
344 }
345 
346 
347 static struct wpabuf *
dpp_build_recipient_info(struct dpp_authentication * auth,size_t hash_len,const struct wpabuf * cont_enc_key)348 dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len,
349                                const struct wpabuf *cont_enc_key)
350 {
351           struct wpabuf *pwri;
352 
353           /*
354            * RecipientInfo ::= CHOICE {
355            *    ktri                    KeyTransRecipientInfo,
356            *    kari          [1]       KeyAgreeRecipientInfo,
357            *    kekri         [2]       KEKRecipientInfo,
358            *    pwri          [3]       PasswordRecipientInfo,
359            *    ori [4]       OtherRecipientInfo}
360            *
361            * Shall always use the pwri CHOICE.
362            */
363 
364           pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key);
365           return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3);
366 }
367 
368 
369 static struct wpabuf *
dpp_build_enc_cont_info(struct dpp_authentication * auth,size_t hash_len,const struct wpabuf * cont_enc_key)370 dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len,
371                               const struct wpabuf *cont_enc_key)
372 {
373           struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL,
374                     *enc_alg;
375           const struct asn1_oid *oid;
376           size_t enc_cont_len;
377 
378           /*
379            * EncryptedContentInfo ::= SEQUENCE {
380            *    contentType                       ContentType,
381            *    contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
382            *    encryptedContent        [0] IMPLICIT        EncryptedContent OPTIONAL}
383            */
384 
385           if (hash_len == 32)
386                     oid = &asn1_aes_siv_cmac_aead_256_oid;
387           else if (hash_len == 48)
388                     oid = &asn1_aes_siv_cmac_aead_384_oid;
389           else if (hash_len == 64)
390                     oid = &asn1_aes_siv_cmac_aead_512_oid;
391           else
392                     return NULL;
393 
394           key_pkg = dpp_build_key_pkg(auth);
395           enc_alg = asn1_build_alg_id(oid, NULL);
396           if (!key_pkg || !enc_alg)
397                     goto fail;
398 
399           wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage",
400                                   key_pkg);
401 
402           enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE;
403           enc_cont = wpabuf_alloc(enc_cont_len);
404           if (!enc_cont ||
405               aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key),
406                                   wpabuf_head(key_pkg), wpabuf_len(key_pkg),
407                                   0, NULL, NULL,
408                                   wpabuf_put(enc_cont, enc_cont_len)) < 0)
409                     goto fail;
410 
411           enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) +
412                                              wpabuf_len(enc_cont));
413           if (!enc_cont_info)
414                     goto fail;
415 
416           /* ContentType ::= OBJECT IDENTIFIER */
417           asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid);
418 
419           /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
420           wpabuf_put_buf(enc_cont_info, enc_alg);
421 
422           /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
423            * EncryptedContent ::= OCTET STRING */
424           asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0,
425                          wpabuf_len(enc_cont));
426           wpabuf_put_buf(enc_cont_info, enc_cont);
427 
428 fail:
429           wpabuf_clear_free(key_pkg);
430           wpabuf_free(enc_cont);
431           wpabuf_free(enc_alg);
432           return enc_cont_info;
433 }
434 
435 
dpp_gen_random(size_t len)436 static struct wpabuf * dpp_gen_random(size_t len)
437 {
438           struct wpabuf *key;
439 
440           key = wpabuf_alloc(len);
441           if (!key || os_get_random(wpabuf_put(key, len), len) < 0) {
442                     wpabuf_free(key);
443                     key = NULL;
444           }
445           wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key);
446           return key;
447 }
448 
449 
dpp_build_enveloped_data(struct dpp_authentication * auth)450 struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth)
451 {
452           struct wpabuf *env = NULL;
453           struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL;
454           struct wpabuf *cont_enc_key = NULL;
455           size_t hash_len;
456 
457           if (!auth->conf) {
458                     wpa_printf(MSG_DEBUG,
459                                  "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData");
460                     return NULL;
461           }
462 
463           if (!auth->provision_configurator) {
464                     wpa_printf(MSG_DEBUG,
465                                  "DPP: Configurator provisioning not allowed");
466                     return NULL;
467           }
468 
469           wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData");
470 
471           hash_len = auth->conf->curve->hash_len;
472           cont_enc_key = dpp_gen_random(hash_len);
473           if (!cont_enc_key)
474                     goto fail;
475           recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key);
476           enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key);
477           if (!recipient_info || !enc_cont_info)
478                     goto fail;
479 
480           env = wpabuf_alloc(wpabuf_len(recipient_info) +
481                                  wpabuf_len(enc_cont_info) +
482                                  100);
483           if (!env)
484                     goto fail;
485 
486           /*
487            * DPPEnvelopedData ::= EnvelopedData
488            *
489            * EnvelopedData ::= SEQUENCE {
490            *    version                           CMSVersion,
491            *    originatorInfo          [0]       IMPLICIT OriginatorInfo OPTIONAL,
492            *    recipientInfos                    RecipientInfos,
493            *    encryptedContentInfo    EncryptedContentInfo,
494            *    unprotectedAttrs  [1] IMPLICIT    UnprotectedAttributes OPTIONAL}
495            *
496            * For DPP, version is 3, both originatorInfo and
497            * unprotectedAttrs are omitted, and recipientInfos contains a single
498            * RecipientInfo.
499            */
500 
501           /* EnvelopedData.version = 3 */
502           asn1_put_integer(env, 3);
503 
504           /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */
505           asn1_put_set(env, recipient_info);
506 
507           /* EncryptedContentInfo ::= SEQUENCE */
508           asn1_put_sequence(env, enc_cont_info);
509 
510           env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
511           wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env);
512 out:
513           wpabuf_clear_free(cont_enc_key);
514           wpabuf_clear_free(recipient_info);
515           wpabuf_free(enc_cont_info);
516           return env;
517 fail:
518           wpabuf_free(env);
519           env = NULL;
520           goto out;
521 }
522 
523 
524 struct 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 
dpp_parse_recipient_infos(const u8 * pos,size_t len,struct dpp_enveloped_data * data)535 static 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 
dpp_parse_encrypted_content_info(const u8 * pos,const u8 * end,struct dpp_enveloped_data * data)728 static 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 
dpp_parse_enveloped_data(const u8 * env_data,size_t env_data_len,struct dpp_enveloped_data * data)799 static 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 
856 static struct dpp_asymmetric_key *
dpp_parse_one_asymmetric_key(const u8 * buf,size_t len)857 dpp_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;
1091 fail:
1092           wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey");
1093           dpp_free_asymmetric_key(key);
1094           return NULL;
1095 }
1096 
1097 
1098 static struct dpp_asymmetric_key *
dpp_parse_dpp_asymmetric_key_package(const u8 * key_pkg,size_t key_pkg_len)1099 dpp_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 
dpp_conf_resp_env_data(struct dpp_authentication * auth,const u8 * env_data,size_t env_data_len)1132 int 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