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