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