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 
13 #include "utils/common.h"
14 #include "utils/base64.h"
15 #include "utils/json.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/ieee802_11_defs.h"
18 #include "common/wpa_ctrl.h"
19 #include "crypto/crypto.h"
20 #include "crypto/random.h"
21 #include "crypto/aes.h"
22 #include "crypto/aes_siv.h"
23 #include "crypto/sha384.h"
24 #include "crypto/sha512.h"
25 #include "dpp.h"
26 
27 
28 #if OPENSSL_VERSION_NUMBER < 0x10100000L
29 /* Compatibility wrappers for older versions. */
30 
ECDSA_SIG_set0(ECDSA_SIG * sig,BIGNUM * r,BIGNUM * s)31 static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
32 {
33 	sig->r = r;
34 	sig->s = s;
35 	return 1;
36 }
37 
38 
ECDSA_SIG_get0(const ECDSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)39 static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
40 			   const BIGNUM **ps)
41 {
42 	if (pr)
43 		*pr = sig->r;
44 	if (ps)
45 		*ps = sig->s;
46 }
47 
48 #endif
49 
50 
51 static const struct dpp_curve_params dpp_curves[] = {
52 	/* The mandatory to support and the default NIST P-256 curve needs to
53 	 * be the first entry on this list. */
54 	{ "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
55 	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
56 	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
57 	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
58 	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
59 	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
60 	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
61 };
62 
63 
64 /* Role-specific elements for PKEX */
65 
66 /* NIST P-256 */
67 static const u8 pkex_init_x_p256[32] = {
68 	0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
69 	0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
70 	0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
71 	0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
72  };
73 static const u8 pkex_init_y_p256[32] = {
74 	0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
75 	0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
76 	0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
77 	0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
78  };
79 static const u8 pkex_resp_x_p256[32] = {
80 	0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
81 	0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
82 	0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
83 	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
84 };
85 static const u8 pkex_resp_y_p256[32] = {
86 	0x26, 0x04, 0x09, 0x45, 0x0a, 0x05, 0x20, 0xe7,
87 	0xa7, 0x27, 0xc1, 0x36, 0x76, 0x85, 0xca, 0x3e,
88 	0x42, 0x16, 0xf4, 0x89, 0x85, 0x34, 0x6e, 0xd5,
89 	0x17, 0xde, 0xc0, 0xb8, 0xad, 0xfd, 0xb2, 0x98
90 };
91 
92 /* NIST P-384 */
93 static const u8 pkex_init_x_p384[48] = {
94 	0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
95 	0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
96 	0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
97 	0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
98 	0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
99 	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
100 };
101 static const u8 pkex_init_y_p384[48] = {
102 	0x89, 0xd0, 0x97, 0x7b, 0x59, 0x4f, 0xa6, 0xd6,
103 	0x7c, 0x5d, 0x93, 0x5b, 0x93, 0xc4, 0x07, 0xa9,
104 	0x89, 0xee, 0xd5, 0xcd, 0x6f, 0x42, 0xf8, 0x38,
105 	0xc8, 0xc6, 0x62, 0x24, 0x69, 0x0c, 0xd4, 0x48,
106 	0xd8, 0x44, 0xd6, 0xc2, 0xe8, 0xcc, 0x62, 0x6b,
107 	0x3c, 0x25, 0x53, 0xba, 0x4f, 0x71, 0xf8, 0xe7
108 };
109 static const u8 pkex_resp_x_p384[48] = {
110 	0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
111 	0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
112 	0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
113 	0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
114 	0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
115 	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
116 };
117 static const u8 pkex_resp_y_p384[48] = {
118 	0x54, 0x58, 0x20, 0xad, 0x55, 0x1d, 0xca, 0xf3,
119 	0x1c, 0x8a, 0xcd, 0x19, 0x40, 0xf9, 0x37, 0x83,
120 	0xc7, 0xd6, 0xb3, 0x13, 0x7d, 0x53, 0x28, 0x5c,
121 	0xf6, 0x2d, 0xf1, 0xdd, 0xa5, 0x8b, 0xad, 0x5d,
122 	0x81, 0xab, 0xb1, 0x00, 0x39, 0xd6, 0xcc, 0x9c,
123 	0xea, 0x1e, 0x84, 0x1d, 0xbf, 0xe3, 0x35, 0xf9
124 };
125 
126 /* NIST P-521 */
127 static const u8 pkex_init_x_p521[66] = {
128 	0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
129 	0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
130 	0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
131 	0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
132 	0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
133 	0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
134 	0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
135 	0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
136 	0x97, 0x76
137 };
138 static const u8 pkex_init_y_p521[66] = {
139 	0x01, 0x4c, 0x71, 0xfd, 0x1b, 0xd5, 0x9c, 0xa6,
140 	0xed, 0x39, 0xef, 0x45, 0xc5, 0x06, 0xfd, 0x66,
141 	0xc0, 0xeb, 0x0f, 0xbf, 0x21, 0xa3, 0x36, 0x74,
142 	0xfd, 0xaa, 0x05, 0x6e, 0x4e, 0x33, 0x95, 0x42,
143 	0x1a, 0x9d, 0x3f, 0x3a, 0x1c, 0x5e, 0xa8, 0x60,
144 	0xf7, 0xe5, 0x59, 0x1d, 0x07, 0xaa, 0x6f, 0x40,
145 	0x0a, 0x59, 0x3c, 0x27, 0xad, 0xe0, 0x48, 0xfd,
146 	0xd1, 0x83, 0x37, 0x4c, 0xdf, 0xe1, 0x86, 0x72,
147 	0xfc, 0x57
148 };
149 static const u8 pkex_resp_x_p521[66] = {
150 	0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
151 	0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
152 	0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
153 	0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
154 	0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
155 	0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
156 	0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
157 	0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
158 	0x84, 0xb4
159 };
160 static const u8 pkex_resp_y_p521[66] = {
161 	0x01, 0xb9, 0x9c, 0xc6, 0x41, 0x32, 0x5b, 0xd2,
162 	0x35, 0xd8, 0x8b, 0x2b, 0xe4, 0x6e, 0xcc, 0xdf,
163 	0x7c, 0x38, 0xc4, 0x5b, 0xf6, 0x74, 0x71, 0x5c,
164 	0x77, 0x16, 0x8a, 0x80, 0xa9, 0x84, 0xc7, 0x7b,
165 	0x9d, 0xfd, 0x83, 0x6f, 0xae, 0xf8, 0x24, 0x16,
166 	0x2f, 0x21, 0x25, 0x65, 0xa2, 0x1a, 0x6b, 0x2d,
167 	0x30, 0x62, 0xb3, 0xcc, 0x6e, 0x59, 0x3c, 0x7f,
168 	0x58, 0x91, 0x81, 0x72, 0x07, 0x8c, 0x91, 0xac,
169 	0x31, 0x1e
170 };
171 
172 /* Brainpool P-256r1 */
173 static const u8 pkex_init_x_bp_p256r1[32] = {
174 	0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
175 	0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
176 	0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
177 	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
178 };
179 static const u8 pkex_init_y_bp_p256r1[32] = {
180 	0x16, 0x30, 0x68, 0x32, 0x3b, 0xb0, 0x21, 0xee,
181 	0xeb, 0xf7, 0xb6, 0x7c, 0xae, 0x52, 0x26, 0x42,
182 	0x59, 0x28, 0x58, 0xb6, 0x14, 0x90, 0xed, 0x69,
183 	0xd0, 0x67, 0xea, 0x25, 0x60, 0x0f, 0xa9, 0x6c
184 };
185 static const u8 pkex_resp_x_bp_p256r1[32] = {
186 	0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
187 	0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
188 	0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
189 	0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
190 };
191 static const u8 pkex_resp_y_bp_p256r1[32] = {
192 	0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
193 	0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
194 	0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
195 	0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
196 };
197 
198 /* Brainpool P-384r1 */
199 static const u8 pkex_init_x_bp_p384r1[48] = {
200 	0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
201 	0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
202 	0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
203 	0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
204 	0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
205 	0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
206 };
207 static const u8 pkex_init_y_bp_p384r1[48] = {
208 	0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
209 	0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
210 	0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
211 	0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
212 	0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
213 	0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
214 };
215 static const u8 pkex_resp_x_bp_p384r1[48] = {
216 	0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
217 	0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
218 	0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
219 	0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
220 	0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
221 	0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
222 };
223 static const u8 pkex_resp_y_bp_p384r1[48] = {
224 	0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
225 	0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
226 	0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
227 	0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
228 	0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
229 	0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
230 };
231 
232 /* Brainpool P-512r1 */
233 static const u8 pkex_init_x_bp_p512r1[64] = {
234 	0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
235 	0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
236 	0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
237 	0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
238 	0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
239 	0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
240 	0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
241 	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
242 };
243 static const u8 pkex_init_y_bp_p512r1[64] = {
244 	0x5a, 0x28, 0x01, 0xbe, 0x96, 0x82, 0x4e, 0xf6,
245 	0xfa, 0xed, 0x7d, 0xfd, 0x48, 0x8b, 0x48, 0x4e,
246 	0xd1, 0x97, 0x87, 0xc4, 0x05, 0x5d, 0x15, 0x2a,
247 	0xf4, 0x91, 0x4b, 0x75, 0x90, 0xd9, 0x34, 0x2c,
248 	0x3c, 0x12, 0xf2, 0xf5, 0x25, 0x94, 0x24, 0x34,
249 	0xa7, 0x6d, 0x66, 0xbc, 0x27, 0xa4, 0xa0, 0x8d,
250 	0xd5, 0xe1, 0x54, 0xa3, 0x55, 0x26, 0xd4, 0x14,
251 	0x17, 0x0f, 0xc1, 0xc7, 0x3d, 0x68, 0x7f, 0x5a
252 };
253 static const u8 pkex_resp_x_bp_p512r1[64] = {
254 	0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
255 	0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
256 	0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
257 	0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
258 	0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
259 	0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
260 	0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
261 	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
262 };
263 static const u8 pkex_resp_y_bp_p512r1[64] = {
264 	0x2a, 0xbe, 0x59, 0xe6, 0xc4, 0xb3, 0xd8, 0x09,
265 	0x66, 0x89, 0x0a, 0x2d, 0x19, 0xf0, 0x9c, 0x9f,
266 	0xb4, 0xab, 0x8f, 0x50, 0x68, 0x3c, 0x74, 0x64,
267 	0x4e, 0x19, 0x55, 0x81, 0x9b, 0x48, 0x5c, 0xf4,
268 	0x12, 0x8d, 0xb9, 0xd8, 0x02, 0x5b, 0xe1, 0x26,
269 	0x7e, 0x19, 0x5c, 0xfd, 0x70, 0xf7, 0x4b, 0xdc,
270 	0xb5, 0x5d, 0xc1, 0x7a, 0xe9, 0xd1, 0x05, 0x2e,
271 	0xd1, 0xfd, 0x2f, 0xce, 0x63, 0x77, 0x48, 0x2c
272 };
273 
274 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)275 static int dpp_hash_vector(const struct dpp_curve_params *curve,
276 			   size_t num_elem, const u8 *addr[], const size_t *len,
277 			   u8 *mac)
278 {
279 	if (curve->hash_len == 32)
280 		return sha256_vector(num_elem, addr, len, mac);
281 	if (curve->hash_len == 48)
282 		return sha384_vector(num_elem, addr, len, mac);
283 	if (curve->hash_len == 64)
284 		return sha512_vector(num_elem, addr, len, mac);
285 	return -1;
286 }
287 
288 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)289 static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
290 			   const char *label, u8 *out, size_t outlen)
291 {
292 	if (hash_len == 32)
293 		return hmac_sha256_kdf(secret, secret_len, NULL,
294 				       (const u8 *) label, os_strlen(label),
295 				       out, outlen);
296 	if (hash_len == 48)
297 		return hmac_sha384_kdf(secret, secret_len, NULL,
298 				       (const u8 *) label, os_strlen(label),
299 				       out, outlen);
300 	if (hash_len == 64)
301 		return hmac_sha512_kdf(secret, secret_len, NULL,
302 				       (const u8 *) label, os_strlen(label),
303 				       out, outlen);
304 	return -1;
305 }
306 
307 
dpp_hmac_vector(size_t hash_len,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)308 static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
309 			   size_t num_elem, const u8 *addr[],
310 			   const size_t *len, u8 *mac)
311 {
312 	if (hash_len == 32)
313 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
314 					  mac);
315 	if (hash_len == 48)
316 		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
317 					  mac);
318 	if (hash_len == 64)
319 		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
320 					  mac);
321 	return -1;
322 }
323 
324 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)325 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
326 		    const u8 *data, size_t data_len, u8 *mac)
327 {
328 	if (hash_len == 32)
329 		return hmac_sha256(key, key_len, data, data_len, mac);
330 	if (hash_len == 48)
331 		return hmac_sha384(key, key_len, data, data_len, mac);
332 	if (hash_len == 64)
333 		return hmac_sha512(key, key_len, data, data_len, mac);
334 	return -1;
335 }
336 
337 
dpp_get_pubkey_point(EVP_PKEY * pkey,int prefix)338 static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
339 {
340 	int len, res;
341 	EC_KEY *eckey;
342 	struct wpabuf *buf;
343 	unsigned char *pos;
344 
345 	eckey = EVP_PKEY_get1_EC_KEY(pkey);
346 	if (!eckey)
347 		return NULL;
348 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
349 	len = i2o_ECPublicKey(eckey, NULL);
350 	if (len <= 0) {
351 		wpa_printf(MSG_ERROR,
352 			   "DDP: Failed to determine public key encoding length");
353 		EC_KEY_free(eckey);
354 		return NULL;
355 	}
356 
357 	buf = wpabuf_alloc(len);
358 	if (!buf) {
359 		EC_KEY_free(eckey);
360 		return NULL;
361 	}
362 
363 	pos = wpabuf_put(buf, len);
364 	res = i2o_ECPublicKey(eckey, &pos);
365 	EC_KEY_free(eckey);
366 	if (res != len) {
367 		wpa_printf(MSG_ERROR,
368 			   "DDP: Failed to encode public key (res=%d/%d)",
369 			   res, len);
370 		wpabuf_free(buf);
371 		return NULL;
372 	}
373 
374 	if (!prefix) {
375 		/* Remove 0x04 prefix to match DPP definition */
376 		pos = wpabuf_mhead(buf);
377 		os_memmove(pos, pos + 1, len - 1);
378 		buf->used--;
379 	}
380 
381 	return buf;
382 }
383 
384 
dpp_set_pubkey_point_group(const EC_GROUP * group,const u8 * buf_x,const u8 * buf_y,size_t len)385 static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
386 					     const u8 *buf_x, const u8 *buf_y,
387 					     size_t len)
388 {
389 	EC_KEY *eckey = NULL;
390 	BN_CTX *ctx;
391 	EC_POINT *point = NULL;
392 	BIGNUM *x = NULL, *y = NULL;
393 	EVP_PKEY *pkey = NULL;
394 
395 	ctx = BN_CTX_new();
396 	if (!ctx) {
397 		wpa_printf(MSG_ERROR, "DPP: Out of memory");
398 		return NULL;
399 	}
400 
401 	point = EC_POINT_new(group);
402 	x = BN_bin2bn(buf_x, len, NULL);
403 	y = BN_bin2bn(buf_y, len, NULL);
404 	if (!point || !x || !y) {
405 		wpa_printf(MSG_ERROR, "DPP: Out of memory");
406 		goto fail;
407 	}
408 
409 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
410 		wpa_printf(MSG_ERROR,
411 			   "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
412 			   ERR_error_string(ERR_get_error(), NULL));
413 		goto fail;
414 	}
415 
416 	if (!EC_POINT_is_on_curve(group, point, ctx) ||
417 	    EC_POINT_is_at_infinity(group, point)) {
418 		wpa_printf(MSG_ERROR, "DPP: Invalid point");
419 		goto fail;
420 	}
421 
422 	eckey = EC_KEY_new();
423 	if (!eckey ||
424 	    EC_KEY_set_group(eckey, group) != 1 ||
425 	    EC_KEY_set_public_key(eckey, point) != 1) {
426 		wpa_printf(MSG_ERROR,
427 			   "DPP: Failed to set EC_KEY: %s",
428 			   ERR_error_string(ERR_get_error(), NULL));
429 		goto fail;
430 	}
431 	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
432 
433 	pkey = EVP_PKEY_new();
434 	if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
435 		wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
436 		goto fail;
437 	}
438 
439 out:
440 	BN_free(x);
441 	BN_free(y);
442 	EC_KEY_free(eckey);
443 	EC_POINT_free(point);
444 	BN_CTX_free(ctx);
445 	return pkey;
446 fail:
447 	EVP_PKEY_free(pkey);
448 	pkey = NULL;
449 	goto out;
450 }
451 
452 
dpp_set_pubkey_point(EVP_PKEY * group_key,const u8 * buf,size_t len)453 static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key,
454 				       const u8 *buf, size_t len)
455 {
456 	EC_KEY *eckey;
457 	const EC_GROUP *group;
458 	EVP_PKEY *pkey = NULL;
459 
460 	if (len & 1)
461 		return NULL;
462 
463 	eckey = EVP_PKEY_get1_EC_KEY(group_key);
464 	if (!eckey) {
465 		wpa_printf(MSG_ERROR,
466 			   "DPP: Could not get EC_KEY from group_key");
467 		return NULL;
468 	}
469 
470 	group = EC_KEY_get0_group(eckey);
471 	if (group)
472 		pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
473 						  len / 2);
474 	else
475 		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
476 
477 	EC_KEY_free(eckey);
478 	return pkey;
479 }
480 
481 
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)482 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
483 			      size_t len)
484 {
485 	struct wpabuf *msg;
486 
487 	msg = wpabuf_alloc(8 + len);
488 	if (!msg)
489 		return NULL;
490 	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
491 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
492 	wpabuf_put_be24(msg, OUI_WFA);
493 	wpabuf_put_u8(msg, DPP_OUI_TYPE);
494 	wpabuf_put_u8(msg, 1); /* Crypto Suite */
495 	wpabuf_put_u8(msg, type);
496 	return msg;
497 }
498 
499 
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)500 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
501 {
502 	u16 id, alen;
503 	const u8 *pos = buf, *end = buf + len;
504 
505 	while (end - pos >= 4) {
506 		id = WPA_GET_LE16(pos);
507 		pos += 2;
508 		alen = WPA_GET_LE16(pos);
509 		pos += 2;
510 		if (alen > end - pos)
511 			return NULL;
512 		if (id == req_id) {
513 			*ret_len = alen;
514 			return pos;
515 		}
516 		pos += alen;
517 	}
518 
519 	return NULL;
520 }
521 
522 
dpp_check_attrs(const u8 * buf,size_t len)523 int dpp_check_attrs(const u8 *buf, size_t len)
524 {
525 	const u8 *pos, *end;
526 
527 	pos = buf;
528 	end = buf + len;
529 	while (end - pos >= 4) {
530 		u16 id, alen;
531 
532 		id = WPA_GET_LE16(pos);
533 		pos += 2;
534 		alen = WPA_GET_LE16(pos);
535 		pos += 2;
536 		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
537 			   id, alen);
538 		if (alen > end - pos) {
539 			wpa_printf(MSG_DEBUG,
540 				   "DPP: Truncated message - not enough room for the attribute - dropped");
541 			return -1;
542 		}
543 		pos += alen;
544 	}
545 
546 	if (end != pos) {
547 		wpa_printf(MSG_DEBUG,
548 			   "DPP: Unexpected octets (%d) after the last attribute",
549 			   (int) (end - pos));
550 		return -1;
551 	}
552 
553 	return 0;
554 }
555 
556 
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)557 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
558 {
559 	if (!info)
560 		return;
561 	os_free(info->uri);
562 	os_free(info->info);
563 	EVP_PKEY_free(info->pubkey);
564 	os_free(info);
565 }
566 
567 
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)568 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
569 {
570 	switch (type) {
571 	case DPP_BOOTSTRAP_QR_CODE:
572 		return "QRCODE";
573 	case DPP_BOOTSTRAP_PKEX:
574 		return "PKEX";
575 	}
576 	return "??";
577 }
578 
579 
dpp_uri_valid_info(const char * info)580 static int dpp_uri_valid_info(const char *info)
581 {
582 	while (*info) {
583 		unsigned char val = *info++;
584 
585 		if (val < 0x20 || val > 0x7e || val == 0x3b)
586 			return 0;
587 	}
588 
589 	return 1;
590 }
591 
592 
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)593 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
594 {
595 	bi->uri = os_strdup(uri);
596 	return bi->uri ? 0 : -1;
597 }
598 
599 
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)600 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
601 			    const char *chan_list)
602 {
603 	const char *pos = chan_list;
604 	int opclass, channel, freq;
605 
606 	while (pos && *pos && *pos != ';') {
607 		opclass = atoi(pos);
608 		if (opclass <= 0)
609 			goto fail;
610 		pos = os_strchr(pos, '/');
611 		if (!pos)
612 			goto fail;
613 		pos++;
614 		channel = atoi(pos);
615 		if (channel <= 0)
616 			goto fail;
617 		while (*pos >= '0' && *pos <= '9')
618 			pos++;
619 		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
620 		wpa_printf(MSG_DEBUG,
621 			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
622 			   opclass, channel, freq);
623 		if (freq < 0) {
624 			wpa_printf(MSG_DEBUG,
625 				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
626 				   opclass, channel);
627 		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
628 			wpa_printf(MSG_DEBUG,
629 				   "DPP: Too many channels in URI channel-list - ignore list");
630 			bi->num_freq = 0;
631 			break;
632 		} else {
633 			bi->freq[bi->num_freq++] = freq;
634 		}
635 
636 		if (*pos == ';' || *pos == '\0')
637 			break;
638 		if (*pos != ',')
639 			goto fail;
640 		pos++;
641 	}
642 
643 	return 0;
644 fail:
645 	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
646 	return -1;
647 }
648 
649 
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)650 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
651 {
652 	if (!mac)
653 		return 0;
654 
655 	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
656 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
657 		return -1;
658 	}
659 
660 	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
661 
662 	return 0;
663 }
664 
665 
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)666 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
667 {
668 	const char *end;
669 
670 	if (!info)
671 		return 0;
672 
673 	end = os_strchr(info, ';');
674 	if (!end)
675 		end = info + os_strlen(info);
676 	bi->info = os_malloc(end - info + 1);
677 	if (!bi->info)
678 		return -1;
679 	os_memcpy(bi->info, info, end - info);
680 	bi->info[end - info] = '\0';
681 	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
682 	if (!dpp_uri_valid_info(bi->info)) {
683 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
684 		return -1;
685 	}
686 
687 	return 0;
688 }
689 
690 
691 static const struct dpp_curve_params *
dpp_get_curve_oid(const ASN1_OBJECT * poid)692 dpp_get_curve_oid(const ASN1_OBJECT *poid)
693 {
694 	ASN1_OBJECT *oid;
695 	int i;
696 
697 	for (i = 0; dpp_curves[i].name; i++) {
698 		oid = OBJ_txt2obj(dpp_curves[i].name, 0);
699 		if (oid && OBJ_cmp(poid, oid) == 0)
700 			return &dpp_curves[i];
701 	}
702 	return NULL;
703 }
704 
705 
dpp_get_curve_nid(int nid)706 static const struct dpp_curve_params * dpp_get_curve_nid(int nid)
707 {
708 	int i, tmp;
709 
710 	if (!nid)
711 		return NULL;
712 	for (i = 0; dpp_curves[i].name; i++) {
713 		tmp = OBJ_txt2nid(dpp_curves[i].name);
714 		if (tmp == nid)
715 			return &dpp_curves[i];
716 	}
717 	return NULL;
718 }
719 
720 
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)721 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
722 {
723 	const char *end;
724 	u8 *data;
725 	size_t data_len;
726 	EVP_PKEY *pkey;
727 	const unsigned char *p;
728 	int res;
729 	X509_PUBKEY *pub = NULL;
730 	ASN1_OBJECT *ppkalg;
731 	const unsigned char *pk;
732 	int ppklen;
733 	X509_ALGOR *pa;
734 #if OPENSSL_VERSION_NUMBER < 0x10100000L
735 	ASN1_OBJECT *pa_oid;
736 #else
737 	const ASN1_OBJECT *pa_oid;
738 #endif
739 	const void *pval;
740 	int ptype;
741 	const ASN1_OBJECT *poid;
742 	char buf[100];
743 
744 	end = os_strchr(info, ';');
745 	if (!end)
746 		return -1;
747 
748 	data = base64_decode((const unsigned char *) info, end - info,
749 			     &data_len);
750 	if (!data) {
751 		wpa_printf(MSG_DEBUG,
752 			   "DPP: Invalid base64 encoding on URI public-key");
753 		return -1;
754 	}
755 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
756 		    data, data_len);
757 
758 	if (sha256_vector(1, (const u8 **) &data, &data_len,
759 			  bi->pubkey_hash) < 0) {
760 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
761 		return -1;
762 	}
763 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
764 		    bi->pubkey_hash, SHA256_MAC_LEN);
765 
766 	/* DER encoded ASN.1 SubjectPublicKeyInfo
767 	 *
768 	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
769 	 *      algorithm            AlgorithmIdentifier,
770 	 *      subjectPublicKey     BIT STRING  }
771 	 *
772 	 * AlgorithmIdentifier  ::=  SEQUENCE  {
773 	 *      algorithm               OBJECT IDENTIFIER,
774 	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
775 	 *
776 	 * subjectPublicKey = compressed format public key per ANSI X9.63
777 	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
778 	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
779 	 *       prime256v1 (1.2.840.10045.3.1.7)
780 	 */
781 
782 	p = data;
783 	pkey = d2i_PUBKEY(NULL, &p, data_len);
784 	os_free(data);
785 
786 	if (!pkey) {
787 		wpa_printf(MSG_DEBUG,
788 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
789 		return -1;
790 	}
791 
792 	if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
793 		wpa_printf(MSG_DEBUG,
794 			   "DPP: SubjectPublicKeyInfo does not describe an EC key");
795 		EVP_PKEY_free(pkey);
796 		return -1;
797 	}
798 
799 	res = X509_PUBKEY_set(&pub, pkey);
800 	if (res != 1) {
801 		wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
802 		goto fail;
803 	}
804 
805 	res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
806 	if (res != 1) {
807 		wpa_printf(MSG_DEBUG,
808 			   "DPP: Could not extract SubjectPublicKeyInfo parameters");
809 		goto fail;
810 	}
811 	res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
812 	if (res < 0 || (size_t) res >= sizeof(buf)) {
813 		wpa_printf(MSG_DEBUG,
814 			   "DPP: Could not extract SubjectPublicKeyInfo algorithm");
815 		goto fail;
816 	}
817 	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
818 	if (os_strcmp(buf, "id-ecPublicKey") != 0) {
819 		wpa_printf(MSG_DEBUG,
820 			   "DPP: Unsupported SubjectPublicKeyInfo algorithm");
821 		goto fail;
822 	}
823 
824 	X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
825 	if (ptype != V_ASN1_OBJECT) {
826 		wpa_printf(MSG_DEBUG,
827 			   "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
828 		goto fail;
829 	}
830 	poid = pval;
831 	res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
832 	if (res < 0 || (size_t) res >= sizeof(buf)) {
833 		wpa_printf(MSG_DEBUG,
834 			   "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
835 		goto fail;
836 	}
837 	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
838 	bi->curve = dpp_get_curve_oid(poid);
839 	if (!bi->curve) {
840 		wpa_printf(MSG_DEBUG,
841 			   "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
842 			   buf);
843 		goto fail;
844 	}
845 
846 	wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
847 
848 	X509_PUBKEY_free(pub);
849 	bi->pubkey = pkey;
850 	return 0;
851 fail:
852 	X509_PUBKEY_free(pub);
853 	EVP_PKEY_free(pkey);
854 	return -1;
855 }
856 
857 
dpp_parse_uri(const char * uri)858 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
859 {
860 	const char *pos = uri;
861 	const char *end;
862 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
863 	struct dpp_bootstrap_info *bi;
864 
865 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
866 
867 	if (os_strncmp(pos, "DPP:", 4) != 0) {
868 		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
869 		return NULL;
870 	}
871 	pos += 4;
872 
873 	for (;;) {
874 		end = os_strchr(pos, ';');
875 		if (!end)
876 			break;
877 
878 		if (end == pos) {
879 			/* Handle terminating ";;" and ignore unexpected ";"
880 			 * for parsing robustness. */
881 			pos++;
882 			continue;
883 		}
884 
885 		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
886 			chan_list = pos + 2;
887 		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
888 			mac = pos + 2;
889 		else if (pos[0] == 'I' && pos[1] == ':' && !info)
890 			info = pos + 2;
891 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
892 			pk = pos + 2;
893 		else
894 			wpa_hexdump_ascii(MSG_DEBUG,
895 					  "DPP: Ignore unrecognized URI parameter",
896 					  pos, end - pos);
897 		pos = end + 1;
898 	}
899 
900 	if (!pk) {
901 		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
902 		return NULL;
903 	}
904 
905 	bi = os_zalloc(sizeof(*bi));
906 	if (!bi)
907 		return NULL;
908 
909 	if (dpp_clone_uri(bi, uri) < 0 ||
910 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
911 	    dpp_parse_uri_mac(bi, mac) < 0 ||
912 	    dpp_parse_uri_info(bi, info) < 0 ||
913 	    dpp_parse_uri_pk(bi, pk) < 0) {
914 		dpp_bootstrap_info_free(bi);
915 		bi = NULL;
916 	}
917 
918 	return bi;
919 }
920 
921 
dpp_parse_qr_code(const char * uri)922 struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
923 {
924 	struct dpp_bootstrap_info *bi;
925 
926 	bi = dpp_parse_uri(uri);
927 	if (bi)
928 		bi->type = DPP_BOOTSTRAP_QR_CODE;
929 	return bi;
930 }
931 
932 
dpp_debug_print_key(const char * title,EVP_PKEY * key)933 static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
934 {
935 	EC_KEY *eckey;
936 	BIO *out;
937 	size_t rlen;
938 	char *txt;
939 	int res;
940 	unsigned char *der = NULL;
941 	int der_len;
942 
943 	out = BIO_new(BIO_s_mem());
944 	if (!out)
945 		return;
946 
947 	EVP_PKEY_print_private(out, key, 0, NULL);
948 	rlen = BIO_ctrl_pending(out);
949 	txt = os_malloc(rlen + 1);
950 	if (txt) {
951 		res = BIO_read(out, txt, rlen);
952 		if (res > 0) {
953 			txt[res] = '\0';
954 			wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
955 		}
956 		os_free(txt);
957 	}
958 	BIO_free(out);
959 
960 	eckey = EVP_PKEY_get1_EC_KEY(key);
961 	if (!eckey)
962 		return;
963 
964 	der_len = i2d_ECPrivateKey(eckey, &der);
965 	if (der_len > 0)
966 		wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
967 	OPENSSL_free(der);
968 	if (der_len <= 0) {
969 		der = NULL;
970 		der_len = i2d_EC_PUBKEY(eckey, &der);
971 		if (der_len > 0)
972 			wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
973 		OPENSSL_free(der);
974 	}
975 
976 	EC_KEY_free(eckey);
977 }
978 
979 
dpp_gen_keypair(const struct dpp_curve_params * curve)980 static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
981 {
982 #ifdef OPENSSL_IS_BORINGSSL
983 	EVP_PKEY_CTX *kctx = NULL;
984 	const EC_GROUP *group;
985 	EC_KEY *ec_params;
986 #else
987 	EVP_PKEY_CTX *pctx, *kctx = NULL;
988 #endif
989 	EVP_PKEY *params = NULL, *key = NULL;
990 	int nid;
991 
992 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
993 
994 	nid = OBJ_txt2nid(curve->name);
995 	if (nid == NID_undef) {
996 		wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
997 		return NULL;
998 	}
999 #ifdef OPENSSL_IS_BORINGSSL
1000 	group = EC_GROUP_new_by_curve_name(nid);
1001 	ec_params = EC_KEY_new();
1002 	if (!ec_params || EC_KEY_set_group(ec_params, group) != 1) {
1003 		wpa_printf(MSG_ERROR,
1004 			   "DPP: Failed to generate EC_KEY parameters");
1005 		goto fail;
1006 	}
1007 	EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
1008 	params = EVP_PKEY_new();
1009 	if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
1010 		wpa_printf(MSG_ERROR,
1011 			   "DPP: Failed to generate EVP_PKEY parameters");
1012 		goto fail;
1013 	}
1014 #else
1015 	pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
1016 	if (!pctx ||
1017 	    EVP_PKEY_paramgen_init(pctx) != 1 ||
1018 	    EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1 ||
1019 	    EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE) != 1 ||
1020 	    EVP_PKEY_paramgen(pctx, &params) != 1) {
1021 		wpa_printf(MSG_ERROR,
1022 			   "DPP: Failed to generate EVP_PKEY parameters");
1023 		EVP_PKEY_CTX_free(pctx);
1024 		goto fail;
1025 	}
1026 	EVP_PKEY_CTX_free(pctx);
1027 #endif
1028 
1029 	kctx = EVP_PKEY_CTX_new(params, NULL);
1030 	if (!kctx ||
1031 	    EVP_PKEY_keygen_init(kctx) != 1 ||
1032 	    EVP_PKEY_keygen(kctx, &key) != 1) {
1033 		wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
1034 		goto fail;
1035 	}
1036 
1037 	if (wpa_debug_show_keys)
1038 		dpp_debug_print_key("Own generated key", key);
1039 
1040 	EVP_PKEY_free(params);
1041 	EVP_PKEY_CTX_free(kctx);
1042 	return key;
1043 fail:
1044 	EVP_PKEY_CTX_free(kctx);
1045 	EVP_PKEY_free(params);
1046 	return NULL;
1047 }
1048 
1049 
1050 static const struct dpp_curve_params *
dpp_get_curve_name(const char * name)1051 dpp_get_curve_name(const char *name)
1052 {
1053 	int i;
1054 
1055 	for (i = 0; dpp_curves[i].name; i++) {
1056 		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
1057 		    (dpp_curves[i].jwk_crv &&
1058 		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
1059 			return &dpp_curves[i];
1060 	}
1061 	return NULL;
1062 }
1063 
1064 
1065 static const struct dpp_curve_params *
dpp_get_curve_jwk_crv(const char * name)1066 dpp_get_curve_jwk_crv(const char *name)
1067 {
1068 	int i;
1069 
1070 	for (i = 0; dpp_curves[i].name; i++) {
1071 		if (dpp_curves[i].jwk_crv &&
1072 		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
1073 			return &dpp_curves[i];
1074 	}
1075 	return NULL;
1076 }
1077 
1078 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)1079 static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
1080 				  const u8 *privkey, size_t privkey_len)
1081 {
1082 	EVP_PKEY *pkey;
1083 	EC_KEY *eckey;
1084 	const EC_GROUP *group;
1085 	int nid;
1086 
1087 	pkey = EVP_PKEY_new();
1088 	if (!pkey)
1089 		return NULL;
1090 	eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
1091 	if (!eckey) {
1092 		wpa_printf(MSG_INFO,
1093 			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
1094 			   ERR_error_string(ERR_get_error(), NULL));
1095 		EVP_PKEY_free(pkey);
1096 		return NULL;
1097 	}
1098 	group = EC_KEY_get0_group(eckey);
1099 	if (!group) {
1100 		EC_KEY_free(eckey);
1101 		EVP_PKEY_free(pkey);
1102 		return NULL;
1103 	}
1104 	nid = EC_GROUP_get_curve_name(group);
1105 	*curve = dpp_get_curve_nid(nid);
1106 	if (!*curve) {
1107 		wpa_printf(MSG_INFO,
1108 			   "DPP: Unsupported curve (nid=%d) in pre-assigned key",
1109 			   nid);
1110 		EC_KEY_free(eckey);
1111 		EVP_PKEY_free(pkey);
1112 		return NULL;
1113 	}
1114 
1115 	if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
1116 		EC_KEY_free(eckey);
1117 		EVP_PKEY_free(pkey);
1118 		return NULL;
1119 	}
1120 	return pkey;
1121 }
1122 
1123 
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)1124 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
1125 {
1126 	unsigned char *der = NULL;
1127 	int der_len;
1128 	EC_KEY *eckey;
1129 	int res;
1130 	size_t len;
1131 
1132 	/* Need to get the compressed form of the public key through EC_KEY, so
1133 	 * cannot use the simpler i2d_PUBKEY() here. */
1134 	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
1135 	if (!eckey)
1136 		return -1;
1137 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
1138 	der_len = i2d_EC_PUBKEY(eckey, &der);
1139 	EC_KEY_free(eckey);
1140 	if (der_len <= 0) {
1141 		wpa_printf(MSG_ERROR,
1142 			   "DDP: Failed to build DER encoded public key");
1143 		OPENSSL_free(der);
1144 		return -1;
1145 	}
1146 
1147 	len = der_len;
1148 	res = sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash);
1149 	OPENSSL_free(der);
1150 	if (res < 0)
1151 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
1152 	return res;
1153 }
1154 
1155 
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,const u8 * privkey,size_t privkey_len)1156 char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
1157 		  const u8 *privkey, size_t privkey_len)
1158 {
1159 	unsigned char *base64 = NULL;
1160 	char *pos, *end;
1161 	size_t len;
1162 	unsigned char *der = NULL;
1163 	int der_len;
1164 	EC_KEY *eckey;
1165 
1166 	if (!curve) {
1167 		bi->curve = &dpp_curves[0];
1168 	} else {
1169 		bi->curve = dpp_get_curve_name(curve);
1170 		if (!bi->curve) {
1171 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
1172 				   curve);
1173 			return NULL;
1174 		}
1175 	}
1176 	if (privkey)
1177 		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
1178 	else
1179 		bi->pubkey = dpp_gen_keypair(bi->curve);
1180 	if (!bi->pubkey)
1181 		goto fail;
1182 	bi->own = 1;
1183 
1184 	/* Need to get the compressed form of the public key through EC_KEY, so
1185 	 * cannot use the simpler i2d_PUBKEY() here. */
1186 	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
1187 	if (!eckey)
1188 		goto fail;
1189 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
1190 	der_len = i2d_EC_PUBKEY(eckey, &der);
1191 	EC_KEY_free(eckey);
1192 	if (der_len <= 0) {
1193 		wpa_printf(MSG_ERROR,
1194 			   "DDP: Failed to build DER encoded public key");
1195 		goto fail;
1196 	}
1197 
1198 	len = der_len;
1199 	if (sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash) < 0) {
1200 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
1201 		goto fail;
1202 	}
1203 
1204 	base64 = base64_encode(der, der_len, &len);
1205 	OPENSSL_free(der);
1206 	der = NULL;
1207 	if (!base64)
1208 		goto fail;
1209 	pos = (char *) base64;
1210 	end = pos + len;
1211 	for (;;) {
1212 		pos = os_strchr(pos, '\n');
1213 		if (!pos)
1214 			break;
1215 		os_memmove(pos, pos + 1, end - pos);
1216 	}
1217 	return (char *) base64;
1218 fail:
1219 	os_free(base64);
1220 	OPENSSL_free(der);
1221 	return NULL;
1222 }
1223 
1224 
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)1225 static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
1226 			 unsigned int hash_len)
1227 {
1228 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1229 	const char *info = "first intermediate key";
1230 	int res;
1231 
1232 	/* k1 = HKDF(<>, "first intermediate key", M.x) */
1233 
1234 	/* HKDF-Extract(<>, M.x) */
1235 	os_memset(salt, 0, hash_len);
1236 	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
1237 		return -1;
1238 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
1239 			prk, hash_len);
1240 
1241 	/* HKDF-Expand(PRK, info, L) */
1242 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
1243 	os_memset(prk, 0, hash_len);
1244 	if (res < 0)
1245 		return -1;
1246 
1247 	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
1248 			k1, hash_len);
1249 	return 0;
1250 }
1251 
1252 
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)1253 static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
1254 			 unsigned int hash_len)
1255 {
1256 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1257 	const char *info = "second intermediate key";
1258 	int res;
1259 
1260 	/* k2 = HKDF(<>, "second intermediate key", N.x) */
1261 
1262 	/* HKDF-Extract(<>, N.x) */
1263 	os_memset(salt, 0, hash_len);
1264 	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
1265 	if (res < 0)
1266 		return -1;
1267 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1268 			prk, hash_len);
1269 
1270 	/* HKDF-Expand(PRK, info, L) */
1271 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
1272 	os_memset(prk, 0, hash_len);
1273 	if (res < 0)
1274 		return -1;
1275 
1276 	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
1277 			k2, hash_len);
1278 	return 0;
1279 }
1280 
1281 
dpp_derive_ke(struct dpp_authentication * auth,u8 * ke,unsigned int hash_len)1282 static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
1283 			 unsigned int hash_len)
1284 {
1285 	size_t nonce_len;
1286 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
1287 	const char *info_ke = "DPP Key";
1288 	u8 prk[DPP_MAX_HASH_LEN];
1289 	int res;
1290 	const u8 *addr[3];
1291 	size_t len[3];
1292 	size_t num_elem = 0;
1293 
1294 	/* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
1295 
1296 	/* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
1297 	nonce_len = auth->curve->nonce_len;
1298 	os_memcpy(nonces, auth->i_nonce, nonce_len);
1299 	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
1300 	addr[num_elem] = auth->Mx;
1301 	len[num_elem] = auth->secret_len;
1302 	num_elem++;
1303 	addr[num_elem] = auth->Nx;
1304 	len[num_elem] = auth->secret_len;
1305 	num_elem++;
1306 	if (auth->peer_bi && auth->own_bi) {
1307 		addr[num_elem] = auth->Lx;
1308 		len[num_elem] = auth->secret_len;
1309 		num_elem++;
1310 	}
1311 	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
1312 			      num_elem, addr, len, prk);
1313 	if (res < 0)
1314 		return -1;
1315 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1316 			prk, hash_len);
1317 
1318 	/* HKDF-Expand(PRK, info, L) */
1319 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len);
1320 	os_memset(prk, 0, hash_len);
1321 	if (res < 0)
1322 		return -1;
1323 
1324 	wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
1325 			ke, hash_len);
1326 	return 0;
1327 }
1328 
1329 
dpp_auth_init(void * msg_ctx,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,int configurator)1330 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
1331 					  struct dpp_bootstrap_info *peer_bi,
1332 					  struct dpp_bootstrap_info *own_bi,
1333 					  int configurator)
1334 {
1335 	struct dpp_authentication *auth;
1336 	size_t nonce_len;
1337 	EVP_PKEY_CTX *ctx = NULL;
1338 	size_t secret_len;
1339 	struct wpabuf *msg, *pi = NULL;
1340 	u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
1341 	u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
1342 	u8 *pos;
1343 	const u8 *addr[2];
1344 	size_t len[2], siv_len, attr_len;
1345 	u8 *attr_start, *attr_end;
1346 
1347 	auth = os_zalloc(sizeof(*auth));
1348 	if (!auth)
1349 		return NULL;
1350 	auth->msg_ctx = msg_ctx;
1351 	auth->initiator = 1;
1352 	auth->configurator = configurator;
1353 	auth->peer_bi = peer_bi;
1354 	auth->own_bi = own_bi;
1355 	auth->curve = peer_bi->curve;
1356 
1357 	nonce_len = auth->curve->nonce_len;
1358 	if (random_get_bytes(auth->i_nonce, nonce_len)) {
1359 		wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
1360 		goto fail;
1361 	}
1362 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
1363 
1364 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1365 	if (!auth->own_protocol_key)
1366 		goto fail;
1367 
1368 	pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1369 	if (!pi)
1370 		goto fail;
1371 
1372 	/* ECDH: M = pI * BR */
1373 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
1374 	if (!ctx ||
1375 	    EVP_PKEY_derive_init(ctx) != 1 ||
1376 	    EVP_PKEY_derive_set_peer(ctx, auth->peer_bi->pubkey) != 1 ||
1377 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
1378 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
1379 	    EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
1380 		wpa_printf(MSG_ERROR,
1381 			   "DPP: Failed to derive ECDH shared secret: %s",
1382 			   ERR_error_string(ERR_get_error(), NULL));
1383 		goto fail;
1384 	}
1385 	auth->secret_len = secret_len;
1386 	EVP_PKEY_CTX_free(ctx);
1387 	ctx = NULL;
1388 
1389 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
1390 			auth->Mx, auth->secret_len);
1391 
1392 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
1393 			  auth->curve->hash_len) < 0)
1394 		goto fail;
1395 
1396 	/* Build DPP Authentication Request frame attributes */
1397 	attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) +
1398 		4 + sizeof(wrapped_data);
1399 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
1400 	if (!msg)
1401 		goto fail;
1402 	auth->req_msg = msg;
1403 
1404 	attr_start = wpabuf_put(msg, 0);
1405 
1406 	/* Responder Bootstrapping Key Hash */
1407 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1408 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
1409 	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
1410 
1411 	/* Initiator Bootstrapping Key Hash */
1412 	wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1413 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
1414 	if (auth->own_bi)
1415 		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
1416 	else
1417 		os_memset(wpabuf_put(msg, SHA256_MAC_LEN), 0, SHA256_MAC_LEN);
1418 
1419 	/* Initiator Protocol Key */
1420 	wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
1421 	wpabuf_put_le16(msg, wpabuf_len(pi));
1422 	wpabuf_put_buf(msg, pi);
1423 	wpabuf_free(pi);
1424 	pi = NULL;
1425 
1426 	/* Wrapped data ({I-nonce, I-capabilities}k1) */
1427 	pos = clear;
1428 	/* I-nonce */
1429 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1430 	pos += 2;
1431 	WPA_PUT_LE16(pos, nonce_len);
1432 	pos += 2;
1433 	os_memcpy(pos, auth->i_nonce, nonce_len);
1434 	pos += nonce_len;
1435 	/* I-capabilities */
1436 	WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
1437 	pos += 2;
1438 	WPA_PUT_LE16(pos, 1);
1439 	pos += 2;
1440 	auth->i_capab = configurator ? DPP_CAPAB_CONFIGURATOR :
1441 		DPP_CAPAB_ENROLLEE;
1442 	*pos++ = auth->i_capab;
1443 
1444 	attr_end = wpabuf_put(msg, 0);
1445 
1446 	/* OUI, OUI type, Crypto Suite, DPP frame type */
1447 	addr[0] = wpabuf_head_u8(msg) + 2;
1448 	len[0] = 3 + 1 + 1 + 1;
1449 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
1450 
1451 	/* Attributes before Wrapped Data */
1452 	addr[1] = attr_start;
1453 	len[1] = attr_end - attr_start;
1454 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
1455 
1456 	siv_len = pos - clear;
1457 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
1458 	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
1459 			    2, addr, len, wrapped_data) < 0)
1460 		goto fail;
1461 	siv_len += AES_BLOCK_SIZE;
1462 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1463 		    wrapped_data, siv_len);
1464 
1465 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1466 	wpabuf_put_le16(msg, siv_len);
1467 	wpabuf_put_data(msg, wrapped_data, siv_len);
1468 
1469 	wpa_hexdump_buf(MSG_DEBUG,
1470 			"DPP: Authentication Request frame attributes", msg);
1471 
1472 	return auth;
1473 fail:
1474 	wpabuf_free(pi);
1475 	EVP_PKEY_CTX_free(ctx);
1476 	dpp_auth_deinit(auth);
1477 	return NULL;
1478 }
1479 
1480 
dpp_build_conf_req(struct dpp_authentication * auth,const char * json)1481 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
1482 				   const char *json)
1483 {
1484 	size_t nonce_len;
1485 	size_t json_len, clear_len;
1486 	struct wpabuf *clear = NULL, *msg = NULL;
1487 	u8 *wrapped;
1488 
1489 	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
1490 
1491 	nonce_len = auth->curve->nonce_len;
1492 	if (random_get_bytes(auth->e_nonce, nonce_len)) {
1493 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1494 		goto fail;
1495 	}
1496 	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
1497 	json_len = os_strlen(json);
1498 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configAttr JSON", json, json_len);
1499 
1500 	/* { E-nonce, configAttrib }ke */
1501 	clear_len = 4 + nonce_len + 4 + json_len;
1502 	clear = wpabuf_alloc(clear_len);
1503 	msg = wpabuf_alloc(4 + clear_len + AES_BLOCK_SIZE);
1504 	if (!clear || !msg)
1505 		goto fail;
1506 
1507 	/* E-nonce */
1508 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
1509 	wpabuf_put_le16(clear, nonce_len);
1510 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
1511 
1512 	/* configAttrib */
1513 	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
1514 	wpabuf_put_le16(clear, json_len);
1515 	wpabuf_put_data(clear, json, json_len);
1516 
1517 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
1518 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
1519 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
1520 
1521 	/* No AES-SIV AD */
1522 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
1523 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
1524 			    wpabuf_head(clear), wpabuf_len(clear),
1525 			    0, NULL, NULL, wrapped) < 0)
1526 		goto fail;
1527 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
1528 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
1529 
1530 	wpa_hexdump_buf(MSG_DEBUG,
1531 			"DPP: Configuration Request frame attributes", msg);
1532 	wpabuf_free(clear);
1533 	return msg;
1534 
1535 fail:
1536 	wpabuf_free(clear);
1537 	wpabuf_free(msg);
1538 	return NULL;
1539 }
1540 
1541 
dpp_auth_success(struct dpp_authentication * auth)1542 static void dpp_auth_success(struct dpp_authentication *auth)
1543 {
1544 	wpa_printf(MSG_DEBUG,
1545 		   "DPP: Authentication success - clear temporary keys");
1546 	os_memset(auth->Mx, 0, sizeof(auth->Mx));
1547 	os_memset(auth->Nx, 0, sizeof(auth->Nx));
1548 	os_memset(auth->Lx, 0, sizeof(auth->Lx));
1549 	os_memset(auth->k1, 0, sizeof(auth->k1));
1550 	os_memset(auth->k2, 0, sizeof(auth->k2));
1551 
1552 	auth->auth_success = 1;
1553 }
1554 
1555 
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)1556 static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
1557 {
1558 	struct wpabuf *pix, *prx, *bix, *brx;
1559 	const u8 *addr[7];
1560 	size_t len[7];
1561 	size_t i, num_elem = 0;
1562 	size_t nonce_len;
1563 	u8 zero = 0;
1564 	int res = -1;
1565 
1566 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1567 	nonce_len = auth->curve->nonce_len;
1568 
1569 	if (auth->initiator) {
1570 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1571 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1572 		if (auth->own_bi)
1573 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1574 		else
1575 			bix = NULL;
1576 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1577 	} else {
1578 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1579 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1580 		if (auth->peer_bi)
1581 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1582 		else
1583 			bix = NULL;
1584 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1585 	}
1586 	if (!pix || !prx || !brx)
1587 		goto fail;
1588 
1589 	addr[num_elem] = auth->i_nonce;
1590 	len[num_elem] = nonce_len;
1591 	num_elem++;
1592 
1593 	addr[num_elem] = auth->r_nonce;
1594 	len[num_elem] = nonce_len;
1595 	num_elem++;
1596 
1597 	addr[num_elem] = wpabuf_head(pix);
1598 	len[num_elem] = wpabuf_len(pix) / 2;
1599 	num_elem++;
1600 
1601 	addr[num_elem] = wpabuf_head(prx);
1602 	len[num_elem] = wpabuf_len(prx) / 2;
1603 	num_elem++;
1604 
1605 	if (bix) {
1606 		addr[num_elem] = wpabuf_head(bix);
1607 		len[num_elem] = wpabuf_len(bix) / 2;
1608 		num_elem++;
1609 	}
1610 
1611 	addr[num_elem] = wpabuf_head(brx);
1612 	len[num_elem] = wpabuf_len(brx) / 2;
1613 	num_elem++;
1614 
1615 	addr[num_elem] = &zero;
1616 	len[num_elem] = 1;
1617 	num_elem++;
1618 
1619 	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
1620 	for (i = 0; i < num_elem; i++)
1621 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1622 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
1623 	if (res == 0)
1624 		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
1625 			    auth->curve->hash_len);
1626 fail:
1627 	wpabuf_free(pix);
1628 	wpabuf_free(prx);
1629 	wpabuf_free(bix);
1630 	wpabuf_free(brx);
1631 	return res;
1632 }
1633 
1634 
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)1635 static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
1636 {
1637 	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
1638 	const u8 *addr[7];
1639 	size_t len[7];
1640 	size_t i, num_elem = 0;
1641 	size_t nonce_len;
1642 	u8 one = 1;
1643 	int res = -1;
1644 
1645 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
1646 	nonce_len = auth->curve->nonce_len;
1647 
1648 	if (auth->initiator) {
1649 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1650 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1651 		if (auth->own_bi)
1652 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1653 		else
1654 			bix = NULL;
1655 		if (!auth->peer_bi)
1656 			goto fail;
1657 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1658 	} else {
1659 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
1660 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1661 		if (auth->peer_bi)
1662 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
1663 		else
1664 			bix = NULL;
1665 		if (!auth->own_bi)
1666 			goto fail;
1667 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
1668 	}
1669 	if (!pix || !prx || !brx)
1670 		goto fail;
1671 
1672 	addr[num_elem] = auth->r_nonce;
1673 	len[num_elem] = nonce_len;
1674 	num_elem++;
1675 
1676 	addr[num_elem] = auth->i_nonce;
1677 	len[num_elem] = nonce_len;
1678 	num_elem++;
1679 
1680 	addr[num_elem] = wpabuf_head(prx);
1681 	len[num_elem] = wpabuf_len(prx) / 2;
1682 	num_elem++;
1683 
1684 	addr[num_elem] = wpabuf_head(pix);
1685 	len[num_elem] = wpabuf_len(pix) / 2;
1686 	num_elem++;
1687 
1688 	addr[num_elem] = wpabuf_head(brx);
1689 	len[num_elem] = wpabuf_len(brx) / 2;
1690 	num_elem++;
1691 
1692 	if (bix) {
1693 		addr[num_elem] = wpabuf_head(bix);
1694 		len[num_elem] = wpabuf_len(bix) / 2;
1695 		num_elem++;
1696 	}
1697 
1698 	addr[num_elem] = &one;
1699 	len[num_elem] = 1;
1700 	num_elem++;
1701 
1702 	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1703 	for (i = 0; i < num_elem; i++)
1704 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1705 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1706 	if (res == 0)
1707 		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1708 			    auth->curve->hash_len);
1709 fail:
1710 	wpabuf_free(pix);
1711 	wpabuf_free(prx);
1712 	wpabuf_free(bix);
1713 	wpabuf_free(brx);
1714 	return res;
1715 }
1716 
1717 
dpp_auth_derive_l_responder(struct dpp_authentication * auth)1718 static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1719 {
1720 	const EC_GROUP *group;
1721 	EC_POINT *l = NULL;
1722 	EC_KEY *BI = NULL, *bR = NULL, *pR = NULL;
1723 	const EC_POINT *BI_point;
1724 	BN_CTX *bnctx;
1725 	BIGNUM *lx, *sum, *q;
1726 	const BIGNUM *bR_bn, *pR_bn;
1727 	int ret = -1;
1728 	int num_bytes, offset;
1729 
1730 	/* L = ((bR + pR) modulo q) * BI */
1731 
1732 	bnctx = BN_CTX_new();
1733 	sum = BN_new();
1734 	q = BN_new();
1735 	lx = BN_new();
1736 	if (!bnctx || !sum || !q || !lx)
1737 		goto fail;
1738 	BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
1739 	if (!BI)
1740 		goto fail;
1741 	BI_point = EC_KEY_get0_public_key(BI);
1742 	group = EC_KEY_get0_group(BI);
1743 	if (!group)
1744 		goto fail;
1745 
1746 	bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
1747 	pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
1748 	if (!bR || !pR)
1749 		goto fail;
1750 	bR_bn = EC_KEY_get0_private_key(bR);
1751 	pR_bn = EC_KEY_get0_private_key(pR);
1752 	if (!bR_bn || !pR_bn)
1753 		goto fail;
1754 	if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
1755 	    BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
1756 		goto fail;
1757 	l = EC_POINT_new(group);
1758 	if (!l ||
1759 	    EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
1760 	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
1761 						bnctx) != 1) {
1762 		wpa_printf(MSG_ERROR,
1763 			   "OpenSSL: failed: %s",
1764 			   ERR_error_string(ERR_get_error(), NULL));
1765 		goto fail;
1766 	}
1767 
1768 	num_bytes = BN_num_bytes(lx);
1769 	if ((size_t) num_bytes > auth->secret_len)
1770 		goto fail;
1771 	if (auth->secret_len > (size_t) num_bytes)
1772 		offset = auth->secret_len - num_bytes;
1773 	else
1774 		offset = 0;
1775 
1776 	os_memset(auth->Lx, 0, offset);
1777 	BN_bn2bin(lx, auth->Lx + offset);
1778 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1779 	ret = 0;
1780 fail:
1781 	EC_POINT_clear_free(l);
1782 	EC_KEY_free(BI);
1783 	EC_KEY_free(bR);
1784 	EC_KEY_free(pR);
1785 	BN_clear_free(lx);
1786 	BN_clear_free(sum);
1787 	BN_free(q);
1788 	BN_CTX_free(bnctx);
1789 	return ret;
1790 }
1791 
1792 
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)1793 static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1794 {
1795 	const EC_GROUP *group;
1796 	EC_POINT *l = NULL, *sum = NULL;
1797 	EC_KEY *bI = NULL, *BR = NULL, *PR = NULL;
1798 	const EC_POINT *BR_point, *PR_point;
1799 	BN_CTX *bnctx;
1800 	BIGNUM *lx;
1801 	const BIGNUM *bI_bn;
1802 	int ret = -1;
1803 	int num_bytes, offset;
1804 
1805 	/* L = bI * (BR + PR) */
1806 
1807 	bnctx = BN_CTX_new();
1808 	lx = BN_new();
1809 	if (!bnctx || !lx)
1810 		goto fail;
1811 	BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
1812 	PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key);
1813 	if (!BR || !PR)
1814 		goto fail;
1815 	BR_point = EC_KEY_get0_public_key(BR);
1816 	PR_point = EC_KEY_get0_public_key(PR);
1817 
1818 	bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
1819 	if (!bI)
1820 		goto fail;
1821 	group = EC_KEY_get0_group(bI);
1822 	bI_bn = EC_KEY_get0_private_key(bI);
1823 	if (!group || !bI_bn)
1824 		goto fail;
1825 	sum = EC_POINT_new(group);
1826 	l = EC_POINT_new(group);
1827 	if (!sum || !l ||
1828 	    EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
1829 	    EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
1830 	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
1831 						bnctx) != 1) {
1832 		wpa_printf(MSG_ERROR,
1833 			   "OpenSSL: failed: %s",
1834 			   ERR_error_string(ERR_get_error(), NULL));
1835 		goto fail;
1836 	}
1837 
1838 	num_bytes = BN_num_bytes(lx);
1839 	if ((size_t) num_bytes > auth->secret_len)
1840 		goto fail;
1841 	if (auth->secret_len > (size_t) num_bytes)
1842 		offset = auth->secret_len - num_bytes;
1843 	else
1844 		offset = 0;
1845 
1846 	os_memset(auth->Lx, 0, offset);
1847 	BN_bn2bin(lx, auth->Lx + offset);
1848 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1849 	ret = 0;
1850 fail:
1851 	EC_POINT_clear_free(l);
1852 	EC_KEY_free(bI);
1853 	EC_KEY_free(BR);
1854 	EC_KEY_free(PR);
1855 	BN_clear_free(lx);
1856 	BN_CTX_free(bnctx);
1857 	return ret;
1858 }
1859 
1860 
dpp_auth_build_resp(struct dpp_authentication * auth)1861 static int dpp_auth_build_resp(struct dpp_authentication *auth)
1862 {
1863 	size_t nonce_len;
1864 	EVP_PKEY_CTX *ctx = NULL;
1865 	size_t secret_len;
1866 	struct wpabuf *msg, *pr = NULL;
1867 	u8 r_auth[4 + DPP_MAX_HASH_LEN];
1868 	u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE];
1869 #define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
1870 		4 + sizeof(wrapped_r_auth)
1871 	size_t wrapped_r_auth_len;
1872 	u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
1873 	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
1874 	u8 *pos;
1875 	const u8 *addr[2];
1876 	size_t len[2], siv_len, attr_len;
1877 	u8 *attr_start, *attr_end;
1878 
1879 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
1880 
1881 	nonce_len = auth->curve->nonce_len;
1882 	if (random_get_bytes(auth->r_nonce, nonce_len)) {
1883 		wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
1884 		goto fail;
1885 	}
1886 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
1887 
1888 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
1889 	if (!auth->own_protocol_key)
1890 		goto fail;
1891 
1892 	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
1893 	if (!pr)
1894 		goto fail;
1895 
1896 	/* ECDH: N = pR * PI */
1897 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
1898 	if (!ctx ||
1899 	    EVP_PKEY_derive_init(ctx) != 1 ||
1900 	    EVP_PKEY_derive_set_peer(ctx, auth->peer_protocol_key) != 1 ||
1901 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
1902 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
1903 	    EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
1904 		wpa_printf(MSG_ERROR,
1905 			   "DPP: Failed to derive ECDH shared secret: %s",
1906 			   ERR_error_string(ERR_get_error(), NULL));
1907 		goto fail;
1908 	}
1909 	EVP_PKEY_CTX_free(ctx);
1910 	ctx = NULL;
1911 
1912 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
1913 			auth->Nx, auth->secret_len);
1914 
1915 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
1916 			  auth->curve->hash_len) < 0)
1917 		goto fail;
1918 
1919 	if (auth->own_bi && auth->peer_bi) {
1920 		/* Mutual authentication */
1921 		if (dpp_auth_derive_l_responder(auth) < 0)
1922 			goto fail;
1923 	}
1924 
1925 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
1926 		goto fail;
1927 
1928 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
1929 	WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
1930 	WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
1931 	if (dpp_gen_r_auth(auth, r_auth + 4) < 0 ||
1932 	    aes_siv_encrypt(auth->ke, auth->curve->hash_len,
1933 			    r_auth, 4 + auth->curve->hash_len,
1934 			    0, NULL, NULL, wrapped_r_auth) < 0)
1935 		goto fail;
1936 	wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
1937 	wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
1938 		    wrapped_r_auth, wrapped_r_auth_len);
1939 
1940 	/* Build DPP Authentication Response frame attributes */
1941 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
1942 		4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data);
1943 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
1944 	if (!msg)
1945 		goto fail;
1946 	wpabuf_free(auth->resp_msg);
1947 	auth->resp_msg = msg;
1948 
1949 	attr_start = wpabuf_put(msg, 0);
1950 
1951 	/* DPP Status */
1952 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1953 	wpabuf_put_le16(msg, 1);
1954 	wpabuf_put_u8(msg, DPP_STATUS_OK);
1955 
1956 	/* Responder Bootstrapping Key Hash */
1957 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
1958 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
1959 	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
1960 
1961 	if (auth->peer_bi) {
1962 		/* Mutual authentication */
1963 		/* Initiator Bootstrapping Key Hash */
1964 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
1965 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
1966 		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
1967 				SHA256_MAC_LEN);
1968 	}
1969 
1970 	/* Responder Protocol Key */
1971 	wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
1972 	wpabuf_put_le16(msg, wpabuf_len(pr));
1973 	wpabuf_put_buf(msg, pr);
1974 	wpabuf_free(pr);
1975 	pr = NULL;
1976 
1977 	attr_end = wpabuf_put(msg, 0);
1978 
1979 	/* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
1980 	pos = clear;
1981 	/* R-nonce */
1982 	WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
1983 	pos += 2;
1984 	WPA_PUT_LE16(pos, nonce_len);
1985 	pos += 2;
1986 	os_memcpy(pos, auth->r_nonce, nonce_len);
1987 	pos += nonce_len;
1988 	/* I-nonce */
1989 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
1990 	pos += 2;
1991 	WPA_PUT_LE16(pos, nonce_len);
1992 	pos += 2;
1993 	os_memcpy(pos, auth->i_nonce, nonce_len);
1994 	pos += nonce_len;
1995 	/* R-capabilities */
1996 	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
1997 	pos += 2;
1998 	WPA_PUT_LE16(pos, 1);
1999 	pos += 2;
2000 	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
2001 		DPP_CAPAB_ENROLLEE;
2002 	*pos++ = auth->r_capab;
2003 	/* {R-auth}ke */
2004 	WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
2005 	pos += 2;
2006 	WPA_PUT_LE16(pos, wrapped_r_auth_len);
2007 	pos += 2;
2008 	os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
2009 	pos += wrapped_r_auth_len;
2010 
2011 	/* OUI, OUI type, Crypto Suite, DPP frame type */
2012 	addr[0] = wpabuf_head_u8(msg) + 2;
2013 	len[0] = 3 + 1 + 1 + 1;
2014 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2015 
2016 	/* Attributes before Wrapped Data */
2017 	addr[1] = attr_start;
2018 	len[1] = attr_end - attr_start;
2019 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2020 
2021 	siv_len = pos - clear;
2022 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
2023 	if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, clear, siv_len,
2024 			    2, addr, len, wrapped_data) < 0)
2025 		goto fail;
2026 	siv_len += AES_BLOCK_SIZE;
2027 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2028 		    wrapped_data, siv_len);
2029 
2030 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2031 	wpabuf_put_le16(msg, siv_len);
2032 	wpabuf_put_data(msg, wrapped_data, siv_len);
2033 
2034 	wpa_hexdump_buf(MSG_DEBUG,
2035 			"DPP: Authentication Response frame attributes", msg);
2036 
2037 	return 0;
2038 
2039 fail:
2040 	wpabuf_free(pr);
2041 	return -1;
2042 }
2043 
2044 
dpp_auth_build_resp_status(struct dpp_authentication * auth,enum dpp_status_error status)2045 static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
2046 				      enum dpp_status_error status)
2047 {
2048 	size_t nonce_len;
2049 	struct wpabuf *msg;
2050 #define DPP_AUTH_RESP_CLEAR_LEN2 4 + DPP_MAX_NONCE_LEN + 4 + 1
2051 	u8 clear[DPP_AUTH_RESP_CLEAR_LEN2];
2052 	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN2 + AES_BLOCK_SIZE];
2053 	u8 *pos;
2054 	const u8 *addr[2];
2055 	size_t len[2], siv_len, attr_len;
2056 	u8 *attr_start, *attr_end;
2057 
2058 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
2059 
2060 	/* Build DPP Authentication Response frame attributes */
2061 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + 4 + sizeof(wrapped_data);
2062 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
2063 	if (!msg)
2064 		goto fail;
2065 	wpabuf_free(auth->resp_msg);
2066 	auth->resp_msg = msg;
2067 
2068 	attr_start = wpabuf_put(msg, 0);
2069 
2070 	/* DPP Status */
2071 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
2072 	wpabuf_put_le16(msg, 1);
2073 	wpabuf_put_u8(msg, status);
2074 
2075 	/* Responder Bootstrapping Key Hash */
2076 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
2077 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
2078 	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
2079 
2080 	if (auth->peer_bi) {
2081 		/* Mutual authentication */
2082 		/* Initiator Bootstrapping Key Hash */
2083 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
2084 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
2085 		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
2086 				SHA256_MAC_LEN);
2087 	}
2088 
2089 	attr_end = wpabuf_put(msg, 0);
2090 
2091 	/* Wrapped data ({I-nonce, R-capabilities}k1) */
2092 	pos = clear;
2093 	/* I-nonce */
2094 	nonce_len = auth->curve->nonce_len;
2095 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
2096 	pos += 2;
2097 	WPA_PUT_LE16(pos, nonce_len);
2098 	pos += 2;
2099 	os_memcpy(pos, auth->i_nonce, nonce_len);
2100 	pos += nonce_len;
2101 	/* R-capabilities */
2102 	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
2103 	pos += 2;
2104 	WPA_PUT_LE16(pos, 1);
2105 	pos += 2;
2106 	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
2107 		DPP_CAPAB_ENROLLEE;
2108 	*pos++ = auth->r_capab;
2109 
2110 	/* OUI, OUI type, Crypto Suite, DPP frame type */
2111 	addr[0] = wpabuf_head_u8(msg) + 2;
2112 	len[0] = 3 + 1 + 1 + 1;
2113 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2114 
2115 	/* Attributes before Wrapped Data */
2116 	addr[1] = attr_start;
2117 	len[1] = attr_end - attr_start;
2118 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2119 
2120 	siv_len = pos - clear;
2121 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
2122 	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
2123 			    2, addr, len, wrapped_data) < 0)
2124 		goto fail;
2125 	siv_len += AES_BLOCK_SIZE;
2126 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2127 		    wrapped_data, siv_len);
2128 
2129 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2130 	wpabuf_put_le16(msg, siv_len);
2131 	wpabuf_put_data(msg, wrapped_data, siv_len);
2132 
2133 	wpa_hexdump_buf(MSG_DEBUG,
2134 			"DPP: Authentication Response frame attributes", msg);
2135 
2136 	return 0;
2137 
2138 fail:
2139 	return -1;
2140 }
2141 
2142 
2143 struct dpp_authentication *
dpp_auth_req_rx(void * msg_ctx,u8 dpp_allowed_roles,int qr_mutual,struct dpp_bootstrap_info * peer_bi,struct dpp_bootstrap_info * own_bi,unsigned int freq,const u8 * hdr,const u8 * attr_start,const u8 * wrapped_data,u16 wrapped_data_len)2144 dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
2145 		struct dpp_bootstrap_info *peer_bi,
2146 		struct dpp_bootstrap_info *own_bi,
2147 		unsigned int freq, const u8 *hdr, const u8 *attr_start,
2148 		const u8 *wrapped_data,	u16 wrapped_data_len)
2149 {
2150 	EVP_PKEY *pi = NULL;
2151 	EVP_PKEY_CTX *ctx = NULL;
2152 	size_t secret_len;
2153 	const u8 *addr[2];
2154 	size_t len[2];
2155 	u8 *unwrapped = NULL;
2156 	size_t unwrapped_len = 0;
2157 	const u8 *i_proto, *i_nonce, *i_capab, *i_bootstrap;
2158 	u16 i_proto_len, i_nonce_len, i_capab_len, i_bootstrap_len;
2159 	struct dpp_authentication *auth = NULL;
2160 	size_t attr_len;
2161 
2162 	if (wrapped_data_len < AES_BLOCK_SIZE)
2163 		return NULL;
2164 
2165 	attr_len = wrapped_data - 4 - attr_start;
2166 
2167 	auth = os_zalloc(sizeof(*auth));
2168 	if (!auth)
2169 		goto fail;
2170 	auth->msg_ctx = msg_ctx;
2171 	auth->peer_bi = peer_bi;
2172 	auth->own_bi = own_bi;
2173 	auth->curve = own_bi->curve;
2174 	auth->curr_freq = freq;
2175 
2176 	i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
2177 			       &i_proto_len);
2178 	if (!i_proto) {
2179 		wpa_printf(MSG_DEBUG,
2180 			   "DPP: Missing required Initiator Protocol Key attribute");
2181 		goto fail;
2182 	}
2183 	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
2184 		    i_proto, i_proto_len);
2185 
2186 	/* M = bR * PI */
2187 	pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
2188 	if (!pi) {
2189 		wpa_printf(MSG_DEBUG, "DPP: Invalid Initiator Protocol Key");
2190 		goto fail;
2191 	}
2192 	dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
2193 
2194 	ctx = EVP_PKEY_CTX_new(own_bi->pubkey, NULL);
2195 	if (!ctx ||
2196 	    EVP_PKEY_derive_init(ctx) != 1 ||
2197 	    EVP_PKEY_derive_set_peer(ctx, pi) != 1 ||
2198 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
2199 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
2200 	    EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
2201 		wpa_printf(MSG_ERROR,
2202 			   "DPP: Failed to derive ECDH shared secret: %s",
2203 			   ERR_error_string(ERR_get_error(), NULL));
2204 		goto fail;
2205 	}
2206 	auth->secret_len = secret_len;
2207 	EVP_PKEY_CTX_free(ctx);
2208 	ctx = NULL;
2209 
2210 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
2211 			auth->Mx, auth->secret_len);
2212 
2213 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
2214 			  auth->curve->hash_len) < 0)
2215 		goto fail;
2216 
2217 	addr[0] = hdr;
2218 	len[0] = DPP_HDR_LEN;
2219 	addr[1] = attr_start;
2220 	len[1] = attr_len;
2221 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2222 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2223 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2224 		    wrapped_data, wrapped_data_len);
2225 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2226 	unwrapped = os_malloc(unwrapped_len);
2227 	if (!unwrapped)
2228 		goto fail;
2229 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
2230 			    wrapped_data, wrapped_data_len,
2231 			    2, addr, len, unwrapped) < 0) {
2232 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2233 		goto fail;
2234 	}
2235 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2236 		    unwrapped, unwrapped_len);
2237 
2238 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2239 		wpa_printf(MSG_DEBUG,
2240 			   "DPP: Invalid attribute in unwrapped data");
2241 		goto fail;
2242 	}
2243 
2244 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2245 			       &i_nonce_len);
2246 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2247 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
2248 		goto fail;
2249 	}
2250 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2251 	os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
2252 
2253 	i_capab = dpp_get_attr(unwrapped, unwrapped_len,
2254 			       DPP_ATTR_I_CAPABILITIES,
2255 			       &i_capab_len);
2256 	if (!i_capab || i_capab_len < 1) {
2257 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-capabilities");
2258 		goto fail;
2259 	}
2260 	auth->i_capab = i_capab[0];
2261 	wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
2262 
2263 	bin_clear_free(unwrapped, unwrapped_len);
2264 	unwrapped = NULL;
2265 
2266 	switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
2267 	case DPP_CAPAB_ENROLLEE:
2268 		if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
2269 			wpa_printf(MSG_DEBUG,
2270 				   "DPP: Local policy does not allow Configurator role");
2271 			goto not_compatible;
2272 		}
2273 		wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
2274 		auth->configurator = 1;
2275 		break;
2276 	case DPP_CAPAB_CONFIGURATOR:
2277 		if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
2278 			wpa_printf(MSG_DEBUG,
2279 				   "DPP: Local policy does not allow Enrollee role");
2280 			goto not_compatible;
2281 		}
2282 		wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
2283 		auth->configurator = 0;
2284 		break;
2285 	default:
2286 		wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
2287 		goto not_compatible;
2288 	}
2289 
2290 	auth->peer_protocol_key = pi;
2291 	pi = NULL;
2292 	if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
2293 		char hex[SHA256_MAC_LEN * 2 + 1];
2294 
2295 		wpa_printf(MSG_DEBUG,
2296 			   "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
2297 		if (dpp_auth_build_resp_status(auth,
2298 					       DPP_STATUS_RESPONSE_PENDING) < 0)
2299 			goto fail;
2300 		i_bootstrap = dpp_get_attr(attr_start, attr_len,
2301 					   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2302 					   &i_bootstrap_len);
2303 		if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
2304 			auth->response_pending = 1;
2305 			os_memcpy(auth->waiting_pubkey_hash,
2306 				  i_bootstrap, i_bootstrap_len);
2307 			wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
2308 					 i_bootstrap_len);
2309 		} else {
2310 			hex[0] = '\0';
2311 		}
2312 
2313 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
2314 			"%s", hex);
2315 		return auth;
2316 	}
2317 	if (dpp_auth_build_resp(auth) < 0)
2318 		goto fail;
2319 
2320 	return auth;
2321 
2322 not_compatible:
2323 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
2324 		"i-capab=0x%02x", auth->i_capab);
2325 	if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
2326 		auth->configurator = 1;
2327 	else
2328 		auth->configurator = 0;
2329 	auth->peer_protocol_key = pi;
2330 	pi = NULL;
2331 	if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
2332 		goto fail;
2333 
2334 	auth->remove_on_tx_status = 1;
2335 	return auth;
2336 fail:
2337 	bin_clear_free(unwrapped, unwrapped_len);
2338 	EVP_PKEY_free(pi);
2339 	EVP_PKEY_CTX_free(ctx);
2340 	dpp_auth_deinit(auth);
2341 	return NULL;
2342 }
2343 
2344 
dpp_notify_new_qr_code(struct dpp_authentication * auth,struct dpp_bootstrap_info * peer_bi)2345 int dpp_notify_new_qr_code(struct dpp_authentication *auth,
2346 			   struct dpp_bootstrap_info *peer_bi)
2347 {
2348 	if (!auth || !auth->response_pending ||
2349 	    os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
2350 		      SHA256_MAC_LEN) != 0)
2351 		return 0;
2352 
2353 	wpa_printf(MSG_DEBUG,
2354 		   "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
2355 		   MACSTR, MAC2STR(auth->peer_mac_addr));
2356 	auth->peer_bi = peer_bi;
2357 
2358 	if (dpp_auth_build_resp(auth) < 0)
2359 		return -1;
2360 
2361 	return 1;
2362 }
2363 
2364 
dpp_auth_build_conf(struct dpp_authentication * auth)2365 static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth)
2366 {
2367 	struct wpabuf *msg;
2368 	u8 i_auth[4 + DPP_MAX_HASH_LEN];
2369 	size_t i_auth_len;
2370 	const u8 *addr[2];
2371 	size_t len[2], attr_len;
2372 	u8 *wrapped_i_auth;
2373 	u8 *attr_start, *attr_end;
2374 
2375 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
2376 
2377 	i_auth_len = 4 + auth->curve->hash_len;
2378 	/* Build DPP Authentication Confirmation frame attributes */
2379 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
2380 		4 + i_auth_len + AES_BLOCK_SIZE;
2381 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
2382 	if (!msg)
2383 		goto fail;
2384 
2385 	attr_start = wpabuf_put(msg, 0);
2386 
2387 	/* DPP Status */
2388 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
2389 	wpabuf_put_le16(msg, 1);
2390 	wpabuf_put_u8(msg, DPP_STATUS_OK);
2391 
2392 	/* Responder Bootstrapping Key Hash */
2393 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
2394 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
2395 	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2396 
2397 	if (auth->own_bi) {
2398 		/* Mutual authentication */
2399 		/* Initiator Bootstrapping Key Hash */
2400 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
2401 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
2402 		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
2403 	}
2404 
2405 	attr_end = wpabuf_put(msg, 0);
2406 
2407 	/* OUI, OUI type, Crypto Suite, DPP frame type */
2408 	addr[0] = wpabuf_head_u8(msg) + 2;
2409 	len[0] = 3 + 1 + 1 + 1;
2410 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2411 
2412 	/* Attributes before Wrapped Data */
2413 	addr[1] = attr_start;
2414 	len[1] = attr_end - attr_start;
2415 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2416 
2417 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2418 	wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
2419 	wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
2420 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
2421 	WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
2422 	WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
2423 	if (dpp_gen_i_auth(auth, i_auth + 4) < 0 ||
2424 	    aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2425 			    i_auth, i_auth_len,
2426 			    2, addr, len, wrapped_i_auth) < 0)
2427 		goto fail;
2428 	wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
2429 		    wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
2430 
2431 	wpa_hexdump_buf(MSG_DEBUG,
2432 			"DPP: Authentication Confirmation frame attributes",
2433 			msg);
2434 	dpp_auth_success(auth);
2435 
2436 	return msg;
2437 
2438 fail:
2439 	return NULL;
2440 }
2441 
2442 
2443 static void
dpp_auth_resp_rx_status(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,const u8 * wrapped_data,u16 wrapped_data_len,enum dpp_status_error status)2444 dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
2445 			const u8 *attr_start, size_t attr_len,
2446 			const u8 *wrapped_data, u16 wrapped_data_len,
2447 			enum dpp_status_error status)
2448 {
2449 	const u8 *addr[2];
2450 	size_t len[2];
2451 	u8 *unwrapped = NULL;
2452 	size_t unwrapped_len = 0;
2453 	const u8 *i_nonce, *r_capab;
2454 	u16 i_nonce_len, r_capab_len;
2455 
2456 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
2457 		wpa_printf(MSG_DEBUG,
2458 			   "DPP: Responder reported incompatible roles");
2459 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
2460 		wpa_printf(MSG_DEBUG,
2461 			   "DPP: Responder reported more time needed");
2462 	} else {
2463 		wpa_printf(MSG_DEBUG,
2464 			   "DPP: Responder reported failure (status %d)",
2465 			   status);
2466 		return;
2467 	}
2468 
2469 	addr[0] = hdr;
2470 	len[0] = DPP_HDR_LEN;
2471 	addr[1] = attr_start;
2472 	len[1] = attr_len;
2473 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2474 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2475 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2476 		    wrapped_data, wrapped_data_len);
2477 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2478 	unwrapped = os_malloc(unwrapped_len);
2479 	if (!unwrapped)
2480 		goto fail;
2481 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
2482 			    wrapped_data, wrapped_data_len,
2483 			    2, addr, len, unwrapped) < 0) {
2484 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2485 		goto fail;
2486 	}
2487 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2488 		    unwrapped, unwrapped_len);
2489 
2490 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2491 		wpa_printf(MSG_DEBUG,
2492 			   "DPP: Invalid attribute in unwrapped data");
2493 		goto fail;
2494 	}
2495 
2496 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2497 			       &i_nonce_len);
2498 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2499 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
2500 		goto fail;
2501 	}
2502 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2503 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
2504 		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
2505 		goto fail;
2506 	}
2507 
2508 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
2509 			       DPP_ATTR_R_CAPABILITIES,
2510 			       &r_capab_len);
2511 	if (!r_capab || r_capab_len < 1) {
2512 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
2513 		goto fail;
2514 	}
2515 	auth->r_capab = r_capab[0];
2516 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
2517 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
2518 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
2519 			"r-capab=0x%02x", auth->r_capab);
2520 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
2521 		wpa_printf(MSG_DEBUG,
2522 			   "DPP: Continue waiting for full DPP Authentication Response");
2523 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_RESPONSE_PENDING);
2524 	}
2525 fail:
2526 	bin_clear_free(unwrapped, unwrapped_len);
2527 }
2528 
2529 
2530 struct wpabuf *
dpp_auth_resp_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)2531 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
2532 		 const u8 *attr_start, size_t attr_len)
2533 {
2534 	EVP_PKEY *pr;
2535 	EVP_PKEY_CTX *ctx = NULL;
2536 	size_t secret_len;
2537 	const u8 *addr[2];
2538 	size_t len[2];
2539 	u8 *unwrapped = NULL, *unwrapped2 = NULL;
2540 	size_t unwrapped_len = 0, unwrapped2_len = 0;
2541 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
2542 		*r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
2543 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
2544 		r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
2545 		wrapped2_len, r_auth_len;
2546 	u8 r_auth2[DPP_MAX_HASH_LEN];
2547 
2548 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2549 				    &wrapped_data_len);
2550 	if (!wrapped_data) {
2551 		wpa_printf(MSG_DEBUG,
2552 			   "DPP: Missing required Wrapped data attribute");
2553 		return NULL;
2554 	}
2555 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
2556 		    wrapped_data, wrapped_data_len);
2557 
2558 	if (wrapped_data_len < AES_BLOCK_SIZE)
2559 		return NULL;
2560 
2561 	attr_len = wrapped_data - 4 - attr_start;
2562 
2563 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
2564 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2565 				   &r_bootstrap_len);
2566 	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2567 		wpa_printf(MSG_DEBUG,
2568 			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2569 		return NULL;
2570 	}
2571 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
2572 		    r_bootstrap, r_bootstrap_len);
2573 	if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
2574 		      SHA256_MAC_LEN) != 0) {
2575 		wpa_hexdump(MSG_DEBUG,
2576 			    "DPP: Expected Responder Bootstrapping Key Hash",
2577 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2578 		return NULL;
2579 	}
2580 
2581 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
2582 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2583 				   &i_bootstrap_len);
2584 	if (i_bootstrap) {
2585 		if (i_bootstrap_len != SHA256_MAC_LEN) {
2586 			wpa_printf(MSG_DEBUG,
2587 				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
2588 			return NULL;
2589 		}
2590 		wpa_hexdump(MSG_MSGDUMP,
2591 			    "DPP: Initiator Bootstrapping Key Hash",
2592 			    i_bootstrap, i_bootstrap_len);
2593 		if (!auth->own_bi ||
2594 		    os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
2595 			      SHA256_MAC_LEN) != 0) {
2596 			wpa_printf(MSG_DEBUG,
2597 				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
2598 			return NULL;
2599 		}
2600 	}
2601 
2602 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
2603 			      &status_len);
2604 	if (!status || status_len < 1) {
2605 		wpa_printf(MSG_DEBUG,
2606 			   "DPP: Missing or invalid required DPP Status attribute");
2607 		return NULL;
2608 	}
2609 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
2610 	auth->auth_resp_status = status[0];
2611 	if (status[0] != DPP_STATUS_OK) {
2612 		dpp_auth_resp_rx_status(auth, hdr, attr_start,
2613 					attr_len, wrapped_data,
2614 					wrapped_data_len, status[0]);
2615 		return NULL;
2616 	}
2617 
2618 	r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
2619 			       &r_proto_len);
2620 	if (!r_proto) {
2621 		wpa_printf(MSG_DEBUG,
2622 			   "DPP: Missing required Responder Protocol Key attribute");
2623 		return NULL;
2624 	}
2625 	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
2626 		    r_proto, r_proto_len);
2627 
2628 	/* N = pI * PR */
2629 	pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
2630 	if (!pr) {
2631 		wpa_printf(MSG_DEBUG, "DPP: Invalid Responder Protocol Key");
2632 		return NULL;
2633 	}
2634 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
2635 
2636 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
2637 	if (!ctx ||
2638 	    EVP_PKEY_derive_init(ctx) != 1 ||
2639 	    EVP_PKEY_derive_set_peer(ctx, pr) != 1 ||
2640 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
2641 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
2642 	    EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
2643 		wpa_printf(MSG_ERROR,
2644 			   "DPP: Failed to derive ECDH shared secret: %s",
2645 			   ERR_error_string(ERR_get_error(), NULL));
2646 		goto fail;
2647 	}
2648 	EVP_PKEY_CTX_free(ctx);
2649 	ctx = NULL;
2650 	auth->peer_protocol_key = pr;
2651 	pr = NULL;
2652 
2653 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
2654 			auth->Nx, auth->secret_len);
2655 
2656 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
2657 			  auth->curve->hash_len) < 0)
2658 		goto fail;
2659 
2660 	addr[0] = hdr;
2661 	len[0] = DPP_HDR_LEN;
2662 	addr[1] = attr_start;
2663 	len[1] = attr_len;
2664 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2665 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2666 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2667 		    wrapped_data, wrapped_data_len);
2668 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2669 	unwrapped = os_malloc(unwrapped_len);
2670 	if (!unwrapped)
2671 		goto fail;
2672 	if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
2673 			    wrapped_data, wrapped_data_len,
2674 			    2, addr, len, unwrapped) < 0) {
2675 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2676 		goto fail;
2677 	}
2678 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2679 		    unwrapped, unwrapped_len);
2680 
2681 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2682 		wpa_printf(MSG_DEBUG,
2683 			   "DPP: Invalid attribute in unwrapped data");
2684 		goto fail;
2685 	}
2686 
2687 	r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
2688 			       &r_nonce_len);
2689 	if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
2690 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-nonce");
2691 		goto fail;
2692 	}
2693 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
2694 	os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
2695 
2696 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
2697 			       &i_nonce_len);
2698 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
2699 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
2700 		goto fail;
2701 	}
2702 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
2703 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
2704 		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
2705 		goto fail;
2706 	}
2707 
2708 	if (auth->own_bi && auth->peer_bi) {
2709 		/* Mutual authentication */
2710 		if (dpp_auth_derive_l_initiator(auth) < 0)
2711 			goto fail;
2712 	}
2713 
2714 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
2715 		goto fail;
2716 
2717 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
2718 			       DPP_ATTR_R_CAPABILITIES,
2719 			       &r_capab_len);
2720 	if (!r_capab || r_capab_len < 1) {
2721 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
2722 		goto fail;
2723 	}
2724 	auth->r_capab = r_capab[0];
2725 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
2726 	if ((auth->configurator && (auth->r_capab & DPP_CAPAB_CONFIGURATOR)) ||
2727 	    (!auth->configurator && (auth->r_capab & DPP_CAPAB_ENROLLEE))) {
2728 		wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
2729 		goto fail;
2730 	}
2731 
2732 	wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
2733 				DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
2734 	if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
2735 		wpa_printf(MSG_DEBUG,
2736 			   "DPP: Missing or invalid Secondary Wrapped Data");
2737 		goto fail;
2738 	}
2739 
2740 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2741 		    wrapped2, wrapped2_len);
2742 	unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
2743 	unwrapped2 = os_malloc(unwrapped2_len);
2744 	if (!unwrapped2)
2745 		goto fail;
2746 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2747 			    wrapped2, wrapped2_len,
2748 			    0, NULL, NULL, unwrapped2) < 0) {
2749 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2750 		goto fail;
2751 	}
2752 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2753 		    unwrapped2, unwrapped2_len);
2754 
2755 	if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
2756 		wpa_printf(MSG_DEBUG,
2757 			   "DPP: Invalid attribute in secondary unwrapped data");
2758 		goto fail;
2759 	}
2760 
2761 	r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
2762 			       &r_auth_len);
2763 	if (!r_auth || r_auth_len != auth->curve->hash_len) {
2764 		wpa_printf(MSG_DEBUG,
2765 			   "DPP: Missing or invalid Responder Authenticating Tag");
2766 		goto fail;
2767 	}
2768 	wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
2769 		    r_auth, r_auth_len);
2770 	/* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
2771 	if (dpp_gen_r_auth(auth, r_auth2) < 0)
2772 		goto fail;
2773 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
2774 		    r_auth2, r_auth_len);
2775 	if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
2776 		wpa_printf(MSG_DEBUG,
2777 			   "DPP: Mismatching Responder Authenticating Tag");
2778 		goto fail;
2779 	}
2780 
2781 	bin_clear_free(unwrapped, unwrapped_len);
2782 	bin_clear_free(unwrapped2, unwrapped2_len);
2783 
2784 	return dpp_auth_build_conf(auth);
2785 
2786 fail:
2787 	bin_clear_free(unwrapped, unwrapped_len);
2788 	bin_clear_free(unwrapped2, unwrapped2_len);
2789 	EVP_PKEY_free(pr);
2790 	EVP_PKEY_CTX_free(ctx);
2791 	return NULL;
2792 }
2793 
2794 
dpp_auth_conf_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)2795 int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
2796 		     const u8 *attr_start, size_t attr_len)
2797 {
2798 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
2799 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
2800 		i_auth_len;
2801 	const u8 *addr[2];
2802 	size_t len[2];
2803 	u8 *unwrapped = NULL;
2804 	size_t unwrapped_len = 0;
2805 	u8 i_auth2[DPP_MAX_HASH_LEN];
2806 
2807 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2808 				    &wrapped_data_len);
2809 	if (!wrapped_data) {
2810 		wpa_printf(MSG_DEBUG,
2811 			   "DPP: Missing required Wrapped data attribute");
2812 		return -1;
2813 	}
2814 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
2815 		    wrapped_data, wrapped_data_len);
2816 
2817 	if (wrapped_data_len < AES_BLOCK_SIZE)
2818 		return -1;
2819 
2820 	attr_len = wrapped_data - 4 - attr_start;
2821 
2822 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
2823 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2824 				   &r_bootstrap_len);
2825 	if (!r_bootstrap || r_bootstrap > wrapped_data ||
2826 	    r_bootstrap_len != SHA256_MAC_LEN) {
2827 		wpa_printf(MSG_DEBUG,
2828 			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2829 		return -1;
2830 	}
2831 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
2832 		    r_bootstrap, r_bootstrap_len);
2833 	if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
2834 		      SHA256_MAC_LEN) != 0) {
2835 		wpa_hexdump(MSG_DEBUG,
2836 			    "DPP: Expected Responder Bootstrapping Key Hash",
2837 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
2838 		return -1;
2839 	}
2840 
2841 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
2842 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
2843 				   &i_bootstrap_len);
2844 	if (i_bootstrap) {
2845 		if (i_bootstrap > wrapped_data ||
2846 		    i_bootstrap_len != SHA256_MAC_LEN) {
2847 			wpa_printf(MSG_DEBUG,
2848 				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
2849 			return -1;
2850 		}
2851 		wpa_hexdump(MSG_MSGDUMP,
2852 			    "DPP: Initiator Bootstrapping Key Hash",
2853 			    i_bootstrap, i_bootstrap_len);
2854 		if (!auth->peer_bi ||
2855 		    os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
2856 			      SHA256_MAC_LEN) != 0) {
2857 			wpa_printf(MSG_DEBUG,
2858 				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
2859 			return -1;
2860 		}
2861 	}
2862 
2863 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
2864 			      &status_len);
2865 	if (!status || status_len < 1) {
2866 		wpa_printf(MSG_DEBUG,
2867 			   "DPP: Missing or invalid required DPP Status attribute");
2868 		return -1;
2869 	}
2870 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
2871 	if (status[0] != DPP_STATUS_OK) {
2872 		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
2873 		return -1;
2874 	}
2875 
2876 	addr[0] = hdr;
2877 	len[0] = DPP_HDR_LEN;
2878 	addr[1] = attr_start;
2879 	len[1] = attr_len;
2880 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
2881 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
2882 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2883 		    wrapped_data, wrapped_data_len);
2884 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2885 	unwrapped = os_malloc(unwrapped_len);
2886 	if (!unwrapped)
2887 		return -1;
2888 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2889 			    wrapped_data, wrapped_data_len,
2890 			    2, addr, len, unwrapped) < 0) {
2891 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
2892 		goto fail;
2893 	}
2894 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2895 		    unwrapped, unwrapped_len);
2896 
2897 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2898 		wpa_printf(MSG_DEBUG,
2899 			   "DPP: Invalid attribute in unwrapped data");
2900 		goto fail;
2901 	}
2902 
2903 	i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
2904 			      &i_auth_len);
2905 	if (!i_auth || i_auth_len != auth->curve->hash_len) {
2906 		wpa_printf(MSG_DEBUG,
2907 			   "DPP: Missing or invalid Initiator Authenticating Tag");
2908 		goto fail;
2909 	}
2910 	wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
2911 		    i_auth, i_auth_len);
2912 	/* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
2913 	if (dpp_gen_i_auth(auth, i_auth2) < 0)
2914 		goto fail;
2915 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
2916 		    i_auth2, i_auth_len);
2917 	if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
2918 		wpa_printf(MSG_DEBUG,
2919 			   "DPP: Mismatching Initiator Authenticating Tag");
2920 		goto fail;
2921 	}
2922 
2923 	bin_clear_free(unwrapped, unwrapped_len);
2924 	dpp_auth_success(auth);
2925 	return 0;
2926 fail:
2927 	bin_clear_free(unwrapped, unwrapped_len);
2928 	return -1;
2929 }
2930 
2931 
dpp_configuration_free(struct dpp_configuration * conf)2932 void dpp_configuration_free(struct dpp_configuration *conf)
2933 {
2934 	if (!conf)
2935 		return;
2936 	str_clear_free(conf->passphrase);
2937 	bin_clear_free(conf, sizeof(*conf));
2938 }
2939 
2940 
dpp_auth_deinit(struct dpp_authentication * auth)2941 void dpp_auth_deinit(struct dpp_authentication *auth)
2942 {
2943 	if (!auth)
2944 		return;
2945 	dpp_configuration_free(auth->conf_ap);
2946 	dpp_configuration_free(auth->conf_sta);
2947 	EVP_PKEY_free(auth->own_protocol_key);
2948 	EVP_PKEY_free(auth->peer_protocol_key);
2949 	wpabuf_free(auth->req_msg);
2950 	wpabuf_free(auth->resp_msg);
2951 	wpabuf_free(auth->conf_req);
2952 	os_free(auth->connector);
2953 	wpabuf_free(auth->net_access_key);
2954 	wpabuf_free(auth->c_sign_key);
2955 #ifdef CONFIG_TESTING_OPTIONS
2956 	os_free(auth->config_obj_override);
2957 	os_free(auth->discovery_override);
2958 	os_free(auth->groups_override);
2959 #endif /* CONFIG_TESTING_OPTIONS */
2960 	bin_clear_free(auth, sizeof(*auth));
2961 }
2962 
2963 
2964 static struct wpabuf *
dpp_build_conf_start(struct dpp_authentication * auth,struct dpp_configuration * conf,size_t tailroom)2965 dpp_build_conf_start(struct dpp_authentication *auth,
2966 		     struct dpp_configuration *conf, size_t tailroom)
2967 {
2968 	struct wpabuf *buf;
2969 	char ssid[6 * sizeof(conf->ssid) + 1];
2970 
2971 #ifdef CONFIG_TESTING_OPTIONS
2972 	if (auth->discovery_override)
2973 		tailroom += os_strlen(auth->discovery_override);
2974 #endif /* CONFIG_TESTING_OPTIONS */
2975 
2976 	buf = wpabuf_alloc(200 + tailroom);
2977 	if (!buf)
2978 		return NULL;
2979 	wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":");
2980 #ifdef CONFIG_TESTING_OPTIONS
2981 	if (auth->discovery_override) {
2982 		wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
2983 			   auth->discovery_override);
2984 		wpabuf_put_str(buf, auth->discovery_override);
2985 		wpabuf_put_u8(buf, ',');
2986 		return buf;
2987 	}
2988 #endif /* CONFIG_TESTING_OPTIONS */
2989 	wpabuf_put_str(buf, "{\"ssid\":\"");
2990 	json_escape_string(ssid, sizeof(ssid),
2991 			   (const char *) conf->ssid, conf->ssid_len);
2992 	wpabuf_put_str(buf, ssid);
2993 	wpabuf_put_str(buf, "\"");
2994 	/* TODO: optional channel information */
2995 	wpabuf_put_str(buf, "},");
2996 
2997 	return buf;
2998 }
2999 
3000 
dpp_bn2bin_pad(const BIGNUM * bn,u8 * pos,size_t len)3001 static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
3002 {
3003 	int num_bytes, offset;
3004 
3005 	num_bytes = BN_num_bytes(bn);
3006 	if ((size_t) num_bytes > len)
3007 		return -1;
3008 	offset = len - num_bytes;
3009 	os_memset(pos, 0, offset);
3010 	BN_bn2bin(bn, pos + offset);
3011 	return 0;
3012 }
3013 
3014 
dpp_build_jwk(struct wpabuf * buf,const char * name,EVP_PKEY * key,const char * kid,const struct dpp_curve_params * curve)3015 static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
3016 			 const char *kid, const struct dpp_curve_params *curve)
3017 {
3018 	struct wpabuf *pub;
3019 	const u8 *pos;
3020 	char *x = NULL, *y = NULL;
3021 	int ret = -1;
3022 
3023 	pub = dpp_get_pubkey_point(key, 0);
3024 	if (!pub)
3025 		goto fail;
3026 	pos = wpabuf_head(pub);
3027 	x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
3028 	pos += curve->prime_len;
3029 	y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
3030 	if (!x || !y)
3031 		goto fail;
3032 
3033 	wpabuf_put_str(buf, "\"");
3034 	wpabuf_put_str(buf, name);
3035 	wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\"");
3036 	wpabuf_put_str(buf, curve->jwk_crv);
3037 	wpabuf_put_str(buf, "\",\"x\":\"");
3038 	wpabuf_put_str(buf, x);
3039 	wpabuf_put_str(buf, "\",\"y\":\"");
3040 	wpabuf_put_str(buf, y);
3041 	if (kid) {
3042 		wpabuf_put_str(buf, "\",\"kid\":\"");
3043 		wpabuf_put_str(buf, kid);
3044 	}
3045 	wpabuf_put_str(buf, "\"}");
3046 	ret = 0;
3047 fail:
3048 	wpabuf_free(pub);
3049 	os_free(x);
3050 	os_free(y);
3051 	return ret;
3052 }
3053 
3054 
3055 static struct wpabuf *
dpp_build_conf_obj_dpp(struct dpp_authentication * auth,int ap,struct dpp_configuration * conf)3056 dpp_build_conf_obj_dpp(struct dpp_authentication *auth, int ap,
3057 		       struct dpp_configuration *conf)
3058 {
3059 	struct wpabuf *buf = NULL;
3060 	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
3061 	size_t tailroom;
3062 	const struct dpp_curve_params *curve;
3063 	char jws_prot_hdr[100];
3064 	size_t signed1_len, signed2_len, signed3_len;
3065 	struct wpabuf *dppcon = NULL;
3066 	unsigned char *signature = NULL;
3067 	const unsigned char *p;
3068 	size_t signature_len;
3069 	EVP_MD_CTX *md_ctx = NULL;
3070 	ECDSA_SIG *sig = NULL;
3071 	char *dot = ".";
3072 	const EVP_MD *sign_md;
3073 	const BIGNUM *r, *s;
3074 	size_t extra_len = 1000;
3075 
3076 	if (!auth->conf) {
3077 		wpa_printf(MSG_INFO,
3078 			   "DPP: No configurator specified - cannot generate DPP config object");
3079 		goto fail;
3080 	}
3081 	curve = auth->conf->curve;
3082 	if (curve->hash_len == SHA256_MAC_LEN) {
3083 		sign_md = EVP_sha256();
3084 	} else if (curve->hash_len == SHA384_MAC_LEN) {
3085 		sign_md = EVP_sha384();
3086 	} else if (curve->hash_len == SHA512_MAC_LEN) {
3087 		sign_md = EVP_sha512();
3088 	} else {
3089 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
3090 		goto fail;
3091 	}
3092 
3093 #ifdef CONFIG_TESTING_OPTIONS
3094 	if (auth->groups_override)
3095 		extra_len += os_strlen(auth->groups_override);
3096 #endif /* CONFIG_TESTING_OPTIONS */
3097 
3098 	/* Connector (JSON dppCon object) */
3099 	dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3);
3100 	if (!dppcon)
3101 		goto fail;
3102 #ifdef CONFIG_TESTING_OPTIONS
3103 	if (auth->groups_override) {
3104 		wpabuf_put_u8(dppcon, '{');
3105 		if (auth->groups_override) {
3106 			wpa_printf(MSG_DEBUG,
3107 				   "DPP: TESTING - groups override: '%s'",
3108 				   auth->groups_override);
3109 			wpabuf_put_str(dppcon, "\"groups\":");
3110 			wpabuf_put_str(dppcon, auth->groups_override);
3111 			wpabuf_put_u8(dppcon, ',');
3112 		}
3113 		goto skip_groups;
3114 	}
3115 #endif /* CONFIG_TESTING_OPTIONS */
3116 	wpabuf_put_str(dppcon, "{\"groups\":[{\"groupId\":\"*\",");
3117 	wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],", ap ? "ap" : "sta");
3118 #ifdef CONFIG_TESTING_OPTIONS
3119 skip_groups:
3120 #endif /* CONFIG_TESTING_OPTIONS */
3121 	if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
3122 			  auth->curve) < 0) {
3123 		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
3124 		goto fail;
3125 	}
3126 	if (conf->netaccesskey_expiry) {
3127 		struct os_tm tm;
3128 
3129 		if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
3130 			wpa_printf(MSG_DEBUG,
3131 				   "DPP: Failed to generate expiry string");
3132 			goto fail;
3133 		}
3134 		wpabuf_printf(dppcon,
3135 			      ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"",
3136 			      tm.year, tm.month, tm.day,
3137 			      tm.hour, tm.min, tm.sec);
3138 	}
3139 	wpabuf_put_u8(dppcon, '}');
3140 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
3141 		   (const char *) wpabuf_head(dppcon));
3142 
3143 	os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr),
3144 		    "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}",
3145 		    auth->conf->kid, curve->jws_alg);
3146 	signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr,
3147 					     os_strlen(jws_prot_hdr),
3148 					     &signed1_len, 0);
3149 	signed2 = (char *) base64_url_encode(wpabuf_head(dppcon),
3150 					     wpabuf_len(dppcon),
3151 					     &signed2_len, 0);
3152 	if (!signed1 || !signed2)
3153 		goto fail;
3154 
3155 	md_ctx = EVP_MD_CTX_create();
3156 	if (!md_ctx)
3157 		goto fail;
3158 
3159 	ERR_clear_error();
3160 	if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL,
3161 			       auth->conf->csign) != 1) {
3162 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
3163 			   ERR_error_string(ERR_get_error(), NULL));
3164 		goto fail;
3165 	}
3166 	if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
3167 	    EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
3168 	    EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
3169 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
3170 			   ERR_error_string(ERR_get_error(), NULL));
3171 		goto fail;
3172 	}
3173 	if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
3174 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
3175 			   ERR_error_string(ERR_get_error(), NULL));
3176 		goto fail;
3177 	}
3178 	signature = os_malloc(signature_len);
3179 	if (!signature)
3180 		goto fail;
3181 	if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
3182 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
3183 			   ERR_error_string(ERR_get_error(), NULL));
3184 		goto fail;
3185 	}
3186 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
3187 		    signature, signature_len);
3188 	/* Convert to raw coordinates r,s */
3189 	p = signature;
3190 	sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
3191 	if (!sig)
3192 		goto fail;
3193 	ECDSA_SIG_get0(sig, &r, &s);
3194 	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
3195 	    dpp_bn2bin_pad(s, signature + curve->prime_len,
3196 			   curve->prime_len) < 0)
3197 		goto fail;
3198 	signature_len = 2 * curve->prime_len;
3199 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
3200 		    signature, signature_len);
3201 	signed3 = (char *) base64_url_encode(signature, signature_len,
3202 					     &signed3_len, 0);
3203 	if (!signed3)
3204 		goto fail;
3205 
3206 	tailroom = 1000;
3207 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
3208 	tailroom += signed1_len + signed2_len + signed3_len;
3209 	buf = dpp_build_conf_start(auth, conf, tailroom);
3210 	if (!buf)
3211 		return NULL;
3212 
3213 	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"dpp\",\"signedConnector\":\"");
3214 	wpabuf_put_str(buf, signed1);
3215 	wpabuf_put_u8(buf, '.');
3216 	wpabuf_put_str(buf, signed2);
3217 	wpabuf_put_u8(buf, '.');
3218 	wpabuf_put_str(buf, signed3);
3219 	wpabuf_put_str(buf, "\",");
3220 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
3221 			  curve) < 0) {
3222 		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
3223 		goto fail;
3224 	}
3225 
3226 	wpabuf_put_str(buf, "}}");
3227 
3228 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
3229 			      wpabuf_head(buf), wpabuf_len(buf));
3230 
3231 out:
3232 	EVP_MD_CTX_destroy(md_ctx);
3233 	ECDSA_SIG_free(sig);
3234 	os_free(signed1);
3235 	os_free(signed2);
3236 	os_free(signed3);
3237 	os_free(signature);
3238 	wpabuf_free(dppcon);
3239 	return buf;
3240 fail:
3241 	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
3242 	wpabuf_free(buf);
3243 	buf = NULL;
3244 	goto out;
3245 }
3246 
3247 
3248 static struct wpabuf *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,int ap,struct dpp_configuration * conf)3249 dpp_build_conf_obj_legacy(struct dpp_authentication *auth, int ap,
3250 			  struct dpp_configuration *conf)
3251 {
3252 	struct wpabuf *buf;
3253 
3254 	buf = dpp_build_conf_start(auth, conf, 1000);
3255 	if (!buf)
3256 		return NULL;
3257 
3258 	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"psk\",");
3259 	if (conf->passphrase) {
3260 		char pass[63 * 6 + 1];
3261 
3262 		if (os_strlen(conf->passphrase) > 63) {
3263 			wpabuf_free(buf);
3264 			return NULL;
3265 		}
3266 
3267 		json_escape_string(pass, sizeof(pass), conf->passphrase,
3268 				   os_strlen(conf->passphrase));
3269 		wpabuf_put_str(buf, "\"pass\":\"");
3270 		wpabuf_put_str(buf, pass);
3271 		wpabuf_put_str(buf, "\"");
3272 	} else {
3273 		char psk[2 * sizeof(conf->psk) + 1];
3274 
3275 		wpa_snprintf_hex(psk, sizeof(psk),
3276 				 conf->psk, sizeof(conf->psk));
3277 		wpabuf_put_str(buf, "\"psk_hex\":\"");
3278 		wpabuf_put_str(buf, psk);
3279 		wpabuf_put_str(buf, "\"");
3280 	}
3281 	wpabuf_put_str(buf, "}}");
3282 
3283 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
3284 			      wpabuf_head(buf), wpabuf_len(buf));
3285 
3286 	return buf;
3287 }
3288 
3289 
3290 static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication * auth,int ap)3291 dpp_build_conf_obj(struct dpp_authentication *auth, int ap)
3292 {
3293 	struct dpp_configuration *conf;
3294 
3295 #ifdef CONFIG_TESTING_OPTIONS
3296 	if (auth->config_obj_override) {
3297 		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
3298 		return wpabuf_alloc_copy(auth->config_obj_override,
3299 					 os_strlen(auth->config_obj_override));
3300 	}
3301 #endif /* CONFIG_TESTING_OPTIONS */
3302 
3303 	conf = ap ? auth->conf_ap : auth->conf_sta;
3304 	if (!conf) {
3305 		wpa_printf(MSG_DEBUG,
3306 			   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
3307 			   ap ? "ap" : "sta");
3308 		return NULL;
3309 	}
3310 
3311 	if (conf->dpp)
3312 		return dpp_build_conf_obj_dpp(auth, ap, conf);
3313 	return dpp_build_conf_obj_legacy(auth, ap, conf);
3314 }
3315 
3316 
3317 static struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,int ap)3318 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
3319 		    u16 e_nonce_len, int ap)
3320 {
3321 	struct wpabuf *conf;
3322 	size_t clear_len;
3323 	struct wpabuf *clear = NULL, *msg = NULL;
3324 	u8 *wrapped;
3325 	const u8 *addr[1];
3326 	size_t len[1];
3327 	enum dpp_status_error status;
3328 
3329 	conf = dpp_build_conf_obj(auth, ap);
3330 	if (conf) {
3331 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
3332 				  wpabuf_head(conf), wpabuf_len(conf));
3333 	}
3334 	status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
3335 
3336 	/* { E-nonce, configurationObject}ke */
3337 	clear_len = 4 + e_nonce_len;
3338 	if (conf)
3339 		clear_len += 4 + wpabuf_len(conf);
3340 	clear = wpabuf_alloc(clear_len);
3341 	msg = wpabuf_alloc(4 + 1 + 4 + clear_len + AES_BLOCK_SIZE);
3342 	if (!clear || !msg)
3343 		goto fail;
3344 
3345 	/* E-nonce */
3346 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
3347 	wpabuf_put_le16(clear, e_nonce_len);
3348 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
3349 
3350 	if (conf) {
3351 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
3352 		wpabuf_put_le16(clear, wpabuf_len(conf));
3353 		wpabuf_put_buf(clear, conf);
3354 		wpabuf_free(conf);
3355 		conf = NULL;
3356 	}
3357 
3358 	/* DPP Status */
3359 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
3360 	wpabuf_put_le16(msg, 1);
3361 	wpabuf_put_u8(msg, status);
3362 
3363 	addr[0] = wpabuf_head(msg);
3364 	len[0] = wpabuf_len(msg);
3365 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
3366 
3367 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3368 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3369 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3370 
3371 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
3372 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3373 			    wpabuf_head(clear), wpabuf_len(clear),
3374 			    1, addr, len, wrapped) < 0)
3375 		goto fail;
3376 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3377 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
3378 	wpabuf_free(clear);
3379 	clear = NULL;
3380 
3381 	wpa_hexdump_buf(MSG_DEBUG,
3382 			"DPP: Configuration Response attributes", msg);
3383 	return msg;
3384 fail:
3385 	wpabuf_free(conf);
3386 	wpabuf_free(clear);
3387 	wpabuf_free(msg);
3388 	return NULL;
3389 }
3390 
3391 
3392 struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)3393 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
3394 		size_t attr_len)
3395 {
3396 	const u8 *wrapped_data, *e_nonce, *config_attr;
3397 	u16 wrapped_data_len, e_nonce_len, config_attr_len;
3398 	u8 *unwrapped = NULL;
3399 	size_t unwrapped_len = 0;
3400 	struct wpabuf *resp = NULL;
3401 	struct json_token *root = NULL, *token;
3402 	int ap;
3403 
3404 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
3405 		wpa_printf(MSG_DEBUG,
3406 			   "DPP: Invalid attribute in config request");
3407 		return NULL;
3408 	}
3409 
3410 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3411 				    &wrapped_data_len);
3412 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3413 		wpa_printf(MSG_DEBUG,
3414 			   "DPP: Missing or invalid required Wrapped data attribute");
3415 		return NULL;
3416 	}
3417 
3418 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3419 		    wrapped_data, wrapped_data_len);
3420 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3421 	unwrapped = os_malloc(unwrapped_len);
3422 	if (!unwrapped)
3423 		return NULL;
3424 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3425 			    wrapped_data, wrapped_data_len,
3426 			    0, NULL, NULL, unwrapped) < 0) {
3427 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
3428 		goto fail;
3429 	}
3430 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3431 		    unwrapped, unwrapped_len);
3432 
3433 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3434 		wpa_printf(MSG_DEBUG,
3435 			   "DPP: Invalid attribute in unwrapped data");
3436 		goto fail;
3437 	}
3438 
3439 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3440 			       DPP_ATTR_ENROLLEE_NONCE,
3441 			       &e_nonce_len);
3442 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3443 		wpa_printf(MSG_DEBUG,
3444 			   "DPP: Missing or invalid Enrollee Nonce attribute");
3445 		goto fail;
3446 	}
3447 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3448 
3449 	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
3450 				   DPP_ATTR_CONFIG_ATTR_OBJ,
3451 				   &config_attr_len);
3452 	if (!config_attr) {
3453 		wpa_printf(MSG_DEBUG,
3454 			   "DPP: Missing or invalid Config Attributes attribute");
3455 		goto fail;
3456 	}
3457 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
3458 			  config_attr, config_attr_len);
3459 
3460 	root = json_parse((const char *) config_attr, config_attr_len);
3461 	if (!root) {
3462 		wpa_printf(MSG_DEBUG, "DPP: Could not parse Config Attributes");
3463 		goto fail;
3464 	}
3465 
3466 	token = json_get_member(root, "name");
3467 	if (!token || token->type != JSON_STRING) {
3468 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - name");
3469 		goto fail;
3470 	}
3471 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
3472 
3473 	token = json_get_member(root, "wi-fi_tech");
3474 	if (!token || token->type != JSON_STRING) {
3475 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - wi-fi_tech");
3476 		goto fail;
3477 	}
3478 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
3479 	if (os_strcmp(token->string, "infra") != 0) {
3480 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
3481 			   token->string);
3482 		goto fail;
3483 	}
3484 
3485 	token = json_get_member(root, "netRole");
3486 	if (!token || token->type != JSON_STRING) {
3487 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - netRole");
3488 		goto fail;
3489 	}
3490 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
3491 	if (os_strcmp(token->string, "sta") == 0) {
3492 		ap = 0;
3493 	} else if (os_strcmp(token->string, "ap") == 0) {
3494 		ap = 1;
3495 	} else {
3496 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
3497 			   token->string);
3498 		goto fail;
3499 	}
3500 
3501 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, ap);
3502 
3503 fail:
3504 	json_free(root);
3505 	os_free(unwrapped);
3506 	return resp;
3507 }
3508 
3509 
3510 static struct wpabuf *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params * curve,const u8 * prot_hdr,u16 prot_hdr_len,const EVP_MD ** ret_md)3511 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
3512 		       const u8 *prot_hdr, u16 prot_hdr_len,
3513 		       const EVP_MD **ret_md)
3514 {
3515 	struct json_token *root, *token;
3516 	struct wpabuf *kid = NULL;
3517 
3518 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
3519 	if (!root) {
3520 		wpa_printf(MSG_DEBUG,
3521 			   "DPP: JSON parsing failed for JWS Protected Header");
3522 		goto fail;
3523 	}
3524 
3525 	if (root->type != JSON_OBJECT) {
3526 		wpa_printf(MSG_DEBUG,
3527 			   "DPP: JWS Protected Header root is not an object");
3528 		goto fail;
3529 	}
3530 
3531 	token = json_get_member(root, "typ");
3532 	if (!token || token->type != JSON_STRING) {
3533 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
3534 		goto fail;
3535 	}
3536 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
3537 		   token->string);
3538 	if (os_strcmp(token->string, "dppCon") != 0) {
3539 		wpa_printf(MSG_DEBUG,
3540 			   "DPP: Unsupported JWS Protected Header typ=%s",
3541 			   token->string);
3542 		goto fail;
3543 	}
3544 
3545 	token = json_get_member(root, "alg");
3546 	if (!token || token->type != JSON_STRING) {
3547 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
3548 		goto fail;
3549 	}
3550 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
3551 		   token->string);
3552 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
3553 		wpa_printf(MSG_DEBUG,
3554 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
3555 			   token->string, curve->jws_alg);
3556 		goto fail;
3557 	}
3558 	if (os_strcmp(token->string, "ES256") == 0 ||
3559 	    os_strcmp(token->string, "BS256") == 0)
3560 		*ret_md = EVP_sha256();
3561 	else if (os_strcmp(token->string, "ES384") == 0 ||
3562 		 os_strcmp(token->string, "BS384") == 0)
3563 		*ret_md = EVP_sha384();
3564 	else if (os_strcmp(token->string, "ES512") == 0 ||
3565 		 os_strcmp(token->string, "BS512") == 0)
3566 		*ret_md = EVP_sha512();
3567 	else
3568 		*ret_md = NULL;
3569 	if (!*ret_md) {
3570 		wpa_printf(MSG_DEBUG,
3571 			   "DPP: Unsupported JWS Protected Header alg=%s",
3572 			   token->string);
3573 		goto fail;
3574 	}
3575 
3576 	kid = json_get_member_base64url(root, "kid");
3577 	if (!kid) {
3578 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
3579 		goto fail;
3580 	}
3581 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
3582 			kid);
3583 
3584 fail:
3585 	json_free(root);
3586 	return kid;
3587 }
3588 
3589 
dpp_parse_cred_legacy(struct dpp_authentication * auth,struct json_token * cred)3590 static int dpp_parse_cred_legacy(struct dpp_authentication *auth,
3591 				 struct json_token *cred)
3592 {
3593 	struct json_token *pass, *psk_hex;
3594 
3595 	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
3596 
3597 	pass = json_get_member(cred, "pass");
3598 	psk_hex = json_get_member(cred, "psk_hex");
3599 
3600 	if (pass && pass->type == JSON_STRING) {
3601 		size_t len = os_strlen(pass->string);
3602 
3603 		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
3604 				      pass->string, len);
3605 		if (len < 8 || len > 63)
3606 			return -1;
3607 		os_strlcpy(auth->passphrase, pass->string,
3608 			   sizeof(auth->passphrase));
3609 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
3610 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
3611 		    hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) {
3612 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
3613 			return -1;
3614 		}
3615 		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
3616 				auth->psk, PMK_LEN);
3617 		auth->psk_set = 1;
3618 	} else {
3619 		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
3620 		return -1;
3621 	}
3622 
3623 	return 0;
3624 }
3625 
3626 
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)3627 static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
3628 				const struct dpp_curve_params **key_curve)
3629 {
3630 	struct json_token *token;
3631 	const struct dpp_curve_params *curve;
3632 	struct wpabuf *x = NULL, *y = NULL;
3633 	EC_GROUP *group;
3634 	EVP_PKEY *pkey = NULL;
3635 
3636 	token = json_get_member(jwk, "kty");
3637 	if (!token || token->type != JSON_STRING) {
3638 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
3639 		goto fail;
3640 	}
3641 	if (os_strcmp(token->string, "EC") != 0) {
3642 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s",
3643 			   token->string);
3644 		goto fail;
3645 	}
3646 
3647 	token = json_get_member(jwk, "crv");
3648 	if (!token || token->type != JSON_STRING) {
3649 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
3650 		goto fail;
3651 	}
3652 	curve = dpp_get_curve_jwk_crv(token->string);
3653 	if (!curve) {
3654 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
3655 			   token->string);
3656 		goto fail;
3657 	}
3658 
3659 	x = json_get_member_base64url(jwk, "x");
3660 	if (!x) {
3661 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
3662 		goto fail;
3663 	}
3664 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
3665 	if (wpabuf_len(x) != curve->prime_len) {
3666 		wpa_printf(MSG_DEBUG,
3667 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
3668 			   (unsigned int) wpabuf_len(x),
3669 			   (unsigned int) curve->prime_len, curve->name);
3670 		goto fail;
3671 	}
3672 
3673 	y = json_get_member_base64url(jwk, "y");
3674 	if (!y) {
3675 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
3676 		goto fail;
3677 	}
3678 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
3679 	if (wpabuf_len(y) != curve->prime_len) {
3680 		wpa_printf(MSG_DEBUG,
3681 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
3682 			   (unsigned int) wpabuf_len(y),
3683 			   (unsigned int) curve->prime_len, curve->name);
3684 		goto fail;
3685 	}
3686 
3687 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
3688 	if (!group) {
3689 		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
3690 		goto fail;
3691 	}
3692 
3693 	pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y),
3694 					  wpabuf_len(x));
3695 	*key_curve = curve;
3696 
3697 fail:
3698 	wpabuf_free(x);
3699 	wpabuf_free(y);
3700 
3701 	return pkey;
3702 }
3703 
3704 
dpp_key_expired(const char * timestamp,os_time_t * expiry)3705 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
3706 {
3707 	struct os_time now;
3708 	unsigned int year, month, day, hour, min, sec;
3709 	os_time_t utime;
3710 	const char *pos;
3711 
3712 	/* ISO 8601 date and time:
3713 	 * <date>T<time>
3714 	 * YYYY-MM-DDTHH:MM:SSZ
3715 	 * YYYY-MM-DDTHH:MM:SS+03:00
3716 	 */
3717 	if (os_strlen(timestamp) < 19) {
3718 		wpa_printf(MSG_DEBUG,
3719 			   "DPP: Too short timestamp - assume expired key");
3720 		return 1;
3721 	}
3722 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
3723 		   &year, &month, &day, &hour, &min, &sec) != 6) {
3724 		wpa_printf(MSG_DEBUG,
3725 			   "DPP: Failed to parse expiration day - assume expired key");
3726 		return 1;
3727 	}
3728 
3729 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
3730 		wpa_printf(MSG_DEBUG,
3731 			   "DPP: Invalid date/time information - assume expired key");
3732 		return 1;
3733 	}
3734 
3735 	pos = timestamp + 19;
3736 	if (*pos == 'Z' || *pos == '\0') {
3737 		/* In UTC - no need to adjust */
3738 	} else if (*pos == '-' || *pos == '+') {
3739 		int items;
3740 
3741 		/* Adjust local time to UTC */
3742 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
3743 		if (items < 1) {
3744 			wpa_printf(MSG_DEBUG,
3745 				   "DPP: Invalid time zone designator (%s) - assume expired key",
3746 				   pos);
3747 			return 1;
3748 		}
3749 		if (*pos == '-')
3750 			utime += 3600 * hour;
3751 		if (*pos == '+')
3752 			utime -= 3600 * hour;
3753 		if (items > 1) {
3754 			if (*pos == '-')
3755 				utime += 60 * min;
3756 			if (*pos == '+')
3757 				utime -= 60 * min;
3758 		}
3759 	} else {
3760 		wpa_printf(MSG_DEBUG,
3761 			   "DPP: Invalid time zone designator (%s) - assume expired key",
3762 			   pos);
3763 		return 1;
3764 	}
3765 	if (expiry)
3766 		*expiry = utime;
3767 
3768 	if (os_get_time(&now) < 0) {
3769 		wpa_printf(MSG_DEBUG,
3770 			   "DPP: Cannot get current time - assume expired key");
3771 		return 1;
3772 	}
3773 
3774 	if (now.sec > utime) {
3775 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
3776 			   utime, now.sec);
3777 		return 1;
3778 	}
3779 
3780 	return 0;
3781 }
3782 
3783 
dpp_parse_connector(struct dpp_authentication * auth,const unsigned char * payload,u16 payload_len)3784 static int dpp_parse_connector(struct dpp_authentication *auth,
3785 			       const unsigned char *payload,
3786 			       u16 payload_len)
3787 {
3788 	struct json_token *root, *groups, *netkey, *token;
3789 	int ret = -1;
3790 	EVP_PKEY *key = NULL;
3791 	const struct dpp_curve_params *curve;
3792 	unsigned int rules = 0;
3793 
3794 	root = json_parse((const char *) payload, payload_len);
3795 	if (!root) {
3796 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
3797 		goto fail;
3798 	}
3799 
3800 	groups = json_get_member(root, "groups");
3801 	if (!groups || groups->type != JSON_ARRAY) {
3802 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
3803 		goto skip_groups;
3804 	}
3805 	for (token = groups->child; token; token = token->sibling) {
3806 		struct json_token *id, *role;
3807 
3808 		id = json_get_member(token, "groupId");
3809 		if (!id || id->type != JSON_STRING) {
3810 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
3811 			goto fail;
3812 		}
3813 
3814 		role = json_get_member(token, "netRole");
3815 		if (!role || role->type != JSON_STRING) {
3816 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
3817 			goto fail;
3818 		}
3819 		wpa_printf(MSG_DEBUG,
3820 			   "DPP: connector group: groupId='%s' netRole='%s'",
3821 			   id->string, role->string);
3822 		rules++;
3823 	}
3824 skip_groups:
3825 
3826 	if (!rules) {
3827 		wpa_printf(MSG_DEBUG,
3828 			   "DPP: Connector includes no groups");
3829 		goto fail;
3830 	}
3831 
3832 	token = json_get_member(root, "expiry");
3833 	if (!token || token->type != JSON_STRING) {
3834 		wpa_printf(MSG_DEBUG,
3835 			   "DPP: No expiry string found - connector does not expire");
3836 	} else {
3837 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
3838 		if (dpp_key_expired(token->string,
3839 				    &auth->net_access_key_expiry)) {
3840 			wpa_printf(MSG_DEBUG,
3841 				   "DPP: Connector (netAccessKey) has expired");
3842 			goto fail;
3843 		}
3844 	}
3845 
3846 	netkey = json_get_member(root, "netAccessKey");
3847 	if (!netkey || netkey->type != JSON_OBJECT) {
3848 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
3849 		goto fail;
3850 	}
3851 
3852 	key = dpp_parse_jwk(netkey, &curve);
3853 	if (!key)
3854 		goto fail;
3855 	dpp_debug_print_key("DPP: Received netAccessKey", key);
3856 
3857 	if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
3858 		wpa_printf(MSG_DEBUG,
3859 			   "DPP: netAccessKey in connector does not match own protocol key");
3860 #ifdef CONFIG_TESTING_OPTIONS
3861 		if (auth->ignore_netaccesskey_mismatch) {
3862 			wpa_printf(MSG_DEBUG,
3863 				   "DPP: TESTING - skip netAccessKey mismatch");
3864 		} else {
3865 			goto fail;
3866 		}
3867 #else /* CONFIG_TESTING_OPTIONS */
3868 		goto fail;
3869 #endif /* CONFIG_TESTING_OPTIONS */
3870 	}
3871 
3872 	ret = 0;
3873 fail:
3874 	EVP_PKEY_free(key);
3875 	json_free(root);
3876 	return ret;
3877 }
3878 
3879 
dpp_check_pubkey_match(EVP_PKEY * pub,struct wpabuf * r_hash)3880 static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
3881 {
3882 	struct wpabuf *uncomp;
3883 	int res;
3884 	u8 hash[SHA256_MAC_LEN];
3885 	const u8 *addr[1];
3886 	size_t len[1];
3887 
3888 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
3889 		return -1;
3890 	uncomp = dpp_get_pubkey_point(pub, 1);
3891 	if (!uncomp)
3892 		return -1;
3893 	addr[0] = wpabuf_head(uncomp);
3894 	len[0] = wpabuf_len(uncomp);
3895 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
3896 		    addr[0], len[0]);
3897 	res = sha256_vector(1, addr, len, hash);
3898 	wpabuf_free(uncomp);
3899 	if (res < 0)
3900 		return -1;
3901 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
3902 		wpa_printf(MSG_DEBUG,
3903 			   "DPP: Received hash value does not match calculated public key hash value");
3904 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
3905 			    hash, SHA256_MAC_LEN);
3906 		return -1;
3907 	}
3908 	return 0;
3909 }
3910 
3911 
dpp_copy_csign(struct dpp_authentication * auth,EVP_PKEY * csign)3912 static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign)
3913 {
3914 	unsigned char *der = NULL;
3915 	int der_len;
3916 
3917 	der_len = i2d_PUBKEY(csign, &der);
3918 	if (der_len <= 0)
3919 		return;
3920 	wpabuf_free(auth->c_sign_key);
3921 	auth->c_sign_key = wpabuf_alloc_copy(der, der_len);
3922 	OPENSSL_free(der);
3923 }
3924 
3925 
dpp_copy_netaccesskey(struct dpp_authentication * auth)3926 static void dpp_copy_netaccesskey(struct dpp_authentication *auth)
3927 {
3928 	unsigned char *der = NULL;
3929 	int der_len;
3930 	EC_KEY *eckey;
3931 
3932 	eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
3933 	if (!eckey)
3934 		return;
3935 
3936 	der_len = i2d_ECPrivateKey(eckey, &der);
3937 	if (der_len <= 0) {
3938 		EC_KEY_free(eckey);
3939 		return;
3940 	}
3941 	wpabuf_free(auth->net_access_key);
3942 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
3943 	OPENSSL_free(der);
3944 	EC_KEY_free(eckey);
3945 }
3946 
3947 
3948 struct dpp_signed_connector_info {
3949 	unsigned char *payload;
3950 	size_t payload_len;
3951 };
3952 
3953 static int
dpp_process_signed_connector(struct dpp_signed_connector_info * info,EVP_PKEY * csign_pub,const char * connector)3954 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
3955 			     EVP_PKEY *csign_pub, const char *connector)
3956 {
3957 	int ret = -1;
3958 	const char *pos, *end, *signed_start, *signed_end;
3959 	struct wpabuf *kid = NULL;
3960 	unsigned char *prot_hdr = NULL, *signature = NULL;
3961 	size_t prot_hdr_len = 0, signature_len = 0;
3962 	const EVP_MD *sign_md = NULL;
3963 	unsigned char *der = NULL;
3964 	int der_len;
3965 	int res;
3966 	EVP_MD_CTX *md_ctx = NULL;
3967 	ECDSA_SIG *sig = NULL;
3968 	BIGNUM *r = NULL, *s = NULL;
3969 	const struct dpp_curve_params *curve;
3970 	EC_KEY *eckey;
3971 	const EC_GROUP *group;
3972 	int nid;
3973 
3974 	eckey = EVP_PKEY_get1_EC_KEY(csign_pub);
3975 	if (!eckey)
3976 		goto fail;
3977 	group = EC_KEY_get0_group(eckey);
3978 	if (!group)
3979 		goto fail;
3980 	nid = EC_GROUP_get_curve_name(group);
3981 	curve = dpp_get_curve_nid(nid);
3982 	if (!curve)
3983 		goto fail;
3984 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
3985 	os_memset(info, 0, sizeof(*info));
3986 
3987 	signed_start = pos = connector;
3988 	end = os_strchr(pos, '.');
3989 	if (!end) {
3990 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
3991 		goto fail;
3992 	}
3993 	prot_hdr = base64_url_decode((const unsigned char *) pos,
3994 				     end - pos, &prot_hdr_len);
3995 	if (!prot_hdr) {
3996 		wpa_printf(MSG_DEBUG,
3997 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
3998 		goto fail;
3999 	}
4000 	wpa_hexdump_ascii(MSG_DEBUG,
4001 			  "DPP: signedConnector - JWS Protected Header",
4002 			  prot_hdr, prot_hdr_len);
4003 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
4004 	if (!kid)
4005 		goto fail;
4006 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
4007 		wpa_printf(MSG_DEBUG,
4008 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
4009 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
4010 		goto fail;
4011 	}
4012 
4013 	pos = end + 1;
4014 	end = os_strchr(pos, '.');
4015 	if (!end) {
4016 		wpa_printf(MSG_DEBUG,
4017 			   "DPP: Missing dot(2) in signedConnector");
4018 		goto fail;
4019 	}
4020 	signed_end = end - 1;
4021 	info->payload = base64_url_decode((const unsigned char *) pos,
4022 					  end - pos, &info->payload_len);
4023 	if (!info->payload) {
4024 		wpa_printf(MSG_DEBUG,
4025 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
4026 		goto fail;
4027 	}
4028 	wpa_hexdump_ascii(MSG_DEBUG,
4029 			  "DPP: signedConnector - JWS Payload",
4030 			  info->payload, info->payload_len);
4031 	pos = end + 1;
4032 	signature = base64_url_decode((const unsigned char *) pos,
4033 				      os_strlen(pos), &signature_len);
4034 	if (!signature) {
4035 		wpa_printf(MSG_DEBUG,
4036 			   "DPP: Failed to base64url decode signedConnector signature");
4037 		goto fail;
4038 		}
4039 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
4040 		    signature, signature_len);
4041 
4042 	if (dpp_check_pubkey_match(csign_pub, kid) < 0)
4043 		goto fail;
4044 
4045 	if (signature_len & 0x01) {
4046 		wpa_printf(MSG_DEBUG,
4047 			   "DPP: Unexpected signedConnector signature length (%d)",
4048 			   (int) signature_len);
4049 		goto fail;
4050 	}
4051 
4052 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
4053 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
4054 	r = BN_bin2bn(signature, signature_len / 2, NULL);
4055 	s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
4056 	sig = ECDSA_SIG_new();
4057 	if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
4058 		goto fail;
4059 	r = NULL;
4060 	s = NULL;
4061 
4062 	der_len = i2d_ECDSA_SIG(sig, &der);
4063 	if (der_len <= 0) {
4064 		wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
4065 		goto fail;
4066 	}
4067 	wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
4068 	md_ctx = EVP_MD_CTX_create();
4069 	if (!md_ctx)
4070 		goto fail;
4071 
4072 	ERR_clear_error();
4073 	if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
4074 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
4075 			   ERR_error_string(ERR_get_error(), NULL));
4076 		goto fail;
4077 	}
4078 	if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
4079 				   signed_end - signed_start + 1) != 1) {
4080 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
4081 			   ERR_error_string(ERR_get_error(), NULL));
4082 		goto fail;
4083 	}
4084 	res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
4085 	if (res != 1) {
4086 		wpa_printf(MSG_DEBUG,
4087 			   "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
4088 			   res, ERR_error_string(ERR_get_error(), NULL));
4089 		goto fail;
4090 	}
4091 
4092 	ret = 0;
4093 fail:
4094 	EC_KEY_free(eckey);
4095 	EVP_MD_CTX_destroy(md_ctx);
4096 	os_free(prot_hdr);
4097 	wpabuf_free(kid);
4098 	os_free(signature);
4099 	ECDSA_SIG_free(sig);
4100 	BN_free(r);
4101 	BN_free(s);
4102 	OPENSSL_free(der);
4103 	return ret;
4104 }
4105 
4106 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct json_token * cred)4107 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
4108 			      struct json_token *cred)
4109 {
4110 	struct dpp_signed_connector_info info;
4111 	struct json_token *token, *csign;
4112 	int ret = -1;
4113 	EVP_PKEY *csign_pub = NULL;
4114 	const struct dpp_curve_params *key_curve = NULL;
4115 	const char *signed_connector;
4116 
4117 	os_memset(&info, 0, sizeof(info));
4118 
4119 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
4120 
4121 	csign = json_get_member(cred, "csign");
4122 	if (!csign || csign->type != JSON_OBJECT) {
4123 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
4124 		goto fail;
4125 	}
4126 
4127 	csign_pub = dpp_parse_jwk(csign, &key_curve);
4128 	if (!csign_pub) {
4129 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
4130 		goto fail;
4131 	}
4132 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
4133 
4134 	token = json_get_member(cred, "signedConnector");
4135 	if (!token || token->type != JSON_STRING) {
4136 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
4137 		goto fail;
4138 	}
4139 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
4140 			  token->string, os_strlen(token->string));
4141 	signed_connector = token->string;
4142 
4143 	if (os_strchr(signed_connector, '"') ||
4144 	    os_strchr(signed_connector, '\n')) {
4145 		wpa_printf(MSG_DEBUG,
4146 			   "DPP: Unexpected character in signedConnector");
4147 		goto fail;
4148 	}
4149 
4150 	if (dpp_process_signed_connector(&info, csign_pub,
4151 					 signed_connector) < 0)
4152 		goto fail;
4153 
4154 	if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
4155 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
4156 		goto fail;
4157 	}
4158 
4159 	os_free(auth->connector);
4160 	auth->connector = os_strdup(signed_connector);
4161 
4162 	dpp_copy_csign(auth, csign_pub);
4163 	dpp_copy_netaccesskey(auth);
4164 
4165 	ret = 0;
4166 fail:
4167 	EVP_PKEY_free(csign_pub);
4168 	os_free(info.payload);
4169 	return ret;
4170 }
4171 
4172 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)4173 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
4174 			      const u8 *conf_obj, u16 conf_obj_len)
4175 {
4176 	int ret = -1;
4177 	struct json_token *root, *token, *discovery, *cred;
4178 
4179 	root = json_parse((const char *) conf_obj, conf_obj_len);
4180 	if (!root)
4181 		return -1;
4182 	if (root->type != JSON_OBJECT) {
4183 		wpa_printf(MSG_DEBUG, "DPP: JSON root is not an object");
4184 		goto fail;
4185 	}
4186 
4187 	token = json_get_member(root, "wi-fi_tech");
4188 	if (!token || token->type != JSON_STRING) {
4189 		wpa_printf(MSG_DEBUG, "DPP: No wi-fi_tech string value found");
4190 		goto fail;
4191 	}
4192 	if (os_strcmp(token->string, "infra") != 0) {
4193 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
4194 			   token->string);
4195 		goto fail;
4196 	}
4197 
4198 	discovery = json_get_member(root, "discovery");
4199 	if (!discovery || discovery->type != JSON_OBJECT) {
4200 		wpa_printf(MSG_DEBUG, "DPP: No discovery object in JSON");
4201 		goto fail;
4202 	}
4203 
4204 	token = json_get_member(discovery, "ssid");
4205 	if (!token || token->type != JSON_STRING) {
4206 		wpa_printf(MSG_DEBUG,
4207 			   "DPP: No discovery::ssid string value found");
4208 		goto fail;
4209 	}
4210 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
4211 			  token->string, os_strlen(token->string));
4212 	if (os_strlen(token->string) > SSID_MAX_LEN) {
4213 		wpa_printf(MSG_DEBUG,
4214 			   "DPP: Too long discovery::ssid string value");
4215 		goto fail;
4216 	}
4217 	auth->ssid_len = os_strlen(token->string);
4218 	os_memcpy(auth->ssid, token->string, auth->ssid_len);
4219 
4220 	cred = json_get_member(root, "cred");
4221 	if (!cred || cred->type != JSON_OBJECT) {
4222 		wpa_printf(MSG_DEBUG, "DPP: No cred object in JSON");
4223 		goto fail;
4224 	}
4225 
4226 	token = json_get_member(cred, "akm");
4227 	if (!token || token->type != JSON_STRING) {
4228 		wpa_printf(MSG_DEBUG,
4229 			   "DPP: No cred::akm string value found");
4230 		goto fail;
4231 	}
4232 	if (os_strcmp(token->string, "psk") == 0) {
4233 		if (dpp_parse_cred_legacy(auth, cred) < 0)
4234 			goto fail;
4235 	} else if (os_strcmp(token->string, "dpp") == 0) {
4236 		if (dpp_parse_cred_dpp(auth, cred) < 0)
4237 			goto fail;
4238 	} else {
4239 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
4240 			   token->string);
4241 		goto fail;
4242 	}
4243 
4244 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
4245 	ret = 0;
4246 fail:
4247 	json_free(root);
4248 	return ret;
4249 }
4250 
4251 
dpp_conf_resp_rx(struct dpp_authentication * auth,const struct wpabuf * resp)4252 int dpp_conf_resp_rx(struct dpp_authentication *auth,
4253 		     const struct wpabuf *resp)
4254 {
4255 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
4256 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
4257 	const u8 *addr[1];
4258 	size_t len[1];
4259 	u8 *unwrapped = NULL;
4260 	size_t unwrapped_len = 0;
4261 	int ret = -1;
4262 
4263 	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
4264 		wpa_printf(MSG_DEBUG,
4265 			   "DPP: Invalid attribute in config response");
4266 		return -1;
4267 	}
4268 
4269 	wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
4270 				    DPP_ATTR_WRAPPED_DATA,
4271 				    &wrapped_data_len);
4272 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
4273 		wpa_printf(MSG_DEBUG,
4274 			   "DPP: Missing or invalid required Wrapped data attribute");
4275 		return -1;
4276 	}
4277 
4278 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
4279 		    wrapped_data, wrapped_data_len);
4280 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
4281 	unwrapped = os_malloc(unwrapped_len);
4282 	if (!unwrapped)
4283 		return -1;
4284 
4285 	addr[0] = wpabuf_head(resp);
4286 	len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
4287 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
4288 
4289 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
4290 			    wrapped_data, wrapped_data_len,
4291 			    1, addr, len, unwrapped) < 0) {
4292 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
4293 		goto fail;
4294 	}
4295 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
4296 		    unwrapped, unwrapped_len);
4297 
4298 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
4299 		wpa_printf(MSG_DEBUG,
4300 			   "DPP: Invalid attribute in unwrapped data");
4301 		goto fail;
4302 	}
4303 
4304 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
4305 			       DPP_ATTR_ENROLLEE_NONCE,
4306 			       &e_nonce_len);
4307 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
4308 		wpa_printf(MSG_DEBUG,
4309 			   "DPP: Missing or invalid Enrollee Nonce attribute");
4310 		goto fail;
4311 	}
4312 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
4313 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
4314 		wpa_printf(MSG_DEBUG, "Enrollee Nonce mismatch");
4315 		goto fail;
4316 	}
4317 
4318 	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
4319 			      DPP_ATTR_STATUS, &status_len);
4320 	if (!status || status_len < 1) {
4321 		wpa_printf(MSG_DEBUG,
4322 			   "DPP: Missing or invalid required DPP Status attribute");
4323 		goto fail;
4324 	}
4325 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
4326 	if (status[0] != DPP_STATUS_OK) {
4327 		wpa_printf(MSG_DEBUG, "DPP: Configuration failed");
4328 		goto fail;
4329 	}
4330 
4331 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len,
4332 				DPP_ATTR_CONFIG_OBJ, &conf_obj_len);
4333 	if (!conf_obj) {
4334 		wpa_printf(MSG_DEBUG,
4335 			   "DPP: Missing required Configuration Object attribute");
4336 		goto fail;
4337 	}
4338 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
4339 			  conf_obj, conf_obj_len);
4340 	if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
4341 		goto fail;
4342 
4343 	ret = 0;
4344 
4345 fail:
4346 	os_free(unwrapped);
4347 	return ret;
4348 }
4349 
4350 
dpp_configurator_free(struct dpp_configurator * conf)4351 void dpp_configurator_free(struct dpp_configurator *conf)
4352 {
4353 	if (!conf)
4354 		return;
4355 	EVP_PKEY_free(conf->csign);
4356 	os_free(conf->kid);
4357 	os_free(conf);
4358 }
4359 
4360 
4361 struct dpp_configurator *
dpp_keygen_configurator(const char * curve,const u8 * privkey,size_t privkey_len)4362 dpp_keygen_configurator(const char *curve, const u8 *privkey,
4363 			size_t privkey_len)
4364 {
4365 	struct dpp_configurator *conf;
4366 	struct wpabuf *csign_pub = NULL;
4367 	u8 kid_hash[SHA256_MAC_LEN];
4368 	const u8 *addr[1];
4369 	size_t len[1];
4370 
4371 	conf = os_zalloc(sizeof(*conf));
4372 	if (!conf)
4373 		return NULL;
4374 
4375 	if (!curve) {
4376 		conf->curve = &dpp_curves[0];
4377 	} else {
4378 		conf->curve = dpp_get_curve_name(curve);
4379 		if (!conf->curve) {
4380 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
4381 				   curve);
4382 			return NULL;
4383 		}
4384 	}
4385 	if (privkey)
4386 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
4387 					      privkey_len);
4388 	else
4389 		conf->csign = dpp_gen_keypair(conf->curve);
4390 	if (!conf->csign)
4391 		goto fail;
4392 	conf->own = 1;
4393 
4394 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
4395 	if (!csign_pub) {
4396 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
4397 		goto fail;
4398 	}
4399 
4400 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
4401 	addr[0] = wpabuf_head(csign_pub);
4402 	len[0] = wpabuf_len(csign_pub);
4403 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
4404 		wpa_printf(MSG_DEBUG,
4405 			   "DPP: Failed to derive kid for C-sign-key");
4406 		goto fail;
4407 	}
4408 
4409 	conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
4410 					       NULL, 0);
4411 	if (!conf->kid)
4412 		goto fail;
4413 out:
4414 	wpabuf_free(csign_pub);
4415 	return conf;
4416 fail:
4417 	dpp_configurator_free(conf);
4418 	conf = NULL;
4419 	goto out;
4420 }
4421 
4422 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve)4423 int dpp_configurator_own_config(struct dpp_authentication *auth,
4424 				const char *curve)
4425 {
4426 	struct wpabuf *conf_obj;
4427 	int ret = -1;
4428 
4429 	if (!auth->conf) {
4430 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
4431 		return -1;
4432 	}
4433 
4434 	if (!curve) {
4435 		auth->curve = &dpp_curves[0];
4436 	} else {
4437 		auth->curve = dpp_get_curve_name(curve);
4438 		if (!auth->curve) {
4439 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
4440 				   curve);
4441 			return -1;
4442 		}
4443 	}
4444 	wpa_printf(MSG_DEBUG,
4445 		   "DPP: Building own configuration/connector with curve %s",
4446 		   auth->curve->name);
4447 
4448 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
4449 	if (!auth->own_protocol_key)
4450 		return -1;
4451 	dpp_copy_netaccesskey(auth);
4452 	auth->peer_protocol_key = auth->own_protocol_key;
4453 	dpp_copy_csign(auth, auth->conf->csign);
4454 
4455 	conf_obj = dpp_build_conf_obj(auth, 0);
4456 	if (!conf_obj)
4457 		goto fail;
4458 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
4459 				 wpabuf_len(conf_obj));
4460 fail:
4461 	wpabuf_free(conf_obj);
4462 	auth->peer_protocol_key = NULL;
4463 	return ret;
4464 }
4465 
4466 
dpp_compatible_netrole(const char * role1,const char * role2)4467 static int dpp_compatible_netrole(const char *role1, const char *role2)
4468 {
4469 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
4470 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
4471 }
4472 
4473 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role)4474 static int dpp_connector_compatible_group(struct json_token *root,
4475 					  const char *group_id,
4476 					  const char *net_role)
4477 {
4478 	struct json_token *groups, *token;
4479 
4480 	groups = json_get_member(root, "groups");
4481 	if (!groups || groups->type != JSON_ARRAY)
4482 		return 0;
4483 
4484 	for (token = groups->child; token; token = token->sibling) {
4485 		struct json_token *id, *role;
4486 
4487 		id = json_get_member(token, "groupId");
4488 		if (!id || id->type != JSON_STRING)
4489 			continue;
4490 
4491 		role = json_get_member(token, "netRole");
4492 		if (!role || role->type != JSON_STRING)
4493 			continue;
4494 
4495 		if (os_strcmp(id->string, "*") != 0 &&
4496 		    os_strcmp(group_id, "*") != 0 &&
4497 		    os_strcmp(id->string, group_id) != 0)
4498 			continue;
4499 
4500 		if (dpp_compatible_netrole(role->string, net_role))
4501 			return 1;
4502 	}
4503 
4504 	return 0;
4505 }
4506 
4507 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root)4508 static int dpp_connector_match_groups(struct json_token *own_root,
4509 				      struct json_token *peer_root)
4510 {
4511 	struct json_token *groups, *token;
4512 
4513 	groups = json_get_member(peer_root, "groups");
4514 	if (!groups || groups->type != JSON_ARRAY) {
4515 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
4516 		return 0;
4517 	}
4518 
4519 	for (token = groups->child; token; token = token->sibling) {
4520 		struct json_token *id, *role;
4521 
4522 		id = json_get_member(token, "groupId");
4523 		if (!id || id->type != JSON_STRING) {
4524 			wpa_printf(MSG_DEBUG,
4525 				   "DPP: Missing peer groupId string");
4526 			continue;
4527 		}
4528 
4529 		role = json_get_member(token, "netRole");
4530 		if (!role || role->type != JSON_STRING) {
4531 			wpa_printf(MSG_DEBUG,
4532 				   "DPP: Missing peer groups::netRole string");
4533 			continue;
4534 		}
4535 		wpa_printf(MSG_DEBUG,
4536 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
4537 			   id->string, role->string);
4538 		if (dpp_connector_compatible_group(own_root, id->string,
4539 						   role->string)) {
4540 			wpa_printf(MSG_DEBUG,
4541 				   "DPP: Compatible group/netRole in own connector");
4542 			return 1;
4543 		}
4544 	}
4545 
4546 	return 0;
4547 }
4548 
4549 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)4550 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
4551 			  unsigned int hash_len)
4552 {
4553 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
4554 	const char *info = "DPP PMK";
4555 	int res;
4556 
4557 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
4558 
4559 	/* HKDF-Extract(<>, N.x) */
4560 	os_memset(salt, 0, hash_len);
4561 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
4562 		return -1;
4563 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
4564 			prk, hash_len);
4565 
4566 	/* HKDF-Expand(PRK, info, L) */
4567 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
4568 	os_memset(prk, 0, hash_len);
4569 	if (res < 0)
4570 		return -1;
4571 
4572 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
4573 			pmk, hash_len);
4574 	return 0;
4575 }
4576 
4577 
dpp_derive_pmkid(const struct dpp_curve_params * curve,EVP_PKEY * own_key,EVP_PKEY * peer_key,u8 * pmkid)4578 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
4579 			    EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
4580 {
4581 	struct wpabuf *nkx, *pkx;
4582 	int ret = -1, res;
4583 	const u8 *addr[2];
4584 	size_t len[2];
4585 	u8 hash[SHA256_MAC_LEN];
4586 
4587 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
4588 	nkx = dpp_get_pubkey_point(own_key, 0);
4589 	pkx = dpp_get_pubkey_point(peer_key, 0);
4590 	if (!nkx || !pkx)
4591 		goto fail;
4592 	addr[0] = wpabuf_head(nkx);
4593 	len[0] = wpabuf_len(nkx) / 2;
4594 	addr[1] = wpabuf_head(pkx);
4595 	len[1] = wpabuf_len(pkx) / 2;
4596 	if (len[0] != len[1])
4597 		goto fail;
4598 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
4599 		addr[0] = wpabuf_head(pkx);
4600 		addr[1] = wpabuf_head(nkx);
4601 	}
4602 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
4603 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
4604 	res = sha256_vector(2, addr, len, hash);
4605 	if (res < 0)
4606 		goto fail;
4607 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
4608 	os_memcpy(pmkid, hash, PMKID_LEN);
4609 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
4610 	ret = 0;
4611 fail:
4612 	wpabuf_free(nkx);
4613 	wpabuf_free(pkx);
4614 	return ret;
4615 }
4616 
4617 
dpp_peer_intro(struct dpp_introduction * intro,const char * own_connector,const u8 * net_access_key,size_t net_access_key_len,const u8 * csign_key,size_t csign_key_len,const u8 * peer_connector,size_t peer_connector_len,os_time_t * expiry)4618 int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
4619 		   const u8 *net_access_key, size_t net_access_key_len,
4620 		   const u8 *csign_key, size_t csign_key_len,
4621 		   const u8 *peer_connector, size_t peer_connector_len,
4622 		   os_time_t *expiry)
4623 {
4624 	struct json_token *root = NULL, *netkey, *token;
4625 	struct json_token *own_root = NULL;
4626 	int ret = -1;
4627 	EVP_PKEY *own_key = NULL, *peer_key = NULL;
4628 	struct wpabuf *own_key_pub = NULL;
4629 	const struct dpp_curve_params *curve, *own_curve;
4630 	struct dpp_signed_connector_info info;
4631 	const unsigned char *p;
4632 	EVP_PKEY *csign = NULL;
4633 	char *signed_connector = NULL;
4634 	const char *pos, *end;
4635 	unsigned char *own_conn = NULL;
4636 	size_t own_conn_len;
4637 	EVP_PKEY_CTX *ctx = NULL;
4638 	size_t Nx_len;
4639 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
4640 
4641 	os_memset(intro, 0, sizeof(*intro));
4642 	os_memset(&info, 0, sizeof(info));
4643 	if (expiry)
4644 		*expiry = 0;
4645 
4646 	p = csign_key;
4647 	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
4648 	if (!csign) {
4649 		wpa_printf(MSG_ERROR,
4650 			   "DPP: Failed to parse local C-sign-key information");
4651 		goto fail;
4652 	}
4653 
4654 	own_key = dpp_set_keypair(&own_curve, net_access_key,
4655 				  net_access_key_len);
4656 	if (!own_key) {
4657 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
4658 		goto fail;
4659 	}
4660 
4661 	pos = os_strchr(own_connector, '.');
4662 	if (!pos) {
4663 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
4664 		goto fail;
4665 	}
4666 	pos++;
4667 	end = os_strchr(pos, '.');
4668 	if (!end) {
4669 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
4670 		goto fail;
4671 	}
4672 	own_conn = base64_url_decode((const unsigned char *) pos,
4673 				     end - pos, &own_conn_len);
4674 	if (!own_conn) {
4675 		wpa_printf(MSG_DEBUG,
4676 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
4677 		goto fail;
4678 	}
4679 
4680 	own_root = json_parse((const char *) own_conn, own_conn_len);
4681 	if (!own_root) {
4682 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
4683 		goto fail;
4684 	}
4685 
4686 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
4687 			  peer_connector, peer_connector_len);
4688 	signed_connector = os_malloc(peer_connector_len + 1);
4689 	if (!signed_connector)
4690 		goto fail;
4691 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
4692 	signed_connector[peer_connector_len] = '\0';
4693 
4694 	if (dpp_process_signed_connector(&info, csign, signed_connector) < 0)
4695 		goto fail;
4696 
4697 	root = json_parse((const char *) info.payload, info.payload_len);
4698 	if (!root) {
4699 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4700 		goto fail;
4701 	}
4702 
4703 	if (!dpp_connector_match_groups(own_root, root)) {
4704 		wpa_printf(MSG_DEBUG,
4705 			   "DPP: Peer connector does not include compatible group netrole with own connector");
4706 		goto fail;
4707 	}
4708 
4709 	token = json_get_member(root, "expiry");
4710 	if (!token || token->type != JSON_STRING) {
4711 		wpa_printf(MSG_DEBUG,
4712 			   "DPP: No expiry string found - connector does not expire");
4713 	} else {
4714 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4715 		if (dpp_key_expired(token->string, expiry)) {
4716 			wpa_printf(MSG_DEBUG,
4717 				   "DPP: Connector (netAccessKey) has expired");
4718 			goto fail;
4719 		}
4720 	}
4721 
4722 	netkey = json_get_member(root, "netAccessKey");
4723 	if (!netkey || netkey->type != JSON_OBJECT) {
4724 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4725 		goto fail;
4726 	}
4727 
4728 	peer_key = dpp_parse_jwk(netkey, &curve);
4729 	if (!peer_key)
4730 		goto fail;
4731 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
4732 
4733 	if (own_curve != curve) {
4734 		wpa_printf(MSG_DEBUG,
4735 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
4736 			   own_curve->name, curve->name);
4737 		goto fail;
4738 	}
4739 
4740 	/* ECDH: N = nk * PK */
4741 	ctx = EVP_PKEY_CTX_new(own_key, NULL);
4742 	if (!ctx ||
4743 	    EVP_PKEY_derive_init(ctx) != 1 ||
4744 	    EVP_PKEY_derive_set_peer(ctx, peer_key) != 1 ||
4745 	    EVP_PKEY_derive(ctx, NULL, &Nx_len) != 1 ||
4746 	    Nx_len > DPP_MAX_SHARED_SECRET_LEN ||
4747 	    EVP_PKEY_derive(ctx, Nx, &Nx_len) != 1) {
4748 		wpa_printf(MSG_ERROR,
4749 			   "DPP: Failed to derive ECDH shared secret: %s",
4750 			   ERR_error_string(ERR_get_error(), NULL));
4751 		goto fail;
4752 	}
4753 
4754 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
4755 			Nx, Nx_len);
4756 
4757 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
4758 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
4759 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
4760 		goto fail;
4761 	}
4762 	intro->pmk_len = curve->hash_len;
4763 
4764 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
4765 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
4766 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
4767 		goto fail;
4768 	}
4769 
4770 	ret = 0;
4771 fail:
4772 	if (ret < 0)
4773 		os_memset(intro, 0, sizeof(*intro));
4774 	os_memset(Nx, 0, sizeof(Nx));
4775 	EVP_PKEY_CTX_free(ctx);
4776 	os_free(own_conn);
4777 	os_free(signed_connector);
4778 	os_free(info.payload);
4779 	EVP_PKEY_free(own_key);
4780 	wpabuf_free(own_key_pub);
4781 	EVP_PKEY_free(peer_key);
4782 	EVP_PKEY_free(csign);
4783 	json_free(root);
4784 	json_free(own_root);
4785 	return ret;
4786 }
4787 
4788 
dpp_pkex_get_role_elem(const struct dpp_curve_params * curve,int init)4789 static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
4790 					 int init)
4791 {
4792 	EC_GROUP *group;
4793 	size_t len = curve->prime_len;
4794 	const u8 *x, *y;
4795 
4796 	switch (curve->ike_group) {
4797 	case 19:
4798 		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
4799 		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
4800 		break;
4801 	case 20:
4802 		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
4803 		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
4804 		break;
4805 	case 21:
4806 		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
4807 		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
4808 		break;
4809 	case 28:
4810 		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
4811 		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
4812 		break;
4813 	case 29:
4814 		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
4815 		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
4816 		break;
4817 	case 30:
4818 		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
4819 		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
4820 		break;
4821 	default:
4822 		return NULL;
4823 	}
4824 
4825 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
4826 	if (!group)
4827 		return NULL;
4828 	return dpp_set_pubkey_point_group(group, x, y, len);
4829 }
4830 
4831 
dpp_pkex_derive_Qi(const struct dpp_curve_params * curve,const u8 * mac_init,const char * code,const char * identifier,BN_CTX * bnctx,const EC_GROUP ** ret_group)4832 static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
4833 				     const u8 *mac_init, const char *code,
4834 				     const char *identifier, BN_CTX *bnctx,
4835 				     const EC_GROUP **ret_group)
4836 {
4837 	u8 hash[DPP_MAX_HASH_LEN];
4838 	const u8 *addr[3];
4839 	size_t len[3];
4840 	unsigned int num_elem = 0;
4841 	EC_POINT *Qi = NULL;
4842 	EVP_PKEY *Pi = NULL;
4843 	EC_KEY *Pi_ec = NULL;
4844 	const EC_POINT *Pi_point;
4845 	BIGNUM *hash_bn = NULL;
4846 	const EC_GROUP *group = NULL;
4847 	EC_GROUP *group2 = NULL;
4848 
4849 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
4850 
4851 	wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
4852 	addr[num_elem] = mac_init;
4853 	len[num_elem] = ETH_ALEN;
4854 	num_elem++;
4855 	if (identifier) {
4856 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
4857 			   identifier);
4858 		addr[num_elem] = (const u8 *) identifier;
4859 		len[num_elem] = os_strlen(identifier);
4860 		num_elem++;
4861 	}
4862 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
4863 	addr[num_elem] = (const u8 *) code;
4864 	len[num_elem] = os_strlen(code);
4865 	num_elem++;
4866 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
4867 		goto fail;
4868 	wpa_hexdump_key(MSG_DEBUG,
4869 			"DPP: H(MAC-Initiator | [identifier |] code)",
4870 			hash, curve->hash_len);
4871 	Pi = dpp_pkex_get_role_elem(curve, 1);
4872 	if (!Pi)
4873 		goto fail;
4874 	dpp_debug_print_key("DPP: Pi", Pi);
4875 	Pi_ec = EVP_PKEY_get1_EC_KEY(Pi);
4876 	if (!Pi_ec)
4877 		goto fail;
4878 	Pi_point = EC_KEY_get0_public_key(Pi_ec);
4879 
4880 	group = EC_KEY_get0_group(Pi_ec);
4881 	if (!group)
4882 		goto fail;
4883 	group2 = EC_GROUP_dup(group);
4884 	if (!group2)
4885 		goto fail;
4886 	Qi = EC_POINT_new(group2);
4887 	if (!Qi) {
4888 		EC_GROUP_free(group2);
4889 		goto fail;
4890 	}
4891 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
4892 	if (!hash_bn ||
4893 	    EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
4894 		goto fail;
4895 	if (EC_POINT_is_at_infinity(group, Qi)) {
4896 		wpa_printf(MSG_INFO, "PDP: Qi is the point-at-infinity");
4897 		goto fail;
4898 	}
4899 out:
4900 	EC_KEY_free(Pi_ec);
4901 	EVP_PKEY_free(Pi);
4902 	BN_clear_free(hash_bn);
4903 	if (ret_group)
4904 		*ret_group = group2;
4905 	return Qi;
4906 fail:
4907 	EC_POINT_free(Qi);
4908 	Qi = NULL;
4909 	goto out;
4910 }
4911 
4912 
dpp_pkex_derive_Qr(const struct dpp_curve_params * curve,const u8 * mac_resp,const char * code,const char * identifier,BN_CTX * bnctx,const EC_GROUP ** ret_group)4913 static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
4914 				     const u8 *mac_resp, const char *code,
4915 				     const char *identifier, BN_CTX *bnctx,
4916 				     const EC_GROUP **ret_group)
4917 {
4918 	u8 hash[DPP_MAX_HASH_LEN];
4919 	const u8 *addr[3];
4920 	size_t len[3];
4921 	unsigned int num_elem = 0;
4922 	EC_POINT *Qr = NULL;
4923 	EVP_PKEY *Pr = NULL;
4924 	EC_KEY *Pr_ec = NULL;
4925 	const EC_POINT *Pr_point;
4926 	BIGNUM *hash_bn = NULL;
4927 	const EC_GROUP *group = NULL;
4928 	EC_GROUP *group2 = NULL;
4929 
4930 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
4931 
4932 	wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
4933 	addr[num_elem] = mac_resp;
4934 	len[num_elem] = ETH_ALEN;
4935 	num_elem++;
4936 	if (identifier) {
4937 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
4938 			   identifier);
4939 		addr[num_elem] = (const u8 *) identifier;
4940 		len[num_elem] = os_strlen(identifier);
4941 		num_elem++;
4942 	}
4943 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
4944 	addr[num_elem] = (const u8 *) code;
4945 	len[num_elem] = os_strlen(code);
4946 	num_elem++;
4947 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
4948 		goto fail;
4949 	wpa_hexdump_key(MSG_DEBUG,
4950 			"DPP: H(MAC-Responder | [identifier |] code)",
4951 			hash, curve->hash_len);
4952 	Pr = dpp_pkex_get_role_elem(curve, 0);
4953 	if (!Pr)
4954 		goto fail;
4955 	dpp_debug_print_key("DPP: Pr", Pr);
4956 	Pr_ec = EVP_PKEY_get1_EC_KEY(Pr);
4957 	if (!Pr_ec)
4958 		goto fail;
4959 	Pr_point = EC_KEY_get0_public_key(Pr_ec);
4960 
4961 	group = EC_KEY_get0_group(Pr_ec);
4962 	if (!group)
4963 		goto fail;
4964 	group2 = EC_GROUP_dup(group);
4965 	if (!group2)
4966 		goto fail;
4967 	Qr = EC_POINT_new(group2);
4968 	if (!Qr) {
4969 		EC_GROUP_free(group2);
4970 		goto fail;
4971 	}
4972 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
4973 	if (!hash_bn ||
4974 	    EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
4975 		goto fail;
4976 out:
4977 	EC_KEY_free(Pr_ec);
4978 	EVP_PKEY_free(Pr);
4979 	BN_clear_free(hash_bn);
4980 	if (ret_group)
4981 		*ret_group = group2;
4982 	return Qr;
4983 fail:
4984 	EC_POINT_free(Qr);
4985 	Qr = NULL;
4986 	goto out;
4987 }
4988 
4989 
dpp_pkex_build_exchange_req(struct dpp_pkex * pkex)4990 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
4991 {
4992 	EC_KEY *X_ec = NULL;
4993 	const EC_POINT *X_point;
4994 	BN_CTX *bnctx = NULL;
4995 	const EC_GROUP *group;
4996 	EC_POINT *Qi = NULL, *M = NULL;
4997 	struct wpabuf *M_buf = NULL;
4998 	BIGNUM *Mx = NULL, *My = NULL;
4999 	struct wpabuf *msg = NULL;
5000 	size_t attr_len;
5001 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
5002 	int num_bytes, offset;
5003 
5004 	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
5005 
5006 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
5007 	bnctx = BN_CTX_new();
5008 	if (!bnctx)
5009 		goto fail;
5010 	Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
5011 				pkex->identifier, bnctx, &group);
5012 	if (!Qi)
5013 		goto fail;
5014 
5015 	/* Generate a random ephemeral keypair x/X */
5016 	pkex->x = dpp_gen_keypair(curve);
5017 	if (!pkex->x)
5018 		goto fail;
5019 
5020 	/* M = X + Qi */
5021 	X_ec = EVP_PKEY_get1_EC_KEY(pkex->x);
5022 	if (!X_ec)
5023 		goto fail;
5024 	X_point = EC_KEY_get0_public_key(X_ec);
5025 	if (!X_point)
5026 		goto fail;
5027 	M = EC_POINT_new(group);
5028 	Mx = BN_new();
5029 	My = BN_new();
5030 	if (!M || !Mx || !My ||
5031 	    EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
5032 	    EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
5033 		goto fail;
5034 
5035 	/* Initiator -> Responder: group, [identifier,] M */
5036 	attr_len = 4 + 2;
5037 	if (pkex->identifier)
5038 		attr_len += 4 + os_strlen(pkex->identifier);
5039 	attr_len += 4 + 2 * curve->prime_len;
5040 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
5041 	if (!msg)
5042 		goto fail;
5043 
5044 	/* Finite Cyclic Group attribute */
5045 	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
5046 	wpabuf_put_le16(msg, 2);
5047 	wpabuf_put_le16(msg, curve->ike_group);
5048 
5049 	/* Code Identifier attribute */
5050 	if (pkex->identifier) {
5051 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
5052 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
5053 		wpabuf_put_str(msg, pkex->identifier);
5054 	}
5055 
5056 	/* M in Encrypted Key attribute */
5057 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
5058 	wpabuf_put_le16(msg, 2 * curve->prime_len);
5059 
5060 	num_bytes = BN_num_bytes(Mx);
5061 	if ((size_t) num_bytes > curve->prime_len)
5062 		goto fail;
5063 	if (curve->prime_len > (size_t) num_bytes)
5064 		offset = curve->prime_len - num_bytes;
5065 	else
5066 		offset = 0;
5067 	os_memset(wpabuf_put(msg, offset), 0, offset);
5068 	BN_bn2bin(Mx, wpabuf_put(msg, num_bytes));
5069 	os_memset(pkex->Mx, 0, offset);
5070 	BN_bn2bin(Mx, pkex->Mx + offset);
5071 
5072 	num_bytes = BN_num_bytes(My);
5073 	if ((size_t) num_bytes > curve->prime_len)
5074 		goto fail;
5075 	if (curve->prime_len > (size_t) num_bytes)
5076 		offset = curve->prime_len - num_bytes;
5077 	else
5078 		offset = 0;
5079 	os_memset(wpabuf_put(msg, offset), 0, offset);
5080 	BN_bn2bin(My, wpabuf_put(msg, num_bytes));
5081 
5082 out:
5083 	wpabuf_free(M_buf);
5084 	EC_KEY_free(X_ec);
5085 	EC_POINT_free(M);
5086 	EC_POINT_free(Qi);
5087 	BN_clear_free(Mx);
5088 	BN_clear_free(My);
5089 	BN_CTX_free(bnctx);
5090 	return msg;
5091 fail:
5092 	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
5093 	wpabuf_free(msg);
5094 	msg = NULL;
5095 	goto out;
5096 }
5097 
5098 
dpp_pkex_init(struct dpp_bootstrap_info * bi,const u8 * own_mac,const char * identifier,const char * code)5099 struct dpp_pkex * dpp_pkex_init(struct dpp_bootstrap_info *bi,
5100 				const u8 *own_mac,
5101 				const char *identifier,
5102 				const char *code)
5103 {
5104 	struct dpp_pkex *pkex;
5105 
5106 	pkex = os_zalloc(sizeof(*pkex));
5107 	if (!pkex)
5108 		return NULL;
5109 	pkex->initiator = 1;
5110 	pkex->own_bi = bi;
5111 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
5112 	if (identifier) {
5113 		pkex->identifier = os_strdup(identifier);
5114 		if (!pkex->identifier)
5115 			goto fail;
5116 	}
5117 	pkex->code = os_strdup(code);
5118 	if (!pkex->code)
5119 		goto fail;
5120 	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
5121 	if (!pkex->exchange_req)
5122 		goto fail;
5123 	return pkex;
5124 fail:
5125 	dpp_pkex_free(pkex);
5126 	return NULL;
5127 }
5128 
5129 
dpp_pkex_rx_exchange_req(struct dpp_bootstrap_info * bi,const u8 * own_mac,const u8 * peer_mac,const char * identifier,const char * code,const u8 * buf,size_t len)5130 struct dpp_pkex * dpp_pkex_rx_exchange_req(struct dpp_bootstrap_info *bi,
5131 					   const u8 *own_mac,
5132 					   const u8 *peer_mac,
5133 					   const char *identifier,
5134 					   const char *code,
5135 					   const u8 *buf, size_t len)
5136 {
5137 	const u8 *attr_group, *attr_id, *attr_key;
5138 	u16 attr_group_len, attr_id_len, attr_key_len;
5139 	const struct dpp_curve_params *curve = bi->curve;
5140 	u16 ike_group;
5141 	struct dpp_pkex *pkex = NULL;
5142 	EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
5143 	BN_CTX *bnctx = NULL;
5144 	const EC_GROUP *group;
5145 	BIGNUM *Mx = NULL, *My = NULL;
5146 	EC_KEY *Y_ec = NULL, *X_ec = NULL;;
5147 	const EC_POINT *Y_point;
5148 	BIGNUM *Nx = NULL, *Ny = NULL;
5149 	struct wpabuf *msg = NULL;
5150 	size_t attr_len;
5151 	int num_bytes, offset;
5152 
5153 	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
5154 			       &attr_id_len);
5155 	if (!attr_id && identifier) {
5156 		wpa_printf(MSG_DEBUG,
5157 			   "DPP: No PKEX code identifier received, but expected one");
5158 		return NULL;
5159 	}
5160 	if (attr_id && identifier &&
5161 	    (os_strlen(identifier) != attr_id_len ||
5162 	     os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
5163 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
5164 		return NULL;
5165 	}
5166 
5167 	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
5168 				  &attr_group_len);
5169 	if (!attr_group || attr_group_len != 2) {
5170 		wpa_printf(MSG_DEBUG,
5171 			   "DPP: Missing or invalid Finite Cyclic Group attribute");
5172 		return NULL;
5173 	}
5174 	ike_group = WPA_GET_LE16(attr_group);
5175 	if (ike_group != curve->ike_group) {
5176 		wpa_printf(MSG_DEBUG,
5177 			   "DPP: Mismatching PKEX curve: peer=%u own=%u",
5178 			   ike_group, curve->ike_group);
5179 		/* TODO: error response with suggested curve:
5180 		 * DPP Status, group */
5181 		return NULL;
5182 	}
5183 
5184 	/* M in Encrypted Key attribute */
5185 	attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
5186 				&attr_key_len);
5187 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
5188 	    attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
5189 		wpa_printf(MSG_DEBUG, "DPP: Missing Encrypted Key attribute");
5190 		return NULL;
5191 	}
5192 
5193 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
5194 	bnctx = BN_CTX_new();
5195 	if (!bnctx)
5196 		goto fail;
5197 	Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
5198 				&group);
5199 	if (!Qi)
5200 		goto fail;
5201 
5202 	/* X' = M - Qi */
5203 	X = EC_POINT_new(group);
5204 	M = EC_POINT_new(group);
5205 	Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
5206 	My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
5207 	if (!X || !M || !Mx || !My ||
5208 	    EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
5209 	    EC_POINT_is_at_infinity(group, M) ||
5210 	    !EC_POINT_is_on_curve(group, M, bnctx) ||
5211 	    EC_POINT_invert(group, Qi, bnctx) != 1 ||
5212 	    EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
5213 	    EC_POINT_is_at_infinity(group, X) ||
5214 	    !EC_POINT_is_on_curve(group, X, bnctx))
5215 		goto fail;
5216 
5217 	pkex = os_zalloc(sizeof(*pkex));
5218 	if (!pkex)
5219 		goto fail;
5220 	pkex->own_bi = bi;
5221 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
5222 	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
5223 	if (identifier) {
5224 		pkex->identifier = os_strdup(identifier);
5225 		if (!pkex->identifier)
5226 			goto fail;
5227 	}
5228 	pkex->code = os_strdup(code);
5229 	if (!pkex->code)
5230 		goto fail;
5231 
5232 	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
5233 
5234 	X_ec = EC_KEY_new();
5235 	if (!X_ec ||
5236 	    EC_KEY_set_group(X_ec, group) != 1 ||
5237 	    EC_KEY_set_public_key(X_ec, X) != 1)
5238 		goto fail;
5239 	pkex->x = EVP_PKEY_new();
5240 	if (!pkex->x ||
5241 	    EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
5242 		goto fail;
5243 
5244 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
5245 	Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
5246 	if (!Qr)
5247 		goto fail;
5248 
5249 	/* Generate a random ephemeral keypair y/Y */
5250 	pkex->y = dpp_gen_keypair(curve);
5251 	if (!pkex->y)
5252 		goto fail;
5253 
5254 	/* N = Y + Qr */
5255 	Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y);
5256 	if (!Y_ec)
5257 		goto fail;
5258 	Y_point = EC_KEY_get0_public_key(Y_ec);
5259 	if (!Y_point)
5260 		goto fail;
5261 	N = EC_POINT_new(group);
5262 	Nx = BN_new();
5263 	Ny = BN_new();
5264 	if (!N || !Nx || !Ny ||
5265 	    EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
5266 	    EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
5267 		goto fail;
5268 
5269 	/* Initiator -> Responder: DPP Status, [identifier,] N */
5270 	attr_len = 4 + 1;
5271 	if (identifier)
5272 		attr_len += 4 + os_strlen(identifier);
5273 	attr_len += 4 + 2 * curve->prime_len;
5274 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
5275 	if (!msg)
5276 		goto fail;
5277 
5278 	/* DPP Status */
5279 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
5280 	wpabuf_put_le16(msg, 1);
5281 	wpabuf_put_u8(msg, DPP_STATUS_OK);
5282 
5283 	/* Code Identifier attribute */
5284 	if (pkex->identifier) {
5285 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
5286 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
5287 		wpabuf_put_str(msg, pkex->identifier);
5288 	}
5289 
5290 	/* N in Encrypted Key attribute */
5291 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
5292 	wpabuf_put_le16(msg, 2 * curve->prime_len);
5293 
5294 	num_bytes = BN_num_bytes(Nx);
5295 	if ((size_t) num_bytes > curve->prime_len)
5296 		goto fail;
5297 	if (curve->prime_len > (size_t) num_bytes)
5298 		offset = curve->prime_len - num_bytes;
5299 	else
5300 		offset = 0;
5301 	os_memset(wpabuf_put(msg, offset), 0, offset);
5302 	BN_bn2bin(Nx, wpabuf_put(msg, num_bytes));
5303 	os_memset(pkex->Nx, 0, offset);
5304 	BN_bn2bin(Nx, pkex->Nx + offset);
5305 
5306 	num_bytes = BN_num_bytes(Ny);
5307 	if ((size_t) num_bytes > curve->prime_len)
5308 		goto fail;
5309 	if (curve->prime_len > (size_t) num_bytes)
5310 		offset = curve->prime_len - num_bytes;
5311 	else
5312 		offset = 0;
5313 	os_memset(wpabuf_put(msg, offset), 0, offset);
5314 	BN_bn2bin(Ny, wpabuf_put(msg, num_bytes));
5315 
5316 	pkex->exchange_resp = msg;
5317 	msg = NULL;
5318 	pkex->exchange_done = 1;
5319 
5320 out:
5321 	wpabuf_free(msg);
5322 	BN_CTX_free(bnctx);
5323 	EC_POINT_free(Qi);
5324 	EC_POINT_free(Qr);
5325 	BN_free(Mx);
5326 	BN_free(My);
5327 	BN_free(Nx);
5328 	BN_free(Ny);
5329 	EC_POINT_free(M);
5330 	EC_POINT_free(N);
5331 	EC_POINT_free(X);
5332 	EC_KEY_free(X_ec);
5333 	EC_KEY_free(Y_ec);
5334 	return pkex;
5335 fail:
5336 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing faileed");
5337 	dpp_pkex_free(pkex);
5338 	pkex = NULL;
5339 	goto out;
5340 }
5341 
5342 
dpp_pkex_derive_z(const u8 * mac_init,const u8 * mac_resp,const u8 * Mx,size_t Mx_len,const u8 * Nx,size_t Nx_len,const char * code,const u8 * Kx,size_t Kx_len,u8 * z,unsigned int hash_len)5343 static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
5344 			     const u8 *Mx, size_t Mx_len,
5345 			     const u8 *Nx, size_t Nx_len,
5346 			     const char *code,
5347 			     const u8 *Kx, size_t Kx_len,
5348 			     u8 *z, unsigned int hash_len)
5349 {
5350 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
5351 	int res;
5352 	u8 *info, *pos;
5353 	size_t info_len;
5354 
5355 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
5356 	 */
5357 
5358 	/* HKDF-Extract(<>, IKM=K.x) */
5359 	os_memset(salt, 0, hash_len);
5360 	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
5361 		return -1;
5362 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
5363 			prk, hash_len);
5364 	info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
5365 	info = os_malloc(info_len);
5366 	if (!info)
5367 		return -1;
5368 	pos = info;
5369 	os_memcpy(pos, mac_init, ETH_ALEN);
5370 	pos += ETH_ALEN;
5371 	os_memcpy(pos, mac_resp, ETH_ALEN);
5372 	pos += ETH_ALEN;
5373 	os_memcpy(pos, Mx, Mx_len);
5374 	pos += Mx_len;
5375 	os_memcpy(pos, Nx, Nx_len);
5376 	pos += Nx_len;
5377 	os_memcpy(pos, code, os_strlen(code));
5378 
5379 	/* HKDF-Expand(PRK, info, L) */
5380 	if (hash_len == 32)
5381 		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
5382 				      z, hash_len);
5383 	else if (hash_len == 48)
5384 		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
5385 				      z, hash_len);
5386 	else if (hash_len == 64)
5387 		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
5388 				      z, hash_len);
5389 	else
5390 		res = -1;
5391 	os_free(info);
5392 	os_memset(prk, 0, hash_len);
5393 	if (res < 0)
5394 		return -1;
5395 
5396 	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
5397 			z, hash_len);
5398 	return 0;
5399 }
5400 
5401 
dpp_pkex_rx_exchange_resp(struct dpp_pkex * pkex,const u8 * buf,size_t buflen)5402 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
5403 					  const u8 *buf, size_t buflen)
5404 {
5405 	const u8 *attr_status, *attr_id, *attr_key;
5406 	u16 attr_status_len, attr_id_len, attr_key_len;
5407 	const EC_GROUP *group;
5408 	BN_CTX *bnctx = NULL;
5409 	size_t clear_len;
5410 	struct wpabuf *clear = NULL;
5411 	u8 *wrapped;
5412 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
5413 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
5414 	EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
5415 	BIGNUM *Nx = NULL, *Ny = NULL;
5416 	EVP_PKEY_CTX *ctx = NULL;
5417 	EC_KEY *Y_ec = NULL;
5418 	size_t Jx_len, Kx_len;
5419 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
5420 	const u8 *addr[4];
5421 	size_t len[4];
5422 	u8 u[DPP_MAX_HASH_LEN];
5423 	u8 octet;
5424 	int res;
5425 
5426 	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
5427 				   &attr_status_len);
5428 	if (!attr_status || attr_status_len != 1) {
5429 		wpa_printf(MSG_DEBUG, "DPP: No DPP Status attribute");
5430 		return NULL;
5431 	}
5432 	wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
5433 	if (attr_status[0] != DPP_STATUS_OK) {
5434 		wpa_printf(MSG_DEBUG, "DPP: PKEX failed");
5435 		return NULL;
5436 	}
5437 
5438 	attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
5439 			       &attr_id_len);
5440 	if (!attr_id && pkex->identifier) {
5441 		wpa_printf(MSG_DEBUG,
5442 			   "DPP: No PKEX code identifier received, but expected one");
5443 		return NULL;
5444 	}
5445 	if (attr_id && pkex->identifier &&
5446 	    (os_strlen(pkex->identifier) != attr_id_len ||
5447 	     os_memcmp(pkex->identifier, attr_id, attr_id_len) != 0)) {
5448 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
5449 		return NULL;
5450 	}
5451 
5452 	/* N in Encrypted Key attribute */
5453 	attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
5454 				&attr_key_len);
5455 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
5456 		wpa_printf(MSG_DEBUG, "DPP: Missing Encrypted Key attribute");
5457 		return NULL;
5458 	}
5459 
5460 	/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
5461 	bnctx = BN_CTX_new();
5462 	if (!bnctx)
5463 		goto fail;
5464 	Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
5465 				pkex->identifier, bnctx, &group);
5466 	if (!Qr)
5467 		goto fail;
5468 
5469 	/* Y' = N - Qr */
5470 	Y = EC_POINT_new(group);
5471 	N = EC_POINT_new(group);
5472 	Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
5473 	Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
5474 	if (!Y || !N || !Nx || !Ny ||
5475 	    EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
5476 	    EC_POINT_is_at_infinity(group, N) ||
5477 	    !EC_POINT_is_on_curve(group, N, bnctx) ||
5478 	    EC_POINT_invert(group, Qr, bnctx) != 1 ||
5479 	    EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
5480 	    EC_POINT_is_at_infinity(group, Y) ||
5481 	    !EC_POINT_is_on_curve(group, Y, bnctx))
5482 		goto fail;
5483 
5484 	pkex->exchange_done = 1;
5485 
5486 	/* ECDH: J = a * Y’ */
5487 	Y_ec = EC_KEY_new();
5488 	if (!Y_ec ||
5489 	    EC_KEY_set_group(Y_ec, group) != 1 ||
5490 	    EC_KEY_set_public_key(Y_ec, Y) != 1)
5491 		goto fail;
5492 	pkex->y = EVP_PKEY_new();
5493 	if (!pkex->y ||
5494 	    EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
5495 		goto fail;
5496 	ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
5497 	if (!ctx ||
5498 	    EVP_PKEY_derive_init(ctx) != 1 ||
5499 	    EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
5500 	    EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
5501 	    Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
5502 	    EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
5503 		wpa_printf(MSG_ERROR,
5504 			   "DPP: Failed to derive ECDH shared secret: %s",
5505 			   ERR_error_string(ERR_get_error(), NULL));
5506 		goto fail;
5507 	}
5508 
5509 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
5510 			Jx, Jx_len);
5511 
5512 	/* u = HMAC(J.x,  MAC-Initiator | A.x | Y’.x | X.x ) */
5513 	A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
5514 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
5515 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
5516 	if (!A_pub || !Y_pub || !X_pub)
5517 		goto fail;
5518 	addr[0] = pkex->own_mac;
5519 	len[0] = ETH_ALEN;
5520 	addr[1] = wpabuf_head(A_pub);
5521 	len[1] = wpabuf_len(A_pub) / 2;
5522 	addr[2] = wpabuf_head(Y_pub);
5523 	len[2] = wpabuf_len(Y_pub) / 2;
5524 	addr[3] = wpabuf_head(X_pub);
5525 	len[3] = wpabuf_len(X_pub) / 2;
5526 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
5527 		goto fail;
5528 	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
5529 
5530 	/* K = x * Y’ */
5531 	EVP_PKEY_CTX_free(ctx);
5532 	ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
5533 	if (!ctx ||
5534 	    EVP_PKEY_derive_init(ctx) != 1 ||
5535 	    EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
5536 	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
5537 	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
5538 	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
5539 		wpa_printf(MSG_ERROR,
5540 			   "DPP: Failed to derive ECDH shared secret: %s",
5541 			   ERR_error_string(ERR_get_error(), NULL));
5542 		goto fail;
5543 	}
5544 
5545 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
5546 			Kx, Kx_len);
5547 
5548 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
5549 	 */
5550 	res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
5551 				pkex->Mx, curve->prime_len,
5552 				attr_key /* N.x */, attr_key_len / 2,
5553 				pkex->code, Kx, Kx_len,
5554 				pkex->z, curve->hash_len);
5555 	os_memset(Kx, 0, Kx_len);
5556 	if (res < 0)
5557 		goto fail;
5558 
5559 	/* {A, u, [bootstrapping info]}z */
5560 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
5561 	clear = wpabuf_alloc(clear_len);
5562 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ,
5563 			    4 + clear_len + AES_BLOCK_SIZE);
5564 	if (!clear || !msg)
5565 		goto fail;
5566 
5567 	/* A in Bootstrap Key attribute */
5568 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
5569 	wpabuf_put_le16(clear, wpabuf_len(A_pub));
5570 	wpabuf_put_buf(clear, A_pub);
5571 
5572 	/* u in I-Auth tag attribute */
5573 	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
5574 	wpabuf_put_le16(clear, curve->hash_len);
5575 	wpabuf_put_data(clear, u, curve->hash_len);
5576 
5577 	addr[0] = wpabuf_head_u8(msg) + 2;
5578 	len[0] = DPP_HDR_LEN;
5579 	octet = 0;
5580 	addr[1] = &octet;
5581 	len[1] = sizeof(octet);
5582 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
5583 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
5584 
5585 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
5586 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
5587 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
5588 
5589 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
5590 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
5591 			    wpabuf_head(clear), wpabuf_len(clear),
5592 			    2, addr, len, wrapped) < 0)
5593 		goto fail;
5594 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5595 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
5596 
5597 out:
5598 	wpabuf_free(clear);
5599 	wpabuf_free(A_pub);
5600 	wpabuf_free(X_pub);
5601 	wpabuf_free(Y_pub);
5602 	EC_POINT_free(Qr);
5603 	EC_POINT_free(Y);
5604 	EC_POINT_free(N);
5605 	BN_free(Nx);
5606 	BN_free(Ny);
5607 	EC_KEY_free(Y_ec);
5608 	EVP_PKEY_CTX_free(ctx);
5609 	BN_CTX_free(bnctx);
5610 	return msg;
5611 fail:
5612 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing faileed");
5613 	wpabuf_free(msg);
5614 	msg = NULL;
5615 	goto out;
5616 }
5617 
5618 
dpp_pkex_rx_commit_reveal_req(struct dpp_pkex * pkex,const u8 * hdr,const u8 * buf,size_t buflen)5619 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
5620 					      const u8 *hdr,
5621 					      const u8 *buf, size_t buflen)
5622 {
5623 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
5624 	EVP_PKEY_CTX *ctx;
5625 	size_t Jx_len, Kx_len, Lx_len;
5626 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
5627 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
5628 	const u8 *wrapped_data, *b_key, *peer_u;
5629 	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
5630 	const u8 *addr[4];
5631 	size_t len[4];
5632 	u8 octet;
5633 	u8 *unwrapped = NULL;
5634 	size_t unwrapped_len = 0;
5635 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
5636 	struct wpabuf *B_pub = NULL;
5637 	u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
5638 	size_t clear_len;
5639 	struct wpabuf *clear = NULL;
5640 	u8 *wrapped;
5641 	int res;
5642 
5643 	/* K = y * X' */
5644 	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
5645 	if (!ctx ||
5646 	    EVP_PKEY_derive_init(ctx) != 1 ||
5647 	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
5648 	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
5649 	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
5650 	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
5651 		wpa_printf(MSG_ERROR,
5652 			   "DPP: Failed to derive ECDH shared secret: %s",
5653 			   ERR_error_string(ERR_get_error(), NULL));
5654 		goto fail;
5655 	}
5656 
5657 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
5658 			Kx, Kx_len);
5659 
5660 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
5661 	 */
5662 	res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
5663 				pkex->Mx, curve->prime_len,
5664 				pkex->Nx, curve->prime_len, pkex->code,
5665 				Kx, Kx_len, pkex->z, curve->hash_len);
5666 	os_memset(Kx, 0, Kx_len);
5667 	if (res < 0)
5668 		goto fail;
5669 
5670 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
5671 				    &wrapped_data_len);
5672 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5673 		wpa_printf(MSG_DEBUG,
5674 			   "DPP: Missing or invalid required Wrapped data attribute");
5675 		goto fail;
5676 	}
5677 
5678 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5679 		    wrapped_data, wrapped_data_len);
5680 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5681 	unwrapped = os_malloc(unwrapped_len);
5682 	if (!unwrapped)
5683 		goto fail;
5684 
5685 	addr[0] = hdr;
5686 	len[0] = DPP_HDR_LEN;
5687 	octet = 0;
5688 	addr[1] = &octet;
5689 	len[1] = sizeof(octet);
5690 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
5691 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
5692 
5693 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
5694 			    wrapped_data, wrapped_data_len,
5695 			    2, addr, len, unwrapped) < 0) {
5696 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
5697 		goto fail;
5698 	}
5699 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5700 		    unwrapped, unwrapped_len);
5701 
5702 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5703 		wpa_printf(MSG_DEBUG,
5704 			   "DPP: Invalid attribute in unwrapped data");
5705 		goto fail;
5706 	}
5707 
5708 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
5709 			     &b_key_len);
5710 	if (!b_key || b_key_len != 2 * curve->prime_len) {
5711 		wpa_printf(MSG_DEBUG,
5712 			   "DPP: No valid peer bootstrapping key found");
5713 		goto fail;
5714 	}
5715 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
5716 							b_key_len);
5717 	if (!pkex->peer_bootstrap_key)
5718 		goto fail;
5719 	dpp_debug_print_key("DPP: Peer bootstrap public key",
5720 			    pkex->peer_bootstrap_key);
5721 
5722 	/* ECDH: J' = y * A' */
5723 	EVP_PKEY_CTX_free(ctx);
5724 	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
5725 	if (!ctx ||
5726 	    EVP_PKEY_derive_init(ctx) != 1 ||
5727 	    EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
5728 	    EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
5729 	    Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
5730 	    EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
5731 		wpa_printf(MSG_ERROR,
5732 			   "DPP: Failed to derive ECDH shared secret: %s",
5733 			   ERR_error_string(ERR_get_error(), NULL));
5734 		goto fail;
5735 	}
5736 
5737 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
5738 			Jx, Jx_len);
5739 
5740 	/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
5741 	A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
5742 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
5743 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
5744 	if (!A_pub || !Y_pub || !X_pub)
5745 		goto fail;
5746 	addr[0] = pkex->peer_mac;
5747 	len[0] = ETH_ALEN;
5748 	addr[1] = wpabuf_head(A_pub);
5749 	len[1] = wpabuf_len(A_pub) / 2;
5750 	addr[2] = wpabuf_head(Y_pub);
5751 	len[2] = wpabuf_len(Y_pub) / 2;
5752 	addr[3] = wpabuf_head(X_pub);
5753 	len[3] = wpabuf_len(X_pub) / 2;
5754 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
5755 		goto fail;
5756 
5757 	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
5758 			      &peer_u_len);
5759 	if (!peer_u || peer_u_len != curve->hash_len ||
5760 	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
5761 		wpa_printf(MSG_DEBUG, "DPP: No valid u (I-Auth tag) found");
5762 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
5763 			    u, curve->hash_len);
5764 		wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
5765 		goto fail;
5766 	}
5767 	wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
5768 
5769 	/* ECDH: L = b * X' */
5770 	EVP_PKEY_CTX_free(ctx);
5771 	ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
5772 	if (!ctx ||
5773 	    EVP_PKEY_derive_init(ctx) != 1 ||
5774 	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
5775 	    EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
5776 	    Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
5777 	    EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
5778 		wpa_printf(MSG_ERROR,
5779 			   "DPP: Failed to derive ECDH shared secret: %s",
5780 			   ERR_error_string(ERR_get_error(), NULL));
5781 		goto fail;
5782 	}
5783 
5784 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
5785 			Lx, Lx_len);
5786 
5787 	/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
5788 	B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
5789 	if (!B_pub)
5790 		goto fail;
5791 	addr[0] = pkex->own_mac;
5792 	len[0] = ETH_ALEN;
5793 	addr[1] = wpabuf_head(B_pub);
5794 	len[1] = wpabuf_len(B_pub) / 2;
5795 	addr[2] = wpabuf_head(X_pub);
5796 	len[2] = wpabuf_len(X_pub) / 2;
5797 	addr[3] = wpabuf_head(Y_pub);
5798 	len[3] = wpabuf_len(Y_pub) / 2;
5799 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
5800 		goto fail;
5801 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
5802 
5803 	/* {B, v [bootstrapping info]}z */
5804 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
5805 	clear = wpabuf_alloc(clear_len);
5806 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP,
5807 			    4 + clear_len + AES_BLOCK_SIZE);
5808 	if (!clear || !msg)
5809 		goto fail;
5810 
5811 	/* A in Bootstrap Key attribute */
5812 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
5813 	wpabuf_put_le16(clear, wpabuf_len(B_pub));
5814 	wpabuf_put_buf(clear, B_pub);
5815 
5816 	/* v in R-Auth tag attribute */
5817 	wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
5818 	wpabuf_put_le16(clear, curve->hash_len);
5819 	wpabuf_put_data(clear, v, curve->hash_len);
5820 
5821 	addr[0] = wpabuf_head_u8(msg) + 2;
5822 	len[0] = DPP_HDR_LEN;
5823 	octet = 1;
5824 	addr[1] = &octet;
5825 	len[1] = sizeof(octet);
5826 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
5827 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
5828 
5829 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
5830 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
5831 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
5832 
5833 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
5834 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
5835 			    wpabuf_head(clear), wpabuf_len(clear),
5836 			    2, addr, len, wrapped) < 0)
5837 		goto fail;
5838 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5839 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
5840 out:
5841 	EVP_PKEY_CTX_free(ctx);
5842 	os_free(unwrapped);
5843 	wpabuf_free(A_pub);
5844 	wpabuf_free(B_pub);
5845 	wpabuf_free(X_pub);
5846 	wpabuf_free(Y_pub);
5847 	wpabuf_free(clear);
5848 	return msg;
5849 fail:
5850 	wpabuf_free(msg);
5851 	msg = NULL;
5852 	goto out;
5853 }
5854 
5855 
dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex * pkex,const u8 * hdr,const u8 * buf,size_t buflen)5856 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
5857 				   const u8 *buf, size_t buflen)
5858 {
5859 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
5860 	const u8 *wrapped_data, *b_key, *peer_v;
5861 	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
5862 	const u8 *addr[4];
5863 	size_t len[4];
5864 	u8 octet;
5865 	u8 *unwrapped = NULL;
5866 	size_t unwrapped_len = 0;
5867 	int ret = -1;
5868 	u8 v[DPP_MAX_HASH_LEN];
5869 	size_t Lx_len;
5870 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
5871 	EVP_PKEY_CTX *ctx = NULL;
5872 	struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
5873 
5874 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
5875 				    &wrapped_data_len);
5876 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
5877 		wpa_printf(MSG_DEBUG,
5878 			   "DPP: Missing or invalid required Wrapped data attribute");
5879 		goto fail;
5880 	}
5881 
5882 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
5883 		    wrapped_data, wrapped_data_len);
5884 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
5885 	unwrapped = os_malloc(unwrapped_len);
5886 	if (!unwrapped)
5887 		goto fail;
5888 
5889 	addr[0] = hdr;
5890 	len[0] = DPP_HDR_LEN;
5891 	octet = 1;
5892 	addr[1] = &octet;
5893 	len[1] = sizeof(octet);
5894 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
5895 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
5896 
5897 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
5898 			    wrapped_data, wrapped_data_len,
5899 			    2, addr, len, unwrapped) < 0) {
5900 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
5901 		goto fail;
5902 	}
5903 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
5904 		    unwrapped, unwrapped_len);
5905 
5906 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
5907 		wpa_printf(MSG_DEBUG,
5908 			   "DPP: Invalid attribute in unwrapped data");
5909 		goto fail;
5910 	}
5911 
5912 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
5913 			     &b_key_len);
5914 	if (!b_key || b_key_len != 2 * curve->prime_len) {
5915 		wpa_printf(MSG_DEBUG,
5916 			   "DPP: No valid peer bootstrapping key found");
5917 		goto fail;
5918 	}
5919 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
5920 							b_key_len);
5921 	if (!pkex->peer_bootstrap_key)
5922 		goto fail;
5923 	dpp_debug_print_key("DPP: Peer bootstrap public key",
5924 			    pkex->peer_bootstrap_key);
5925 
5926 	/* ECDH: L' = x * B' */
5927 	ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
5928 	if (!ctx ||
5929 	    EVP_PKEY_derive_init(ctx) != 1 ||
5930 	    EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
5931 	    EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
5932 	    Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
5933 	    EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
5934 		wpa_printf(MSG_ERROR,
5935 			   "DPP: Failed to derive ECDH shared secret: %s",
5936 			   ERR_error_string(ERR_get_error(), NULL));
5937 		goto fail;
5938 	}
5939 
5940 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
5941 			Lx, Lx_len);
5942 
5943 	/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
5944 	B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
5945 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
5946 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
5947 	if (!B_pub || !X_pub || !Y_pub)
5948 		goto fail;
5949 	addr[0] = pkex->peer_mac;
5950 	len[0] = ETH_ALEN;
5951 	addr[1] = wpabuf_head(B_pub);
5952 	len[1] = wpabuf_len(B_pub) / 2;
5953 	addr[2] = wpabuf_head(X_pub);
5954 	len[2] = wpabuf_len(X_pub) / 2;
5955 	addr[3] = wpabuf_head(Y_pub);
5956 	len[3] = wpabuf_len(Y_pub) / 2;
5957 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
5958 		goto fail;
5959 
5960 	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
5961 			      &peer_v_len);
5962 	if (!peer_v || peer_v_len != curve->hash_len ||
5963 	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
5964 		wpa_printf(MSG_DEBUG, "DPP: No valid v (R-Auth tag) found");
5965 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
5966 			    v, curve->hash_len);
5967 		wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
5968 		goto fail;
5969 	}
5970 	wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
5971 
5972 	ret = 0;
5973 out:
5974 	wpabuf_free(B_pub);
5975 	wpabuf_free(X_pub);
5976 	wpabuf_free(Y_pub);
5977 	EVP_PKEY_CTX_free(ctx);
5978 	os_free(unwrapped);
5979 	return ret;
5980 fail:
5981 	goto out;
5982 }
5983 
5984 
dpp_pkex_free(struct dpp_pkex * pkex)5985 void dpp_pkex_free(struct dpp_pkex *pkex)
5986 {
5987 	if (!pkex)
5988 		return;
5989 
5990 	os_free(pkex->identifier);
5991 	os_free(pkex->code);
5992 	EVP_PKEY_free(pkex->x);
5993 	EVP_PKEY_free(pkex->y);
5994 	EVP_PKEY_free(pkex->peer_bootstrap_key);
5995 	wpabuf_free(pkex->exchange_req);
5996 	wpabuf_free(pkex->exchange_resp);
5997 	os_free(pkex);
5998 }
5999