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
37enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
38u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
39u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
40u8 dpp_pkex_ephemeral_key_override[600];
41size_t dpp_pkex_ephemeral_key_override_len = 0;
42u8 dpp_protocol_key_override[600];
43size_t dpp_protocol_key_override_len = 0;
44u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
45size_t dpp_nonce_override_len = 0;
46
47static 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
56static 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
64static 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
76struct 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 */
98struct 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 */
112struct 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
121struct 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
134static 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 */
150static 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 };
156static 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 };
162static 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};
168static 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 */
176static 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};
184static 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};
192static 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};
200static 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 */
210static 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};
221static 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};
232static 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};
243static 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 */
256static 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};
262static 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};
268static 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};
274static 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 */
282static 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};
290static 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};
298static 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};
306static 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 */
316static 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};
326static 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};
336static 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};
346static 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
358static 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
382fail:
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
391static 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
405static 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
424static 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
441static 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
454static 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
468static 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
515static 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
570out:
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;
577fail:
578	EVP_PKEY_free(pkey);
579	pkey = NULL;
580	goto out;
581}
582
583
584static 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
613static 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
689done:
690	ret = 0;
691
692fail:
693	EVP_PKEY_CTX_free(ctx);
694	return ret;
695}
696
697
698static 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
704struct 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
722const 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
745int 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
787void 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
798const 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
810static 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
823static 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
830int 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;
876fail:
877	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
878	return -1;
879}
880
881
882int 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
898int 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
923static const struct dpp_curve_params *
924dpp_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
938static 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
953static 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;
1086fail:
1087	X509_PUBKEY_free(pub);
1088	EVP_PKEY_free(pkey);
1089	return -1;
1090}
1091
1092
1093static 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
1157struct 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
1168static 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
1222static 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
1263fail:
1264	EC_KEY_free(ec_params);
1265	EVP_PKEY_free(params);
1266	EVP_PKEY_CTX_free(kctx);
1267	return key;
1268}
1269
1270
1271static const struct dpp_curve_params *
1272dpp_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
1286static const struct dpp_curve_params *
1287dpp_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
1300static 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
1345typedef 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
1353ASN1_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
1358IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
1359
1360
1361static 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);
1419fail:
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
1428int 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
1454char * 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;
1512fail:
1513	os_free(base64);
1514	wpabuf_free(der);
1515	return NULL;
1516}
1517
1518
1519static 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
1547static 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
1576static 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
1635static 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
1645static 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
1657static 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
1669static 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
1777skip_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	}
1796skip_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	}
1831skip_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
1841static 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	}
1971skip_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	}
2014skip_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
2023static 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
2050static 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
2061static 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
2077static 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
2101static 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
2141static 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
2181static 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;
2213fail:
2214	os_free(pk);
2215	dpp_bootstrap_info_free(bi);
2216	return -1;
2217}
2218
2219
2220struct 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
2351out:
2352	wpabuf_free(pi);
2353	return auth;
2354fail:
2355	dpp_auth_deinit(auth);
2356	auth = NULL;
2357	goto out;
2358}
2359
2360
2361static 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
2417skip_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
2430skip_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	}
2451skip_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
2459fail:
2460	wpabuf_free(clear);
2461	wpabuf_free(msg);
2462	return NULL;
2463}
2464
2465
2466static 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
2480static 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
2488struct 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
2515static 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
2532static 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);
2602fail:
2603	wpabuf_free(pix);
2604	wpabuf_free(prx);
2605	wpabuf_free(bix);
2606	wpabuf_free(brx);
2607	return res;
2608}
2609
2610
2611static 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);
2685fail:
2686	wpabuf_free(pix);
2687	wpabuf_free(prx);
2688	wpabuf_free(bix);
2689	wpabuf_free(brx);
2690	return res;
2691}
2692
2693
2694static 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;
2748fail:
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
2761static 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;
2810fail:
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
2822static 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;
3000fail:
3001	wpabuf_free(pr);
3002	return ret;
3003}
3004
3005
3006static 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
3071struct dpp_authentication *
3072dpp_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
3317not_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;
3331fail:
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
3340int 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
3360static 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
3415skip_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		}
3490skip_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	}
3521skip_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
3532fail:
3533	wpabuf_free(msg);
3534	return NULL;
3535}
3536
3537
3538static void
3539dpp_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	}
3631fail:
3632	bin_clear_free(unwrapped, unwrapped_len);
3633}
3634
3635
3636struct wpabuf *
3637dpp_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
3961fail:
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
3969static 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
4034fail:
4035	bin_clear_free(unwrapped, unwrapped_len);
4036	return -1;
4037}
4038
4039
4040int 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;
4193fail:
4194	bin_clear_free(unwrapped, unwrapped_len);
4195	return -1;
4196}
4197
4198
4199static 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
4205struct 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;
4240fail:
4241	dpp_configuration_free(conf);
4242	return NULL;
4243}
4244
4245
4246int 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
4253int 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
4260int 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
4267int 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
4274int dpp_akm_ver2(enum dpp_akm akm)
4275{
4276	return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
4277}
4278
4279
4280int 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
4292void 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
4302static 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
4403fail:
4404	dpp_configuration_free(conf_sta);
4405	dpp_configuration_free(conf_ap);
4406	return -1;
4407}
4408
4409
4410static struct dpp_configurator *
4411dpp_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
4427int 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
4458void 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
4482static struct wpabuf *
4483dpp_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
4517static 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;
4549fail:
4550	wpabuf_free(pub);
4551	os_free(x);
4552	os_free(y);
4553	return ret;
4554}
4555
4556
4557static 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
4582static struct wpabuf *
4583dpp_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
4659skip_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
4779out:
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;
4788fail:
4789	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
4790	wpabuf_free(buf);
4791	buf = NULL;
4792	goto out;
4793}
4794
4795
4796static struct wpabuf *
4797dpp_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
4817static struct wpabuf *
4818dpp_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
4844static struct wpabuf *
4845dpp_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
4903skip_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
4917skip_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
4932skip_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	}
4956skip_wrapped_data:
4957#endif /* CONFIG_TESTING_OPTIONS */
4958
4959	wpa_hexdump_buf(MSG_DEBUG,
4960			"DPP: Configuration Response attributes", msg);
4961out:
4962	wpabuf_free(conf);
4963	wpabuf_free(clear);
4964
4965	return msg;
4966fail:
4967	wpabuf_free(msg);
4968	msg = NULL;
4969	goto out;
4970}
4971
4972
4973struct wpabuf *
4974dpp_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
5093fail:
5094	json_free(root);
5095	os_free(unwrapped);
5096	return resp;
5097}
5098
5099
5100static struct wpabuf *
5101dpp_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
5174fail:
5175	json_free(root);
5176	return kid;
5177}
5178
5179
5180static 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
5227static 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
5298fail:
5299	wpabuf_free(x);
5300	wpabuf_free(y);
5301
5302	return pkey;
5303}
5304
5305
5306int 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
5386static 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	}
5426skip_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;
5475fail:
5476	EVP_PKEY_free(key);
5477	json_free(root);
5478	return ret;
5479}
5480
5481
5482static 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
5514static 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
5528static 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
5550struct dpp_signed_connector_info {
5551	unsigned char *payload;
5552	size_t payload_len;
5553};
5554
5555static enum dpp_status_error
5556dpp_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;
5707fail:
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
5721static 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;
5787fail:
5788	EVP_PKEY_free(csign_pub);
5789	os_free(info.payload);
5790	return ret;
5791}
5792
5793
5794const 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
5815static 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
5833static 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;
5907fail:
5908	json_free(root);
5909	return ret;
5910}
5911
5912
5913int 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
6007fail:
6008	os_free(unwrapped);
6009	return ret;
6010}
6011
6012
6013#ifdef CONFIG_DPP2
6014enum 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
6090fail:
6091	bin_clear_free(unwrapped, unwrapped_len);
6092	return ret;
6093}
6094#endif /* CONFIG_DPP2 */
6095
6096
6097struct 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;
6146fail:
6147	wpabuf_free(clear);
6148	wpabuf_free(msg);
6149	return NULL;
6150}
6151
6152
6153void 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
6163int 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
6187struct dpp_configurator *
6188dpp_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;
6240out:
6241	wpabuf_free(csign_pub);
6242	return conf;
6243fail:
6244	dpp_configurator_free(conf);
6245	conf = NULL;
6246	goto out;
6247}
6248
6249
6250int 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));
6287fail:
6288	wpabuf_free(conf_obj);
6289	auth->peer_protocol_key = NULL;
6290	return ret;
6291}
6292
6293
6294static 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
6301static 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
6335static 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
6377static 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
6405static 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;
6438fail:
6439	wpabuf_free(nkx);
6440	wpabuf_free(pkx);
6441	return ret;
6442}
6443
6444
6445enum dpp_status_error
6446dpp_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;
6598fail:
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
6615static 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
6661static 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);
6729out:
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;
6738fail:
6739	EC_POINT_free(Qi);
6740	Qi = NULL;
6741	goto out;
6742}
6743
6744
6745static 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);
6813out:
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;
6822fail:
6823	EC_POINT_free(Qr);
6824	Qr = NULL;
6825	goto out;
6826}
6827
6828
6829#ifdef CONFIG_TESTING_OPTIONS
6830static 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;
6882fail:
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
6896static 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
6978skip_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
7015out:
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;
7025fail:
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
7033static 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
7039struct 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;
7073fail:
7074	dpp_pkex_free(pkex);
7075	return NULL;
7076}
7077
7078
7079static struct wpabuf *
7080dpp_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
7113skip_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
7153skip_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;
7162fail:
7163	wpabuf_free(msg);
7164	return NULL;
7165}
7166
7167
7168static 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
7227static 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
7253struct 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
7460out:
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;
7475fail:
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
7483static struct wpabuf *
7484dpp_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
7529skip_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
7550skip_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	}
7582skip_wrapped_data:
7583#endif /* CONFIG_TESTING_OPTIONS */
7584
7585out:
7586	wpabuf_free(clear);
7587	return msg;
7588
7589fail:
7590	wpabuf_free(msg);
7591	msg = NULL;
7592	goto out;
7593}
7594
7595
7596struct 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
7765out:
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;
7778fail:
7779	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
7780	goto out;
7781}
7782
7783
7784static struct wpabuf *
7785dpp_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
7830skip_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
7851skip_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	}
7883skip_wrapped_data:
7884#endif /* CONFIG_TESTING_OPTIONS */
7885
7886out:
7887	wpabuf_free(clear);
7888	return msg;
7889
7890fail:
7891	wpabuf_free(msg);
7892	msg = NULL;
7893	goto out;
7894}
7895
7896
7897struct 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
8048out:
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;
8055fail:
8056	wpa_printf(MSG_DEBUG,
8057		   "DPP: PKEX Commit-Reveal Request processing failed");
8058	goto out;
8059}
8060
8061
8062int 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;
8184out:
8185	wpabuf_free(B_pub);
8186	wpabuf_free(X_pub);
8187	wpabuf_free(Y_pub);
8188	os_free(unwrapped);
8189	return ret;
8190fail:
8191	goto out;
8192}
8193
8194
8195void 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
8212char * 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
8252out:
8253	os_free(signature);
8254	os_free(signed3);
8255	return tmp;
8256fail:
8257	os_free(tmp);
8258	tmp = NULL;
8259	goto out;
8260}
8261#endif /* CONFIG_TESTING_OPTIONS */
8262
8263
8264#ifdef CONFIG_DPP2
8265
8266struct 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;
8307fail:
8308	wpabuf_free(pub);
8309	dpp_pfs_free(pfs);
8310	return NULL;
8311}
8312
8313
8314int 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
8335void 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
8348static 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
8361static 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
8384struct 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
8402int 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;
8473fail:
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
8486struct dpp_bootstrap_info *
8487dpp_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
8502int 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
8518struct dpp_bootstrap_info *
8519dpp_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
8545const 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
8556int 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
8582void 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
8618static 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
8632int 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;
8660fail:
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
8669static 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
8692int 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
8708int 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
8723static 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
8739static void dpp_connection_remove(struct dpp_connection *conn)
8740{
8741	dl_list_del(&conn->list);
8742	dpp_connection_free(conn);
8743}
8744
8745
8746static 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
8756static 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
8767static 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
8784struct 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
8808void 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
8823void 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
8832static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
8833static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
8834static void dpp_controller_auth_success(struct dpp_connection *conn,
8835					int initiator);
8836
8837
8838int 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
8861static struct dpp_relay_controller *
8862dpp_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
8879static 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
8895static 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
8951static 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
9002static 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
9030static 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
9039static 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
9076static struct dpp_connection *
9077dpp_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;
9139fail:
9140	dpp_connection_free(conn);
9141	return NULL;
9142}
9143
9144
9145static 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
9161static 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
9185int 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
9233int 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
9276static 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
9296static 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
9383static 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
9433static 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
9456static 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
9485static 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
9541static 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
9622static 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
9676static 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
9746static 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
9859static 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
9903fail:
9904	close(fd);
9905	os_free(conn);
9906}
9907
9908
9909int 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;
9975fail:
9976	dpp_connection_free(conn);
9977	return -1;
9978}
9979
9980
9981int 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;
10043fail:
10044	dpp_controller_free(ctrl);
10045	return -1;
10046}
10047
10048
10049void 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