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