xref: /netbsd/external/bsd/wpa/dist/src/common/dpp.c (revision 72504a81)
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 
ECDSA_SIG_set0(ECDSA_SIG * sig,BIGNUM * r,BIGNUM * s)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 
ECDSA_SIG_get0(const ECDSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)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 
dpp_debug_print_point(const char * title,const EC_GROUP * group,const EC_POINT * point)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 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)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 
dpp_hmac_vector(size_t hash_len,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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 
dpp_bn2bin_pad(const BIGNUM * bn,u8 * pos,size_t len)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 
dpp_get_pubkey_point(EVP_PKEY * pkey,int prefix)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 
dpp_set_pubkey_point_group(const EC_GROUP * group,const u8 * buf_x,const u8 * buf_y,size_t len)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 
dpp_set_pubkey_point(EVP_PKEY * group_key,const u8 * buf,size_t len)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 
dpp_ecdh(EVP_PKEY * own,EVP_PKEY * peer,u8 * secret,size_t * secret_len)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 
dpp_auth_fail(struct dpp_authentication * auth,const char * txt)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 
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)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 
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)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 
dpp_check_attrs(const u8 * buf,size_t len)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 
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)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 
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)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 
dpp_uri_valid_info(const char * info)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 
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)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 
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)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 
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)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 
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)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 *
dpp_get_curve_oid(const ASN1_OBJECT * poid)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 
dpp_get_curve_nid(int nid)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 
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)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 
dpp_parse_uri(const char * uri)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 
dpp_parse_qr_code(const char * uri)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 
dpp_debug_print_key(const char * title,EVP_PKEY * key)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 
dpp_gen_keypair(const struct dpp_curve_params * curve)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 *
dpp_get_curve_name(const char * name)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 *
dpp_get_curve_jwk_crv(const char * name)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 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)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 
dpp_bootstrap_key_der(EVP_PKEY * key)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 
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)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 
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,const u8 * privkey,size_t privkey_len)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 
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)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 
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)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 
dpp_derive_ke(struct dpp_authentication * auth,u8 * ke,unsigned int hash_len)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 
dpp_build_attr_status(struct wpabuf * msg,enum dpp_status_error status)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 
dpp_build_attr_r_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)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 
dpp_build_attr_i_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)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 
dpp_auth_build_req(struct dpp_authentication * auth,const struct wpabuf * pi,size_t nonce_len,const u8 * r_pubkey_hash,const u8 * i_pubkey_hash,unsigned int neg_freq)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 
dpp_auth_build_resp(struct dpp_authentication * auth,enum dpp_status_error status,const struct wpabuf * pr,size_t nonce_len,const u8 * r_pubkey_hash,const u8 * i_pubkey_hash,const u8 * r_nonce,const u8 * i_nonce,const u8 * wrapped_r_auth,size_t wrapped_r_auth_len,const u8 * siv_key)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 
dpp_channel_ok_init(struct hostapd_hw_modes * own_modes,u16 num_modes,unsigned int freq)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 
freq_included(const unsigned int freqs[],unsigned int num,unsigned int freq)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 
freq_to_start(unsigned int freqs[],unsigned int num,unsigned int freq)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 
dpp_channel_intersect(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)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 
dpp_channel_local_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)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 
dpp_prepare_channel_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)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 
dpp_autogen_bootstrap_key(struct dpp_authentication * auth)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 
dpp_auth_init(void * msg_ctx,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,u8 dpp_allowed_roles,unsigned int neg_freq,struct hostapd_hw_modes * own_modes,u16 num_modes)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 
dpp_build_conf_req_attr(struct dpp_authentication * auth,const char * json)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 
dpp_write_adv_proto(struct wpabuf * buf)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 
dpp_write_gas_query(struct wpabuf * buf,struct wpabuf * query)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 
dpp_build_conf_req(struct dpp_authentication * auth,const char * json)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 
dpp_auth_success(struct dpp_authentication * auth)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 
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)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 
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)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 
dpp_auth_derive_l_responder(struct dpp_authentication * auth)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 
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)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 
dpp_auth_build_resp_ok(struct dpp_authentication * auth)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 
dpp_auth_build_resp_status(struct dpp_authentication * auth,enum dpp_status_error status)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 *
dpp_auth_req_rx(void * msg_ctx,u8 dpp_allowed_roles,int qr_mutual,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,unsigned int freq,const u8 * hdr,const u8 * attr_start,size_t attr_len)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 
dpp_notify_new_qr_code(struct dpp_authentication * auth,struct dpp_bootstrap_info * peer_bi)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 
dpp_auth_build_conf(struct dpp_authentication * auth,enum dpp_status_error status)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
dpp_auth_resp_rx_status(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,const u8 * wrapped_data,u16 wrapped_data_len,enum dpp_status_error status)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 *
dpp_auth_resp_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)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 
dpp_auth_conf_rx_failure(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,const u8 * wrapped_data,u16 wrapped_data_len,enum dpp_status_error status)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 
dpp_auth_conf_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)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 
bin_str_eq(const char * val,size_t len,const char * cmp)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 
dpp_configuration_alloc(const char * type)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 
dpp_akm_psk(enum dpp_akm akm)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 
dpp_akm_sae(enum dpp_akm akm)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 
dpp_akm_legacy(enum dpp_akm akm)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 
dpp_akm_dpp(enum dpp_akm akm)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 
dpp_akm_ver2(enum dpp_akm akm)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 
dpp_configuration_valid(const struct dpp_configuration * conf)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 
dpp_configuration_free(struct dpp_configuration * conf)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 
dpp_configuration_parse(struct dpp_authentication * auth,const char * cmd)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 *
dpp_configurator_get_id(struct dpp_global * dpp,unsigned int id)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 
dpp_set_configurator(struct dpp_global * dpp,void * msg_ctx,struct dpp_authentication * auth,const char * cmd)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 
dpp_auth_deinit(struct dpp_authentication * auth)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 *
dpp_build_conf_start(struct dpp_authentication * auth,struct dpp_configuration * conf,size_t tailroom)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 
dpp_build_jwk(struct wpabuf * buf,const char * name,EVP_PKEY * key,const char * kid,const struct dpp_curve_params * curve)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 
dpp_build_legacy_cred_params(struct wpabuf * buf,struct dpp_configuration * conf)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 *
dpp_build_conf_obj_dpp(struct dpp_authentication * auth,int ap,struct dpp_configuration * conf)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 *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,int ap,struct dpp_configuration * conf)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 *
dpp_build_conf_obj(struct dpp_authentication * auth,int ap)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 *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,int ap)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 *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)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 *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params * curve,const u8 * prot_hdr,u16 prot_hdr_len,const EVP_MD ** ret_md)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 
dpp_parse_cred_legacy(struct dpp_authentication * auth,struct json_token * cred)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 
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)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 
dpp_key_expired(const char * timestamp,os_time_t * expiry)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 (%llu < %llu)",
5377 			   (unsigned long long)utime,
5378 			   (unsigned long long)now.sec);
5379 		return 1;
5380 	}
5381 
5382 	return 0;
5383 }
5384 
5385 
dpp_parse_connector(struct dpp_authentication * auth,const unsigned char * payload,u16 payload_len)5386 static int dpp_parse_connector(struct dpp_authentication *auth,
5387 			       const unsigned char *payload,
5388 			       u16 payload_len)
5389 {
5390 	struct json_token *root, *groups, *netkey, *token;
5391 	int ret = -1;
5392 	EVP_PKEY *key = NULL;
5393 	const struct dpp_curve_params *curve;
5394 	unsigned int rules = 0;
5395 
5396 	root = json_parse((const char *) payload, payload_len);
5397 	if (!root) {
5398 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
5399 		goto fail;
5400 	}
5401 
5402 	groups = json_get_member(root, "groups");
5403 	if (!groups || groups->type != JSON_ARRAY) {
5404 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
5405 		goto skip_groups;
5406 	}
5407 	for (token = groups->child; token; token = token->sibling) {
5408 		struct json_token *id, *role;
5409 
5410 		id = json_get_member(token, "groupId");
5411 		if (!id || id->type != JSON_STRING) {
5412 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
5413 			goto fail;
5414 		}
5415 
5416 		role = json_get_member(token, "netRole");
5417 		if (!role || role->type != JSON_STRING) {
5418 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
5419 			goto fail;
5420 		}
5421 		wpa_printf(MSG_DEBUG,
5422 			   "DPP: connector group: groupId='%s' netRole='%s'",
5423 			   id->string, role->string);
5424 		rules++;
5425 	}
5426 skip_groups:
5427 
5428 	if (!rules) {
5429 		wpa_printf(MSG_DEBUG,
5430 			   "DPP: Connector includes no groups");
5431 		goto fail;
5432 	}
5433 
5434 	token = json_get_member(root, "expiry");
5435 	if (!token || token->type != JSON_STRING) {
5436 		wpa_printf(MSG_DEBUG,
5437 			   "DPP: No expiry string found - connector does not expire");
5438 	} else {
5439 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
5440 		if (dpp_key_expired(token->string,
5441 				    &auth->net_access_key_expiry)) {
5442 			wpa_printf(MSG_DEBUG,
5443 				   "DPP: Connector (netAccessKey) has expired");
5444 			goto fail;
5445 		}
5446 	}
5447 
5448 	netkey = json_get_member(root, "netAccessKey");
5449 	if (!netkey || netkey->type != JSON_OBJECT) {
5450 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
5451 		goto fail;
5452 	}
5453 
5454 	key = dpp_parse_jwk(netkey, &curve);
5455 	if (!key)
5456 		goto fail;
5457 	dpp_debug_print_key("DPP: Received netAccessKey", key);
5458 
5459 	if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
5460 		wpa_printf(MSG_DEBUG,
5461 			   "DPP: netAccessKey in connector does not match own protocol key");
5462 #ifdef CONFIG_TESTING_OPTIONS
5463 		if (auth->ignore_netaccesskey_mismatch) {
5464 			wpa_printf(MSG_DEBUG,
5465 				   "DPP: TESTING - skip netAccessKey mismatch");
5466 		} else {
5467 			goto fail;
5468 		}
5469 #else /* CONFIG_TESTING_OPTIONS */
5470 		goto fail;
5471 #endif /* CONFIG_TESTING_OPTIONS */
5472 	}
5473 
5474 	ret = 0;
5475 fail:
5476 	EVP_PKEY_free(key);
5477 	json_free(root);
5478 	return ret;
5479 }
5480 
5481 
dpp_check_pubkey_match(EVP_PKEY * pub,struct wpabuf * r_hash)5482 static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
5483 {
5484 	struct wpabuf *uncomp;
5485 	int res;
5486 	u8 hash[SHA256_MAC_LEN];
5487 	const u8 *addr[1];
5488 	size_t len[1];
5489 
5490 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
5491 		return -1;
5492 	uncomp = dpp_get_pubkey_point(pub, 1);
5493 	if (!uncomp)
5494 		return -1;
5495 	addr[0] = wpabuf_head(uncomp);
5496 	len[0] = wpabuf_len(uncomp);
5497 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
5498 		    addr[0], len[0]);
5499 	res = sha256_vector(1, addr, len, hash);
5500 	wpabuf_free(uncomp);
5501 	if (res < 0)
5502 		return -1;
5503 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
5504 		wpa_printf(MSG_DEBUG,
5505 			   "DPP: Received hash value does not match calculated public key hash value");
5506 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
5507 			    hash, SHA256_MAC_LEN);
5508 		return -1;
5509 	}
5510 	return 0;
5511 }
5512 
5513 
dpp_copy_csign(struct dpp_authentication * auth,EVP_PKEY * csign)5514 static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign)
5515 {
5516 	unsigned char *der = NULL;
5517 	int der_len;
5518 
5519 	der_len = i2d_PUBKEY(csign, &der);
5520 	if (der_len <= 0)
5521 		return;
5522 	wpabuf_free(auth->c_sign_key);
5523 	auth->c_sign_key = wpabuf_alloc_copy(der, der_len);
5524 	OPENSSL_free(der);
5525 }
5526 
5527 
dpp_copy_netaccesskey(struct dpp_authentication * auth)5528 static void dpp_copy_netaccesskey(struct dpp_authentication *auth)
5529 {
5530 	unsigned char *der = NULL;
5531 	int der_len;
5532 	EC_KEY *eckey;
5533 
5534 	eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
5535 	if (!eckey)
5536 		return;
5537 
5538 	der_len = i2d_ECPrivateKey(eckey, &der);
5539 	if (der_len <= 0) {
5540 		EC_KEY_free(eckey);
5541 		return;
5542 	}
5543 	wpabuf_free(auth->net_access_key);
5544 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
5545 	OPENSSL_free(der);
5546 	EC_KEY_free(eckey);
5547 }
5548 
5549 
5550 struct dpp_signed_connector_info {
5551 	unsigned char *payload;
5552 	size_t payload_len;
5553 };
5554 
5555 static enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,EVP_PKEY * csign_pub,const char * connector)5556 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
5557 			     EVP_PKEY *csign_pub, const char *connector)
5558 {
5559 	enum dpp_status_error ret = 255;
5560 	const char *pos, *end, *signed_start, *signed_end;
5561 	struct wpabuf *kid = NULL;
5562 	unsigned char *prot_hdr = NULL, *signature = NULL;
5563 	size_t prot_hdr_len = 0, signature_len = 0;
5564 	const EVP_MD *sign_md = NULL;
5565 	unsigned char *der = NULL;
5566 	int der_len;
5567 	int res;
5568 	EVP_MD_CTX *md_ctx = NULL;
5569 	ECDSA_SIG *sig = NULL;
5570 	BIGNUM *r = NULL, *s = NULL;
5571 	const struct dpp_curve_params *curve;
5572 	EC_KEY *eckey;
5573 	const EC_GROUP *group;
5574 	int nid;
5575 
5576 	eckey = EVP_PKEY_get1_EC_KEY(csign_pub);
5577 	if (!eckey)
5578 		goto fail;
5579 	group = EC_KEY_get0_group(eckey);
5580 	if (!group)
5581 		goto fail;
5582 	nid = EC_GROUP_get_curve_name(group);
5583 	curve = dpp_get_curve_nid(nid);
5584 	if (!curve)
5585 		goto fail;
5586 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
5587 	os_memset(info, 0, sizeof(*info));
5588 
5589 	signed_start = pos = connector;
5590 	end = os_strchr(pos, '.');
5591 	if (!end) {
5592 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
5593 		ret = DPP_STATUS_INVALID_CONNECTOR;
5594 		goto fail;
5595 	}
5596 	prot_hdr = base64_url_decode((const unsigned char *) pos,
5597 				     end - pos, &prot_hdr_len);
5598 	if (!prot_hdr) {
5599 		wpa_printf(MSG_DEBUG,
5600 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
5601 		ret = DPP_STATUS_INVALID_CONNECTOR;
5602 		goto fail;
5603 	}
5604 	wpa_hexdump_ascii(MSG_DEBUG,
5605 			  "DPP: signedConnector - JWS Protected Header",
5606 			  prot_hdr, prot_hdr_len);
5607 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
5608 	if (!kid) {
5609 		ret = DPP_STATUS_INVALID_CONNECTOR;
5610 		goto fail;
5611 	}
5612 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
5613 		wpa_printf(MSG_DEBUG,
5614 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
5615 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
5616 		ret = DPP_STATUS_INVALID_CONNECTOR;
5617 		goto fail;
5618 	}
5619 
5620 	pos = end + 1;
5621 	end = os_strchr(pos, '.');
5622 	if (!end) {
5623 		wpa_printf(MSG_DEBUG,
5624 			   "DPP: Missing dot(2) in signedConnector");
5625 		ret = DPP_STATUS_INVALID_CONNECTOR;
5626 		goto fail;
5627 	}
5628 	signed_end = end - 1;
5629 	info->payload = base64_url_decode((const unsigned char *) pos,
5630 					  end - pos, &info->payload_len);
5631 	if (!info->payload) {
5632 		wpa_printf(MSG_DEBUG,
5633 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
5634 		ret = DPP_STATUS_INVALID_CONNECTOR;
5635 		goto fail;
5636 	}
5637 	wpa_hexdump_ascii(MSG_DEBUG,
5638 			  "DPP: signedConnector - JWS Payload",
5639 			  info->payload, info->payload_len);
5640 	pos = end + 1;
5641 	signature = base64_url_decode((const unsigned char *) pos,
5642 				      os_strlen(pos), &signature_len);
5643 	if (!signature) {
5644 		wpa_printf(MSG_DEBUG,
5645 			   "DPP: Failed to base64url decode signedConnector signature");
5646 		ret = DPP_STATUS_INVALID_CONNECTOR;
5647 		goto fail;
5648 		}
5649 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
5650 		    signature, signature_len);
5651 
5652 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
5653 		ret = DPP_STATUS_NO_MATCH;
5654 		goto fail;
5655 	}
5656 
5657 	if (signature_len & 0x01) {
5658 		wpa_printf(MSG_DEBUG,
5659 			   "DPP: Unexpected signedConnector signature length (%d)",
5660 			   (int) signature_len);
5661 		ret = DPP_STATUS_INVALID_CONNECTOR;
5662 		goto fail;
5663 	}
5664 
5665 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
5666 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
5667 	r = BN_bin2bn(signature, signature_len / 2, NULL);
5668 	s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
5669 	sig = ECDSA_SIG_new();
5670 	if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
5671 		goto fail;
5672 	r = NULL;
5673 	s = NULL;
5674 
5675 	der_len = i2d_ECDSA_SIG(sig, &der);
5676 	if (der_len <= 0) {
5677 		wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
5678 		goto fail;
5679 	}
5680 	wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
5681 	md_ctx = EVP_MD_CTX_create();
5682 	if (!md_ctx)
5683 		goto fail;
5684 
5685 	ERR_clear_error();
5686 	if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
5687 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
5688 			   ERR_error_string(ERR_get_error(), NULL));
5689 		goto fail;
5690 	}
5691 	if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
5692 				   signed_end - signed_start + 1) != 1) {
5693 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
5694 			   ERR_error_string(ERR_get_error(), NULL));
5695 		goto fail;
5696 	}
5697 	res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
5698 	if (res != 1) {
5699 		wpa_printf(MSG_DEBUG,
5700 			   "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
5701 			   res, ERR_error_string(ERR_get_error(), NULL));
5702 		ret = DPP_STATUS_INVALID_CONNECTOR;
5703 		goto fail;
5704 	}
5705 
5706 	ret = DPP_STATUS_OK;
5707 fail:
5708 	EC_KEY_free(eckey);
5709 	EVP_MD_CTX_destroy(md_ctx);
5710 	os_free(prot_hdr);
5711 	wpabuf_free(kid);
5712 	os_free(signature);
5713 	ECDSA_SIG_free(sig);
5714 	BN_free(r);
5715 	BN_free(s);
5716 	OPENSSL_free(der);
5717 	return ret;
5718 }
5719 
5720 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct json_token * cred)5721 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
5722 			      struct json_token *cred)
5723 {
5724 	struct dpp_signed_connector_info info;
5725 	struct json_token *token, *csign;
5726 	int ret = -1;
5727 	EVP_PKEY *csign_pub = NULL;
5728 	const struct dpp_curve_params *key_curve = NULL;
5729 	const char *signed_connector;
5730 
5731 	os_memset(&info, 0, sizeof(info));
5732 
5733 	if (dpp_akm_psk(auth->akm) || dpp_akm_sae(auth->akm)) {
5734 		wpa_printf(MSG_DEBUG,
5735 			   "DPP: Legacy credential included in Connector credential");
5736 		if (dpp_parse_cred_legacy(auth, cred) < 0)
5737 			return -1;
5738 	}
5739 
5740 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
5741 
5742 	csign = json_get_member(cred, "csign");
5743 	if (!csign || csign->type != JSON_OBJECT) {
5744 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
5745 		goto fail;
5746 	}
5747 
5748 	csign_pub = dpp_parse_jwk(csign, &key_curve);
5749 	if (!csign_pub) {
5750 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
5751 		goto fail;
5752 	}
5753 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
5754 
5755 	token = json_get_member(cred, "signedConnector");
5756 	if (!token || token->type != JSON_STRING) {
5757 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
5758 		goto fail;
5759 	}
5760 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
5761 			  token->string, os_strlen(token->string));
5762 	signed_connector = token->string;
5763 
5764 	if (os_strchr(signed_connector, '"') ||
5765 	    os_strchr(signed_connector, '\n')) {
5766 		wpa_printf(MSG_DEBUG,
5767 			   "DPP: Unexpected character in signedConnector");
5768 		goto fail;
5769 	}
5770 
5771 	if (dpp_process_signed_connector(&info, csign_pub,
5772 					 signed_connector) != DPP_STATUS_OK)
5773 		goto fail;
5774 
5775 	if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
5776 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
5777 		goto fail;
5778 	}
5779 
5780 	os_free(auth->connector);
5781 	auth->connector = os_strdup(signed_connector);
5782 
5783 	dpp_copy_csign(auth, csign_pub);
5784 	dpp_copy_netaccesskey(auth);
5785 
5786 	ret = 0;
5787 fail:
5788 	EVP_PKEY_free(csign_pub);
5789 	os_free(info.payload);
5790 	return ret;
5791 }
5792 
5793 
dpp_akm_str(enum dpp_akm akm)5794 const char * dpp_akm_str(enum dpp_akm akm)
5795 {
5796 	switch (akm) {
5797 	case DPP_AKM_DPP:
5798 		return "dpp";
5799 	case DPP_AKM_PSK:
5800 		return "psk";
5801 	case DPP_AKM_SAE:
5802 		return "sae";
5803 	case DPP_AKM_PSK_SAE:
5804 		return "psk+sae";
5805 	case DPP_AKM_SAE_DPP:
5806 		return "dpp+sae";
5807 	case DPP_AKM_PSK_SAE_DPP:
5808 		return "dpp+psk+sae";
5809 	default:
5810 		return "??";
5811 	}
5812 }
5813 
5814 
dpp_akm_from_str(const char * akm)5815 static enum dpp_akm dpp_akm_from_str(const char *akm)
5816 {
5817 	if (os_strcmp(akm, "psk") == 0)
5818 		return DPP_AKM_PSK;
5819 	if (os_strcmp(akm, "sae") == 0)
5820 		return DPP_AKM_SAE;
5821 	if (os_strcmp(akm, "psk+sae") == 0)
5822 		return DPP_AKM_PSK_SAE;
5823 	if (os_strcmp(akm, "dpp") == 0)
5824 		return DPP_AKM_DPP;
5825 	if (os_strcmp(akm, "dpp+sae") == 0)
5826 		return DPP_AKM_SAE_DPP;
5827 	if (os_strcmp(akm, "dpp+psk+sae") == 0)
5828 		return DPP_AKM_PSK_SAE_DPP;
5829 	return DPP_AKM_UNKNOWN;
5830 }
5831 
5832 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)5833 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
5834 			      const u8 *conf_obj, u16 conf_obj_len)
5835 {
5836 	int ret = -1;
5837 	struct json_token *root, *token, *discovery, *cred;
5838 
5839 	root = json_parse((const char *) conf_obj, conf_obj_len);
5840 	if (!root)
5841 		return -1;
5842 	if (root->type != JSON_OBJECT) {
5843 		dpp_auth_fail(auth, "JSON root is not an object");
5844 		goto fail;
5845 	}
5846 
5847 	token = json_get_member(root, "wi-fi_tech");
5848 	if (!token || token->type != JSON_STRING) {
5849 		dpp_auth_fail(auth, "No wi-fi_tech string value found");
5850 		goto fail;
5851 	}
5852 	if (os_strcmp(token->string, "infra") != 0) {
5853 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
5854 			   token->string);
5855 		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
5856 		goto fail;
5857 	}
5858 
5859 	discovery = json_get_member(root, "discovery");
5860 	if (!discovery || discovery->type != JSON_OBJECT) {
5861 		dpp_auth_fail(auth, "No discovery object in JSON");
5862 		goto fail;
5863 	}
5864 
5865 	token = json_get_member(discovery, "ssid");
5866 	if (!token || token->type != JSON_STRING) {
5867 		dpp_auth_fail(auth, "No discovery::ssid string value found");
5868 		goto fail;
5869 	}
5870 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
5871 			  token->string, os_strlen(token->string));
5872 	if (os_strlen(token->string) > SSID_MAX_LEN) {
5873 		dpp_auth_fail(auth, "Too long discovery::ssid string value");
5874 		goto fail;
5875 	}
5876 	auth->ssid_len = os_strlen(token->string);
5877 	os_memcpy(auth->ssid, token->string, auth->ssid_len);
5878 
5879 	cred = json_get_member(root, "cred");
5880 	if (!cred || cred->type != JSON_OBJECT) {
5881 		dpp_auth_fail(auth, "No cred object in JSON");
5882 		goto fail;
5883 	}
5884 
5885 	token = json_get_member(cred, "akm");
5886 	if (!token || token->type != JSON_STRING) {
5887 		dpp_auth_fail(auth, "No cred::akm string value found");
5888 		goto fail;
5889 	}
5890 	auth->akm = dpp_akm_from_str(token->string);
5891 
5892 	if (dpp_akm_legacy(auth->akm)) {
5893 		if (dpp_parse_cred_legacy(auth, cred) < 0)
5894 			goto fail;
5895 	} else if (dpp_akm_dpp(auth->akm)) {
5896 		if (dpp_parse_cred_dpp(auth, cred) < 0)
5897 			goto fail;
5898 	} else {
5899 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
5900 			   token->string);
5901 		dpp_auth_fail(auth, "Unsupported akm");
5902 		goto fail;
5903 	}
5904 
5905 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
5906 	ret = 0;
5907 fail:
5908 	json_free(root);
5909 	return ret;
5910 }
5911 
5912 
dpp_conf_resp_rx(struct dpp_authentication * auth,const struct wpabuf * resp)5913 int dpp_conf_resp_rx(struct dpp_authentication *auth,
5914 		     const struct wpabuf *resp)
5915 {
5916 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
5917 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
5918 	const u8 *addr[1];
5919 	size_t len[1];
5920 	u8 *unwrapped = NULL;
5921 	size_t unwrapped_len = 0;
5922 	int ret = -1;
5923 
5924 	auth->conf_resp_status = 255;
5925 
5926 	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
5927 		dpp_auth_fail(auth, "Invalid attribute in config response");
5928 		return -1;
5929 	}
5930 
5931 	wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
5932 				    DPP_ATTR_WRAPPED_DATA,
5933 				    &wrapped_data_len);
5934 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5935 		dpp_auth_fail(auth,
5936 			      "Missing or invalid required Wrapped Data attribute");
5937 		return -1;
5938 	}
5939 
5940 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5941 		    wrapped_data, wrapped_data_len);
5942 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5943 	unwrapped = os_malloc(unwrapped_len);
5944 	if (!unwrapped)
5945 		return -1;
5946 
5947 	addr[0] = wpabuf_head(resp);
5948 	len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
5949 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
5950 
5951 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
5952 			    wrapped_data, wrapped_data_len,
5953 			    1, addr, len, unwrapped) < 0) {
5954 		dpp_auth_fail(auth, "AES-SIV decryption failed");
5955 		goto fail;
5956 	}
5957 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5958 		    unwrapped, unwrapped_len);
5959 
5960 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5961 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
5962 		goto fail;
5963 	}
5964 
5965 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
5966 			       DPP_ATTR_ENROLLEE_NONCE,
5967 			       &e_nonce_len);
5968 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
5969 		dpp_auth_fail(auth,
5970 			      "Missing or invalid Enrollee Nonce attribute");
5971 		goto fail;
5972 	}
5973 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
5974 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
5975 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
5976 		goto fail;
5977 	}
5978 
5979 	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
5980 			      DPP_ATTR_STATUS, &status_len);
5981 	if (!status || status_len < 1) {
5982 		dpp_auth_fail(auth,
5983 			      "Missing or invalid required DPP Status attribute");
5984 		goto fail;
5985 	}
5986 	auth->conf_resp_status = status[0];
5987 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
5988 	if (status[0] != DPP_STATUS_OK) {
5989 		dpp_auth_fail(auth, "Configurator rejected configuration");
5990 		goto fail;
5991 	}
5992 
5993 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len,
5994 				DPP_ATTR_CONFIG_OBJ, &conf_obj_len);
5995 	if (!conf_obj) {
5996 		dpp_auth_fail(auth,
5997 			      "Missing required Configuration Object attribute");
5998 		goto fail;
5999 	}
6000 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
6001 			  conf_obj, conf_obj_len);
6002 	if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
6003 		goto fail;
6004 
6005 	ret = 0;
6006 
6007 fail:
6008 	os_free(unwrapped);
6009 	return ret;
6010 }
6011 
6012 
6013 #ifdef CONFIG_DPP2
dpp_conf_result_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)6014 enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
6015 					 const u8 *hdr,
6016 					 const u8 *attr_start, size_t attr_len)
6017 {
6018 	const u8 *wrapped_data, *status, *e_nonce;
6019 	u16 wrapped_data_len, status_len, e_nonce_len;
6020 	const u8 *addr[2];
6021 	size_t len[2];
6022 	u8 *unwrapped = NULL;
6023 	size_t unwrapped_len = 0;
6024 	enum dpp_status_error ret = 256;
6025 
6026 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
6027 				    &wrapped_data_len);
6028 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
6029 		dpp_auth_fail(auth,
6030 			      "Missing or invalid required Wrapped Data attribute");
6031 		goto fail;
6032 	}
6033 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
6034 		    wrapped_data, wrapped_data_len);
6035 
6036 	attr_len = wrapped_data - 4 - attr_start;
6037 
6038 	addr[0] = hdr;
6039 	len[0] = DPP_HDR_LEN;
6040 	addr[1] = attr_start;
6041 	len[1] = attr_len;
6042 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
6043 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
6044 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
6045 		    wrapped_data, wrapped_data_len);
6046 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
6047 	unwrapped = os_malloc(unwrapped_len);
6048 	if (!unwrapped)
6049 		goto fail;
6050 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
6051 			    wrapped_data, wrapped_data_len,
6052 			    2, addr, len, unwrapped) < 0) {
6053 		dpp_auth_fail(auth, "AES-SIV decryption failed");
6054 		goto fail;
6055 	}
6056 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
6057 		    unwrapped, unwrapped_len);
6058 
6059 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
6060 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
6061 		goto fail;
6062 	}
6063 
6064 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
6065 			       DPP_ATTR_ENROLLEE_NONCE,
6066 			       &e_nonce_len);
6067 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
6068 		dpp_auth_fail(auth,
6069 			      "Missing or invalid Enrollee Nonce attribute");
6070 		goto fail;
6071 	}
6072 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
6073 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
6074 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
6075 		wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
6076 			    auth->e_nonce, e_nonce_len);
6077 		goto fail;
6078 	}
6079 
6080 	status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS,
6081 			      &status_len);
6082 	if (!status || status_len < 1) {
6083 		dpp_auth_fail(auth,
6084 			      "Missing or invalid required DPP Status attribute");
6085 		goto fail;
6086 	}
6087 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
6088 	ret = status[0];
6089 
6090 fail:
6091 	bin_clear_free(unwrapped, unwrapped_len);
6092 	return ret;
6093 }
6094 #endif /* CONFIG_DPP2 */
6095 
6096 
dpp_build_conf_result(struct dpp_authentication * auth,enum dpp_status_error status)6097 struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
6098 				      enum dpp_status_error status)
6099 {
6100 	struct wpabuf *msg, *clear;
6101 	size_t nonce_len, clear_len, attr_len;
6102 	const u8 *addr[2];
6103 	size_t len[2];
6104 	u8 *wrapped;
6105 
6106 	nonce_len = auth->curve->nonce_len;
6107 	clear_len = 5 + 4 + nonce_len;
6108 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
6109 	clear = wpabuf_alloc(clear_len);
6110 	msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len);
6111 	if (!clear || !msg)
6112 		return NULL;
6113 
6114 	/* DPP Status */
6115 	dpp_build_attr_status(clear, status);
6116 
6117 	/* E-nonce */
6118 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
6119 	wpabuf_put_le16(clear, nonce_len);
6120 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
6121 
6122 	/* OUI, OUI type, Crypto Suite, DPP frame type */
6123 	addr[0] = wpabuf_head_u8(msg) + 2;
6124 	len[0] = 3 + 1 + 1 + 1;
6125 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
6126 
6127 	/* Attributes before Wrapped Data (none) */
6128 	addr[1] = wpabuf_put(msg, 0);
6129 	len[1] = 0;
6130 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
6131 
6132 	/* Wrapped Data */
6133 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
6134 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
6135 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
6136 
6137 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
6138 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
6139 			    wpabuf_head(clear), wpabuf_len(clear),
6140 			    2, addr, len, wrapped) < 0)
6141 		goto fail;
6142 
6143 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg);
6144 	wpabuf_free(clear);
6145 	return msg;
6146 fail:
6147 	wpabuf_free(clear);
6148 	wpabuf_free(msg);
6149 	return NULL;
6150 }
6151 
6152 
dpp_configurator_free(struct dpp_configurator * conf)6153 void dpp_configurator_free(struct dpp_configurator *conf)
6154 {
6155 	if (!conf)
6156 		return;
6157 	EVP_PKEY_free(conf->csign);
6158 	os_free(conf->kid);
6159 	os_free(conf);
6160 }
6161 
6162 
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)6163 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
6164 			     size_t buflen)
6165 {
6166 	EC_KEY *eckey;
6167 	int key_len, ret = -1;
6168 	unsigned char *key = NULL;
6169 
6170 	if (!conf->csign)
6171 		return -1;
6172 
6173 	eckey = EVP_PKEY_get1_EC_KEY(conf->csign);
6174 	if (!eckey)
6175 		return -1;
6176 
6177 	key_len = i2d_ECPrivateKey(eckey, &key);
6178 	if (key_len > 0)
6179 		ret = wpa_snprintf_hex(buf, buflen, key, key_len);
6180 
6181 	EC_KEY_free(eckey);
6182 	OPENSSL_free(key);
6183 	return ret;
6184 }
6185 
6186 
6187 struct dpp_configurator *
dpp_keygen_configurator(const char * curve,const u8 * privkey,size_t privkey_len)6188 dpp_keygen_configurator(const char *curve, const u8 *privkey,
6189 			size_t privkey_len)
6190 {
6191 	struct dpp_configurator *conf;
6192 	struct wpabuf *csign_pub = NULL;
6193 	u8 kid_hash[SHA256_MAC_LEN];
6194 	const u8 *addr[1];
6195 	size_t len[1];
6196 
6197 	conf = os_zalloc(sizeof(*conf));
6198 	if (!conf)
6199 		return NULL;
6200 
6201 	if (!curve) {
6202 		conf->curve = &dpp_curves[0];
6203 	} else {
6204 		conf->curve = dpp_get_curve_name(curve);
6205 		if (!conf->curve) {
6206 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
6207 				   curve);
6208 			os_free(conf);
6209 			return NULL;
6210 		}
6211 	}
6212 	if (privkey)
6213 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
6214 					      privkey_len);
6215 	else
6216 		conf->csign = dpp_gen_keypair(conf->curve);
6217 	if (!conf->csign)
6218 		goto fail;
6219 	conf->own = 1;
6220 
6221 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
6222 	if (!csign_pub) {
6223 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
6224 		goto fail;
6225 	}
6226 
6227 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
6228 	addr[0] = wpabuf_head(csign_pub);
6229 	len[0] = wpabuf_len(csign_pub);
6230 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
6231 		wpa_printf(MSG_DEBUG,
6232 			   "DPP: Failed to derive kid for C-sign-key");
6233 		goto fail;
6234 	}
6235 
6236 	conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
6237 					       NULL, 0);
6238 	if (!conf->kid)
6239 		goto fail;
6240 out:
6241 	wpabuf_free(csign_pub);
6242 	return conf;
6243 fail:
6244 	dpp_configurator_free(conf);
6245 	conf = NULL;
6246 	goto out;
6247 }
6248 
6249 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)6250 int dpp_configurator_own_config(struct dpp_authentication *auth,
6251 				const char *curve, int ap)
6252 {
6253 	struct wpabuf *conf_obj;
6254 	int ret = -1;
6255 
6256 	if (!auth->conf) {
6257 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
6258 		return -1;
6259 	}
6260 
6261 	if (!curve) {
6262 		auth->curve = &dpp_curves[0];
6263 	} else {
6264 		auth->curve = dpp_get_curve_name(curve);
6265 		if (!auth->curve) {
6266 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
6267 				   curve);
6268 			return -1;
6269 		}
6270 	}
6271 	wpa_printf(MSG_DEBUG,
6272 		   "DPP: Building own configuration/connector with curve %s",
6273 		   auth->curve->name);
6274 
6275 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
6276 	if (!auth->own_protocol_key)
6277 		return -1;
6278 	dpp_copy_netaccesskey(auth);
6279 	auth->peer_protocol_key = auth->own_protocol_key;
6280 	dpp_copy_csign(auth, auth->conf->csign);
6281 
6282 	conf_obj = dpp_build_conf_obj(auth, ap);
6283 	if (!conf_obj)
6284 		goto fail;
6285 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
6286 				 wpabuf_len(conf_obj));
6287 fail:
6288 	wpabuf_free(conf_obj);
6289 	auth->peer_protocol_key = NULL;
6290 	return ret;
6291 }
6292 
6293 
dpp_compatible_netrole(const char * role1,const char * role2)6294 static int dpp_compatible_netrole(const char *role1, const char *role2)
6295 {
6296 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
6297 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
6298 }
6299 
6300 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role)6301 static int dpp_connector_compatible_group(struct json_token *root,
6302 					  const char *group_id,
6303 					  const char *net_role)
6304 {
6305 	struct json_token *groups, *token;
6306 
6307 	groups = json_get_member(root, "groups");
6308 	if (!groups || groups->type != JSON_ARRAY)
6309 		return 0;
6310 
6311 	for (token = groups->child; token; token = token->sibling) {
6312 		struct json_token *id, *role;
6313 
6314 		id = json_get_member(token, "groupId");
6315 		if (!id || id->type != JSON_STRING)
6316 			continue;
6317 
6318 		role = json_get_member(token, "netRole");
6319 		if (!role || role->type != JSON_STRING)
6320 			continue;
6321 
6322 		if (os_strcmp(id->string, "*") != 0 &&
6323 		    os_strcmp(group_id, "*") != 0 &&
6324 		    os_strcmp(id->string, group_id) != 0)
6325 			continue;
6326 
6327 		if (dpp_compatible_netrole(role->string, net_role))
6328 			return 1;
6329 	}
6330 
6331 	return 0;
6332 }
6333 
6334 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root)6335 static int dpp_connector_match_groups(struct json_token *own_root,
6336 				      struct json_token *peer_root)
6337 {
6338 	struct json_token *groups, *token;
6339 
6340 	groups = json_get_member(peer_root, "groups");
6341 	if (!groups || groups->type != JSON_ARRAY) {
6342 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
6343 		return 0;
6344 	}
6345 
6346 	for (token = groups->child; token; token = token->sibling) {
6347 		struct json_token *id, *role;
6348 
6349 		id = json_get_member(token, "groupId");
6350 		if (!id || id->type != JSON_STRING) {
6351 			wpa_printf(MSG_DEBUG,
6352 				   "DPP: Missing peer groupId string");
6353 			continue;
6354 		}
6355 
6356 		role = json_get_member(token, "netRole");
6357 		if (!role || role->type != JSON_STRING) {
6358 			wpa_printf(MSG_DEBUG,
6359 				   "DPP: Missing peer groups::netRole string");
6360 			continue;
6361 		}
6362 		wpa_printf(MSG_DEBUG,
6363 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
6364 			   id->string, role->string);
6365 		if (dpp_connector_compatible_group(own_root, id->string,
6366 						   role->string)) {
6367 			wpa_printf(MSG_DEBUG,
6368 				   "DPP: Compatible group/netRole in own connector");
6369 			return 1;
6370 		}
6371 	}
6372 
6373 	return 0;
6374 }
6375 
6376 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)6377 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
6378 			  unsigned int hash_len)
6379 {
6380 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
6381 	const char *info = "DPP PMK";
6382 	int res;
6383 
6384 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
6385 
6386 	/* HKDF-Extract(<>, N.x) */
6387 	os_memset(salt, 0, hash_len);
6388 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
6389 		return -1;
6390 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
6391 			prk, hash_len);
6392 
6393 	/* HKDF-Expand(PRK, info, L) */
6394 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
6395 	os_memset(prk, 0, hash_len);
6396 	if (res < 0)
6397 		return -1;
6398 
6399 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
6400 			pmk, hash_len);
6401 	return 0;
6402 }
6403 
6404 
dpp_derive_pmkid(const struct dpp_curve_params * curve,EVP_PKEY * own_key,EVP_PKEY * peer_key,u8 * pmkid)6405 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
6406 			    EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
6407 {
6408 	struct wpabuf *nkx, *pkx;
6409 	int ret = -1, res;
6410 	const u8 *addr[2];
6411 	size_t len[2];
6412 	u8 hash[SHA256_MAC_LEN];
6413 
6414 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
6415 	nkx = dpp_get_pubkey_point(own_key, 0);
6416 	pkx = dpp_get_pubkey_point(peer_key, 0);
6417 	if (!nkx || !pkx)
6418 		goto fail;
6419 	addr[0] = wpabuf_head(nkx);
6420 	len[0] = wpabuf_len(nkx) / 2;
6421 	addr[1] = wpabuf_head(pkx);
6422 	len[1] = wpabuf_len(pkx) / 2;
6423 	if (len[0] != len[1])
6424 		goto fail;
6425 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
6426 		addr[0] = wpabuf_head(pkx);
6427 		addr[1] = wpabuf_head(nkx);
6428 	}
6429 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
6430 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
6431 	res = sha256_vector(2, addr, len, hash);
6432 	if (res < 0)
6433 		goto fail;
6434 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
6435 	os_memcpy(pmkid, hash, PMKID_LEN);
6436 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
6437 	ret = 0;
6438 fail:
6439 	wpabuf_free(nkx);
6440 	wpabuf_free(pkx);
6441 	return ret;
6442 }
6443 
6444 
6445 enum dpp_status_error
dpp_peer_intro(struct dpp_introduction * intro,const char * own_connector,const u8 * net_access_key,size_t net_access_key_len,const u8 * csign_key,size_t csign_key_len,const u8 * peer_connector,size_t peer_connector_len,os_time_t * expiry)6446 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
6447 	       const u8 *net_access_key, size_t net_access_key_len,
6448 	       const u8 *csign_key, size_t csign_key_len,
6449 	       const u8 *peer_connector, size_t peer_connector_len,
6450 	       os_time_t *expiry)
6451 {
6452 	struct json_token *root = NULL, *netkey, *token;
6453 	struct json_token *own_root = NULL;
6454 	enum dpp_status_error ret = 255, res;
6455 	EVP_PKEY *own_key = NULL, *peer_key = NULL;
6456 	struct wpabuf *own_key_pub = NULL;
6457 	const struct dpp_curve_params *curve, *own_curve;
6458 	struct dpp_signed_connector_info info;
6459 	const unsigned char *p;
6460 	EVP_PKEY *csign = NULL;
6461 	char *signed_connector = NULL;
6462 	const char *pos, *end;
6463 	unsigned char *own_conn = NULL;
6464 	size_t own_conn_len;
6465 	size_t Nx_len;
6466 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
6467 
6468 	os_memset(intro, 0, sizeof(*intro));
6469 	os_memset(&info, 0, sizeof(info));
6470 	if (expiry)
6471 		*expiry = 0;
6472 
6473 	p = csign_key;
6474 	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
6475 	if (!csign) {
6476 		wpa_printf(MSG_ERROR,
6477 			   "DPP: Failed to parse local C-sign-key information");
6478 		goto fail;
6479 	}
6480 
6481 	own_key = dpp_set_keypair(&own_curve, net_access_key,
6482 				  net_access_key_len);
6483 	if (!own_key) {
6484 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
6485 		goto fail;
6486 	}
6487 
6488 	pos = os_strchr(own_connector, '.');
6489 	if (!pos) {
6490 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
6491 		goto fail;
6492 	}
6493 	pos++;
6494 	end = os_strchr(pos, '.');
6495 	if (!end) {
6496 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
6497 		goto fail;
6498 	}
6499 	own_conn = base64_url_decode((const unsigned char *) pos,
6500 				     end - pos, &own_conn_len);
6501 	if (!own_conn) {
6502 		wpa_printf(MSG_DEBUG,
6503 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
6504 		goto fail;
6505 	}
6506 
6507 	own_root = json_parse((const char *) own_conn, own_conn_len);
6508 	if (!own_root) {
6509 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
6510 		goto fail;
6511 	}
6512 
6513 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
6514 			  peer_connector, peer_connector_len);
6515 	signed_connector = os_malloc(peer_connector_len + 1);
6516 	if (!signed_connector)
6517 		goto fail;
6518 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
6519 	signed_connector[peer_connector_len] = '\0';
6520 
6521 	res = dpp_process_signed_connector(&info, csign, signed_connector);
6522 	if (res != DPP_STATUS_OK) {
6523 		ret = res;
6524 		goto fail;
6525 	}
6526 
6527 	root = json_parse((const char *) info.payload, info.payload_len);
6528 	if (!root) {
6529 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
6530 		ret = DPP_STATUS_INVALID_CONNECTOR;
6531 		goto fail;
6532 	}
6533 
6534 	if (!dpp_connector_match_groups(own_root, root)) {
6535 		wpa_printf(MSG_DEBUG,
6536 			   "DPP: Peer connector does not include compatible group netrole with own connector");
6537 		ret = DPP_STATUS_NO_MATCH;
6538 		goto fail;
6539 	}
6540 
6541 	token = json_get_member(root, "expiry");
6542 	if (!token || token->type != JSON_STRING) {
6543 		wpa_printf(MSG_DEBUG,
6544 			   "DPP: No expiry string found - connector does not expire");
6545 	} else {
6546 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
6547 		if (dpp_key_expired(token->string, expiry)) {
6548 			wpa_printf(MSG_DEBUG,
6549 				   "DPP: Connector (netAccessKey) has expired");
6550 			ret = DPP_STATUS_INVALID_CONNECTOR;
6551 			goto fail;
6552 		}
6553 	}
6554 
6555 	netkey = json_get_member(root, "netAccessKey");
6556 	if (!netkey || netkey->type != JSON_OBJECT) {
6557 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
6558 		ret = DPP_STATUS_INVALID_CONNECTOR;
6559 		goto fail;
6560 	}
6561 
6562 	peer_key = dpp_parse_jwk(netkey, &curve);
6563 	if (!peer_key) {
6564 		ret = DPP_STATUS_INVALID_CONNECTOR;
6565 		goto fail;
6566 	}
6567 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
6568 
6569 	if (own_curve != curve) {
6570 		wpa_printf(MSG_DEBUG,
6571 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
6572 			   own_curve->name, curve->name);
6573 		ret = DPP_STATUS_INVALID_CONNECTOR;
6574 		goto fail;
6575 	}
6576 
6577 	/* ECDH: N = nk * PK */
6578 	if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
6579 		goto fail;
6580 
6581 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
6582 			Nx, Nx_len);
6583 
6584 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
6585 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
6586 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
6587 		goto fail;
6588 	}
6589 	intro->pmk_len = curve->hash_len;
6590 
6591 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
6592 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
6593 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
6594 		goto fail;
6595 	}
6596 
6597 	ret = DPP_STATUS_OK;
6598 fail:
6599 	if (ret != DPP_STATUS_OK)
6600 		os_memset(intro, 0, sizeof(*intro));
6601 	os_memset(Nx, 0, sizeof(Nx));
6602 	os_free(own_conn);
6603 	os_free(signed_connector);
6604 	os_free(info.payload);
6605 	EVP_PKEY_free(own_key);
6606 	wpabuf_free(own_key_pub);
6607 	EVP_PKEY_free(peer_key);
6608 	EVP_PKEY_free(csign);
6609 	json_free(root);
6610 	json_free(own_root);
6611 	return ret;
6612 }
6613 
6614 
dpp_pkex_get_role_elem(const struct dpp_curve_params * curve,int init)6615 static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
6616 					 int init)
6617 {
6618 	EC_GROUP *group;
6619 	size_t len = curve->prime_len;
6620 	const u8 *x, *y;
6621 	EVP_PKEY *res;
6622 
6623 	switch (curve->ike_group) {
6624 	case 19:
6625 		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
6626 		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
6627 		break;
6628 	case 20:
6629 		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
6630 		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
6631 		break;
6632 	case 21:
6633 		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
6634 		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
6635 		break;
6636 	case 28:
6637 		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
6638 		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
6639 		break;
6640 	case 29:
6641 		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
6642 		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
6643 		break;
6644 	case 30:
6645 		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
6646 		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
6647 		break;
6648 	default:
6649 		return NULL;
6650 	}
6651 
6652 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
6653 	if (!group)
6654 		return NULL;
6655 	res = dpp_set_pubkey_point_group(group, x, y, len);
6656 	EC_GROUP_free(group);
6657 	return res;
6658 }
6659 
6660 
dpp_pkex_derive_Qi(const struct dpp_curve_params * curve,const u8 * mac_init,const char * code,const char * identifier,BN_CTX * bnctx,EC_GROUP ** ret_group)6661 static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
6662 				     const u8 *mac_init, const char *code,
6663 				     const char *identifier, BN_CTX *bnctx,
6664 				     EC_GROUP **ret_group)
6665 {
6666 	u8 hash[DPP_MAX_HASH_LEN];
6667 	const u8 *addr[3];
6668 	size_t len[3];
6669 	unsigned int num_elem = 0;
6670 	EC_POINT *Qi = NULL;
6671 	EVP_PKEY *Pi = NULL;
6672 	EC_KEY *Pi_ec = NULL;
6673 	const EC_POINT *Pi_point;
6674 	BIGNUM *hash_bn = NULL;
6675 	const EC_GROUP *group = NULL;
6676 	EC_GROUP *group2 = NULL;
6677 
6678 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
6679 
6680 	wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
6681 	addr[num_elem] = mac_init;
6682 	len[num_elem] = ETH_ALEN;
6683 	num_elem++;
6684 	if (identifier) {
6685 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
6686 			   identifier);
6687 		addr[num_elem] = (const u8 *) identifier;
6688 		len[num_elem] = os_strlen(identifier);
6689 		num_elem++;
6690 	}
6691 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
6692 	addr[num_elem] = (const u8 *) code;
6693 	len[num_elem] = os_strlen(code);
6694 	num_elem++;
6695 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
6696 		goto fail;
6697 	wpa_hexdump_key(MSG_DEBUG,
6698 			"DPP: H(MAC-Initiator | [identifier |] code)",
6699 			hash, curve->hash_len);
6700 	Pi = dpp_pkex_get_role_elem(curve, 1);
6701 	if (!Pi)
6702 		goto fail;
6703 	dpp_debug_print_key("DPP: Pi", Pi);
6704 	Pi_ec = EVP_PKEY_get1_EC_KEY(Pi);
6705 	if (!Pi_ec)
6706 		goto fail;
6707 	Pi_point = EC_KEY_get0_public_key(Pi_ec);
6708 
6709 	group = EC_KEY_get0_group(Pi_ec);
6710 	if (!group)
6711 		goto fail;
6712 	group2 = EC_GROUP_dup(group);
6713 	if (!group2)
6714 		goto fail;
6715 	Qi = EC_POINT_new(group2);
6716 	if (!Qi) {
6717 		EC_GROUP_free(group2);
6718 		goto fail;
6719 	}
6720 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
6721 	if (!hash_bn ||
6722 	    EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
6723 		goto fail;
6724 	if (EC_POINT_is_at_infinity(group, Qi)) {
6725 		wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
6726 		goto fail;
6727 	}
6728 	dpp_debug_print_point("DPP: Qi", group, Qi);
6729 out:
6730 	EC_KEY_free(Pi_ec);
6731 	EVP_PKEY_free(Pi);
6732 	BN_clear_free(hash_bn);
6733 	if (ret_group && Qi)
6734 		*ret_group = group2;
6735 	else
6736 		EC_GROUP_free(group2);
6737 	return Qi;
6738 fail:
6739 	EC_POINT_free(Qi);
6740 	Qi = NULL;
6741 	goto out;
6742 }
6743 
6744 
dpp_pkex_derive_Qr(const struct dpp_curve_params * curve,const u8 * mac_resp,const char * code,const char * identifier,BN_CTX * bnctx,EC_GROUP ** ret_group)6745 static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
6746 				     const u8 *mac_resp, const char *code,
6747 				     const char *identifier, BN_CTX *bnctx,
6748 				     EC_GROUP **ret_group)
6749 {
6750 	u8 hash[DPP_MAX_HASH_LEN];
6751 	const u8 *addr[3];
6752 	size_t len[3];
6753 	unsigned int num_elem = 0;
6754 	EC_POINT *Qr = NULL;
6755 	EVP_PKEY *Pr = NULL;
6756 	EC_KEY *Pr_ec = NULL;
6757 	const EC_POINT *Pr_point;
6758 	BIGNUM *hash_bn = NULL;
6759 	const EC_GROUP *group = NULL;
6760 	EC_GROUP *group2 = NULL;
6761 
6762 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
6763 
6764 	wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
6765 	addr[num_elem] = mac_resp;
6766 	len[num_elem] = ETH_ALEN;
6767 	num_elem++;
6768 	if (identifier) {
6769 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
6770 			   identifier);
6771 		addr[num_elem] = (const u8 *) identifier;
6772 		len[num_elem] = os_strlen(identifier);
6773 		num_elem++;
6774 	}
6775 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
6776 	addr[num_elem] = (const u8 *) code;
6777 	len[num_elem] = os_strlen(code);
6778 	num_elem++;
6779 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
6780 		goto fail;
6781 	wpa_hexdump_key(MSG_DEBUG,
6782 			"DPP: H(MAC-Responder | [identifier |] code)",
6783 			hash, curve->hash_len);
6784 	Pr = dpp_pkex_get_role_elem(curve, 0);
6785 	if (!Pr)
6786 		goto fail;
6787 	dpp_debug_print_key("DPP: Pr", Pr);
6788 	Pr_ec = EVP_PKEY_get1_EC_KEY(Pr);
6789 	if (!Pr_ec)
6790 		goto fail;
6791 	Pr_point = EC_KEY_get0_public_key(Pr_ec);
6792 
6793 	group = EC_KEY_get0_group(Pr_ec);
6794 	if (!group)
6795 		goto fail;
6796 	group2 = EC_GROUP_dup(group);
6797 	if (!group2)
6798 		goto fail;
6799 	Qr = EC_POINT_new(group2);
6800 	if (!Qr) {
6801 		EC_GROUP_free(group2);
6802 		goto fail;
6803 	}
6804 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
6805 	if (!hash_bn ||
6806 	    EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
6807 		goto fail;
6808 	if (EC_POINT_is_at_infinity(group, Qr)) {
6809 		wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
6810 		goto fail;
6811 	}
6812 	dpp_debug_print_point("DPP: Qr", group, Qr);
6813 out:
6814 	EC_KEY_free(Pr_ec);
6815 	EVP_PKEY_free(Pr);
6816 	BN_clear_free(hash_bn);
6817 	if (ret_group && Qr)
6818 		*ret_group = group2;
6819 	else
6820 		EC_GROUP_free(group2);
6821 	return Qr;
6822 fail:
6823 	EC_POINT_free(Qr);
6824 	Qr = NULL;
6825 	goto out;
6826 }
6827 
6828 
6829 #ifdef CONFIG_TESTING_OPTIONS
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)6830 static int dpp_test_gen_invalid_key(struct wpabuf *msg,
6831 				    const struct dpp_curve_params *curve)
6832 {
6833 	BN_CTX *ctx;
6834 	BIGNUM *x, *y;
6835 	int ret = -1;
6836 	EC_GROUP *group;
6837 	EC_POINT *point;
6838 
6839 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
6840 	if (!group)
6841 		return -1;
6842 
6843 	ctx = BN_CTX_new();
6844 	point = EC_POINT_new(group);
6845 	x = BN_new();
6846 	y = BN_new();
6847 	if (!ctx || !point || !x || !y)
6848 		goto fail;
6849 
6850 	if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1)
6851 		goto fail;
6852 
6853 	/* Generate a random y coordinate that results in a point that is not
6854 	 * on the curve. */
6855 	for (;;) {
6856 		if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1)
6857 			goto fail;
6858 
6859 		if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y,
6860 							ctx) != 1) {
6861 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6862 		/* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL
6863 		 * return an error from EC_POINT_set_affine_coordinates_GFp()
6864 		 * when the point is not on the curve. */
6865 			break;
6866 #else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */
6867 			goto fail;
6868 #endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */
6869 		}
6870 
6871 		if (!EC_POINT_is_on_curve(group, point, ctx))
6872 			break;
6873 	}
6874 
6875 	if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len),
6876 			   curve->prime_len) < 0 ||
6877 	    dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len),
6878 			   curve->prime_len) < 0)
6879 		goto fail;
6880 
6881 	ret = 0;
6882 fail:
6883 	if (ret < 0)
6884 		wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key");
6885 	BN_free(x);
6886 	BN_free(y);
6887 	EC_POINT_free(point);
6888 	BN_CTX_free(ctx);
6889 	EC_GROUP_free(group);
6890 
6891 	return ret;
6892 }
6893 #endif /* CONFIG_TESTING_OPTIONS */
6894 
6895 
dpp_pkex_build_exchange_req(struct dpp_pkex * pkex)6896 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
6897 {
6898 	EC_KEY *X_ec = NULL;
6899 	const EC_POINT *X_point;
6900 	BN_CTX *bnctx = NULL;
6901 	EC_GROUP *group = NULL;
6902 	EC_POINT *Qi = NULL, *M = NULL;
6903 	struct wpabuf *M_buf = NULL;
6904 	BIGNUM *Mx = NULL, *My = NULL;
6905 	struct wpabuf *msg = NULL;
6906 	size_t attr_len;
6907 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
6908 
6909 	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
6910 
6911 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
6912 	bnctx = BN_CTX_new();
6913 	if (!bnctx)
6914 		goto fail;
6915 	Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
6916 				pkex->identifier, bnctx, &group);
6917 	if (!Qi)
6918 		goto fail;
6919 
6920 	/* Generate a random ephemeral keypair x/X */
6921 #ifdef CONFIG_TESTING_OPTIONS
6922 	if (dpp_pkex_ephemeral_key_override_len) {
6923 		const struct dpp_curve_params *tmp_curve;
6924 
6925 		wpa_printf(MSG_INFO,
6926 			   "DPP: TESTING - override ephemeral key x/X");
6927 		pkex->x = dpp_set_keypair(&tmp_curve,
6928 					  dpp_pkex_ephemeral_key_override,
6929 					  dpp_pkex_ephemeral_key_override_len);
6930 	} else {
6931 		pkex->x = dpp_gen_keypair(curve);
6932 	}
6933 #else /* CONFIG_TESTING_OPTIONS */
6934 	pkex->x = dpp_gen_keypair(curve);
6935 #endif /* CONFIG_TESTING_OPTIONS */
6936 	if (!pkex->x)
6937 		goto fail;
6938 
6939 	/* M = X + Qi */
6940 	X_ec = EVP_PKEY_get1_EC_KEY(pkex->x);
6941 	if (!X_ec)
6942 		goto fail;
6943 	X_point = EC_KEY_get0_public_key(X_ec);
6944 	if (!X_point)
6945 		goto fail;
6946 	dpp_debug_print_point("DPP: X", group, X_point);
6947 	M = EC_POINT_new(group);
6948 	Mx = BN_new();
6949 	My = BN_new();
6950 	if (!M || !Mx || !My ||
6951 	    EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
6952 	    EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
6953 		goto fail;
6954 	dpp_debug_print_point("DPP: M", group, M);
6955 
6956 	/* Initiator -> Responder: group, [identifier,] M */
6957 	attr_len = 4 + 2;
6958 	if (pkex->identifier)
6959 		attr_len += 4 + os_strlen(pkex->identifier);
6960 	attr_len += 4 + 2 * curve->prime_len;
6961 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
6962 	if (!msg)
6963 		goto fail;
6964 
6965 #ifdef CONFIG_TESTING_OPTIONS
6966 	if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
6967 		wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
6968 		goto skip_finite_cyclic_group;
6969 	}
6970 #endif /* CONFIG_TESTING_OPTIONS */
6971 
6972 	/* Finite Cyclic Group attribute */
6973 	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
6974 	wpabuf_put_le16(msg, 2);
6975 	wpabuf_put_le16(msg, curve->ike_group);
6976 
6977 #ifdef CONFIG_TESTING_OPTIONS
6978 skip_finite_cyclic_group:
6979 #endif /* CONFIG_TESTING_OPTIONS */
6980 
6981 	/* Code Identifier attribute */
6982 	if (pkex->identifier) {
6983 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
6984 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
6985 		wpabuf_put_str(msg, pkex->identifier);
6986 	}
6987 
6988 #ifdef CONFIG_TESTING_OPTIONS
6989 	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
6990 		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
6991 		goto out;
6992 	}
6993 #endif /* CONFIG_TESTING_OPTIONS */
6994 
6995 	/* M in Encrypted Key attribute */
6996 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
6997 	wpabuf_put_le16(msg, 2 * curve->prime_len);
6998 
6999 #ifdef CONFIG_TESTING_OPTIONS
7000 	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
7001 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
7002 		if (dpp_test_gen_invalid_key(msg, curve) < 0)
7003 			goto fail;
7004 		goto out;
7005 	}
7006 #endif /* CONFIG_TESTING_OPTIONS */
7007 
7008 	if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len),
7009 			   curve->prime_len) < 0 ||
7010 	    dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 ||
7011 	    dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len),
7012 			   curve->prime_len) < 0)
7013 		goto fail;
7014 
7015 out:
7016 	wpabuf_free(M_buf);
7017 	EC_KEY_free(X_ec);
7018 	EC_POINT_free(M);
7019 	EC_POINT_free(Qi);
7020 	BN_clear_free(Mx);
7021 	BN_clear_free(My);
7022 	BN_CTX_free(bnctx);
7023 	EC_GROUP_free(group);
7024 	return msg;
7025 fail:
7026 	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
7027 	wpabuf_free(msg);
7028 	msg = NULL;
7029 	goto out;
7030 }
7031 
7032 
dpp_pkex_fail(struct dpp_pkex * pkex,const char * txt)7033 static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
7034 {
7035 	wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
7036 }
7037 
7038 
dpp_pkex_init(void * msg_ctx,struct dpp_bootstrap_info * bi,const u8 * own_mac,const char * identifier,const char * code)7039 struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
7040 				const u8 *own_mac,
7041 				const char *identifier,
7042 				const char *code)
7043 {
7044 	struct dpp_pkex *pkex;
7045 
7046 #ifdef CONFIG_TESTING_OPTIONS
7047 	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
7048 		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
7049 			   MAC2STR(dpp_pkex_own_mac_override));
7050 		own_mac = dpp_pkex_own_mac_override;
7051 	}
7052 #endif /* CONFIG_TESTING_OPTIONS */
7053 
7054 	pkex = os_zalloc(sizeof(*pkex));
7055 	if (!pkex)
7056 		return NULL;
7057 	pkex->msg_ctx = msg_ctx;
7058 	pkex->initiator = 1;
7059 	pkex->own_bi = bi;
7060 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
7061 	if (identifier) {
7062 		pkex->identifier = os_strdup(identifier);
7063 		if (!pkex->identifier)
7064 			goto fail;
7065 	}
7066 	pkex->code = os_strdup(code);
7067 	if (!pkex->code)
7068 		goto fail;
7069 	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
7070 	if (!pkex->exchange_req)
7071 		goto fail;
7072 	return pkex;
7073 fail:
7074 	dpp_pkex_free(pkex);
7075 	return NULL;
7076 }
7077 
7078 
7079 static struct wpabuf *
dpp_pkex_build_exchange_resp(struct dpp_pkex * pkex,enum dpp_status_error status,const BIGNUM * Nx,const BIGNUM * Ny)7080 dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
7081 			     enum dpp_status_error status,
7082 			     const BIGNUM *Nx, const BIGNUM *Ny)
7083 {
7084 	struct wpabuf *msg = NULL;
7085 	size_t attr_len;
7086 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
7087 
7088 	/* Initiator -> Responder: DPP Status, [identifier,] N */
7089 	attr_len = 4 + 1;
7090 	if (pkex->identifier)
7091 		attr_len += 4 + os_strlen(pkex->identifier);
7092 	attr_len += 4 + 2 * curve->prime_len;
7093 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
7094 	if (!msg)
7095 		goto fail;
7096 
7097 #ifdef CONFIG_TESTING_OPTIONS
7098 	if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) {
7099 		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
7100 		goto skip_status;
7101 	}
7102 
7103 	if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) {
7104 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
7105 		status = 255;
7106 	}
7107 #endif /* CONFIG_TESTING_OPTIONS */
7108 
7109 	/* DPP Status */
7110 	dpp_build_attr_status(msg, status);
7111 
7112 #ifdef CONFIG_TESTING_OPTIONS
7113 skip_status:
7114 #endif /* CONFIG_TESTING_OPTIONS */
7115 
7116 	/* Code Identifier attribute */
7117 	if (pkex->identifier) {
7118 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
7119 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
7120 		wpabuf_put_str(msg, pkex->identifier);
7121 	}
7122 
7123 	if (status != DPP_STATUS_OK)
7124 		goto skip_encrypted_key;
7125 
7126 #ifdef CONFIG_TESTING_OPTIONS
7127 	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
7128 		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
7129 		goto skip_encrypted_key;
7130 	}
7131 #endif /* CONFIG_TESTING_OPTIONS */
7132 
7133 	/* N in Encrypted Key attribute */
7134 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
7135 	wpabuf_put_le16(msg, 2 * curve->prime_len);
7136 
7137 #ifdef CONFIG_TESTING_OPTIONS
7138 	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
7139 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
7140 		if (dpp_test_gen_invalid_key(msg, curve) < 0)
7141 			goto fail;
7142 		goto skip_encrypted_key;
7143 	}
7144 #endif /* CONFIG_TESTING_OPTIONS */
7145 
7146 	if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len),
7147 			   curve->prime_len) < 0 ||
7148 	    dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 ||
7149 	    dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len),
7150 			   curve->prime_len) < 0)
7151 		goto fail;
7152 
7153 skip_encrypted_key:
7154 	if (status == DPP_STATUS_BAD_GROUP) {
7155 		/* Finite Cyclic Group attribute */
7156 		wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
7157 		wpabuf_put_le16(msg, 2);
7158 		wpabuf_put_le16(msg, curve->ike_group);
7159 	}
7160 
7161 	return msg;
7162 fail:
7163 	wpabuf_free(msg);
7164 	return NULL;
7165 }
7166 
7167 
dpp_pkex_derive_z(const u8 * mac_init,const u8 * mac_resp,const u8 * Mx,size_t Mx_len,const u8 * Nx,size_t Nx_len,const char * code,const u8 * Kx,size_t Kx_len,u8 * z,unsigned int hash_len)7168 static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
7169 			     const u8 *Mx, size_t Mx_len,
7170 			     const u8 *Nx, size_t Nx_len,
7171 			     const char *code,
7172 			     const u8 *Kx, size_t Kx_len,
7173 			     u8 *z, unsigned int hash_len)
7174 {
7175 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
7176 	int res;
7177 	u8 *info, *pos;
7178 	size_t info_len;
7179 
7180 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7181 	 */
7182 
7183 	/* HKDF-Extract(<>, IKM=K.x) */
7184 	os_memset(salt, 0, hash_len);
7185 	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
7186 		return -1;
7187 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
7188 			prk, hash_len);
7189 	info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
7190 	info = os_malloc(info_len);
7191 	if (!info)
7192 		return -1;
7193 	pos = info;
7194 	os_memcpy(pos, mac_init, ETH_ALEN);
7195 	pos += ETH_ALEN;
7196 	os_memcpy(pos, mac_resp, ETH_ALEN);
7197 	pos += ETH_ALEN;
7198 	os_memcpy(pos, Mx, Mx_len);
7199 	pos += Mx_len;
7200 	os_memcpy(pos, Nx, Nx_len);
7201 	pos += Nx_len;
7202 	os_memcpy(pos, code, os_strlen(code));
7203 
7204 	/* HKDF-Expand(PRK, info, L) */
7205 	if (hash_len == 32)
7206 		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
7207 				      z, hash_len);
7208 	else if (hash_len == 48)
7209 		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
7210 				      z, hash_len);
7211 	else if (hash_len == 64)
7212 		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
7213 				      z, hash_len);
7214 	else
7215 		res = -1;
7216 	os_free(info);
7217 	os_memset(prk, 0, hash_len);
7218 	if (res < 0)
7219 		return -1;
7220 
7221 	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
7222 			z, hash_len);
7223 	return 0;
7224 }
7225 
7226 
dpp_pkex_identifier_match(const u8 * attr_id,u16 attr_id_len,const char * identifier)7227 static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len,
7228 				     const char *identifier)
7229 {
7230 	if (!attr_id && identifier) {
7231 		wpa_printf(MSG_DEBUG,
7232 			   "DPP: No PKEX code identifier received, but expected one");
7233 		return 0;
7234 	}
7235 
7236 	if (attr_id && !identifier) {
7237 		wpa_printf(MSG_DEBUG,
7238 			   "DPP: PKEX code identifier received, but not expecting one");
7239 		return 0;
7240 	}
7241 
7242 	if (attr_id && identifier &&
7243 	    (os_strlen(identifier) != attr_id_len ||
7244 	     os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
7245 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
7246 		return 0;
7247 	}
7248 
7249 	return 1;
7250 }
7251 
7252 
dpp_pkex_rx_exchange_req(void * msg_ctx,struct dpp_bootstrap_info * bi,const u8 * own_mac,const u8 * peer_mac,const char * identifier,const char * code,const u8 * buf,size_t len)7253 struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
7254 					   struct dpp_bootstrap_info *bi,
7255 					   const u8 *own_mac,
7256 					   const u8 *peer_mac,
7257 					   const char *identifier,
7258 					   const char *code,
7259 					   const u8 *buf, size_t len)
7260 {
7261 	const u8 *attr_group, *attr_id, *attr_key;
7262 	u16 attr_group_len, attr_id_len, attr_key_len;
7263 	const struct dpp_curve_params *curve = bi->curve;
7264 	u16 ike_group;
7265 	struct dpp_pkex *pkex = NULL;
7266 	EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
7267 	BN_CTX *bnctx = NULL;
7268 	EC_GROUP *group = NULL;
7269 	BIGNUM *Mx = NULL, *My = NULL;
7270 	EC_KEY *Y_ec = NULL, *X_ec = NULL;;
7271 	const EC_POINT *Y_point;
7272 	BIGNUM *Nx = NULL, *Ny = NULL;
7273 	u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
7274 	size_t Kx_len;
7275 	int res;
7276 
7277 	if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
7278 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7279 			"PKEX counter t limit reached - ignore message");
7280 		return NULL;
7281 	}
7282 
7283 #ifdef CONFIG_TESTING_OPTIONS
7284 	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
7285 		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
7286 			   MAC2STR(dpp_pkex_peer_mac_override));
7287 		peer_mac = dpp_pkex_peer_mac_override;
7288 	}
7289 	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
7290 		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
7291 			   MAC2STR(dpp_pkex_own_mac_override));
7292 		own_mac = dpp_pkex_own_mac_override;
7293 	}
7294 #endif /* CONFIG_TESTING_OPTIONS */
7295 
7296 	attr_id_len = 0;
7297 	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
7298 			       &attr_id_len);
7299 	if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier))
7300 		return NULL;
7301 
7302 	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
7303 				  &attr_group_len);
7304 	if (!attr_group || attr_group_len != 2) {
7305 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7306 			"Missing or invalid Finite Cyclic Group attribute");
7307 		return NULL;
7308 	}
7309 	ike_group = WPA_GET_LE16(attr_group);
7310 	if (ike_group != curve->ike_group) {
7311 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7312 			"Mismatching PKEX curve: peer=%u own=%u",
7313 			ike_group, curve->ike_group);
7314 		pkex = os_zalloc(sizeof(*pkex));
7315 		if (!pkex)
7316 			goto fail;
7317 		pkex->own_bi = bi;
7318 		pkex->failed = 1;
7319 		pkex->exchange_resp = dpp_pkex_build_exchange_resp(
7320 			pkex, DPP_STATUS_BAD_GROUP, NULL, NULL);
7321 		if (!pkex->exchange_resp)
7322 			goto fail;
7323 		return pkex;
7324 	}
7325 
7326 	/* M in Encrypted Key attribute */
7327 	attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
7328 				&attr_key_len);
7329 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
7330 	    attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
7331 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7332 			"Missing Encrypted Key attribute");
7333 		return NULL;
7334 	}
7335 
7336 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
7337 	bnctx = BN_CTX_new();
7338 	if (!bnctx)
7339 		goto fail;
7340 	Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
7341 				&group);
7342 	if (!Qi)
7343 		goto fail;
7344 
7345 	/* X' = M - Qi */
7346 	X = EC_POINT_new(group);
7347 	M = EC_POINT_new(group);
7348 	Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
7349 	My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
7350 	if (!X || !M || !Mx || !My ||
7351 	    EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
7352 	    EC_POINT_is_at_infinity(group, M) ||
7353 	    !EC_POINT_is_on_curve(group, M, bnctx) ||
7354 	    EC_POINT_invert(group, Qi, bnctx) != 1 ||
7355 	    EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
7356 	    EC_POINT_is_at_infinity(group, X) ||
7357 	    !EC_POINT_is_on_curve(group, X, bnctx)) {
7358 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7359 			"Invalid Encrypted Key value");
7360 		bi->pkex_t++;
7361 		goto fail;
7362 	}
7363 	dpp_debug_print_point("DPP: M", group, M);
7364 	dpp_debug_print_point("DPP: X'", group, X);
7365 
7366 	pkex = os_zalloc(sizeof(*pkex));
7367 	if (!pkex)
7368 		goto fail;
7369 	pkex->t = bi->pkex_t;
7370 	pkex->msg_ctx = msg_ctx;
7371 	pkex->own_bi = bi;
7372 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
7373 	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
7374 	if (identifier) {
7375 		pkex->identifier = os_strdup(identifier);
7376 		if (!pkex->identifier)
7377 			goto fail;
7378 	}
7379 	pkex->code = os_strdup(code);
7380 	if (!pkex->code)
7381 		goto fail;
7382 
7383 	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
7384 
7385 	X_ec = EC_KEY_new();
7386 	if (!X_ec ||
7387 	    EC_KEY_set_group(X_ec, group) != 1 ||
7388 	    EC_KEY_set_public_key(X_ec, X) != 1)
7389 		goto fail;
7390 	pkex->x = EVP_PKEY_new();
7391 	if (!pkex->x ||
7392 	    EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
7393 		goto fail;
7394 
7395 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
7396 	Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
7397 	if (!Qr)
7398 		goto fail;
7399 
7400 	/* Generate a random ephemeral keypair y/Y */
7401 #ifdef CONFIG_TESTING_OPTIONS
7402 	if (dpp_pkex_ephemeral_key_override_len) {
7403 		const struct dpp_curve_params *tmp_curve;
7404 
7405 		wpa_printf(MSG_INFO,
7406 			   "DPP: TESTING - override ephemeral key y/Y");
7407 		pkex->y = dpp_set_keypair(&tmp_curve,
7408 					  dpp_pkex_ephemeral_key_override,
7409 					  dpp_pkex_ephemeral_key_override_len);
7410 	} else {
7411 		pkex->y = dpp_gen_keypair(curve);
7412 	}
7413 #else /* CONFIG_TESTING_OPTIONS */
7414 	pkex->y = dpp_gen_keypair(curve);
7415 #endif /* CONFIG_TESTING_OPTIONS */
7416 	if (!pkex->y)
7417 		goto fail;
7418 
7419 	/* N = Y + Qr */
7420 	Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y);
7421 	if (!Y_ec)
7422 		goto fail;
7423 	Y_point = EC_KEY_get0_public_key(Y_ec);
7424 	if (!Y_point)
7425 		goto fail;
7426 	dpp_debug_print_point("DPP: Y", group, Y_point);
7427 	N = EC_POINT_new(group);
7428 	Nx = BN_new();
7429 	Ny = BN_new();
7430 	if (!N || !Nx || !Ny ||
7431 	    EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
7432 	    EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
7433 		goto fail;
7434 	dpp_debug_print_point("DPP: N", group, N);
7435 
7436 	pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
7437 							   Nx, Ny);
7438 	if (!pkex->exchange_resp)
7439 		goto fail;
7440 
7441 	/* K = y * X' */
7442 	if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0)
7443 		goto fail;
7444 
7445 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
7446 			Kx, Kx_len);
7447 
7448 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7449 	 */
7450 	res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
7451 				pkex->Mx, curve->prime_len,
7452 				pkex->Nx, curve->prime_len, pkex->code,
7453 				Kx, Kx_len, pkex->z, curve->hash_len);
7454 	os_memset(Kx, 0, Kx_len);
7455 	if (res < 0)
7456 		goto fail;
7457 
7458 	pkex->exchange_done = 1;
7459 
7460 out:
7461 	BN_CTX_free(bnctx);
7462 	EC_POINT_free(Qi);
7463 	EC_POINT_free(Qr);
7464 	BN_free(Mx);
7465 	BN_free(My);
7466 	BN_free(Nx);
7467 	BN_free(Ny);
7468 	EC_POINT_free(M);
7469 	EC_POINT_free(N);
7470 	EC_POINT_free(X);
7471 	EC_KEY_free(X_ec);
7472 	EC_KEY_free(Y_ec);
7473 	EC_GROUP_free(group);
7474 	return pkex;
7475 fail:
7476 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
7477 	dpp_pkex_free(pkex);
7478 	pkex = NULL;
7479 	goto out;
7480 }
7481 
7482 
7483 static struct wpabuf *
dpp_pkex_build_commit_reveal_req(struct dpp_pkex * pkex,const struct wpabuf * A_pub,const u8 * u)7484 dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
7485 				 const struct wpabuf *A_pub, const u8 *u)
7486 {
7487 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
7488 	struct wpabuf *msg = NULL;
7489 	size_t clear_len, attr_len;
7490 	struct wpabuf *clear = NULL;
7491 	u8 *wrapped;
7492 	u8 octet;
7493 	const u8 *addr[2];
7494 	size_t len[2];
7495 
7496 	/* {A, u, [bootstrapping info]}z */
7497 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
7498 	clear = wpabuf_alloc(clear_len);
7499 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
7500 #ifdef CONFIG_TESTING_OPTIONS
7501 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ)
7502 		attr_len += 5;
7503 #endif /* CONFIG_TESTING_OPTIONS */
7504 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len);
7505 	if (!clear || !msg)
7506 		goto fail;
7507 
7508 #ifdef CONFIG_TESTING_OPTIONS
7509 	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) {
7510 		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
7511 		goto skip_bootstrap_key;
7512 	}
7513 	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) {
7514 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
7515 		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7516 		wpabuf_put_le16(clear, 2 * curve->prime_len);
7517 		if (dpp_test_gen_invalid_key(clear, curve) < 0)
7518 			goto fail;
7519 		goto skip_bootstrap_key;
7520 	}
7521 #endif /* CONFIG_TESTING_OPTIONS */
7522 
7523 	/* A in Bootstrap Key attribute */
7524 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7525 	wpabuf_put_le16(clear, wpabuf_len(A_pub));
7526 	wpabuf_put_buf(clear, A_pub);
7527 
7528 #ifdef CONFIG_TESTING_OPTIONS
7529 skip_bootstrap_key:
7530 	if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) {
7531 		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag");
7532 		goto skip_i_auth_tag;
7533 	}
7534 	if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) {
7535 		wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch");
7536 		wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
7537 		wpabuf_put_le16(clear, curve->hash_len);
7538 		wpabuf_put_data(clear, u, curve->hash_len - 1);
7539 		wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01);
7540 		goto skip_i_auth_tag;
7541 	}
7542 #endif /* CONFIG_TESTING_OPTIONS */
7543 
7544 	/* u in I-Auth tag attribute */
7545 	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
7546 	wpabuf_put_le16(clear, curve->hash_len);
7547 	wpabuf_put_data(clear, u, curve->hash_len);
7548 
7549 #ifdef CONFIG_TESTING_OPTIONS
7550 skip_i_auth_tag:
7551 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) {
7552 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
7553 		goto skip_wrapped_data;
7554 	}
7555 #endif /* CONFIG_TESTING_OPTIONS */
7556 
7557 	addr[0] = wpabuf_head_u8(msg) + 2;
7558 	len[0] = DPP_HDR_LEN;
7559 	octet = 0;
7560 	addr[1] = &octet;
7561 	len[1] = sizeof(octet);
7562 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7563 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7564 
7565 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
7566 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7567 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7568 
7569 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
7570 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
7571 			    wpabuf_head(clear), wpabuf_len(clear),
7572 			    2, addr, len, wrapped) < 0)
7573 		goto fail;
7574 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7575 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
7576 
7577 #ifdef CONFIG_TESTING_OPTIONS
7578 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) {
7579 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
7580 		dpp_build_attr_status(msg, DPP_STATUS_OK);
7581 	}
7582 skip_wrapped_data:
7583 #endif /* CONFIG_TESTING_OPTIONS */
7584 
7585 out:
7586 	wpabuf_free(clear);
7587 	return msg;
7588 
7589 fail:
7590 	wpabuf_free(msg);
7591 	msg = NULL;
7592 	goto out;
7593 }
7594 
7595 
dpp_pkex_rx_exchange_resp(struct dpp_pkex * pkex,const u8 * peer_mac,const u8 * buf,size_t buflen)7596 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
7597 					  const u8 *peer_mac,
7598 					  const u8 *buf, size_t buflen)
7599 {
7600 	const u8 *attr_status, *attr_id, *attr_key, *attr_group;
7601 	u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
7602 	EC_GROUP *group = NULL;
7603 	BN_CTX *bnctx = NULL;
7604 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
7605 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
7606 	EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
7607 	BIGNUM *Nx = NULL, *Ny = NULL;
7608 	EC_KEY *Y_ec = NULL;
7609 	size_t Jx_len, Kx_len;
7610 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
7611 	const u8 *addr[4];
7612 	size_t len[4];
7613 	u8 u[DPP_MAX_HASH_LEN];
7614 	int res;
7615 
7616 	if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
7617 		return NULL;
7618 
7619 #ifdef CONFIG_TESTING_OPTIONS
7620 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) {
7621 		wpa_printf(MSG_INFO,
7622 			   "DPP: TESTING - stop at PKEX Exchange Response");
7623 		pkex->failed = 1;
7624 		return NULL;
7625 	}
7626 
7627 	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
7628 		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
7629 			   MAC2STR(dpp_pkex_peer_mac_override));
7630 		peer_mac = dpp_pkex_peer_mac_override;
7631 	}
7632 #endif /* CONFIG_TESTING_OPTIONS */
7633 
7634 	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
7635 
7636 	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
7637 				   &attr_status_len);
7638 	if (!attr_status || attr_status_len != 1) {
7639 		dpp_pkex_fail(pkex, "No DPP Status attribute");
7640 		return NULL;
7641 	}
7642 	wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
7643 
7644 	if (attr_status[0] == DPP_STATUS_BAD_GROUP) {
7645 		attr_group = dpp_get_attr(buf, buflen,
7646 					  DPP_ATTR_FINITE_CYCLIC_GROUP,
7647 					  &attr_group_len);
7648 		if (attr_group && attr_group_len == 2) {
7649 			wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
7650 				"Peer indicated mismatching PKEX group - proposed %u",
7651 				WPA_GET_LE16(attr_group));
7652 			return NULL;
7653 		}
7654 	}
7655 
7656 	if (attr_status[0] != DPP_STATUS_OK) {
7657 		dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)");
7658 		return NULL;
7659 	}
7660 
7661 	attr_id_len = 0;
7662 	attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
7663 			       &attr_id_len);
7664 	if (!dpp_pkex_identifier_match(attr_id, attr_id_len,
7665 				       pkex->identifier)) {
7666 		dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
7667 		return NULL;
7668 	}
7669 
7670 	/* N in Encrypted Key attribute */
7671 	attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
7672 				&attr_key_len);
7673 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
7674 		dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
7675 		return NULL;
7676 	}
7677 
7678 	/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
7679 	bnctx = BN_CTX_new();
7680 	if (!bnctx)
7681 		goto fail;
7682 	Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
7683 				pkex->identifier, bnctx, &group);
7684 	if (!Qr)
7685 		goto fail;
7686 
7687 	/* Y' = N - Qr */
7688 	Y = EC_POINT_new(group);
7689 	N = EC_POINT_new(group);
7690 	Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
7691 	Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
7692 	if (!Y || !N || !Nx || !Ny ||
7693 	    EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
7694 	    EC_POINT_is_at_infinity(group, N) ||
7695 	    !EC_POINT_is_on_curve(group, N, bnctx) ||
7696 	    EC_POINT_invert(group, Qr, bnctx) != 1 ||
7697 	    EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
7698 	    EC_POINT_is_at_infinity(group, Y) ||
7699 	    !EC_POINT_is_on_curve(group, Y, bnctx)) {
7700 		dpp_pkex_fail(pkex, "Invalid Encrypted Key value");
7701 		pkex->t++;
7702 		goto fail;
7703 	}
7704 	dpp_debug_print_point("DPP: N", group, N);
7705 	dpp_debug_print_point("DPP: Y'", group, Y);
7706 
7707 	pkex->exchange_done = 1;
7708 
7709 	/* ECDH: J = a * Y’ */
7710 	Y_ec = EC_KEY_new();
7711 	if (!Y_ec ||
7712 	    EC_KEY_set_group(Y_ec, group) != 1 ||
7713 	    EC_KEY_set_public_key(Y_ec, Y) != 1)
7714 		goto fail;
7715 	pkex->y = EVP_PKEY_new();
7716 	if (!pkex->y ||
7717 	    EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
7718 		goto fail;
7719 	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
7720 		goto fail;
7721 
7722 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
7723 			Jx, Jx_len);
7724 
7725 	/* u = HMAC(J.x,  MAC-Initiator | A.x | Y’.x | X.x ) */
7726 	A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
7727 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
7728 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
7729 	if (!A_pub || !Y_pub || !X_pub)
7730 		goto fail;
7731 	addr[0] = pkex->own_mac;
7732 	len[0] = ETH_ALEN;
7733 	addr[1] = wpabuf_head(A_pub);
7734 	len[1] = wpabuf_len(A_pub) / 2;
7735 	addr[2] = wpabuf_head(Y_pub);
7736 	len[2] = wpabuf_len(Y_pub) / 2;
7737 	addr[3] = wpabuf_head(X_pub);
7738 	len[3] = wpabuf_len(X_pub) / 2;
7739 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
7740 		goto fail;
7741 	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
7742 
7743 	/* K = x * Y’ */
7744 	if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0)
7745 		goto fail;
7746 
7747 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
7748 			Kx, Kx_len);
7749 
7750 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
7751 	 */
7752 	res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
7753 				pkex->Mx, curve->prime_len,
7754 				attr_key /* N.x */, attr_key_len / 2,
7755 				pkex->code, Kx, Kx_len,
7756 				pkex->z, curve->hash_len);
7757 	os_memset(Kx, 0, Kx_len);
7758 	if (res < 0)
7759 		goto fail;
7760 
7761 	msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u);
7762 	if (!msg)
7763 		goto fail;
7764 
7765 out:
7766 	wpabuf_free(A_pub);
7767 	wpabuf_free(X_pub);
7768 	wpabuf_free(Y_pub);
7769 	EC_POINT_free(Qr);
7770 	EC_POINT_free(Y);
7771 	EC_POINT_free(N);
7772 	BN_free(Nx);
7773 	BN_free(Ny);
7774 	EC_KEY_free(Y_ec);
7775 	BN_CTX_free(bnctx);
7776 	EC_GROUP_free(group);
7777 	return msg;
7778 fail:
7779 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
7780 	goto out;
7781 }
7782 
7783 
7784 static struct wpabuf *
dpp_pkex_build_commit_reveal_resp(struct dpp_pkex * pkex,const struct wpabuf * B_pub,const u8 * v)7785 dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex,
7786 				  const struct wpabuf *B_pub, const u8 *v)
7787 {
7788 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
7789 	struct wpabuf *msg = NULL;
7790 	const u8 *addr[2];
7791 	size_t len[2];
7792 	u8 octet;
7793 	u8 *wrapped;
7794 	struct wpabuf *clear = NULL;
7795 	size_t clear_len, attr_len;
7796 
7797 	/* {B, v [bootstrapping info]}z */
7798 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
7799 	clear = wpabuf_alloc(clear_len);
7800 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
7801 #ifdef CONFIG_TESTING_OPTIONS
7802 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP)
7803 		attr_len += 5;
7804 #endif /* CONFIG_TESTING_OPTIONS */
7805 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len);
7806 	if (!clear || !msg)
7807 		goto fail;
7808 
7809 #ifdef CONFIG_TESTING_OPTIONS
7810 	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) {
7811 		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
7812 		goto skip_bootstrap_key;
7813 	}
7814 	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) {
7815 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
7816 		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7817 		wpabuf_put_le16(clear, 2 * curve->prime_len);
7818 		if (dpp_test_gen_invalid_key(clear, curve) < 0)
7819 			goto fail;
7820 		goto skip_bootstrap_key;
7821 	}
7822 #endif /* CONFIG_TESTING_OPTIONS */
7823 
7824 	/* B in Bootstrap Key attribute */
7825 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
7826 	wpabuf_put_le16(clear, wpabuf_len(B_pub));
7827 	wpabuf_put_buf(clear, B_pub);
7828 
7829 #ifdef CONFIG_TESTING_OPTIONS
7830 skip_bootstrap_key:
7831 	if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) {
7832 		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag");
7833 		goto skip_r_auth_tag;
7834 	}
7835 	if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) {
7836 		wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch");
7837 		wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
7838 		wpabuf_put_le16(clear, curve->hash_len);
7839 		wpabuf_put_data(clear, v, curve->hash_len - 1);
7840 		wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01);
7841 		goto skip_r_auth_tag;
7842 	}
7843 #endif /* CONFIG_TESTING_OPTIONS */
7844 
7845 	/* v in R-Auth tag attribute */
7846 	wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
7847 	wpabuf_put_le16(clear, curve->hash_len);
7848 	wpabuf_put_data(clear, v, curve->hash_len);
7849 
7850 #ifdef CONFIG_TESTING_OPTIONS
7851 skip_r_auth_tag:
7852 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) {
7853 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
7854 		goto skip_wrapped_data;
7855 	}
7856 #endif /* CONFIG_TESTING_OPTIONS */
7857 
7858 	addr[0] = wpabuf_head_u8(msg) + 2;
7859 	len[0] = DPP_HDR_LEN;
7860 	octet = 1;
7861 	addr[1] = &octet;
7862 	len[1] = sizeof(octet);
7863 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7864 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7865 
7866 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
7867 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7868 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
7869 
7870 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
7871 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
7872 			    wpabuf_head(clear), wpabuf_len(clear),
7873 			    2, addr, len, wrapped) < 0)
7874 		goto fail;
7875 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7876 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
7877 
7878 #ifdef CONFIG_TESTING_OPTIONS
7879 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) {
7880 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
7881 		dpp_build_attr_status(msg, DPP_STATUS_OK);
7882 	}
7883 skip_wrapped_data:
7884 #endif /* CONFIG_TESTING_OPTIONS */
7885 
7886 out:
7887 	wpabuf_free(clear);
7888 	return msg;
7889 
7890 fail:
7891 	wpabuf_free(msg);
7892 	msg = NULL;
7893 	goto out;
7894 }
7895 
7896 
dpp_pkex_rx_commit_reveal_req(struct dpp_pkex * pkex,const u8 * hdr,const u8 * buf,size_t buflen)7897 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
7898 					      const u8 *hdr,
7899 					      const u8 *buf, size_t buflen)
7900 {
7901 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
7902 	size_t Jx_len, Lx_len;
7903 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
7904 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
7905 	const u8 *wrapped_data, *b_key, *peer_u;
7906 	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
7907 	const u8 *addr[4];
7908 	size_t len[4];
7909 	u8 octet;
7910 	u8 *unwrapped = NULL;
7911 	size_t unwrapped_len = 0;
7912 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
7913 	struct wpabuf *B_pub = NULL;
7914 	u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
7915 
7916 #ifdef CONFIG_TESTING_OPTIONS
7917 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) {
7918 		wpa_printf(MSG_INFO,
7919 			   "DPP: TESTING - stop at PKEX CR Request");
7920 		pkex->failed = 1;
7921 		return NULL;
7922 	}
7923 #endif /* CONFIG_TESTING_OPTIONS */
7924 
7925 	if (!pkex->exchange_done || pkex->failed ||
7926 	    pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator)
7927 		goto fail;
7928 
7929 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
7930 				    &wrapped_data_len);
7931 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
7932 		dpp_pkex_fail(pkex,
7933 			      "Missing or invalid required Wrapped Data attribute");
7934 		goto fail;
7935 	}
7936 
7937 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
7938 		    wrapped_data, wrapped_data_len);
7939 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
7940 	unwrapped = os_malloc(unwrapped_len);
7941 	if (!unwrapped)
7942 		goto fail;
7943 
7944 	addr[0] = hdr;
7945 	len[0] = DPP_HDR_LEN;
7946 	octet = 0;
7947 	addr[1] = &octet;
7948 	len[1] = sizeof(octet);
7949 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
7950 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
7951 
7952 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
7953 			    wrapped_data, wrapped_data_len,
7954 			    2, addr, len, unwrapped) < 0) {
7955 		dpp_pkex_fail(pkex,
7956 			      "AES-SIV decryption failed - possible PKEX code mismatch");
7957 		pkex->failed = 1;
7958 		pkex->t++;
7959 		goto fail;
7960 	}
7961 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
7962 		    unwrapped, unwrapped_len);
7963 
7964 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
7965 		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
7966 		goto fail;
7967 	}
7968 
7969 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
7970 			     &b_key_len);
7971 	if (!b_key || b_key_len != 2 * curve->prime_len) {
7972 		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
7973 		goto fail;
7974 	}
7975 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
7976 							b_key_len);
7977 	if (!pkex->peer_bootstrap_key) {
7978 		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
7979 		goto fail;
7980 	}
7981 	dpp_debug_print_key("DPP: Peer bootstrap public key",
7982 			    pkex->peer_bootstrap_key);
7983 
7984 	/* ECDH: J' = y * A' */
7985 	if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0)
7986 		goto fail;
7987 
7988 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
7989 			Jx, Jx_len);
7990 
7991 	/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
7992 	A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
7993 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
7994 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
7995 	if (!A_pub || !Y_pub || !X_pub)
7996 		goto fail;
7997 	addr[0] = pkex->peer_mac;
7998 	len[0] = ETH_ALEN;
7999 	addr[1] = wpabuf_head(A_pub);
8000 	len[1] = wpabuf_len(A_pub) / 2;
8001 	addr[2] = wpabuf_head(Y_pub);
8002 	len[2] = wpabuf_len(Y_pub) / 2;
8003 	addr[3] = wpabuf_head(X_pub);
8004 	len[3] = wpabuf_len(X_pub) / 2;
8005 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
8006 		goto fail;
8007 
8008 	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
8009 			      &peer_u_len);
8010 	if (!peer_u || peer_u_len != curve->hash_len ||
8011 	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
8012 		dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found");
8013 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
8014 			    u, curve->hash_len);
8015 		wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
8016 		pkex->t++;
8017 		goto fail;
8018 	}
8019 	wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
8020 
8021 	/* ECDH: L = b * X' */
8022 	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0)
8023 		goto fail;
8024 
8025 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
8026 			Lx, Lx_len);
8027 
8028 	/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
8029 	B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
8030 	if (!B_pub)
8031 		goto fail;
8032 	addr[0] = pkex->own_mac;
8033 	len[0] = ETH_ALEN;
8034 	addr[1] = wpabuf_head(B_pub);
8035 	len[1] = wpabuf_len(B_pub) / 2;
8036 	addr[2] = wpabuf_head(X_pub);
8037 	len[2] = wpabuf_len(X_pub) / 2;
8038 	addr[3] = wpabuf_head(Y_pub);
8039 	len[3] = wpabuf_len(Y_pub) / 2;
8040 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
8041 		goto fail;
8042 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
8043 
8044 	msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v);
8045 	if (!msg)
8046 		goto fail;
8047 
8048 out:
8049 	os_free(unwrapped);
8050 	wpabuf_free(A_pub);
8051 	wpabuf_free(B_pub);
8052 	wpabuf_free(X_pub);
8053 	wpabuf_free(Y_pub);
8054 	return msg;
8055 fail:
8056 	wpa_printf(MSG_DEBUG,
8057 		   "DPP: PKEX Commit-Reveal Request processing failed");
8058 	goto out;
8059 }
8060 
8061 
dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex * pkex,const u8 * hdr,const u8 * buf,size_t buflen)8062 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
8063 				   const u8 *buf, size_t buflen)
8064 {
8065 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
8066 	const u8 *wrapped_data, *b_key, *peer_v;
8067 	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
8068 	const u8 *addr[4];
8069 	size_t len[4];
8070 	u8 octet;
8071 	u8 *unwrapped = NULL;
8072 	size_t unwrapped_len = 0;
8073 	int ret = -1;
8074 	u8 v[DPP_MAX_HASH_LEN];
8075 	size_t Lx_len;
8076 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
8077 	struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
8078 
8079 #ifdef CONFIG_TESTING_OPTIONS
8080 	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) {
8081 		wpa_printf(MSG_INFO,
8082 			   "DPP: TESTING - stop at PKEX CR Response");
8083 		pkex->failed = 1;
8084 		goto fail;
8085 	}
8086 #endif /* CONFIG_TESTING_OPTIONS */
8087 
8088 	if (!pkex->exchange_done || pkex->failed ||
8089 	    pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
8090 		goto fail;
8091 
8092 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
8093 				    &wrapped_data_len);
8094 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
8095 		dpp_pkex_fail(pkex,
8096 			      "Missing or invalid required Wrapped Data attribute");
8097 		goto fail;
8098 	}
8099 
8100 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
8101 		    wrapped_data, wrapped_data_len);
8102 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
8103 	unwrapped = os_malloc(unwrapped_len);
8104 	if (!unwrapped)
8105 		goto fail;
8106 
8107 	addr[0] = hdr;
8108 	len[0] = DPP_HDR_LEN;
8109 	octet = 1;
8110 	addr[1] = &octet;
8111 	len[1] = sizeof(octet);
8112 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
8113 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
8114 
8115 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
8116 			    wrapped_data, wrapped_data_len,
8117 			    2, addr, len, unwrapped) < 0) {
8118 		dpp_pkex_fail(pkex,
8119 			      "AES-SIV decryption failed - possible PKEX code mismatch");
8120 		pkex->t++;
8121 		goto fail;
8122 	}
8123 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
8124 		    unwrapped, unwrapped_len);
8125 
8126 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
8127 		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
8128 		goto fail;
8129 	}
8130 
8131 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
8132 			     &b_key_len);
8133 	if (!b_key || b_key_len != 2 * curve->prime_len) {
8134 		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
8135 		goto fail;
8136 	}
8137 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
8138 							b_key_len);
8139 	if (!pkex->peer_bootstrap_key) {
8140 		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
8141 		goto fail;
8142 	}
8143 	dpp_debug_print_key("DPP: Peer bootstrap public key",
8144 			    pkex->peer_bootstrap_key);
8145 
8146 	/* ECDH: L' = x * B' */
8147 	if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0)
8148 		goto fail;
8149 
8150 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
8151 			Lx, Lx_len);
8152 
8153 	/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
8154 	B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
8155 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
8156 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
8157 	if (!B_pub || !X_pub || !Y_pub)
8158 		goto fail;
8159 	addr[0] = pkex->peer_mac;
8160 	len[0] = ETH_ALEN;
8161 	addr[1] = wpabuf_head(B_pub);
8162 	len[1] = wpabuf_len(B_pub) / 2;
8163 	addr[2] = wpabuf_head(X_pub);
8164 	len[2] = wpabuf_len(X_pub) / 2;
8165 	addr[3] = wpabuf_head(Y_pub);
8166 	len[3] = wpabuf_len(Y_pub) / 2;
8167 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
8168 		goto fail;
8169 
8170 	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
8171 			      &peer_v_len);
8172 	if (!peer_v || peer_v_len != curve->hash_len ||
8173 	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
8174 		dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found");
8175 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
8176 			    v, curve->hash_len);
8177 		wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
8178 		pkex->t++;
8179 		goto fail;
8180 	}
8181 	wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
8182 
8183 	ret = 0;
8184 out:
8185 	wpabuf_free(B_pub);
8186 	wpabuf_free(X_pub);
8187 	wpabuf_free(Y_pub);
8188 	os_free(unwrapped);
8189 	return ret;
8190 fail:
8191 	goto out;
8192 }
8193 
8194 
dpp_pkex_free(struct dpp_pkex * pkex)8195 void dpp_pkex_free(struct dpp_pkex *pkex)
8196 {
8197 	if (!pkex)
8198 		return;
8199 
8200 	os_free(pkex->identifier);
8201 	os_free(pkex->code);
8202 	EVP_PKEY_free(pkex->x);
8203 	EVP_PKEY_free(pkex->y);
8204 	EVP_PKEY_free(pkex->peer_bootstrap_key);
8205 	wpabuf_free(pkex->exchange_req);
8206 	wpabuf_free(pkex->exchange_resp);
8207 	os_free(pkex);
8208 }
8209 
8210 
8211 #ifdef CONFIG_TESTING_OPTIONS
dpp_corrupt_connector_signature(const char * connector)8212 char * dpp_corrupt_connector_signature(const char *connector)
8213 {
8214 	char *tmp, *pos, *signed3 = NULL;
8215 	unsigned char *signature = NULL;
8216 	size_t signature_len = 0, signed3_len;
8217 
8218 	tmp = os_zalloc(os_strlen(connector) + 5);
8219 	if (!tmp)
8220 		goto fail;
8221 	os_memcpy(tmp, connector, os_strlen(connector));
8222 
8223 	pos = os_strchr(tmp, '.');
8224 	if (!pos)
8225 		goto fail;
8226 
8227 	pos = os_strchr(pos + 1, '.');
8228 	if (!pos)
8229 		goto fail;
8230 	pos++;
8231 
8232 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
8233 		   pos);
8234 	signature = base64_url_decode((const unsigned char *) pos,
8235 				      os_strlen(pos), &signature_len);
8236 	if (!signature || signature_len == 0)
8237 		goto fail;
8238 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
8239 		    signature, signature_len);
8240 	signature[signature_len - 1] ^= 0x01;
8241 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
8242 		    signature, signature_len);
8243 	signed3 = (char *) base64_url_encode(signature, signature_len,
8244 					     &signed3_len, 0);
8245 	if (!signed3)
8246 		goto fail;
8247 	os_memcpy(pos, signed3, signed3_len);
8248 	pos[signed3_len] = '\0';
8249 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
8250 		   pos);
8251 
8252 out:
8253 	os_free(signature);
8254 	os_free(signed3);
8255 	return tmp;
8256 fail:
8257 	os_free(tmp);
8258 	tmp = NULL;
8259 	goto out;
8260 }
8261 #endif /* CONFIG_TESTING_OPTIONS */
8262 
8263 
8264 #ifdef CONFIG_DPP2
8265 
dpp_pfs_init(const u8 * net_access_key,size_t net_access_key_len)8266 struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
8267 			      size_t net_access_key_len)
8268 {
8269 	struct wpabuf *pub = NULL;
8270 	EVP_PKEY *own_key;
8271 	struct dpp_pfs *pfs;
8272 
8273 	pfs = os_zalloc(sizeof(*pfs));
8274 	if (!pfs)
8275 		return NULL;
8276 
8277 	own_key = dpp_set_keypair(&pfs->curve, net_access_key,
8278 				  net_access_key_len);
8279 	if (!own_key) {
8280 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
8281 		goto fail;
8282 	}
8283 	EVP_PKEY_free(own_key);
8284 
8285 	pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
8286 	if (!pfs->ecdh)
8287 		goto fail;
8288 
8289 	pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
8290 	pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
8291 	if (!pub)
8292 		goto fail;
8293 
8294 	pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
8295 	if (!pfs->ie)
8296 		goto fail;
8297 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
8298 	wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
8299 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
8300 	wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
8301 	wpabuf_put_buf(pfs->ie, pub);
8302 	wpabuf_free(pub);
8303 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
8304 			pfs->ie);
8305 
8306 	return pfs;
8307 fail:
8308 	wpabuf_free(pub);
8309 	dpp_pfs_free(pfs);
8310 	return NULL;
8311 }
8312 
8313 
dpp_pfs_process(struct dpp_pfs * pfs,const u8 * peer_ie,size_t peer_ie_len)8314 int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
8315 {
8316 	if (peer_ie_len < 2)
8317 		return -1;
8318 	if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
8319 		wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
8320 		return -1;
8321 	}
8322 
8323 	pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
8324 					      peer_ie_len - 2);
8325 	pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
8326 	if (!pfs->secret) {
8327 		wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
8328 		return -1;
8329 	}
8330 	wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
8331 	return 0;
8332 }
8333 
8334 
dpp_pfs_free(struct dpp_pfs * pfs)8335 void dpp_pfs_free(struct dpp_pfs *pfs)
8336 {
8337 	if (!pfs)
8338 		return;
8339 	crypto_ecdh_deinit(pfs->ecdh);
8340 	wpabuf_free(pfs->ie);
8341 	wpabuf_clear_free(pfs->secret);
8342 	os_free(pfs);
8343 }
8344 
8345 #endif /* CONFIG_DPP2 */
8346 
8347 
dpp_next_id(struct dpp_global * dpp)8348 static unsigned int dpp_next_id(struct dpp_global *dpp)
8349 {
8350 	struct dpp_bootstrap_info *bi;
8351 	unsigned int max_id = 0;
8352 
8353 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8354 		if (bi->id > max_id)
8355 			max_id = bi->id;
8356 	}
8357 	return max_id + 1;
8358 }
8359 
8360 
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)8361 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
8362 {
8363 	struct dpp_bootstrap_info *bi, *tmp;
8364 	int found = 0;
8365 
8366 	if (!dpp)
8367 		return -1;
8368 
8369 	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
8370 			      struct dpp_bootstrap_info, list) {
8371 		if (id && bi->id != id)
8372 			continue;
8373 		found = 1;
8374 		dl_list_del(&bi->list);
8375 		dpp_bootstrap_info_free(bi);
8376 	}
8377 
8378 	if (id == 0)
8379 		return 0; /* flush succeeds regardless of entries found */
8380 	return found ? 0 : -1;
8381 }
8382 
8383 
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)8384 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
8385 					    const char *uri)
8386 {
8387 	struct dpp_bootstrap_info *bi;
8388 
8389 	if (!dpp)
8390 		return NULL;
8391 
8392 	bi = dpp_parse_qr_code(uri);
8393 	if (!bi)
8394 		return NULL;
8395 
8396 	bi->id = dpp_next_id(dpp);
8397 	dl_list_add(&dpp->bootstrap, &bi->list);
8398 	return bi;
8399 }
8400 
8401 
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)8402 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
8403 {
8404 	char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
8405 	char *key = NULL;
8406 	u8 *privkey = NULL;
8407 	size_t privkey_len = 0;
8408 	size_t len;
8409 	int ret = -1;
8410 	struct dpp_bootstrap_info *bi;
8411 
8412 	if (!dpp)
8413 		return -1;
8414 
8415 	bi = os_zalloc(sizeof(*bi));
8416 	if (!bi)
8417 		goto fail;
8418 
8419 	if (os_strstr(cmd, "type=qrcode"))
8420 		bi->type = DPP_BOOTSTRAP_QR_CODE;
8421 	else if (os_strstr(cmd, "type=pkex"))
8422 		bi->type = DPP_BOOTSTRAP_PKEX;
8423 	else
8424 		goto fail;
8425 
8426 	chan = get_param(cmd, " chan=");
8427 	mac = get_param(cmd, " mac=");
8428 	info = get_param(cmd, " info=");
8429 	curve = get_param(cmd, " curve=");
8430 	key = get_param(cmd, " key=");
8431 
8432 	if (key) {
8433 		privkey_len = os_strlen(key) / 2;
8434 		privkey = os_malloc(privkey_len);
8435 		if (!privkey ||
8436 		    hexstr2bin(key, privkey, privkey_len) < 0)
8437 			goto fail;
8438 	}
8439 
8440 	pk = dpp_keygen(bi, curve, privkey, privkey_len);
8441 	if (!pk)
8442 		goto fail;
8443 
8444 	len = 4; /* "DPP:" */
8445 	if (chan) {
8446 		if (dpp_parse_uri_chan_list(bi, chan) < 0)
8447 			goto fail;
8448 		len += 3 + os_strlen(chan); /* C:...; */
8449 	}
8450 	if (mac) {
8451 		if (dpp_parse_uri_mac(bi, mac) < 0)
8452 			goto fail;
8453 		len += 3 + os_strlen(mac); /* M:...; */
8454 	}
8455 	if (info) {
8456 		if (dpp_parse_uri_info(bi, info) < 0)
8457 			goto fail;
8458 		len += 3 + os_strlen(info); /* I:...; */
8459 	}
8460 	len += 4 + os_strlen(pk);
8461 	bi->uri = os_malloc(len + 1);
8462 	if (!bi->uri)
8463 		goto fail;
8464 	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
8465 		    chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
8466 		    mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
8467 		    info ? "I:" : "", info ? info : "", info ? ";" : "",
8468 		    pk);
8469 	bi->id = dpp_next_id(dpp);
8470 	dl_list_add(&dpp->bootstrap, &bi->list);
8471 	ret = bi->id;
8472 	bi = NULL;
8473 fail:
8474 	os_free(curve);
8475 	os_free(pk);
8476 	os_free(chan);
8477 	os_free(mac);
8478 	os_free(info);
8479 	str_clear_free(key);
8480 	bin_clear_free(privkey, privkey_len);
8481 	dpp_bootstrap_info_free(bi);
8482 	return ret;
8483 }
8484 
8485 
8486 struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)8487 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
8488 {
8489 	struct dpp_bootstrap_info *bi;
8490 
8491 	if (!dpp)
8492 		return NULL;
8493 
8494 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8495 		if (bi->id == id)
8496 			return bi;
8497 	}
8498 	return NULL;
8499 }
8500 
8501 
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)8502 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
8503 {
8504 	unsigned int id_val;
8505 
8506 	if (os_strcmp(id, "*") == 0) {
8507 		id_val = 0;
8508 	} else {
8509 		id_val = atoi(id);
8510 		if (id_val == 0)
8511 			return -1;
8512 	}
8513 
8514 	return dpp_bootstrap_del(dpp, id_val);
8515 }
8516 
8517 
8518 struct dpp_bootstrap_info *
dpp_pkex_finish(struct dpp_global * dpp,struct dpp_pkex * pkex,const u8 * peer,unsigned int freq)8519 dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
8520 		unsigned int freq)
8521 {
8522 	struct dpp_bootstrap_info *bi;
8523 
8524 	bi = os_zalloc(sizeof(*bi));
8525 	if (!bi)
8526 		return NULL;
8527 	bi->id = dpp_next_id(dpp);
8528 	bi->type = DPP_BOOTSTRAP_PKEX;
8529 	os_memcpy(bi->mac_addr, peer, ETH_ALEN);
8530 	bi->num_freq = 1;
8531 	bi->freq[0] = freq;
8532 	bi->curve = pkex->own_bi->curve;
8533 	bi->pubkey = pkex->peer_bootstrap_key;
8534 	pkex->peer_bootstrap_key = NULL;
8535 	if (dpp_bootstrap_key_hash(bi) < 0) {
8536 		dpp_bootstrap_info_free(bi);
8537 		return NULL;
8538 	}
8539 	dpp_pkex_free(pkex);
8540 	dl_list_add(&dpp->bootstrap, &bi->list);
8541 	return bi;
8542 }
8543 
8544 
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)8545 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
8546 {
8547 	struct dpp_bootstrap_info *bi;
8548 
8549 	bi = dpp_bootstrap_get_id(dpp, id);
8550 	if (!bi)
8551 		return NULL;
8552 	return bi->uri;
8553 }
8554 
8555 
dpp_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)8556 int dpp_bootstrap_info(struct dpp_global *dpp, int id,
8557 		       char *reply, int reply_size)
8558 {
8559 	struct dpp_bootstrap_info *bi;
8560 	char pkhash[2 * SHA256_MAC_LEN + 1];
8561 
8562 	bi = dpp_bootstrap_get_id(dpp, id);
8563 	if (!bi)
8564 		return -1;
8565 	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
8566 			 SHA256_MAC_LEN);
8567 	return os_snprintf(reply, reply_size, "type=%s\n"
8568 			   "mac_addr=" MACSTR "\n"
8569 			   "info=%s\n"
8570 			   "num_freq=%u\n"
8571 			   "curve=%s\n"
8572 			   "pkhash=%s\n",
8573 			   dpp_bootstrap_type_txt(bi->type),
8574 			   MAC2STR(bi->mac_addr),
8575 			   bi->info ? bi->info : "",
8576 			   bi->num_freq,
8577 			   bi->curve->name,
8578 			   pkhash);
8579 }
8580 
8581 
dpp_bootstrap_find_pair(struct dpp_global * dpp,const u8 * i_bootstrap,const u8 * r_bootstrap,struct dpp_bootstrap_info ** own_bi,struct dpp_bootstrap_info ** peer_bi)8582 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
8583 			     const u8 *r_bootstrap,
8584 			     struct dpp_bootstrap_info **own_bi,
8585 			     struct dpp_bootstrap_info **peer_bi)
8586 {
8587 	struct dpp_bootstrap_info *bi;
8588 
8589 	*own_bi = NULL;
8590 	*peer_bi = NULL;
8591 	if (!dpp)
8592 		return;
8593 
8594 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
8595 		if (!*own_bi && bi->own &&
8596 		    os_memcmp(bi->pubkey_hash, r_bootstrap,
8597 			      SHA256_MAC_LEN) == 0) {
8598 			wpa_printf(MSG_DEBUG,
8599 				   "DPP: Found matching own bootstrapping information");
8600 			*own_bi = bi;
8601 		}
8602 
8603 		if (!*peer_bi && !bi->own &&
8604 		    os_memcmp(bi->pubkey_hash, i_bootstrap,
8605 			      SHA256_MAC_LEN) == 0) {
8606 			wpa_printf(MSG_DEBUG,
8607 				   "DPP: Found matching peer bootstrapping information");
8608 			*peer_bi = bi;
8609 		}
8610 
8611 		if (*own_bi && *peer_bi)
8612 			break;
8613 	}
8614 
8615 }
8616 
8617 
dpp_next_configurator_id(struct dpp_global * dpp)8618 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
8619 {
8620 	struct dpp_configurator *conf;
8621 	unsigned int max_id = 0;
8622 
8623 	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
8624 			 list) {
8625 		if (conf->id > max_id)
8626 			max_id = conf->id;
8627 	}
8628 	return max_id + 1;
8629 }
8630 
8631 
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)8632 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
8633 {
8634 	char *curve = NULL;
8635 	char *key = NULL;
8636 	u8 *privkey = NULL;
8637 	size_t privkey_len = 0;
8638 	int ret = -1;
8639 	struct dpp_configurator *conf = NULL;
8640 
8641 	curve = get_param(cmd, " curve=");
8642 	key = get_param(cmd, " key=");
8643 
8644 	if (key) {
8645 		privkey_len = os_strlen(key) / 2;
8646 		privkey = os_malloc(privkey_len);
8647 		if (!privkey ||
8648 		    hexstr2bin(key, privkey, privkey_len) < 0)
8649 			goto fail;
8650 	}
8651 
8652 	conf = dpp_keygen_configurator(curve, privkey, privkey_len);
8653 	if (!conf)
8654 		goto fail;
8655 
8656 	conf->id = dpp_next_configurator_id(dpp);
8657 	dl_list_add(&dpp->configurator, &conf->list);
8658 	ret = conf->id;
8659 	conf = NULL;
8660 fail:
8661 	os_free(curve);
8662 	str_clear_free(key);
8663 	bin_clear_free(privkey, privkey_len);
8664 	dpp_configurator_free(conf);
8665 	return ret;
8666 }
8667 
8668 
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)8669 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
8670 {
8671 	struct dpp_configurator *conf, *tmp;
8672 	int found = 0;
8673 
8674 	if (!dpp)
8675 		return -1;
8676 
8677 	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
8678 			      struct dpp_configurator, list) {
8679 		if (id && conf->id != id)
8680 			continue;
8681 		found = 1;
8682 		dl_list_del(&conf->list);
8683 		dpp_configurator_free(conf);
8684 	}
8685 
8686 	if (id == 0)
8687 		return 0; /* flush succeeds regardless of entries found */
8688 	return found ? 0 : -1;
8689 }
8690 
8691 
dpp_configurator_remove(struct dpp_global * dpp,const char * id)8692 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
8693 {
8694 	unsigned int id_val;
8695 
8696 	if (os_strcmp(id, "*") == 0) {
8697 		id_val = 0;
8698 	} else {
8699 		id_val = atoi(id);
8700 		if (id_val == 0)
8701 			return -1;
8702 	}
8703 
8704 	return dpp_configurator_del(dpp, id_val);
8705 }
8706 
8707 
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)8708 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
8709 				char *buf, size_t buflen)
8710 {
8711 	struct dpp_configurator *conf;
8712 
8713 	conf = dpp_configurator_get_id(dpp, id);
8714 	if (!conf)
8715 		return -1;
8716 
8717 	return dpp_configurator_get_key(conf, buf, buflen);
8718 }
8719 
8720 
8721 #ifdef CONFIG_DPP2
8722 
dpp_connection_free(struct dpp_connection * conn)8723 static void dpp_connection_free(struct dpp_connection *conn)
8724 {
8725 	if (conn->sock >= 0) {
8726 		wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
8727 			   conn->sock);
8728 		eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
8729 		eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8730 		close(conn->sock);
8731 	}
8732 	wpabuf_free(conn->msg);
8733 	wpabuf_free(conn->msg_out);
8734 	dpp_auth_deinit(conn->auth);
8735 	os_free(conn);
8736 }
8737 
8738 
dpp_connection_remove(struct dpp_connection * conn)8739 static void dpp_connection_remove(struct dpp_connection *conn)
8740 {
8741 	dl_list_del(&conn->list);
8742 	dpp_connection_free(conn);
8743 }
8744 
8745 
dpp_tcp_init_flush(struct dpp_global * dpp)8746 static void dpp_tcp_init_flush(struct dpp_global *dpp)
8747 {
8748 	struct dpp_connection *conn, *tmp;
8749 
8750 	dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
8751 			      list)
8752 		dpp_connection_remove(conn);
8753 }
8754 
8755 
dpp_relay_controller_free(struct dpp_relay_controller * ctrl)8756 static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
8757 {
8758 	struct dpp_connection *conn, *tmp;
8759 
8760 	dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
8761 			      list)
8762 		dpp_connection_remove(conn);
8763 	os_free(ctrl);
8764 }
8765 
8766 
dpp_relay_flush_controllers(struct dpp_global * dpp)8767 static void dpp_relay_flush_controllers(struct dpp_global *dpp)
8768 {
8769 	struct dpp_relay_controller *ctrl, *tmp;
8770 
8771 	if (!dpp)
8772 		return;
8773 
8774 	dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
8775 			      struct dpp_relay_controller, list) {
8776 		dl_list_del(&ctrl->list);
8777 		dpp_relay_controller_free(ctrl);
8778 	}
8779 }
8780 
8781 #endif /* CONFIG_DPP2 */
8782 
8783 
dpp_global_init(struct dpp_global_config * config)8784 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
8785 {
8786 	struct dpp_global *dpp;
8787 
8788 	dpp = os_zalloc(sizeof(*dpp));
8789 	if (!dpp)
8790 		return NULL;
8791 	dpp->msg_ctx = config->msg_ctx;
8792 #ifdef CONFIG_DPP2
8793 	dpp->cb_ctx = config->cb_ctx;
8794 	dpp->process_conf_obj = config->process_conf_obj;
8795 #endif /* CONFIG_DPP2 */
8796 
8797 	dl_list_init(&dpp->bootstrap);
8798 	dl_list_init(&dpp->configurator);
8799 #ifdef CONFIG_DPP2
8800 	dl_list_init(&dpp->controllers);
8801 	dl_list_init(&dpp->tcp_init);
8802 #endif /* CONFIG_DPP2 */
8803 
8804 	return dpp;
8805 }
8806 
8807 
dpp_global_clear(struct dpp_global * dpp)8808 void dpp_global_clear(struct dpp_global *dpp)
8809 {
8810 	if (!dpp)
8811 		return;
8812 
8813 	dpp_bootstrap_del(dpp, 0);
8814 	dpp_configurator_del(dpp, 0);
8815 #ifdef CONFIG_DPP2
8816 	dpp_tcp_init_flush(dpp);
8817 	dpp_relay_flush_controllers(dpp);
8818 	dpp_controller_stop(dpp);
8819 #endif /* CONFIG_DPP2 */
8820 }
8821 
8822 
dpp_global_deinit(struct dpp_global * dpp)8823 void dpp_global_deinit(struct dpp_global *dpp)
8824 {
8825 	dpp_global_clear(dpp);
8826 	os_free(dpp);
8827 }
8828 
8829 
8830 #ifdef CONFIG_DPP2
8831 
8832 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
8833 static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
8834 static void dpp_controller_auth_success(struct dpp_connection *conn,
8835 					int initiator);
8836 
8837 
dpp_relay_add_controller(struct dpp_global * dpp,struct dpp_relay_config * config)8838 int dpp_relay_add_controller(struct dpp_global *dpp,
8839 			     struct dpp_relay_config *config)
8840 {
8841 	struct dpp_relay_controller *ctrl;
8842 
8843 	if (!dpp)
8844 		return -1;
8845 
8846 	ctrl = os_zalloc(sizeof(*ctrl));
8847 	if (!ctrl)
8848 		return -1;
8849 	dl_list_init(&ctrl->conn);
8850 	ctrl->global = dpp;
8851 	os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
8852 	os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
8853 	ctrl->cb_ctx = config->cb_ctx;
8854 	ctrl->tx = config->tx;
8855 	ctrl->gas_resp_tx = config->gas_resp_tx;
8856 	dl_list_add(&dpp->controllers, &ctrl->list);
8857 	return 0;
8858 }
8859 
8860 
8861 static struct dpp_relay_controller *
dpp_relay_controller_get(struct dpp_global * dpp,const u8 * pkhash)8862 dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
8863 {
8864 	struct dpp_relay_controller *ctrl;
8865 
8866 	if (!dpp)
8867 		return NULL;
8868 
8869 	dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
8870 			 list) {
8871 		if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
8872 			return ctrl;
8873 	}
8874 
8875 	return NULL;
8876 }
8877 
8878 
dpp_controller_gas_done(struct dpp_connection * conn)8879 static void dpp_controller_gas_done(struct dpp_connection *conn)
8880 {
8881 	struct dpp_authentication *auth = conn->auth;
8882 
8883 	if (auth->peer_version >= 2 &&
8884 	    auth->conf_resp_status == DPP_STATUS_OK) {
8885 		wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
8886 		auth->waiting_conf_result = 1;
8887 		return;
8888 	}
8889 
8890 	wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
8891 	dpp_connection_remove(conn);
8892 }
8893 
8894 
dpp_tcp_send(struct dpp_connection * conn)8895 static int dpp_tcp_send(struct dpp_connection *conn)
8896 {
8897 	int res;
8898 
8899 	if (!conn->msg_out) {
8900 		eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8901 		conn->write_eloop = 0;
8902 		return -1;
8903 	}
8904 	res = send(conn->sock,
8905 		   wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
8906 		   wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
8907 	if (res < 0) {
8908 		wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
8909 			   strerror(errno));
8910 		dpp_connection_remove(conn);
8911 		return -1;
8912 	}
8913 
8914 	conn->msg_out_pos += res;
8915 	if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
8916 		wpa_printf(MSG_DEBUG,
8917 			   "DPP: %u/%u bytes of message sent to Controller",
8918 			   (unsigned int) conn->msg_out_pos,
8919 			   (unsigned int) wpabuf_len(conn->msg_out));
8920 		if (!conn->write_eloop &&
8921 		    eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
8922 					dpp_conn_tx_ready, conn, NULL) == 0)
8923 			conn->write_eloop = 1;
8924 		return 1;
8925 	}
8926 
8927 	wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
8928 	wpabuf_free(conn->msg_out);
8929 	conn->msg_out = NULL;
8930 	conn->msg_out_pos = 0;
8931 	eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
8932 	conn->write_eloop = 0;
8933 	if (!conn->read_eloop &&
8934 	    eloop_register_sock(conn->sock, EVENT_TYPE_READ,
8935 				dpp_controller_rx, conn, NULL) == 0)
8936 		conn->read_eloop = 1;
8937 	if (conn->on_tcp_tx_complete_remove) {
8938 		dpp_connection_remove(conn);
8939 	} else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done &&
8940 		   conn->auth) {
8941 		dpp_controller_gas_done(conn);
8942 	} else if (conn->on_tcp_tx_complete_auth_ok) {
8943 		conn->on_tcp_tx_complete_auth_ok = 0;
8944 		dpp_controller_auth_success(conn, 1);
8945 	}
8946 
8947 	return 0;
8948 }
8949 
8950 
dpp_controller_start_gas_client(struct dpp_connection * conn)8951 static void dpp_controller_start_gas_client(struct dpp_connection *conn)
8952 {
8953 	struct dpp_authentication *auth = conn->auth;
8954 	struct wpabuf *buf;
8955 	char json[100];
8956 	int netrole_ap = 0; /* TODO: make this configurable */
8957 
8958 	os_snprintf(json, sizeof(json),
8959 		    "{\"name\":\"Test\","
8960 		    "\"wi-fi_tech\":\"infra\","
8961 		    "\"netRole\":\"%s\"}",
8962 		    netrole_ap ? "ap" : "sta");
8963 #ifdef CONFIG_TESTING_OPTIONS
8964 	if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
8965 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
8966 		json[29] = 'k'; /* replace "infra" with "knfra" */
8967 	}
8968 #endif /* CONFIG_TESTING_OPTIONS */
8969 	wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
8970 
8971 	buf = dpp_build_conf_req(auth, json);
8972 	if (!buf) {
8973 		wpa_printf(MSG_DEBUG,
8974 			   "DPP: No configuration request data available");
8975 		return;
8976 	}
8977 
8978 	wpabuf_free(conn->msg_out);
8979 	conn->msg_out_pos = 0;
8980 	conn->msg_out = wpabuf_alloc(4 + wpabuf_len(buf) - 1);
8981 	if (!conn->msg_out) {
8982 		wpabuf_free(buf);
8983 		return;
8984 	}
8985 	wpabuf_put_be32(conn->msg_out, wpabuf_len(buf) - 1);
8986 	wpabuf_put_data(conn->msg_out, wpabuf_head_u8(buf) + 1,
8987 			wpabuf_len(buf) - 1);
8988 	wpabuf_free(buf);
8989 
8990 	if (dpp_tcp_send(conn) == 1) {
8991 		if (!conn->write_eloop) {
8992 			if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
8993 						dpp_conn_tx_ready,
8994 						conn, NULL) < 0)
8995 				return;
8996 			conn->write_eloop = 1;
8997 		}
8998 	}
8999 }
9000 
9001 
dpp_controller_auth_success(struct dpp_connection * conn,int initiator)9002 static void dpp_controller_auth_success(struct dpp_connection *conn,
9003 					int initiator)
9004 {
9005 	struct dpp_authentication *auth = conn->auth;
9006 
9007 	if (!auth)
9008 		return;
9009 
9010 	wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
9011 	wpa_msg(conn->global->msg_ctx, MSG_INFO,
9012 		DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
9013 #ifdef CONFIG_TESTING_OPTIONS
9014 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
9015 		wpa_printf(MSG_INFO,
9016 			   "DPP: TESTING - stop at Authentication Confirm");
9017 		if (auth->configurator) {
9018 			/* Prevent GAS response */
9019 			auth->auth_success = 0;
9020 		}
9021 		return;
9022 	}
9023 #endif /* CONFIG_TESTING_OPTIONS */
9024 
9025 	if (!auth->configurator)
9026 		dpp_controller_start_gas_client(conn);
9027 }
9028 
9029 
dpp_conn_tx_ready(int sock,void * eloop_ctx,void * sock_ctx)9030 static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
9031 {
9032 	struct dpp_connection *conn = eloop_ctx;
9033 
9034 	wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
9035 	dpp_tcp_send(conn);
9036 }
9037 
9038 
dpp_ipaddr_to_sockaddr(struct sockaddr * addr,socklen_t * addrlen,const struct hostapd_ip_addr * ipaddr,int port)9039 static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
9040 				  const struct hostapd_ip_addr *ipaddr,
9041 				  int port)
9042 {
9043 	struct sockaddr_in *dst;
9044 #ifdef CONFIG_IPV6
9045 	struct sockaddr_in6 *dst6;
9046 #endif /* CONFIG_IPV6 */
9047 
9048 	switch (ipaddr->af) {
9049 	case AF_INET:
9050 		dst = (struct sockaddr_in *) addr;
9051 		os_memset(dst, 0, sizeof(*dst));
9052 		dst->sin_family = AF_INET;
9053 		dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
9054 		dst->sin_port = htons(port);
9055 		*addrlen = sizeof(*dst);
9056 		break;
9057 #ifdef CONFIG_IPV6
9058 	case AF_INET6:
9059 		dst6 = (struct sockaddr_in6 *) addr;
9060 		os_memset(dst6, 0, sizeof(*dst6));
9061 		dst6->sin6_family = AF_INET6;
9062 		os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
9063 			  sizeof(struct in6_addr));
9064 		dst6->sin6_port = htons(port);
9065 		*addrlen = sizeof(*dst6);
9066 		break;
9067 #endif /* CONFIG_IPV6 */
9068 	default:
9069 		return -1;
9070 	}
9071 
9072 	return 0;
9073 }
9074 
9075 
9076 static struct dpp_connection *
dpp_relay_new_conn(struct dpp_relay_controller * ctrl,const u8 * src,unsigned int freq)9077 dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
9078 		   unsigned int freq)
9079 {
9080 	struct dpp_connection *conn;
9081 	struct sockaddr_storage addr;
9082 	socklen_t addrlen;
9083 	char txt[100];
9084 
9085 	if (dl_list_len(&ctrl->conn) >= 15) {
9086 		wpa_printf(MSG_DEBUG,
9087 			   "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
9088 		return NULL;
9089 	}
9090 
9091 	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
9092 				   &ctrl->ipaddr, DPP_TCP_PORT) < 0)
9093 		return NULL;
9094 
9095 	conn = os_zalloc(sizeof(*conn));
9096 	if (!conn)
9097 		return NULL;
9098 
9099 	conn->global = ctrl->global;
9100 	conn->relay = ctrl;
9101 	os_memcpy(conn->mac_addr, src, ETH_ALEN);
9102 	conn->freq = freq;
9103 
9104 	conn->sock = socket(AF_INET, SOCK_STREAM, 0);
9105 	if (conn->sock < 0)
9106 		goto fail;
9107 	wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
9108 		   conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
9109 
9110 	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9111 		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9112 			   strerror(errno));
9113 		goto fail;
9114 	}
9115 
9116 	if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
9117 		if (errno != EINPROGRESS) {
9118 			wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
9119 				   strerror(errno));
9120 			goto fail;
9121 		}
9122 
9123 		/*
9124 		 * Continue connecting in the background; eloop will call us
9125 		 * once the connection is ready (or failed).
9126 		 */
9127 	}
9128 
9129 	if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9130 				dpp_conn_tx_ready, conn, NULL) < 0)
9131 		goto fail;
9132 	conn->write_eloop = 1;
9133 
9134 	/* TODO: eloop timeout to clear a connection if it does not complete
9135 	 * properly */
9136 
9137 	dl_list_add(&ctrl->conn, &conn->list);
9138 	return conn;
9139 fail:
9140 	dpp_connection_free(conn);
9141 	return NULL;
9142 }
9143 
9144 
dpp_tcp_encaps(const u8 * hdr,const u8 * buf,size_t len)9145 static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
9146 {
9147 	struct wpabuf *msg;
9148 
9149 	msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
9150 	if (!msg)
9151 		return NULL;
9152 	wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
9153 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
9154 	wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
9155 	wpabuf_put_data(msg, buf, len);
9156 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
9157 	return msg;
9158 }
9159 
9160 
dpp_relay_tx(struct dpp_connection * conn,const u8 * hdr,const u8 * buf,size_t len)9161 static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
9162 			const u8 *buf, size_t len)
9163 {
9164 	u8 type = hdr[DPP_HDR_LEN - 1];
9165 
9166 	wpa_printf(MSG_DEBUG,
9167 		   "DPP: Continue already established Relay/Controller connection for this session");
9168 	wpabuf_free(conn->msg_out);
9169 	conn->msg_out_pos = 0;
9170 	conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
9171 	if (!conn->msg_out) {
9172 		dpp_connection_remove(conn);
9173 		return -1;
9174 	}
9175 
9176 	/* TODO: for proto ver 1, need to do remove connection based on GAS Resp
9177 	 * TX status */
9178 	if (type == DPP_PA_CONFIGURATION_RESULT)
9179 		conn->on_tcp_tx_complete_remove = 1;
9180 	dpp_tcp_send(conn);
9181 	return 0;
9182 }
9183 
9184 
dpp_relay_rx_action(struct dpp_global * dpp,const u8 * src,const u8 * hdr,const u8 * buf,size_t len,unsigned int freq,const u8 * i_bootstrap,const u8 * r_bootstrap)9185 int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
9186 			const u8 *buf, size_t len, unsigned int freq,
9187 			const u8 *i_bootstrap, const u8 *r_bootstrap)
9188 {
9189 	struct dpp_relay_controller *ctrl;
9190 	struct dpp_connection *conn;
9191 	u8 type = hdr[DPP_HDR_LEN - 1];
9192 
9193 	/* Check if there is an already started session for this peer and if so,
9194 	 * continue that session (send this over TCP) and return 0.
9195 	 */
9196 	if (type != DPP_PA_PEER_DISCOVERY_REQ &&
9197 	    type != DPP_PA_PEER_DISCOVERY_RESP) {
9198 		dl_list_for_each(ctrl, &dpp->controllers,
9199 				 struct dpp_relay_controller, list) {
9200 			dl_list_for_each(conn, &ctrl->conn,
9201 					 struct dpp_connection, list) {
9202 				if (os_memcmp(src, conn->mac_addr,
9203 					      ETH_ALEN) == 0)
9204 					return dpp_relay_tx(conn, hdr, buf, len);
9205 			}
9206 		}
9207 	}
9208 
9209 	if (!r_bootstrap)
9210 		return -1;
9211 
9212 	ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
9213 	if (!ctrl)
9214 		return -1;
9215 
9216 	wpa_printf(MSG_DEBUG,
9217 		   "DPP: Authentication Request for a configured Controller");
9218 	conn = dpp_relay_new_conn(ctrl, src, freq);
9219 	if (!conn)
9220 		return -1;
9221 
9222 	conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
9223 	if (!conn->msg_out) {
9224 		dpp_connection_remove(conn);
9225 		return -1;
9226 	}
9227 	/* Message will be sent in dpp_conn_tx_ready() */
9228 
9229 	return 0;
9230 }
9231 
9232 
dpp_relay_rx_gas_req(struct dpp_global * dpp,const u8 * src,const u8 * data,size_t data_len)9233 int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
9234 			 size_t data_len)
9235 {
9236 	struct dpp_relay_controller *ctrl;
9237 	struct dpp_connection *conn, *found = NULL;
9238 	struct wpabuf *msg;
9239 
9240 	/* Check if there is a successfully completed authentication for this
9241 	 * and if so, continue that session (send this over TCP) and return 0.
9242 	 */
9243 	dl_list_for_each(ctrl, &dpp->controllers,
9244 			 struct dpp_relay_controller, list) {
9245 		if (found)
9246 			break;
9247 		dl_list_for_each(conn, &ctrl->conn,
9248 				 struct dpp_connection, list) {
9249 			if (os_memcmp(src, conn->mac_addr,
9250 				      ETH_ALEN) == 0) {
9251 				found = conn;
9252 				break;
9253 			}
9254 		}
9255 	}
9256 
9257 	if (!found)
9258 		return -1;
9259 
9260 	msg = wpabuf_alloc(4 + 1 + data_len);
9261 	if (!msg)
9262 		return -1;
9263 	wpabuf_put_be32(msg, 1 + data_len);
9264 	wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
9265 	wpabuf_put_data(msg, data, data_len);
9266 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
9267 
9268 	wpabuf_free(conn->msg_out);
9269 	conn->msg_out_pos = 0;
9270 	conn->msg_out = msg;
9271 	dpp_tcp_send(conn);
9272 	return 0;
9273 }
9274 
9275 
dpp_controller_free(struct dpp_controller * ctrl)9276 static void dpp_controller_free(struct dpp_controller *ctrl)
9277 {
9278 	struct dpp_connection *conn, *tmp;
9279 
9280 	if (!ctrl)
9281 		return;
9282 
9283 	dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
9284 			      list)
9285 		dpp_connection_remove(conn);
9286 
9287 	if (ctrl->sock >= 0) {
9288 		close(ctrl->sock);
9289 		eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
9290 	}
9291 	os_free(ctrl->configurator_params);
9292 	os_free(ctrl);
9293 }
9294 
9295 
dpp_controller_rx_auth_req(struct dpp_connection * conn,const u8 * hdr,const u8 * buf,size_t len)9296 static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
9297 				      const u8 *hdr, const u8 *buf, size_t len)
9298 {
9299 	const u8 *r_bootstrap, *i_bootstrap;
9300 	u16 r_bootstrap_len, i_bootstrap_len;
9301 	struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
9302 
9303 	if (!conn->ctrl)
9304 		return 0;
9305 
9306 	wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
9307 
9308 	r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
9309 				   &r_bootstrap_len);
9310 	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
9311 		wpa_printf(MSG_INFO,
9312 			   "Missing or invalid required Responder Bootstrapping Key Hash attribute");
9313 		return -1;
9314 	}
9315 	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
9316 		    r_bootstrap, r_bootstrap_len);
9317 
9318 	i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
9319 				   &i_bootstrap_len);
9320 	if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
9321 		wpa_printf(MSG_INFO,
9322 			   "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
9323 		return -1;
9324 	}
9325 	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
9326 		    i_bootstrap, i_bootstrap_len);
9327 
9328 	/* Try to find own and peer bootstrapping key matches based on the
9329 	 * received hash values */
9330 	dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
9331 				&own_bi, &peer_bi);
9332 	if (!own_bi) {
9333 		wpa_printf(MSG_INFO,
9334 			"No matching own bootstrapping key found - ignore message");
9335 		return -1;
9336 	}
9337 
9338 	if (conn->auth) {
9339 		wpa_printf(MSG_INFO,
9340 			   "Already in DPP authentication exchange - ignore new one");
9341 		return 0;
9342 	}
9343 
9344 	conn->auth = dpp_auth_req_rx(conn->ctrl->global->msg_ctx,
9345 				     conn->ctrl->allowed_roles,
9346 				     conn->ctrl->qr_mutual,
9347 				     peer_bi, own_bi, -1, hdr, buf, len);
9348 	if (!conn->auth) {
9349 		wpa_printf(MSG_DEBUG, "DPP: No response generated");
9350 		return -1;
9351 	}
9352 
9353 	if (dpp_set_configurator(conn->ctrl->global, conn->ctrl->global->msg_ctx,
9354 				 conn->auth,
9355 				 conn->ctrl->configurator_params) < 0) {
9356 		dpp_connection_remove(conn);
9357 		return -1;
9358 	}
9359 
9360 	wpabuf_free(conn->msg_out);
9361 	conn->msg_out_pos = 0;
9362 	conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->resp_msg) - 1);
9363 	if (!conn->msg_out)
9364 		return -1;
9365 	wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->resp_msg) - 1);
9366 	wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->resp_msg) + 1,
9367 			wpabuf_len(conn->auth->resp_msg) - 1);
9368 
9369 	if (dpp_tcp_send(conn) == 1) {
9370 		if (!conn->write_eloop) {
9371 			if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9372 						dpp_conn_tx_ready,
9373 						conn, NULL) < 0)
9374 				return -1;
9375 			conn->write_eloop = 1;
9376 		}
9377 	}
9378 
9379 	return 0;
9380 }
9381 
9382 
dpp_controller_rx_auth_resp(struct dpp_connection * conn,const u8 * hdr,const u8 * buf,size_t len)9383 static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
9384 				       const u8 *hdr, const u8 *buf, size_t len)
9385 {
9386 	struct dpp_authentication *auth = conn->auth;
9387 	struct wpabuf *msg;
9388 
9389 	if (!auth)
9390 		return -1;
9391 
9392 	wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
9393 
9394 	msg = dpp_auth_resp_rx(auth, hdr, buf, len);
9395 	if (!msg) {
9396 		if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
9397 			wpa_printf(MSG_DEBUG,
9398 				   "DPP: Start wait for full response");
9399 			return -1;
9400 		}
9401 		wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
9402 		dpp_connection_remove(conn);
9403 		return -1;
9404 	}
9405 
9406 	wpabuf_free(conn->msg_out);
9407 	conn->msg_out_pos = 0;
9408 	conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
9409 	if (!conn->msg_out) {
9410 		wpabuf_free(msg);
9411 		return -1;
9412 	}
9413 	wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
9414 	wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
9415 			wpabuf_len(msg) - 1);
9416 	wpabuf_free(msg);
9417 
9418 	conn->on_tcp_tx_complete_auth_ok = 1;
9419 	if (dpp_tcp_send(conn) == 1) {
9420 		if (!conn->write_eloop) {
9421 			if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9422 						dpp_conn_tx_ready,
9423 						conn, NULL) < 0)
9424 				return -1;
9425 			conn->write_eloop = 1;
9426 		}
9427 	}
9428 
9429 	return 0;
9430 }
9431 
9432 
dpp_controller_rx_auth_conf(struct dpp_connection * conn,const u8 * hdr,const u8 * buf,size_t len)9433 static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
9434 				       const u8 *hdr, const u8 *buf, size_t len)
9435 {
9436 	struct dpp_authentication *auth = conn->auth;
9437 
9438 	wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
9439 
9440 	if (!auth) {
9441 		wpa_printf(MSG_DEBUG,
9442 			   "DPP: No DPP Authentication in progress - drop");
9443 		return -1;
9444 	}
9445 
9446 	if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
9447 		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
9448 		return -1;
9449 	}
9450 
9451 	dpp_controller_auth_success(conn, 0);
9452 	return 0;
9453 }
9454 
9455 
dpp_controller_rx_conf_result(struct dpp_connection * conn,const u8 * hdr,const u8 * buf,size_t len)9456 static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
9457 					 const u8 *hdr, const u8 *buf,
9458 					 size_t len)
9459 {
9460 	struct dpp_authentication *auth = conn->auth;
9461 	enum dpp_status_error status;
9462 
9463 	if (!conn->ctrl)
9464 		return 0;
9465 
9466 	wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
9467 
9468 	if (!auth || !auth->waiting_conf_result) {
9469 		wpa_printf(MSG_DEBUG,
9470 			   "DPP: No DPP Configuration waiting for result - drop");
9471 		return -1;
9472 	}
9473 
9474 	status = dpp_conf_result_rx(auth, hdr, buf, len);
9475 	if (status == DPP_STATUS_OK)
9476 		wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
9477 			DPP_EVENT_CONF_SENT);
9478 	else
9479 		wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
9480 			DPP_EVENT_CONF_FAILED);
9481 	return -1; /* to remove the completed connection */
9482 }
9483 
9484 
dpp_controller_rx_action(struct dpp_connection * conn,const u8 * msg,size_t len)9485 static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
9486 				    size_t len)
9487 {
9488 	const u8 *pos, *end;
9489 	u8 type;
9490 
9491 	wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
9492 	pos = msg;
9493 	end = msg + len;
9494 
9495 	if (end - pos < DPP_HDR_LEN ||
9496 	    WPA_GET_BE24(pos) != OUI_WFA ||
9497 	    pos[3] != DPP_OUI_TYPE) {
9498 		wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
9499 		return -1;
9500 	}
9501 
9502 	if (pos[4] != 1) {
9503 		wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
9504 			   pos[4]);
9505 		return -1;
9506 	}
9507 	type = pos[5];
9508 	wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
9509 	pos += DPP_HDR_LEN;
9510 
9511 	wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
9512 		    pos, end - pos);
9513 	if (dpp_check_attrs(pos, end - pos) < 0)
9514 		return -1;
9515 
9516 	if (conn->relay) {
9517 		wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
9518 		conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
9519 				conn->freq, msg, len);
9520 		return 0;
9521 	}
9522 
9523 	switch (type) {
9524 	case DPP_PA_AUTHENTICATION_REQ:
9525 		return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
9526 	case DPP_PA_AUTHENTICATION_RESP:
9527 		return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
9528 	case DPP_PA_AUTHENTICATION_CONF:
9529 		return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
9530 	case DPP_PA_CONFIGURATION_RESULT:
9531 		return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
9532 	default:
9533 		/* TODO: missing messages types */
9534 		wpa_printf(MSG_DEBUG,
9535 			   "DPP: Unsupported frame subtype %d", type);
9536 		return -1;
9537 	}
9538 }
9539 
9540 
dpp_controller_rx_gas_req(struct dpp_connection * conn,const u8 * msg,size_t len)9541 static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
9542 				     size_t len)
9543 {
9544 	const u8 *pos, *end, *next;
9545 	u8 dialog_token;
9546 	const u8 *adv_proto;
9547 	u16 slen;
9548 	struct wpabuf *resp, *buf;
9549 	struct dpp_authentication *auth = conn->auth;
9550 
9551 	if (len < 1 + 2)
9552 		return -1;
9553 
9554 	wpa_printf(MSG_DEBUG,
9555 		   "DPP: Received DPP Configuration Request over TCP");
9556 
9557 	if (!conn->ctrl || !auth || !auth->auth_success) {
9558 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
9559 		return -1;
9560 	}
9561 
9562 	pos = msg;
9563 	end = msg + len;
9564 
9565 	dialog_token = *pos++;
9566 	adv_proto = pos++;
9567 	slen = *pos++;
9568 	if (*adv_proto != WLAN_EID_ADV_PROTO ||
9569 	    slen > end - pos || slen < 2)
9570 		return -1;
9571 
9572 	next = pos + slen;
9573 	pos++; /* skip QueryRespLenLimit and PAME-BI */
9574 
9575 	if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
9576 	    pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
9577 	    pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
9578 		return -1;
9579 
9580 	pos = next;
9581 	/* Query Request */
9582 	if (end - pos < 2)
9583 		return -1;
9584 	slen = WPA_GET_LE16(pos);
9585 	pos += 2;
9586 	if (slen > end - pos)
9587 		return -1;
9588 
9589 	resp = dpp_conf_req_rx(auth, pos, slen);
9590 	if (!resp)
9591 		return -1;
9592 
9593 	buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp));
9594 	if (!buf) {
9595 		wpabuf_free(resp);
9596 		return -1;
9597 	}
9598 
9599 	wpabuf_put_be32(buf, 18 + wpabuf_len(resp));
9600 
9601 	wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP);
9602 	wpabuf_put_u8(buf, dialog_token);
9603 	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
9604 	wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
9605 
9606 	dpp_write_adv_proto(buf);
9607 	dpp_write_gas_query(buf, resp);
9608 	wpabuf_free(resp);
9609 
9610 	/* Send Config Response over TCP; GAS fragmentation is taken care of by
9611 	 * the Relay */
9612 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
9613 	wpabuf_free(conn->msg_out);
9614 	conn->msg_out_pos = 0;
9615 	conn->msg_out = buf;
9616 	conn->on_tcp_tx_complete_gas_done = 1;
9617 	dpp_tcp_send(conn);
9618 	return 0;
9619 }
9620 
9621 
dpp_tcp_rx_gas_resp(struct dpp_connection * conn,struct wpabuf * resp)9622 static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
9623 {
9624 	struct dpp_authentication *auth = conn->auth;
9625 	int res;
9626 	struct wpabuf *msg, *encaps;
9627 	enum dpp_status_error status;
9628 
9629 	wpa_printf(MSG_DEBUG,
9630 		   "DPP: Configuration Response for local stack from TCP");
9631 
9632 	res = dpp_conf_resp_rx(auth, resp);
9633 	wpabuf_free(resp);
9634 	if (res < 0) {
9635 		wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
9636 		return -1;
9637 	}
9638 
9639 	if (conn->global->process_conf_obj)
9640 		res = conn->global->process_conf_obj(conn->global->cb_ctx,
9641 						     auth);
9642 	else
9643 		res = 0;
9644 
9645 	if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
9646 		return -1;
9647 
9648 	wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
9649 	status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
9650 	msg = dpp_build_conf_result(auth, status);
9651 	if (!msg)
9652 		return -1;
9653 
9654 	encaps = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
9655 	if (!encaps) {
9656 		wpabuf_free(msg);
9657 		return -1;
9658 	}
9659 	wpabuf_put_be32(encaps, wpabuf_len(msg) - 1);
9660 	wpabuf_put_data(encaps, wpabuf_head_u8(msg) + 1, wpabuf_len(msg) - 1);
9661 	wpabuf_free(msg);
9662 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", encaps);
9663 
9664 	wpabuf_free(conn->msg_out);
9665 	conn->msg_out_pos = 0;
9666 	conn->msg_out = encaps;
9667 	conn->on_tcp_tx_complete_remove = 1;
9668 	dpp_tcp_send(conn);
9669 
9670 	/* This exchange will be terminated in the TX status handler */
9671 
9672 	return 0;
9673 }
9674 
9675 
dpp_rx_gas_resp(struct dpp_connection * conn,const u8 * msg,size_t len)9676 static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
9677 			   size_t len)
9678 {
9679 	struct wpabuf *buf;
9680 	u8 dialog_token;
9681 	const u8 *pos, *end, *next, *adv_proto;
9682 	u16 status, slen;
9683 
9684 	if (len < 5 + 2)
9685 		return -1;
9686 
9687 	wpa_printf(MSG_DEBUG,
9688 		   "DPP: Received DPP Configuration Response over TCP");
9689 
9690 	pos = msg;
9691 	end = msg + len;
9692 
9693 	dialog_token = *pos++;
9694 	status = WPA_GET_LE16(pos);
9695 	if (status != WLAN_STATUS_SUCCESS) {
9696 		wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
9697 		return -1;
9698 	}
9699 	pos += 2;
9700 	pos += 2; /* ignore GAS Comeback Delay */
9701 
9702 	adv_proto = pos++;
9703 	slen = *pos++;
9704 	if (*adv_proto != WLAN_EID_ADV_PROTO ||
9705 	    slen > end - pos || slen < 2)
9706 		return -1;
9707 
9708 	next = pos + slen;
9709 	pos++; /* skip QueryRespLenLimit and PAME-BI */
9710 
9711 	if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
9712 	    pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
9713 	    pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
9714 		return -1;
9715 
9716 	pos = next;
9717 	/* Query Response */
9718 	if (end - pos < 2)
9719 		return -1;
9720 	slen = WPA_GET_LE16(pos);
9721 	pos += 2;
9722 	if (slen > end - pos)
9723 		return -1;
9724 
9725 	buf = wpabuf_alloc(slen);
9726 	if (!buf)
9727 		return -1;
9728 	wpabuf_put_data(buf, pos, slen);
9729 
9730 	if (!conn->relay && !conn->ctrl)
9731 		return dpp_tcp_rx_gas_resp(conn, buf);
9732 
9733 	if (!conn->relay) {
9734 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
9735 		wpabuf_free(buf);
9736 		return -1;
9737 	}
9738 	wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
9739 	conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
9740 				 dialog_token, 0, buf);
9741 
9742 	return 0;
9743 }
9744 
9745 
dpp_controller_rx(int sd,void * eloop_ctx,void * sock_ctx)9746 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
9747 {
9748 	struct dpp_connection *conn = eloop_ctx;
9749 	int res;
9750 	const u8 *pos;
9751 
9752 	wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
9753 		   sd);
9754 
9755 	if (conn->msg_len_octets < 4) {
9756 		u32 msglen;
9757 
9758 		res = recv(sd, &conn->msg_len[conn->msg_len_octets],
9759 			   4 - conn->msg_len_octets, 0);
9760 		if (res < 0) {
9761 			wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
9762 				   strerror(errno));
9763 			dpp_connection_remove(conn);
9764 			return;
9765 		}
9766 		if (res == 0) {
9767 			wpa_printf(MSG_DEBUG,
9768 				   "DPP: No more data available over TCP");
9769 			dpp_connection_remove(conn);
9770 			return;
9771 		}
9772 		wpa_printf(MSG_DEBUG,
9773 			   "DPP: Received %d/%d octet(s) of message length field",
9774 			   res, (int) (4 - conn->msg_len_octets));
9775 		conn->msg_len_octets += res;
9776 
9777 		if (conn->msg_len_octets < 4) {
9778 			wpa_printf(MSG_DEBUG,
9779 				   "DPP: Need %d more octets of message length field",
9780 				   (int) (4 - conn->msg_len_octets));
9781 			return;
9782 		}
9783 
9784 		msglen = WPA_GET_BE32(conn->msg_len);
9785 		wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
9786 		if (msglen > 65535) {
9787 			wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
9788 			dpp_connection_remove(conn);
9789 			return;
9790 		}
9791 
9792 		wpabuf_free(conn->msg);
9793 		conn->msg = wpabuf_alloc(msglen);
9794 	}
9795 
9796 	if (!conn->msg) {
9797 		wpa_printf(MSG_DEBUG,
9798 			   "DPP: No buffer available for receiving the message");
9799 		dpp_connection_remove(conn);
9800 		return;
9801 	}
9802 
9803 	wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
9804 		   (unsigned int) wpabuf_tailroom(conn->msg));
9805 
9806 	res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
9807 	if (res < 0) {
9808 		wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
9809 		dpp_connection_remove(conn);
9810 		return;
9811 	}
9812 	if (res == 0) {
9813 		wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
9814 		dpp_connection_remove(conn);
9815 		return;
9816 	}
9817 	wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
9818 	wpabuf_put(conn->msg, res);
9819 
9820 	if (wpabuf_tailroom(conn->msg) > 0) {
9821 		wpa_printf(MSG_DEBUG,
9822 			   "DPP: Need %u more octets of message payload",
9823 			   (unsigned int) wpabuf_tailroom(conn->msg));
9824 		return;
9825 	}
9826 
9827 	conn->msg_len_octets = 0;
9828 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
9829 	if (wpabuf_len(conn->msg) < 1) {
9830 		dpp_connection_remove(conn);
9831 		return;
9832 	}
9833 
9834 	pos = wpabuf_head(conn->msg);
9835 	switch (*pos) {
9836 	case WLAN_PA_VENDOR_SPECIFIC:
9837 		if (dpp_controller_rx_action(conn, pos + 1,
9838 					     wpabuf_len(conn->msg) - 1) < 0)
9839 			dpp_connection_remove(conn);
9840 		break;
9841 	case WLAN_PA_GAS_INITIAL_REQ:
9842 		if (dpp_controller_rx_gas_req(conn, pos + 1,
9843 					      wpabuf_len(conn->msg) - 1) < 0)
9844 			dpp_connection_remove(conn);
9845 		break;
9846 	case WLAN_PA_GAS_INITIAL_RESP:
9847 		if (dpp_rx_gas_resp(conn, pos + 1,
9848 				    wpabuf_len(conn->msg) - 1) < 0)
9849 			dpp_connection_remove(conn);
9850 		break;
9851 	default:
9852 		wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
9853 			   *pos);
9854 		break;
9855 	}
9856 }
9857 
9858 
dpp_controller_tcp_cb(int sd,void * eloop_ctx,void * sock_ctx)9859 static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
9860 {
9861 	struct dpp_controller *ctrl = eloop_ctx;
9862 	struct sockaddr_in addr;
9863 	socklen_t addr_len = sizeof(addr);
9864 	int fd;
9865 	struct dpp_connection *conn;
9866 
9867 	wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
9868 
9869 	fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
9870 	if (fd < 0) {
9871 		wpa_printf(MSG_DEBUG,
9872 			   "DPP: Failed to accept new connection: %s",
9873 			   strerror(errno));
9874 		return;
9875 	}
9876 	wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
9877 		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
9878 
9879 	conn = os_zalloc(sizeof(*conn));
9880 	if (!conn)
9881 		goto fail;
9882 
9883 	conn->global = ctrl->global;
9884 	conn->ctrl = ctrl;
9885 	conn->sock = fd;
9886 
9887 	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9888 		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9889 			   strerror(errno));
9890 		goto fail;
9891 	}
9892 
9893 	if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
9894 				dpp_controller_rx, conn, NULL) < 0)
9895 		goto fail;
9896 	conn->read_eloop = 1;
9897 
9898 	/* TODO: eloop timeout to expire connections that do not complete in
9899 	 * reasonable time */
9900 	dl_list_add(&ctrl->conn, &conn->list);
9901 	return;
9902 
9903 fail:
9904 	close(fd);
9905 	os_free(conn);
9906 }
9907 
9908 
dpp_tcp_init(struct dpp_global * dpp,struct dpp_authentication * auth,const struct hostapd_ip_addr * addr,int port)9909 int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
9910 		 const struct hostapd_ip_addr *addr, int port)
9911 {
9912 	struct dpp_connection *conn;
9913 	struct sockaddr_storage saddr;
9914 	socklen_t addrlen;
9915 	const u8 *hdr, *pos, *end;
9916 	char txt[100];
9917 
9918 	wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
9919 		   hostapd_ip_txt(addr, txt, sizeof(txt)), port);
9920 	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
9921 				   addr, port) < 0) {
9922 		dpp_auth_deinit(auth);
9923 		return -1;
9924 	}
9925 
9926 	conn = os_zalloc(sizeof(*conn));
9927 	if (!conn) {
9928 		dpp_auth_deinit(auth);
9929 		return -1;
9930 	}
9931 
9932 	conn->global = dpp;
9933 	conn->auth = auth;
9934 	conn->sock = socket(AF_INET, SOCK_STREAM, 0);
9935 	if (conn->sock < 0)
9936 		goto fail;
9937 
9938 	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
9939 		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
9940 			   strerror(errno));
9941 		goto fail;
9942 	}
9943 
9944 	if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
9945 		if (errno != EINPROGRESS) {
9946 			wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
9947 				   strerror(errno));
9948 			goto fail;
9949 		}
9950 
9951 		/*
9952 		 * Continue connecting in the background; eloop will call us
9953 		 * once the connection is ready (or failed).
9954 		 */
9955 	}
9956 
9957 	if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
9958 				dpp_conn_tx_ready, conn, NULL) < 0)
9959 		goto fail;
9960 	conn->write_eloop = 1;
9961 
9962 	hdr = wpabuf_head(auth->req_msg);
9963 	end = hdr + wpabuf_len(auth->req_msg);
9964 	hdr += 2; /* skip Category and Actiom */
9965 	pos = hdr + DPP_HDR_LEN;
9966 	conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
9967 	if (!conn->msg_out)
9968 		goto fail;
9969 	/* Message will be sent in dpp_conn_tx_ready() */
9970 
9971 	/* TODO: eloop timeout to clear a connection if it does not complete
9972 	 * properly */
9973 	dl_list_add(&dpp->tcp_init, &conn->list);
9974 	return 0;
9975 fail:
9976 	dpp_connection_free(conn);
9977 	return -1;
9978 }
9979 
9980 
dpp_controller_start(struct dpp_global * dpp,struct dpp_controller_config * config)9981 int dpp_controller_start(struct dpp_global *dpp,
9982 			 struct dpp_controller_config *config)
9983 {
9984 	struct dpp_controller *ctrl;
9985 	int on = 1;
9986 	struct sockaddr_in sin;
9987 	int port;
9988 
9989 	if (!dpp || dpp->controller)
9990 		return -1;
9991 
9992 	ctrl = os_zalloc(sizeof(*ctrl));
9993 	if (!ctrl)
9994 		return -1;
9995 	ctrl->global = dpp;
9996 	if (config->configurator_params)
9997 		ctrl->configurator_params =
9998 			os_strdup(config->configurator_params);
9999 	dl_list_init(&ctrl->conn);
10000 	/* TODO: configure these somehow */
10001 	ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
10002 	ctrl->qr_mutual = 0;
10003 
10004 	ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
10005 	if (ctrl->sock < 0)
10006 		goto fail;
10007 
10008 	if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
10009 		       &on, sizeof(on)) < 0) {
10010 		wpa_printf(MSG_DEBUG,
10011 			   "DPP: setsockopt(SO_REUSEADDR) failed: %s",
10012 			   strerror(errno));
10013 		/* try to continue anyway */
10014 	}
10015 
10016 	if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
10017 		wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
10018 			   strerror(errno));
10019 		goto fail;
10020 	}
10021 
10022 	/* TODO: IPv6 */
10023 	os_memset(&sin, 0, sizeof(sin));
10024 	sin.sin_family = AF_INET;
10025 	sin.sin_addr.s_addr = INADDR_ANY;
10026 	port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
10027 	sin.sin_port = htons(port);
10028 	if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
10029 		wpa_printf(MSG_INFO,
10030 			   "DPP: Failed to bind Controller TCP port: %s",
10031 			   strerror(errno));
10032 		goto fail;
10033 	}
10034 	if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
10035 	    fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
10036 	    eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
10037 				dpp_controller_tcp_cb, ctrl, NULL))
10038 		goto fail;
10039 
10040 	dpp->controller = ctrl;
10041 	wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
10042 	return 0;
10043 fail:
10044 	dpp_controller_free(ctrl);
10045 	return -1;
10046 }
10047 
10048 
dpp_controller_stop(struct dpp_global * dpp)10049 void dpp_controller_stop(struct dpp_global *dpp)
10050 {
10051 	if (dpp) {
10052 		dpp_controller_free(dpp->controller);
10053 		dpp->controller = NULL;
10054 	}
10055 }
10056 
10057 #endif /* CONFIG_DPP2 */
10058