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