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