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