]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/common/dpp.c
DPP: Authentication exchange
[thirdparty/hostap.git] / src / common / dpp.c
CommitLineData
be27e185
JM
1/*
2 * DPP functionality shared between hostapd and wpa_supplicant
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
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/err.h>
11
12#include "utils/common.h"
13#include "utils/base64.h"
14#include "common/ieee802_11_common.h"
30d27b04
JM
15#include "common/ieee802_11_defs.h"
16#include "common/wpa_ctrl.h"
be27e185 17#include "crypto/crypto.h"
30d27b04
JM
18#include "crypto/random.h"
19#include "crypto/aes.h"
20#include "crypto/aes_siv.h"
21#include "crypto/sha384.h"
22#include "crypto/sha512.h"
be27e185
JM
23#include "dpp.h"
24
25
26static const struct dpp_curve_params dpp_curves[] = {
27 /* The mandatory to support and the default NIST P-256 curve needs to
28 * be the first entry on this list. */
29 { "prime256v1", 32, 32, 16, 32, "P-256" },
30 { "secp384r1", 48, 48, 24, 48, "P-384" },
31 { "secp521r1", 64, 64, 32, 66, "P-521" },
32 { "brainpoolP256r1", 32, 32, 16, 32, "BP-256R1" },
33 { "brainpoolP384r1", 48, 48, 24, 48, "BP-384R1" },
34 { "brainpoolP512r1", 64, 64, 32, 64, "BP-512R1" },
35 { NULL, 0, 0, 0, 0, NULL }
36};
37
38
30d27b04
JM
39static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
40{
41 int len, res;
42 EC_KEY *eckey;
43 struct wpabuf *buf;
44 unsigned char *pos;
45
46 eckey = EVP_PKEY_get1_EC_KEY(pkey);
47 if (!eckey)
48 return NULL;
49 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
50 len = i2o_ECPublicKey(eckey, NULL);
51 if (len <= 0) {
52 wpa_printf(MSG_ERROR,
53 "DDP: Failed to determine public key encoding length");
54 EC_KEY_free(eckey);
55 return NULL;
56 }
57
58 buf = wpabuf_alloc(len);
59 if (!buf) {
60 EC_KEY_free(eckey);
61 return NULL;
62 }
63
64 pos = wpabuf_put(buf, len);
65 res = i2o_ECPublicKey(eckey, &pos);
66 EC_KEY_free(eckey);
67 if (res != len) {
68 wpa_printf(MSG_ERROR,
69 "DDP: Failed to encode public key (res=%d/%d)",
70 res, len);
71 wpabuf_free(buf);
72 return NULL;
73 }
74
75 if (!prefix) {
76 /* Remove 0x04 prefix to match DPP definition */
77 pos = wpabuf_mhead(buf);
78 os_memmove(pos, pos + 1, len - 1);
79 buf->used--;
80 }
81
82 return buf;
83}
84
85
86static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
87 const u8 *buf_x, const u8 *buf_y,
88 size_t len)
89{
90 EC_KEY *eckey = NULL;
91 BN_CTX *ctx;
92 EC_POINT *point = NULL;
93 BIGNUM *x = NULL, *y = NULL;
94 EVP_PKEY *pkey = NULL;
95
96 ctx = BN_CTX_new();
97 if (!ctx) {
98 wpa_printf(MSG_ERROR, "DPP: Out of memory");
99 return NULL;
100 }
101
102 point = EC_POINT_new(group);
103 x = BN_bin2bn(buf_x, len, NULL);
104 y = BN_bin2bn(buf_y, len, NULL);
105 if (!point || !x || !y) {
106 wpa_printf(MSG_ERROR, "DPP: Out of memory");
107 goto fail;
108 }
109
110 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
111 wpa_printf(MSG_ERROR,
112 "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
113 ERR_error_string(ERR_get_error(), NULL));
114 goto fail;
115 }
116
117 if (!EC_POINT_is_on_curve(group, point, ctx) ||
118 EC_POINT_is_at_infinity(group, point)) {
119 wpa_printf(MSG_ERROR, "DPP: Invalid point");
120 goto fail;
121 }
122
123 eckey = EC_KEY_new();
124 if (!eckey ||
125 EC_KEY_set_group(eckey, group) != 1 ||
126 EC_KEY_set_public_key(eckey, point) != 1) {
127 wpa_printf(MSG_ERROR,
128 "DPP: Failed to set EC_KEY: %s",
129 ERR_error_string(ERR_get_error(), NULL));
130 goto fail;
131 }
132 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
133
134 pkey = EVP_PKEY_new();
135 if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
136 wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
137 goto fail;
138 }
139
140out:
141 BN_free(x);
142 BN_free(y);
143 EC_KEY_free(eckey);
144 EC_POINT_free(point);
145 BN_CTX_free(ctx);
146 return pkey;
147fail:
148 EVP_PKEY_free(pkey);
149 pkey = NULL;
150 goto out;
151}
152
153
154static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key,
155 const u8 *buf, size_t len)
156{
157 EC_KEY *eckey;
158 const EC_GROUP *group;
159 EVP_PKEY *pkey = NULL;
160
161 if (len & 1)
162 return NULL;
163
164 eckey = EVP_PKEY_get1_EC_KEY(group_key);
165 if (!eckey) {
166 wpa_printf(MSG_ERROR,
167 "DPP: Could not get EC_KEY from group_key");
168 return NULL;
169 }
170
171 group = EC_KEY_get0_group(eckey);
172 if (group)
173 pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
174 len / 2);
175 else
176 wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
177
178 EC_KEY_free(eckey);
179 return pkey;
180}
181
182
183struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
184 size_t len)
185{
186 struct wpabuf *msg;
187
188 msg = wpabuf_alloc(7 + len);
189 if (!msg)
190 return NULL;
191 wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
192 wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
193 wpabuf_put_be24(msg, OUI_WFA);
194 wpabuf_put_u8(msg, DPP_OUI_TYPE);
195 wpabuf_put_u8(msg, type);
196 return msg;
197}
198
199
200const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
201{
202 u16 id, alen;
203 const u8 *pos = buf, *end = buf + len;
204
205 while (end - pos >= 4) {
206 id = WPA_GET_LE16(pos);
207 pos += 2;
208 alen = WPA_GET_LE16(pos);
209 pos += 2;
210 if (alen > end - pos)
211 return NULL;
212 if (id == req_id) {
213 *ret_len = alen;
214 return pos;
215 }
216 pos += alen;
217 }
218
219 return NULL;
220}
221
222
223int dpp_check_attrs(const u8 *buf, size_t len)
224{
225 const u8 *pos, *end;
226
227 pos = buf;
228 end = buf + len;
229 while (end - pos >= 4) {
230 u16 id, alen;
231
232 id = WPA_GET_LE16(pos);
233 pos += 2;
234 alen = WPA_GET_LE16(pos);
235 pos += 2;
236 wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
237 id, alen);
238 if (alen > end - pos) {
239 wpa_printf(MSG_DEBUG,
240 "DPP: Truncated message - not enough room for the attribute - dropped");
241 return -1;
242 }
243 pos += alen;
244 }
245
246 if (end != pos) {
247 wpa_printf(MSG_DEBUG,
248 "DPP: Unexpected octets (%d) after the last attribute",
249 (int) (end - pos));
250 return -1;
251 }
252
253 return 0;
254}
255
256
be27e185
JM
257void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
258{
259 if (!info)
260 return;
261 os_free(info->uri);
262 os_free(info->info);
263 EVP_PKEY_free(info->pubkey);
264 os_free(info);
265}
266
267
268static int dpp_uri_valid_info(const char *info)
269{
270 while (*info) {
271 unsigned char val = *info++;
272
273 if (val < 0x20 || val > 0x7e || val == 0x3b)
274 return 0;
275 }
276
277 return 1;
278}
279
280
281static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
282{
283 bi->uri = os_strdup(uri);
284 return bi->uri ? 0 : -1;
285}
286
287
288int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
289 const char *chan_list)
290{
291 const char *pos = chan_list;
292 int opclass, channel, freq;
293
294 while (pos && *pos && *pos != ';') {
295 opclass = atoi(pos);
296 if (opclass <= 0)
297 goto fail;
298 pos = os_strchr(pos, '/');
299 if (!pos)
300 goto fail;
301 pos++;
302 channel = atoi(pos);
303 if (channel <= 0)
304 goto fail;
305 while (*pos >= '0' && *pos <= '9')
306 pos++;
307 freq = ieee80211_chan_to_freq(NULL, opclass, channel);
308 wpa_printf(MSG_DEBUG,
309 "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
310 opclass, channel, freq);
311 if (freq < 0) {
312 wpa_printf(MSG_DEBUG,
313 "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
314 opclass, channel);
315 } else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
316 wpa_printf(MSG_DEBUG,
317 "DPP: Too many channels in URI channel-list - ignore list");
318 bi->num_freq = 0;
319 break;
320 } else {
321 bi->freq[bi->num_freq++] = freq;
322 }
323
324 if (*pos == ';' || *pos == '\0')
325 break;
326 if (*pos != ',')
327 goto fail;
328 pos++;
329 }
330
331 return 0;
332fail:
333 wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
334 return -1;
335}
336
337
338int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
339{
340 if (!mac)
341 return 0;
342
343 if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
344 wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
345 return -1;
346 }
347
348 wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
349
350 return 0;
351}
352
353
354int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
355{
356 const char *end;
357
358 if (!info)
359 return 0;
360
361 end = os_strchr(info, ';');
362 if (!end)
363 end = info + os_strlen(info);
364 bi->info = os_malloc(end - info + 1);
365 if (!bi->info)
366 return -1;
367 os_memcpy(bi->info, info, end - info);
368 bi->info[end - info] = '\0';
369 wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
370 if (!dpp_uri_valid_info(bi->info)) {
371 wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
372 return -1;
373 }
374
375 return 0;
376}
377
378
379static const struct dpp_curve_params *
380dpp_get_curve_oid(const ASN1_OBJECT *poid)
381{
382 ASN1_OBJECT *oid;
383 int i;
384
385 for (i = 0; dpp_curves[i].name; i++) {
386 oid = OBJ_txt2obj(dpp_curves[i].name, 0);
387 if (oid && OBJ_cmp(poid, oid) == 0)
388 return &dpp_curves[i];
389 }
390 return NULL;
391}
392
393
394static const struct dpp_curve_params * dpp_get_curve_nid(int nid)
395{
396 int i, tmp;
397
398 if (!nid)
399 return NULL;
400 for (i = 0; dpp_curves[i].name; i++) {
401 tmp = OBJ_txt2nid(dpp_curves[i].name);
402 if (tmp == nid)
403 return &dpp_curves[i];
404 }
405 return NULL;
406}
407
408
409static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
410{
411 const char *end;
412 u8 *data;
413 size_t data_len;
414 EVP_PKEY *pkey;
415 const unsigned char *p;
416 int res;
417 X509_PUBKEY *pub = NULL;
418 ASN1_OBJECT *ppkalg;
419 const unsigned char *pk;
420 int ppklen;
421 X509_ALGOR *pa;
422 ASN1_OBJECT *pa_oid;
423 const void *pval;
424 int ptype;
425 const ASN1_OBJECT *poid;
426 char buf[100];
427
428 end = os_strchr(info, ';');
429 if (!end)
430 return -1;
431
432 data = base64_decode((const unsigned char *) info, end - info,
433 &data_len);
434 if (!data) {
435 wpa_printf(MSG_DEBUG,
436 "DPP: Invalid base64 encoding on URI public-key");
437 return -1;
438 }
439 wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
440 data, data_len);
441
442 if (sha256_vector(1, (const u8 **) &data, &data_len,
443 bi->pubkey_hash) < 0) {
444 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
445 return -1;
446 }
30d27b04
JM
447 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
448 bi->pubkey_hash, SHA256_MAC_LEN);
be27e185
JM
449
450 /* DER encoded ASN.1 SubjectPublicKeyInfo
451 *
452 * SubjectPublicKeyInfo ::= SEQUENCE {
453 * algorithm AlgorithmIdentifier,
454 * subjectPublicKey BIT STRING }
455 *
456 * AlgorithmIdentifier ::= SEQUENCE {
457 * algorithm OBJECT IDENTIFIER,
458 * parameters ANY DEFINED BY algorithm OPTIONAL }
459 *
460 * subjectPublicKey = compressed format public key per ANSI X9.63
461 * algorithm = ecPublicKey (1.2.840.10045.2.1)
462 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
463 * prime256v1 (1.2.840.10045.3.1.7)
464 */
465
466 p = data;
467 pkey = d2i_PUBKEY(NULL, &p, data_len);
468 os_free(data);
469
470 if (!pkey) {
471 wpa_printf(MSG_DEBUG,
472 "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
473 return -1;
474 }
475
476 if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
477 wpa_printf(MSG_DEBUG,
478 "DPP: SubjectPublicKeyInfo does not describe an EC key");
479 EVP_PKEY_free(pkey);
480 return -1;
481 }
482
483 res = X509_PUBKEY_set(&pub, pkey);
484 if (res != 1) {
485 wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
486 goto fail;
487 }
488
489 res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
490 if (res != 1) {
491 wpa_printf(MSG_DEBUG,
492 "DPP: Could not extract SubjectPublicKeyInfo parameters");
493 goto fail;
494 }
495 res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
496 if (res < 0 || (size_t) res >= sizeof(buf)) {
497 wpa_printf(MSG_DEBUG,
498 "DPP: Could not extract SubjectPublicKeyInfo algorithm");
499 goto fail;
500 }
501 wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
502 if (os_strcmp(buf, "id-ecPublicKey") != 0) {
503 wpa_printf(MSG_DEBUG,
504 "DPP: Unsupported SubjectPublicKeyInfo algorithm");
505 goto fail;
506 }
507
508 X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
509 if (ptype != V_ASN1_OBJECT) {
510 wpa_printf(MSG_DEBUG,
511 "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
512 goto fail;
513 }
514 poid = pval;
515 res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
516 if (res < 0 || (size_t) res >= sizeof(buf)) {
517 wpa_printf(MSG_DEBUG,
518 "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
519 goto fail;
520 }
521 wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
522 bi->curve = dpp_get_curve_oid(poid);
523 if (!bi->curve) {
524 wpa_printf(MSG_DEBUG,
525 "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
526 buf);
527 goto fail;
528 }
529
530 wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
531
532 X509_PUBKEY_free(pub);
533 bi->pubkey = pkey;
534 return 0;
535fail:
536 X509_PUBKEY_free(pub);
537 EVP_PKEY_free(pkey);
538 return -1;
539}
540
541
542static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
543{
544 const char *pos = uri;
545 const char *end;
546 const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
547 struct dpp_bootstrap_info *bi;
548
549 wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
550
551 if (os_strncmp(pos, "DPP:", 4) != 0) {
552 wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
553 return NULL;
554 }
555 pos += 4;
556
557 for (;;) {
558 end = os_strchr(pos, ';');
559 if (!end)
560 break;
561
562 if (end == pos) {
563 /* Handle terminating ";;" and ignore unexpected ";"
564 * for parsing robustness. */
565 pos++;
566 continue;
567 }
568
569 if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
570 chan_list = pos + 2;
571 else if (pos[0] == 'M' && pos[1] == ':' && !mac)
572 mac = pos + 2;
573 else if (pos[0] == 'I' && pos[1] == ':' && !info)
574 info = pos + 2;
575 else if (pos[0] == 'K' && pos[1] == ':' && !pk)
576 pk = pos + 2;
577 else
578 wpa_hexdump_ascii(MSG_DEBUG,
579 "DPP: Ignore unrecognized URI parameter",
580 pos, end - pos);
581 pos = end + 1;
582 }
583
584 if (!pk) {
585 wpa_printf(MSG_INFO, "DPP: URI missing public-key");
586 return NULL;
587 }
588
589 bi = os_zalloc(sizeof(*bi));
590 if (!bi)
591 return NULL;
592
593 if (dpp_clone_uri(bi, uri) < 0 ||
594 dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
595 dpp_parse_uri_mac(bi, mac) < 0 ||
596 dpp_parse_uri_info(bi, info) < 0 ||
597 dpp_parse_uri_pk(bi, pk) < 0) {
598 dpp_bootstrap_info_free(bi);
599 bi = NULL;
600 }
601
602 return bi;
603}
604
605
606struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
607{
608 struct dpp_bootstrap_info *bi;
609
610 bi = dpp_parse_uri(uri);
611 if (bi)
612 bi->type = DPP_BOOTSTRAP_QR_CODE;
613 return bi;
614}
615
616
617static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
618{
619 EC_KEY *eckey;
620 BIO *out;
621 size_t rlen;
622 char *txt;
623 int res;
624 unsigned char *der = NULL;
625 int der_len;
626
627 out = BIO_new(BIO_s_mem());
628 if (!out)
629 return;
630
631 EVP_PKEY_print_private(out, key, 0, NULL);
632 rlen = BIO_ctrl_pending(out);
633 txt = os_malloc(rlen + 1);
634 if (txt) {
635 res = BIO_read(out, txt, rlen);
636 if (res > 0) {
637 txt[res] = '\0';
638 wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
639 }
640 os_free(txt);
641 }
642 BIO_free(out);
643
644 eckey = EVP_PKEY_get1_EC_KEY(key);
645 if (!eckey)
646 return;
647
648 der_len = i2d_ECPrivateKey(eckey, &der);
649 if (der_len > 0)
650 wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
651 OPENSSL_free(der);
652 if (der_len <= 0) {
653 der = NULL;
654 der_len = i2d_EC_PUBKEY(eckey, &der);
655 if (der_len > 0)
656 wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
657 OPENSSL_free(der);
658 }
659
660 EC_KEY_free(eckey);
661}
662
663
664static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
665{
666#ifdef OPENSSL_IS_BORINGSSL
667 EVP_PKEY_CTX *kctx = NULL;
668 const EC_GROUP *group;
669 EC_KEY *ec_params;
670#else
671 EVP_PKEY_CTX *pctx, *kctx = NULL;
672#endif
673 EVP_PKEY *params = NULL, *key = NULL;
674 int nid;
675
676 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
677
678 nid = OBJ_txt2nid(curve->name);
679 if (nid == NID_undef) {
680 wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
681 return NULL;
682 }
683#ifdef OPENSSL_IS_BORINGSSL
684 group = EC_GROUP_new_by_curve_name(nid);
685 ec_params = EC_KEY_new();
686 if (!ec_params || EC_KEY_set_group(ec_params, group) != 1) {
687 wpa_printf(MSG_ERROR,
688 "DPP: Failed to generate EC_KEY parameters");
689 goto fail;
690 }
691 EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
692 params = EVP_PKEY_new();
693 if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
694 wpa_printf(MSG_ERROR,
695 "DPP: Failed to generate EVP_PKEY parameters");
696 goto fail;
697 }
698#else
699 pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
700 if (!pctx ||
701 EVP_PKEY_paramgen_init(pctx) != 1 ||
702 EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1 ||
703 EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE) != 1 ||
704 EVP_PKEY_paramgen(pctx, &params) != 1) {
705 wpa_printf(MSG_ERROR,
706 "DPP: Failed to generate EVP_PKEY parameters");
707 EVP_PKEY_CTX_free(pctx);
708 goto fail;
709 }
710 EVP_PKEY_CTX_free(pctx);
711#endif
712
713 kctx = EVP_PKEY_CTX_new(params, NULL);
714 if (!kctx ||
715 EVP_PKEY_keygen_init(kctx) != 1 ||
716 EVP_PKEY_keygen(kctx, &key) != 1) {
717 wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
718 goto fail;
719 }
720
721 if (wpa_debug_show_keys)
722 dpp_debug_print_key("Own generated key", key);
723
724 EVP_PKEY_free(params);
725 EVP_PKEY_CTX_free(kctx);
726 return key;
727fail:
728 EVP_PKEY_CTX_free(kctx);
729 EVP_PKEY_free(params);
730 return NULL;
731}
732
733
734static const struct dpp_curve_params *
735dpp_get_curve_name(const char *name)
736{
737 int i;
738
739 for (i = 0; dpp_curves[i].name; i++) {
740 if (os_strcmp(name, dpp_curves[i].name) == 0 ||
741 (dpp_curves[i].jwk_crv &&
742 os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
743 return &dpp_curves[i];
744 }
745 return NULL;
746}
747
748
749static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
750 const u8 *privkey, size_t privkey_len)
751{
752 EVP_PKEY *pkey;
753 EC_KEY *eckey;
754 const EC_GROUP *group;
755 int nid;
756
757 pkey = EVP_PKEY_new();
758 if (!pkey)
759 return NULL;
760 eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
761 if (!eckey) {
762 wpa_printf(MSG_INFO,
763 "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
764 ERR_error_string(ERR_get_error(), NULL));
765 EVP_PKEY_free(pkey);
766 return NULL;
767 }
768 group = EC_KEY_get0_group(eckey);
769 if (!group) {
770 EC_KEY_free(eckey);
771 EVP_PKEY_free(pkey);
772 return NULL;
773 }
774 nid = EC_GROUP_get_curve_name(group);
775 *curve = dpp_get_curve_nid(nid);
776 if (!*curve) {
777 wpa_printf(MSG_INFO,
778 "DPP: Unsupported curve (nid=%d) in pre-assigned key",
779 nid);
780 EC_KEY_free(eckey);
781 EVP_PKEY_free(pkey);
782 return NULL;
783 }
784
785 if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
786 EC_KEY_free(eckey);
787 EVP_PKEY_free(pkey);
788 return NULL;
789 }
790 return pkey;
791}
792
793
794char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
795 const u8 *privkey, size_t privkey_len)
796{
797 unsigned char *base64 = NULL;
798 char *pos, *end;
799 size_t len;
800 unsigned char *der = NULL;
801 int der_len;
802 EC_KEY *eckey;
803
804 if (!curve) {
805 bi->curve = &dpp_curves[0];
806 } else {
807 bi->curve = dpp_get_curve_name(curve);
808 if (!bi->curve) {
809 wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
810 curve);
811 return NULL;
812 }
813 }
814 if (privkey)
815 bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
816 else
817 bi->pubkey = dpp_gen_keypair(bi->curve);
818 if (!bi->pubkey)
819 goto fail;
820 bi->own = 1;
821
822 /* Need to get the compressed form of the public key through EC_KEY, so
823 * cannot use the simpler i2d_PUBKEY() here. */
824 eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
825 if (!eckey)
826 goto fail;
827 EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
828 der_len = i2d_EC_PUBKEY(eckey, &der);
829 EC_KEY_free(eckey);
830 if (der_len <= 0) {
831 wpa_printf(MSG_ERROR,
832 "DDP: Failed to build DER encoded public key");
833 goto fail;
834 }
835
836 len = der_len;
837 if (sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash) < 0) {
838 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
839 goto fail;
840 }
841
842 base64 = base64_encode(der, der_len, &len);
843 OPENSSL_free(der);
844 if (!base64)
845 goto fail;
846 pos = (char *) base64;
847 end = pos + len;
848 for (;;) {
849 pos = os_strchr(pos, '\n');
850 if (!pos)
851 break;
852 os_memmove(pos, pos + 1, end - pos);
853 }
854 return (char *) base64;
855fail:
856 os_free(base64);
857 OPENSSL_free(der);
858 return NULL;
859}
30d27b04
JM
860
861
862static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
863 unsigned int hash_len)
864{
865 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
866 const char *info = "first intermediate key";
867 int res = -1;
868
869 /* k1 = HKDF(<>, "first intermediate key", M.x) */
870
871 /* HKDF-Extract(<>, M.x) */
872 os_memset(salt, 0, hash_len);
873 if (hash_len == 32) {
874 if (hmac_sha256(salt, SHA256_MAC_LEN, Mx, Mx_len, prk) < 0)
875 return -1;
876 } else if (hash_len == 48) {
877 if (hmac_sha384(salt, SHA384_MAC_LEN, Mx, Mx_len, prk) < 0)
878 return -1;
879 } else if (hash_len == 64) {
880 if (hmac_sha512(salt, SHA512_MAC_LEN, Mx, Mx_len, prk) < 0)
881 return -1;
882 } else {
883 return -1;
884 }
885 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
886 prk, hash_len);
887
888 /* HKDF-Expand(PRK, info, L) */
889 if (hash_len == 32)
890 res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL,
891 (const u8 *) info, os_strlen(info),
892 k1, SHA256_MAC_LEN);
893 else if (hash_len == 48)
894 res = hmac_sha384_kdf(prk, SHA384_MAC_LEN, NULL,
895 (const u8 *) info, os_strlen(info),
896 k1, SHA384_MAC_LEN);
897 else if (hash_len == 64)
898 res = hmac_sha512_kdf(prk, SHA512_MAC_LEN, NULL,
899 (const u8 *) info, os_strlen(info),
900 k1, SHA512_MAC_LEN);
901 os_memset(prk, 0, hash_len);
902 if (res < 0)
903 return -1;
904
905 wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
906 k1, hash_len);
907 return 0;
908}
909
910
911static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
912 unsigned int hash_len)
913{
914 u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
915 const char *info = "second intermediate key";
916 int res;
917
918 /* k2 = HKDF(<>, "second intermediate key", N.x) */
919
920 /* HKDF-Extract(<>, N.x) */
921 os_memset(salt, 0, hash_len);
922 if (hash_len == 32)
923 res = hmac_sha256(salt, SHA256_MAC_LEN, Nx, Nx_len, prk);
924 else if (hash_len == 48)
925 res = hmac_sha384(salt, SHA384_MAC_LEN, Nx, Nx_len, prk);
926 else if (hash_len == 64)
927 res = hmac_sha512(salt, SHA512_MAC_LEN, Nx, Nx_len, prk);
928 else
929 res = -1;
930 if (res < 0)
931 return -1;
932 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
933 prk, hash_len);
934
935 /* HKDF-Expand(PRK, info, L) */
936 if (hash_len == 32)
937 res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL,
938 (const u8 *) info, os_strlen(info),
939 k2, SHA256_MAC_LEN);
940 else if (hash_len == 48)
941 res = hmac_sha384_kdf(prk, SHA384_MAC_LEN, NULL,
942 (const u8 *) info, os_strlen(info),
943 k2, SHA384_MAC_LEN);
944 else if (hash_len == 64)
945 res = hmac_sha512_kdf(prk, SHA512_MAC_LEN, NULL,
946 (const u8 *) info, os_strlen(info),
947 k2, SHA512_MAC_LEN);
948 os_memset(prk, 0, hash_len);
949 if (res < 0)
950 return -1;
951
952 wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
953 k2, hash_len);
954 return 0;
955}
956
957
958static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
959 unsigned int hash_len)
960{
961 size_t nonce_len;
962 u8 nonces[2 * DPP_MAX_NONCE_LEN];
963 const char *info_ke = "DPP Key";
964 u8 prk[DPP_MAX_HASH_LEN];
965 int res;
966 const u8 *addr[3];
967 size_t len[3];
968 size_t num_elem = 0;
969
970 /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
971
972 /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
973 nonce_len = auth->curve->nonce_len;
974 os_memcpy(nonces, auth->i_nonce, nonce_len);
975 os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
976 addr[num_elem] = auth->Mx;
977 len[num_elem] = auth->secret_len;
978 num_elem++;
979 addr[num_elem] = auth->Nx;
980 len[num_elem] = auth->secret_len;
981 num_elem++;
982 if (auth->peer_bi && auth->own_bi) {
983 addr[num_elem] = auth->Lx;
984 len[num_elem] = auth->secret_len;
985 num_elem++;
986 }
987 if (hash_len == 32)
988 res = hmac_sha256_vector(nonces, 2 * nonce_len,
989 num_elem, addr, len, prk);
990 else if (hash_len == 48)
991 res = hmac_sha384_vector(nonces, 2 * nonce_len,
992 num_elem, addr, len, prk);
993 else if (hash_len == 64)
994 res = hmac_sha512_vector(nonces, 2 * nonce_len,
995 num_elem, addr, len, prk);
996 else
997 res = -1;
998 if (res < 0)
999 return -1;
1000 wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1001 prk, hash_len);
1002
1003 /* HKDF-Expand(PRK, info, L) */
1004 if (hash_len == 32)
1005 res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL,
1006 (const u8 *) info_ke, os_strlen(info_ke),
1007 ke, SHA256_MAC_LEN);
1008 else if (hash_len == 48)
1009 res = hmac_sha384_kdf(prk, SHA384_MAC_LEN, NULL,
1010 (const u8 *) info_ke, os_strlen(info_ke),
1011 ke, SHA384_MAC_LEN);
1012 else if (hash_len == 64)
1013 res = hmac_sha512_kdf(prk, SHA512_MAC_LEN, NULL,
1014 (const u8 *) info_ke, os_strlen(info_ke),
1015 ke, SHA512_MAC_LEN);
1016 os_memset(prk, 0, hash_len);
1017 if (res < 0)
1018 return -1;
1019
1020 wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
1021 ke, hash_len);
1022 return 0;
1023}
1024
1025
1026struct dpp_authentication * dpp_auth_init(void *msg_ctx,
1027 struct dpp_bootstrap_info *peer_bi,
1028 struct dpp_bootstrap_info *own_bi,
1029 int configurator)
1030{
1031 struct dpp_authentication *auth;
1032 size_t nonce_len;
1033 EVP_PKEY_CTX *ctx = NULL;
1034 size_t secret_len;
1035 struct wpabuf *msg, *pi = NULL;
1036 u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
1037 u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
1038 u8 *pos;
1039 const u8 *addr[1];
1040 size_t len[1], siv_len;
1041
1042 auth = os_zalloc(sizeof(*auth));
1043 if (!auth)
1044 return NULL;
1045 auth->msg_ctx = msg_ctx;
1046 auth->initiator = 1;
1047 auth->configurator = configurator;
1048 auth->peer_bi = peer_bi;
1049 auth->own_bi = own_bi;
1050 auth->curve = peer_bi->curve;
1051
1052 nonce_len = auth->curve->nonce_len;
1053 if (random_get_bytes(auth->i_nonce, nonce_len)) {
1054 wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
1055 goto fail;
1056 }
1057 wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
1058
1059 auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1060 if (!auth->own_protocol_key)
1061 goto fail;
1062
1063 pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1064 if (!pi)
1065 goto fail;
1066
1067 /* ECDH: M = pI * BR */
1068 ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
1069 if (!ctx ||
1070 EVP_PKEY_derive_init(ctx) != 1 ||
1071 EVP_PKEY_derive_set_peer(ctx, auth->peer_bi->pubkey) != 1 ||
1072 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
1073 secret_len > DPP_MAX_SHARED_SECRET_LEN ||
1074 EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
1075 wpa_printf(MSG_ERROR,
1076 "DPP: Failed to derive ECDH shared secret: %s",
1077 ERR_error_string(ERR_get_error(), NULL));
1078 goto fail;
1079 }
1080 auth->secret_len = secret_len;
1081 EVP_PKEY_CTX_free(ctx);
1082 ctx = NULL;
1083
1084 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
1085 auth->Mx, auth->secret_len);
1086
1087 if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
1088 auth->curve->hash_len) < 0)
1089 goto fail;
1090
1091 /* Build DPP Authentication Request frame attributes */
1092 msg = wpabuf_alloc(2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) +
1093 4 + sizeof(wrapped_data));
1094 if (!msg)
1095 goto fail;
1096 auth->req_attr = msg;
1097
1098 /* Responder Bootstrapping Key Hash */
1099 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1100 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1101 wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
1102
1103 /* Initiator Bootstrapping Key Hash */
1104 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1105 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1106 if (auth->own_bi)
1107 wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
1108 else
1109 os_memset(wpabuf_put(msg, SHA256_MAC_LEN), 0, SHA256_MAC_LEN);
1110
1111 /* Initiator Protocol Key */
1112 wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
1113 wpabuf_put_le16(msg, wpabuf_len(pi));
1114 wpabuf_put_buf(msg, pi);
1115 wpabuf_free(pi);
1116 pi = NULL;
1117
1118 /* Wrapped data ({I-nonce, I-capabilities}k1) */
1119 pos = clear;
1120 /* I-nonce */
1121 WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1122 pos += 2;
1123 WPA_PUT_LE16(pos, nonce_len);
1124 pos += 2;
1125 os_memcpy(pos, auth->i_nonce, nonce_len);
1126 pos += nonce_len;
1127 /* I-capabilities */
1128 WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
1129 pos += 2;
1130 WPA_PUT_LE16(pos, 1);
1131 pos += 2;
1132 auth->i_capab = configurator ? DPP_CAPAB_CONFIGURATOR :
1133 DPP_CAPAB_ENROLLEE;
1134 *pos++ = auth->i_capab;
1135
1136 addr[0] = wpabuf_head(msg);
1137 len[0] = wpabuf_len(msg);
1138 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
1139 siv_len = pos - clear;
1140 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1141 if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
1142 1, addr, len, wrapped_data) < 0)
1143 goto fail;
1144 siv_len += AES_BLOCK_SIZE;
1145 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1146 wrapped_data, siv_len);
1147
1148 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1149 wpabuf_put_le16(msg, siv_len);
1150 wpabuf_put_data(msg, wrapped_data, siv_len);
1151
1152 wpa_hexdump_buf(MSG_DEBUG,
1153 "DPP: Authentication Request frame attributes", msg);
1154
1155 return auth;
1156fail:
1157 wpabuf_free(pi);
1158 EVP_PKEY_CTX_free(ctx);
1159 dpp_auth_deinit(auth);
1160 return NULL;
1161}
1162
1163
1164static void dpp_auth_success(struct dpp_authentication *auth)
1165{
1166 wpa_printf(MSG_DEBUG,
1167 "DPP: Authentication success - clear temporary keys");
1168 os_memset(auth->Mx, 0, sizeof(auth->Mx));
1169 os_memset(auth->Nx, 0, sizeof(auth->Nx));
1170 os_memset(auth->Lx, 0, sizeof(auth->Lx));
1171 os_memset(auth->k1, 0, sizeof(auth->k1));
1172 os_memset(auth->k2, 0, sizeof(auth->k2));
1173
1174 auth->auth_success = 1;
1175}
1176
1177
1178static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
1179{
1180 struct wpabuf *pix, *prx, *bix, *brx;
1181 const u8 *addr[7];
1182 size_t len[7];
1183 size_t i, num_elem = 0;
1184 size_t nonce_len;
1185 u8 zero = 0;
1186 int res = -1;
1187
1188 /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1189 nonce_len = auth->curve->nonce_len;
1190
1191 if (auth->initiator) {
1192 pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1193 prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1194 if (auth->own_bi)
1195 bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1196 else
1197 bix = NULL;
1198 brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1199 } else {
1200 pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1201 prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1202 if (auth->peer_bi)
1203 bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1204 else
1205 bix = NULL;
1206 brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1207 }
1208 if (!pix || !prx || !brx)
1209 goto fail;
1210
1211 addr[num_elem] = auth->i_nonce;
1212 len[num_elem] = nonce_len;
1213 num_elem++;
1214
1215 addr[num_elem] = auth->r_nonce;
1216 len[num_elem] = nonce_len;
1217 num_elem++;
1218
1219 addr[num_elem] = wpabuf_head(pix);
1220 len[num_elem] = wpabuf_len(pix) / 2;
1221 num_elem++;
1222
1223 addr[num_elem] = wpabuf_head(prx);
1224 len[num_elem] = wpabuf_len(prx) / 2;
1225 num_elem++;
1226
1227 if (bix) {
1228 addr[num_elem] = wpabuf_head(bix);
1229 len[num_elem] = wpabuf_len(bix) / 2;
1230 num_elem++;
1231 }
1232
1233 addr[num_elem] = wpabuf_head(brx);
1234 len[num_elem] = wpabuf_len(brx) / 2;
1235 num_elem++;
1236
1237 addr[num_elem] = &zero;
1238 len[num_elem] = 1;
1239 num_elem++;
1240
1241 wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
1242 for (i = 0; i < num_elem; i++)
1243 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1244 if (auth->curve->hash_len == 32)
1245 res = sha256_vector(num_elem, addr, len, r_auth);
1246 else if (auth->curve->hash_len == 48)
1247 res = sha384_vector(num_elem, addr, len, r_auth);
1248 else if (auth->curve->hash_len == 64)
1249 res = sha512_vector(num_elem, addr, len, r_auth);
1250 else
1251 res = -1;
1252 if (res == 0)
1253 wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
1254 auth->curve->hash_len);
1255fail:
1256 wpabuf_free(pix);
1257 wpabuf_free(prx);
1258 wpabuf_free(bix);
1259 wpabuf_free(brx);
1260 return res;
1261}
1262
1263
1264static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
1265{
1266 struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
1267 const u8 *addr[7];
1268 size_t len[7];
1269 size_t i, num_elem = 0;
1270 size_t nonce_len;
1271 u8 one = 1;
1272 int res = -1;
1273
1274 /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
1275 nonce_len = auth->curve->nonce_len;
1276
1277 if (auth->initiator) {
1278 pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1279 prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1280 if (auth->own_bi)
1281 bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1282 else
1283 bix = NULL;
1284 if (!auth->peer_bi)
1285 goto fail;
1286 brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1287 } else {
1288 pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1289 prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1290 if (auth->peer_bi)
1291 bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1292 else
1293 bix = NULL;
1294 if (!auth->own_bi)
1295 goto fail;
1296 brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1297 }
1298 if (!pix || !prx || !brx)
1299 goto fail;
1300
1301 addr[num_elem] = auth->r_nonce;
1302 len[num_elem] = nonce_len;
1303 num_elem++;
1304
1305 addr[num_elem] = auth->i_nonce;
1306 len[num_elem] = nonce_len;
1307 num_elem++;
1308
1309 addr[num_elem] = wpabuf_head(prx);
1310 len[num_elem] = wpabuf_len(prx) / 2;
1311 num_elem++;
1312
1313 addr[num_elem] = wpabuf_head(pix);
1314 len[num_elem] = wpabuf_len(pix) / 2;
1315 num_elem++;
1316
1317 addr[num_elem] = wpabuf_head(brx);
1318 len[num_elem] = wpabuf_len(brx) / 2;
1319 num_elem++;
1320
1321 if (bix) {
1322 addr[num_elem] = wpabuf_head(bix);
1323 len[num_elem] = wpabuf_len(bix) / 2;
1324 num_elem++;
1325 }
1326
1327 addr[num_elem] = &one;
1328 len[num_elem] = 1;
1329 num_elem++;
1330
1331 wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1332 for (i = 0; i < num_elem; i++)
1333 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1334 if (auth->curve->hash_len == 32)
1335 res = sha256_vector(num_elem, addr, len, i_auth);
1336 else if (auth->curve->hash_len == 48)
1337 res = sha384_vector(num_elem, addr, len, i_auth);
1338 else if (auth->curve->hash_len == 64)
1339 res = sha512_vector(num_elem, addr, len, i_auth);
1340 else
1341 res = -1;
1342 if (res == 0)
1343 wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1344 auth->curve->hash_len);
1345fail:
1346 wpabuf_free(pix);
1347 wpabuf_free(prx);
1348 wpabuf_free(bix);
1349 wpabuf_free(brx);
1350 return res;
1351}
1352
1353
1354static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1355{
1356 const EC_GROUP *group;
1357 EC_POINT *l = NULL;
1358 EC_KEY *BI = NULL, *bR = NULL, *pR = NULL;
1359 const EC_POINT *BI_point;
1360 BN_CTX *bnctx;
1361 BIGNUM *lx, *sum, *q;
1362 const BIGNUM *bR_bn, *pR_bn;
1363 int ret = -1;
1364 int num_bytes, offset;
1365
1366 /* L = ((bR + pR) modulo q) * BI */
1367
1368 bnctx = BN_CTX_new();
1369 sum = BN_new();
1370 q = BN_new();
1371 lx = BN_new();
1372 if (!bnctx || !sum || !q || !lx)
1373 goto fail;
1374 BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
1375 if (!BI)
1376 goto fail;
1377 BI_point = EC_KEY_get0_public_key(BI);
1378 group = EC_KEY_get0_group(BI);
1379 if (!group)
1380 goto fail;
1381
1382 bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
1383 pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
1384 if (!bR || !pR)
1385 goto fail;
1386 bR_bn = EC_KEY_get0_private_key(bR);
1387 pR_bn = EC_KEY_get0_private_key(pR);
1388 if (!bR_bn || !pR_bn)
1389 goto fail;
1390 if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
1391 BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
1392 goto fail;
1393 l = EC_POINT_new(group);
1394 if (!l ||
1395 EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
1396 EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
1397 bnctx) != 1) {
1398 wpa_printf(MSG_ERROR,
1399 "OpenSSL: failed: %s",
1400 ERR_error_string(ERR_get_error(), NULL));
1401 goto fail;
1402 }
1403
1404 num_bytes = BN_num_bytes(lx);
1405 if ((size_t) num_bytes > auth->secret_len)
1406 goto fail;
1407 if (auth->secret_len > (size_t) num_bytes)
1408 offset = auth->secret_len - num_bytes;
1409 else
1410 offset = 0;
1411
1412 os_memset(auth->Lx, 0, offset);
1413 BN_bn2bin(lx, auth->Lx + offset);
1414 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1415 ret = 0;
1416fail:
1417 EC_POINT_clear_free(l);
1418 EC_KEY_free(BI);
1419 EC_KEY_free(bR);
1420 EC_KEY_free(pR);
1421 BN_clear_free(lx);
1422 BN_clear_free(sum);
1423 BN_free(q);
1424 BN_CTX_free(bnctx);
1425 return ret;
1426}
1427
1428
1429static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1430{
1431 const EC_GROUP *group;
1432 EC_POINT *l = NULL, *sum = NULL;
1433 EC_KEY *bI = NULL, *BR = NULL, *PR = NULL;
1434 const EC_POINT *BR_point, *PR_point;
1435 BN_CTX *bnctx;
1436 BIGNUM *lx;
1437 const BIGNUM *bI_bn;
1438 int ret = -1;
1439 int num_bytes, offset;
1440
1441 /* L = bI * (BR + PR) */
1442
1443 bnctx = BN_CTX_new();
1444 lx = BN_new();
1445 if (!bnctx || !lx)
1446 goto fail;
1447 BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
1448 PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key);
1449 if (!BR || !PR)
1450 goto fail;
1451 BR_point = EC_KEY_get0_public_key(BR);
1452 PR_point = EC_KEY_get0_public_key(PR);
1453
1454 bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
1455 if (!bI)
1456 goto fail;
1457 group = EC_KEY_get0_group(bI);
1458 bI_bn = EC_KEY_get0_private_key(bI);
1459 if (!group || !bI_bn)
1460 goto fail;
1461 sum = EC_POINT_new(group);
1462 l = EC_POINT_new(group);
1463 if (!sum || !l ||
1464 EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
1465 EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
1466 EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
1467 bnctx) != 1) {
1468 wpa_printf(MSG_ERROR,
1469 "OpenSSL: failed: %s",
1470 ERR_error_string(ERR_get_error(), NULL));
1471 goto fail;
1472 }
1473
1474 num_bytes = BN_num_bytes(lx);
1475 if ((size_t) num_bytes > auth->secret_len)
1476 goto fail;
1477 if (auth->secret_len > (size_t) num_bytes)
1478 offset = auth->secret_len - num_bytes;
1479 else
1480 offset = 0;
1481
1482 os_memset(auth->Lx, 0, offset);
1483 BN_bn2bin(lx, auth->Lx + offset);
1484 wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1485 ret = 0;
1486fail:
1487 EC_POINT_clear_free(l);
1488 EC_KEY_free(bI);
1489 EC_KEY_free(BR);
1490 EC_KEY_free(PR);
1491 BN_clear_free(lx);
1492 BN_CTX_free(bnctx);
1493 return ret;
1494}
1495
1496
1497static int dpp_auth_build_resp(struct dpp_authentication *auth)
1498{
1499 size_t nonce_len;
1500 EVP_PKEY_CTX *ctx = NULL;
1501 size_t secret_len;
1502 struct wpabuf *msg, *pr = NULL;
1503 u8 r_auth[4 + DPP_MAX_HASH_LEN];
1504 u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE];
1505#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
1506 4 + sizeof(wrapped_r_auth)
1507 size_t wrapped_r_auth_len;
1508 u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
1509 u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
1510 u8 *pos;
1511 const u8 *addr[1];
1512 size_t len[1], siv_len;
1513
1514 wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
1515
1516 nonce_len = auth->curve->nonce_len;
1517 if (random_get_bytes(auth->r_nonce, nonce_len)) {
1518 wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
1519 goto fail;
1520 }
1521 wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
1522
1523 auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1524 if (!auth->own_protocol_key)
1525 goto fail;
1526
1527 pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1528 if (!pr)
1529 goto fail;
1530
1531 /* ECDH: N = pR * PI */
1532 ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
1533 if (!ctx ||
1534 EVP_PKEY_derive_init(ctx) != 1 ||
1535 EVP_PKEY_derive_set_peer(ctx, auth->peer_protocol_key) != 1 ||
1536 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
1537 secret_len > DPP_MAX_SHARED_SECRET_LEN ||
1538 EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
1539 wpa_printf(MSG_ERROR,
1540 "DPP: Failed to derive ECDH shared secret: %s",
1541 ERR_error_string(ERR_get_error(), NULL));
1542 goto fail;
1543 }
1544 EVP_PKEY_CTX_free(ctx);
1545 ctx = NULL;
1546
1547 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
1548 auth->Nx, auth->secret_len);
1549
1550 if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
1551 auth->curve->hash_len) < 0)
1552 goto fail;
1553
1554 if (auth->own_bi && auth->peer_bi) {
1555 /* Mutual authentication */
1556 if (dpp_auth_derive_l_responder(auth) < 0)
1557 goto fail;
1558 }
1559
1560 if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
1561 goto fail;
1562
1563 /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1564 WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
1565 WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
1566 if (dpp_gen_r_auth(auth, r_auth + 4) < 0 ||
1567 aes_siv_encrypt(auth->ke, auth->curve->hash_len,
1568 r_auth, 4 + auth->curve->hash_len,
1569 0, NULL, NULL, wrapped_r_auth) < 0)
1570 goto fail;
1571 wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
1572 wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
1573 wrapped_r_auth, wrapped_r_auth_len);
1574
1575 /* Build DPP Authentication Response frame attributes */
1576 msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1577 4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data));
1578 if (!msg)
1579 goto fail;
1580 wpabuf_free(auth->resp_attr);
1581 auth->resp_attr = msg;
1582
1583 /* DPP Status */
1584 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1585 wpabuf_put_le16(msg, 1);
1586 wpabuf_put_u8(msg, DPP_STATUS_OK);
1587
1588 /* Responder Bootstrapping Key Hash */
1589 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1590 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1591 wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
1592
1593 if (auth->peer_bi) {
1594 /* Mutual authentication */
1595 /* Initiator Bootstrapping Key Hash */
1596 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1597 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1598 wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
1599 SHA256_MAC_LEN);
1600 }
1601
1602 /* Responder Protocol Key */
1603 wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
1604 wpabuf_put_le16(msg, wpabuf_len(pr));
1605 wpabuf_put_buf(msg, pr);
1606 wpabuf_free(pr);
1607 pr = NULL;
1608
1609 /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
1610 pos = clear;
1611 /* R-nonce */
1612 WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
1613 pos += 2;
1614 WPA_PUT_LE16(pos, nonce_len);
1615 pos += 2;
1616 os_memcpy(pos, auth->r_nonce, nonce_len);
1617 pos += nonce_len;
1618 /* I-nonce */
1619 WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1620 pos += 2;
1621 WPA_PUT_LE16(pos, nonce_len);
1622 pos += 2;
1623 os_memcpy(pos, auth->i_nonce, nonce_len);
1624 pos += nonce_len;
1625 /* R-capabilities */
1626 WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
1627 pos += 2;
1628 WPA_PUT_LE16(pos, 1);
1629 pos += 2;
1630 auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
1631 DPP_CAPAB_ENROLLEE;
1632 *pos++ = auth->r_capab;
1633 /* {R-auth}ke */
1634 WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
1635 pos += 2;
1636 WPA_PUT_LE16(pos, wrapped_r_auth_len);
1637 pos += 2;
1638 os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
1639 pos += wrapped_r_auth_len;
1640
1641 addr[0] = wpabuf_head(msg);
1642 len[0] = wpabuf_len(msg);
1643 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
1644 siv_len = pos - clear;
1645 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1646 if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, clear, siv_len,
1647 1, addr, len, wrapped_data) < 0)
1648 goto fail;
1649 siv_len += AES_BLOCK_SIZE;
1650 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1651 wrapped_data, siv_len);
1652
1653 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1654 wpabuf_put_le16(msg, siv_len);
1655 wpabuf_put_data(msg, wrapped_data, siv_len);
1656
1657 wpa_hexdump_buf(MSG_DEBUG,
1658 "DPP: Authentication Response frame attributes", msg);
1659
1660 return 0;
1661
1662fail:
1663 wpabuf_free(pr);
1664 return -1;
1665}
1666
1667
1668static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
1669 enum dpp_status_error status)
1670{
1671 size_t nonce_len;
1672 struct wpabuf *msg;
1673#define DPP_AUTH_RESP_CLEAR_LEN2 4 + DPP_MAX_NONCE_LEN + 4 + 1
1674 u8 clear[DPP_AUTH_RESP_CLEAR_LEN2];
1675 u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN2 + AES_BLOCK_SIZE];
1676 u8 *pos;
1677 const u8 *addr[1];
1678 size_t len[1], siv_len;
1679
1680 wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
1681
1682 /* Build DPP Authentication Response frame attributes */
1683 msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1684 4 + sizeof(wrapped_data));
1685 if (!msg)
1686 goto fail;
1687 wpabuf_free(auth->resp_attr);
1688 auth->resp_attr = msg;
1689
1690 /* DPP Status */
1691 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1692 wpabuf_put_le16(msg, 1);
1693 wpabuf_put_u8(msg, status);
1694
1695 /* Responder Bootstrapping Key Hash */
1696 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1697 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1698 wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
1699
1700 if (auth->peer_bi) {
1701 /* Mutual authentication */
1702 /* Initiator Bootstrapping Key Hash */
1703 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1704 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1705 wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
1706 SHA256_MAC_LEN);
1707 }
1708
1709 /* Wrapped data ({I-nonce, R-capabilities}k1) */
1710 pos = clear;
1711 /* I-nonce */
1712 nonce_len = auth->curve->nonce_len;
1713 WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1714 pos += 2;
1715 WPA_PUT_LE16(pos, nonce_len);
1716 pos += 2;
1717 os_memcpy(pos, auth->i_nonce, nonce_len);
1718 pos += nonce_len;
1719 /* R-capabilities */
1720 WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
1721 pos += 2;
1722 WPA_PUT_LE16(pos, 1);
1723 pos += 2;
1724 auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
1725 DPP_CAPAB_ENROLLEE;
1726 *pos++ = auth->r_capab;
1727
1728 addr[0] = wpabuf_head(msg);
1729 len[0] = wpabuf_len(msg);
1730 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
1731 siv_len = pos - clear;
1732 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1733 if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
1734 1, addr, len, wrapped_data) < 0)
1735 goto fail;
1736 siv_len += AES_BLOCK_SIZE;
1737 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1738 wrapped_data, siv_len);
1739
1740 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1741 wpabuf_put_le16(msg, siv_len);
1742 wpabuf_put_data(msg, wrapped_data, siv_len);
1743
1744 wpa_hexdump_buf(MSG_DEBUG,
1745 "DPP: Authentication Response frame attributes", msg);
1746
1747 return 0;
1748
1749fail:
1750 return -1;
1751}
1752
1753
1754struct dpp_authentication *
1755dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
1756 struct dpp_bootstrap_info *peer_bi,
1757 struct dpp_bootstrap_info *own_bi,
1758 unsigned int freq, const u8 *attr_start,
1759 const u8 *wrapped_data, u16 wrapped_data_len)
1760{
1761 EVP_PKEY *pi = NULL;
1762 EVP_PKEY_CTX *ctx = NULL;
1763 size_t secret_len;
1764 const u8 *addr[1];
1765 size_t len[1];
1766 u8 *unwrapped = NULL;
1767 size_t unwrapped_len = 0;
1768 const u8 *i_proto, *i_nonce, *i_capab, *i_bootstrap;
1769 u16 i_proto_len, i_nonce_len, i_capab_len, i_bootstrap_len;
1770 struct dpp_authentication *auth = NULL;
1771 size_t attr_len;
1772
1773 if (wrapped_data_len < AES_BLOCK_SIZE)
1774 return NULL;
1775
1776 attr_len = wrapped_data - 4 - attr_start;
1777
1778 auth = os_zalloc(sizeof(*auth));
1779 if (!auth)
1780 goto fail;
1781 auth->msg_ctx = msg_ctx;
1782 auth->peer_bi = peer_bi;
1783 auth->own_bi = own_bi;
1784 auth->curve = own_bi->curve;
1785 auth->curr_freq = freq;
1786
1787 i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
1788 &i_proto_len);
1789 if (!i_proto) {
1790 wpa_printf(MSG_DEBUG,
1791 "DPP: Missing required Initiator Protocol Key attribute");
1792 goto fail;
1793 }
1794 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
1795 i_proto, i_proto_len);
1796
1797 /* M = bR * PI */
1798 pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
1799 if (!pi) {
1800 wpa_printf(MSG_DEBUG, "DPP: Invalid Initiator Protocol Key");
1801 goto fail;
1802 }
1803 dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
1804
1805 ctx = EVP_PKEY_CTX_new(own_bi->pubkey, NULL);
1806 if (!ctx ||
1807 EVP_PKEY_derive_init(ctx) != 1 ||
1808 EVP_PKEY_derive_set_peer(ctx, pi) != 1 ||
1809 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
1810 secret_len > DPP_MAX_SHARED_SECRET_LEN ||
1811 EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
1812 wpa_printf(MSG_ERROR,
1813 "DPP: Failed to derive ECDH shared secret: %s",
1814 ERR_error_string(ERR_get_error(), NULL));
1815 goto fail;
1816 }
1817 auth->secret_len = secret_len;
1818 EVP_PKEY_CTX_free(ctx);
1819 ctx = NULL;
1820
1821 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
1822 auth->Mx, auth->secret_len);
1823
1824 if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
1825 auth->curve->hash_len) < 0)
1826 goto fail;
1827
1828 addr[0] = attr_start;
1829 len[0] = attr_len;
1830 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
1831 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1832 wrapped_data, wrapped_data_len);
1833 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
1834 unwrapped = os_malloc(unwrapped_len);
1835 if (!unwrapped)
1836 goto fail;
1837 if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
1838 wrapped_data, wrapped_data_len,
1839 1, addr, len, unwrapped) < 0) {
1840 wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
1841 goto fail;
1842 }
1843 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
1844 unwrapped, unwrapped_len);
1845
1846 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
1847 wpa_printf(MSG_DEBUG,
1848 "DPP: Invalid attribute in unwrapped data");
1849 goto fail;
1850 }
1851
1852 i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
1853 &i_nonce_len);
1854 if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
1855 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
1856 goto fail;
1857 }
1858 wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
1859 os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
1860
1861 i_capab = dpp_get_attr(unwrapped, unwrapped_len,
1862 DPP_ATTR_I_CAPABILITIES,
1863 &i_capab_len);
1864 if (!i_capab || i_capab_len < 1) {
1865 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-capabilities");
1866 goto fail;
1867 }
1868 auth->i_capab = i_capab[0];
1869 wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
1870
1871 bin_clear_free(unwrapped, unwrapped_len);
1872 unwrapped = NULL;
1873
1874 switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
1875 case DPP_CAPAB_ENROLLEE:
1876 if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
1877 wpa_printf(MSG_DEBUG,
1878 "DPP: Local policy does not allow Configurator role");
1879 goto not_compatible;
1880 }
1881 wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
1882 auth->configurator = 1;
1883 break;
1884 case DPP_CAPAB_CONFIGURATOR:
1885 if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
1886 wpa_printf(MSG_DEBUG,
1887 "DPP: Local policy does not allow Enrollee role");
1888 goto not_compatible;
1889 }
1890 wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
1891 auth->configurator = 0;
1892 break;
1893 default:
1894 wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
1895 goto not_compatible;
1896 }
1897
1898 auth->peer_protocol_key = pi;
1899 pi = NULL;
1900 if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
1901 char hex[SHA256_MAC_LEN * 2 + 1];
1902
1903 wpa_printf(MSG_DEBUG,
1904 "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
1905 if (dpp_auth_build_resp_status(auth,
1906 DPP_STATUS_RESPONSE_PENDING) < 0)
1907 goto fail;
1908 i_bootstrap = dpp_get_attr(attr_start, attr_len,
1909 DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1910 &i_bootstrap_len);
1911 if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
1912 auth->response_pending = 1;
1913 os_memcpy(auth->waiting_pubkey_hash,
1914 i_bootstrap, i_bootstrap_len);
1915 wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
1916 i_bootstrap_len);
1917 } else {
1918 hex[0] = '\0';
1919 }
1920
1921 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
1922 "%s", hex);
1923 return auth;
1924 }
1925 if (dpp_auth_build_resp(auth) < 0)
1926 goto fail;
1927
1928 return auth;
1929
1930not_compatible:
1931 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
1932 "i-capab=0x%02x", auth->i_capab);
1933 if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
1934 auth->configurator = 1;
1935 else
1936 auth->configurator = 0;
1937 auth->peer_protocol_key = pi;
1938 pi = NULL;
1939 if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
1940 goto fail;
1941
1942 auth->remove_on_tx_status = 1;
1943 return auth;
1944fail:
1945 bin_clear_free(unwrapped, unwrapped_len);
1946 EVP_PKEY_free(pi);
1947 EVP_PKEY_CTX_free(ctx);
1948 dpp_auth_deinit(auth);
1949 return NULL;
1950}
1951
1952
1953int dpp_notify_new_qr_code(struct dpp_authentication *auth,
1954 struct dpp_bootstrap_info *peer_bi)
1955{
1956 if (!auth || !auth->response_pending ||
1957 os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
1958 SHA256_MAC_LEN) != 0)
1959 return 0;
1960
1961 wpa_printf(MSG_DEBUG,
1962 "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
1963 MACSTR, MAC2STR(auth->peer_mac_addr));
1964 auth->peer_bi = peer_bi;
1965
1966 if (dpp_auth_build_resp(auth) < 0)
1967 return -1;
1968
1969 return 1;
1970}
1971
1972
1973static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth)
1974{
1975 struct wpabuf *msg;
1976 u8 i_auth[4 + DPP_MAX_HASH_LEN];
1977 size_t i_auth_len;
1978 const u8 *addr[1];
1979 size_t len[1];
1980 u8 *wrapped_i_auth;
1981
1982 wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
1983
1984 i_auth_len = 4 + auth->curve->hash_len;
1985 /* Build DPP Authentication Confirmation frame attributes */
1986 msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1987 4 + i_auth_len + AES_BLOCK_SIZE);
1988 if (!msg)
1989 goto fail;
1990
1991 /* DPP Status */
1992 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1993 wpabuf_put_le16(msg, 1);
1994 wpabuf_put_u8(msg, DPP_STATUS_OK);
1995
1996 /* Responder Bootstrapping Key Hash */
1997 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1998 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1999 wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2000
2001 if (auth->own_bi) {
2002 /* Mutual authentication */
2003 /* Initiator Bootstrapping Key Hash */
2004 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
2005 wpabuf_put_le16(msg, SHA256_MAC_LEN);
2006 wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
2007 }
2008
2009 addr[0] = wpabuf_head(msg);
2010 len[0] = wpabuf_len(msg);
2011 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2012 wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
2013 wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
2014 /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
2015 WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
2016 WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
2017 if (dpp_gen_i_auth(auth, i_auth + 4) < 0 ||
2018 aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2019 i_auth, i_auth_len,
2020 1, addr, len, wrapped_i_auth) < 0)
2021 goto fail;
2022 wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
2023 wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
2024
2025 wpa_hexdump_buf(MSG_DEBUG,
2026 "DPP: Authentication Confirmation frame attributes",
2027 msg);
2028 dpp_auth_success(auth);
2029
2030 return msg;
2031
2032fail:
2033 return NULL;
2034}
2035
2036
2037static void
2038dpp_auth_resp_rx_status(struct dpp_authentication *auth,
2039 const u8 *attr_start, size_t attr_len,
2040 const u8 *wrapped_data, u16 wrapped_data_len,
2041 enum dpp_status_error status)
2042{
2043 const u8 *addr[1];
2044 size_t len[1];
2045 u8 *unwrapped = NULL;
2046 size_t unwrapped_len = 0;
2047 const u8 *i_nonce, *r_capab;
2048 u16 i_nonce_len, r_capab_len;
2049
2050 if (status == DPP_STATUS_NOT_COMPATIBLE) {
2051 wpa_printf(MSG_DEBUG,
2052 "DPP: Responder reported incompatible roles");
2053 } else if (status == DPP_STATUS_RESPONSE_PENDING) {
2054 wpa_printf(MSG_DEBUG,
2055 "DPP: Responder reported more time needed");
2056 } else {
2057 wpa_printf(MSG_DEBUG,
2058 "DPP: Responder reported failure (status %d)",
2059 status);
2060 return;
2061 }
2062
2063 addr[0] = attr_start;
2064 len[0] = attr_len;
2065 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
2066 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2067 wrapped_data, wrapped_data_len);
2068 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2069 unwrapped = os_malloc(unwrapped_len);
2070 if (!unwrapped)
2071 goto fail;
2072 if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
2073 wrapped_data, wrapped_data_len,
2074 1, addr, len, unwrapped) < 0) {
2075 wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2076 goto fail;
2077 }
2078 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2079 unwrapped, unwrapped_len);
2080
2081 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2082 wpa_printf(MSG_DEBUG,
2083 "DPP: Invalid attribute in unwrapped data");
2084 goto fail;
2085 }
2086
2087 i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2088 &i_nonce_len);
2089 if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2090 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
2091 goto fail;
2092 }
2093 wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2094 if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
2095 wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
2096 goto fail;
2097 }
2098
2099 r_capab = dpp_get_attr(unwrapped, unwrapped_len,
2100 DPP_ATTR_R_CAPABILITIES,
2101 &r_capab_len);
2102 if (!r_capab || r_capab_len < 1) {
2103 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
2104 goto fail;
2105 }
2106 auth->r_capab = r_capab[0];
2107 wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
2108 if (status == DPP_STATUS_NOT_COMPATIBLE) {
2109 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
2110 "r-capab=0x%02x", auth->r_capab);
2111 } else if (status == DPP_STATUS_RESPONSE_PENDING) {
2112 wpa_printf(MSG_DEBUG,
2113 "DPP: Continue waiting for full DPP Authentication Response");
2114 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_RESPONSE_PENDING);
2115 }
2116fail:
2117 bin_clear_free(unwrapped, unwrapped_len);
2118}
2119
2120
2121struct wpabuf *
2122dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start,
2123 size_t attr_len)
2124{
2125 EVP_PKEY *pr;
2126 EVP_PKEY_CTX *ctx = NULL;
2127 size_t secret_len;
2128 const u8 *addr[1];
2129 size_t len[1];
2130 u8 *unwrapped = NULL, *unwrapped2 = NULL;
2131 size_t unwrapped_len = 0, unwrapped2_len = 0;
2132 const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
2133 *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
2134 u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
2135 r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
2136 wrapped2_len, r_auth_len;
2137 u8 r_auth2[DPP_MAX_HASH_LEN];
2138
2139 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2140 &wrapped_data_len);
2141 if (!wrapped_data) {
2142 wpa_printf(MSG_DEBUG,
2143 "DPP: Missing required Wrapped data attribute");
2144 return NULL;
2145 }
2146 wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
2147 wrapped_data, wrapped_data_len);
2148
2149 if (wrapped_data_len < AES_BLOCK_SIZE)
2150 return NULL;
2151
2152 attr_len = wrapped_data - 4 - attr_start;
2153
2154 r_bootstrap = dpp_get_attr(attr_start, attr_len,
2155 DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2156 &r_bootstrap_len);
2157 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2158 wpa_printf(MSG_DEBUG,
2159 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2160 return NULL;
2161 }
2162 wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
2163 r_bootstrap, r_bootstrap_len);
2164 if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
2165 SHA256_MAC_LEN) != 0) {
2166 wpa_hexdump(MSG_DEBUG,
2167 "DPP: Expected Responder Bootstrapping Key Hash",
2168 auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2169 return NULL;
2170 }
2171
2172 i_bootstrap = dpp_get_attr(attr_start, attr_len,
2173 DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2174 &i_bootstrap_len);
2175 if (i_bootstrap) {
2176 if (i_bootstrap_len != SHA256_MAC_LEN) {
2177 wpa_printf(MSG_DEBUG,
2178 "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
2179 return NULL;
2180 }
2181 wpa_hexdump(MSG_MSGDUMP,
2182 "DPP: Initiator Bootstrapping Key Hash",
2183 i_bootstrap, i_bootstrap_len);
2184 if (!auth->own_bi ||
2185 os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
2186 SHA256_MAC_LEN) != 0) {
2187 wpa_printf(MSG_DEBUG,
2188 "DPP: Initiator Bootstrapping Key Hash attribute did not match");
2189 return NULL;
2190 }
2191 }
2192
2193 status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
2194 &status_len);
2195 if (!status || status_len < 1) {
2196 wpa_printf(MSG_DEBUG,
2197 "DPP: Missing or invalid required DPP Status attribute");
2198 return NULL;
2199 }
2200 wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
2201 auth->auth_resp_status = status[0];
2202 if (status[0] != DPP_STATUS_OK) {
2203 dpp_auth_resp_rx_status(auth, attr_start,
2204 attr_len, wrapped_data,
2205 wrapped_data_len, status[0]);
2206 return NULL;
2207 }
2208
2209 r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
2210 &r_proto_len);
2211 if (!r_proto) {
2212 wpa_printf(MSG_DEBUG,
2213 "DPP: Missing required Responder Protocol Key attribute");
2214 return NULL;
2215 }
2216 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
2217 r_proto, r_proto_len);
2218
2219 /* N = pI * PR */
2220 pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
2221 if (!pr) {
2222 wpa_printf(MSG_DEBUG, "DPP: Invalid Responder Protocol Key");
2223 return NULL;
2224 }
2225 dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
2226
2227 ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
2228 if (!ctx ||
2229 EVP_PKEY_derive_init(ctx) != 1 ||
2230 EVP_PKEY_derive_set_peer(ctx, pr) != 1 ||
2231 EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
2232 secret_len > DPP_MAX_SHARED_SECRET_LEN ||
2233 EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
2234 wpa_printf(MSG_ERROR,
2235 "DPP: Failed to derive ECDH shared secret: %s",
2236 ERR_error_string(ERR_get_error(), NULL));
2237 goto fail;
2238 }
2239 EVP_PKEY_CTX_free(ctx);
2240 ctx = NULL;
2241 auth->peer_protocol_key = pr;
2242 pr = NULL;
2243
2244 wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
2245 auth->Nx, auth->secret_len);
2246
2247 if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
2248 auth->curve->hash_len) < 0)
2249 goto fail;
2250
2251 addr[0] = attr_start;
2252 len[0] = attr_len;
2253 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
2254 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2255 wrapped_data, wrapped_data_len);
2256 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2257 unwrapped = os_malloc(unwrapped_len);
2258 if (!unwrapped)
2259 goto fail;
2260 if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
2261 wrapped_data, wrapped_data_len,
2262 1, addr, len, unwrapped) < 0) {
2263 wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2264 goto fail;
2265 }
2266 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2267 unwrapped, unwrapped_len);
2268
2269 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2270 wpa_printf(MSG_DEBUG,
2271 "DPP: Invalid attribute in unwrapped data");
2272 goto fail;
2273 }
2274
2275 r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
2276 &r_nonce_len);
2277 if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
2278 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-nonce");
2279 goto fail;
2280 }
2281 wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
2282 os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
2283
2284 i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2285 &i_nonce_len);
2286 if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2287 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
2288 goto fail;
2289 }
2290 wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2291 if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
2292 wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
2293 goto fail;
2294 }
2295
2296 if (auth->own_bi && auth->peer_bi) {
2297 /* Mutual authentication */
2298 if (dpp_auth_derive_l_initiator(auth) < 0)
2299 goto fail;
2300 }
2301
2302 if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
2303 goto fail;
2304
2305 r_capab = dpp_get_attr(unwrapped, unwrapped_len,
2306 DPP_ATTR_R_CAPABILITIES,
2307 &r_capab_len);
2308 if (!r_capab || r_capab_len < 1) {
2309 wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
2310 goto fail;
2311 }
2312 auth->r_capab = r_capab[0];
2313 wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
2314 if ((auth->configurator && (auth->r_capab & DPP_CAPAB_CONFIGURATOR)) ||
2315 (!auth->configurator && (auth->r_capab & DPP_CAPAB_ENROLLEE))) {
2316 wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
2317 goto fail;
2318 }
2319
2320 wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
2321 DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
2322 if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
2323 wpa_printf(MSG_DEBUG,
2324 "DPP: Missing or invalid Secondary Wrapped Data");
2325 goto fail;
2326 }
2327
2328 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2329 wrapped2, wrapped2_len);
2330 unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
2331 unwrapped2 = os_malloc(unwrapped2_len);
2332 if (!unwrapped2)
2333 goto fail;
2334 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2335 wrapped2, wrapped2_len,
2336 0, NULL, NULL, unwrapped2) < 0) {
2337 wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2338 goto fail;
2339 }
2340 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2341 unwrapped2, unwrapped2_len);
2342
2343 if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
2344 wpa_printf(MSG_DEBUG,
2345 "DPP: Invalid attribute in secondary unwrapped data");
2346 goto fail;
2347 }
2348
2349 r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
2350 &r_auth_len);
2351 if (!r_auth || r_auth_len != auth->curve->hash_len) {
2352 wpa_printf(MSG_DEBUG,
2353 "DPP: Missing or invalid Responder Authenticating Tag");
2354 goto fail;
2355 }
2356 wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
2357 r_auth, r_auth_len);
2358 /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
2359 if (dpp_gen_r_auth(auth, r_auth2) < 0)
2360 goto fail;
2361 wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
2362 r_auth2, r_auth_len);
2363 if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
2364 wpa_printf(MSG_DEBUG,
2365 "DPP: Mismatching Responder Authenticating Tag");
2366 goto fail;
2367 }
2368
2369 bin_clear_free(unwrapped, unwrapped_len);
2370 bin_clear_free(unwrapped2, unwrapped2_len);
2371
2372 return dpp_auth_build_conf(auth);
2373
2374fail:
2375 bin_clear_free(unwrapped, unwrapped_len);
2376 bin_clear_free(unwrapped2, unwrapped2_len);
2377 EVP_PKEY_free(pr);
2378 EVP_PKEY_CTX_free(ctx);
2379 return NULL;
2380}
2381
2382
2383int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *attr_start,
2384 size_t attr_len)
2385{
2386 const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
2387 u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
2388 i_auth_len;
2389 const u8 *addr[1];
2390 size_t len[1];
2391 u8 *unwrapped = NULL;
2392 size_t unwrapped_len = 0;
2393 u8 i_auth2[DPP_MAX_HASH_LEN];
2394
2395 wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2396 &wrapped_data_len);
2397 if (!wrapped_data) {
2398 wpa_printf(MSG_DEBUG,
2399 "DPP: Missing required Wrapped data attribute");
2400 return -1;
2401 }
2402 wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
2403 wrapped_data, wrapped_data_len);
2404
2405 if (wrapped_data_len < AES_BLOCK_SIZE)
2406 return -1;
2407
2408 attr_len = wrapped_data - 4 - attr_start;
2409
2410 r_bootstrap = dpp_get_attr(attr_start, attr_len,
2411 DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2412 &r_bootstrap_len);
2413 if (!r_bootstrap || r_bootstrap > wrapped_data ||
2414 r_bootstrap_len != SHA256_MAC_LEN) {
2415 wpa_printf(MSG_DEBUG,
2416 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2417 return -1;
2418 }
2419 wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
2420 r_bootstrap, r_bootstrap_len);
2421 if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
2422 SHA256_MAC_LEN) != 0) {
2423 wpa_hexdump(MSG_DEBUG,
2424 "DPP: Expected Responder Bootstrapping Key Hash",
2425 auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2426 return -1;
2427 }
2428
2429 i_bootstrap = dpp_get_attr(attr_start, attr_len,
2430 DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2431 &i_bootstrap_len);
2432 if (i_bootstrap) {
2433 if (i_bootstrap > wrapped_data ||
2434 i_bootstrap_len != SHA256_MAC_LEN) {
2435 wpa_printf(MSG_DEBUG,
2436 "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
2437 return -1;
2438 }
2439 wpa_hexdump(MSG_MSGDUMP,
2440 "DPP: Initiator Bootstrapping Key Hash",
2441 i_bootstrap, i_bootstrap_len);
2442 if (!auth->peer_bi ||
2443 os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
2444 SHA256_MAC_LEN) != 0) {
2445 wpa_printf(MSG_DEBUG,
2446 "DPP: Initiator Bootstrapping Key Hash attribute did not match");
2447 return -1;
2448 }
2449 }
2450
2451 status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
2452 &status_len);
2453 if (!status || status_len < 1) {
2454 wpa_printf(MSG_DEBUG,
2455 "DPP: Missing or invalid required DPP Status attribute");
2456 return -1;
2457 }
2458 wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
2459 if (status[0] != DPP_STATUS_OK) {
2460 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
2461 return -1;
2462 }
2463
2464 addr[0] = attr_start;
2465 len[0] = attr_len;
2466 wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
2467 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2468 wrapped_data, wrapped_data_len);
2469 unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2470 unwrapped = os_malloc(unwrapped_len);
2471 if (!unwrapped)
2472 return -1;
2473 if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2474 wrapped_data, wrapped_data_len,
2475 1, addr, len, unwrapped) < 0) {
2476 wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2477 goto fail;
2478 }
2479 wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2480 unwrapped, unwrapped_len);
2481
2482 if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2483 wpa_printf(MSG_DEBUG,
2484 "DPP: Invalid attribute in unwrapped data");
2485 goto fail;
2486 }
2487
2488 i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
2489 &i_auth_len);
2490 if (!i_auth || i_auth_len != auth->curve->hash_len) {
2491 wpa_printf(MSG_DEBUG,
2492 "DPP: Missing or invalid Initiator Authenticating Tag");
2493 goto fail;
2494 }
2495 wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
2496 i_auth, i_auth_len);
2497 /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
2498 if (dpp_gen_i_auth(auth, i_auth2) < 0)
2499 goto fail;
2500 wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
2501 i_auth2, i_auth_len);
2502 if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
2503 wpa_printf(MSG_DEBUG,
2504 "DPP: Mismatching Initiator Authenticating Tag");
2505 goto fail;
2506 }
2507
2508 bin_clear_free(unwrapped, unwrapped_len);
2509 dpp_auth_success(auth);
2510 return 0;
2511fail:
2512 bin_clear_free(unwrapped, unwrapped_len);
2513 return -1;
2514}
2515
2516
2517void dpp_auth_deinit(struct dpp_authentication *auth)
2518{
2519 if (!auth)
2520 return;
2521 EVP_PKEY_free(auth->own_protocol_key);
2522 EVP_PKEY_free(auth->peer_protocol_key);
2523 wpabuf_free(auth->req_attr);
2524 wpabuf_free(auth->resp_attr);
2525 bin_clear_free(auth, sizeof(*auth));
2526}