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