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