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