]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/common/dpp.c
Update tcsh to 6.21.00.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / common / dpp.c
1 /*
2  * DPP functionality shared between hostapd and wpa_supplicant
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2019, The Linux Foundation
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9
10 #include "utils/includes.h"
11 #include <fcntl.h>
12 #include <openssl/opensslv.h>
13 #include <openssl/err.h>
14 #include <openssl/asn1.h>
15 #include <openssl/asn1t.h>
16
17 #include "utils/common.h"
18 #include "utils/base64.h"
19 #include "utils/json.h"
20 #include "utils/ip_addr.h"
21 #include "utils/eloop.h"
22 #include "common/ieee802_11_common.h"
23 #include "common/ieee802_11_defs.h"
24 #include "common/wpa_ctrl.h"
25 #include "common/gas.h"
26 #include "crypto/crypto.h"
27 #include "crypto/random.h"
28 #include "crypto/aes.h"
29 #include "crypto/aes_siv.h"
30 #include "crypto/sha384.h"
31 #include "crypto/sha512.h"
32 #include "drivers/driver.h"
33 #include "dpp.h"
34
35
36 #ifdef CONFIG_TESTING_OPTIONS
37 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
38 u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
39 u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
40 u8 dpp_pkex_ephemeral_key_override[600];
41 size_t dpp_pkex_ephemeral_key_override_len = 0;
42 u8 dpp_protocol_key_override[600];
43 size_t dpp_protocol_key_override_len = 0;
44 u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
45 size_t dpp_nonce_override_len = 0;
46
47 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
48                                     const struct dpp_curve_params *curve);
49 #endif /* CONFIG_TESTING_OPTIONS */
50
51 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
52         (defined(LIBRESSL_VERSION_NUMBER) && \
53          LIBRESSL_VERSION_NUMBER < 0x20700000L)
54 /* Compatibility wrappers for older versions. */
55
56 static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
57 {
58         sig->r = r;
59         sig->s = s;
60         return 1;
61 }
62
63
64 static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
65                            const BIGNUM **ps)
66 {
67         if (pr)
68                 *pr = sig->r;
69         if (ps)
70                 *ps = sig->s;
71 }
72
73 #endif
74
75
76 struct dpp_connection {
77         struct dl_list list;
78         struct dpp_controller *ctrl;
79         struct dpp_relay_controller *relay;
80         struct dpp_global *global;
81         struct dpp_authentication *auth;
82         int sock;
83         u8 mac_addr[ETH_ALEN];
84         unsigned int freq;
85         u8 msg_len[4];
86         size_t msg_len_octets;
87         struct wpabuf *msg;
88         struct wpabuf *msg_out;
89         size_t msg_out_pos;
90         unsigned int read_eloop:1;
91         unsigned int write_eloop:1;
92         unsigned int on_tcp_tx_complete_gas_done:1;
93         unsigned int on_tcp_tx_complete_remove:1;
94         unsigned int on_tcp_tx_complete_auth_ok:1;
95 };
96
97 /* Remote Controller */
98 struct dpp_relay_controller {
99         struct dl_list list;
100         struct dpp_global *global;
101         u8 pkhash[SHA256_MAC_LEN];
102         struct hostapd_ip_addr ipaddr;
103         void *cb_ctx;
104         void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
105                    size_t len);
106         void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
107                             int prot, struct wpabuf *buf);
108         struct dl_list conn; /* struct dpp_connection */
109 };
110
111 /* Local Controller */
112 struct dpp_controller {
113         struct dpp_global *global;
114         u8 allowed_roles;
115         int qr_mutual;
116         int sock;
117         struct dl_list conn; /* struct dpp_connection */
118         char *configurator_params;
119 };
120
121 struct dpp_global {
122         void *msg_ctx;
123         struct dl_list bootstrap; /* struct dpp_bootstrap_info */
124         struct dl_list configurator; /* struct dpp_configurator */
125 #ifdef CONFIG_DPP2
126         struct dl_list controllers; /* struct dpp_relay_controller */
127         struct dpp_controller *controller;
128         struct dl_list tcp_init; /* struct dpp_connection */
129         void *cb_ctx;
130         int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
131 #endif /* CONFIG_DPP2 */
132 };
133
134 static const struct dpp_curve_params dpp_curves[] = {
135         /* The mandatory to support and the default NIST P-256 curve needs to
136          * be the first entry on this list. */
137         { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
138         { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
139         { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
140         { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
141         { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
142         { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
143         { NULL, 0, 0, 0, 0, NULL, 0, NULL }
144 };
145
146
147 /* Role-specific elements for PKEX */
148
149 /* NIST P-256 */
150 static const u8 pkex_init_x_p256[32] = {
151         0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
152         0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
153         0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
154         0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
155  };
156 static const u8 pkex_init_y_p256[32] = {
157         0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
158         0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
159         0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
160         0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
161  };
162 static const u8 pkex_resp_x_p256[32] = {
163         0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
164         0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
165         0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
166         0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
167 };
168 static const u8 pkex_resp_y_p256[32] = {
169         0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
170         0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
171         0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
172         0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
173 };
174
175 /* NIST P-384 */
176 static const u8 pkex_init_x_p384[48] = {
177         0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
178         0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
179         0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
180         0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
181         0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
182         0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
183 };
184 static const u8 pkex_init_y_p384[48] = {
185         0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
186         0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
187         0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
188         0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
189         0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
190         0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
191 };
192 static const u8 pkex_resp_x_p384[48] = {
193         0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
194         0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
195         0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
196         0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
197         0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
198         0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
199 };
200 static const u8 pkex_resp_y_p384[48] = {
201         0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
202         0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
203         0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
204         0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
205         0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
206         0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
207 };
208
209 /* NIST P-521 */
210 static const u8 pkex_init_x_p521[66] = {
211         0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
212         0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
213         0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
214         0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
215         0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
216         0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
217         0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
218         0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
219         0x97, 0x76
220 };
221 static const u8 pkex_init_y_p521[66] = {
222         0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
223         0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
224         0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
225         0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
226         0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
227         0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
228         0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
229         0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
230         0x03, 0xa8
231 };
232 static const u8 pkex_resp_x_p521[66] = {
233         0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
234         0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
235         0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
236         0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
237         0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
238         0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
239         0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
240         0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
241         0x84, 0xb4
242 };
243 static const u8 pkex_resp_y_p521[66] = {
244         0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
245         0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
246         0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
247         0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
248         0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
249         0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
250         0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
251         0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
252         0xce, 0xe1
253 };
254
255 /* Brainpool P-256r1 */
256 static const u8 pkex_init_x_bp_p256r1[32] = {
257         0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
258         0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
259         0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
260         0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
261 };
262 static const u8 pkex_init_y_bp_p256r1[32] = {
263         0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
264         0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
265         0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
266         0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
267 };
268 static const u8 pkex_resp_x_bp_p256r1[32] = {
269         0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
270         0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
271         0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
272         0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
273 };
274 static const u8 pkex_resp_y_bp_p256r1[32] = {
275         0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
276         0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
277         0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
278         0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
279 };
280
281 /* Brainpool P-384r1 */
282 static const u8 pkex_init_x_bp_p384r1[48] = {
283         0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
284         0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
285         0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
286         0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
287         0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
288         0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
289 };
290 static const u8 pkex_init_y_bp_p384r1[48] = {
291         0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
292         0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
293         0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
294         0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
295         0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
296         0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
297 };
298 static const u8 pkex_resp_x_bp_p384r1[48] = {
299         0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
300         0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
301         0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
302         0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
303         0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
304         0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
305 };
306 static const u8 pkex_resp_y_bp_p384r1[48] = {
307         0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
308         0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
309         0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
310         0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
311         0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
312         0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
313 };
314
315 /* Brainpool P-512r1 */
316 static const u8 pkex_init_x_bp_p512r1[64] = {
317         0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
318         0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
319         0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
320         0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
321         0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
322         0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
323         0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
324         0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
325 };
326 static const u8 pkex_init_y_bp_p512r1[64] = {
327         0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
328         0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
329         0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
330         0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
331         0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
332         0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
333         0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
334         0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
335 };
336 static const u8 pkex_resp_x_bp_p512r1[64] = {
337         0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
338         0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
339         0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
340         0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
341         0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
342         0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
343         0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
344         0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
345 };
346 static const u8 pkex_resp_y_bp_p512r1[64] = {
347         0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
348         0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
349         0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
350         0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
351         0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
352         0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
353         0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
354         0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
355 };
356
357
358 static void dpp_debug_print_point(const char *title, const EC_GROUP *group,
359                                   const EC_POINT *point)
360 {
361         BIGNUM *x, *y;
362         BN_CTX *ctx;
363         char *x_str = NULL, *y_str = NULL;
364
365         if (!wpa_debug_show_keys)
366                 return;
367
368         ctx = BN_CTX_new();
369         x = BN_new();
370         y = BN_new();
371         if (!ctx || !x || !y ||
372             EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1)
373                 goto fail;
374
375         x_str = BN_bn2hex(x);
376         y_str = BN_bn2hex(y);
377         if (!x_str || !y_str)
378                 goto fail;
379
380         wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
381
382 fail:
383         OPENSSL_free(x_str);
384         OPENSSL_free(y_str);
385         BN_free(x);
386         BN_free(y);
387         BN_CTX_free(ctx);
388 }
389
390
391 static int dpp_hash_vector(const struct dpp_curve_params *curve,
392                            size_t num_elem, const u8 *addr[], const size_t *len,
393                            u8 *mac)
394 {
395         if (curve->hash_len == 32)
396                 return sha256_vector(num_elem, addr, len, mac);
397         if (curve->hash_len == 48)
398                 return sha384_vector(num_elem, addr, len, mac);
399         if (curve->hash_len == 64)
400                 return sha512_vector(num_elem, addr, len, mac);
401         return -1;
402 }
403
404
405 static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
406                            const char *label, u8 *out, size_t outlen)
407 {
408         if (hash_len == 32)
409                 return hmac_sha256_kdf(secret, secret_len, NULL,
410                                        (const u8 *) label, os_strlen(label),
411                                        out, outlen);
412         if (hash_len == 48)
413                 return hmac_sha384_kdf(secret, secret_len, NULL,
414                                        (const u8 *) label, os_strlen(label),
415                                        out, outlen);
416         if (hash_len == 64)
417                 return hmac_sha512_kdf(secret, secret_len, NULL,
418                                        (const u8 *) label, os_strlen(label),
419                                        out, outlen);
420         return -1;
421 }
422
423
424 static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
425                            size_t num_elem, const u8 *addr[],
426                            const size_t *len, u8 *mac)
427 {
428         if (hash_len == 32)
429                 return hmac_sha256_vector(key, key_len, num_elem, addr, len,
430                                           mac);
431         if (hash_len == 48)
432                 return hmac_sha384_vector(key, key_len, num_elem, addr, len,
433                                           mac);
434         if (hash_len == 64)
435                 return hmac_sha512_vector(key, key_len, num_elem, addr, len,
436                                           mac);
437         return -1;
438 }
439
440
441 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
442                     const u8 *data, size_t data_len, u8 *mac)
443 {
444         if (hash_len == 32)
445                 return hmac_sha256(key, key_len, data, data_len, mac);
446         if (hash_len == 48)
447                 return hmac_sha384(key, key_len, data, data_len, mac);
448         if (hash_len == 64)
449                 return hmac_sha512(key, key_len, data, data_len, mac);
450         return -1;
451 }
452
453
454 static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
455 {
456         int num_bytes, offset;
457
458         num_bytes = BN_num_bytes(bn);
459         if ((size_t) num_bytes > len)
460                 return -1;
461         offset = len - num_bytes;
462         os_memset(pos, 0, offset);
463         BN_bn2bin(bn, pos + offset);
464         return 0;
465 }
466
467
468 static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
469 {
470         int len, res;
471         EC_KEY *eckey;
472         struct wpabuf *buf;
473         unsigned char *pos;
474
475         eckey = EVP_PKEY_get1_EC_KEY(pkey);
476         if (!eckey)
477                 return NULL;
478         EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
479         len = i2o_ECPublicKey(eckey, NULL);
480         if (len <= 0) {
481                 wpa_printf(MSG_ERROR,
482                            "DDP: Failed to determine public key encoding length");
483                 EC_KEY_free(eckey);
484                 return NULL;
485         }
486
487         buf = wpabuf_alloc(len);
488         if (!buf) {
489                 EC_KEY_free(eckey);
490                 return NULL;
491         }
492
493         pos = wpabuf_put(buf, len);
494         res = i2o_ECPublicKey(eckey, &pos);
495         EC_KEY_free(eckey);
496         if (res != len) {
497                 wpa_printf(MSG_ERROR,
498                            "DDP: Failed to encode public key (res=%d/%d)",
499                            res, len);
500                 wpabuf_free(buf);
501                 return NULL;
502         }
503
504         if (!prefix) {
505                 /* Remove 0x04 prefix to match DPP definition */
506                 pos = wpabuf_mhead(buf);
507                 os_memmove(pos, pos + 1, len - 1);
508                 buf->used--;
509         }
510
511         return buf;
512 }
513
514
515 static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
516                                              const u8 *buf_x, const u8 *buf_y,
517                                              size_t len)
518 {
519         EC_KEY *eckey = NULL;
520         BN_CTX *ctx;
521         EC_POINT *point = NULL;
522         BIGNUM *x = NULL, *y = NULL;
523         EVP_PKEY *pkey = NULL;
524
525         ctx = BN_CTX_new();
526         if (!ctx) {
527                 wpa_printf(MSG_ERROR, "DPP: Out of memory");
528                 return NULL;
529         }
530
531         point = EC_POINT_new(group);
532         x = BN_bin2bn(buf_x, len, NULL);
533         y = BN_bin2bn(buf_y, len, NULL);
534         if (!point || !x || !y) {
535                 wpa_printf(MSG_ERROR, "DPP: Out of memory");
536                 goto fail;
537         }
538
539         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
540                 wpa_printf(MSG_ERROR,
541                            "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
542                            ERR_error_string(ERR_get_error(), NULL));
543                 goto fail;
544         }
545
546         if (!EC_POINT_is_on_curve(group, point, ctx) ||
547             EC_POINT_is_at_infinity(group, point)) {
548                 wpa_printf(MSG_ERROR, "DPP: Invalid point");
549                 goto fail;
550         }
551         dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point);
552
553         eckey = EC_KEY_new();
554         if (!eckey ||
555             EC_KEY_set_group(eckey, group) != 1 ||
556             EC_KEY_set_public_key(eckey, point) != 1) {
557                 wpa_printf(MSG_ERROR,
558                            "DPP: Failed to set EC_KEY: %s",
559                            ERR_error_string(ERR_get_error(), NULL));
560                 goto fail;
561         }
562         EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
563
564         pkey = EVP_PKEY_new();
565         if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
566                 wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
567                 goto fail;
568         }
569
570 out:
571         BN_free(x);
572         BN_free(y);
573         EC_KEY_free(eckey);
574         EC_POINT_free(point);
575         BN_CTX_free(ctx);
576         return pkey;
577 fail:
578         EVP_PKEY_free(pkey);
579         pkey = NULL;
580         goto out;
581 }
582
583
584 static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key,
585                                        const u8 *buf, size_t len)
586 {
587         EC_KEY *eckey;
588         const EC_GROUP *group;
589         EVP_PKEY *pkey = NULL;
590
591         if (len & 1)
592                 return NULL;
593
594         eckey = EVP_PKEY_get1_EC_KEY(group_key);
595         if (!eckey) {
596                 wpa_printf(MSG_ERROR,
597                            "DPP: Could not get EC_KEY from group_key");
598                 return NULL;
599         }
600
601         group = EC_KEY_get0_group(eckey);
602         if (group)
603                 pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
604                                                   len / 2);
605         else
606                 wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
607
608         EC_KEY_free(eckey);
609         return pkey;
610 }
611
612
613 static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer,
614                     u8 *secret, size_t *secret_len)
615 {
616         EVP_PKEY_CTX *ctx;
617         int ret = -1;
618
619         ERR_clear_error();
620         *secret_len = 0;
621
622         ctx = EVP_PKEY_CTX_new(own, NULL);
623         if (!ctx) {
624                 wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
625                            ERR_error_string(ERR_get_error(), NULL));
626                 return -1;
627         }
628
629         if (EVP_PKEY_derive_init(ctx) != 1) {
630                 wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s",
631                            ERR_error_string(ERR_get_error(), NULL));
632                 goto fail;
633         }
634
635         if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) {
636                 wpa_printf(MSG_ERROR,
637                            "DPP: EVP_PKEY_derive_set_peet failed: %s",
638                            ERR_error_string(ERR_get_error(), NULL));
639                 goto fail;
640         }
641
642         if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) {
643                 wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s",
644                            ERR_error_string(ERR_get_error(), NULL));
645                 goto fail;
646         }
647
648         if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
649                 u8 buf[200];
650                 int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG;
651
652                 /* It looks like OpenSSL can return unexpectedly large buffer
653                  * need for shared secret from EVP_PKEY_derive(NULL) in some
654                  * cases. For example, group 19 has shown cases where secret_len
655                  * is set to 72 even though the actual length ends up being
656                  * updated to 32 when EVP_PKEY_derive() is called with a buffer
657                  * for the value. Work around this by trying to fetch the value
658                  * and continue if it is within supported range even when the
659                  * initial buffer need is claimed to be larger. */
660                 wpa_printf(level,
661                            "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
662                            (int) *secret_len);
663                 if (*secret_len > 200)
664                         goto fail;
665                 if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) {
666                         wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
667                                    ERR_error_string(ERR_get_error(), NULL));
668                         goto fail;
669                 }
670                 if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
671                         wpa_printf(MSG_ERROR,
672                                    "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
673                                    (int) *secret_len);
674                         goto fail;
675                 }
676                 wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change",
677                                 buf, *secret_len);
678                 os_memcpy(secret, buf, *secret_len);
679                 forced_memzero(buf, sizeof(buf));
680                 goto done;
681         }
682
683         if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) {
684                 wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
685                            ERR_error_string(ERR_get_error(), NULL));
686                 goto fail;
687         }
688
689 done:
690         ret = 0;
691
692 fail:
693         EVP_PKEY_CTX_free(ctx);
694         return ret;
695 }
696
697
698 static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
699 {
700         wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
701 }
702
703
704 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
705                               size_t len)
706 {
707         struct wpabuf *msg;
708
709         msg = wpabuf_alloc(8 + len);
710         if (!msg)
711                 return NULL;
712         wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
713         wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
714         wpabuf_put_be24(msg, OUI_WFA);
715         wpabuf_put_u8(msg, DPP_OUI_TYPE);
716         wpabuf_put_u8(msg, 1); /* Crypto Suite */
717         wpabuf_put_u8(msg, type);
718         return msg;
719 }
720
721
722 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
723 {
724         u16 id, alen;
725         const u8 *pos = buf, *end = buf + len;
726
727         while (end - pos >= 4) {
728                 id = WPA_GET_LE16(pos);
729                 pos += 2;
730                 alen = WPA_GET_LE16(pos);
731                 pos += 2;
732                 if (alen > end - pos)
733                         return NULL;
734                 if (id == req_id) {
735                         *ret_len = alen;
736                         return pos;
737                 }
738                 pos += alen;
739         }
740
741         return NULL;
742 }
743
744
745 int dpp_check_attrs(const u8 *buf, size_t len)
746 {
747         const u8 *pos, *end;
748         int wrapped_data = 0;
749
750         pos = buf;
751         end = buf + len;
752         while (end - pos >= 4) {
753                 u16 id, alen;
754
755                 id = WPA_GET_LE16(pos);
756                 pos += 2;
757                 alen = WPA_GET_LE16(pos);
758                 pos += 2;
759                 wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
760                            id, alen);
761                 if (alen > end - pos) {
762                         wpa_printf(MSG_DEBUG,
763                                    "DPP: Truncated message - not enough room for the attribute - dropped");
764                         return -1;
765                 }
766                 if (wrapped_data) {
767                         wpa_printf(MSG_DEBUG,
768                                    "DPP: An unexpected attribute included after the Wrapped Data attribute");
769                         return -1;
770                 }
771                 if (id == DPP_ATTR_WRAPPED_DATA)
772                         wrapped_data = 1;
773                 pos += alen;
774         }
775
776         if (end != pos) {
777                 wpa_printf(MSG_DEBUG,
778                            "DPP: Unexpected octets (%d) after the last attribute",
779                            (int) (end - pos));
780                 return -1;
781         }
782
783         return 0;
784 }
785
786
787 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
788 {
789         if (!info)
790                 return;
791         os_free(info->uri);
792         os_free(info->info);
793         EVP_PKEY_free(info->pubkey);
794         os_free(info);
795 }
796
797
798 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
799 {
800         switch (type) {
801         case DPP_BOOTSTRAP_QR_CODE:
802                 return "QRCODE";
803         case DPP_BOOTSTRAP_PKEX:
804                 return "PKEX";
805         }
806         return "??";
807 }
808
809
810 static int dpp_uri_valid_info(const char *info)
811 {
812         while (*info) {
813                 unsigned char val = *info++;
814
815                 if (val < 0x20 || val > 0x7e || val == 0x3b)
816                         return 0;
817         }
818
819         return 1;
820 }
821
822
823 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
824 {
825         bi->uri = os_strdup(uri);
826         return bi->uri ? 0 : -1;
827 }
828
829
830 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
831                             const char *chan_list)
832 {
833         const char *pos = chan_list, *pos2;
834         int opclass = -1, channel, freq;
835
836         while (pos && *pos && *pos != ';') {
837                 pos2 = pos;
838                 while (*pos2 >= '0' && *pos2 <= '9')
839                         pos2++;
840                 if (*pos2 == '/') {
841                         opclass = atoi(pos);
842                         pos = pos2 + 1;
843                 }
844                 if (opclass <= 0)
845                         goto fail;
846                 channel = atoi(pos);
847                 if (channel <= 0)
848                         goto fail;
849                 while (*pos >= '0' && *pos <= '9')
850                         pos++;
851                 freq = ieee80211_chan_to_freq(NULL, opclass, channel);
852                 wpa_printf(MSG_DEBUG,
853                            "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
854                            opclass, channel, freq);
855                 if (freq < 0) {
856                         wpa_printf(MSG_DEBUG,
857                                    "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
858                                    opclass, channel);
859                 } else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
860                         wpa_printf(MSG_DEBUG,
861                                    "DPP: Too many channels in URI channel-list - ignore list");
862                         bi->num_freq = 0;
863                         break;
864                 } else {
865                         bi->freq[bi->num_freq++] = freq;
866                 }
867
868                 if (*pos == ';' || *pos == '\0')
869                         break;
870                 if (*pos != ',')
871                         goto fail;
872                 pos++;
873         }
874
875         return 0;
876 fail:
877         wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
878         return -1;
879 }
880
881
882 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
883 {
884         if (!mac)
885                 return 0;
886
887         if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
888                 wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
889                 return -1;
890         }
891
892         wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
893
894         return 0;
895 }
896
897
898 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
899 {
900         const char *end;
901
902         if (!info)
903                 return 0;
904
905         end = os_strchr(info, ';');
906         if (!end)
907                 end = info + os_strlen(info);
908         bi->info = os_malloc(end - info + 1);
909         if (!bi->info)
910                 return -1;
911         os_memcpy(bi->info, info, end - info);
912         bi->info[end - info] = '\0';
913         wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
914         if (!dpp_uri_valid_info(bi->info)) {
915                 wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
916                 return -1;
917         }
918
919         return 0;
920 }
921
922
923 static const struct dpp_curve_params *
924 dpp_get_curve_oid(const ASN1_OBJECT *poid)
925 {
926         ASN1_OBJECT *oid;
927         int i;
928
929         for (i = 0; dpp_curves[i].name; i++) {
930                 oid = OBJ_txt2obj(dpp_curves[i].name, 0);
931                 if (oid && OBJ_cmp(poid, oid) == 0)
932                         return &dpp_curves[i];
933         }
934         return NULL;
935 }
936
937
938 static const struct dpp_curve_params * dpp_get_curve_nid(int nid)
939 {
940         int i, tmp;
941
942         if (!nid)
943                 return NULL;
944         for (i = 0; dpp_curves[i].name; i++) {
945                 tmp = OBJ_txt2nid(dpp_curves[i].name);
946                 if (tmp == nid)
947                         return &dpp_curves[i];
948         }
949         return NULL;
950 }
951
952
953 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
954 {
955         const char *end;
956         u8 *data;
957         size_t data_len;
958         EVP_PKEY *pkey;
959         const unsigned char *p;
960         int res;
961         X509_PUBKEY *pub = NULL;
962         ASN1_OBJECT *ppkalg;
963         const unsigned char *pk;
964         int ppklen;
965         X509_ALGOR *pa;
966 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
967         (defined(LIBRESSL_VERSION_NUMBER) && \
968          LIBRESSL_VERSION_NUMBER < 0x20800000L)
969         ASN1_OBJECT *pa_oid;
970 #else
971         const ASN1_OBJECT *pa_oid;
972 #endif
973         const void *pval;
974         int ptype;
975         const ASN1_OBJECT *poid;
976         char buf[100];
977
978         end = os_strchr(info, ';');
979         if (!end)
980                 return -1;
981
982         data = base64_decode((const unsigned char *) info, end - info,
983                              &data_len);
984         if (!data) {
985                 wpa_printf(MSG_DEBUG,
986                            "DPP: Invalid base64 encoding on URI public-key");
987                 return -1;
988         }
989         wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
990                     data, data_len);
991
992         if (sha256_vector(1, (const u8 **) &data, &data_len,
993                           bi->pubkey_hash) < 0) {
994                 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
995                 os_free(data);
996                 return -1;
997         }
998         wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
999                     bi->pubkey_hash, SHA256_MAC_LEN);
1000
1001         /* DER encoded ASN.1 SubjectPublicKeyInfo
1002          *
1003          * SubjectPublicKeyInfo  ::=  SEQUENCE  {
1004          *      algorithm            AlgorithmIdentifier,
1005          *      subjectPublicKey     BIT STRING  }
1006          *
1007          * AlgorithmIdentifier  ::=  SEQUENCE  {
1008          *      algorithm               OBJECT IDENTIFIER,
1009          *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
1010          *
1011          * subjectPublicKey = compressed format public key per ANSI X9.63
1012          * algorithm = ecPublicKey (1.2.840.10045.2.1)
1013          * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
1014          *       prime256v1 (1.2.840.10045.3.1.7)
1015          */
1016
1017         p = data;
1018         pkey = d2i_PUBKEY(NULL, &p, data_len);
1019         os_free(data);
1020
1021         if (!pkey) {
1022                 wpa_printf(MSG_DEBUG,
1023                            "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
1024                 return -1;
1025         }
1026
1027         if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
1028                 wpa_printf(MSG_DEBUG,
1029                            "DPP: SubjectPublicKeyInfo does not describe an EC key");
1030                 EVP_PKEY_free(pkey);
1031                 return -1;
1032         }
1033
1034         res = X509_PUBKEY_set(&pub, pkey);
1035         if (res != 1) {
1036                 wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
1037                 goto fail;
1038         }
1039
1040         res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
1041         if (res != 1) {
1042                 wpa_printf(MSG_DEBUG,
1043                            "DPP: Could not extract SubjectPublicKeyInfo parameters");
1044                 goto fail;
1045         }
1046         res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
1047         if (res < 0 || (size_t) res >= sizeof(buf)) {
1048                 wpa_printf(MSG_DEBUG,
1049                            "DPP: Could not extract SubjectPublicKeyInfo algorithm");
1050                 goto fail;
1051         }
1052         wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
1053         if (os_strcmp(buf, "id-ecPublicKey") != 0) {
1054                 wpa_printf(MSG_DEBUG,
1055                            "DPP: Unsupported SubjectPublicKeyInfo algorithm");
1056                 goto fail;
1057         }
1058
1059         X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
1060         if (ptype != V_ASN1_OBJECT) {
1061                 wpa_printf(MSG_DEBUG,
1062                            "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
1063                 goto fail;
1064         }
1065         poid = pval;
1066         res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
1067         if (res < 0 || (size_t) res >= sizeof(buf)) {
1068                 wpa_printf(MSG_DEBUG,
1069                            "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
1070                 goto fail;
1071         }
1072         wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
1073         bi->curve = dpp_get_curve_oid(poid);
1074         if (!bi->curve) {
1075                 wpa_printf(MSG_DEBUG,
1076                            "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
1077                            buf);
1078                 goto fail;
1079         }
1080
1081         wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
1082
1083         X509_PUBKEY_free(pub);
1084         bi->pubkey = pkey;
1085         return 0;
1086 fail:
1087         X509_PUBKEY_free(pub);
1088         EVP_PKEY_free(pkey);
1089         return -1;
1090 }
1091
1092
1093 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
1094 {
1095         const char *pos = uri;
1096         const char *end;
1097         const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
1098         struct dpp_bootstrap_info *bi;
1099
1100         wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
1101
1102         if (os_strncmp(pos, "DPP:", 4) != 0) {
1103                 wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
1104                 return NULL;
1105         }
1106         pos += 4;
1107
1108         for (;;) {
1109                 end = os_strchr(pos, ';');
1110                 if (!end)
1111                         break;
1112
1113                 if (end == pos) {
1114                         /* Handle terminating ";;" and ignore unexpected ";"
1115                          * for parsing robustness. */
1116                         pos++;
1117                         continue;
1118                 }
1119
1120                 if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
1121                         chan_list = pos + 2;
1122                 else if (pos[0] == 'M' && pos[1] == ':' && !mac)
1123                         mac = pos + 2;
1124                 else if (pos[0] == 'I' && pos[1] == ':' && !info)
1125                         info = pos + 2;
1126                 else if (pos[0] == 'K' && pos[1] == ':' && !pk)
1127                         pk = pos + 2;
1128                 else
1129                         wpa_hexdump_ascii(MSG_DEBUG,
1130                                           "DPP: Ignore unrecognized URI parameter",
1131                                           pos, end - pos);
1132                 pos = end + 1;
1133         }
1134
1135         if (!pk) {
1136                 wpa_printf(MSG_INFO, "DPP: URI missing public-key");
1137                 return NULL;
1138         }
1139
1140         bi = os_zalloc(sizeof(*bi));
1141         if (!bi)
1142                 return NULL;
1143
1144         if (dpp_clone_uri(bi, uri) < 0 ||
1145             dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
1146             dpp_parse_uri_mac(bi, mac) < 0 ||
1147             dpp_parse_uri_info(bi, info) < 0 ||
1148             dpp_parse_uri_pk(bi, pk) < 0) {
1149                 dpp_bootstrap_info_free(bi);
1150                 bi = NULL;
1151         }
1152
1153         return bi;
1154 }
1155
1156
1157 struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
1158 {
1159         struct dpp_bootstrap_info *bi;
1160
1161         bi = dpp_parse_uri(uri);
1162         if (bi)
1163                 bi->type = DPP_BOOTSTRAP_QR_CODE;
1164         return bi;
1165 }
1166
1167
1168 static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
1169 {
1170         EC_KEY *eckey;
1171         BIO *out;
1172         size_t rlen;
1173         char *txt;
1174         int res;
1175         unsigned char *der = NULL;
1176         int der_len;
1177         const EC_GROUP *group;
1178         const EC_POINT *point;
1179
1180         out = BIO_new(BIO_s_mem());
1181         if (!out)
1182                 return;
1183
1184         EVP_PKEY_print_private(out, key, 0, NULL);
1185         rlen = BIO_ctrl_pending(out);
1186         txt = os_malloc(rlen + 1);
1187         if (txt) {
1188                 res = BIO_read(out, txt, rlen);
1189                 if (res > 0) {
1190                         txt[res] = '\0';
1191                         wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
1192                 }
1193                 os_free(txt);
1194         }
1195         BIO_free(out);
1196
1197         eckey = EVP_PKEY_get1_EC_KEY(key);
1198         if (!eckey)
1199                 return;
1200
1201         group = EC_KEY_get0_group(eckey);
1202         point = EC_KEY_get0_public_key(eckey);
1203         if (group && point)
1204                 dpp_debug_print_point(title, group, point);
1205
1206         der_len = i2d_ECPrivateKey(eckey, &der);
1207         if (der_len > 0)
1208                 wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
1209         OPENSSL_free(der);
1210         if (der_len <= 0) {
1211                 der = NULL;
1212                 der_len = i2d_EC_PUBKEY(eckey, &der);
1213                 if (der_len > 0)
1214                         wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
1215                 OPENSSL_free(der);
1216         }
1217
1218         EC_KEY_free(eckey);
1219 }
1220
1221
1222 static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
1223 {
1224         EVP_PKEY_CTX *kctx = NULL;
1225         EC_KEY *ec_params = NULL;
1226         EVP_PKEY *params = NULL, *key = NULL;
1227         int nid;
1228
1229         wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
1230
1231         nid = OBJ_txt2nid(curve->name);
1232         if (nid == NID_undef) {
1233                 wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
1234                 return NULL;
1235         }
1236
1237         ec_params = EC_KEY_new_by_curve_name(nid);
1238         if (!ec_params) {
1239                 wpa_printf(MSG_ERROR,
1240                            "DPP: Failed to generate EC_KEY parameters");
1241                 goto fail;
1242         }
1243         EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
1244         params = EVP_PKEY_new();
1245         if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
1246                 wpa_printf(MSG_ERROR,
1247                            "DPP: Failed to generate EVP_PKEY parameters");
1248                 goto fail;
1249         }
1250
1251         kctx = EVP_PKEY_CTX_new(params, NULL);
1252         if (!kctx ||
1253             EVP_PKEY_keygen_init(kctx) != 1 ||
1254             EVP_PKEY_keygen(kctx, &key) != 1) {
1255                 wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
1256                 key = NULL;
1257                 goto fail;
1258         }
1259
1260         if (wpa_debug_show_keys)
1261                 dpp_debug_print_key("Own generated key", key);
1262
1263 fail:
1264         EC_KEY_free(ec_params);
1265         EVP_PKEY_free(params);
1266         EVP_PKEY_CTX_free(kctx);
1267         return key;
1268 }
1269
1270
1271 static const struct dpp_curve_params *
1272 dpp_get_curve_name(const char *name)
1273 {
1274         int i;
1275
1276         for (i = 0; dpp_curves[i].name; i++) {
1277                 if (os_strcmp(name, dpp_curves[i].name) == 0 ||
1278                     (dpp_curves[i].jwk_crv &&
1279                      os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
1280                         return &dpp_curves[i];
1281         }
1282         return NULL;
1283 }
1284
1285
1286 static const struct dpp_curve_params *
1287 dpp_get_curve_jwk_crv(const char *name)
1288 {
1289         int i;
1290
1291         for (i = 0; dpp_curves[i].name; i++) {
1292                 if (dpp_curves[i].jwk_crv &&
1293                     os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
1294                         return &dpp_curves[i];
1295         }
1296         return NULL;
1297 }
1298
1299
1300 static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
1301                                   const u8 *privkey, size_t privkey_len)
1302 {
1303         EVP_PKEY *pkey;
1304         EC_KEY *eckey;
1305         const EC_GROUP *group;
1306         int nid;
1307
1308         pkey = EVP_PKEY_new();
1309         if (!pkey)
1310                 return NULL;
1311         eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
1312         if (!eckey) {
1313                 wpa_printf(MSG_INFO,
1314                            "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
1315                            ERR_error_string(ERR_get_error(), NULL));
1316                 EVP_PKEY_free(pkey);
1317                 return NULL;
1318         }
1319         group = EC_KEY_get0_group(eckey);
1320         if (!group) {
1321                 EC_KEY_free(eckey);
1322                 EVP_PKEY_free(pkey);
1323                 return NULL;
1324         }
1325         nid = EC_GROUP_get_curve_name(group);
1326         *curve = dpp_get_curve_nid(nid);
1327         if (!*curve) {
1328                 wpa_printf(MSG_INFO,
1329                            "DPP: Unsupported curve (nid=%d) in pre-assigned key",
1330                            nid);
1331                 EC_KEY_free(eckey);
1332                 EVP_PKEY_free(pkey);
1333                 return NULL;
1334         }
1335
1336         if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
1337                 EC_KEY_free(eckey);
1338                 EVP_PKEY_free(pkey);
1339                 return NULL;
1340         }
1341         return pkey;
1342 }
1343
1344
1345 typedef struct {
1346         /* AlgorithmIdentifier ecPublicKey with optional parameters present
1347          * as an OID identifying the curve */
1348         X509_ALGOR *alg;
1349         /* Compressed format public key per ANSI X9.63 */
1350         ASN1_BIT_STRING *pub_key;
1351 } DPP_BOOTSTRAPPING_KEY;
1352
1353 ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = {
1354         ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR),
1355         ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING)
1356 } ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY);
1357
1358 IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
1359
1360
1361 static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key)
1362 {
1363         unsigned char *der = NULL;
1364         int der_len;
1365         EC_KEY *eckey;
1366         struct wpabuf *ret = NULL;
1367         size_t len;
1368         const EC_GROUP *group;
1369         const EC_POINT *point;
1370         BN_CTX *ctx;
1371         DPP_BOOTSTRAPPING_KEY *bootstrap = NULL;
1372         int nid;
1373
1374         ctx = BN_CTX_new();
1375         eckey = EVP_PKEY_get1_EC_KEY(key);
1376         if (!ctx || !eckey)
1377                 goto fail;
1378
1379         group = EC_KEY_get0_group(eckey);
1380         point = EC_KEY_get0_public_key(eckey);
1381         if (!group || !point)
1382                 goto fail;
1383         dpp_debug_print_point("DPP: bootstrap public key", group, point);
1384         nid = EC_GROUP_get_curve_name(group);
1385
1386         bootstrap = DPP_BOOTSTRAPPING_KEY_new();
1387         if (!bootstrap ||
1388             X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC),
1389                             V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
1390                 goto fail;
1391
1392         len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
1393                                  NULL, 0, ctx);
1394         if (len == 0)
1395                 goto fail;
1396
1397         der = OPENSSL_malloc(len);
1398         if (!der)
1399                 goto fail;
1400         len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
1401                                  der, len, ctx);
1402
1403         OPENSSL_free(bootstrap->pub_key->data);
1404         bootstrap->pub_key->data = der;
1405         der = NULL;
1406         bootstrap->pub_key->length = len;
1407         /* No unused bits */
1408         bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
1409         bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1410
1411         der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der);
1412         if (der_len <= 0) {
1413                 wpa_printf(MSG_ERROR,
1414                            "DDP: Failed to build DER encoded public key");
1415                 goto fail;
1416         }
1417
1418         ret = wpabuf_alloc_copy(der, der_len);
1419 fail:
1420         DPP_BOOTSTRAPPING_KEY_free(bootstrap);
1421         OPENSSL_free(der);
1422         EC_KEY_free(eckey);
1423         BN_CTX_free(ctx);
1424         return ret;
1425 }
1426
1427
1428 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
1429 {
1430         struct wpabuf *der;
1431         int res;
1432         const u8 *addr[1];
1433         size_t len[1];
1434
1435         der = dpp_bootstrap_key_der(bi->pubkey);
1436         if (!der)
1437                 return -1;
1438         wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
1439                         der);
1440
1441         addr[0] = wpabuf_head(der);
1442         len[0] = wpabuf_len(der);
1443         res = sha256_vector(1, addr, len, bi->pubkey_hash);
1444         if (res < 0)
1445                 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
1446         else
1447                 wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
1448                             SHA256_MAC_LEN);
1449         wpabuf_free(der);
1450         return res;
1451 }
1452
1453
1454 char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
1455                   const u8 *privkey, size_t privkey_len)
1456 {
1457         unsigned char *base64 = NULL;
1458         char *pos, *end;
1459         size_t len;
1460         struct wpabuf *der = NULL;
1461         const u8 *addr[1];
1462         int res;
1463
1464         if (!curve) {
1465                 bi->curve = &dpp_curves[0];
1466         } else {
1467                 bi->curve = dpp_get_curve_name(curve);
1468                 if (!bi->curve) {
1469                         wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
1470                                    curve);
1471                         return NULL;
1472                 }
1473         }
1474         if (privkey)
1475                 bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
1476         else
1477                 bi->pubkey = dpp_gen_keypair(bi->curve);
1478         if (!bi->pubkey)
1479                 goto fail;
1480         bi->own = 1;
1481
1482         der = dpp_bootstrap_key_der(bi->pubkey);
1483         if (!der)
1484                 goto fail;
1485         wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
1486                         der);
1487
1488         addr[0] = wpabuf_head(der);
1489         len = wpabuf_len(der);
1490         res = sha256_vector(1, addr, &len, bi->pubkey_hash);
1491         if (res < 0) {
1492                 wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
1493                 goto fail;
1494         }
1495         wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
1496                     SHA256_MAC_LEN);
1497
1498         base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
1499         wpabuf_free(der);
1500         der = NULL;
1501         if (!base64)
1502                 goto fail;
1503         pos = (char *) base64;
1504         end = pos + len;
1505         for (;;) {
1506                 pos = os_strchr(pos, '\n');
1507                 if (!pos)
1508                         break;
1509                 os_memmove(pos, pos + 1, end - pos);
1510         }
1511         return (char *) base64;
1512 fail:
1513         os_free(base64);
1514         wpabuf_free(der);
1515         return NULL;
1516 }
1517
1518
1519 static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
1520                          unsigned int hash_len)
1521 {
1522         u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1523         const char *info = "first intermediate key";
1524         int res;
1525
1526         /* k1 = HKDF(<>, "first intermediate key", M.x) */
1527
1528         /* HKDF-Extract(<>, M.x) */
1529         os_memset(salt, 0, hash_len);
1530         if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
1531                 return -1;
1532         wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
1533                         prk, hash_len);
1534
1535         /* HKDF-Expand(PRK, info, L) */
1536         res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
1537         os_memset(prk, 0, hash_len);
1538         if (res < 0)
1539                 return -1;
1540
1541         wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
1542                         k1, hash_len);
1543         return 0;
1544 }
1545
1546
1547 static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
1548                          unsigned int hash_len)
1549 {
1550         u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1551         const char *info = "second intermediate key";
1552         int res;
1553
1554         /* k2 = HKDF(<>, "second intermediate key", N.x) */
1555
1556         /* HKDF-Extract(<>, N.x) */
1557         os_memset(salt, 0, hash_len);
1558         res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
1559         if (res < 0)
1560                 return -1;
1561         wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1562                         prk, hash_len);
1563
1564         /* HKDF-Expand(PRK, info, L) */
1565         res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
1566         os_memset(prk, 0, hash_len);
1567         if (res < 0)
1568                 return -1;
1569
1570         wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
1571                         k2, hash_len);
1572         return 0;
1573 }
1574
1575
1576 static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
1577                          unsigned int hash_len)
1578 {
1579         size_t nonce_len;
1580         u8 nonces[2 * DPP_MAX_NONCE_LEN];
1581         const char *info_ke = "DPP Key";
1582         u8 prk[DPP_MAX_HASH_LEN];
1583         int res;
1584         const u8 *addr[3];
1585         size_t len[3];
1586         size_t num_elem = 0;
1587
1588         if (!auth->Mx_len || !auth->Nx_len) {
1589                 wpa_printf(MSG_DEBUG,
1590                            "DPP: Mx/Nx not available - cannot derive ke");
1591                 return -1;
1592         }
1593
1594         /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
1595
1596         /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
1597         nonce_len = auth->curve->nonce_len;
1598         os_memcpy(nonces, auth->i_nonce, nonce_len);
1599         os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
1600         addr[num_elem] = auth->Mx;
1601         len[num_elem] = auth->Mx_len;
1602         num_elem++;
1603         addr[num_elem] = auth->Nx;
1604         len[num_elem] = auth->Nx_len;
1605         num_elem++;
1606         if (auth->peer_bi && auth->own_bi) {
1607                 if (!auth->Lx_len) {
1608                         wpa_printf(MSG_DEBUG,
1609                                    "DPP: Lx not available - cannot derive ke");
1610                         return -1;
1611                 }
1612                 addr[num_elem] = auth->Lx;
1613                 len[num_elem] = auth->secret_len;
1614                 num_elem++;
1615         }
1616         res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
1617                               num_elem, addr, len, prk);
1618         if (res < 0)
1619                 return -1;
1620         wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1621                         prk, hash_len);
1622
1623         /* HKDF-Expand(PRK, info, L) */
1624         res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len);
1625         os_memset(prk, 0, hash_len);
1626         if (res < 0)
1627                 return -1;
1628
1629         wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
1630                         ke, hash_len);
1631         return 0;
1632 }
1633
1634
1635 static void dpp_build_attr_status(struct wpabuf *msg,
1636                                   enum dpp_status_error status)
1637 {
1638         wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
1639         wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1640         wpabuf_put_le16(msg, 1);
1641         wpabuf_put_u8(msg, status);
1642 }
1643
1644
1645 static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg,
1646                                                 const u8 *hash)
1647 {
1648         if (hash) {
1649                 wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash");
1650                 wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1651                 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1652                 wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
1653         }
1654 }
1655
1656
1657 static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg,
1658                                                 const u8 *hash)
1659 {
1660         if (hash) {
1661                 wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
1662                 wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1663                 wpabuf_put_le16(msg, SHA256_MAC_LEN);
1664                 wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
1665         }
1666 }
1667
1668
1669 static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
1670                                           const struct wpabuf *pi,
1671                                           size_t nonce_len,
1672                                           const u8 *r_pubkey_hash,
1673                                           const u8 *i_pubkey_hash,
1674                                           unsigned int neg_freq)
1675 {
1676         struct wpabuf *msg;
1677         u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
1678         u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
1679         u8 *pos;
1680         const u8 *addr[2];
1681         size_t len[2], siv_len, attr_len;
1682         u8 *attr_start, *attr_end;
1683
1684         /* Build DPP Authentication Request frame attributes */
1685         attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) +
1686                 4 + sizeof(wrapped_data);
1687         if (neg_freq > 0)
1688                 attr_len += 4 + 2;
1689 #ifdef CONFIG_DPP2
1690         attr_len += 5;
1691 #endif /* CONFIG_DPP2 */
1692 #ifdef CONFIG_TESTING_OPTIONS
1693         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
1694                 attr_len += 5;
1695 #endif /* CONFIG_TESTING_OPTIONS */
1696         msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
1697         if (!msg)
1698                 return NULL;
1699
1700         attr_start = wpabuf_put(msg, 0);
1701
1702         /* Responder Bootstrapping Key Hash */
1703         dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
1704
1705         /* Initiator Bootstrapping Key Hash */
1706         dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
1707
1708         /* Initiator Protocol Key */
1709         if (pi) {
1710                 wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
1711                 wpabuf_put_le16(msg, wpabuf_len(pi));
1712                 wpabuf_put_buf(msg, pi);
1713         }
1714
1715         /* Channel */
1716         if (neg_freq > 0) {
1717                 u8 op_class, channel;
1718
1719                 if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class,
1720                                                   &channel) ==
1721                     NUM_HOSTAPD_MODES) {
1722                         wpa_printf(MSG_INFO,
1723                                    "DPP: Unsupported negotiation frequency request: %d",
1724                                    neg_freq);
1725                         wpabuf_free(msg);
1726                         return NULL;
1727                 }
1728                 wpabuf_put_le16(msg, DPP_ATTR_CHANNEL);
1729                 wpabuf_put_le16(msg, 2);
1730                 wpabuf_put_u8(msg, op_class);
1731                 wpabuf_put_u8(msg, channel);
1732         }
1733
1734 #ifdef CONFIG_DPP2
1735         /* Protocol Version */
1736         wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1737         wpabuf_put_le16(msg, 1);
1738         wpabuf_put_u8(msg, 2);
1739 #endif /* CONFIG_DPP2 */
1740
1741 #ifdef CONFIG_TESTING_OPTIONS
1742         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) {
1743                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
1744                 goto skip_wrapped_data;
1745         }
1746 #endif /* CONFIG_TESTING_OPTIONS */
1747
1748         /* Wrapped data ({I-nonce, I-capabilities}k1) */
1749         pos = clear;
1750
1751 #ifdef CONFIG_TESTING_OPTIONS
1752         if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) {
1753                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
1754                 goto skip_i_nonce;
1755         }
1756         if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) {
1757                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce");
1758                 WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1759                 pos += 2;
1760                 WPA_PUT_LE16(pos, nonce_len - 1);
1761                 pos += 2;
1762                 os_memcpy(pos, auth->i_nonce, nonce_len - 1);
1763                 pos += nonce_len - 1;
1764                 goto skip_i_nonce;
1765         }
1766 #endif /* CONFIG_TESTING_OPTIONS */
1767
1768         /* I-nonce */
1769         WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1770         pos += 2;
1771         WPA_PUT_LE16(pos, nonce_len);
1772         pos += 2;
1773         os_memcpy(pos, auth->i_nonce, nonce_len);
1774         pos += nonce_len;
1775
1776 #ifdef CONFIG_TESTING_OPTIONS
1777 skip_i_nonce:
1778         if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) {
1779                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab");
1780                 goto skip_i_capab;
1781         }
1782 #endif /* CONFIG_TESTING_OPTIONS */
1783
1784         /* I-capabilities */
1785         WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
1786         pos += 2;
1787         WPA_PUT_LE16(pos, 1);
1788         pos += 2;
1789         auth->i_capab = auth->allowed_roles;
1790         *pos++ = auth->i_capab;
1791 #ifdef CONFIG_TESTING_OPTIONS
1792         if (dpp_test == DPP_TEST_ZERO_I_CAPAB) {
1793                 wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities");
1794                 pos[-1] = 0;
1795         }
1796 skip_i_capab:
1797 #endif /* CONFIG_TESTING_OPTIONS */
1798
1799         attr_end = wpabuf_put(msg, 0);
1800
1801         /* OUI, OUI type, Crypto Suite, DPP frame type */
1802         addr[0] = wpabuf_head_u8(msg) + 2;
1803         len[0] = 3 + 1 + 1 + 1;
1804         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1805
1806         /* Attributes before Wrapped Data */
1807         addr[1] = attr_start;
1808         len[1] = attr_end - attr_start;
1809         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1810
1811         siv_len = pos - clear;
1812         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1813         if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
1814                             2, addr, len, wrapped_data) < 0) {
1815                 wpabuf_free(msg);
1816                 return NULL;
1817         }
1818         siv_len += AES_BLOCK_SIZE;
1819         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1820                     wrapped_data, siv_len);
1821
1822         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1823         wpabuf_put_le16(msg, siv_len);
1824         wpabuf_put_data(msg, wrapped_data, siv_len);
1825
1826 #ifdef CONFIG_TESTING_OPTIONS
1827         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) {
1828                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
1829                 dpp_build_attr_status(msg, DPP_STATUS_OK);
1830         }
1831 skip_wrapped_data:
1832 #endif /* CONFIG_TESTING_OPTIONS */
1833
1834         wpa_hexdump_buf(MSG_DEBUG,
1835                         "DPP: Authentication Request frame attributes", msg);
1836
1837         return msg;
1838 }
1839
1840
1841 static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth,
1842                                            enum dpp_status_error status,
1843                                            const struct wpabuf *pr,
1844                                            size_t nonce_len,
1845                                            const u8 *r_pubkey_hash,
1846                                            const u8 *i_pubkey_hash,
1847                                            const u8 *r_nonce, const u8 *i_nonce,
1848                                            const u8 *wrapped_r_auth,
1849                                            size_t wrapped_r_auth_len,
1850                                            const u8 *siv_key)
1851 {
1852         struct wpabuf *msg;
1853 #define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
1854                 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE
1855         u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
1856         u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
1857         const u8 *addr[2];
1858         size_t len[2], siv_len, attr_len;
1859         u8 *attr_start, *attr_end, *pos;
1860
1861         auth->waiting_auth_conf = 1;
1862         auth->auth_resp_tries = 0;
1863
1864         /* Build DPP Authentication Response frame attributes */
1865         attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1866                 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data);
1867 #ifdef CONFIG_DPP2
1868         attr_len += 5;
1869 #endif /* CONFIG_DPP2 */
1870 #ifdef CONFIG_TESTING_OPTIONS
1871         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP)
1872                 attr_len += 5;
1873 #endif /* CONFIG_TESTING_OPTIONS */
1874         msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
1875         if (!msg)
1876                 return NULL;
1877
1878         attr_start = wpabuf_put(msg, 0);
1879
1880         /* DPP Status */
1881         if (status != 255)
1882                 dpp_build_attr_status(msg, status);
1883
1884         /* Responder Bootstrapping Key Hash */
1885         dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
1886
1887         /* Initiator Bootstrapping Key Hash (mutual authentication) */
1888         dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
1889
1890         /* Responder Protocol Key */
1891         if (pr) {
1892                 wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
1893                 wpabuf_put_le16(msg, wpabuf_len(pr));
1894                 wpabuf_put_buf(msg, pr);
1895         }
1896
1897 #ifdef CONFIG_DPP2
1898         /* Protocol Version */
1899         wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1900         wpabuf_put_le16(msg, 1);
1901         wpabuf_put_u8(msg, 2);
1902 #endif /* CONFIG_DPP2 */
1903
1904         attr_end = wpabuf_put(msg, 0);
1905
1906 #ifdef CONFIG_TESTING_OPTIONS
1907         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) {
1908                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
1909                 goto skip_wrapped_data;
1910         }
1911 #endif /* CONFIG_TESTING_OPTIONS */
1912
1913         /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
1914         pos = clear;
1915
1916         if (r_nonce) {
1917                 /* R-nonce */
1918                 WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
1919                 pos += 2;
1920                 WPA_PUT_LE16(pos, nonce_len);
1921                 pos += 2;
1922                 os_memcpy(pos, r_nonce, nonce_len);
1923                 pos += nonce_len;
1924         }
1925
1926         if (i_nonce) {
1927                 /* I-nonce */
1928                 WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1929                 pos += 2;
1930                 WPA_PUT_LE16(pos, nonce_len);
1931                 pos += 2;
1932                 os_memcpy(pos, i_nonce, nonce_len);
1933 #ifdef CONFIG_TESTING_OPTIONS
1934                 if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) {
1935                         wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch");
1936                         pos[nonce_len / 2] ^= 0x01;
1937                 }
1938 #endif /* CONFIG_TESTING_OPTIONS */
1939                 pos += nonce_len;
1940         }
1941
1942 #ifdef CONFIG_TESTING_OPTIONS
1943         if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) {
1944                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab");
1945                 goto skip_r_capab;
1946         }
1947 #endif /* CONFIG_TESTING_OPTIONS */
1948
1949         /* R-capabilities */
1950         WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
1951         pos += 2;
1952         WPA_PUT_LE16(pos, 1);
1953         pos += 2;
1954         auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
1955                 DPP_CAPAB_ENROLLEE;
1956         *pos++ = auth->r_capab;
1957 #ifdef CONFIG_TESTING_OPTIONS
1958         if (dpp_test == DPP_TEST_ZERO_R_CAPAB) {
1959                 wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities");
1960                 pos[-1] = 0;
1961         } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) {
1962                 wpa_printf(MSG_INFO,
1963                            "DPP: TESTING - incompatible R-capabilities");
1964                 if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) ==
1965                     (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE))
1966                         pos[-1] = 0;
1967                 else
1968                         pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE :
1969                                 DPP_CAPAB_CONFIGURATOR;
1970         }
1971 skip_r_capab:
1972 #endif /* CONFIG_TESTING_OPTIONS */
1973
1974         if (wrapped_r_auth) {
1975                 /* {R-auth}ke */
1976                 WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
1977                 pos += 2;
1978                 WPA_PUT_LE16(pos, wrapped_r_auth_len);
1979                 pos += 2;
1980                 os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
1981                 pos += wrapped_r_auth_len;
1982         }
1983
1984         /* OUI, OUI type, Crypto Suite, DPP frame type */
1985         addr[0] = wpabuf_head_u8(msg) + 2;
1986         len[0] = 3 + 1 + 1 + 1;
1987         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1988
1989         /* Attributes before Wrapped Data */
1990         addr[1] = attr_start;
1991         len[1] = attr_end - attr_start;
1992         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1993
1994         siv_len = pos - clear;
1995         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1996         if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len,
1997                             2, addr, len, wrapped_data) < 0) {
1998                 wpabuf_free(msg);
1999                 return NULL;
2000         }
2001         siv_len += AES_BLOCK_SIZE;
2002         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2003                     wrapped_data, siv_len);
2004
2005         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2006         wpabuf_put_le16(msg, siv_len);
2007         wpabuf_put_data(msg, wrapped_data, siv_len);
2008
2009 #ifdef CONFIG_TESTING_OPTIONS
2010         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) {
2011                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
2012                 dpp_build_attr_status(msg, DPP_STATUS_OK);
2013         }
2014 skip_wrapped_data:
2015 #endif /* CONFIG_TESTING_OPTIONS */
2016
2017         wpa_hexdump_buf(MSG_DEBUG,
2018                         "DPP: Authentication Response frame attributes", msg);
2019         return msg;
2020 }
2021
2022
2023 static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
2024                                u16 num_modes, unsigned int freq)
2025 {
2026         u16 m;
2027         int c, flag;
2028
2029         if (!own_modes || !num_modes)
2030                 return 1;
2031
2032         for (m = 0; m < num_modes; m++) {
2033                 for (c = 0; c < own_modes[m].num_channels; c++) {
2034                         if ((unsigned int) own_modes[m].channels[c].freq !=
2035                             freq)
2036                                 continue;
2037                         flag = own_modes[m].channels[c].flag;
2038                         if (!(flag & (HOSTAPD_CHAN_DISABLED |
2039                                       HOSTAPD_CHAN_NO_IR |
2040                                       HOSTAPD_CHAN_RADAR)))
2041                                 return 1;
2042                 }
2043         }
2044
2045         wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
2046         return 0;
2047 }
2048
2049
2050 static int freq_included(const unsigned int freqs[], unsigned int num,
2051                          unsigned int freq)
2052 {
2053         while (num > 0) {
2054                 if (freqs[--num] == freq)
2055                         return 1;
2056         }
2057         return 0;
2058 }
2059
2060
2061 static void freq_to_start(unsigned int freqs[], unsigned int num,
2062                           unsigned int freq)
2063 {
2064         unsigned int i;
2065
2066         for (i = 0; i < num; i++) {
2067                 if (freqs[i] == freq)
2068                         break;
2069         }
2070         if (i == 0 || i >= num)
2071                 return;
2072         os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
2073         freqs[0] = freq;
2074 }
2075
2076
2077 static int dpp_channel_intersect(struct dpp_authentication *auth,
2078                                  struct hostapd_hw_modes *own_modes,
2079                                  u16 num_modes)
2080 {
2081         struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
2082         unsigned int i, freq;
2083
2084         for (i = 0; i < peer_bi->num_freq; i++) {
2085                 freq = peer_bi->freq[i];
2086                 if (freq_included(auth->freq, auth->num_freq, freq))
2087                         continue;
2088                 if (dpp_channel_ok_init(own_modes, num_modes, freq))
2089                         auth->freq[auth->num_freq++] = freq;
2090         }
2091         if (!auth->num_freq) {
2092                 wpa_printf(MSG_INFO,
2093                            "DPP: No available channels for initiating DPP Authentication");
2094                 return -1;
2095         }
2096         auth->curr_freq = auth->freq[0];
2097         return 0;
2098 }
2099
2100
2101 static int dpp_channel_local_list(struct dpp_authentication *auth,
2102                                   struct hostapd_hw_modes *own_modes,
2103                                   u16 num_modes)
2104 {
2105         u16 m;
2106         int c, flag;
2107         unsigned int freq;
2108
2109         auth->num_freq = 0;
2110
2111         if (!own_modes || !num_modes) {
2112                 auth->freq[0] = 2412;
2113                 auth->freq[1] = 2437;
2114                 auth->freq[2] = 2462;
2115                 auth->num_freq = 3;
2116                 return 0;
2117         }
2118
2119         for (m = 0; m < num_modes; m++) {
2120                 for (c = 0; c < own_modes[m].num_channels; c++) {
2121                         freq = own_modes[m].channels[c].freq;
2122                         flag = own_modes[m].channels[c].flag;
2123                         if (flag & (HOSTAPD_CHAN_DISABLED |
2124                                     HOSTAPD_CHAN_NO_IR |
2125                                     HOSTAPD_CHAN_RADAR))
2126                                 continue;
2127                         if (freq_included(auth->freq, auth->num_freq, freq))
2128                                 continue;
2129                         auth->freq[auth->num_freq++] = freq;
2130                         if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
2131                                 m = num_modes;
2132                                 break;
2133                         }
2134                 }
2135         }
2136
2137         return auth->num_freq == 0 ? -1 : 0;
2138 }
2139
2140
2141 static int dpp_prepare_channel_list(struct dpp_authentication *auth,
2142                                     struct hostapd_hw_modes *own_modes,
2143                                     u16 num_modes)
2144 {
2145         int res;
2146         char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
2147         unsigned int i;
2148
2149         if (auth->peer_bi->num_freq > 0)
2150                 res = dpp_channel_intersect(auth, own_modes, num_modes);
2151         else
2152                 res = dpp_channel_local_list(auth, own_modes, num_modes);
2153         if (res < 0)
2154                 return res;
2155
2156         /* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
2157          * likely channels first. */
2158         freq_to_start(auth->freq, auth->num_freq, 2462);
2159         freq_to_start(auth->freq, auth->num_freq, 2412);
2160         freq_to_start(auth->freq, auth->num_freq, 2437);
2161
2162         auth->freq_idx = 0;
2163         auth->curr_freq = auth->freq[0];
2164
2165         pos = freqs;
2166         end = pos + sizeof(freqs);
2167         for (i = 0; i < auth->num_freq; i++) {
2168                 res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
2169                 if (os_snprintf_error(end - pos, res))
2170                         break;
2171                 pos += res;
2172         }
2173         *pos = '\0';
2174         wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
2175                    freqs);
2176
2177         return 0;
2178 }
2179
2180
2181 static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
2182 {
2183         struct dpp_bootstrap_info *bi;
2184         char *pk = NULL;
2185         size_t len;
2186
2187         if (auth->own_bi)
2188                 return 0; /* already generated */
2189
2190         bi = os_zalloc(sizeof(*bi));
2191         if (!bi)
2192                 return -1;
2193         bi->type = DPP_BOOTSTRAP_QR_CODE;
2194         pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0);
2195         if (!pk)
2196                 goto fail;
2197
2198         len = 4; /* "DPP:" */
2199         len += 4 + os_strlen(pk);
2200         bi->uri = os_malloc(len + 1);
2201         if (!bi->uri)
2202                 goto fail;
2203         os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk);
2204         wpa_printf(MSG_DEBUG,
2205                    "DPP: Auto-generated own bootstrapping key info: URI %s",
2206                    bi->uri);
2207
2208         auth->tmp_own_bi = auth->own_bi = bi;
2209
2210         os_free(pk);
2211
2212         return 0;
2213 fail:
2214         os_free(pk);
2215         dpp_bootstrap_info_free(bi);
2216         return -1;
2217 }
2218
2219
2220 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
2221                                           struct dpp_bootstrap_info *peer_bi,
2222                                           struct dpp_bootstrap_info *own_bi,
2223                                           u8 dpp_allowed_roles,
2224                                           unsigned int neg_freq,
2225                                           struct hostapd_hw_modes *own_modes,
2226                                           u16 num_modes)
2227 {
2228         struct dpp_authentication *auth;
2229         size_t nonce_len;
2230         size_t secret_len;
2231         struct wpabuf *pi = NULL;
2232         const u8 *r_pubkey_hash, *i_pubkey_hash;
2233 #ifdef CONFIG_TESTING_OPTIONS
2234         u8 test_hash[SHA256_MAC_LEN];
2235 #endif /* CONFIG_TESTING_OPTIONS */
2236
2237         auth = os_zalloc(sizeof(*auth));
2238         if (!auth)
2239                 return NULL;
2240         auth->msg_ctx = msg_ctx;
2241         auth->initiator = 1;
2242         auth->waiting_auth_resp = 1;
2243         auth->allowed_roles = dpp_allowed_roles;
2244         auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR);
2245         auth->peer_bi = peer_bi;
2246         auth->own_bi = own_bi;
2247         auth->curve = peer_bi->curve;
2248
2249         if (dpp_autogen_bootstrap_key(auth) < 0 ||
2250             dpp_prepare_channel_list(auth, own_modes, num_modes) < 0)
2251                 goto fail;
2252
2253 #ifdef CONFIG_TESTING_OPTIONS
2254         if (dpp_nonce_override_len > 0) {
2255                 wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce");
2256                 nonce_len = dpp_nonce_override_len;
2257                 os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len);
2258         } else {
2259                 nonce_len = auth->curve->nonce_len;
2260                 if (random_get_bytes(auth->i_nonce, nonce_len)) {
2261                         wpa_printf(MSG_ERROR,
2262                                    "DPP: Failed to generate I-nonce");
2263                         goto fail;
2264                 }
2265         }
2266 #else /* CONFIG_TESTING_OPTIONS */
2267         nonce_len = auth->curve->nonce_len;
2268         if (random_get_bytes(auth->i_nonce, nonce_len)) {
2269                 wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
2270                 goto fail;
2271         }
2272 #endif /* CONFIG_TESTING_OPTIONS */
2273         wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
2274
2275 #ifdef CONFIG_TESTING_OPTIONS
2276         if (dpp_protocol_key_override_len) {
2277                 const struct dpp_curve_params *tmp_curve;
2278
2279                 wpa_printf(MSG_INFO,
2280                            "DPP: TESTING - override protocol key");
2281                 auth->own_protocol_key = dpp_set_keypair(
2282                         &tmp_curve, dpp_protocol_key_override,
2283                         dpp_protocol_key_override_len);
2284         } else {
2285                 auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2286         }
2287 #else /* CONFIG_TESTING_OPTIONS */
2288         auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2289 #endif /* CONFIG_TESTING_OPTIONS */
2290         if (!auth->own_protocol_key)
2291                 goto fail;
2292
2293         pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2294         if (!pi)
2295                 goto fail;
2296
2297         /* ECDH: M = pI * BR */
2298         if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey,
2299                      auth->Mx, &secret_len) < 0)
2300                 goto fail;
2301         auth->secret_len = secret_len;
2302
2303         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
2304                         auth->Mx, auth->secret_len);
2305         auth->Mx_len = auth->secret_len;
2306
2307         if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
2308                           auth->curve->hash_len) < 0)
2309                 goto fail;
2310
2311         r_pubkey_hash = auth->peer_bi->pubkey_hash;
2312         i_pubkey_hash = auth->own_bi->pubkey_hash;
2313
2314 #ifdef CONFIG_TESTING_OPTIONS
2315         if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
2316                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
2317                 r_pubkey_hash = NULL;
2318         } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
2319                 wpa_printf(MSG_INFO,
2320                            "DPP: TESTING - invalid R-Bootstrap Key Hash");
2321                 os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
2322                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2323                 r_pubkey_hash = test_hash;
2324         } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
2325                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
2326                 i_pubkey_hash = NULL;
2327         } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
2328                 wpa_printf(MSG_INFO,
2329                            "DPP: TESTING - invalid I-Bootstrap Key Hash");
2330                 os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
2331                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2332                 i_pubkey_hash = test_hash;
2333         } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) {
2334                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key");
2335                 wpabuf_free(pi);
2336                 pi = NULL;
2337         } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) {
2338                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key");
2339                 wpabuf_free(pi);
2340                 pi = wpabuf_alloc(2 * auth->curve->prime_len);
2341                 if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0)
2342                         goto fail;
2343         }
2344 #endif /* CONFIG_TESTING_OPTIONS */
2345
2346         auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash,
2347                                            i_pubkey_hash, neg_freq);
2348         if (!auth->req_msg)
2349                 goto fail;
2350
2351 out:
2352         wpabuf_free(pi);
2353         return auth;
2354 fail:
2355         dpp_auth_deinit(auth);
2356         auth = NULL;
2357         goto out;
2358 }
2359
2360
2361 static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
2362                                                const char *json)
2363 {
2364         size_t nonce_len;
2365         size_t json_len, clear_len;
2366         struct wpabuf *clear = NULL, *msg = NULL;
2367         u8 *wrapped;
2368         size_t attr_len;
2369
2370         wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
2371
2372         nonce_len = auth->curve->nonce_len;
2373         if (random_get_bytes(auth->e_nonce, nonce_len)) {
2374                 wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
2375                 goto fail;
2376         }
2377         wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
2378         json_len = os_strlen(json);
2379         wpa_hexdump_ascii(MSG_DEBUG, "DPP: configAttr JSON", json, json_len);
2380
2381         /* { E-nonce, configAttrib }ke */
2382         clear_len = 4 + nonce_len + 4 + json_len;
2383         clear = wpabuf_alloc(clear_len);
2384         attr_len = 4 + clear_len + AES_BLOCK_SIZE;
2385 #ifdef CONFIG_TESTING_OPTIONS
2386         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
2387                 attr_len += 5;
2388 #endif /* CONFIG_TESTING_OPTIONS */
2389         msg = wpabuf_alloc(attr_len);
2390         if (!clear || !msg)
2391                 goto fail;
2392
2393 #ifdef CONFIG_TESTING_OPTIONS
2394         if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) {
2395                 wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
2396                 goto skip_e_nonce;
2397         }
2398         if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) {
2399                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce");
2400                 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2401                 wpabuf_put_le16(clear, nonce_len - 1);
2402                 wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1);
2403                 goto skip_e_nonce;
2404         }
2405         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) {
2406                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
2407                 goto skip_wrapped_data;
2408         }
2409 #endif /* CONFIG_TESTING_OPTIONS */
2410
2411         /* E-nonce */
2412         wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2413         wpabuf_put_le16(clear, nonce_len);
2414         wpabuf_put_data(clear, auth->e_nonce, nonce_len);
2415
2416 #ifdef CONFIG_TESTING_OPTIONS
2417 skip_e_nonce:
2418         if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) {
2419                 wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib");
2420                 goto skip_conf_attr_obj;
2421         }
2422 #endif /* CONFIG_TESTING_OPTIONS */
2423
2424         /* configAttrib */
2425         wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
2426         wpabuf_put_le16(clear, json_len);
2427         wpabuf_put_data(clear, json, json_len);
2428
2429 #ifdef CONFIG_TESTING_OPTIONS
2430 skip_conf_attr_obj:
2431 #endif /* CONFIG_TESTING_OPTIONS */
2432
2433         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2434         wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2435         wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2436
2437         /* No AES-SIV AD */
2438         wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
2439         if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2440                             wpabuf_head(clear), wpabuf_len(clear),
2441                             0, NULL, NULL, wrapped) < 0)
2442                 goto fail;
2443         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2444                     wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
2445
2446 #ifdef CONFIG_TESTING_OPTIONS
2447         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) {
2448                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
2449                 dpp_build_attr_status(msg, DPP_STATUS_OK);
2450         }
2451 skip_wrapped_data:
2452 #endif /* CONFIG_TESTING_OPTIONS */
2453
2454         wpa_hexdump_buf(MSG_DEBUG,
2455                         "DPP: Configuration Request frame attributes", msg);
2456         wpabuf_free(clear);
2457         return msg;
2458
2459 fail:
2460         wpabuf_free(clear);
2461         wpabuf_free(msg);
2462         return NULL;
2463 }
2464
2465
2466 static void dpp_write_adv_proto(struct wpabuf *buf)
2467 {
2468         /* Advertisement Protocol IE */
2469         wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
2470         wpabuf_put_u8(buf, 8); /* Length */
2471         wpabuf_put_u8(buf, 0x7f);
2472         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
2473         wpabuf_put_u8(buf, 5);
2474         wpabuf_put_be24(buf, OUI_WFA);
2475         wpabuf_put_u8(buf, DPP_OUI_TYPE);
2476         wpabuf_put_u8(buf, 0x01);
2477 }
2478
2479
2480 static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
2481 {
2482         /* GAS Query */
2483         wpabuf_put_le16(buf, wpabuf_len(query));
2484         wpabuf_put_buf(buf, query);
2485 }
2486
2487
2488 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
2489                                    const char *json)
2490 {
2491         struct wpabuf *buf, *conf_req;
2492
2493         conf_req = dpp_build_conf_req_attr(auth, json);
2494         if (!conf_req) {
2495                 wpa_printf(MSG_DEBUG,
2496                            "DPP: No configuration request data available");
2497                 return NULL;
2498         }
2499
2500         buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
2501         if (!buf) {
2502                 wpabuf_free(conf_req);
2503                 return NULL;
2504         }
2505
2506         dpp_write_adv_proto(buf);
2507         dpp_write_gas_query(buf, conf_req);
2508         wpabuf_free(conf_req);
2509         wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf);
2510
2511         return buf;
2512 }
2513
2514
2515 static void dpp_auth_success(struct dpp_authentication *auth)
2516 {
2517         wpa_printf(MSG_DEBUG,
2518                    "DPP: Authentication success - clear temporary keys");
2519         os_memset(auth->Mx, 0, sizeof(auth->Mx));
2520         auth->Mx_len = 0;
2521         os_memset(auth->Nx, 0, sizeof(auth->Nx));
2522         auth->Nx_len = 0;
2523         os_memset(auth->Lx, 0, sizeof(auth->Lx));
2524         auth->Lx_len = 0;
2525         os_memset(auth->k1, 0, sizeof(auth->k1));
2526         os_memset(auth->k2, 0, sizeof(auth->k2));
2527
2528         auth->auth_success = 1;
2529 }
2530
2531
2532 static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
2533 {
2534         struct wpabuf *pix, *prx, *bix, *brx;
2535         const u8 *addr[7];
2536         size_t len[7];
2537         size_t i, num_elem = 0;
2538         size_t nonce_len;
2539         u8 zero = 0;
2540         int res = -1;
2541
2542         /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
2543         nonce_len = auth->curve->nonce_len;
2544
2545         if (auth->initiator) {
2546                 pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2547                 prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
2548                 if (auth->own_bi)
2549                         bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
2550                 else
2551                         bix = NULL;
2552                 brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
2553         } else {
2554                 pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
2555                 prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2556                 if (auth->peer_bi)
2557                         bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
2558                 else
2559                         bix = NULL;
2560                 brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
2561         }
2562         if (!pix || !prx || !brx)
2563                 goto fail;
2564
2565         addr[num_elem] = auth->i_nonce;
2566         len[num_elem] = nonce_len;
2567         num_elem++;
2568
2569         addr[num_elem] = auth->r_nonce;
2570         len[num_elem] = nonce_len;
2571         num_elem++;
2572
2573         addr[num_elem] = wpabuf_head(pix);
2574         len[num_elem] = wpabuf_len(pix) / 2;
2575         num_elem++;
2576
2577         addr[num_elem] = wpabuf_head(prx);
2578         len[num_elem] = wpabuf_len(prx) / 2;
2579         num_elem++;
2580
2581         if (bix) {
2582                 addr[num_elem] = wpabuf_head(bix);
2583                 len[num_elem] = wpabuf_len(bix) / 2;
2584                 num_elem++;
2585         }
2586
2587         addr[num_elem] = wpabuf_head(brx);
2588         len[num_elem] = wpabuf_len(brx) / 2;
2589         num_elem++;
2590
2591         addr[num_elem] = &zero;
2592         len[num_elem] = 1;
2593         num_elem++;
2594
2595         wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
2596         for (i = 0; i < num_elem; i++)
2597                 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
2598         res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
2599         if (res == 0)
2600                 wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
2601                             auth->curve->hash_len);
2602 fail:
2603         wpabuf_free(pix);
2604         wpabuf_free(prx);
2605         wpabuf_free(bix);
2606         wpabuf_free(brx);
2607         return res;
2608 }
2609
2610
2611 static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
2612 {
2613         struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
2614         const u8 *addr[7];
2615         size_t len[7];
2616         size_t i, num_elem = 0;
2617         size_t nonce_len;
2618         u8 one = 1;
2619         int res = -1;
2620
2621         /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
2622         nonce_len = auth->curve->nonce_len;
2623
2624         if (auth->initiator) {
2625                 pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2626                 prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
2627                 if (auth->own_bi)
2628                         bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
2629                 else
2630                         bix = NULL;
2631                 if (!auth->peer_bi)
2632                         goto fail;
2633                 brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
2634         } else {
2635                 pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
2636                 prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2637                 if (auth->peer_bi)
2638                         bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
2639                 else
2640                         bix = NULL;
2641                 if (!auth->own_bi)
2642                         goto fail;
2643                 brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
2644         }
2645         if (!pix || !prx || !brx)
2646                 goto fail;
2647
2648         addr[num_elem] = auth->r_nonce;
2649         len[num_elem] = nonce_len;
2650         num_elem++;
2651
2652         addr[num_elem] = auth->i_nonce;
2653         len[num_elem] = nonce_len;
2654         num_elem++;
2655
2656         addr[num_elem] = wpabuf_head(prx);
2657         len[num_elem] = wpabuf_len(prx) / 2;
2658         num_elem++;
2659
2660         addr[num_elem] = wpabuf_head(pix);
2661         len[num_elem] = wpabuf_len(pix) / 2;
2662         num_elem++;
2663
2664         addr[num_elem] = wpabuf_head(brx);
2665         len[num_elem] = wpabuf_len(brx) / 2;
2666         num_elem++;
2667
2668         if (bix) {
2669                 addr[num_elem] = wpabuf_head(bix);
2670                 len[num_elem] = wpabuf_len(bix) / 2;
2671                 num_elem++;
2672         }
2673
2674         addr[num_elem] = &one;
2675         len[num_elem] = 1;
2676         num_elem++;
2677
2678         wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
2679         for (i = 0; i < num_elem; i++)
2680                 wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
2681         res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
2682         if (res == 0)
2683                 wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
2684                             auth->curve->hash_len);
2685 fail:
2686         wpabuf_free(pix);
2687         wpabuf_free(prx);
2688         wpabuf_free(bix);
2689         wpabuf_free(brx);
2690         return res;
2691 }
2692
2693
2694 static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
2695 {
2696         const EC_GROUP *group;
2697         EC_POINT *l = NULL;
2698         EC_KEY *BI = NULL, *bR = NULL, *pR = NULL;
2699         const EC_POINT *BI_point;
2700         BN_CTX *bnctx;
2701         BIGNUM *lx, *sum, *q;
2702         const BIGNUM *bR_bn, *pR_bn;
2703         int ret = -1;
2704
2705         /* L = ((bR + pR) modulo q) * BI */
2706
2707         bnctx = BN_CTX_new();
2708         sum = BN_new();
2709         q = BN_new();
2710         lx = BN_new();
2711         if (!bnctx || !sum || !q || !lx)
2712                 goto fail;
2713         BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
2714         if (!BI)
2715                 goto fail;
2716         BI_point = EC_KEY_get0_public_key(BI);
2717         group = EC_KEY_get0_group(BI);
2718         if (!group)
2719                 goto fail;
2720
2721         bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
2722         pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
2723         if (!bR || !pR)
2724                 goto fail;
2725         bR_bn = EC_KEY_get0_private_key(bR);
2726         pR_bn = EC_KEY_get0_private_key(pR);
2727         if (!bR_bn || !pR_bn)
2728                 goto fail;
2729         if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
2730             BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
2731                 goto fail;
2732         l = EC_POINT_new(group);
2733         if (!l ||
2734             EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
2735             EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
2736                                                 bnctx) != 1) {
2737                 wpa_printf(MSG_ERROR,
2738                            "OpenSSL: failed: %s",
2739                            ERR_error_string(ERR_get_error(), NULL));
2740                 goto fail;
2741         }
2742
2743         if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
2744                 goto fail;
2745         wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
2746         auth->Lx_len = auth->secret_len;
2747         ret = 0;
2748 fail:
2749         EC_POINT_clear_free(l);
2750         EC_KEY_free(BI);
2751         EC_KEY_free(bR);
2752         EC_KEY_free(pR);
2753         BN_clear_free(lx);
2754         BN_clear_free(sum);
2755         BN_free(q);
2756         BN_CTX_free(bnctx);
2757         return ret;
2758 }
2759
2760
2761 static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
2762 {
2763         const EC_GROUP *group;
2764         EC_POINT *l = NULL, *sum = NULL;
2765         EC_KEY *bI = NULL, *BR = NULL, *PR = NULL;
2766         const EC_POINT *BR_point, *PR_point;
2767         BN_CTX *bnctx;
2768         BIGNUM *lx;
2769         const BIGNUM *bI_bn;
2770         int ret = -1;
2771
2772         /* L = bI * (BR + PR) */
2773
2774         bnctx = BN_CTX_new();
2775         lx = BN_new();
2776         if (!bnctx || !lx)
2777                 goto fail;
2778         BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
2779         PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key);
2780         if (!BR || !PR)
2781                 goto fail;
2782         BR_point = EC_KEY_get0_public_key(BR);
2783         PR_point = EC_KEY_get0_public_key(PR);
2784
2785         bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
2786         if (!bI)
2787                 goto fail;
2788         group = EC_KEY_get0_group(bI);
2789         bI_bn = EC_KEY_get0_private_key(bI);
2790         if (!group || !bI_bn)
2791                 goto fail;
2792         sum = EC_POINT_new(group);
2793         l = EC_POINT_new(group);
2794         if (!sum || !l ||
2795             EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
2796             EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
2797             EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
2798                                                 bnctx) != 1) {
2799                 wpa_printf(MSG_ERROR,
2800                            "OpenSSL: failed: %s",
2801                            ERR_error_string(ERR_get_error(), NULL));
2802                 goto fail;
2803         }
2804
2805         if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
2806                 goto fail;
2807         wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
2808         auth->Lx_len = auth->secret_len;
2809         ret = 0;
2810 fail:
2811         EC_POINT_clear_free(l);
2812         EC_POINT_clear_free(sum);
2813         EC_KEY_free(bI);
2814         EC_KEY_free(BR);
2815         EC_KEY_free(PR);
2816         BN_clear_free(lx);
2817         BN_CTX_free(bnctx);
2818         return ret;
2819 }
2820
2821
2822 static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
2823 {
2824         size_t nonce_len;
2825         size_t secret_len;
2826         struct wpabuf *msg, *pr = NULL;
2827         u8 r_auth[4 + DPP_MAX_HASH_LEN];
2828         u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth;
2829         size_t wrapped_r_auth_len;
2830         int ret = -1;
2831         const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce;
2832         enum dpp_status_error status = DPP_STATUS_OK;
2833 #ifdef CONFIG_TESTING_OPTIONS
2834         u8 test_hash[SHA256_MAC_LEN];
2835 #endif /* CONFIG_TESTING_OPTIONS */
2836
2837         wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
2838         if (!auth->own_bi)
2839                 return -1;
2840
2841 #ifdef CONFIG_TESTING_OPTIONS
2842         if (dpp_nonce_override_len > 0) {
2843                 wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce");
2844                 nonce_len = dpp_nonce_override_len;
2845                 os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len);
2846         } else {
2847                 nonce_len = auth->curve->nonce_len;
2848                 if (random_get_bytes(auth->r_nonce, nonce_len)) {
2849                         wpa_printf(MSG_ERROR,
2850                                    "DPP: Failed to generate R-nonce");
2851                         goto fail;
2852                 }
2853         }
2854 #else /* CONFIG_TESTING_OPTIONS */
2855         nonce_len = auth->curve->nonce_len;
2856         if (random_get_bytes(auth->r_nonce, nonce_len)) {
2857                 wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
2858                 goto fail;
2859         }
2860 #endif /* CONFIG_TESTING_OPTIONS */
2861         wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
2862
2863         EVP_PKEY_free(auth->own_protocol_key);
2864 #ifdef CONFIG_TESTING_OPTIONS
2865         if (dpp_protocol_key_override_len) {
2866                 const struct dpp_curve_params *tmp_curve;
2867
2868                 wpa_printf(MSG_INFO,
2869                            "DPP: TESTING - override protocol key");
2870                 auth->own_protocol_key = dpp_set_keypair(
2871                         &tmp_curve, dpp_protocol_key_override,
2872                         dpp_protocol_key_override_len);
2873         } else {
2874                 auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2875         }
2876 #else /* CONFIG_TESTING_OPTIONS */
2877         auth->own_protocol_key = dpp_gen_keypair(auth->curve);
2878 #endif /* CONFIG_TESTING_OPTIONS */
2879         if (!auth->own_protocol_key)
2880                 goto fail;
2881
2882         pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
2883         if (!pr)
2884                 goto fail;
2885
2886         /* ECDH: N = pR * PI */
2887         if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2888                      auth->Nx, &secret_len) < 0)
2889                 goto fail;
2890
2891         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
2892                         auth->Nx, auth->secret_len);
2893         auth->Nx_len = auth->secret_len;
2894
2895         if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
2896                           auth->curve->hash_len) < 0)
2897                 goto fail;
2898
2899         if (auth->own_bi && auth->peer_bi) {
2900                 /* Mutual authentication */
2901                 if (dpp_auth_derive_l_responder(auth) < 0)
2902                         goto fail;
2903         }
2904
2905         if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
2906                 goto fail;
2907
2908         /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
2909         WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
2910         WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
2911         if (dpp_gen_r_auth(auth, r_auth + 4) < 0)
2912                 goto fail;
2913 #ifdef CONFIG_TESTING_OPTIONS
2914         if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) {
2915                 wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch");
2916                 r_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
2917         }
2918 #endif /* CONFIG_TESTING_OPTIONS */
2919         if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2920                             r_auth, 4 + auth->curve->hash_len,
2921                             0, NULL, NULL, wrapped_r_auth) < 0)
2922                 goto fail;
2923         wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
2924         wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
2925                     wrapped_r_auth, wrapped_r_auth_len);
2926         w_r_auth = wrapped_r_auth;
2927
2928         r_pubkey_hash = auth->own_bi->pubkey_hash;
2929         if (auth->peer_bi)
2930                 i_pubkey_hash = auth->peer_bi->pubkey_hash;
2931         else
2932                 i_pubkey_hash = NULL;
2933
2934         i_nonce = auth->i_nonce;
2935         r_nonce = auth->r_nonce;
2936
2937 #ifdef CONFIG_TESTING_OPTIONS
2938         if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2939                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
2940                 r_pubkey_hash = NULL;
2941         } else if (dpp_test ==
2942                    DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2943                 wpa_printf(MSG_INFO,
2944                            "DPP: TESTING - invalid R-Bootstrap Key Hash");
2945                 os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
2946                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2947                 r_pubkey_hash = test_hash;
2948         } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2949                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
2950                 i_pubkey_hash = NULL;
2951         } else if (dpp_test ==
2952                    DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
2953                 wpa_printf(MSG_INFO,
2954                            "DPP: TESTING - invalid I-Bootstrap Key Hash");
2955                 if (i_pubkey_hash)
2956                         os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
2957                 else
2958                         os_memset(test_hash, 0, SHA256_MAC_LEN);
2959                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
2960                 i_pubkey_hash = test_hash;
2961         } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) {
2962                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key");
2963                 wpabuf_free(pr);
2964                 pr = NULL;
2965         } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) {
2966                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key");
2967                 wpabuf_free(pr);
2968                 pr = wpabuf_alloc(2 * auth->curve->prime_len);
2969                 if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0)
2970                         goto fail;
2971         } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) {
2972                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth");
2973                 w_r_auth = NULL;
2974                 wrapped_r_auth_len = 0;
2975         } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
2976                 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
2977                 status = 255;
2978         } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) {
2979                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
2980                 status = 254;
2981         } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) {
2982                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce");
2983                 r_nonce = NULL;
2984         } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
2985                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
2986                 i_nonce = NULL;
2987         }
2988 #endif /* CONFIG_TESTING_OPTIONS */
2989
2990         msg = dpp_auth_build_resp(auth, status, pr, nonce_len,
2991                                   r_pubkey_hash, i_pubkey_hash,
2992                                   r_nonce, i_nonce,
2993                                   w_r_auth, wrapped_r_auth_len,
2994                                   auth->k2);
2995         if (!msg)
2996                 goto fail;
2997         wpabuf_free(auth->resp_msg);
2998         auth->resp_msg = msg;
2999         ret = 0;
3000 fail:
3001         wpabuf_free(pr);
3002         return ret;
3003 }
3004
3005
3006 static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
3007                                       enum dpp_status_error status)
3008 {
3009         struct wpabuf *msg;
3010         const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce;
3011 #ifdef CONFIG_TESTING_OPTIONS
3012         u8 test_hash[SHA256_MAC_LEN];
3013 #endif /* CONFIG_TESTING_OPTIONS */
3014
3015         if (!auth->own_bi)
3016                 return -1;
3017         wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
3018
3019         r_pubkey_hash = auth->own_bi->pubkey_hash;
3020         if (auth->peer_bi)
3021                 i_pubkey_hash = auth->peer_bi->pubkey_hash;
3022         else
3023                 i_pubkey_hash = NULL;
3024
3025         i_nonce = auth->i_nonce;
3026
3027 #ifdef CONFIG_TESTING_OPTIONS
3028         if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
3029                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
3030                 r_pubkey_hash = NULL;
3031         } else if (dpp_test ==
3032                    DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
3033                 wpa_printf(MSG_INFO,
3034                            "DPP: TESTING - invalid R-Bootstrap Key Hash");
3035                 os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
3036                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
3037                 r_pubkey_hash = test_hash;
3038         } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
3039                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
3040                 i_pubkey_hash = NULL;
3041         } else if (dpp_test ==
3042                    DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
3043                 wpa_printf(MSG_INFO,
3044                            "DPP: TESTING - invalid I-Bootstrap Key Hash");
3045                 if (i_pubkey_hash)
3046                         os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
3047                 else
3048                         os_memset(test_hash, 0, SHA256_MAC_LEN);
3049                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
3050                 i_pubkey_hash = test_hash;
3051         } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
3052                 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
3053                 status = 255;
3054         } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
3055                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
3056                 i_nonce = NULL;
3057         }
3058 #endif /* CONFIG_TESTING_OPTIONS */
3059
3060         msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len,
3061                                   r_pubkey_hash, i_pubkey_hash,
3062                                   NULL, i_nonce, NULL, 0, auth->k1);
3063         if (!msg)
3064                 return -1;
3065         wpabuf_free(auth->resp_msg);
3066         auth->resp_msg = msg;
3067         return 0;
3068 }
3069
3070
3071 struct dpp_authentication *
3072 dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
3073                 struct dpp_bootstrap_info *peer_bi,
3074                 struct dpp_bootstrap_info *own_bi,
3075                 unsigned int freq, const u8 *hdr, const u8 *attr_start,
3076                 size_t attr_len)
3077 {
3078         EVP_PKEY *pi = NULL;
3079         EVP_PKEY_CTX *ctx = NULL;
3080         size_t secret_len;
3081         const u8 *addr[2];
3082         size_t len[2];
3083         u8 *unwrapped = NULL;
3084         size_t unwrapped_len = 0;
3085         const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap,
3086                 *channel;
3087         u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len,
3088                 i_bootstrap_len, channel_len;
3089         struct dpp_authentication *auth = NULL;
3090 #ifdef CONFIG_DPP2
3091         const u8 *version;
3092         u16 version_len;
3093 #endif /* CONFIG_DPP2 */
3094
3095 #ifdef CONFIG_TESTING_OPTIONS
3096         if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
3097                 wpa_printf(MSG_INFO,
3098                            "DPP: TESTING - stop at Authentication Request");
3099                 return NULL;
3100         }
3101 #endif /* CONFIG_TESTING_OPTIONS */
3102
3103         wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3104                                     &wrapped_data_len);
3105         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3106                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
3107                         "Missing or invalid required Wrapped Data attribute");
3108                 return NULL;
3109         }
3110         wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
3111                     wrapped_data, wrapped_data_len);
3112         attr_len = wrapped_data - 4 - attr_start;
3113
3114         auth = os_zalloc(sizeof(*auth));
3115         if (!auth)
3116                 goto fail;
3117         auth->msg_ctx = msg_ctx;
3118         auth->peer_bi = peer_bi;
3119         auth->own_bi = own_bi;
3120         auth->curve = own_bi->curve;
3121         auth->curr_freq = freq;
3122
3123         auth->peer_version = 1; /* default to the first version */
3124 #ifdef CONFIG_DPP2
3125         version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
3126                                &version_len);
3127         if (version) {
3128                 if (version_len < 1 || version[0] == 0) {
3129                         dpp_auth_fail(auth,
3130                                       "Invalid Protocol Version attribute");
3131                         goto fail;
3132                 }
3133                 auth->peer_version = version[0];
3134                 wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
3135                            auth->peer_version);
3136         }
3137 #endif /* CONFIG_DPP2 */
3138
3139         channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
3140                                &channel_len);
3141         if (channel) {
3142                 int neg_freq;
3143
3144                 if (channel_len < 2) {
3145                         dpp_auth_fail(auth, "Too short Channel attribute");
3146                         goto fail;
3147                 }
3148
3149                 neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
3150                 wpa_printf(MSG_DEBUG,
3151                            "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
3152                            channel[0], channel[1], neg_freq);
3153                 if (neg_freq < 0) {
3154                         dpp_auth_fail(auth,
3155                                       "Unsupported Channel attribute value");
3156                         goto fail;
3157                 }
3158
3159                 if (auth->curr_freq != (unsigned int) neg_freq) {
3160                         wpa_printf(MSG_DEBUG,
3161                                    "DPP: Changing negotiation channel from %u MHz to %u MHz",
3162                                    freq, neg_freq);
3163                         auth->curr_freq = neg_freq;
3164                 }
3165         }
3166
3167         i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
3168                                &i_proto_len);
3169         if (!i_proto) {
3170                 dpp_auth_fail(auth,
3171                               "Missing required Initiator Protocol Key attribute");
3172                 goto fail;
3173         }
3174         wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
3175                     i_proto, i_proto_len);
3176
3177         /* M = bR * PI */
3178         pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
3179         if (!pi) {
3180                 dpp_auth_fail(auth, "Invalid Initiator Protocol Key");
3181                 goto fail;
3182         }
3183         dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
3184
3185         if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
3186                 goto fail;
3187         auth->secret_len = secret_len;
3188
3189         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
3190                         auth->Mx, auth->secret_len);
3191         auth->Mx_len = auth->secret_len;
3192
3193         if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
3194                           auth->curve->hash_len) < 0)
3195                 goto fail;
3196
3197         addr[0] = hdr;
3198         len[0] = DPP_HDR_LEN;
3199         addr[1] = attr_start;
3200         len[1] = attr_len;
3201         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3202         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3203         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3204                     wrapped_data, wrapped_data_len);
3205         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3206         unwrapped = os_malloc(unwrapped_len);
3207         if (!unwrapped)
3208                 goto fail;
3209         if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
3210                             wrapped_data, wrapped_data_len,
3211                             2, addr, len, unwrapped) < 0) {
3212                 dpp_auth_fail(auth, "AES-SIV decryption failed");
3213                 goto fail;
3214         }
3215         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3216                     unwrapped, unwrapped_len);
3217
3218         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3219                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3220                 goto fail;
3221         }
3222
3223         i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
3224                                &i_nonce_len);
3225         if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
3226                 dpp_auth_fail(auth, "Missing or invalid I-nonce");
3227                 goto fail;
3228         }
3229         wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
3230         os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
3231
3232         i_capab = dpp_get_attr(unwrapped, unwrapped_len,
3233                                DPP_ATTR_I_CAPABILITIES,
3234                                &i_capab_len);
3235         if (!i_capab || i_capab_len < 1) {
3236                 dpp_auth_fail(auth, "Missing or invalid I-capabilities");
3237                 goto fail;
3238         }
3239         auth->i_capab = i_capab[0];
3240         wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
3241
3242         bin_clear_free(unwrapped, unwrapped_len);
3243         unwrapped = NULL;
3244
3245         switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
3246         case DPP_CAPAB_ENROLLEE:
3247                 if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
3248                         wpa_printf(MSG_DEBUG,
3249                                    "DPP: Local policy does not allow Configurator role");
3250                         goto not_compatible;
3251                 }
3252                 wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
3253                 auth->configurator = 1;
3254                 break;
3255         case DPP_CAPAB_CONFIGURATOR:
3256                 if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
3257                         wpa_printf(MSG_DEBUG,
3258                                    "DPP: Local policy does not allow Enrollee role");
3259                         goto not_compatible;
3260                 }
3261                 wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
3262                 auth->configurator = 0;
3263                 break;
3264         case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE:
3265                 if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) {
3266                         wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
3267                         auth->configurator = 0;
3268                 } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) {
3269                         wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
3270                         auth->configurator = 1;
3271                 } else {
3272                         wpa_printf(MSG_DEBUG,
3273                                    "DPP: Local policy does not allow Configurator/Enrollee role");
3274                         goto not_compatible;
3275                 }
3276                 break;
3277         default:
3278                 wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
3279                 wpa_msg(auth->msg_ctx, MSG_INFO,
3280                         DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x",
3281                         auth->i_capab & DPP_CAPAB_ROLE_MASK);
3282                 goto fail;
3283         }
3284
3285         auth->peer_protocol_key = pi;
3286         pi = NULL;
3287         if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
3288                 char hex[SHA256_MAC_LEN * 2 + 1];
3289
3290                 wpa_printf(MSG_DEBUG,
3291                            "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
3292                 if (dpp_auth_build_resp_status(auth,
3293                                                DPP_STATUS_RESPONSE_PENDING) < 0)
3294                         goto fail;
3295                 i_bootstrap = dpp_get_attr(attr_start, attr_len,
3296                                            DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3297                                            &i_bootstrap_len);
3298                 if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
3299                         auth->response_pending = 1;
3300                         os_memcpy(auth->waiting_pubkey_hash,
3301                                   i_bootstrap, i_bootstrap_len);
3302                         wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
3303                                          i_bootstrap_len);
3304                 } else {
3305                         hex[0] = '\0';
3306                 }
3307
3308                 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
3309                         "%s", hex);
3310                 return auth;
3311         }
3312         if (dpp_auth_build_resp_ok(auth) < 0)
3313                 goto fail;
3314
3315         return auth;
3316
3317 not_compatible:
3318         wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
3319                 "i-capab=0x%02x", auth->i_capab);
3320         if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
3321                 auth->configurator = 1;
3322         else
3323                 auth->configurator = 0;
3324         auth->peer_protocol_key = pi;
3325         pi = NULL;
3326         if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
3327                 goto fail;
3328
3329         auth->remove_on_tx_status = 1;
3330         return auth;
3331 fail:
3332         bin_clear_free(unwrapped, unwrapped_len);
3333         EVP_PKEY_free(pi);
3334         EVP_PKEY_CTX_free(ctx);
3335         dpp_auth_deinit(auth);
3336         return NULL;
3337 }
3338
3339
3340 int dpp_notify_new_qr_code(struct dpp_authentication *auth,
3341                            struct dpp_bootstrap_info *peer_bi)
3342 {
3343         if (!auth || !auth->response_pending ||
3344             os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
3345                       SHA256_MAC_LEN) != 0)
3346                 return 0;
3347
3348         wpa_printf(MSG_DEBUG,
3349                    "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
3350                    MACSTR, MAC2STR(auth->peer_mac_addr));
3351         auth->peer_bi = peer_bi;
3352
3353         if (dpp_auth_build_resp_ok(auth) < 0)
3354                 return -1;
3355
3356         return 1;
3357 }
3358
3359
3360 static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth,
3361                                            enum dpp_status_error status)
3362 {
3363         struct wpabuf *msg;
3364         u8 i_auth[4 + DPP_MAX_HASH_LEN];
3365         size_t i_auth_len;
3366         u8 r_nonce[4 + DPP_MAX_NONCE_LEN];
3367         size_t r_nonce_len;
3368         const u8 *addr[2];
3369         size_t len[2], attr_len;
3370         u8 *wrapped_i_auth;
3371         u8 *wrapped_r_nonce;
3372         u8 *attr_start, *attr_end;
3373         const u8 *r_pubkey_hash, *i_pubkey_hash;
3374 #ifdef CONFIG_TESTING_OPTIONS
3375         u8 test_hash[SHA256_MAC_LEN];
3376 #endif /* CONFIG_TESTING_OPTIONS */
3377
3378         wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
3379
3380         i_auth_len = 4 + auth->curve->hash_len;
3381         r_nonce_len = 4 + auth->curve->nonce_len;
3382         /* Build DPP Authentication Confirmation frame attributes */
3383         attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
3384                 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE;
3385 #ifdef CONFIG_TESTING_OPTIONS
3386         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF)
3387                 attr_len += 5;
3388 #endif /* CONFIG_TESTING_OPTIONS */
3389         msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
3390         if (!msg)
3391                 goto fail;
3392
3393         attr_start = wpabuf_put(msg, 0);
3394
3395         r_pubkey_hash = auth->peer_bi->pubkey_hash;
3396         if (auth->own_bi)
3397                 i_pubkey_hash = auth->own_bi->pubkey_hash;
3398         else
3399                 i_pubkey_hash = NULL;
3400
3401 #ifdef CONFIG_TESTING_OPTIONS
3402         if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) {
3403                 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
3404                 goto skip_status;
3405         } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) {
3406                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
3407                 status = 254;
3408         }
3409 #endif /* CONFIG_TESTING_OPTIONS */
3410
3411         /* DPP Status */
3412         dpp_build_attr_status(msg, status);
3413
3414 #ifdef CONFIG_TESTING_OPTIONS
3415 skip_status:
3416         if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
3417                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
3418                 r_pubkey_hash = NULL;
3419         } else if (dpp_test ==
3420                    DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
3421                 wpa_printf(MSG_INFO,
3422                            "DPP: TESTING - invalid R-Bootstrap Key Hash");
3423                 os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
3424                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
3425                 r_pubkey_hash = test_hash;
3426         } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
3427                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
3428                 i_pubkey_hash = NULL;
3429         } else if (dpp_test ==
3430                    DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
3431                 wpa_printf(MSG_INFO,
3432                            "DPP: TESTING - invalid I-Bootstrap Key Hash");
3433                 if (i_pubkey_hash)
3434                         os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
3435                 else
3436                         os_memset(test_hash, 0, SHA256_MAC_LEN);
3437                 test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
3438                 i_pubkey_hash = test_hash;
3439         }
3440 #endif /* CONFIG_TESTING_OPTIONS */
3441
3442         /* Responder Bootstrapping Key Hash */
3443         dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
3444
3445         /* Initiator Bootstrapping Key Hash (mutual authentication) */
3446         dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
3447
3448 #ifdef CONFIG_TESTING_OPTIONS
3449         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF)
3450                 goto skip_wrapped_data;
3451         if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
3452                 i_auth_len = 0;
3453 #endif /* CONFIG_TESTING_OPTIONS */
3454
3455         attr_end = wpabuf_put(msg, 0);
3456
3457         /* OUI, OUI type, Crypto Suite, DPP frame type */
3458         addr[0] = wpabuf_head_u8(msg) + 2;
3459         len[0] = 3 + 1 + 1 + 1;
3460         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3461
3462         /* Attributes before Wrapped Data */
3463         addr[1] = attr_start;
3464         len[1] = attr_end - attr_start;
3465         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3466
3467         if (status == DPP_STATUS_OK) {
3468                 /* I-auth wrapped with ke */
3469                 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3470                 wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
3471                 wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
3472
3473 #ifdef CONFIG_TESTING_OPTIONS
3474                 if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
3475                         goto skip_i_auth;
3476 #endif /* CONFIG_TESTING_OPTIONS */
3477
3478                 /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |]
3479                  *            1) */
3480                 WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
3481                 WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
3482                 if (dpp_gen_i_auth(auth, i_auth + 4) < 0)
3483                         goto fail;
3484
3485 #ifdef CONFIG_TESTING_OPTIONS
3486                 if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) {
3487                         wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch");
3488                         i_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
3489                 }
3490 skip_i_auth:
3491 #endif /* CONFIG_TESTING_OPTIONS */
3492                 if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3493                                     i_auth, i_auth_len,
3494                                     2, addr, len, wrapped_i_auth) < 0)
3495                         goto fail;
3496                 wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
3497                             wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
3498         } else {
3499                 /* R-nonce wrapped with k2 */
3500                 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3501                 wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE);
3502                 wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE);
3503
3504                 WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE);
3505                 WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len);
3506                 os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len);
3507
3508                 if (aes_siv_encrypt(auth->k2, auth->curve->hash_len,
3509                                     r_nonce, r_nonce_len,
3510                                     2, addr, len, wrapped_r_nonce) < 0)
3511                         goto fail;
3512                 wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2",
3513                             wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE);
3514         }
3515
3516 #ifdef CONFIG_TESTING_OPTIONS
3517         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) {
3518                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
3519                 dpp_build_attr_status(msg, DPP_STATUS_OK);
3520         }
3521 skip_wrapped_data:
3522 #endif /* CONFIG_TESTING_OPTIONS */
3523
3524         wpa_hexdump_buf(MSG_DEBUG,
3525                         "DPP: Authentication Confirmation frame attributes",
3526                         msg);
3527         if (status == DPP_STATUS_OK)
3528                 dpp_auth_success(auth);
3529
3530         return msg;
3531
3532 fail:
3533         wpabuf_free(msg);
3534         return NULL;
3535 }
3536
3537
3538 static void
3539 dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
3540                         const u8 *attr_start, size_t attr_len,
3541                         const u8 *wrapped_data, u16 wrapped_data_len,
3542                         enum dpp_status_error status)
3543 {
3544         const u8 *addr[2];
3545         size_t len[2];
3546         u8 *unwrapped = NULL;
3547         size_t unwrapped_len = 0;
3548         const u8 *i_nonce, *r_capab;
3549         u16 i_nonce_len, r_capab_len;
3550
3551         if (status == DPP_STATUS_NOT_COMPATIBLE) {
3552                 wpa_printf(MSG_DEBUG,
3553                            "DPP: Responder reported incompatible roles");
3554         } else if (status == DPP_STATUS_RESPONSE_PENDING) {
3555                 wpa_printf(MSG_DEBUG,
3556                            "DPP: Responder reported more time needed");
3557         } else {
3558                 wpa_printf(MSG_DEBUG,
3559                            "DPP: Responder reported failure (status %d)",
3560                            status);
3561                 dpp_auth_fail(auth, "Responder reported failure");
3562                 return;
3563         }
3564
3565         addr[0] = hdr;
3566         len[0] = DPP_HDR_LEN;
3567         addr[1] = attr_start;
3568         len[1] = attr_len;
3569         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3570         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3571         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3572                     wrapped_data, wrapped_data_len);
3573         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3574         unwrapped = os_malloc(unwrapped_len);
3575         if (!unwrapped)
3576                 goto fail;
3577         if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
3578                             wrapped_data, wrapped_data_len,
3579                             2, addr, len, unwrapped) < 0) {
3580                 dpp_auth_fail(auth, "AES-SIV decryption failed");
3581                 goto fail;
3582         }
3583         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3584                     unwrapped, unwrapped_len);
3585
3586         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3587                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3588                 goto fail;
3589         }
3590
3591         i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
3592                                &i_nonce_len);
3593         if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
3594                 dpp_auth_fail(auth, "Missing or invalid I-nonce");
3595                 goto fail;
3596         }
3597         wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
3598         if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
3599                 dpp_auth_fail(auth, "I-nonce mismatch");
3600                 goto fail;
3601         }
3602
3603         r_capab = dpp_get_attr(unwrapped, unwrapped_len,
3604                                DPP_ATTR_R_CAPABILITIES,
3605                                &r_capab_len);
3606         if (!r_capab || r_capab_len < 1) {
3607                 dpp_auth_fail(auth, "Missing or invalid R-capabilities");
3608                 goto fail;
3609         }
3610         auth->r_capab = r_capab[0];
3611         wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
3612         if (status == DPP_STATUS_NOT_COMPATIBLE) {
3613                 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
3614                         "r-capab=0x%02x", auth->r_capab);
3615         } else if (status == DPP_STATUS_RESPONSE_PENDING) {
3616                 u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
3617
3618                 if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
3619                     (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
3620                         wpa_msg(auth->msg_ctx, MSG_INFO,
3621                                 DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x",
3622                                 role);
3623                 } else {
3624                         wpa_printf(MSG_DEBUG,
3625                                    "DPP: Continue waiting for full DPP Authentication Response");
3626                         wpa_msg(auth->msg_ctx, MSG_INFO,
3627                                 DPP_EVENT_RESPONSE_PENDING "%s",
3628                                 auth->tmp_own_bi ? auth->tmp_own_bi->uri : "");
3629                 }
3630         }
3631 fail:
3632         bin_clear_free(unwrapped, unwrapped_len);
3633 }
3634
3635
3636 struct wpabuf *
3637 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
3638                  const u8 *attr_start, size_t attr_len)
3639 {
3640         EVP_PKEY *pr;
3641         size_t secret_len;
3642         const u8 *addr[2];
3643         size_t len[2];
3644         u8 *unwrapped = NULL, *unwrapped2 = NULL;
3645         size_t unwrapped_len = 0, unwrapped2_len = 0;
3646         const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
3647                 *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
3648         u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
3649                 r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
3650                 wrapped2_len, r_auth_len;
3651         u8 r_auth2[DPP_MAX_HASH_LEN];
3652         u8 role;
3653 #ifdef CONFIG_DPP2
3654         const u8 *version;
3655         u16 version_len;
3656 #endif /* CONFIG_DPP2 */
3657
3658 #ifdef CONFIG_TESTING_OPTIONS
3659         if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) {
3660                 wpa_printf(MSG_INFO,
3661                            "DPP: TESTING - stop at Authentication Response");
3662                 return NULL;
3663         }
3664 #endif /* CONFIG_TESTING_OPTIONS */
3665
3666         if (!auth->initiator || !auth->peer_bi) {
3667                 dpp_auth_fail(auth, "Unexpected Authentication Response");
3668                 return NULL;
3669         }
3670
3671         auth->waiting_auth_resp = 0;
3672
3673         wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3674                                     &wrapped_data_len);
3675         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3676                 dpp_auth_fail(auth,
3677                               "Missing or invalid required Wrapped Data attribute");
3678                 return NULL;
3679         }
3680         wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3681                     wrapped_data, wrapped_data_len);
3682
3683         attr_len = wrapped_data - 4 - attr_start;
3684
3685         r_bootstrap = dpp_get_attr(attr_start, attr_len,
3686                                    DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3687                                    &r_bootstrap_len);
3688         if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
3689                 dpp_auth_fail(auth,
3690                               "Missing or invalid required Responder Bootstrapping Key Hash attribute");
3691                 return NULL;
3692         }
3693         wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
3694                     r_bootstrap, r_bootstrap_len);
3695         if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
3696                       SHA256_MAC_LEN) != 0) {
3697                 dpp_auth_fail(auth,
3698                               "Unexpected Responder Bootstrapping Key Hash value");
3699                 wpa_hexdump(MSG_DEBUG,
3700                             "DPP: Expected Responder Bootstrapping Key Hash",
3701                             auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
3702                 return NULL;
3703         }
3704
3705         i_bootstrap = dpp_get_attr(attr_start, attr_len,
3706                                    DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3707                                    &i_bootstrap_len);
3708         if (i_bootstrap) {
3709                 if (i_bootstrap_len != SHA256_MAC_LEN) {
3710                         dpp_auth_fail(auth,
3711                                       "Invalid Initiator Bootstrapping Key Hash attribute");
3712                         return NULL;
3713                 }
3714                 wpa_hexdump(MSG_MSGDUMP,
3715                             "DPP: Initiator Bootstrapping Key Hash",
3716                             i_bootstrap, i_bootstrap_len);
3717                 if (!auth->own_bi ||
3718                     os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
3719                               SHA256_MAC_LEN) != 0) {
3720                         dpp_auth_fail(auth,
3721                                       "Initiator Bootstrapping Key Hash attribute did not match");
3722                         return NULL;
3723                 }
3724         } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) {
3725                 /* PKEX bootstrapping mandates use of mutual authentication */
3726                 dpp_auth_fail(auth,
3727                               "Missing Initiator Bootstrapping Key Hash attribute");
3728                 return NULL;
3729         }
3730
3731         auth->peer_version = 1; /* default to the first version */
3732 #ifdef CONFIG_DPP2
3733         version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
3734                                &version_len);
3735         if (version) {
3736                 if (version_len < 1 || version[0] == 0) {
3737                         dpp_auth_fail(auth,
3738                                       "Invalid Protocol Version attribute");
3739                         return NULL;
3740                 }
3741                 auth->peer_version = version[0];
3742                 wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
3743                            auth->peer_version);
3744         }
3745 #endif /* CONFIG_DPP2 */
3746
3747         status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
3748                               &status_len);
3749         if (!status || status_len < 1) {
3750                 dpp_auth_fail(auth,
3751                               "Missing or invalid required DPP Status attribute");
3752                 return NULL;
3753         }
3754         wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3755         auth->auth_resp_status = status[0];
3756         if (status[0] != DPP_STATUS_OK) {
3757                 dpp_auth_resp_rx_status(auth, hdr, attr_start,
3758                                         attr_len, wrapped_data,
3759                                         wrapped_data_len, status[0]);
3760                 return NULL;
3761         }
3762
3763         if (!i_bootstrap && auth->own_bi) {
3764                 wpa_printf(MSG_DEBUG,
3765                            "DPP: Responder decided not to use mutual authentication");
3766                 auth->own_bi = NULL;
3767         }
3768
3769         wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d",
3770                 auth->own_bi != NULL);
3771
3772         r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
3773                                &r_proto_len);
3774         if (!r_proto) {
3775                 dpp_auth_fail(auth,
3776                               "Missing required Responder Protocol Key attribute");
3777                 return NULL;
3778         }
3779         wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
3780                     r_proto, r_proto_len);
3781
3782         /* N = pI * PR */
3783         pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
3784         if (!pr) {
3785                 dpp_auth_fail(auth, "Invalid Responder Protocol Key");
3786                 return NULL;
3787         }
3788         dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
3789
3790         if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
3791                 dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
3792                 goto fail;
3793         }
3794         EVP_PKEY_free(auth->peer_protocol_key);
3795         auth->peer_protocol_key = pr;
3796         pr = NULL;
3797
3798         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
3799                         auth->Nx, auth->secret_len);
3800         auth->Nx_len = auth->secret_len;
3801
3802         if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
3803                           auth->curve->hash_len) < 0)
3804                 goto fail;
3805
3806         addr[0] = hdr;
3807         len[0] = DPP_HDR_LEN;
3808         addr[1] = attr_start;
3809         len[1] = attr_len;
3810         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3811         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3812         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3813                     wrapped_data, wrapped_data_len);
3814         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3815         unwrapped = os_malloc(unwrapped_len);
3816         if (!unwrapped)
3817                 goto fail;
3818         if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
3819                             wrapped_data, wrapped_data_len,
3820                             2, addr, len, unwrapped) < 0) {
3821                 dpp_auth_fail(auth, "AES-SIV decryption failed");
3822                 goto fail;
3823         }
3824         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3825                     unwrapped, unwrapped_len);
3826
3827         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3828                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3829                 goto fail;
3830         }
3831
3832         r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
3833                                &r_nonce_len);
3834         if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
3835                 dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
3836                 goto fail;
3837         }
3838         wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
3839         os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
3840
3841         i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
3842                                &i_nonce_len);
3843         if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
3844                 dpp_auth_fail(auth, "Missing or invalid I-nonce");
3845                 goto fail;
3846         }
3847         wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
3848         if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
3849                 dpp_auth_fail(auth, "I-nonce mismatch");
3850                 goto fail;
3851         }
3852
3853         if (auth->own_bi) {
3854                 /* Mutual authentication */
3855                 if (dpp_auth_derive_l_initiator(auth) < 0)
3856                         goto fail;
3857         }
3858
3859         r_capab = dpp_get_attr(unwrapped, unwrapped_len,
3860                                DPP_ATTR_R_CAPABILITIES,
3861                                &r_capab_len);
3862         if (!r_capab || r_capab_len < 1) {
3863                 dpp_auth_fail(auth, "Missing or invalid R-capabilities");
3864                 goto fail;
3865         }
3866         auth->r_capab = r_capab[0];
3867         wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
3868         role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
3869         if ((auth->allowed_roles ==
3870              (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) &&
3871             (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) {
3872                 /* Peer selected its role, so move from "either role" to the
3873                  * role that is compatible with peer's selection. */
3874                 auth->configurator = role == DPP_CAPAB_ENROLLEE;
3875                 wpa_printf(MSG_DEBUG, "DPP: Acting as %s",
3876                            auth->configurator ? "Configurator" : "Enrollee");
3877         } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
3878                    (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
3879                 wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
3880                 wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
3881                         "Unexpected role in R-capabilities 0x%02x",
3882                         role);
3883                 if (role != DPP_CAPAB_ENROLLEE &&
3884                     role != DPP_CAPAB_CONFIGURATOR)
3885                         goto fail;
3886                 bin_clear_free(unwrapped, unwrapped_len);
3887                 auth->remove_on_tx_status = 1;
3888                 return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE);
3889         }
3890
3891         wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
3892                                 DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
3893         if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
3894                 dpp_auth_fail(auth,
3895                               "Missing or invalid Secondary Wrapped Data");
3896                 goto fail;
3897         }
3898
3899         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3900                     wrapped2, wrapped2_len);
3901
3902         if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
3903                 goto fail;
3904
3905         unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
3906         unwrapped2 = os_malloc(unwrapped2_len);
3907         if (!unwrapped2)
3908                 goto fail;
3909         if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3910                             wrapped2, wrapped2_len,
3911                             0, NULL, NULL, unwrapped2) < 0) {
3912                 dpp_auth_fail(auth, "AES-SIV decryption failed");
3913                 goto fail;
3914         }
3915         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3916                     unwrapped2, unwrapped2_len);
3917
3918         if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
3919                 dpp_auth_fail(auth,
3920                               "Invalid attribute in secondary unwrapped data");
3921                 goto fail;
3922         }
3923
3924         r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
3925                                &r_auth_len);
3926         if (!r_auth || r_auth_len != auth->curve->hash_len) {
3927                 dpp_auth_fail(auth,
3928                               "Missing or invalid Responder Authenticating Tag");
3929                 goto fail;
3930         }
3931         wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
3932                     r_auth, r_auth_len);
3933         /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
3934         if (dpp_gen_r_auth(auth, r_auth2) < 0)
3935                 goto fail;
3936         wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
3937                     r_auth2, r_auth_len);
3938         if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
3939                 dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag");
3940                 bin_clear_free(unwrapped, unwrapped_len);
3941                 bin_clear_free(unwrapped2, unwrapped2_len);
3942                 auth->remove_on_tx_status = 1;
3943                 return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE);
3944         }
3945
3946         bin_clear_free(unwrapped, unwrapped_len);
3947         bin_clear_free(unwrapped2, unwrapped2_len);
3948
3949 #ifdef CONFIG_TESTING_OPTIONS
3950         if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) {
3951                 wpa_printf(MSG_INFO,
3952                            "DPP: TESTING - Authentication Response in place of Confirm");
3953                 if (dpp_auth_build_resp_ok(auth) < 0)
3954                         return NULL;
3955                 return wpabuf_dup(auth->resp_msg);
3956         }
3957 #endif /* CONFIG_TESTING_OPTIONS */
3958
3959         return dpp_auth_build_conf(auth, DPP_STATUS_OK);
3960
3961 fail:
3962         bin_clear_free(unwrapped, unwrapped_len);
3963         bin_clear_free(unwrapped2, unwrapped2_len);
3964         EVP_PKEY_free(pr);
3965         return NULL;
3966 }
3967
3968
3969 static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth,
3970                                     const u8 *hdr,
3971                                     const u8 *attr_start, size_t attr_len,
3972                                     const u8 *wrapped_data,
3973                                     u16 wrapped_data_len,
3974                                     enum dpp_status_error status)
3975 {
3976         const u8 *addr[2];
3977         size_t len[2];
3978         u8 *unwrapped = NULL;
3979         size_t unwrapped_len = 0;
3980         const u8 *r_nonce;
3981         u16 r_nonce_len;
3982
3983         /* Authentication Confirm failure cases are expected to include
3984          * {R-nonce}k2 in the Wrapped Data attribute. */
3985
3986         addr[0] = hdr;
3987         len[0] = DPP_HDR_LEN;
3988         addr[1] = attr_start;
3989         len[1] = attr_len;
3990         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3991         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3992         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3993                     wrapped_data, wrapped_data_len);
3994         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3995         unwrapped = os_malloc(unwrapped_len);
3996         if (!unwrapped) {
3997                 dpp_auth_fail(auth, "Authentication failed");
3998                 goto fail;
3999         }
4000         if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
4001                             wrapped_data, wrapped_data_len,
4002                             2, addr, len, unwrapped) < 0) {
4003                 dpp_auth_fail(auth, "AES-SIV decryption failed");
4004                 goto fail;
4005         }
4006         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
4007                     unwrapped, unwrapped_len);
4008
4009         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
4010                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
4011                 goto fail;
4012         }
4013
4014         r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
4015                                &r_nonce_len);
4016         if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
4017                 dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
4018                 goto fail;
4019         }
4020         if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
4021                 wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce",
4022                             r_nonce, r_nonce_len);
4023                 wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce",
4024                             auth->r_nonce, r_nonce_len);
4025                 dpp_auth_fail(auth, "R-nonce mismatch");
4026                 goto fail;
4027         }
4028
4029         if (status == DPP_STATUS_NOT_COMPATIBLE)
4030                 dpp_auth_fail(auth, "Peer reported incompatible R-capab role");
4031         else if (status == DPP_STATUS_AUTH_FAILURE)
4032                 dpp_auth_fail(auth, "Peer reported authentication failure)");
4033
4034 fail:
4035         bin_clear_free(unwrapped, unwrapped_len);
4036         return -1;
4037 }
4038
4039
4040 int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
4041                      const u8 *attr_start, size_t attr_len)
4042 {
4043         const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
4044         u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
4045                 i_auth_len;
4046         const u8 *addr[2];
4047         size_t len[2];
4048         u8 *unwrapped = NULL;
4049         size_t unwrapped_len = 0;
4050         u8 i_auth2[DPP_MAX_HASH_LEN];
4051
4052 #ifdef CONFIG_TESTING_OPTIONS
4053         if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
4054                 wpa_printf(MSG_INFO,
4055                            "DPP: TESTING - stop at Authentication Confirm");
4056                 return -1;
4057         }
4058 #endif /* CONFIG_TESTING_OPTIONS */
4059
4060         if (auth->initiator || !auth->own_bi) {
4061                 dpp_auth_fail(auth, "Unexpected Authentication Confirm");
4062                 return -1;
4063         }
4064
4065         auth->waiting_auth_conf = 0;
4066
4067         wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
4068                                     &wrapped_data_len);
4069         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
4070                 dpp_auth_fail(auth,
4071                               "Missing or invalid required Wrapped Data attribute");
4072                 return -1;
4073         }
4074         wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
4075                     wrapped_data, wrapped_data_len);
4076
4077         attr_len = wrapped_data - 4 - attr_start;
4078
4079         r_bootstrap = dpp_get_attr(attr_start, attr_len,
4080                                    DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
4081                                    &r_bootstrap_len);
4082         if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
4083                 dpp_auth_fail(auth,
4084                               "Missing or invalid required Responder Bootstrapping Key Hash attribute");
4085                 return -1;
4086         }
4087         wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
4088                     r_bootstrap, r_bootstrap_len);
4089         if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
4090                       SHA256_MAC_LEN) != 0) {
4091                 wpa_hexdump(MSG_DEBUG,
4092                             "DPP: Expected Responder Bootstrapping Key Hash",
4093                             auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
4094                 dpp_auth_fail(auth,
4095                               "Responder Bootstrapping Key Hash mismatch");
4096                 return -1;
4097         }
4098
4099         i_bootstrap = dpp_get_attr(attr_start, attr_len,
4100                                    DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
4101                                    &i_bootstrap_len);
4102         if (i_bootstrap) {
4103                 if (i_bootstrap_len != SHA256_MAC_LEN) {
4104                         dpp_auth_fail(auth,
4105                                       "Invalid Initiator Bootstrapping Key Hash attribute");
4106                         return -1;
4107                 }
4108                 wpa_hexdump(MSG_MSGDUMP,
4109                             "DPP: Initiator Bootstrapping Key Hash",
4110                             i_bootstrap, i_bootstrap_len);
4111                 if (!auth->peer_bi ||
4112                     os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
4113                               SHA256_MAC_LEN) != 0) {
4114                         dpp_auth_fail(auth,
4115                                       "Initiator Bootstrapping Key Hash mismatch");
4116                         return -1;
4117                 }
4118         } else if (auth->peer_bi) {
4119                 /* Mutual authentication and peer did not include its
4120                  * Bootstrapping Key Hash attribute. */
4121                 dpp_auth_fail(auth,
4122                               "Missing Initiator Bootstrapping Key Hash attribute");
4123                 return -1;
4124         }
4125
4126         status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
4127                               &status_len);
4128         if (!status || status_len < 1) {
4129                 dpp_auth_fail(auth,
4130                               "Missing or invalid required DPP Status attribute");
4131                 return -1;
4132         }
4133         wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
4134         if (status[0] == DPP_STATUS_NOT_COMPATIBLE ||
4135             status[0] == DPP_STATUS_AUTH_FAILURE)
4136                 return dpp_auth_conf_rx_failure(auth, hdr, attr_start,
4137                                                 attr_len, wrapped_data,
4138                                                 wrapped_data_len, status[0]);
4139
4140         if (status[0] != DPP_STATUS_OK) {
4141                 dpp_auth_fail(auth, "Authentication failed");
4142                 return -1;
4143         }
4144
4145         addr[0] = hdr;
4146         len[0] = DPP_HDR_LEN;
4147         addr[1] = attr_start;
4148         len[1] = attr_len;
4149         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
4150         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
4151         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4152                     wrapped_data, wrapped_data_len);
4153         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
4154         unwrapped = os_malloc(unwrapped_len);
4155         if (!unwrapped)
4156                 return -1;
4157         if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
4158                             wrapped_data, wrapped_data_len,
4159                             2, addr, len, unwrapped) < 0) {
4160                 dpp_auth_fail(auth, "AES-SIV decryption failed");
4161                 goto fail;
4162         }
4163         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
4164                     unwrapped, unwrapped_len);
4165
4166         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
4167                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
4168                 goto fail;
4169         }
4170
4171         i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
4172                               &i_auth_len);
4173         if (!i_auth || i_auth_len != auth->curve->hash_len) {
4174                 dpp_auth_fail(auth,
4175                               "Missing or invalid Initiator Authenticating Tag");
4176                 goto fail;
4177         }
4178         wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
4179                     i_auth, i_auth_len);
4180         /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
4181         if (dpp_gen_i_auth(auth, i_auth2) < 0)
4182                 goto fail;
4183         wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
4184                     i_auth2, i_auth_len);
4185         if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
4186                 dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag");
4187                 goto fail;
4188         }
4189
4190         bin_clear_free(unwrapped, unwrapped_len);
4191         dpp_auth_success(auth);
4192         return 0;
4193 fail:
4194         bin_clear_free(unwrapped, unwrapped_len);
4195         return -1;
4196 }
4197
4198
4199 static int bin_str_eq(const char *val, size_t len, const char *cmp)
4200 {
4201         return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
4202 }
4203
4204
4205 struct dpp_configuration * dpp_configuration_alloc(const char *type)
4206 {
4207         struct dpp_configuration *conf;
4208         const char *end;
4209         size_t len;
4210
4211         conf = os_zalloc(sizeof(*conf));
4212         if (!conf)
4213                 goto fail;
4214
4215         end = os_strchr(type, ' ');
4216         if (end)
4217                 len = end - type;
4218         else
4219                 len = os_strlen(type);
4220
4221         if (bin_str_eq(type, len, "psk"))
4222                 conf->akm = DPP_AKM_PSK;
4223         else if (bin_str_eq(type, len, "sae"))
4224                 conf->akm = DPP_AKM_SAE;
4225         else if (bin_str_eq(type, len, "psk-sae") ||
4226                  bin_str_eq(type, len, "psk+sae"))
4227                 conf->akm = DPP_AKM_PSK_SAE;
4228         else if (bin_str_eq(type, len, "sae-dpp") ||
4229                  bin_str_eq(type, len, "dpp+sae"))
4230                 conf->akm = DPP_AKM_SAE_DPP;
4231         else if (bin_str_eq(type, len, "psk-sae-dpp") ||
4232                  bin_str_eq(type, len, "dpp+psk+sae"))
4233                 conf->akm = DPP_AKM_PSK_SAE_DPP;
4234         else if (bin_str_eq(type, len, "dpp"))
4235                 conf->akm = DPP_AKM_DPP;
4236         else
4237                 goto fail;
4238
4239         return conf;
4240 fail:
4241         dpp_configuration_free(conf);
4242         return NULL;
4243 }
4244
4245
4246 int dpp_akm_psk(enum dpp_akm akm)
4247 {
4248         return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
4249                 akm == DPP_AKM_PSK_SAE_DPP;
4250 }
4251
4252
4253 int dpp_akm_sae(enum dpp_akm akm)
4254 {
4255         return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE ||
4256                 akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
4257 }
4258
4259
4260 int dpp_akm_legacy(enum dpp_akm akm)
4261 {
4262         return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
4263                 akm == DPP_AKM_SAE;
4264 }
4265
4266
4267 int dpp_akm_dpp(enum dpp_akm akm)
4268 {
4269         return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP ||
4270                 akm == DPP_AKM_PSK_SAE_DPP;
4271 }
4272
4273
4274 int dpp_akm_ver2(enum dpp_akm akm)
4275 {
4276         return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
4277 }
4278
4279
4280 int dpp_configuration_valid(const struct dpp_configuration *conf)
4281 {
4282         if (conf->ssid_len == 0)
4283                 return 0;
4284         if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
4285                 return 0;
4286         if (dpp_akm_sae(conf->akm) && !conf->passphrase)
4287                 return 0;
4288         return 1;
4289 }
4290
4291
4292 void dpp_configuration_free(struct dpp_configuration *conf)
4293 {
4294         if (!conf)
4295                 return;
4296         str_clear_free(conf->passphrase);
4297         os_free(conf->group_id);
4298         bin_clear_free(conf, sizeof(*conf));
4299 }
4300
4301
4302 static int dpp_configuration_parse(struct dpp_authentication *auth,
4303                                    const char *cmd)
4304 {
4305         const char *pos, *end;
4306         struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
4307         struct dpp_configuration *conf = NULL;
4308
4309         pos = os_strstr(cmd, " conf=sta-");
4310         if (pos) {
4311                 conf_sta = dpp_configuration_alloc(pos + 10);
4312                 if (!conf_sta)
4313                         goto fail;
4314                 conf = conf_sta;
4315         }
4316
4317         pos = os_strstr(cmd, " conf=ap-");
4318         if (pos) {
4319                 conf_ap = dpp_configuration_alloc(pos + 9);
4320                 if (!conf_ap)
4321                         goto fail;
4322                 conf = conf_ap;
4323         }
4324
4325         if (!conf)
4326                 return 0;
4327
4328         pos = os_strstr(cmd, " ssid=");
4329         if (pos) {
4330                 pos += 6;
4331                 end = os_strchr(pos, ' ');
4332                 conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
4333                 conf->ssid_len /= 2;
4334                 if (conf->ssid_len > sizeof(conf->ssid) ||
4335                     hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0)
4336                         goto fail;
4337         } else {
4338 #ifdef CONFIG_TESTING_OPTIONS
4339                 /* use a default SSID for legacy testing reasons */
4340                 os_memcpy(conf->ssid, "test", 4);
4341                 conf->ssid_len = 4;
4342 #else /* CONFIG_TESTING_OPTIONS */
4343                 goto fail;
4344 #endif /* CONFIG_TESTING_OPTIONS */
4345         }
4346
4347         pos = os_strstr(cmd, " pass=");
4348         if (pos) {
4349                 size_t pass_len;
4350
4351                 pos += 6;
4352                 end = os_strchr(pos, ' ');
4353                 pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
4354                 pass_len /= 2;
4355                 if (pass_len > 63 || pass_len < 8)
4356                         goto fail;
4357                 conf->passphrase = os_zalloc(pass_len + 1);
4358                 if (!conf->passphrase ||
4359                     hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
4360                         goto fail;
4361         }
4362
4363         pos = os_strstr(cmd, " psk=");
4364         if (pos) {
4365                 pos += 5;
4366                 if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0)
4367                         goto fail;
4368                 conf->psk_set = 1;
4369         }
4370
4371         pos = os_strstr(cmd, " group_id=");
4372         if (pos) {
4373                 size_t group_id_len;
4374
4375                 pos += 10;
4376                 end = os_strchr(pos, ' ');
4377                 group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
4378                 conf->group_id = os_malloc(group_id_len + 1);
4379                 if (!conf->group_id)
4380                         goto fail;
4381                 os_memcpy(conf->group_id, pos, group_id_len);
4382                 conf->group_id[group_id_len] = '\0';
4383         }
4384
4385         pos = os_strstr(cmd, " expiry=");
4386         if (pos) {
4387                 long int val;
4388
4389                 pos += 8;
4390                 val = strtol(pos, NULL, 0);
4391                 if (val <= 0)
4392                         goto fail;
4393                 conf->netaccesskey_expiry = val;
4394         }
4395
4396         if (!dpp_configuration_valid(conf))
4397                 goto fail;
4398
4399         auth->conf_sta = conf_sta;
4400         auth->conf_ap = conf_ap;
4401         return 0;
4402
4403 fail:
4404         dpp_configuration_free(conf_sta);
4405         dpp_configuration_free(conf_ap);
4406         return -1;
4407 }
4408
4409
4410 static struct dpp_configurator *
4411 dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id)
4412 {
4413         struct dpp_configurator *conf;
4414
4415         if (!dpp)
4416                 return NULL;
4417
4418         dl_list_for_each(conf, &dpp->configurator,
4419                          struct dpp_configurator, list) {
4420                 if (conf->id == id)
4421                         return conf;
4422         }
4423         return NULL;
4424 }
4425
4426
4427 int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
4428                          struct dpp_authentication *auth,
4429                          const char *cmd)
4430 {
4431         const char *pos;
4432
4433         if (!cmd)
4434                 return 0;
4435
4436         wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
4437
4438         pos = os_strstr(cmd, " configurator=");
4439         if (pos) {
4440                 pos += 14;
4441                 auth->conf = dpp_configurator_get_id(dpp, atoi(pos));
4442                 if (!auth->conf) {
4443                         wpa_printf(MSG_INFO,
4444                                    "DPP: Could not find the specified configurator");
4445                         return -1;
4446                 }
4447         }
4448
4449         if (dpp_configuration_parse(auth, cmd) < 0) {
4450                 wpa_msg(msg_ctx, MSG_INFO,
4451                         "DPP: Failed to set configurator parameters");
4452                 return -1;
4453         }
4454         return 0;
4455 }
4456
4457
4458 void dpp_auth_deinit(struct dpp_authentication *auth)
4459 {
4460         if (!auth)
4461                 return;
4462         dpp_configuration_free(auth->conf_ap);
4463         dpp_configuration_free(auth->conf_sta);
4464         EVP_PKEY_free(auth->own_protocol_key);
4465         EVP_PKEY_free(auth->peer_protocol_key);
4466         wpabuf_free(auth->req_msg);
4467         wpabuf_free(auth->resp_msg);
4468         wpabuf_free(auth->conf_req);
4469         os_free(auth->connector);
4470         wpabuf_free(auth->net_access_key);
4471         wpabuf_free(auth->c_sign_key);
4472         dpp_bootstrap_info_free(auth->tmp_own_bi);
4473 #ifdef CONFIG_TESTING_OPTIONS
4474         os_free(auth->config_obj_override);
4475         os_free(auth->discovery_override);
4476         os_free(auth->groups_override);
4477 #endif /* CONFIG_TESTING_OPTIONS */
4478         bin_clear_free(auth, sizeof(*auth));
4479 }
4480
4481
4482 static struct wpabuf *
4483 dpp_build_conf_start(struct dpp_authentication *auth,
4484                      struct dpp_configuration *conf, size_t tailroom)
4485 {
4486         struct wpabuf *buf;
4487         char ssid[6 * sizeof(conf->ssid) + 1];
4488
4489 #ifdef CONFIG_TESTING_OPTIONS
4490         if (auth->discovery_override)
4491                 tailroom += os_strlen(auth->discovery_override);
4492 #endif /* CONFIG_TESTING_OPTIONS */
4493
4494         buf = wpabuf_alloc(200 + tailroom);
4495         if (!buf)
4496                 return NULL;
4497         wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":");
4498 #ifdef CONFIG_TESTING_OPTIONS
4499         if (auth->discovery_override) {
4500                 wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
4501                            auth->discovery_override);
4502                 wpabuf_put_str(buf, auth->discovery_override);
4503                 wpabuf_put_u8(buf, ',');
4504                 return buf;
4505         }
4506 #endif /* CONFIG_TESTING_OPTIONS */
4507         wpabuf_put_str(buf, "{\"ssid\":\"");
4508         json_escape_string(ssid, sizeof(ssid),
4509                            (const char *) conf->ssid, conf->ssid_len);
4510         wpabuf_put_str(buf, ssid);
4511         wpabuf_put_str(buf, "\"},");
4512
4513         return buf;
4514 }
4515
4516
4517 static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
4518                          const char *kid, const struct dpp_curve_params *curve)
4519 {
4520         struct wpabuf *pub;
4521         const u8 *pos;
4522         char *x = NULL, *y = NULL;
4523         int ret = -1;
4524
4525         pub = dpp_get_pubkey_point(key, 0);
4526         if (!pub)
4527                 goto fail;
4528         pos = wpabuf_head(pub);
4529         x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
4530         pos += curve->prime_len;
4531         y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
4532         if (!x || !y)
4533                 goto fail;
4534
4535         wpabuf_put_str(buf, "\"");
4536         wpabuf_put_str(buf, name);
4537         wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\"");
4538         wpabuf_put_str(buf, curve->jwk_crv);
4539         wpabuf_put_str(buf, "\",\"x\":\"");
4540         wpabuf_put_str(buf, x);
4541         wpabuf_put_str(buf, "\",\"y\":\"");
4542         wpabuf_put_str(buf, y);
4543         if (kid) {
4544                 wpabuf_put_str(buf, "\",\"kid\":\"");
4545                 wpabuf_put_str(buf, kid);
4546         }
4547         wpabuf_put_str(buf, "\"}");
4548         ret = 0;
4549 fail:
4550         wpabuf_free(pub);
4551         os_free(x);
4552         os_free(y);
4553         return ret;
4554 }
4555
4556
4557 static void dpp_build_legacy_cred_params(struct wpabuf *buf,
4558                                          struct dpp_configuration *conf)
4559 {
4560         if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
4561                 char pass[63 * 6 + 1];
4562
4563                 json_escape_string(pass, sizeof(pass), conf->passphrase,
4564                                    os_strlen(conf->passphrase));
4565                 wpabuf_put_str(buf, "\"pass\":\"");
4566                 wpabuf_put_str(buf, pass);
4567                 wpabuf_put_str(buf, "\"");
4568                 os_memset(pass, 0, sizeof(pass));
4569         } else if (conf->psk_set) {
4570                 char psk[2 * sizeof(conf->psk) + 1];
4571
4572                 wpa_snprintf_hex(psk, sizeof(psk),
4573                                  conf->psk, sizeof(conf->psk));
4574                 wpabuf_put_str(buf, "\"psk_hex\":\"");
4575                 wpabuf_put_str(buf, psk);
4576                 wpabuf_put_str(buf, "\"");
4577                 os_memset(psk, 0, sizeof(psk));
4578         }
4579 }
4580
4581
4582 static struct wpabuf *
4583 dpp_build_conf_obj_dpp(struct dpp_authentication *auth, int ap,
4584                        struct dpp_configuration *conf)
4585 {
4586         struct wpabuf *buf = NULL;
4587         char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
4588         size_t tailroom;
4589         const struct dpp_curve_params *curve;
4590         char jws_prot_hdr[100];
4591         size_t signed1_len, signed2_len, signed3_len;
4592         struct wpabuf *dppcon = NULL;
4593         unsigned char *signature = NULL;
4594         const unsigned char *p;
4595         size_t signature_len;
4596         EVP_MD_CTX *md_ctx = NULL;
4597         ECDSA_SIG *sig = NULL;
4598         char *dot = ".";
4599         const EVP_MD *sign_md;
4600         const BIGNUM *r, *s;
4601         size_t extra_len = 1000;
4602         int incl_legacy;
4603         enum dpp_akm akm;
4604
4605         if (!auth->conf) {
4606                 wpa_printf(MSG_INFO,
4607                            "DPP: No configurator specified - cannot generate DPP config object");
4608                 goto fail;
4609         }
4610         curve = auth->conf->curve;
4611         if (curve->hash_len == SHA256_MAC_LEN) {
4612                 sign_md = EVP_sha256();
4613         } else if (curve->hash_len == SHA384_MAC_LEN) {
4614                 sign_md = EVP_sha384();
4615         } else if (curve->hash_len == SHA512_MAC_LEN) {
4616                 sign_md = EVP_sha512();
4617         } else {
4618                 wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
4619                 goto fail;
4620         }
4621
4622         akm = conf->akm;
4623         if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
4624                 wpa_printf(MSG_DEBUG,
4625                            "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2");
4626                 akm = DPP_AKM_DPP;
4627         }
4628
4629 #ifdef CONFIG_TESTING_OPTIONS
4630         if (auth->groups_override)
4631                 extra_len += os_strlen(auth->groups_override);
4632 #endif /* CONFIG_TESTING_OPTIONS */
4633
4634         if (conf->group_id)
4635                 extra_len += os_strlen(conf->group_id);
4636
4637         /* Connector (JSON dppCon object) */
4638         dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3);
4639         if (!dppcon)
4640                 goto fail;
4641 #ifdef CONFIG_TESTING_OPTIONS
4642         if (auth->groups_override) {
4643                 wpabuf_put_u8(dppcon, '{');
4644                 if (auth->groups_override) {
4645                         wpa_printf(MSG_DEBUG,
4646                                    "DPP: TESTING - groups override: '%s'",
4647                                    auth->groups_override);
4648                         wpabuf_put_str(dppcon, "\"groups\":");
4649                         wpabuf_put_str(dppcon, auth->groups_override);
4650                         wpabuf_put_u8(dppcon, ',');
4651                 }
4652                 goto skip_groups;
4653         }
4654 #endif /* CONFIG_TESTING_OPTIONS */
4655         wpabuf_printf(dppcon, "{\"groups\":[{\"groupId\":\"%s\",",
4656                       conf->group_id ? conf->group_id : "*");
4657         wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],", ap ? "ap" : "sta");
4658 #ifdef CONFIG_TESTING_OPTIONS
4659 skip_groups:
4660 #endif /* CONFIG_TESTING_OPTIONS */
4661         if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
4662                           auth->curve) < 0) {
4663                 wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
4664                 goto fail;
4665         }
4666         if (conf->netaccesskey_expiry) {
4667                 struct os_tm tm;
4668
4669                 if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
4670                         wpa_printf(MSG_DEBUG,
4671                                    "DPP: Failed to generate expiry string");
4672                         goto fail;
4673                 }
4674                 wpabuf_printf(dppcon,
4675                               ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"",
4676                               tm.year, tm.month, tm.day,
4677                               tm.hour, tm.min, tm.sec);
4678         }
4679         wpabuf_put_u8(dppcon, '}');
4680         wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
4681                    (const char *) wpabuf_head(dppcon));
4682
4683         os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr),
4684                     "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}",
4685                     auth->conf->kid, curve->jws_alg);
4686         signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr,
4687                                              os_strlen(jws_prot_hdr),
4688                                              &signed1_len, 0);
4689         signed2 = (char *) base64_url_encode(wpabuf_head(dppcon),
4690                                              wpabuf_len(dppcon),
4691                                              &signed2_len, 0);
4692         if (!signed1 || !signed2)
4693                 goto fail;
4694
4695         md_ctx = EVP_MD_CTX_create();
4696         if (!md_ctx)
4697                 goto fail;
4698
4699         ERR_clear_error();
4700         if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL,
4701                                auth->conf->csign) != 1) {
4702                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
4703                            ERR_error_string(ERR_get_error(), NULL));
4704                 goto fail;
4705         }
4706         if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
4707             EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
4708             EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
4709                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
4710                            ERR_error_string(ERR_get_error(), NULL));
4711                 goto fail;
4712         }
4713         if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
4714                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
4715                            ERR_error_string(ERR_get_error(), NULL));
4716                 goto fail;
4717         }
4718         signature = os_malloc(signature_len);
4719         if (!signature)
4720                 goto fail;
4721         if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
4722                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
4723                            ERR_error_string(ERR_get_error(), NULL));
4724                 goto fail;
4725         }
4726         wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
4727                     signature, signature_len);
4728         /* Convert to raw coordinates r,s */
4729         p = signature;
4730         sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
4731         if (!sig)
4732                 goto fail;
4733         ECDSA_SIG_get0(sig, &r, &s);
4734         if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
4735             dpp_bn2bin_pad(s, signature + curve->prime_len,
4736                            curve->prime_len) < 0)
4737                 goto fail;
4738         signature_len = 2 * curve->prime_len;
4739         wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
4740                     signature, signature_len);
4741         signed3 = (char *) base64_url_encode(signature, signature_len,
4742                                              &signed3_len, 0);
4743         if (!signed3)
4744                 goto fail;
4745
4746         incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
4747         tailroom = 1000;
4748         tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
4749         tailroom += signed1_len + signed2_len + signed3_len;
4750         if (incl_legacy)
4751                 tailroom += 1000;
4752         buf = dpp_build_conf_start(auth, conf, tailroom);
4753         if (!buf)
4754                 goto fail;
4755
4756         wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", dpp_akm_str(akm));
4757         if (incl_legacy) {
4758                 dpp_build_legacy_cred_params(buf, conf);
4759                 wpabuf_put_str(buf, ",");
4760         }
4761         wpabuf_put_str(buf, "\"signedConnector\":\"");
4762         wpabuf_put_str(buf, signed1);
4763         wpabuf_put_u8(buf, '.');
4764         wpabuf_put_str(buf, signed2);
4765         wpabuf_put_u8(buf, '.');
4766         wpabuf_put_str(buf, signed3);
4767         wpabuf_put_str(buf, "\",");
4768         if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
4769                           curve) < 0) {
4770                 wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
4771                 goto fail;
4772         }
4773
4774         wpabuf_put_str(buf, "}}");
4775
4776         wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
4777                               wpabuf_head(buf), wpabuf_len(buf));
4778
4779 out:
4780         EVP_MD_CTX_destroy(md_ctx);
4781         ECDSA_SIG_free(sig);
4782         os_free(signed1);
4783         os_free(signed2);
4784         os_free(signed3);
4785         os_free(signature);
4786         wpabuf_free(dppcon);
4787         return buf;
4788 fail:
4789         wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
4790         wpabuf_free(buf);
4791         buf = NULL;
4792         goto out;
4793 }
4794
4795
4796 static struct wpabuf *
4797 dpp_build_conf_obj_legacy(struct dpp_authentication *auth, int ap,
4798                           struct dpp_configuration *conf)
4799 {
4800         struct wpabuf *buf;
4801
4802         buf = dpp_build_conf_start(auth, conf, 1000);
4803         if (!buf)
4804                 return NULL;
4805
4806         wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", dpp_akm_str(conf->akm));
4807         dpp_build_legacy_cred_params(buf, conf);
4808         wpabuf_put_str(buf, "}}");
4809
4810         wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
4811                               wpabuf_head(buf), wpabuf_len(buf));
4812
4813         return buf;
4814 }
4815
4816
4817 static struct wpabuf *
4818 dpp_build_conf_obj(struct dpp_authentication *auth, int ap)
4819 {
4820         struct dpp_configuration *conf;
4821
4822 #ifdef CONFIG_TESTING_OPTIONS
4823         if (auth->config_obj_override) {
4824                 wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
4825                 return wpabuf_alloc_copy(auth->config_obj_override,
4826                                          os_strlen(auth->config_obj_override));
4827         }
4828 #endif /* CONFIG_TESTING_OPTIONS */
4829
4830         conf = ap ? auth->conf_ap : auth->conf_sta;
4831         if (!conf) {
4832                 wpa_printf(MSG_DEBUG,
4833                            "DPP: No configuration available for Enrollee(%s) - reject configuration request",
4834                            ap ? "ap" : "sta");
4835                 return NULL;
4836         }
4837
4838         if (dpp_akm_dpp(conf->akm))
4839                 return dpp_build_conf_obj_dpp(auth, ap, conf);
4840         return dpp_build_conf_obj_legacy(auth, ap, conf);
4841 }
4842
4843
4844 static struct wpabuf *
4845 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
4846                     u16 e_nonce_len, int ap)
4847 {
4848         struct wpabuf *conf;
4849         size_t clear_len, attr_len;
4850         struct wpabuf *clear = NULL, *msg = NULL;
4851         u8 *wrapped;
4852         const u8 *addr[1];
4853         size_t len[1];
4854         enum dpp_status_error status;
4855
4856         conf = dpp_build_conf_obj(auth, ap);
4857         if (conf) {
4858                 wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
4859                                   wpabuf_head(conf), wpabuf_len(conf));
4860         }
4861         status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
4862         auth->conf_resp_status = status;
4863
4864         /* { E-nonce, configurationObject}ke */
4865         clear_len = 4 + e_nonce_len;
4866         if (conf)
4867                 clear_len += 4 + wpabuf_len(conf);
4868         clear = wpabuf_alloc(clear_len);
4869         attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
4870 #ifdef CONFIG_TESTING_OPTIONS
4871         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
4872                 attr_len += 5;
4873 #endif /* CONFIG_TESTING_OPTIONS */
4874         msg = wpabuf_alloc(attr_len);
4875         if (!clear || !msg)
4876                 goto fail;
4877
4878 #ifdef CONFIG_TESTING_OPTIONS
4879         if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
4880                 wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
4881                 goto skip_e_nonce;
4882         }
4883         if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
4884                 wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
4885                 wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4886                 wpabuf_put_le16(clear, e_nonce_len);
4887                 wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
4888                 wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
4889                 goto skip_e_nonce;
4890         }
4891         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
4892                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
4893                 goto skip_wrapped_data;
4894         }
4895 #endif /* CONFIG_TESTING_OPTIONS */
4896
4897         /* E-nonce */
4898         wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
4899         wpabuf_put_le16(clear, e_nonce_len);
4900         wpabuf_put_data(clear, e_nonce, e_nonce_len);
4901
4902 #ifdef CONFIG_TESTING_OPTIONS
4903 skip_e_nonce:
4904         if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
4905                 wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
4906                 goto skip_config_obj;
4907         }
4908 #endif /* CONFIG_TESTING_OPTIONS */
4909
4910         if (conf) {
4911                 wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
4912                 wpabuf_put_le16(clear, wpabuf_len(conf));
4913                 wpabuf_put_buf(clear, conf);
4914         }
4915
4916 #ifdef CONFIG_TESTING_OPTIONS
4917 skip_config_obj:
4918         if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
4919                 wpa_printf(MSG_INFO, "DPP: TESTING - Status");
4920                 goto skip_status;
4921         }
4922         if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
4923                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
4924                 status = 255;
4925         }
4926 #endif /* CONFIG_TESTING_OPTIONS */
4927
4928         /* DPP Status */
4929         dpp_build_attr_status(msg, status);
4930
4931 #ifdef CONFIG_TESTING_OPTIONS
4932 skip_status:
4933 #endif /* CONFIG_TESTING_OPTIONS */
4934
4935         addr[0] = wpabuf_head(msg);
4936         len[0] = wpabuf_len(msg);
4937         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
4938
4939         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
4940         wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4941         wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
4942
4943         wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
4944         if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
4945                             wpabuf_head(clear), wpabuf_len(clear),
4946                             1, addr, len, wrapped) < 0)
4947                 goto fail;
4948         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4949                     wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
4950
4951 #ifdef CONFIG_TESTING_OPTIONS
4952         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) {
4953                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
4954                 dpp_build_attr_status(msg, DPP_STATUS_OK);
4955         }
4956 skip_wrapped_data:
4957 #endif /* CONFIG_TESTING_OPTIONS */
4958
4959         wpa_hexdump_buf(MSG_DEBUG,
4960                         "DPP: Configuration Response attributes", msg);
4961 out:
4962         wpabuf_free(conf);
4963         wpabuf_free(clear);
4964
4965         return msg;
4966 fail:
4967         wpabuf_free(msg);
4968         msg = NULL;
4969         goto out;
4970 }
4971
4972
4973 struct wpabuf *
4974 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
4975                 size_t attr_len)
4976 {
4977         const u8 *wrapped_data, *e_nonce, *config_attr;
4978         u16 wrapped_data_len, e_nonce_len, config_attr_len;
4979         u8 *unwrapped = NULL;
4980         size_t unwrapped_len = 0;
4981         struct wpabuf *resp = NULL;
4982         struct json_token *root = NULL, *token;
4983         int ap;
4984
4985 #ifdef CONFIG_TESTING_OPTIONS
4986         if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
4987                 wpa_printf(MSG_INFO,
4988                            "DPP: TESTING - stop at Config Request");
4989                 return NULL;
4990         }
4991 #endif /* CONFIG_TESTING_OPTIONS */
4992
4993         if (dpp_check_attrs(attr_start, attr_len) < 0) {
4994                 dpp_auth_fail(auth, "Invalid attribute in config request");
4995                 return NULL;
4996         }
4997
4998         wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
4999                                     &wrapped_data_len);
5000         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5001                 dpp_auth_fail(auth,
5002                               "Missing or invalid required Wrapped Data attribute");
5003                 return NULL;
5004         }
5005
5006         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5007                     wrapped_data, wrapped_data_len);
5008         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5009         unwrapped = os_malloc(unwrapped_len);
5010         if (!unwrapped)
5011                 return NULL;
5012         if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5013                             wrapped_data, wrapped_data_len,
5014                             0, NULL, NULL, unwrapped) < 0) {
5015                 dpp_auth_fail(auth, "AES-SIV decryption failed");
5016                 goto fail;
5017         }
5018         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5019                     unwrapped, unwrapped_len);
5020
5021         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5022                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5023                 goto fail;
5024         }
5025
5026         e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5027                                DPP_ATTR_ENROLLEE_NONCE,
5028                                &e_nonce_len);
5029         if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5030                 dpp_auth_fail(auth,
5031                               "Missing or invalid Enrollee Nonce attribute");
5032                 goto fail;
5033         }
5034         wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5035         os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
5036
5037         config_attr = dpp_get_attr(unwrapped, unwrapped_len,
5038                                    DPP_ATTR_CONFIG_ATTR_OBJ,
5039                                    &config_attr_len);
5040         if (!config_attr) {
5041                 dpp_auth_fail(auth,
5042                               "Missing or invalid Config Attributes attribute");
5043                 goto fail;
5044         }
5045         wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
5046                           config_attr, config_attr_len);
5047
5048         root = json_parse((const char *) config_attr, config_attr_len);
5049         if (!root) {
5050                 dpp_auth_fail(auth, "Could not parse Config Attributes");
5051                 goto fail;
5052         }
5053
5054         token = json_get_member(root, "name");
5055         if (!token || token->type != JSON_STRING) {
5056                 dpp_auth_fail(auth, "No Config Attributes - name");
5057                 goto fail;
5058         }
5059         wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
5060
5061         token = json_get_member(root, "wi-fi_tech");
5062         if (!token || token->type != JSON_STRING) {
5063                 dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
5064                 goto fail;
5065         }
5066         wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
5067         if (os_strcmp(token->string, "infra") != 0) {
5068                 wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
5069                            token->string);
5070                 dpp_auth_fail(auth, "Unsupported wi-fi_tech");
5071                 goto fail;
5072         }
5073
5074         token = json_get_member(root, "netRole");
5075         if (!token || token->type != JSON_STRING) {
5076                 dpp_auth_fail(auth, "No Config Attributes - netRole");
5077                 goto fail;
5078         }
5079         wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
5080         if (os_strcmp(token->string, "sta") == 0) {
5081                 ap = 0;
5082         } else if (os_strcmp(token->string, "ap") == 0) {
5083                 ap = 1;
5084         } else {
5085                 wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
5086                            token->string);
5087                 dpp_auth_fail(auth, "Unsupported netRole");
5088                 goto fail;
5089         }
5090
5091         resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, ap);
5092
5093 fail:
5094         json_free(root);
5095         os_free(unwrapped);
5096         return resp;
5097 }
5098
5099
5100 static struct wpabuf *
5101 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
5102                        const u8 *prot_hdr, u16 prot_hdr_len,
5103                        const EVP_MD **ret_md)
5104 {
5105         struct json_token *root, *token;
5106         struct wpabuf *kid = NULL;
5107
5108         root = json_parse((const char *) prot_hdr, prot_hdr_len);
5109         if (!root) {
5110                 wpa_printf(MSG_DEBUG,
5111                            "DPP: JSON parsing failed for JWS Protected Header");
5112                 goto fail;
5113         }
5114
5115         if (root->type != JSON_OBJECT) {
5116                 wpa_printf(MSG_DEBUG,
5117                            "DPP: JWS Protected Header root is not an object");
5118                 goto fail;
5119         }
5120
5121         token = json_get_member(root, "typ");
5122         if (!token || token->type != JSON_STRING) {
5123                 wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
5124                 goto fail;
5125         }
5126         wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
5127                    token->string);
5128         if (os_strcmp(token->string, "dppCon") != 0) {
5129                 wpa_printf(MSG_DEBUG,
5130                            "DPP: Unsupported JWS Protected Header typ=%s",
5131                            token->string);
5132                 goto fail;
5133         }
5134
5135         token = json_get_member(root, "alg");
5136         if (!token || token->type != JSON_STRING) {
5137                 wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
5138                 goto fail;
5139         }
5140         wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
5141                    token->string);
5142         if (os_strcmp(token->string, curve->jws_alg) != 0) {
5143                 wpa_printf(MSG_DEBUG,
5144                            "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
5145                            token->string, curve->jws_alg);
5146                 goto fail;
5147         }
5148         if (os_strcmp(token->string, "ES256") == 0 ||
5149             os_strcmp(token->string, "BS256") == 0)
5150                 *ret_md = EVP_sha256();
5151         else if (os_strcmp(token->string, "ES384") == 0 ||
5152                  os_strcmp(token->string, "BS384") == 0)
5153                 *ret_md = EVP_sha384();
5154         else if (os_strcmp(token->string, "ES512") == 0 ||
5155                  os_strcmp(token->string, "BS512") == 0)
5156                 *ret_md = EVP_sha512();
5157         else
5158                 *ret_md = NULL;
5159         if (!*ret_md) {
5160                 wpa_printf(MSG_DEBUG,
5161                            "DPP: Unsupported JWS Protected Header alg=%s",
5162                            token->string);
5163                 goto fail;
5164         }
5165
5166         kid = json_get_member_base64url(root, "kid");
5167         if (!kid) {
5168                 wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
5169                 goto fail;
5170         }
5171         wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
5172                         kid);
5173
5174 fail:
5175         json_free(root);
5176         return kid;
5177 }
5178
5179
5180 static int dpp_parse_cred_legacy(struct dpp_authentication *auth,
5181                                  struct json_token *cred)
5182 {
5183         struct json_token *pass, *psk_hex;
5184
5185         wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
5186
5187         pass = json_get_member(cred, "pass");
5188         psk_hex = json_get_member(cred, "psk_hex");
5189
5190         if (pass && pass->type == JSON_STRING) {
5191                 size_t len = os_strlen(pass->string);
5192
5193                 wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
5194                                       pass->string, len);
5195                 if (len < 8 || len > 63)
5196                         return -1;
5197                 os_strlcpy(auth->passphrase, pass->string,
5198                            sizeof(auth->passphrase));
5199         } else if (psk_hex && psk_hex->type == JSON_STRING) {
5200                 if (dpp_akm_sae(auth->akm) && !dpp_akm_psk(auth->akm)) {
5201                         wpa_printf(MSG_DEBUG,
5202                                    "DPP: Unexpected psk_hex with akm=sae");
5203                         return -1;
5204                 }
5205                 if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
5206                     hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) {
5207                         wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
5208                         return -1;
5209                 }
5210                 wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
5211                                 auth->psk, PMK_LEN);
5212                 auth->psk_set = 1;
5213         } else {
5214                 wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
5215                 return -1;
5216         }
5217
5218         if (dpp_akm_sae(auth->akm) && !auth->passphrase[0]) {
5219                 wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
5220                 return -1;
5221         }
5222
5223         return 0;
5224 }
5225
5226
5227 static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
5228                                 const struct dpp_curve_params **key_curve)
5229 {
5230         struct json_token *token;
5231         const struct dpp_curve_params *curve;
5232         struct wpabuf *x = NULL, *y = NULL;
5233         EC_GROUP *group;
5234         EVP_PKEY *pkey = NULL;
5235
5236         token = json_get_member(jwk, "kty");
5237         if (!token || token->type != JSON_STRING) {
5238                 wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
5239                 goto fail;
5240         }
5241         if (os_strcmp(token->string, "EC") != 0) {
5242                 wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
5243                            token->string);
5244                 goto fail;
5245         }
5246
5247         token = json_get_member(jwk, "crv");
5248         if (!token || token->type != JSON_STRING) {
5249                 wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
5250                 goto fail;
5251         }
5252         curve = dpp_get_curve_jwk_crv(token->string);
5253         if (!curve) {
5254                 wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
5255                            token->string);
5256                 goto fail;
5257         }
5258
5259         x = json_get_member_base64url(jwk, "x");
5260         if (!x) {
5261                 wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
5262                 goto fail;
5263         }
5264         wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
5265         if (wpabuf_len(x) != curve->prime_len) {
5266                 wpa_printf(MSG_DEBUG,
5267                            "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
5268                            (unsigned int) wpabuf_len(x),
5269                            (unsigned int) curve->prime_len, curve->name);
5270                 goto fail;
5271         }
5272
5273         y = json_get_member_base64url(jwk, "y");
5274         if (!y) {
5275                 wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
5276                 goto fail;
5277         }
5278         wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
5279         if (wpabuf_len(y) != curve->prime_len) {
5280                 wpa_printf(MSG_DEBUG,
5281                            "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
5282                            (unsigned int) wpabuf_len(y),
5283                            (unsigned int) curve->prime_len, curve->name);
5284                 goto fail;
5285         }
5286
5287         group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
5288         if (!group) {
5289                 wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
5290                 goto fail;
5291         }
5292
5293         pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y),
5294                                           wpabuf_len(x));
5295         EC_GROUP_free(group);
5296         *key_curve = curve;
5297
5298 fail:
5299         wpabuf_free(x);
5300         wpabuf_free(y);
5301
5302         return pkey;
5303 }
5304
5305
5306 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
5307 {
5308         struct os_time now;
5309         unsigned int year, month, day, hour, min, sec;
5310         os_time_t utime;
5311         const char *pos;
5312
5313         /* ISO 8601 date and time:
5314          * <date>T<time>
5315          * YYYY-MM-DDTHH:MM:SSZ
5316          * YYYY-MM-DDTHH:MM:SS+03:00
5317          */
5318         if (os_strlen(timestamp) < 19) {
5319                 wpa_printf(MSG_DEBUG,
5320                            "DPP: Too short timestamp - assume expired key");
5321                 return 1;
5322         }
5323         if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
5324                    &year, &month, &day, &hour, &min, &sec) != 6) {
5325                 wpa_printf(MSG_DEBUG,
5326                            "DPP: Failed to parse expiration day - assume expired key");
5327                 return 1;
5328         }
5329
5330         if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
5331                 wpa_printf(MSG_DEBUG,
5332                            "DPP: Invalid date/time information - assume expired key");
5333                 return 1;
5334         }
5335
5336         pos = timestamp + 19;
5337         if (*pos == 'Z' || *pos == '\0') {
5338                 /* In UTC - no need to adjust */
5339         } else if (*pos == '-' || *pos == '+') {
5340                 int items;
5341
5342                 /* Adjust local time to UTC */
5343                 items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
5344                 if (items < 1) {
5345                         wpa_printf(MSG_DEBUG,
5346                                    "DPP: Invalid time zone designator (%s) - assume expired key",
5347                                    pos);
5348                         return 1;
5349                 }
5350                 if (*pos == '-')
5351                         utime += 3600 * hour;
5352                 if (*pos == '+')
5353                         utime -= 3600 * hour;
5354                 if (items > 1) {
5355                         if (*pos == '-')
5356                                 utime += 60 * min;
5357                         if (*pos == '+')
5358                                 utime -= 60 * min;
5359                 }
5360         } else {
5361                 wpa_printf(MSG_DEBUG,
5362                            "DPP: Invalid time zone designator (%s) - assume expired key",
5363                            pos);
5364                 return 1;
5365         }
5366         if (expiry)
5367                 *expiry = utime;
5368
5369         if (os_get_time(&now) < 0) {
5370                 wpa_printf(MSG_DEBUG,
5371                            "DPP: Cannot get current time - assume expired key");
5372                 return 1;
5373         }
5374
5375         if (now.sec > utime) {
5376                 wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
5377                            utime, now.sec);
5378                 return 1;
5379         }
5380
5381         return 0;
5382 }
5383
5384
5385 static int dpp_parse_connector(struct dpp_authentication *auth,
5386                                const unsigned char *payload,
5387                                u16 payload_len)
5388 {
5389         struct json_token *root, *groups, *netkey, *token;
5390         int ret = -1;
5391         EVP_PKEY *key = NULL;
5392         const struct dpp_curve_params *curve;
5393         unsigned int rules = 0;
5394
5395         root = json_parse((const char *) payload, payload_len);
5396         if (!root) {
5397                 wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
5398                 goto fail;
5399         }
5400
5401         groups = json_get_member(root, "groups");
5402         if (!groups || groups->type != JSON_ARRAY) {
5403                 wpa_printf(MSG_DEBUG, "DPP: No groups array found");
5404                 goto skip_groups;
5405         }
5406         for (token = groups->child; token; token = token->sibling) {
5407                 struct json_token *id, *role;
5408
5409                 id = json_get_member(token, "groupId");
5410                 if (!id || id->type != JSON_STRING) {
5411                         wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
5412                         goto fail;
5413                 }
5414
5415                 role = json_get_member(token, "netRole");
5416                 if (!role || role->type != JSON_STRING) {
5417                         wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
5418                         goto fail;
5419                 }
5420                 wpa_printf(MSG_DEBUG,
5421                            "DPP: connector group: groupId='%s' netRole='%s'",
5422                            id->string, role->string);
5423                 rules++;
5424         }
5425 skip_groups:
5426
5427         if (!rules) {
5428                 wpa_printf(MSG_DEBUG,
5429                            "DPP: Connector includes no groups");
5430                 goto fail;
5431         }
5432
5433         token = json_get_member(root, "expiry");
5434         if (!token || token->type != JSON_STRING) {
5435                 wpa_printf(MSG_DEBUG,
5436                            "DPP: No expiry string found - connector does not expire");
5437         } else {
5438                 wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
5439                 if (dpp_key_expired(token->string,
5440                                     &auth->net_access_key_expiry)) {
5441                         wpa_printf(MSG_DEBUG,
5442                                    "DPP: Connector (netAccessKey) has expired");
5443                         goto fail;
5444                 }
5445         }
5446
5447         netkey = json_get_member(root, "netAccessKey");
5448         if (!netkey || netkey->type != JSON_OBJECT) {
5449                 wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
5450                 goto fail;
5451         }
5452
5453         key = dpp_parse_jwk(netkey, &curve);
5454         if (!key)
5455                 goto fail;
5456         dpp_debug_print_key("DPP: Received netAccessKey", key);
5457
5458         if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
5459                 wpa_printf(MSG_DEBUG,
5460                            "DPP: netAccessKey in connector does not match own protocol key");
5461 #ifdef CONFIG_TESTING_OPTIONS
5462                 if (auth->ignore_netaccesskey_mismatch) {
5463                         wpa_printf(MSG_DEBUG,
5464                                    "DPP: TESTING - skip netAccessKey mismatch");
5465                 } else {
5466                         goto fail;
5467                 }
5468 #else /* CONFIG_TESTING_OPTIONS */
5469                 goto fail;
5470 #endif /* CONFIG_TESTING_OPTIONS */
5471         }
5472
5473         ret = 0;
5474 fail:
5475         EVP_PKEY_free(key);
5476         json_free(root);
5477         return ret;
5478 }
5479
5480
5481 static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
5482 {
5483         struct wpabuf *uncomp;
5484         int res;
5485         u8 hash[SHA256_MAC_LEN];
5486         const u8 *addr[1];
5487         size_t len[1];
5488
5489         if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
5490                 return -1;
5491         uncomp = dpp_get_pubkey_point(pub, 1);
5492         if (!uncomp)
5493                 return -1;
5494         addr[0] = wpabuf_head(uncomp);
5495         len[0] = wpabuf_len(uncomp);
5496         wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
5497                     addr[0], len[0]);
5498         res = sha256_vector(1, addr, len, hash);
5499         wpabuf_free(uncomp);
5500         if (res < 0)
5501                 return -1;
5502         if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
5503                 wpa_printf(MSG_DEBUG,
5504                            "DPP: Received hash value does not match calculated public key hash value");
5505                 wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
5506                             hash, SHA256_MAC_LEN);
5507                 return -1;
5508         }
5509         return 0;
5510 }
5511
5512
5513 static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign)
5514 {
5515         unsigned char *der = NULL;
5516         int der_len;
5517
5518         der_len = i2d_PUBKEY(csign, &der);
5519         if (der_len <= 0)
5520                 return;
5521         wpabuf_free(auth->c_sign_key);
5522         auth->c_sign_key = wpabuf_alloc_copy(der, der_len);
5523         OPENSSL_free(der);
5524 }
5525
5526
5527 static void dpp_copy_netaccesskey(struct dpp_authentication *auth)
5528 {
5529         unsigned char *der = NULL;
5530         int der_len;
5531         EC_KEY *eckey;
5532
5533         eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
5534         if (!eckey)
5535                 return;
5536
5537         der_len = i2d_ECPrivateKey(eckey, &der);
5538         if (der_len <= 0) {
5539                 EC_KEY_free(eckey);
5540                 return;
5541         }
5542         wpabuf_free(auth->net_access_key);
5543         auth->net_access_key = wpabuf_alloc_copy(der, der_len);
5544         OPENSSL_free(der);
5545         EC_KEY_free(eckey);
5546 }
5547
5548
5549 struct dpp_signed_connector_info {
5550         unsigned char *payload;
5551         size_t payload_len;
5552 };
5553
5554 static enum dpp_status_error
5555 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
5556                              EVP_PKEY *csign_pub, const char *connector)
5557 {
5558         enum dpp_status_error ret = 255;
5559         const char *pos, *end, *signed_start, *signed_end;
5560         struct wpabuf *kid = NULL;
5561         unsigned char *prot_hdr = NULL, *signature = NULL;
5562         size_t prot_hdr_len = 0, signature_len = 0;
5563         const EVP_MD *sign_md = NULL;
5564         unsigned char *der = NULL;
5565         int der_len;
5566         int res;
5567         EVP_MD_CTX *md_ctx = NULL;
5568         ECDSA_SIG *sig = NULL;
5569         BIGNUM *r = NULL, *s = NULL;
5570         const struct dpp_curve_params *curve;
5571         EC_KEY *eckey;
5572         const EC_GROUP *group;
5573         int nid;
5574
5575         eckey = EVP_PKEY_get1_EC_KEY(csign_pub);
5576         if (!eckey)
5577                 goto fail;
5578         group = EC_KEY_get0_group(eckey);
5579         if (!group)
5580                 goto fail;
5581         nid = EC_GROUP_get_curve_name(group);
5582         curve = dpp_get_curve_nid(nid);
5583         if (!curve)
5584                 goto fail;
5585         wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
5586         os_memset(info, 0, sizeof(*info));
5587
5588         signed_start = pos = connector;
5589         end = os_strchr(pos, '.');
5590         if (!end) {
5591                 wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
5592                 ret = DPP_STATUS_INVALID_CONNECTOR;
5593                 goto fail;
5594         }
5595         prot_hdr = base64_url_decode((const unsigned char *) pos,
5596                                      end - pos, &prot_hdr_len);
5597         if (!prot_hdr) {
5598                 wpa_printf(MSG_DEBUG,
5599                            "DPP: Failed to base64url decode signedConnector JWS Protected Header");
5600                 ret = DPP_STATUS_INVALID_CONNECTOR;
5601                 goto fail;
5602         }
5603         wpa_hexdump_ascii(MSG_DEBUG,
5604                           "DPP: signedConnector - JWS Protected Header",
5605                           prot_hdr, prot_hdr_len);
5606         kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
5607         if (!kid) {
5608                 ret = DPP_STATUS_INVALID_CONNECTOR;
5609                 goto fail;
5610         }
5611         if (wpabuf_len(kid) != SHA256_MAC_LEN) {
5612                 wpa_printf(MSG_DEBUG,
5613                            "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
5614                            (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
5615                 ret = DPP_STATUS_INVALID_CONNECTOR;
5616                 goto fail;
5617         }
5618
5619         pos = end + 1;
5620         end = os_strchr(pos, '.');
5621         if (!end) {
5622                 wpa_printf(MSG_DEBUG,
5623                            "DPP: Missing dot(2) in signedConnector");
5624                 ret = DPP_STATUS_INVALID_CONNECTOR;
5625                 goto fail;
5626         }
5627         signed_end = end - 1;
5628         info->payload = base64_url_decode((const unsigned char *) pos,
5629                                           end - pos, &info->payload_len);
5630         if (!info->payload) {
5631                 wpa_printf(MSG_DEBUG,
5632                            "DPP: Failed to base64url decode signedConnector JWS Payload");
5633                 ret = DPP_STATUS_INVALID_CONNECTOR;
5634                 goto fail;
5635         }
5636         wpa_hexdump_ascii(MSG_DEBUG,
5637                           "DPP: signedConnector - JWS Payload",
5638                           info->payload, info->payload_len);
5639         pos = end + 1;
5640         signature = base64_url_decode((const unsigned char *) pos,
5641                                       os_strlen(pos), &signature_len);
5642         if (!signature) {
5643                 wpa_printf(MSG_DEBUG,
5644                            "DPP: Failed to base64url decode signedConnector signature");
5645                 ret = DPP_STATUS_INVALID_CONNECTOR;
5646                 goto fail;
5647                 }
5648         wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
5649                     signature, signature_len);
5650
5651         if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
5652                 ret = DPP_STATUS_NO_MATCH;
5653                 goto fail;
5654         }
5655
5656         if (signature_len & 0x01) {
5657                 wpa_printf(MSG_DEBUG,
5658                            "DPP: Unexpected signedConnector signature length (%d)",
5659                            (int) signature_len);
5660                 ret = DPP_STATUS_INVALID_CONNECTOR;
5661                 goto fail;
5662         }
5663
5664         /* JWS Signature encodes the signature (r,s) as two octet strings. Need
5665          * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
5666         r = BN_bin2bn(signature, signature_len / 2, NULL);
5667         s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
5668         sig = ECDSA_SIG_new();
5669         if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
5670                 goto fail;
5671         r = NULL;
5672         s = NULL;
5673
5674         der_len = i2d_ECDSA_SIG(sig, &der);
5675         if (der_len <= 0) {
5676                 wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
5677                 goto fail;
5678         }
5679         wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
5680         md_ctx = EVP_MD_CTX_create();
5681         if (!md_ctx)
5682                 goto fail;
5683
5684         ERR_clear_error();
5685         if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
5686                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
5687                            ERR_error_string(ERR_get_error(), NULL));
5688                 goto fail;
5689         }
5690         if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
5691                                    signed_end - signed_start + 1) != 1) {
5692                 wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
5693                            ERR_error_string(ERR_get_error(), NULL));
5694                 goto fail;
5695         }
5696         res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
5697         if (res != 1) {
5698                 wpa_printf(MSG_DEBUG,
5699                            "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
5700                            res, ERR_error_string(ERR_get_error(), NULL));
5701                 ret = DPP_STATUS_INVALID_CONNECTOR;
5702                 goto fail;
5703         }
5704
5705         ret = DPP_STATUS_OK;
5706 fail:
5707         EC_KEY_free(eckey);
5708         EVP_MD_CTX_destroy(md_ctx);
5709         os_free(prot_hdr);
5710         wpabuf_free(kid);
5711         os_free(signature);
5712         ECDSA_SIG_free(sig);
5713         BN_free(r);
5714         BN_free(s);
5715         OPENSSL_free(der);
5716         return ret;
5717 }
5718
5719
5720 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
5721                               struct json_token *cred)
5722 {
5723         struct dpp_signed_connector_info info;
5724         struct json_token *token, *csign;
5725         int ret = -1;
5726         EVP_PKEY *csign_pub = NULL;
5727         const struct dpp_curve_params *key_curve = NULL;
5728         const char *signed_connector;
5729
5730         os_memset(&info, 0, sizeof(info));
5731
5732         if (dpp_akm_psk(auth->akm) || dpp_akm_sae(auth->akm)) {
5733                 wpa_printf(MSG_DEBUG,
5734                            "DPP: Legacy credential included in Connector credential");
5735                 if (dpp_parse_cred_legacy(auth, cred) < 0)
5736                         return -1;
5737         }
5738
5739         wpa_printf(MSG_DEBUG, "DPP: Connector credential");
5740
5741         csign = json_get_member(cred, "csign");
5742         if (!csign || csign->type != JSON_OBJECT) {
5743                 wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
5744                 goto fail;
5745         }
5746
5747         csign_pub = dpp_parse_jwk(csign, &key_curve);
5748         if (!csign_pub) {
5749                 wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
5750                 goto fail;
5751         }
5752         dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
5753
5754         token = json_get_member(cred, "signedConnector");
5755         if (!token || token->type != JSON_STRING) {
5756                 wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
5757                 goto fail;
5758         }
5759         wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
5760                           token->string, os_strlen(token->string));
5761         signed_connector = token->string;
5762
5763         if (os_strchr(signed_connector, '"') ||
5764             os_strchr(signed_connector, '\n')) {
5765                 wpa_printf(MSG_DEBUG,
5766                            "DPP: Unexpected character in signedConnector");
5767                 goto fail;
5768         }
5769
5770         if (dpp_process_signed_connector(&info, csign_pub,
5771                                          signed_connector) != DPP_STATUS_OK)
5772                 goto fail;
5773
5774         if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
5775                 wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
5776                 goto fail;
5777         }
5778
5779         os_free(auth->connector);
5780         auth->connector = os_strdup(signed_connector);
5781
5782         dpp_copy_csign(auth, csign_pub);
5783         dpp_copy_netaccesskey(auth);
5784
5785         ret = 0;
5786 fail:
5787         EVP_PKEY_free(csign_pub);
5788         os_free(info.payload);
5789         return ret;
5790 }
5791
5792
5793 const char * dpp_akm_str(enum dpp_akm akm)
5794 {
5795         switch (akm) {
5796         case DPP_AKM_DPP:
5797                 return "dpp";
5798         case DPP_AKM_PSK:
5799                 return "psk";
5800         case DPP_AKM_SAE:
5801                 return "sae";
5802         case DPP_AKM_PSK_SAE:
5803                 return "psk+sae";
5804         case DPP_AKM_SAE_DPP:
5805                 return "dpp+sae";
5806         case DPP_AKM_PSK_SAE_DPP:
5807                 return "dpp+psk+sae";
5808         default:
5809                 return "??";
5810         }
5811 }
5812
5813
5814 static enum dpp_akm dpp_akm_from_str(const char *akm)
5815 {
5816         if (os_strcmp(akm, "psk") == 0)
5817                 return DPP_AKM_PSK;
5818         if (os_strcmp(akm, "sae") == 0)
5819                 return DPP_AKM_SAE;
5820         if (os_strcmp(akm, "psk+sae") == 0)
5821                 return DPP_AKM_PSK_SAE;
5822         if (os_strcmp(akm, "dpp") == 0)
5823                 return DPP_AKM_DPP;
5824         if (os_strcmp(akm, "dpp+sae") == 0)
5825                 return DPP_AKM_SAE_DPP;
5826         if (os_strcmp(akm, "dpp+psk+sae") == 0)
5827                 return DPP_AKM_PSK_SAE_DPP;
5828         return DPP_AKM_UNKNOWN;
5829 }
5830
5831
5832 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
5833                               const u8 *conf_obj, u16 conf_obj_len)
5834 {
5835         int ret = -1;
5836         struct json_token *root, *token, *discovery, *cred;
5837
5838         root = json_parse((const char *) conf_obj, conf_obj_len);
5839         if (!root)
5840                 return -1;
5841         if (root->type != JSON_OBJECT) {
5842                 dpp_auth_fail(auth, "JSON root is not an object");
5843                 goto fail;
5844         }
5845
5846         token = json_get_member(root, "wi-fi_tech");
5847         if (!token || token->type != JSON_STRING) {
5848                 dpp_auth_fail(auth, "No wi-fi_tech string value found");
5849                 goto fail;
5850         }
5851         if (os_strcmp(token->string, "infra") != 0) {
5852                 wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
5853                            token->string);
5854                 dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
5855                 goto fail;
5856         }
5857
5858         discovery = json_get_member(root, "discovery");
5859         if (!discovery || discovery->type != JSON_OBJECT) {
5860                 dpp_auth_fail(auth, "No discovery object in JSON");
5861                 goto fail;
5862         }
5863
5864         token = json_get_member(discovery, "ssid");
5865         if (!token || token->type != JSON_STRING) {
5866                 dpp_auth_fail(auth, "No discovery::ssid string value found");
5867                 goto fail;
5868         }
5869         wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
5870                           token->string, os_strlen(token->string));
5871         if (os_strlen(token->string) > SSID_MAX_LEN) {
5872                 dpp_auth_fail(auth, "Too long discovery::ssid string value");
5873                 goto fail;
5874         }
5875         auth->ssid_len = os_strlen(token->string);
5876         os_memcpy(auth->ssid, token->string, auth->ssid_len);
5877
5878         cred = json_get_member(root, "cred");
5879         if (!cred || cred->type != JSON_OBJECT) {
5880                 dpp_auth_fail(auth, "No cred object in JSON");
5881                 goto fail;
5882         }
5883
5884         token = json_get_member(cred, "akm");
5885         if (!token || token->type != JSON_STRING) {
5886                 dpp_auth_fail(auth, "No cred::akm string value found");
5887                 goto fail;
5888         }
5889         auth->akm = dpp_akm_from_str(token->string);
5890
5891         if (dpp_akm_legacy(auth->akm)) {
5892                 if (dpp_parse_cred_legacy(auth, cred) < 0)
5893                         goto fail;
5894         } else if (dpp_akm_dpp(auth->akm)) {
5895                 if (dpp_parse_cred_dpp(auth, cred) < 0)
5896                         goto fail;
5897         } else {
5898                 wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
5899                            token->string);
5900                 dpp_auth_fail(auth, "Unsupported akm");
5901                 goto fail;
5902         }
5903
5904         wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
5905         ret = 0;
5906 fail:
5907         json_free(root);
5908         return ret;
5909 }
5910
5911
5912 int dpp_conf_resp_rx(struct dpp_authentication *auth,
5913                      const struct wpabuf *resp)
5914 {
5915         const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
5916         u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
5917         const u8 *addr[1];
5918         size_t len[1];
5919         u8 *unwrapped = NULL;
5920         size_t unwrapped_len = 0;
5921         int ret = -1;
5922
5923         auth->conf_resp_status = 255;
5924
5925         if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
5926                 dpp_auth_fail(auth, "Invalid attribute in config response");
5927                 return -1;
5928         }
5929
5930         wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
5931                                     DPP_ATTR_WRAPPED_DATA,
5932                                     &wrapped_data_len);
5933         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5934                 dpp_auth_fail(auth,
5935                               "Missing or invalid required Wrapped Data attribute");
5936                 return -1;
5937         }
5938
5939         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5940                     wrapped_data, wrapped_data_len);
5941         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5942         unwrapped = os_malloc(unwrapped_len);
5943         if (!unwrapped)
5944                 return -1;
5945
5946         addr[0] = wpabuf_head(resp);
5947         len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
5948         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
5949
5950         if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5951                             wrapped_data, wrapped_data_len,
5952                             1, addr, len, unwrapped) < 0) {
5953                 dpp_auth_fail(auth, "AES-SIV decryption failed");
5954                 goto fail;
5955         }
5956         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5957                     unwrapped, unwrapped_len);
5958
5959         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5960                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5961                 goto fail;
5962         }
5963
5964         e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5965                                DPP_ATTR_ENROLLEE_NONCE,
5966                                &e_nonce_len);
5967         if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5968                 dpp_auth_fail(auth,
5969                               "Missing or invalid Enrollee Nonce attribute");
5970                 goto fail;
5971         }
5972         wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5973         if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
5974                 dpp_auth_fail(auth, "Enrollee Nonce mismatch");
5975                 goto fail;
5976         }
5977
5978         status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
5979                               DPP_ATTR_STATUS, &status_len);
5980         if (!status || status_len < 1) {
5981                 dpp_auth_fail(auth,
5982                               "Missing or invalid required DPP Status attribute");
5983                 goto fail;
5984         }
5985         auth->conf_resp_status = status[0];
5986         wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
5987         if (status[0] != DPP_STATUS_OK) {
5988                 dpp_auth_fail(auth, "Configurator rejected configuration");
5989                 goto fail;
5990         }
5991
5992         conf_obj = dpp_get_attr(unwrapped, unwrapped_len,
5993                                 DPP_ATTR_CONFIG_OBJ, &conf_obj_len);
5994         if (!conf_obj) {
5995                 dpp_auth_fail(auth,
5996                               "Missing required Configuration Object attribute");
5997                 goto fail;
5998         }
5999         wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
6000                           conf_obj, conf_obj_len);
6001         if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
6002                 goto fail;
6003
6004         ret = 0;
6005
6006 fail:
6007         os_free(unwrapped);
6008         return ret;
6009 }
6010
6011
6012 #ifdef CONFIG_DPP2
6013 enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
6014                                          const u8 *hdr,
6015                                          const u8 *attr_start, size_t attr_len)
6016 {
6017         const u8 *wrapped_data, *status, *e_nonce;
6018         u16 wrapped_data_len, status_len, e_nonce_len;
6019         const u8 *addr[2];
6020         size_t len[2];
6021         u8 *unwrapped = NULL;
6022         size_t unwrapped_len = 0;
6023         enum dpp_status_error ret = 256;
6024
6025         wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
6026                                     &wrapped_data_len);
6027         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
6028                 dpp_auth_fail(auth,
6029                               "Missing or invalid required Wrapped Data attribute");
6030                 goto fail;
6031         }
6032         wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
6033                     wrapped_data, wrapped_data_len);
6034
6035         attr_len = wrapped_data - 4 - attr_start;
6036
6037         addr[0] = hdr;
6038         len[0] = DPP_HDR_LEN;
6039         addr[1] = attr_start;
6040         len[1] = attr_len;
6041         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
6042         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
6043         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
6044                     wrapped_data, wrapped_data_len);
6045         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
6046         unwrapped = os_malloc(unwrapped_len);
6047         if (!unwrapped)
6048                 goto fail;
6049         if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
6050                             wrapped_data, wrapped_data_len,
6051                             2, addr, len, unwrapped) < 0) {
6052                 dpp_auth_fail(auth, "AES-SIV decryption failed");
6053                 goto fail;
6054         }
6055         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
6056                     unwrapped, unwrapped_len);
6057
6058         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
6059                 dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
6060                 goto fail;
6061         }
6062
6063         e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
6064                                DPP_ATTR_ENROLLEE_NONCE,
6065                                &e_nonce_len);
6066         if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
6067                 dpp_auth_fail(auth,
6068                               "Missing or invalid Enrollee Nonce attribute");
6069                 goto fail;
6070         }
6071         wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
6072         if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
6073                 dpp_auth_fail(auth, "Enrollee Nonce mismatch");
6074                 wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
6075                             auth->e_nonce, e_nonce_len);
6076                 goto fail;
6077         }
6078
6079         status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS,
6080                               &status_len);
6081         if (!status || status_len < 1) {
6082                 dpp_auth_fail(auth,
6083                               "Missing or invalid required DPP Status attribute");
6084                 goto fail;
6085         }
6086         wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
6087         ret = status[0];
6088
6089 fail:
6090         bin_clear_free(unwrapped, unwrapped_len);
6091         return ret;
6092 }
6093 #endif /* CONFIG_DPP2 */
6094
6095
6096 struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
6097                                       enum dpp_status_error status)
6098 {
6099         struct wpabuf *msg, *clear;
6100         size_t nonce_len, clear_len, attr_len;
6101         const u8 *addr[2];
6102         size_t len[2];
6103         u8 *wrapped;
6104
6105         nonce_len = auth->curve->nonce_len;
6106         clear_len = 5 + 4 + nonce_len;
6107         attr_len = 4 + clear_len + AES_BLOCK_SIZE;
6108         clear = wpabuf_alloc(clear_len);
6109         msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len);
6110         if (!clear || !msg)
6111                 return NULL;
6112
6113         /* DPP Status */
6114         dpp_build_attr_status(clear, status);
6115
6116         /* E-nonce */
6117         wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
6118         wpabuf_put_le16(clear, nonce_len);
6119         wpabuf_put_data(clear, auth->e_nonce, nonce_len);
6120
6121         /* OUI, OUI type, Crypto Suite, DPP frame type */
6122         addr[0] = wpabuf_head_u8(msg) + 2;
6123         len[0] = 3 + 1 + 1 + 1;
6124         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
6125
6126         /* Attributes before Wrapped Data (none) */
6127         addr[1] = wpabuf_put(msg, 0);
6128         len[1] = 0;
6129         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
6130
6131         /* Wrapped Data */
6132         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
6133         wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
6134         wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
6135
6136         wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
6137         if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
6138                             wpabuf_head(clear), wpabuf_len(clear),
6139                             2, addr, len, wrapped) < 0)
6140                 goto fail;
6141
6142         wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg);
6143         wpabuf_free(clear);
6144         return msg;
6145 fail:
6146         wpabuf_free(clear);
6147         wpabuf_free(msg);
6148         return NULL;
6149 }
6150
6151
6152 void dpp_configurator_free(struct dpp_configurator *conf)
6153 {
6154         if (!conf)
6155                 return;
6156         EVP_PKEY_free(conf->csign);
6157         os_free(conf->kid);
6158         os_free(conf);
6159 }
6160
6161
6162 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
6163                              size_t buflen)
6164 {
6165         EC_KEY *eckey;
6166         int key_len, ret = -1;
6167         unsigned char *key = NULL;
6168
6169         if (!conf->csign)
6170                 return -1;
6171
6172         eckey = EVP_PKEY_get1_EC_KEY(conf->csign);
6173         if (!eckey)
6174                 return -1;
6175
6176         key_len = i2d_ECPrivateKey(eckey, &key);
6177         if (key_len > 0)
6178                 ret = wpa_snprintf_hex(buf, buflen, key, key_len);
6179
6180         EC_KEY_free(eckey);
6181         OPENSSL_free(key);
6182         return ret;
6183 }
6184
6185
6186 struct dpp_configurator *
6187 dpp_keygen_configurator(const char *curve, const u8 *privkey,
6188                         size_t privkey_len)
6189 {
6190         struct dpp_configurator *conf;
6191         struct wpabuf *csign_pub = NULL;
6192         u8 kid_hash[SHA256_MAC_LEN];
6193         const u8 *addr[1];
6194         size_t len[1];
6195
6196         conf = os_zalloc(sizeof(*conf));
6197         if (!conf)
6198                 return NULL;
6199
6200         if (!curve) {
6201                 conf->curve = &dpp_curves[0];
6202         } else {
6203                 conf->curve = dpp_get_curve_name(curve);
6204                 if (!conf->curve) {
6205                         wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
6206                                    curve);
6207                         os_free(conf);
6208                         return NULL;
6209                 }
6210         }
6211         if (privkey)
6212                 conf->csign = dpp_set_keypair(&conf->curve, privkey,
6213                                               privkey_len);
6214         else
6215                 conf->csign = dpp_gen_keypair(conf->curve);
6216         if (!conf->csign)
6217                 goto fail;
6218         conf->own = 1;
6219
6220         csign_pub = dpp_get_pubkey_point(conf->csign, 1);
6221         if (!csign_pub) {
6222                 wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
6223                 goto fail;
6224         }
6225
6226         /* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
6227         addr[0] = wpabuf_head(csign_pub);
6228         len[0] = wpabuf_len(csign_pub);
6229         if (sha256_vector(1, addr, len, kid_hash) < 0) {
6230                 wpa_printf(MSG_DEBUG,
6231                            "DPP: Failed to derive kid for C-sign-key");
6232                 goto fail;
6233         }
6234
6235         conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
6236                                                NULL, 0);
6237         if (!conf->kid)
6238                 goto fail;
6239 out:
6240         wpabuf_free(csign_pub);
6241         return conf;
6242 fail:
6243         dpp_configurator_free(conf);
6244         conf = NULL;
6245         goto out;
6246 }
6247
6248
6249 int dpp_configurator_own_config(struct dpp_authentication *auth,
6250                                 const char *curve, int ap)
6251 {
6252         struct wpabuf *conf_obj;
6253         int ret = -1;
6254
6255         if (!auth->conf) {
6256                 wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
6257                 return -1;
6258         }
6259
6260         if (!curve) {
6261                 auth->curve = &dpp_curves[0];
6262         } else {
6263                 auth->curve = dpp_get_curve_name(curve);
6264                 if (!auth->curve) {
6265                         wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
6266                                    curve);
6267                         return -1;
6268                 }
6269         }
6270         wpa_printf(MSG_DEBUG,
6271                    "DPP: Building own configuration/connector with curve %s",
6272                    auth->curve->name);
6273
6274         auth->own_protocol_key = dpp_gen_keypair(auth->curve);
6275         if (!auth->own_protocol_key)
6276                 return -1;
6277         dpp_copy_netaccesskey(auth);
6278         auth->peer_protocol_key = auth->own_protocol_key;
6279         dpp_copy_csign(auth, auth->conf->csign);
6280
6281         conf_obj = dpp_build_conf_obj(auth, ap);
6282         if (!conf_obj)
6283                 goto fail;
6284         ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
6285                                  wpabuf_len(conf_obj));
6286 fail:
6287         wpabuf_free(conf_obj);
6288         auth->peer_protocol_key = NULL;
6289         return ret;
6290 }
6291
6292
6293 static int dpp_compatible_netrole(const char *role1, const char *role2)
6294 {
6295         return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
6296                 (os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
6297 }
6298
6299
6300 static int dpp_connector_compatible_group(struct json_token *root,
6301                                           const char *group_id,
6302                                           const char *net_role)
6303 {
6304         struct json_token *groups, *token;
6305
6306         groups = json_get_member(root, "groups");
6307         if (!groups || groups->type != JSON_ARRAY)
6308                 return 0;
6309
6310         for (token = groups->child; token; token = token->sibling) {
6311                 struct json_token *id, *role;
6312
6313                 id = json_get_member(token, "groupId");
6314                 if (!id || id->type != JSON_STRING)
6315                         continue;
6316
6317                 role = json_get_member(token, "netRole");
6318                 if (!role || role->type != JSON_STRING)
6319                         continue;
6320
6321                 if (os_strcmp(id->string, "*") != 0 &&
6322                     os_strcmp(group_id, "*") != 0 &&
6323                     os_strcmp(id->string, group_id) != 0)
6324                         continue;
6325
6326                 if (dpp_compatible_netrole(role->string, net_role))
6327                         return 1;
6328         }
6329
6330         return 0;
6331 }
6332
6333
6334 static int dpp_connector_match_groups(struct json_token *own_root,
6335                                       struct json_token *peer_root)
6336 {
6337         struct json_token *groups, *token;
6338
6339         groups = json_get_member(peer_root, "groups");
6340         if (!groups || groups->type != JSON_ARRAY) {
6341                 wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
6342                 return 0;
6343         }
6344
6345         for (token = groups->child; token; token = token->sibling) {
6346                 struct json_token *id, *role;
6347
6348                 id = json_get_member(token, "groupId");
6349                 if (!id || id->type != JSON_STRING) {
6350                         wpa_printf(MSG_DEBUG,
6351                                    "DPP: Missing peer groupId string");
6352                         continue;
6353                 }
6354
6355                 role = json_get_member(token, "netRole");
6356                 if (!role || role->type != JSON_STRING) {
6357                         wpa_printf(MSG_DEBUG,
6358                                    "DPP: Missing peer groups::netRole string");
6359                         continue;
6360                 }
6361                 wpa_printf(MSG_DEBUG,
6362                            "DPP: peer connector group: groupId='%s' netRole='%s'",
6363                            id->string, role->string);
6364                 if (dpp_connector_compatible_group(own_root, id->string,
6365                                                    role->string)) {
6366                         wpa_printf(MSG_DEBUG,
6367                                    "DPP: Compatible group/netRole in own connector");
6368                         return 1;
6369                 }
6370         }
6371
6372         return 0;
6373 }
6374
6375
6376 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
6377                           unsigned int hash_len)
6378 {
6379         u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
6380         const char *info = "DPP PMK";
6381         int res;
6382
6383         /* PMK = HKDF(<>, "DPP PMK", N.x) */
6384
6385         /* HKDF-Extract(<>, N.x) */
6386         os_memset(salt, 0, hash_len);
6387         if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
6388                 return -1;
6389         wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
6390                         prk, hash_len);
6391
6392         /* HKDF-Expand(PRK, info, L) */
6393         res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
6394         os_memset(prk, 0, hash_len);
6395         if (res < 0)
6396                 return -1;
6397
6398         wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
6399                         pmk, hash_len);
6400         return 0;
6401 }
6402
6403
6404 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
6405                             EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
6406 {
6407         struct wpabuf *nkx, *pkx;
6408         int ret = -1, res;
6409         const u8 *addr[2];
6410         size_t len[2];
6411         u8 hash[SHA256_MAC_LEN];
6412
6413         /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
6414         nkx = dpp_get_pubkey_point(own_key, 0);
6415         pkx = dpp_get_pubkey_point(peer_key, 0);
6416         if (!nkx || !pkx)
6417                 goto fail;
6418         addr[0] = wpabuf_head(nkx);
6419         len[0] = wpabuf_len(nkx) / 2;
6420         addr[1] = wpabuf_head(pkx);
6421         len[1] = wpabuf_len(pkx) / 2;
6422         if (len[0] != len[1])
6423                 goto fail;
6424         if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
6425                 addr[0] = wpabuf_head(pkx);
6426                 addr[1] = wpabuf_head(nkx);
6427         }
6428         wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
6429         wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
6430         res = sha256_vector(2, addr, len, hash);
6431         if (res < 0)
6432                 goto fail;
6433         wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
6434         os_memcpy(pmkid, hash, PMKID_LEN);
6435         wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
6436         ret = 0;
6437 fail:
6438         wpabuf_free(nkx);
6439         wpabuf_free(pkx);
6440         return ret;
6441 }
6442
6443
6444 enum dpp_status_error
6445 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
6446                const u8 *net_access_key, size_t net_access_key_len,
6447                const u8 *csign_key, size_t csign_key_len,
6448                const u8 *peer_connector, size_t peer_connector_len,
6449                os_time_t *expiry)
6450 {
6451         struct json_token *root = NULL, *netkey, *token;
6452         struct json_token *own_root = NULL;
6453         enum dpp_status_error ret = 255, res;
6454         EVP_PKEY *own_key = NULL, *peer_key = NULL;
6455         struct wpabuf *own_key_pub = NULL;
6456         const struct dpp_curve_params *curve, *own_curve;
6457         struct dpp_signed_connector_info info;
6458         const unsigned char *p;
6459         EVP_PKEY *csign = NULL;
6460         char *signed_connector = NULL;
6461         const char *pos, *end;
6462         unsigned char *own_conn = NULL;
6463         size_t own_conn_len;
6464         size_t Nx_len;
6465         u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
6466
6467         os_memset(intro, 0, sizeof(*intro));
6468         os_memset(&info, 0, sizeof(info));
6469         if (expiry)
6470                 *expiry = 0;
6471
6472         p = csign_key;
6473         csign = d2i_PUBKEY(NULL, &p, csign_key_len);
6474         if (!csign) {
6475                 wpa_printf(MSG_ERROR,
6476                            "DPP: Failed to parse local C-sign-key information");
6477                 goto fail;
6478         }
6479
6480         own_key = dpp_set_keypair(&own_curve, net_access_key,
6481                                   net_access_key_len);
6482         if (!own_key) {
6483                 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
6484                 goto fail;
6485         }
6486
6487         pos = os_strchr(own_connector, '.');
6488         if (!pos) {
6489                 wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
6490                 goto fail;
6491         }
6492         pos++;
6493         end = os_strchr(pos, '.');
6494         if (!end) {
6495                 wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
6496                 goto fail;
6497         }
6498         own_conn = base64_url_decode((const unsigned char *) pos,
6499                                      end - pos, &own_conn_len);
6500         if (!own_conn) {
6501                 wpa_printf(MSG_DEBUG,
6502                            "DPP: Failed to base64url decode own signedConnector JWS Payload");
6503                 goto fail;
6504         }
6505
6506         own_root = json_parse((const char *) own_conn, own_conn_len);
6507         if (!own_root) {
6508                 wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
6509                 goto fail;
6510         }
6511
6512         wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
6513                           peer_connector, peer_connector_len);
6514         signed_connector = os_malloc(peer_connector_len + 1);
6515         if (!signed_connector)
6516                 goto fail;
6517         os_memcpy(signed_connector, peer_connector, peer_connector_len);
6518         signed_connector[peer_connector_len] = '\0';
6519
6520         res = dpp_process_signed_connector(&info, csign, signed_connector);
6521         if (res != DPP_STATUS_OK) {
6522                 ret = res;
6523                 goto fail;
6524         }
6525
6526         root = json_parse((const char *) info.payload, info.payload_len);
6527         if (!root) {
6528                 wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
6529                 ret = DPP_STATUS_INVALID_CONNECTOR;
6530                 goto fail;
6531         }
6532
6533         if (!dpp_connector_match_groups(own_root, root)) {
6534                 wpa_printf(MSG_DEBUG,
6535                            "DPP: Peer connector does not include compatible group netrole with own connector");
6536                 ret = DPP_STATUS_NO_MATCH;
6537                 goto fail;
6538         }
6539
6540         token = json_get_member(root, "expiry");
6541         if (!token || token->type != JSON_STRING) {
6542                 wpa_printf(MSG_DEBUG,
6543                            "DPP: No expiry string found - connector does not expire");
6544         } else {
6545                 wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
6546                 if (dpp_key_expired(token->string, expiry)) {
6547                         wpa_printf(MSG_DEBUG,
6548                                    "DPP: Connector (netAccessKey) has expired");
6549                         ret = DPP_STATUS_INVALID_CONNECTOR;
6550                         goto fail;
6551                 }
6552         }
6553
6554         netkey = json_get_member(root, "netAccessKey");
6555         if (!netkey || netkey->type != JSON_OBJECT) {
6556                 wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
6557                 ret = DPP_STATUS_INVALID_CONNECTOR;
6558                 goto fail;
6559         }
6560
6561         peer_key = dpp_parse_jwk(netkey, &curve);
6562         if (!peer_key) {
6563                 ret = DPP_STATUS_INVALID_CONNECTOR;
6564                 goto fail;
6565         }
6566         dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
6567
6568         if (own_curve != curve) {
6569                 wpa_printf(MSG_DEBUG,
6570                            "DPP: Mismatching netAccessKey curves (%s != %s)",
6571                            own_curve->name, curve->name);
6572                 ret = DPP_STATUS_INVALID_CONNECTOR;
6573                 goto fail;
6574         }
6575
6576         /* ECDH: N = nk * PK */
6577         if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
6578                 goto fail;
6579
6580         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
6581                         Nx, Nx_len);
6582
6583         /* PMK = HKDF(<>, "DPP PMK", N.x) */
6584         if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
6585                 wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
6586                 goto fail;
6587         }
6588         intro->pmk_len = curve->hash_len;
6589
6590         /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
6591         if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
6592                 wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
6593                 goto fail;
6594         }
6595
6596         ret = DPP_STATUS_OK;
6597 fail:
6598         if (ret != DPP_STATUS_OK)
6599                 os_memset(intro, 0, sizeof(*intro));
6600         os_memset(Nx, 0, sizeof(Nx));
6601         os_free(own_conn);
6602         os_free(signed_connector);
6603         os_free(info.payload);
6604         EVP_PKEY_free(own_key);
6605         wpabuf_free(own_key_pub);
6606         EVP_PKEY_free(peer_key);
6607         EVP_PKEY_free(csign);
6608         json_free(root);
6609         json_free(own_root);
6610         return ret;
6611 }
6612
6613
6614 static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
6615                                          int init)
6616 {
6617         EC_GROUP *group;
6618         size_t len = curve->prime_len;
6619         const u8 *x, *y;
6620         EVP_PKEY *res;
6621
6622         switch (curve->ike_group) {
6623         case 19:
6624                 x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
6625                 y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
6626                 break;
6627         case 20:
6628                 x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
6629                 y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
6630                 break;
6631         case 21:
6632                 x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
6633                 y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
6634                 break;
6635         case 28:
6636                 x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
6637                 y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
6638                 break;
6639         case 29:
6640                 x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
6641                 y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
6642                 break;
6643         case 30:
6644                 x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
6645                 y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
6646                 break;
6647         default:
6648                 return NULL;
6649         }
6650
6651         group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
6652         if (!group)
6653                 return NULL;
6654         res = dpp_set_pubkey_point_group(group, x, y, len);
6655         EC_GROUP_free(group);
6656         return res;
6657 }
6658
6659
6660 static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
6661                                      const u8 *mac_init, const char *code,
6662                                      const char *identifier, BN_CTX *bnctx,
6663                                      EC_GROUP **ret_group)
6664 {
6665         u8 hash[DPP_MAX_HASH_LEN];
6666         const u8 *addr[3];
6667         size_t len[3];
6668         unsigned int num_elem = 0;
6669         EC_POINT *Qi = NULL;
6670         EVP_PKEY *Pi = NULL;
6671         EC_KEY *Pi_ec = NULL;
6672         const EC_POINT *Pi_point;
6673         BIGNUM *hash_bn = NULL;
6674         const EC_GROUP *group = NULL;
6675         EC_GROUP *group2 = NULL;
6676
6677         /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
6678
6679         wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
6680         addr[num_elem] = mac_init;
6681         len[num_elem] = ETH_ALEN;
6682         num_elem++;
6683         if (identifier) {
6684                 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
6685                            identifier);
6686                 addr[num_elem] = (const u8 *) identifier;
6687                 len[num_elem] = os_strlen(identifier);
6688                 num_elem++;
6689         }
6690         wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
6691         addr[num_elem] = (const u8 *) code;
6692         len[num_elem] = os_strlen(code);
6693         num_elem++;
6694         if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
6695                 goto fail;
6696         wpa_hexdump_key(MSG_DEBUG,
6697                         "DPP: H(MAC-Initiator | [identifier |] code)",
6698                         hash, curve->hash_len);
6699         Pi = dpp_pkex_get_role_elem(curve, 1);
6700         if (!Pi)
6701                 goto fail;
6702         dpp_debug_print_key("DPP: Pi", Pi);
6703         Pi_ec = EVP_PKEY_get1_EC_KEY(Pi);
6704         if (!Pi_ec)
6705                 goto fail;
6706         Pi_point = EC_KEY_get0_public_key(Pi_ec);
6707
6708         group = EC_KEY_get0_group(Pi_ec);
6709         if (!group)
6710                 goto fail;
6711         group2 = EC_GROUP_dup(group);
6712         if (!group2)
6713                 goto fail;
6714         Qi = EC_POINT_new(group2);
6715         if (!Qi) {
6716                 EC_GROUP_free(group2);
6717                 goto fail;
6718         }
6719         hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
6720         if (!hash_bn ||
6721             EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
6722                 goto fail;
6723         if (EC_POINT_is_at_infinity(group, Qi)) {
6724                 wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
6725                 goto fail;
6726         }
6727         dpp_debug_print_point("DPP: Qi", group, Qi);
6728 out:
6729         EC_KEY_free(Pi_ec);
6730         EVP_PKEY_free(Pi);
6731         BN_clear_free(hash_bn);
6732         if (ret_group && Qi)
6733                 *ret_group = group2;
6734         else
6735                 EC_GROUP_free(group2);
6736         return Qi;
6737 fail:
6738         EC_POINT_free(Qi);
6739         Qi = NULL;
6740         goto out;
6741 }
6742
6743
6744 static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
6745                                      const u8 *mac_resp, const char *code,
6746                                      const char *identifier, BN_CTX *bnctx,
6747                                      EC_GROUP **ret_group)
6748 {
6749         u8 hash[DPP_MAX_HASH_LEN];
6750         const u8 *addr[3];
6751         size_t len[3];
6752         unsigned int num_elem = 0;
6753         EC_POINT *Qr = NULL;
6754         EVP_PKEY *Pr = NULL;
6755         EC_KEY *Pr_ec = NULL;
6756         const EC_POINT *Pr_point;
6757         BIGNUM *hash_bn = NULL;
6758         const EC_GROUP *group = NULL;
6759         EC_GROUP *group2 = NULL;
6760
6761         /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
6762
6763         wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
6764         addr[num_elem] = mac_resp;
6765         len[num_elem] = ETH_ALEN;
6766         num_elem++;
6767         if (identifier) {
6768                 wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
6769                            identifier);
6770                 addr[num_elem] = (const u8 *) identifier;
6771                 len[num_elem] = os_strlen(identifier);
6772                 num_elem++;
6773         }
6774         wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
6775         addr[num_elem] = (const u8 *) code;
6776         len[num_elem] = os_strlen(code);
6777         num_elem++;
6778         if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
6779                 goto fail;
6780         wpa_hexdump_key(MSG_DEBUG,
6781                         "DPP: H(MAC-Responder | [identifier |] code)",
6782                         hash, curve->hash_len);
6783         Pr = dpp_pkex_get_role_elem(curve, 0);
6784         if (!Pr)
6785                 goto fail;
6786         dpp_debug_print_key("DPP: Pr", Pr);
6787         Pr_ec = EVP_PKEY_get1_EC_KEY(Pr);
6788         if (!Pr_ec)
6789                 goto fail;
6790         Pr_point = EC_KEY_get0_public_key(Pr_ec);
6791
6792         group = EC_KEY_get0_group(Pr_ec);
6793         if (!group)
6794                 goto fail;
6795         group2 = EC_GROUP_dup(group);
6796         if (!group2)
6797                 goto fail;
6798         Qr = EC_POINT_new(group2);
6799         if (!Qr) {
6800                 EC_GROUP_free(group2);
6801                 goto fail;
6802         }
6803         hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
6804         if (!hash_bn ||
6805             EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
6806                 goto fail;
6807         if (EC_POINT_is_at_infinity(group, Qr)) {
6808                 wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
6809                 goto fail;
6810         }
6811         dpp_debug_print_point("DPP: Qr", group, Qr);
6812 out:
6813         EC_KEY_free(Pr_ec);
6814         EVP_PKEY_free(Pr);
6815         BN_clear_free(hash_bn);
6816         if (ret_group && Qr)
6817                 *ret_group = group2;
6818         else
6819                 EC_GROUP_free(group2);
6820         return Qr;
6821 fail:
6822         EC_POINT_free(Qr);
6823         Qr = NULL;
6824         goto out;
6825 }
6826
6827
6828 #ifdef CONFIG_TESTING_OPTIONS
6829 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
6830                                     const struct dpp_curve_params *curve)
6831 {
6832         BN_CTX *ctx;
6833         BIGNUM *x, *y;
6834         int ret = -1;
6835         EC_GROUP *group;
6836         EC_POINT *point;
6837
6838         group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
6839         if (!group)
6840                 return -1;
6841
6842         ctx = BN_CTX_new();
6843         point = EC_POINT_new(group);
6844         x = BN_new();
6845         y = BN_new();
6846         if (!ctx || !point || !x || !y)
6847                 goto fail;
6848
6849         if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1)
6850                 goto fail;
6851
6852         /* Generate a random y coordinate that results in a point that is not
6853          * on the curve. */
6854         for (;;) {
6855                 if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1)
6856                         goto fail;
6857
6858                 if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y,
6859                                                         ctx) != 1) {
6860 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6861                 /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL
6862                  * return an error from EC_POINT_set_affine_coordinates_GFp()
6863                  * when the point is not on the curve. */
6864                         break;
6865 #else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */
6866                         goto fail;
6867 #endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */
6868                 }
6869
6870                 if (!EC_POINT_is_on_curve(group, point, ctx))
6871                         break;
6872         }
6873
6874         if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len),
6875                            curve->prime_len) < 0 ||
6876             dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len),
6877                            curve->prime_len) < 0)
6878                 goto fail;
6879
6880         ret = 0;
6881 fail:
6882         if (ret < 0)
6883                 wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key");
6884         BN_free(x);
6885         BN_free(y);
6886         EC_POINT_free(point);
6887         BN_CTX_free(ctx);
6888         EC_GROUP_free(group);
6889
6890         return ret;
6891 }
6892 #endif /* CONFIG_TESTING_OPTIONS */
6893
6894
6895 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
6896 {
6897         EC_KEY *X_ec = NULL;
6898         const EC_POINT *X_point;
6899         BN_CTX *bnctx = NULL;
6900         EC_GROUP *group = NULL;
6901         EC_POINT *Qi = NULL, *M = NULL;
6902         struct wpabuf *M_buf = NULL;
6903         BIGNUM *Mx = NULL, *My = NULL;
6904         struct wpabuf *msg = NULL;
6905         size_t attr_len;
6906         const struct dpp_curve_params *curve = pkex->own_bi->curve;
6907
6908         wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
6909
6910         /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
6911         bnctx = BN_CTX_new();
6912         if (!bnctx)
6913                 goto fail;
6914         Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
6915                                 pkex->identifier, bnctx, &group);
6916         if (!Qi)
6917                 goto fail;
6918
6919         /* Generate a random ephemeral keypair x/X */
6920 #ifdef CONFIG_TESTING_OPTIONS
6921         if (dpp_pkex_ephemeral_key_override_len) {
6922                 const struct dpp_curve_params *tmp_curve;
6923
6924                 wpa_printf(MSG_INFO,
6925                            "DPP: TESTING - override ephemeral key x/X");
6926                 pkex->x = dpp_set_keypair(&tmp_curve,
6927                                           dpp_pkex_ephemeral_key_override,
6928                                           dpp_pkex_ephemeral_key_override_len);
6929         } else {
6930                 pkex->x = dpp_gen_keypair(curve);
6931         }
6932 #else /* CONFIG_TESTING_OPTIONS */
6933         pkex->x = dpp_gen_keypair(curve);
6934 #endif /* CONFIG_TESTING_OPTIONS */
6935         if (!pkex->x)
6936                 goto fail;
6937
6938         /* M = X + Qi */
6939         X_ec = EVP_PKEY_get1_EC_KEY(pkex->x);
6940         if (!X_ec)
6941                 goto fail;
6942         X_point = EC_KEY_get0_public_key(X_ec);
6943         if (!X_point)
6944                 goto fail;
6945         dpp_debug_print_point("DPP: X", group, X_point);
6946         M = EC_POINT_new(group);
6947         Mx = BN_new();
6948         My = BN_new();
6949         if (!M || !Mx || !My ||
6950             EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
6951             EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
6952                 goto fail;
6953         dpp_debug_print_point("DPP: M", group, M);
6954
6955         /* Initiator -> Responder: group, [identifier,] M */
6956         attr_len = 4 + 2;
6957         if (pkex->identifier)
6958                 attr_len += 4 + os_strlen(pkex->identifier);
6959         attr_len += 4 + 2 * curve->prime_len;
6960         msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
6961         if (!msg)
6962                 goto fail;
6963
6964 #ifdef CONFIG_TESTING_OPTIONS
6965         if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
6966                 wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
6967                 goto skip_finite_cyclic_group;
6968         }
6969 #endif /* CONFIG_TESTING_OPTIONS */
6970
6971         /* Finite Cyclic Group attribute */
6972         wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
6973         wpabuf_put_le16(msg, 2);
6974         wpabuf_put_le16(msg, curve->ike_group);
6975
6976 #ifdef CONFIG_TESTING_OPTIONS
6977 skip_finite_cyclic_group:
6978 #endif /* CONFIG_TESTING_OPTIONS */
6979
6980         /* Code Identifier attribute */
6981         if (pkex->identifier) {
6982                 wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
6983                 wpabuf_put_le16(msg, os_strlen(pkex->identifier));
6984                 wpabuf_put_str(msg, pkex->identifier);
6985         }
6986
6987 #ifdef CONFIG_TESTING_OPTIONS
6988         if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
6989                 wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
6990                 goto out;
6991         }
6992 #endif /* CONFIG_TESTING_OPTIONS */
6993
6994         /* M in Encrypted Key attribute */
6995         wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
6996         wpabuf_put_le16(msg, 2 * curve->prime_len);
6997
6998 #ifdef CONFIG_TESTING_OPTIONS
6999         if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
7000                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
7001                 if (dpp_test_gen_invalid_key(msg, curve) < 0)
7002                         goto fail;
7003                 goto out;
7004         }
7005 #endif /* CONFIG_TESTING_OPTIONS */
7006
7007         if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len),
7008                            curve->prime_len) < 0 ||
7009             dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 ||
7010             dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len),
7011                            curve->prime_len) < 0)
7012                 goto fail;
7013
7014 out:
7015         wpabuf_free(M_buf);
7016         EC_KEY_free(X_ec);
7017         EC_POINT_free(M);
7018         EC_POINT_free(Qi);
7019         BN_clear_free(Mx);
7020         BN_clear_free(My);
7021         BN_CTX_free(bnctx);
7022         EC_GROUP_free(group);
7023         return msg;
7024 fail:
7025         wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
7026         wpabuf_free(msg);
7027         msg = NULL;
7028         goto out;
7029 }
7030
7031
7032 static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
7033 {
7034         wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
7035 }
7036
7037
7038 struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
7039                                 const u8 *own_mac,
7040                                 const char *identifier,
7041                                 const char *code)
7042 {
7043         struct dpp_pkex *pkex;
7044
7045 #ifdef CONFIG_TESTING_OPTIONS
7046         if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
7047                 wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
7048                            MAC2STR(dpp_pkex_own_mac_override));
7049                 own_mac = dpp_pkex_own_mac_override;
7050         }
7051 #endif /* CONFIG_TESTING_OPTIONS */
7052
7053         pkex = os_zalloc(sizeof(*pkex));
7054         if (!pkex)
7055                 return NULL;
7056         pkex->msg_ctx = msg_ctx;
7057         pkex->initiator = 1;
7058         pkex->own_bi = bi;
7059         os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
7060         if (identifier) {
7061                 pkex->identifier = os_strdup(identifier);
7062                 if (!pkex->identifier)
7063                         goto fail;
7064         }
7065         pkex->code = os_strdup(code);
7066         if (!pkex->code)
7067                 goto fail;
7068         pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
7069         if (!pkex->exchange_req)
7070                 goto fail;
7071         return pkex;
7072 fail:
7073         dpp_pkex_free(pkex);
7074         return NULL;
7075 }
7076
7077
7078 static struct wpabuf *
7079 dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
7080                              enum dpp_status_error status,
7081                              const BIGNUM *Nx, const BIGNUM *Ny)
7082 {
7083         struct wpabuf *msg = NULL;
7084         size_t attr_len;
7085         const struct dpp_curve_params *curve = pkex->own_bi->curve;
7086
7087         /* Initiator -> Responder: DPP Status, [identifier,] N */
7088         attr_len = 4 + 1;
7089         if (pkex->identifier)
7090                 attr_len += 4 + os_strlen(pkex->identifier);
7091         attr_len += 4 + 2 * curve->prime_len;
7092         msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
7093         if (!msg)
7094                 goto fail;
7095
7096 #ifdef CONFIG_TESTING_OPTIONS
7097         if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) {
7098                 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
7099                 goto skip_status;
7100         }
7101
7102         if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) {
7103                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
7104                 status = 255;
7105         }
7106 #endif /* CONFIG_TESTING_OPTIONS */
7107
7108         /* DPP Status */
7109         dpp_build_attr_status(msg, status);
7110
7111 #ifdef CONFIG_TESTING_OPTIONS
7112 skip_status:
7113 #endif /* CONFIG_TESTING_OPTIONS */
7114
7115         /* Code Identifier attribute */
7116         if (pkex->identifier) {
7117                 wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
7118                 wpabuf_put_le16(msg, os_strlen(pkex->identifier));
7119                 wpabuf_put_str(msg, pkex->identifier);
7120         }
7121
7122         if (status != DPP_STATUS_OK)
7123                 goto skip_encrypted_key;
7124
7125 #ifdef CONFIG_TESTING_OPTIONS
7126         if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
7127                 wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
7128                 goto skip_encrypted_key;
7129         }
7130 #endif /* CONFIG_TESTING_OPTIONS */
7131
7132         /* N in Encrypted Key attribute */
7133         wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
7134         wpabuf_put_le16(msg, 2 * curve->prime_len);
7135
7136 #ifdef CONFIG_TESTING_OPTIONS
7137         if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
7138                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
7139                 if (dpp_test_gen_invalid_key(msg, curve) < 0)
7140                         goto fail;
7141                 goto skip_encrypted_key;
7142         }
7143 #endif /* CONFIG_TESTING_OPTIONS */
7144
7145         if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len),
7146                            curve->prime_len) < 0 ||
7147             dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 ||
7148             dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len),
7149                            curve->prime_len) < 0)
7150                 goto fail;
7151
7152 skip_encrypted_key:
7153         if (status == DPP_STATUS_BAD_GROUP) {
7154                 /* Finite Cyclic Group attribute */
7155                 wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
7156                 wpabuf_put_le16(msg, 2);
7157                 wpabuf_put_le16(msg, curve->ike_group);
7158         }
7159
7160         return msg;
7161 fail:
7162         wpabuf_free(msg);
7163         return NULL;
7164 }
7165
7166
7167 static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
7168                              const u8 *Mx, size_t Mx_len,
7169                              const u8 *Nx, size_t Nx_len,
7170                              const char *code,
7171                              const u8 *Kx, size_t Kx_len,
7172                              u8 *z, unsigned int hash_len)
7173 {
7174         u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
7175         int res;
7176         u8 *info, *pos;
7177         size_t info_len;
7178
7179         /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7180          */
7181
7182         /* HKDF-Extract(<>, IKM=K.x) */
7183         os_memset(salt, 0, hash_len);
7184         if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
7185                 return -1;
7186         wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
7187                         prk, hash_len);
7188         info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
7189         info = os_malloc(info_len);
7190         if (!info)
7191                 return -1;
7192         pos = info;
7193         os_memcpy(pos, mac_init, ETH_ALEN);
7194         pos += ETH_ALEN;
7195         os_memcpy(pos, mac_resp, ETH_ALEN);
7196         pos += ETH_ALEN;
7197         os_memcpy(pos, Mx, Mx_len);
7198         pos += Mx_len;
7199         os_memcpy(pos, Nx, Nx_len);
7200         pos += Nx_len;
7201         os_memcpy(pos, code, os_strlen(code));
7202
7203         /* HKDF-Expand(PRK, info, L) */
7204         if (hash_len == 32)
7205                 res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
7206                                       z, hash_len);
7207         else if (hash_len == 48)
7208                 res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
7209                                       z, hash_len);
7210         else if (hash_len == 64)
7211                 res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
7212                                       z, hash_len);
7213         else
7214                 res = -1;
7215         os_free(info);
7216         os_memset(prk, 0, hash_len);
7217         if (res < 0)
7218                 return -1;
7219
7220         wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
7221                         z, hash_len);
7222         return 0;
7223 }
7224
7225
7226 static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len,
7227                                      const char *identifier)
7228 {
7229         if (!attr_id && identifier) {
7230                 wpa_printf(MSG_DEBUG,
7231                            "DPP: No PKEX code identifier received, but expected one");
7232                 return 0;
7233         }
7234
7235         if (attr_id && !identifier) {
7236                 wpa_printf(MSG_DEBUG,
7237                            "DPP: PKEX code identifier received, but not expecting one");
7238                 return 0;
7239         }
7240
7241         if (attr_id && identifier &&
7242             (os_strlen(identifier) != attr_id_len ||
7243              os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
7244                 wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
7245                 return 0;
7246         }
7247
7248         return 1;
7249 }
7250
7251
7252 struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
7253                                            struct dpp_bootstrap_info *bi,
7254                                            const u8 *own_mac,
7255                                            const u8 *peer_mac,
7256                                            const char *identifier,
7257                                            const char *code,
7258                                            const u8 *buf, size_t len)
7259 {
7260         const u8 *attr_group, *attr_id, *attr_key;
7261         u16 attr_group_len, attr_id_len, attr_key_len;
7262         const struct dpp_curve_params *curve = bi->curve;
7263         u16 ike_group;
7264         struct dpp_pkex *pkex = NULL;
7265         EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
7266         BN_CTX *bnctx = NULL;
7267         EC_GROUP *group = NULL;
7268         BIGNUM *Mx = NULL, *My = NULL;
7269         EC_KEY *Y_ec = NULL, *X_ec = NULL;;
7270         const EC_POINT *Y_point;
7271         BIGNUM *Nx = NULL, *Ny = NULL;
7272         u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
7273         size_t Kx_len;
7274         int res;
7275
7276         if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
7277                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7278                         "PKEX counter t limit reached - ignore message");
7279                 return NULL;
7280         }
7281
7282 #ifdef CONFIG_TESTING_OPTIONS
7283         if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
7284                 wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
7285                            MAC2STR(dpp_pkex_peer_mac_override));
7286                 peer_mac = dpp_pkex_peer_mac_override;
7287         }
7288         if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
7289                 wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
7290                            MAC2STR(dpp_pkex_own_mac_override));
7291                 own_mac = dpp_pkex_own_mac_override;
7292         }
7293 #endif /* CONFIG_TESTING_OPTIONS */
7294
7295         attr_id_len = 0;
7296         attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
7297                                &attr_id_len);
7298         if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier))
7299                 return NULL;
7300
7301         attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
7302                                   &attr_group_len);
7303         if (!attr_group || attr_group_len != 2) {
7304                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7305                         "Missing or invalid Finite Cyclic Group attribute");
7306                 return NULL;
7307         }
7308         ike_group = WPA_GET_LE16(attr_group);
7309         if (ike_group != curve->ike_group) {
7310                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7311                         "Mismatching PKEX curve: peer=%u own=%u",
7312                         ike_group, curve->ike_group);
7313                 pkex = os_zalloc(sizeof(*pkex));
7314                 if (!pkex)
7315                         goto fail;
7316                 pkex->own_bi = bi;
7317                 pkex->failed = 1;
7318                 pkex->exchange_resp = dpp_pkex_build_exchange_resp(
7319                         pkex, DPP_STATUS_BAD_GROUP, NULL, NULL);
7320                 if (!pkex->exchange_resp)
7321                         goto fail;
7322                 return pkex;
7323         }
7324
7325         /* M in Encrypted Key attribute */
7326         attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
7327                                 &attr_key_len);
7328         if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
7329             attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
7330                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7331                         "Missing Encrypted Key attribute");
7332                 return NULL;
7333         }
7334
7335         /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
7336         bnctx = BN_CTX_new();
7337         if (!bnctx)
7338                 goto fail;
7339         Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
7340                                 &group);
7341         if (!Qi)
7342                 goto fail;
7343
7344         /* X' = M - Qi */
7345         X = EC_POINT_new(group);
7346         M = EC_POINT_new(group);
7347         Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
7348         My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
7349         if (!X || !M || !Mx || !My ||
7350             EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
7351             EC_POINT_is_at_infinity(group, M) ||
7352             !EC_POINT_is_on_curve(group, M, bnctx) ||
7353             EC_POINT_invert(group, Qi, bnctx) != 1 ||
7354             EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
7355             EC_POINT_is_at_infinity(group, X) ||
7356             !EC_POINT_is_on_curve(group, X, bnctx)) {
7357                 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7358                         "Invalid Encrypted Key value");
7359                 bi->pkex_t++;
7360                 goto fail;
7361         }
7362         dpp_debug_print_point("DPP: M", group, M);
7363         dpp_debug_print_point("DPP: X'", group, X);
7364
7365         pkex = os_zalloc(sizeof(*pkex));
7366         if (!pkex)
7367                 goto fail;
7368         pkex->t = bi->pkex_t;
7369         pkex->msg_ctx = msg_ctx;
7370         pkex->own_bi = bi;
7371         os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
7372         os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
7373         if (identifier) {
7374                 pkex->identifier = os_strdup(identifier);
7375                 if (!pkex->identifier)
7376                         goto fail;
7377         }
7378         pkex->code = os_strdup(code);
7379         if (!pkex->code)
7380                 goto fail;
7381
7382         os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
7383
7384         X_ec = EC_KEY_new();
7385         if (!X_ec ||
7386             EC_KEY_set_group(X_ec, group) != 1 ||
7387             EC_KEY_set_public_key(X_ec, X) != 1)
7388                 goto fail;
7389         pkex->x = EVP_PKEY_new();
7390         if (!pkex->x ||
7391             EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
7392                 goto fail;
7393
7394         /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
7395         Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
7396         if (!Qr)
7397                 goto fail;
7398
7399         /* Generate a random ephemeral keypair y/Y */
7400 #ifdef CONFIG_TESTING_OPTIONS
7401         if (dpp_pkex_ephemeral_key_override_len) {
7402                 const struct dpp_curve_params *tmp_curve;
7403
7404                 wpa_printf(MSG_INFO,
7405                            "DPP: TESTING - override ephemeral key y/Y");
7406                 pkex->y = dpp_set_keypair(&tmp_curve,
7407                                           dpp_pkex_ephemeral_key_override,
7408                                           dpp_pkex_ephemeral_key_override_len);
7409         } else {
7410                 pkex->y = dpp_gen_keypair(curve);
7411         }
7412 #else /* CONFIG_TESTING_OPTIONS */
7413         pkex->y = dpp_gen_keypair(curve);
7414 #endif /* CONFIG_TESTING_OPTIONS */
7415         if (!pkex->y)
7416                 goto fail;
7417
7418         /* N = Y + Qr */
7419         Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y);
7420         if (!Y_ec)
7421                 goto fail;
7422         Y_point = EC_KEY_get0_public_key(Y_ec);
7423         if (!Y_point)
7424                 goto fail;
7425         dpp_debug_print_point("DPP: Y", group, Y_point);
7426         N = EC_POINT_new(group);
7427         Nx = BN_new();
7428         Ny = BN_new();
7429         if (!N || !Nx || !Ny ||
7430             EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
7431             EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
7432                 goto fail;
7433         dpp_debug_print_point("DPP: N", group, N);
7434
7435         pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
7436                                                            Nx, Ny);
7437         if (!pkex->exchange_resp)
7438                 goto fail;
7439
7440         /* K = y * X' */
7441         if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0)
7442                 goto fail;
7443
7444         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
7445                         Kx, Kx_len);
7446
7447         /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7448          */
7449         res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
7450                                 pkex->Mx, curve->prime_len,
7451                                 pkex->Nx, curve->prime_len, pkex->code,
7452                                 Kx, Kx_len, pkex->z, curve->hash_len);
7453         os_memset(Kx, 0, Kx_len);
7454         if (res < 0)
7455                 goto fail;
7456
7457         pkex->exchange_done = 1;
7458
7459 out:
7460         BN_CTX_free(bnctx);
7461         EC_POINT_free(Qi);
7462         EC_POINT_free(Qr);
7463         BN_free(Mx);
7464         BN_free(My);
7465         BN_free(Nx);
7466         BN_free(Ny);
7467         EC_POINT_free(M);
7468         EC_POINT_free(N);
7469         EC_POINT_free(X);
7470         EC_KEY_free(X_ec);
7471         EC_KEY_free(Y_ec);
7472         EC_GROUP_free(group);
7473         return pkex;
7474 fail:
7475         wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
7476         dpp_pkex_free(pkex);
7477         pkex = NULL;
7478         goto out;
7479 }
7480
7481
7482 static struct wpabuf *
7483 dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
7484                                  const struct wpabuf *A_pub, const u8 *u)
7485 {
7486         const struct dpp_curve_params *curve = pkex->own_bi->curve;
7487         struct wpabuf *msg = NULL;
7488         size_t clear_len, attr_len;
7489         struct wpabuf *clear = NULL;
7490         u8 *wrapped;
7491         u8 octet;
7492         const u8 *addr[2];
7493         size_t len[2];
7494
7495         /* {A, u, [bootstrapping info]}z */
7496         clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
7497         clear = wpabuf_alloc(clear_len);
7498         attr_len = 4 + clear_len + AES_BLOCK_SIZE;
7499 #ifdef CONFIG_TESTING_OPTIONS
7500         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ)
7501                 attr_len += 5;
7502 #endif /* CONFIG_TESTING_OPTIONS */
7503         msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len);
7504         if (!clear || !msg)
7505                 goto fail;
7506
7507 #ifdef CONFIG_TESTING_OPTIONS
7508         if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) {
7509                 wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
7510                 goto skip_bootstrap_key;
7511         }
7512         if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) {
7513                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
7514                 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7515                 wpabuf_put_le16(clear, 2 * curve->prime_len);
7516                 if (dpp_test_gen_invalid_key(clear, curve) < 0)
7517                         goto fail;
7518                 goto skip_bootstrap_key;
7519         }
7520 #endif /* CONFIG_TESTING_OPTIONS */
7521
7522         /* A in Bootstrap Key attribute */
7523         wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7524         wpabuf_put_le16(clear, wpabuf_len(A_pub));
7525         wpabuf_put_buf(clear, A_pub);
7526
7527 #ifdef CONFIG_TESTING_OPTIONS
7528 skip_bootstrap_key:
7529         if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) {
7530                 wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag");
7531                 goto skip_i_auth_tag;
7532         }
7533         if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) {
7534                 wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch");
7535                 wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
7536                 wpabuf_put_le16(clear, curve->hash_len);
7537                 wpabuf_put_data(clear, u, curve->hash_len - 1);
7538                 wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01);
7539                 goto skip_i_auth_tag;
7540         }
7541 #endif /* CONFIG_TESTING_OPTIONS */
7542
7543         /* u in I-Auth tag attribute */
7544         wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
7545         wpabuf_put_le16(clear, curve->hash_len);
7546         wpabuf_put_data(clear, u, curve->hash_len);
7547
7548 #ifdef CONFIG_TESTING_OPTIONS
7549 skip_i_auth_tag:
7550         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) {
7551                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
7552                 goto skip_wrapped_data;
7553         }
7554 #endif /* CONFIG_TESTING_OPTIONS */
7555
7556         addr[0] = wpabuf_head_u8(msg) + 2;
7557         len[0] = DPP_HDR_LEN;
7558         octet = 0;
7559         addr[1] = &octet;
7560         len[1] = sizeof(octet);
7561         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7562         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7563
7564         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
7565         wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7566         wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7567
7568         wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
7569         if (aes_siv_encrypt(pkex->z, curve->hash_len,
7570                             wpabuf_head(clear), wpabuf_len(clear),
7571                             2, addr, len, wrapped) < 0)
7572                 goto fail;
7573         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7574                     wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
7575
7576 #ifdef CONFIG_TESTING_OPTIONS
7577         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) {
7578                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
7579                 dpp_build_attr_status(msg, DPP_STATUS_OK);
7580         }
7581 skip_wrapped_data:
7582 #endif /* CONFIG_TESTING_OPTIONS */
7583
7584 out:
7585         wpabuf_free(clear);
7586         return msg;
7587
7588 fail:
7589         wpabuf_free(msg);
7590         msg = NULL;
7591         goto out;
7592 }
7593
7594
7595 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
7596                                           const u8 *peer_mac,
7597                                           const u8 *buf, size_t buflen)
7598 {
7599         const u8 *attr_status, *attr_id, *attr_key, *attr_group;
7600         u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
7601         EC_GROUP *group = NULL;
7602         BN_CTX *bnctx = NULL;
7603         struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
7604         const struct dpp_curve_params *curve = pkex->own_bi->curve;
7605         EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
7606         BIGNUM *Nx = NULL, *Ny = NULL;
7607         EC_KEY *Y_ec = NULL;
7608         size_t Jx_len, Kx_len;
7609         u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
7610         const u8 *addr[4];
7611         size_t len[4];
7612         u8 u[DPP_MAX_HASH_LEN];
7613         int res;
7614
7615         if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
7616                 return NULL;
7617
7618 #ifdef CONFIG_TESTING_OPTIONS
7619         if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) {
7620                 wpa_printf(MSG_INFO,
7621                            "DPP: TESTING - stop at PKEX Exchange Response");
7622                 pkex->failed = 1;
7623                 return NULL;
7624         }
7625
7626         if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
7627                 wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
7628                            MAC2STR(dpp_pkex_peer_mac_override));
7629                 peer_mac = dpp_pkex_peer_mac_override;
7630         }
7631 #endif /* CONFIG_TESTING_OPTIONS */
7632
7633         os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
7634
7635         attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
7636                                    &attr_status_len);
7637         if (!attr_status || attr_status_len != 1) {
7638                 dpp_pkex_fail(pkex, "No DPP Status attribute");
7639                 return NULL;
7640         }
7641         wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
7642
7643         if (attr_status[0] == DPP_STATUS_BAD_GROUP) {
7644                 attr_group = dpp_get_attr(buf, buflen,
7645                                           DPP_ATTR_FINITE_CYCLIC_GROUP,
7646                                           &attr_group_len);
7647                 if (attr_group && attr_group_len == 2) {
7648                         wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7649                                 "Peer indicated mismatching PKEX group - proposed %u",
7650                                 WPA_GET_LE16(attr_group));
7651                         return NULL;
7652                 }
7653         }
7654
7655         if (attr_status[0] != DPP_STATUS_OK) {
7656                 dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)");
7657                 return NULL;
7658         }
7659
7660         attr_id_len = 0;
7661         attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
7662                                &attr_id_len);
7663         if (!dpp_pkex_identifier_match(attr_id, attr_id_len,
7664                                        pkex->identifier)) {
7665                 dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
7666                 return NULL;
7667         }
7668
7669         /* N in Encrypted Key attribute */
7670         attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
7671                                 &attr_key_len);
7672         if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
7673                 dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
7674                 return NULL;
7675         }
7676
7677         /* Qr = H(MAC-Responder | [identifier |] code) * Pr */
7678         bnctx = BN_CTX_new();
7679         if (!bnctx)
7680                 goto fail;
7681         Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
7682                                 pkex->identifier, bnctx, &group);
7683         if (!Qr)
7684                 goto fail;
7685
7686         /* Y' = N - Qr */
7687         Y = EC_POINT_new(group);
7688         N = EC_POINT_new(group);
7689         Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
7690         Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
7691         if (!Y || !N || !Nx || !Ny ||
7692             EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
7693             EC_POINT_is_at_infinity(group, N) ||
7694             !EC_POINT_is_on_curve(group, N, bnctx) ||
7695             EC_POINT_invert(group, Qr, bnctx) != 1 ||
7696             EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
7697             EC_POINT_is_at_infinity(group, Y) ||
7698             !EC_POINT_is_on_curve(group, Y, bnctx)) {
7699                 dpp_pkex_fail(pkex, "Invalid Encrypted Key value");
7700                 pkex->t++;
7701                 goto fail;
7702         }
7703         dpp_debug_print_point("DPP: N", group, N);
7704         dpp_debug_print_point("DPP: Y'", group, Y);
7705
7706         pkex->exchange_done = 1;
7707
7708         /* ECDH: J = a * Y’ */
7709         Y_ec = EC_KEY_new();
7710         if (!Y_ec ||
7711             EC_KEY_set_group(Y_ec, group) != 1 ||
7712             EC_KEY_set_public_key(Y_ec, Y) != 1)
7713                 goto fail;
7714         pkex->y = EVP_PKEY_new();
7715         if (!pkex->y ||
7716             EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
7717                 goto fail;
7718         if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
7719                 goto fail;
7720
7721         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
7722                         Jx, Jx_len);
7723
7724         /* u = HMAC(J.x,  MAC-Initiator | A.x | Y’.x | X.x ) */
7725         A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
7726         Y_pub = dpp_get_pubkey_point(pkex->y, 0);
7727         X_pub = dpp_get_pubkey_point(pkex->x, 0);
7728         if (!A_pub || !Y_pub || !X_pub)
7729                 goto fail;
7730         addr[0] = pkex->own_mac;
7731         len[0] = ETH_ALEN;
7732         addr[1] = wpabuf_head(A_pub);
7733         len[1] = wpabuf_len(A_pub) / 2;
7734         addr[2] = wpabuf_head(Y_pub);
7735         len[2] = wpabuf_len(Y_pub) / 2;
7736         addr[3] = wpabuf_head(X_pub);
7737         len[3] = wpabuf_len(X_pub) / 2;
7738         if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
7739                 goto fail;
7740         wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
7741
7742         /* K = x * Y’ */
7743         if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0)
7744                 goto fail;
7745
7746         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
7747                         Kx, Kx_len);
7748
7749         /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7750          */
7751         res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
7752                                 pkex->Mx, curve->prime_len,
7753                                 attr_key /* N.x */, attr_key_len / 2,
7754                                 pkex->code, Kx, Kx_len,
7755                                 pkex->z, curve->hash_len);
7756         os_memset(Kx, 0, Kx_len);
7757         if (res < 0)
7758                 goto fail;
7759
7760         msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u);
7761         if (!msg)
7762                 goto fail;
7763
7764 out:
7765         wpabuf_free(A_pub);
7766         wpabuf_free(X_pub);
7767         wpabuf_free(Y_pub);
7768         EC_POINT_free(Qr);
7769         EC_POINT_free(Y);
7770         EC_POINT_free(N);
7771         BN_free(Nx);
7772         BN_free(Ny);
7773         EC_KEY_free(Y_ec);
7774         BN_CTX_free(bnctx);
7775         EC_GROUP_free(group);
7776         return msg;
7777 fail:
7778         wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
7779         goto out;
7780 }
7781
7782
7783 static struct wpabuf *
7784 dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex,
7785                                   const struct wpabuf *B_pub, const u8 *v)
7786 {
7787         const struct dpp_curve_params *curve = pkex->own_bi->curve;
7788         struct wpabuf *msg = NULL;
7789         const u8 *addr[2];
7790         size_t len[2];
7791         u8 octet;
7792         u8 *wrapped;
7793         struct wpabuf *clear = NULL;
7794         size_t clear_len, attr_len;
7795
7796         /* {B, v [bootstrapping info]}z */
7797         clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
7798         clear = wpabuf_alloc(clear_len);
7799         attr_len = 4 + clear_len + AES_BLOCK_SIZE;
7800 #ifdef CONFIG_TESTING_OPTIONS
7801         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP)
7802                 attr_len += 5;
7803 #endif /* CONFIG_TESTING_OPTIONS */
7804         msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len);
7805         if (!clear || !msg)
7806                 goto fail;
7807
7808 #ifdef CONFIG_TESTING_OPTIONS
7809         if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) {
7810                 wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
7811                 goto skip_bootstrap_key;
7812         }
7813         if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) {
7814                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
7815                 wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7816                 wpabuf_put_le16(clear, 2 * curve->prime_len);
7817                 if (dpp_test_gen_invalid_key(clear, curve) < 0)
7818                         goto fail;
7819                 goto skip_bootstrap_key;
7820         }
7821 #endif /* CONFIG_TESTING_OPTIONS */
7822
7823         /* B in Bootstrap Key attribute */
7824         wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7825         wpabuf_put_le16(clear, wpabuf_len(B_pub));
7826         wpabuf_put_buf(clear, B_pub);
7827
7828 #ifdef CONFIG_TESTING_OPTIONS
7829 skip_bootstrap_key:
7830         if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) {
7831                 wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag");
7832                 goto skip_r_auth_tag;
7833         }
7834         if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) {
7835                 wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch");
7836                 wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
7837                 wpabuf_put_le16(clear, curve->hash_len);
7838                 wpabuf_put_data(clear, v, curve->hash_len - 1);
7839                 wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01);
7840                 goto skip_r_auth_tag;
7841         }
7842 #endif /* CONFIG_TESTING_OPTIONS */
7843
7844         /* v in R-Auth tag attribute */
7845         wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
7846         wpabuf_put_le16(clear, curve->hash_len);
7847         wpabuf_put_data(clear, v, curve->hash_len);
7848
7849 #ifdef CONFIG_TESTING_OPTIONS
7850 skip_r_auth_tag:
7851         if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) {
7852                 wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
7853                 goto skip_wrapped_data;
7854         }
7855 #endif /* CONFIG_TESTING_OPTIONS */
7856
7857         addr[0] = wpabuf_head_u8(msg) + 2;
7858         len[0] = DPP_HDR_LEN;
7859         octet = 1;
7860         addr[1] = &octet;
7861         len[1] = sizeof(octet);
7862         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7863         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7864
7865         wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
7866         wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7867         wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7868
7869         wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
7870         if (aes_siv_encrypt(pkex->z, curve->hash_len,
7871                             wpabuf_head(clear), wpabuf_len(clear),
7872                             2, addr, len, wrapped) < 0)
7873                 goto fail;
7874         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7875                     wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
7876
7877 #ifdef CONFIG_TESTING_OPTIONS
7878         if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) {
7879                 wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
7880                 dpp_build_attr_status(msg, DPP_STATUS_OK);
7881         }
7882 skip_wrapped_data:
7883 #endif /* CONFIG_TESTING_OPTIONS */
7884
7885 out:
7886         wpabuf_free(clear);
7887         return msg;
7888
7889 fail:
7890         wpabuf_free(msg);
7891         msg = NULL;
7892         goto out;
7893 }
7894
7895
7896 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
7897                                               const u8 *hdr,
7898                                               const u8 *buf, size_t buflen)
7899 {
7900         const struct dpp_curve_params *curve = pkex->own_bi->curve;
7901         size_t Jx_len, Lx_len;
7902         u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
7903         u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
7904         const u8 *wrapped_data, *b_key, *peer_u;
7905         u16 wrapped_data_len, b_key_len, peer_u_len = 0;
7906         const u8 *addr[4];
7907         size_t len[4];
7908         u8 octet;
7909         u8 *unwrapped = NULL;
7910         size_t unwrapped_len = 0;
7911         struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
7912         struct wpabuf *B_pub = NULL;
7913         u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
7914
7915 #ifdef CONFIG_TESTING_OPTIONS
7916         if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) {
7917                 wpa_printf(MSG_INFO,
7918                            "DPP: TESTING - stop at PKEX CR Request");
7919                 pkex->failed = 1;
7920                 return NULL;
7921         }
7922 #endif /* CONFIG_TESTING_OPTIONS */
7923
7924         if (!pkex->exchange_done || pkex->failed ||
7925             pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator)
7926                 goto fail;
7927
7928         wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
7929                                     &wrapped_data_len);
7930         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
7931                 dpp_pkex_fail(pkex,
7932                               "Missing or invalid required Wrapped Data attribute");
7933                 goto fail;
7934         }
7935
7936         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7937                     wrapped_data, wrapped_data_len);
7938         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
7939         unwrapped = os_malloc(unwrapped_len);
7940         if (!unwrapped)
7941                 goto fail;
7942
7943         addr[0] = hdr;
7944         len[0] = DPP_HDR_LEN;
7945         octet = 0;
7946         addr[1] = &octet;
7947         len[1] = sizeof(octet);
7948         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7949         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7950
7951         if (aes_siv_decrypt(pkex->z, curve->hash_len,
7952                             wrapped_data, wrapped_data_len,
7953                             2, addr, len, unwrapped) < 0) {
7954                 dpp_pkex_fail(pkex,
7955                               "AES-SIV decryption failed - possible PKEX code mismatch");
7956                 pkex->failed = 1;
7957                 pkex->t++;
7958                 goto fail;
7959         }
7960         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
7961                     unwrapped, unwrapped_len);
7962
7963         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
7964                 dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
7965                 goto fail;
7966         }
7967
7968         b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
7969                              &b_key_len);
7970         if (!b_key || b_key_len != 2 * curve->prime_len) {
7971                 dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
7972                 goto fail;
7973         }
7974         pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
7975                                                         b_key_len);
7976         if (!pkex->peer_bootstrap_key) {
7977                 dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
7978                 goto fail;
7979         }
7980         dpp_debug_print_key("DPP: Peer bootstrap public key",
7981                             pkex->peer_bootstrap_key);
7982
7983         /* ECDH: J' = y * A' */
7984         if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0)
7985                 goto fail;
7986
7987         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
7988                         Jx, Jx_len);
7989
7990         /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
7991         A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
7992         Y_pub = dpp_get_pubkey_point(pkex->y, 0);
7993         X_pub = dpp_get_pubkey_point(pkex->x, 0);
7994         if (!A_pub || !Y_pub || !X_pub)
7995                 goto fail;
7996         addr[0] = pkex->peer_mac;
7997         len[0] = ETH_ALEN;
7998         addr[1] = wpabuf_head(A_pub);
7999         len[1] = wpabuf_len(A_pub) / 2;
8000         addr[2] = wpabuf_head(Y_pub);
8001         len[2] = wpabuf_len(Y_pub) / 2;
8002         addr[3] = wpabuf_head(X_pub);
8003         len[3] = wpabuf_len(X_pub) / 2;
8004         if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
8005                 goto fail;
8006
8007         peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
8008                               &peer_u_len);
8009         if (!peer_u || peer_u_len != curve->hash_len ||
8010             os_memcmp(peer_u, u, curve->hash_len) != 0) {
8011                 dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found");
8012                 wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
8013                             u, curve->hash_len);
8014                 wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
8015                 pkex->t++;
8016                 goto fail;
8017         }
8018         wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
8019
8020         /* ECDH: L = b * X' */
8021         if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0)
8022                 goto fail;
8023
8024         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
8025                         Lx, Lx_len);
8026
8027         /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
8028         B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
8029         if (!B_pub)
8030                 goto fail;
8031         addr[0] = pkex->own_mac;
8032         len[0] = ETH_ALEN;
8033         addr[1] = wpabuf_head(B_pub);
8034         len[1] = wpabuf_len(B_pub) / 2;
8035         addr[2] = wpabuf_head(X_pub);
8036         len[2] = wpabuf_len(X_pub) / 2;
8037         addr[3] = wpabuf_head(Y_pub);
8038         len[3] = wpabuf_len(Y_pub) / 2;
8039         if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
8040                 goto fail;
8041         wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
8042
8043         msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v);
8044         if (!msg)
8045                 goto fail;
8046
8047 out:
8048         os_free(unwrapped);
8049         wpabuf_free(A_pub);
8050         wpabuf_free(B_pub);
8051         wpabuf_free(X_pub);
8052         wpabuf_free(Y_pub);
8053         return msg;
8054 fail:
8055         wpa_printf(MSG_DEBUG,
8056                    "DPP: PKEX Commit-Reveal Request processing failed");
8057         goto out;
8058 }
8059
8060
8061 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
8062                                    const u8 *buf, size_t buflen)
8063 {
8064         const struct dpp_curve_params *curve = pkex->own_bi->curve;
8065         const u8 *wrapped_data, *b_key, *peer_v;
8066         u16 wrapped_data_len, b_key_len, peer_v_len = 0;
8067         const u8 *addr[4];
8068         size_t len[4];
8069         u8 octet;
8070         u8 *unwrapped = NULL;
8071         size_t unwrapped_len = 0;
8072         int ret = -1;
8073         u8 v[DPP_MAX_HASH_LEN];
8074         size_t Lx_len;
8075         u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
8076         struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
8077
8078 #ifdef CONFIG_TESTING_OPTIONS
8079         if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) {
8080                 wpa_printf(MSG_INFO,
8081                            "DPP: TESTING - stop at PKEX CR Response");
8082                 pkex->failed = 1;
8083                 goto fail;
8084         }
8085 #endif /* CONFIG_TESTING_OPTIONS */
8086
8087         if (!pkex->exchange_done || pkex->failed ||
8088             pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
8089                 goto fail;
8090
8091         wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
8092                                     &wrapped_data_len);
8093         if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
8094                 dpp_pkex_fail(pkex,
8095                               "Missing or invalid required Wrapped Data attribute");
8096                 goto fail;
8097         }
8098
8099         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
8100                     wrapped_data, wrapped_data_len);
8101         unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
8102         unwrapped = os_malloc(unwrapped_len);
8103         if (!unwrapped)
8104                 goto fail;
8105
8106         addr[0] = hdr;
8107         len[0] = DPP_HDR_LEN;
8108         octet = 1;
8109         addr[1] = &octet;
8110         len[1] = sizeof(octet);
8111         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
8112         wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
8113
8114         if (aes_siv_decrypt(pkex->z, curve->hash_len,
8115                             wrapped_data, wrapped_data_len,
8116                             2, addr, len, unwrapped) < 0) {
8117                 dpp_pkex_fail(pkex,
8118                               "AES-SIV decryption failed - possible PKEX code mismatch");
8119                 pkex->t++;
8120                 goto fail;
8121         }
8122         wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
8123                     unwrapped, unwrapped_len);
8124
8125         if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
8126                 dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
8127                 goto fail;
8128         }
8129
8130         b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
8131                              &b_key_len);
8132         if (!b_key || b_key_len != 2 * curve->prime_len) {
8133                 dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
8134                 goto fail;
8135         }
8136         pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
8137                                                         b_key_len);
8138         if (!pkex->peer_bootstrap_key) {
8139                 dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
8140                 goto fail;
8141         }
8142         dpp_debug_print_key("DPP: Peer bootstrap public key",
8143                             pkex->peer_bootstrap_key);
8144
8145         /* ECDH: L' = x * B' */
8146         if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0)
8147                 goto fail;
8148
8149         wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
8150                         Lx, Lx_len);
8151
8152         /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
8153         B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
8154         X_pub = dpp_get_pubkey_point(pkex->x, 0);
8155         Y_pub = dpp_get_pubkey_point(pkex->y, 0);
8156         if (!B_pub || !X_pub || !Y_pub)
8157                 goto fail;
8158         addr[0] = pkex->peer_mac;
8159         len[0] = ETH_ALEN;
8160         addr[1] = wpabuf_head(B_pub);
8161         len[1] = wpabuf_len(B_pub) / 2;
8162         addr[2] = wpabuf_head(X_pub);
8163         len[2] = wpabuf_len(X_pub) / 2;
8164         addr[3] = wpabuf_head(Y_pub);
8165         len[3] = wpabuf_len(Y_pub) / 2;
8166         if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
8167                 goto fail;
8168
8169         peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
8170                               &peer_v_len);
8171         if (!peer_v || peer_v_len != curve->hash_len ||
8172             os_memcmp(peer_v, v, curve->hash_len) != 0) {
8173                 dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found");
8174                 wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
8175                             v, curve->hash_len);
8176                 wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
8177                 pkex->t++;
8178                 goto fail;
8179         }
8180         wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
8181
8182         ret = 0;
8183 out:
8184         wpabuf_free(B_pub);
8185         wpabuf_free(X_pub);
8186         wpabuf_free(Y_pub);
8187         os_free(unwrapped);
8188         return ret;
8189 fail:
8190         goto out;
8191 }
8192
8193
8194 void dpp_pkex_free(struct dpp_pkex *pkex)
8195 {
8196         if (!pkex)
8197                 return;
8198
8199         os_free(pkex->identifier);
8200         os_free(pkex->code);
8201         EVP_PKEY_free(pkex->x);
8202         EVP_PKEY_free(pkex->y);
8203         EVP_PKEY_free(pkex->peer_bootstrap_key);
8204         wpabuf_free(pkex->exchange_req);
8205         wpabuf_free(pkex->exchange_resp);
8206         os_free(pkex);
8207 }
8208
8209
8210 #ifdef CONFIG_TESTING_OPTIONS
8211 char * dpp_corrupt_connector_signature(const char *connector)
8212 {
8213         char *tmp, *pos, *signed3 = NULL;
8214         unsigned char *signature = NULL;
8215         size_t signature_len = 0, signed3_len;
8216
8217         tmp = os_zalloc(os_strlen(connector) + 5);
8218         if (!tmp)
8219                 goto fail;
8220         os_memcpy(tmp, connector, os_strlen(connector));
8221
8222         pos = os_strchr(tmp, '.');
8223         if (!pos)
8224                 goto fail;
8225
8226         pos = os_strchr(pos + 1, '.');
8227         if (!pos)
8228                 goto fail;
8229         pos++;
8230
8231         wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
8232                    pos);
8233         signature = base64_url_decode((const unsigned char *) pos,
8234                                       os_strlen(pos), &signature_len);
8235         if (!signature || signature_len == 0)
8236                 goto fail;
8237         wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
8238                     signature, signature_len);
8239         signature[signature_len - 1] ^= 0x01;
8240         wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
8241                     signature, signature_len);
8242         signed3 = (char *) base64_url_encode(signature, signature_len,
8243                                              &signed3_len, 0);
8244         if (!signed3)
8245                 goto fail;
8246         os_memcpy(pos, signed3, signed3_len);
8247         pos[signed3_len] = '\0';
8248         wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
8249                    pos);
8250
8251 out:
8252         os_free(signature);
8253         os_free(signed3);
8254         return tmp;
8255 fail:
8256         os_free(tmp);
8257         tmp = NULL;
8258         goto out;
8259 }
8260 #endif /* CONFIG_TESTING_OPTIONS */
8261
8262
8263 #ifdef CONFIG_DPP2
8264
8265 struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
8266                               size_t net_access_key_len)
8267 {
8268         struct wpabuf *pub = NULL;
8269         EVP_PKEY *own_key;
8270         struct dpp_pfs *pfs;
8271
8272         pfs = os_zalloc(sizeof(*pfs));
8273         if (!pfs)
8274                 return NULL;
8275
8276         own_key = dpp_set_keypair(&pfs->curve, net_access_key,
8277                                   net_access_key_len);
8278         if (!own_key) {
8279                 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
8280                 goto fail;
8281         }
8282         EVP_PKEY_free(own_key);
8283
8284         pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
8285         if (!pfs->ecdh)
8286                 goto fail;
8287
8288         pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
8289         pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
8290         if (!pub)
8291                 goto fail;
8292
8293         pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
8294         if (!pfs->ie)
8295                 goto fail;
8296         wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
8297         wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
8298         wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
8299         wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
8300         wpabuf_put_buf(pfs->ie, pub);
8301         wpabuf_free(pub);
8302         wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
8303                         pfs->ie);
8304
8305         return pfs;
8306 fail:
8307         wpabuf_free(pub);
8308         dpp_pfs_free(pfs);
8309         return NULL;
8310 }
8311
8312
8313 int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
8314 {
8315         if (peer_ie_len < 2)
8316                 return -1;
8317         if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
8318                 wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
8319                 return -1;
8320         }
8321
8322         pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
8323                                               peer_ie_len - 2);
8324         pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
8325         if (!pfs->secret) {
8326                 wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
8327                 return -1;
8328         }
8329         wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
8330         return 0;
8331 }
8332
8333
8334 void dpp_pfs_free(struct dpp_pfs *pfs)
8335 {
8336         if (!pfs)
8337                 return;
8338         crypto_ecdh_deinit(pfs->ecdh);
8339         wpabuf_free(pfs->ie);
8340         wpabuf_clear_free(pfs->secret);
8341         os_free(pfs);
8342 }
8343
8344 #endif /* CONFIG_DPP2 */
8345
8346
8347 static unsigned int dpp_next_id(struct dpp_global *dpp)
8348 {
8349         struct dpp_bootstrap_info *bi;
8350         unsigned int max_id = 0;
8351
8352         dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8353                 if (bi->id > max_id)
8354                         max_id = bi->id;
8355         }
8356         return max_id + 1;
8357 }
8358
8359
8360 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
8361 {
8362         struct dpp_bootstrap_info *bi, *tmp;
8363         int found = 0;
8364
8365         if (!dpp)
8366                 return -1;
8367
8368         dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
8369                               struct dpp_bootstrap_info, list) {
8370                 if (id && bi->id != id)
8371                         continue;
8372                 found = 1;
8373                 dl_list_del(&bi->list);
8374                 dpp_bootstrap_info_free(bi);
8375         }
8376
8377         if (id == 0)
8378                 return 0; /* flush succeeds regardless of entries found */
8379         return found ? 0 : -1;
8380 }
8381
8382
8383 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
8384                                             const char *uri)
8385 {
8386         struct dpp_bootstrap_info *bi;
8387
8388         if (!dpp)
8389                 return NULL;
8390
8391         bi = dpp_parse_qr_code(uri);
8392         if (!bi)
8393                 return NULL;
8394
8395         bi->id = dpp_next_id(dpp);
8396         dl_list_add(&dpp->bootstrap, &bi->list);
8397         return bi;
8398 }
8399
8400
8401 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
8402 {
8403         char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
8404         char *key = NULL;
8405         u8 *privkey = NULL;
8406         size_t privkey_len = 0;
8407         size_t len;
8408         int ret = -1;
8409         struct dpp_bootstrap_info *bi;
8410
8411         if (!dpp)
8412                 return -1;
8413
8414         bi = os_zalloc(sizeof(*bi));
8415         if (!bi)
8416                 goto fail;
8417
8418         if (os_strstr(cmd, "type=qrcode"))
8419                 bi->type = DPP_BOOTSTRAP_QR_CODE;
8420         else if (os_strstr(cmd, "type=pkex"))
8421                 bi->type = DPP_BOOTSTRAP_PKEX;
8422         else
8423                 goto fail;
8424
8425         chan = get_param(cmd, " chan=");
8426         mac = get_param(cmd, " mac=");
8427         info = get_param(cmd, " info=");
8428         curve = get_param(cmd, " curve=");
8429         key = get_param(cmd, " key=");
8430
8431         if (key) {
8432                 privkey_len = os_strlen(key) / 2;
8433                 privkey = os_malloc(privkey_len);
8434                 if (!privkey ||
8435                     hexstr2bin(key, privkey, privkey_len) < 0)
8436                         goto fail;
8437         }
8438
8439         pk = dpp_keygen(bi, curve, privkey, privkey_len);
8440         if (!pk)
8441                 goto fail;
8442
8443         len = 4; /* "DPP:" */
8444         if (chan) {
8445                 if (dpp_parse_uri_chan_list(bi, chan) < 0)
8446                         goto fail;
8447                 len += 3 + os_strlen(chan); /* C:...; */
8448         }
8449         if (mac) {
8450                 if (dpp_parse_uri_mac(bi, mac) < 0)
8451                         goto fail;
8452                 len += 3 + os_strlen(mac); /* M:...; */
8453         }
8454         if (info) {
8455                 if (dpp_parse_uri_info(bi, info) < 0)
8456                         goto fail;
8457                 len += 3 + os_strlen(info); /* I:...; */
8458         }
8459         len += 4 + os_strlen(pk);
8460         bi->uri = os_malloc(len + 1);
8461         if (!bi->uri)
8462                 goto fail;
8463         os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
8464                     chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
8465                     mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
8466                     info ? "I:" : "", info ? info : "", info ? ";" : "",
8467                     pk);
8468         bi->id = dpp_next_id(dpp);
8469         dl_list_add(&dpp->bootstrap, &bi->list);
8470         ret = bi->id;
8471         bi = NULL;
8472 fail:
8473         os_free(curve);
8474         os_free(pk);
8475         os_free(chan);
8476         os_free(mac);
8477         os_free(info);
8478         str_clear_free(key);
8479         bin_clear_free(privkey, privkey_len);
8480         dpp_bootstrap_info_free(bi);
8481         return ret;
8482 }
8483
8484
8485 struct dpp_bootstrap_info *
8486 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
8487 {
8488         struct dpp_bootstrap_info *bi;
8489
8490         if (!dpp)
8491                 return NULL;
8492
8493         dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8494                 if (bi->id == id)
8495                         return bi;
8496         }
8497         return NULL;
8498 }
8499
8500
8501 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
8502 {
8503         unsigned int id_val;
8504
8505         if (os_strcmp(id, "*") == 0) {
8506                 id_val = 0;
8507         } else {
8508                 id_val = atoi(id);
8509                 if (id_val == 0)
8510                         return -1;
8511         }
8512
8513         return dpp_bootstrap_del(dpp, id_val);
8514 }
8515
8516
8517 struct dpp_bootstrap_info *
8518 dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
8519                 unsigned int freq)
8520 {
8521         struct dpp_bootstrap_info *bi;
8522
8523         bi = os_zalloc(sizeof(*bi));
8524         if (!bi)
8525                 return NULL;
8526         bi->id = dpp_next_id(dpp);
8527         bi->type = DPP_BOOTSTRAP_PKEX;
8528         os_memcpy(bi->mac_addr, peer, ETH_ALEN);
8529         bi->num_freq = 1;
8530         bi->freq[0] = freq;
8531         bi->curve = pkex->own_bi->curve;
8532         bi->pubkey = pkex->peer_bootstrap_key;
8533         pkex->peer_bootstrap_key = NULL;
8534         if (dpp_bootstrap_key_hash(bi) < 0) {
8535                 dpp_bootstrap_info_free(bi);
8536                 return NULL;
8537         }
8538         dpp_pkex_free(pkex);
8539         dl_list_add(&dpp->bootstrap, &bi->list);
8540         return bi;
8541 }
8542
8543
8544 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
8545 {
8546         struct dpp_bootstrap_info *bi;
8547
8548         bi = dpp_bootstrap_get_id(dpp, id);
8549         if (!bi)
8550                 return NULL;
8551         return bi->uri;
8552 }
8553
8554
8555 int dpp_bootstrap_info(struct dpp_global *dpp, int id,
8556                        char *reply, int reply_size)
8557 {
8558         struct dpp_bootstrap_info *bi;
8559         char pkhash[2 * SHA256_MAC_LEN + 1];
8560
8561         bi = dpp_bootstrap_get_id(dpp, id);
8562         if (!bi)
8563                 return -1;
8564         wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
8565                          SHA256_MAC_LEN);
8566         return os_snprintf(reply, reply_size, "type=%s\n"
8567                            "mac_addr=" MACSTR "\n"
8568                            "info=%s\n"
8569                            "num_freq=%u\n"
8570                            "curve=%s\n"
8571                            "pkhash=%s\n",
8572                            dpp_bootstrap_type_txt(bi->type),
8573                            MAC2STR(bi->mac_addr),
8574                            bi->info ? bi->info : "",
8575                            bi->num_freq,
8576                            bi->curve->name,
8577                            pkhash);
8578 }
8579
8580
8581 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
8582                              const u8 *r_bootstrap,
8583                              struct dpp_bootstrap_info **own_bi,
8584                              struct dpp_bootstrap_info **peer_bi)
8585 {
8586         struct dpp_bootstrap_info *bi;
8587
8588         *own_bi = NULL;
8589         *peer_bi = NULL;
8590         if (!dpp)
8591                 return;
8592
8593         dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8594                 if (!*own_bi && bi->own &&
8595                     os_memcmp(bi->pubkey_hash, r_bootstrap,
8596                               SHA256_MAC_LEN) == 0) {
8597                         wpa_printf(MSG_DEBUG,
8598                                    "DPP: Found matching own bootstrapping information");
8599                         *own_bi = bi;
8600                 }
8601
8602                 if (!*peer_bi && !bi->own &&
8603                     os_memcmp(bi->pubkey_hash, i_bootstrap,
8604                               SHA256_MAC_LEN) == 0) {
8605                         wpa_printf(MSG_DEBUG,
8606                                    "DPP: Found matching peer bootstrapping information");
8607                         *peer_bi = bi;
8608                 }
8609
8610                 if (*own_bi && *peer_bi)
8611                         break;
8612         }
8613
8614 }
8615
8616
8617 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
8618 {
8619         struct dpp_configurator *conf;
8620         unsigned int max_id = 0;
8621
8622         dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
8623                          list) {
8624                 if (conf->id > max_id)
8625                         max_id = conf->id;
8626         }
8627         return max_id + 1;
8628 }
8629
8630
8631 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
8632 {
8633         char *curve = NULL;
8634         char *key = NULL;
8635         u8 *privkey = NULL;
8636         size_t privkey_len = 0;
8637         int ret = -1;
8638         struct dpp_configurator *conf = NULL;
8639
8640         curve = get_param(cmd, " curve=");
8641         key = get_param(cmd, " key=");
8642
8643         if (key) {
8644                 privkey_len = os_strlen(key) / 2;
8645                 privkey = os_malloc(privkey_len);
8646                 if (!privkey ||
8647                     hexstr2bin(key, privkey, privkey_len) < 0)
8648                         goto fail;
8649         }
8650
8651         conf = dpp_keygen_configurator(curve, privkey, privkey_len);
8652         if (!conf)
8653                 goto fail;
8654
8655         conf->id = dpp_next_configurator_id(dpp);
8656         dl_list_add(&dpp->configurator, &conf->list);
8657         ret = conf->id;
8658         conf = NULL;
8659 fail:
8660         os_free(curve);
8661         str_clear_free(key);
8662         bin_clear_free(privkey, privkey_len);
8663         dpp_configurator_free(conf);
8664         return ret;
8665 }
8666
8667
8668 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
8669 {
8670         struct dpp_configurator *conf, *tmp;
8671         int found = 0;
8672
8673         if (!dpp)
8674                 return -1;
8675
8676         dl_list_for_each_safe(conf, tmp, &dpp->configurator,
8677                               struct dpp_configurator, list) {
8678                 if (id && conf->id != id)
8679                         continue;
8680                 found = 1;
8681                 dl_list_del(&conf->list);
8682                 dpp_configurator_free(conf);
8683         }
8684
8685         if (id == 0)
8686                 return 0; /* flush succeeds regardless of entries found */
8687         return found ? 0 : -1;
8688 }
8689
8690
8691 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
8692 {
8693         unsigned int id_val;
8694
8695         if (os_strcmp(id, "*") == 0) {
8696                 id_val = 0;
8697         } else {
8698                 id_val = atoi(id);
8699                 if (id_val == 0)
8700                         return -1;
8701         }
8702
8703         return dpp_configurator_del(dpp, id_val);
8704 }
8705
8706
8707 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
8708                                 char *buf, size_t buflen)
8709 {
8710         struct dpp_configurator *conf;
8711
8712         conf = dpp_configurator_get_id(dpp, id);
8713         if (!conf)
8714                 return -1;
8715
8716         return dpp_configurator_get_key(conf, buf, buflen);
8717 }
8718
8719
8720 #ifdef CONFIG_DPP2
8721
8722 static void dpp_connection_free(struct dpp_connection *conn)
8723 {
8724         if (conn->sock >= 0) {
8725                 wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
8726                            conn->sock);
8727                 eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
8728                 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8729                 close(conn->sock);
8730         }
8731         wpabuf_free(conn->msg);
8732         wpabuf_free(conn->msg_out);
8733         dpp_auth_deinit(conn->auth);
8734         os_free(conn);
8735 }
8736
8737
8738 static void dpp_connection_remove(struct dpp_connection *conn)
8739 {
8740         dl_list_del(&conn->list);
8741         dpp_connection_free(conn);
8742 }
8743
8744
8745 static void dpp_tcp_init_flush(struct dpp_global *dpp)
8746 {
8747         struct dpp_connection *conn, *tmp;
8748
8749         dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
8750                               list)
8751                 dpp_connection_remove(conn);
8752 }
8753
8754
8755 static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
8756 {
8757         struct dpp_connection *conn, *tmp;
8758
8759         dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
8760                               list)
8761                 dpp_connection_remove(conn);
8762         os_free(ctrl);
8763 }
8764
8765
8766 static void dpp_relay_flush_controllers(struct dpp_global *dpp)
8767 {
8768         struct dpp_relay_controller *ctrl, *tmp;
8769
8770         if (!dpp)
8771                 return;
8772
8773         dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
8774                               struct dpp_relay_controller, list) {
8775                 dl_list_del(&ctrl->list);
8776                 dpp_relay_controller_free(ctrl);
8777         }
8778 }
8779
8780 #endif /* CONFIG_DPP2 */
8781
8782
8783 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
8784 {
8785         struct dpp_global *dpp;
8786
8787         dpp = os_zalloc(sizeof(*dpp));
8788         if (!dpp)
8789                 return NULL;
8790         dpp->msg_ctx = config->msg_ctx;
8791 #ifdef CONFIG_DPP2
8792         dpp->cb_ctx = config->cb_ctx;
8793         dpp->process_conf_obj = config->process_conf_obj;
8794 #endif /* CONFIG_DPP2 */
8795
8796         dl_list_init(&dpp->bootstrap);
8797         dl_list_init(&dpp->configurator);
8798 #ifdef CONFIG_DPP2
8799         dl_list_init(&dpp->controllers);
8800         dl_list_init(&dpp->tcp_init);
8801 #endif /* CONFIG_DPP2 */
8802
8803         return dpp;
8804 }
8805
8806
8807 void dpp_global_clear(struct dpp_global *dpp)
8808 {
8809         if (!dpp)
8810                 return;
8811
8812         dpp_bootstrap_del(dpp, 0);
8813         dpp_configurator_del(dpp, 0);
8814 #ifdef CONFIG_DPP2
8815         dpp_tcp_init_flush(dpp);
8816         dpp_relay_flush_controllers(dpp);
8817         dpp_controller_stop(dpp);
8818 #endif /* CONFIG_DPP2 */
8819 }
8820
8821
8822 void dpp_global_deinit(struct dpp_global *dpp)
8823 {
8824         dpp_global_clear(dpp);
8825         os_free(dpp);
8826 }
8827
8828
8829 #ifdef CONFIG_DPP2
8830
8831 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
8832 static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
8833 static void dpp_controller_auth_success(struct dpp_connection *conn,
8834                                         int initiator);
8835
8836
8837 int dpp_relay_add_controller(struct dpp_global *dpp,
8838                              struct dpp_relay_config *config)
8839 {
8840         struct dpp_relay_controller *ctrl;
8841
8842         if (!dpp)
8843                 return -1;
8844
8845         ctrl = os_zalloc(sizeof(*ctrl));
8846         if (!ctrl)
8847                 return -1;
8848         dl_list_init(&ctrl->conn);
8849         ctrl->global = dpp;
8850         os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
8851         os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
8852         ctrl->cb_ctx = config->cb_ctx;
8853         ctrl->tx = config->tx;
8854         ctrl->gas_resp_tx = config->gas_resp_tx;
8855         dl_list_add(&dpp->controllers, &ctrl->list);
8856         return 0;
8857 }
8858
8859
8860 static struct dpp_relay_controller *
8861 dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
8862 {
8863         struct dpp_relay_controller *ctrl;
8864
8865         if (!dpp)
8866                 return NULL;
8867
8868         dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
8869                          list) {
8870                 if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
8871                         return ctrl;
8872         }
8873
8874         return NULL;
8875 }
8876
8877
8878 static void dpp_controller_gas_done(struct dpp_connection *conn)
8879 {
8880         struct dpp_authentication *auth = conn->auth;
8881
8882         if (auth->peer_version >= 2 &&
8883             auth->conf_resp_status == DPP_STATUS_OK) {
8884                 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
8885                 auth->waiting_conf_result = 1;
8886                 return;
8887         }
8888
8889         wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
8890         dpp_connection_remove(conn);
8891 }
8892
8893
8894 static int dpp_tcp_send(struct dpp_connection *conn)
8895 {
8896         int res;
8897
8898         if (!conn->msg_out) {
8899                 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8900                 conn->write_eloop = 0;
8901                 return -1;
8902         }
8903         res = send(conn->sock,
8904                    wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
8905                    wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
8906         if (res < 0) {
8907                 wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
8908                            strerror(errno));
8909                 dpp_connection_remove(conn);
8910                 return -1;
8911         }
8912
8913         conn->msg_out_pos += res;
8914         if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
8915                 wpa_printf(MSG_DEBUG,
8916                            "DPP: %u/%u bytes of message sent to Controller",
8917                            (unsigned int) conn->msg_out_pos,
8918                            (unsigned int) wpabuf_len(conn->msg_out));
8919                 if (!conn->write_eloop &&
8920                     eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
8921                                         dpp_conn_tx_ready, conn, NULL) == 0)
8922                         conn->write_eloop = 1;
8923                 return 1;
8924         }
8925
8926         wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
8927         wpabuf_free(conn->msg_out);
8928         conn->msg_out = NULL;
8929         conn->msg_out_pos = 0;
8930         eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8931         conn->write_eloop = 0;
8932         if (!conn->read_eloop &&
8933             eloop_register_sock(conn->sock, EVENT_TYPE_READ,
8934                                 dpp_controller_rx, conn, NULL) == 0)
8935                 conn->read_eloop = 1;
8936         if (conn->on_tcp_tx_complete_remove) {
8937                 dpp_connection_remove(conn);
8938         } else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done &&
8939                    conn->auth) {
8940                 dpp_controller_gas_done(conn);
8941         } else if (conn->on_tcp_tx_complete_auth_ok) {
8942                 conn->on_tcp_tx_complete_auth_ok = 0;
8943                 dpp_controller_auth_success(conn, 1);
8944         }
8945
8946         return 0;
8947 }
8948
8949
8950 static void dpp_controller_start_gas_client(struct dpp_connection *conn)
8951 {
8952         struct dpp_authentication *auth = conn->auth;
8953         struct wpabuf *buf;
8954         char json[100];
8955         int netrole_ap = 0; /* TODO: make this configurable */
8956
8957         os_snprintf(json, sizeof(json),
8958                     "{\"name\":\"Test\","
8959                     "\"wi-fi_tech\":\"infra\","
8960                     "\"netRole\":\"%s\"}",
8961                     netrole_ap ? "ap" : "sta");
8962 #ifdef CONFIG_TESTING_OPTIONS
8963         if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
8964                 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
8965                 json[29] = 'k'; /* replace "infra" with "knfra" */
8966         }
8967 #endif /* CONFIG_TESTING_OPTIONS */
8968         wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
8969
8970         buf = dpp_build_conf_req(auth, json);
8971         if (!buf) {
8972                 wpa_printf(MSG_DEBUG,
8973                            "DPP: No configuration request data available");
8974                 return;
8975         }
8976
8977         wpabuf_free(conn->msg_out);
8978         conn->msg_out_pos = 0;
8979         conn->msg_out = wpabuf_alloc(4 + wpabuf_len(buf) - 1);
8980         if (!conn->msg_out) {
8981                 wpabuf_free(buf);
8982                 return;
8983         }
8984         wpabuf_put_be32(conn->msg_out, wpabuf_len(buf) - 1);
8985         wpabuf_put_data(conn->msg_out, wpabuf_head_u8(buf) + 1,
8986                         wpabuf_len(buf) - 1);
8987         wpabuf_free(buf);
8988
8989         if (dpp_tcp_send(conn) == 1) {
8990                 if (!conn->write_eloop) {
8991                         if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
8992                                                 dpp_conn_tx_ready,
8993                                                 conn, NULL) < 0)
8994                                 return;
8995                         conn->write_eloop = 1;
8996                 }
8997         }
8998 }
8999
9000
9001 static void dpp_controller_auth_success(struct dpp_connection *conn,
9002                                         int initiator)
9003 {
9004         struct dpp_authentication *auth = conn->auth;
9005
9006         if (!auth)
9007                 return;
9008
9009         wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
9010         wpa_msg(conn->global->msg_ctx, MSG_INFO,
9011                 DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
9012 #ifdef CONFIG_TESTING_OPTIONS
9013         if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
9014                 wpa_printf(MSG_INFO,
9015                            "DPP: TESTING - stop at Authentication Confirm");
9016                 if (auth->configurator) {
9017                         /* Prevent GAS response */
9018                         auth->auth_success = 0;
9019                 }
9020                 return;
9021         }
9022 #endif /* CONFIG_TESTING_OPTIONS */
9023
9024         if (!auth->configurator)
9025                 dpp_controller_start_gas_client(conn);
9026 }
9027
9028
9029 static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
9030 {
9031         struct dpp_connection *conn = eloop_ctx;
9032
9033         wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
9034         dpp_tcp_send(conn);
9035 }
9036
9037
9038 static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
9039                                   const struct hostapd_ip_addr *ipaddr,
9040                                   int port)
9041 {
9042         struct sockaddr_in *dst;
9043 #ifdef CONFIG_IPV6
9044         struct sockaddr_in6 *dst6;
9045 #endif /* CONFIG_IPV6 */
9046
9047         switch (ipaddr->af) {
9048         case AF_INET:
9049                 dst = (struct sockaddr_in *) addr;
9050                 os_memset(dst, 0, sizeof(*dst));
9051                 dst->sin_family = AF_INET;
9052                 dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
9053                 dst->sin_port = htons(port);
9054                 *addrlen = sizeof(*dst);
9055                 break;
9056 #ifdef CONFIG_IPV6
9057         case AF_INET6:
9058                 dst6 = (struct sockaddr_in6 *) addr;
9059                 os_memset(dst6, 0, sizeof(*dst6));
9060                 dst6->sin6_family = AF_INET6;
9061                 os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
9062                           sizeof(struct in6_addr));
9063                 dst6->sin6_port = htons(port);
9064                 *addrlen = sizeof(*dst6);
9065                 break;
9066 #endif /* CONFIG_IPV6 */
9067         default:
9068                 return -1;
9069         }
9070
9071         return 0;
9072 }
9073
9074
9075 static struct dpp_connection *
9076 dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
9077                    unsigned int freq)
9078 {
9079         struct dpp_connection *conn;
9080         struct sockaddr_storage addr;
9081         socklen_t addrlen;
9082         char txt[100];
9083
9084         if (dl_list_len(&ctrl->conn) >= 15) {
9085                 wpa_printf(MSG_DEBUG,
9086                            "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
9087                 return NULL;
9088         }
9089
9090         if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
9091                                    &ctrl->ipaddr, DPP_TCP_PORT) < 0)
9092                 return NULL;
9093
9094         conn = os_zalloc(sizeof(*conn));
9095         if (!conn)
9096                 return NULL;
9097
9098         conn->global = ctrl->global;
9099         conn->relay = ctrl;
9100         os_memcpy(conn->mac_addr, src, ETH_ALEN);
9101         conn->freq = freq;
9102
9103         conn->sock = socket(AF_INET, SOCK_STREAM, 0);
9104         if (conn->sock < 0)
9105                 goto fail;
9106         wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
9107                    conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
9108
9109         if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9110                 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9111                            strerror(errno));
9112                 goto fail;
9113         }
9114
9115         if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
9116                 if (errno != EINPROGRESS) {
9117                         wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
9118                                    strerror(errno));
9119                         goto fail;
9120                 }
9121
9122                 /*
9123                  * Continue connecting in the background; eloop will call us
9124                  * once the connection is ready (or failed).
9125                  */
9126         }
9127
9128         if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9129                                 dpp_conn_tx_ready, conn, NULL) < 0)
9130                 goto fail;
9131         conn->write_eloop = 1;
9132
9133         /* TODO: eloop timeout to clear a connection if it does not complete
9134          * properly */
9135
9136         dl_list_add(&ctrl->conn, &conn->list);
9137         return conn;
9138 fail:
9139         dpp_connection_free(conn);
9140         return NULL;
9141 }
9142
9143
9144 static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
9145 {
9146         struct wpabuf *msg;
9147
9148         msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
9149         if (!msg)
9150                 return NULL;
9151         wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
9152         wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
9153         wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
9154         wpabuf_put_data(msg, buf, len);
9155         wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
9156         return msg;
9157 }
9158
9159
9160 static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
9161                         const u8 *buf, size_t len)
9162 {
9163         u8 type = hdr[DPP_HDR_LEN - 1];
9164
9165         wpa_printf(MSG_DEBUG,
9166                    "DPP: Continue already established Relay/Controller connection for this session");
9167         wpabuf_free(conn->msg_out);
9168         conn->msg_out_pos = 0;
9169         conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
9170         if (!conn->msg_out) {
9171                 dpp_connection_remove(conn);
9172                 return -1;
9173         }
9174
9175         /* TODO: for proto ver 1, need to do remove connection based on GAS Resp
9176          * TX status */
9177         if (type == DPP_PA_CONFIGURATION_RESULT)
9178                 conn->on_tcp_tx_complete_remove = 1;
9179         dpp_tcp_send(conn);
9180         return 0;
9181 }
9182
9183
9184 int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
9185                         const u8 *buf, size_t len, unsigned int freq,
9186                         const u8 *i_bootstrap, const u8 *r_bootstrap)
9187 {
9188         struct dpp_relay_controller *ctrl;
9189         struct dpp_connection *conn;
9190         u8 type = hdr[DPP_HDR_LEN - 1];
9191
9192         /* Check if there is an already started session for this peer and if so,
9193          * continue that session (send this over TCP) and return 0.
9194          */
9195         if (type != DPP_PA_PEER_DISCOVERY_REQ &&
9196             type != DPP_PA_PEER_DISCOVERY_RESP) {
9197                 dl_list_for_each(ctrl, &dpp->controllers,
9198                                  struct dpp_relay_controller, list) {
9199                         dl_list_for_each(conn, &ctrl->conn,
9200                                          struct dpp_connection, list) {
9201                                 if (os_memcmp(src, conn->mac_addr,
9202                                               ETH_ALEN) == 0)
9203                                         return dpp_relay_tx(conn, hdr, buf, len);
9204                         }
9205                 }
9206         }
9207
9208         if (!r_bootstrap)
9209                 return -1;
9210
9211         ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
9212         if (!ctrl)
9213                 return -1;
9214
9215         wpa_printf(MSG_DEBUG,
9216                    "DPP: Authentication Request for a configured Controller");
9217         conn = dpp_relay_new_conn(ctrl, src, freq);
9218         if (!conn)
9219                 return -1;
9220
9221         conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
9222         if (!conn->msg_out) {
9223                 dpp_connection_remove(conn);
9224                 return -1;
9225         }
9226         /* Message will be sent in dpp_conn_tx_ready() */
9227
9228         return 0;
9229 }
9230
9231
9232 int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
9233                          size_t data_len)
9234 {
9235         struct dpp_relay_controller *ctrl;
9236         struct dpp_connection *conn, *found = NULL;
9237         struct wpabuf *msg;
9238
9239         /* Check if there is a successfully completed authentication for this
9240          * and if so, continue that session (send this over TCP) and return 0.
9241          */
9242         dl_list_for_each(ctrl, &dpp->controllers,
9243                          struct dpp_relay_controller, list) {
9244                 if (found)
9245                         break;
9246                 dl_list_for_each(conn, &ctrl->conn,
9247                                  struct dpp_connection, list) {
9248                         if (os_memcmp(src, conn->mac_addr,
9249                                       ETH_ALEN) == 0) {
9250                                 found = conn;
9251                                 break;
9252                         }
9253                 }
9254         }
9255
9256         if (!found)
9257                 return -1;
9258
9259         msg = wpabuf_alloc(4 + 1 + data_len);
9260         if (!msg)
9261                 return -1;
9262         wpabuf_put_be32(msg, 1 + data_len);
9263         wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
9264         wpabuf_put_data(msg, data, data_len);
9265         wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
9266
9267         wpabuf_free(conn->msg_out);
9268         conn->msg_out_pos = 0;
9269         conn->msg_out = msg;
9270         dpp_tcp_send(conn);
9271         return 0;
9272 }
9273
9274
9275 static void dpp_controller_free(struct dpp_controller *ctrl)
9276 {
9277         struct dpp_connection *conn, *tmp;
9278
9279         if (!ctrl)
9280                 return;
9281
9282         dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
9283                               list)
9284                 dpp_connection_remove(conn);
9285
9286         if (ctrl->sock >= 0) {
9287                 close(ctrl->sock);
9288                 eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
9289         }
9290         os_free(ctrl->configurator_params);
9291         os_free(ctrl);
9292 }
9293
9294
9295 static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
9296                                       const u8 *hdr, const u8 *buf, size_t len)
9297 {
9298         const u8 *r_bootstrap, *i_bootstrap;
9299         u16 r_bootstrap_len, i_bootstrap_len;
9300         struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
9301
9302         if (!conn->ctrl)
9303                 return 0;
9304
9305         wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
9306
9307         r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
9308                                    &r_bootstrap_len);
9309         if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
9310                 wpa_printf(MSG_INFO,
9311                            "Missing or invalid required Responder Bootstrapping Key Hash attribute");
9312                 return -1;
9313         }
9314         wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
9315                     r_bootstrap, r_bootstrap_len);
9316
9317         i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
9318                                    &i_bootstrap_len);
9319         if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
9320                 wpa_printf(MSG_INFO,
9321                            "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
9322                 return -1;
9323         }
9324         wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
9325                     i_bootstrap, i_bootstrap_len);
9326
9327         /* Try to find own and peer bootstrapping key matches based on the
9328          * received hash values */
9329         dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
9330                                 &own_bi, &peer_bi);
9331         if (!own_bi) {
9332                 wpa_printf(MSG_INFO,
9333                         "No matching own bootstrapping key found - ignore message");
9334                 return -1;
9335         }
9336
9337         if (conn->auth) {
9338                 wpa_printf(MSG_INFO,
9339                            "Already in DPP authentication exchange - ignore new one");
9340                 return 0;
9341         }
9342
9343         conn->auth = dpp_auth_req_rx(conn->ctrl->global->msg_ctx,
9344                                      conn->ctrl->allowed_roles,
9345                                      conn->ctrl->qr_mutual,
9346                                      peer_bi, own_bi, -1, hdr, buf, len);
9347         if (!conn->auth) {
9348                 wpa_printf(MSG_DEBUG, "DPP: No response generated");
9349                 return -1;
9350         }
9351
9352         if (dpp_set_configurator(conn->ctrl->global, conn->ctrl->global->msg_ctx,
9353                                  conn->auth,
9354                                  conn->ctrl->configurator_params) < 0) {
9355                 dpp_connection_remove(conn);
9356                 return -1;
9357         }
9358
9359         wpabuf_free(conn->msg_out);
9360         conn->msg_out_pos = 0;
9361         conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->resp_msg) - 1);
9362         if (!conn->msg_out)
9363                 return -1;
9364         wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->resp_msg) - 1);
9365         wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->resp_msg) + 1,
9366                         wpabuf_len(conn->auth->resp_msg) - 1);
9367
9368         if (dpp_tcp_send(conn) == 1) {
9369                 if (!conn->write_eloop) {
9370                         if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9371                                                 dpp_conn_tx_ready,
9372                                                 conn, NULL) < 0)
9373                                 return -1;
9374                         conn->write_eloop = 1;
9375                 }
9376         }
9377
9378         return 0;
9379 }
9380
9381
9382 static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
9383                                        const u8 *hdr, const u8 *buf, size_t len)
9384 {
9385         struct dpp_authentication *auth = conn->auth;
9386         struct wpabuf *msg;
9387
9388         if (!auth)
9389                 return -1;
9390
9391         wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
9392
9393         msg = dpp_auth_resp_rx(auth, hdr, buf, len);
9394         if (!msg) {
9395                 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
9396                         wpa_printf(MSG_DEBUG,
9397                                    "DPP: Start wait for full response");
9398                         return -1;
9399                 }
9400                 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
9401                 dpp_connection_remove(conn);
9402                 return -1;
9403         }
9404
9405         wpabuf_free(conn->msg_out);
9406         conn->msg_out_pos = 0;
9407         conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
9408         if (!conn->msg_out) {
9409                 wpabuf_free(msg);
9410                 return -1;
9411         }
9412         wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
9413         wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
9414                         wpabuf_len(msg) - 1);
9415         wpabuf_free(msg);
9416
9417         conn->on_tcp_tx_complete_auth_ok = 1;
9418         if (dpp_tcp_send(conn) == 1) {
9419                 if (!conn->write_eloop) {
9420                         if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9421                                                 dpp_conn_tx_ready,
9422                                                 conn, NULL) < 0)
9423                                 return -1;
9424                         conn->write_eloop = 1;
9425                 }
9426         }
9427
9428         return 0;
9429 }
9430
9431
9432 static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
9433                                        const u8 *hdr, const u8 *buf, size_t len)
9434 {
9435         struct dpp_authentication *auth = conn->auth;
9436
9437         wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
9438
9439         if (!auth) {
9440                 wpa_printf(MSG_DEBUG,
9441                            "DPP: No DPP Authentication in progress - drop");
9442                 return -1;
9443         }
9444
9445         if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
9446                 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
9447                 return -1;
9448         }
9449
9450         dpp_controller_auth_success(conn, 0);
9451         return 0;
9452 }
9453
9454
9455 static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
9456                                          const u8 *hdr, const u8 *buf,
9457                                          size_t len)
9458 {
9459         struct dpp_authentication *auth = conn->auth;
9460         enum dpp_status_error status;
9461
9462         if (!conn->ctrl)
9463                 return 0;
9464
9465         wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
9466
9467         if (!auth || !auth->waiting_conf_result) {
9468                 wpa_printf(MSG_DEBUG,
9469                            "DPP: No DPP Configuration waiting for result - drop");
9470                 return -1;
9471         }
9472
9473         status = dpp_conf_result_rx(auth, hdr, buf, len);
9474         if (status == DPP_STATUS_OK)
9475                 wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
9476                         DPP_EVENT_CONF_SENT);
9477         else
9478                 wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
9479                         DPP_EVENT_CONF_FAILED);
9480         return -1; /* to remove the completed connection */
9481 }
9482
9483
9484 static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
9485                                     size_t len)
9486 {
9487         const u8 *pos, *end;
9488         u8 type;
9489
9490         wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
9491         pos = msg;
9492         end = msg + len;
9493
9494         if (end - pos < DPP_HDR_LEN ||
9495             WPA_GET_BE24(pos) != OUI_WFA ||
9496             pos[3] != DPP_OUI_TYPE) {
9497                 wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
9498                 return -1;
9499         }
9500
9501         if (pos[4] != 1) {
9502                 wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
9503                            pos[4]);
9504                 return -1;
9505         }
9506         type = pos[5];
9507         wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
9508         pos += DPP_HDR_LEN;
9509
9510         wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
9511                     pos, end - pos);
9512         if (dpp_check_attrs(pos, end - pos) < 0)
9513                 return -1;
9514
9515         if (conn->relay) {
9516                 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
9517                 conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
9518                                 conn->freq, msg, len);
9519                 return 0;
9520         }
9521
9522         switch (type) {
9523         case DPP_PA_AUTHENTICATION_REQ:
9524                 return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
9525         case DPP_PA_AUTHENTICATION_RESP:
9526                 return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
9527         case DPP_PA_AUTHENTICATION_CONF:
9528                 return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
9529         case DPP_PA_CONFIGURATION_RESULT:
9530                 return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
9531         default:
9532                 /* TODO: missing messages types */
9533                 wpa_printf(MSG_DEBUG,
9534                            "DPP: Unsupported frame subtype %d", type);
9535                 return -1;
9536         }
9537 }
9538
9539
9540 static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
9541                                      size_t len)
9542 {
9543         const u8 *pos, *end, *next;
9544         u8 dialog_token;
9545         const u8 *adv_proto;
9546         u16 slen;
9547         struct wpabuf *resp, *buf;
9548         struct dpp_authentication *auth = conn->auth;
9549
9550         if (len < 1 + 2)
9551                 return -1;
9552
9553         wpa_printf(MSG_DEBUG,
9554                    "DPP: Received DPP Configuration Request over TCP");
9555
9556         if (!conn->ctrl || !auth || !auth->auth_success) {
9557                 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
9558                 return -1;
9559         }
9560
9561         pos = msg;
9562         end = msg + len;
9563
9564         dialog_token = *pos++;
9565         adv_proto = pos++;
9566         slen = *pos++;
9567         if (*adv_proto != WLAN_EID_ADV_PROTO ||
9568             slen > end - pos || slen < 2)
9569                 return -1;
9570
9571         next = pos + slen;
9572         pos++; /* skip QueryRespLenLimit and PAME-BI */
9573
9574         if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
9575             pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
9576             pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
9577                 return -1;
9578
9579         pos = next;
9580         /* Query Request */
9581         if (end - pos < 2)
9582                 return -1;
9583         slen = WPA_GET_LE16(pos);
9584         pos += 2;
9585         if (slen > end - pos)
9586                 return -1;
9587
9588         resp = dpp_conf_req_rx(auth, pos, slen);
9589         if (!resp)
9590                 return -1;
9591
9592         buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp));
9593         if (!buf) {
9594                 wpabuf_free(resp);
9595                 return -1;
9596         }
9597
9598         wpabuf_put_be32(buf, 18 + wpabuf_len(resp));
9599
9600         wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP);
9601         wpabuf_put_u8(buf, dialog_token);
9602         wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
9603         wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
9604
9605         dpp_write_adv_proto(buf);
9606         dpp_write_gas_query(buf, resp);
9607         wpabuf_free(resp);
9608
9609         /* Send Config Response over TCP; GAS fragmentation is taken care of by
9610          * the Relay */
9611         wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
9612         wpabuf_free(conn->msg_out);
9613         conn->msg_out_pos = 0;
9614         conn->msg_out = buf;
9615         conn->on_tcp_tx_complete_gas_done = 1;
9616         dpp_tcp_send(conn);
9617         return 0;
9618 }
9619
9620
9621 static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
9622 {
9623         struct dpp_authentication *auth = conn->auth;
9624         int res;
9625         struct wpabuf *msg, *encaps;
9626         enum dpp_status_error status;
9627
9628         wpa_printf(MSG_DEBUG,
9629                    "DPP: Configuration Response for local stack from TCP");
9630
9631         res = dpp_conf_resp_rx(auth, resp);
9632         wpabuf_free(resp);
9633         if (res < 0) {
9634                 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
9635                 return -1;
9636         }
9637
9638         if (conn->global->process_conf_obj)
9639                 res = conn->global->process_conf_obj(conn->global->cb_ctx,
9640                                                      auth);
9641         else
9642                 res = 0;
9643
9644         if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
9645                 return -1;
9646
9647         wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
9648         status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
9649         msg = dpp_build_conf_result(auth, status);
9650         if (!msg)
9651                 return -1;
9652
9653         encaps = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
9654         if (!encaps) {
9655                 wpabuf_free(msg);
9656                 return -1;
9657         }
9658         wpabuf_put_be32(encaps, wpabuf_len(msg) - 1);
9659         wpabuf_put_data(encaps, wpabuf_head_u8(msg) + 1, wpabuf_len(msg) - 1);
9660         wpabuf_free(msg);
9661         wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", encaps);
9662
9663         wpabuf_free(conn->msg_out);
9664         conn->msg_out_pos = 0;
9665         conn->msg_out = encaps;
9666         conn->on_tcp_tx_complete_remove = 1;
9667         dpp_tcp_send(conn);
9668
9669         /* This exchange will be terminated in the TX status handler */
9670
9671         return 0;
9672 }
9673
9674
9675 static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
9676                            size_t len)
9677 {
9678         struct wpabuf *buf;
9679         u8 dialog_token;
9680         const u8 *pos, *end, *next, *adv_proto;
9681         u16 status, slen;
9682
9683         if (len < 5 + 2)
9684                 return -1;
9685
9686         wpa_printf(MSG_DEBUG,
9687                    "DPP: Received DPP Configuration Response over TCP");
9688
9689         pos = msg;
9690         end = msg + len;
9691
9692         dialog_token = *pos++;
9693         status = WPA_GET_LE16(pos);
9694         if (status != WLAN_STATUS_SUCCESS) {
9695                 wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
9696                 return -1;
9697         }
9698         pos += 2;
9699         pos += 2; /* ignore GAS Comeback Delay */
9700
9701         adv_proto = pos++;
9702         slen = *pos++;
9703         if (*adv_proto != WLAN_EID_ADV_PROTO ||
9704             slen > end - pos || slen < 2)
9705                 return -1;
9706
9707         next = pos + slen;
9708         pos++; /* skip QueryRespLenLimit and PAME-BI */
9709
9710         if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
9711             pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
9712             pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
9713                 return -1;
9714
9715         pos = next;
9716         /* Query Response */
9717         if (end - pos < 2)
9718                 return -1;
9719         slen = WPA_GET_LE16(pos);
9720         pos += 2;
9721         if (slen > end - pos)
9722                 return -1;
9723
9724         buf = wpabuf_alloc(slen);
9725         if (!buf)
9726                 return -1;
9727         wpabuf_put_data(buf, pos, slen);
9728
9729         if (!conn->relay && !conn->ctrl)
9730                 return dpp_tcp_rx_gas_resp(conn, buf);
9731
9732         if (!conn->relay) {
9733                 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
9734                 wpabuf_free(buf);
9735                 return -1;
9736         }
9737         wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
9738         conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
9739                                  dialog_token, 0, buf);
9740
9741         return 0;
9742 }
9743
9744
9745 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
9746 {
9747         struct dpp_connection *conn = eloop_ctx;
9748         int res;
9749         const u8 *pos;
9750
9751         wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
9752                    sd);
9753
9754         if (conn->msg_len_octets < 4) {
9755                 u32 msglen;
9756
9757                 res = recv(sd, &conn->msg_len[conn->msg_len_octets],
9758                            4 - conn->msg_len_octets, 0);
9759                 if (res < 0) {
9760                         wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
9761                                    strerror(errno));
9762                         dpp_connection_remove(conn);
9763                         return;
9764                 }
9765                 if (res == 0) {
9766                         wpa_printf(MSG_DEBUG,
9767                                    "DPP: No more data available over TCP");
9768                         dpp_connection_remove(conn);
9769                         return;
9770                 }
9771                 wpa_printf(MSG_DEBUG,
9772                            "DPP: Received %d/%d octet(s) of message length field",
9773                            res, (int) (4 - conn->msg_len_octets));
9774                 conn->msg_len_octets += res;
9775
9776                 if (conn->msg_len_octets < 4) {
9777                         wpa_printf(MSG_DEBUG,
9778                                    "DPP: Need %d more octets of message length field",
9779                                    (int) (4 - conn->msg_len_octets));
9780                         return;
9781                 }
9782
9783                 msglen = WPA_GET_BE32(conn->msg_len);
9784                 wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
9785                 if (msglen > 65535) {
9786                         wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
9787                         dpp_connection_remove(conn);
9788                         return;
9789                 }
9790
9791                 wpabuf_free(conn->msg);
9792                 conn->msg = wpabuf_alloc(msglen);
9793         }
9794
9795         if (!conn->msg) {
9796                 wpa_printf(MSG_DEBUG,
9797                            "DPP: No buffer available for receiving the message");
9798                 dpp_connection_remove(conn);
9799                 return;
9800         }
9801
9802         wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
9803                    (unsigned int) wpabuf_tailroom(conn->msg));
9804
9805         res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
9806         if (res < 0) {
9807                 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
9808                 dpp_connection_remove(conn);
9809                 return;
9810         }
9811         if (res == 0) {
9812                 wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
9813                 dpp_connection_remove(conn);
9814                 return;
9815         }
9816         wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
9817         wpabuf_put(conn->msg, res);
9818
9819         if (wpabuf_tailroom(conn->msg) > 0) {
9820                 wpa_printf(MSG_DEBUG,
9821                            "DPP: Need %u more octets of message payload",
9822                            (unsigned int) wpabuf_tailroom(conn->msg));
9823                 return;
9824         }
9825
9826         conn->msg_len_octets = 0;
9827         wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
9828         if (wpabuf_len(conn->msg) < 1) {
9829                 dpp_connection_remove(conn);
9830                 return;
9831         }
9832
9833         pos = wpabuf_head(conn->msg);
9834         switch (*pos) {
9835         case WLAN_PA_VENDOR_SPECIFIC:
9836                 if (dpp_controller_rx_action(conn, pos + 1,
9837                                              wpabuf_len(conn->msg) - 1) < 0)
9838                         dpp_connection_remove(conn);
9839                 break;
9840         case WLAN_PA_GAS_INITIAL_REQ:
9841                 if (dpp_controller_rx_gas_req(conn, pos + 1,
9842                                               wpabuf_len(conn->msg) - 1) < 0)
9843                         dpp_connection_remove(conn);
9844                 break;
9845         case WLAN_PA_GAS_INITIAL_RESP:
9846                 if (dpp_rx_gas_resp(conn, pos + 1,
9847                                     wpabuf_len(conn->msg) - 1) < 0)
9848                         dpp_connection_remove(conn);
9849                 break;
9850         default:
9851                 wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
9852                            *pos);
9853                 break;
9854         }
9855 }
9856
9857
9858 static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
9859 {
9860         struct dpp_controller *ctrl = eloop_ctx;
9861         struct sockaddr_in addr;
9862         socklen_t addr_len = sizeof(addr);
9863         int fd;
9864         struct dpp_connection *conn;
9865
9866         wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
9867
9868         fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
9869         if (fd < 0) {
9870                 wpa_printf(MSG_DEBUG,
9871                            "DPP: Failed to accept new connection: %s",
9872                            strerror(errno));
9873                 return;
9874         }
9875         wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
9876                    inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
9877
9878         conn = os_zalloc(sizeof(*conn));
9879         if (!conn)
9880                 goto fail;
9881
9882         conn->global = ctrl->global;
9883         conn->ctrl = ctrl;
9884         conn->sock = fd;
9885
9886         if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9887                 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9888                            strerror(errno));
9889                 goto fail;
9890         }
9891
9892         if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
9893                                 dpp_controller_rx, conn, NULL) < 0)
9894                 goto fail;
9895         conn->read_eloop = 1;
9896
9897         /* TODO: eloop timeout to expire connections that do not complete in
9898          * reasonable time */
9899         dl_list_add(&ctrl->conn, &conn->list);
9900         return;
9901
9902 fail:
9903         close(fd);
9904         os_free(conn);
9905 }
9906
9907
9908 int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
9909                  const struct hostapd_ip_addr *addr, int port)
9910 {
9911         struct dpp_connection *conn;
9912         struct sockaddr_storage saddr;
9913         socklen_t addrlen;
9914         const u8 *hdr, *pos, *end;
9915         char txt[100];
9916
9917         wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
9918                    hostapd_ip_txt(addr, txt, sizeof(txt)), port);
9919         if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
9920                                    addr, port) < 0) {
9921                 dpp_auth_deinit(auth);
9922                 return -1;
9923         }
9924
9925         conn = os_zalloc(sizeof(*conn));
9926         if (!conn) {
9927                 dpp_auth_deinit(auth);
9928                 return -1;
9929         }
9930
9931         conn->global = dpp;
9932         conn->auth = auth;
9933         conn->sock = socket(AF_INET, SOCK_STREAM, 0);
9934         if (conn->sock < 0)
9935                 goto fail;
9936
9937         if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9938                 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9939                            strerror(errno));
9940                 goto fail;
9941         }
9942
9943         if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
9944                 if (errno != EINPROGRESS) {
9945                         wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
9946                                    strerror(errno));
9947                         goto fail;
9948                 }
9949
9950                 /*
9951                  * Continue connecting in the background; eloop will call us
9952                  * once the connection is ready (or failed).
9953                  */
9954         }
9955
9956         if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9957                                 dpp_conn_tx_ready, conn, NULL) < 0)
9958                 goto fail;
9959         conn->write_eloop = 1;
9960
9961         hdr = wpabuf_head(auth->req_msg);
9962         end = hdr + wpabuf_len(auth->req_msg);
9963         hdr += 2; /* skip Category and Actiom */
9964         pos = hdr + DPP_HDR_LEN;
9965         conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
9966         if (!conn->msg_out)
9967                 goto fail;
9968         /* Message will be sent in dpp_conn_tx_ready() */
9969
9970         /* TODO: eloop timeout to clear a connection if it does not complete
9971          * properly */
9972         dl_list_add(&dpp->tcp_init, &conn->list);
9973         return 0;
9974 fail:
9975         dpp_connection_free(conn);
9976         return -1;
9977 }
9978
9979
9980 int dpp_controller_start(struct dpp_global *dpp,
9981                          struct dpp_controller_config *config)
9982 {
9983         struct dpp_controller *ctrl;
9984         int on = 1;
9985         struct sockaddr_in sin;
9986         int port;
9987
9988         if (!dpp || dpp->controller)
9989                 return -1;
9990
9991         ctrl = os_zalloc(sizeof(*ctrl));
9992         if (!ctrl)
9993                 return -1;
9994         ctrl->global = dpp;
9995         if (config->configurator_params)
9996                 ctrl->configurator_params =
9997                         os_strdup(config->configurator_params);
9998         dl_list_init(&ctrl->conn);
9999         /* TODO: configure these somehow */
10000         ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
10001         ctrl->qr_mutual = 0;
10002
10003         ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
10004         if (ctrl->sock < 0)
10005                 goto fail;
10006
10007         if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
10008                        &on, sizeof(on)) < 0) {
10009                 wpa_printf(MSG_DEBUG,
10010                            "DPP: setsockopt(SO_REUSEADDR) failed: %s",
10011                            strerror(errno));
10012                 /* try to continue anyway */
10013         }
10014
10015         if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
10016                 wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
10017                            strerror(errno));
10018                 goto fail;
10019         }
10020
10021         /* TODO: IPv6 */
10022         os_memset(&sin, 0, sizeof(sin));
10023         sin.sin_family = AF_INET;
10024         sin.sin_addr.s_addr = INADDR_ANY;
10025         port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
10026         sin.sin_port = htons(port);
10027         if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
10028                 wpa_printf(MSG_INFO,
10029                            "DPP: Failed to bind Controller TCP port: %s",
10030                            strerror(errno));
10031                 goto fail;
10032         }
10033         if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
10034             fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
10035             eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
10036                                 dpp_controller_tcp_cb, ctrl, NULL))
10037                 goto fail;
10038
10039         dpp->controller = ctrl;
10040         wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
10041         return 0;
10042 fail:
10043         dpp_controller_free(ctrl);
10044         return -1;
10045 }
10046
10047
10048 void dpp_controller_stop(struct dpp_global *dpp)
10049 {
10050         if (dpp) {
10051                 dpp_controller_free(dpp->controller);
10052                 dpp->controller = NULL;
10053         }
10054 }
10055
10056 #endif /* CONFIG_DPP2 */