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