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