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 */
10057