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
31static 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
39static 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
51static 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 */
67static 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 };
73static 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 };
79static 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};
85static 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 */
93static 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};
101static 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};
109static 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};
117static 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 */
127static 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};
138static 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};
149static 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};
160static 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 */
173static 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};
179static 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};
185static 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};
191static 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 */
199static 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};
207static 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};
215static 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};
223static 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 */
233static 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};
243static 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};
253static 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};
263static 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
275static 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
289static 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
308static 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
325static 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
338static 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
385static 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
439out:
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;
446fail:
447	EVP_PKEY_free(pkey);
448	pkey = NULL;
449	goto out;
450}
451
452
453static 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
482struct 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
500const 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
523int 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
557void 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
568const 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
580static 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
593static 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
600int 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;
644fail:
645	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
646	return -1;
647}
648
649
650int 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
666int 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
691static const struct dpp_curve_params *
692dpp_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
706static 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
721static 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;
851fail:
852	X509_PUBKEY_free(pub);
853	EVP_PKEY_free(pkey);
854	return -1;
855}
856
857
858static 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
922struct 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
933static 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
980static 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;
1043fail:
1044	EVP_PKEY_CTX_free(kctx);
1045	EVP_PKEY_free(params);
1046	return NULL;
1047}
1048
1049
1050static const struct dpp_curve_params *
1051dpp_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
1065static const struct dpp_curve_params *
1066dpp_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
1079static 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
1124int 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
1156char * 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;
1218fail:
1219	os_free(base64);
1220	OPENSSL_free(der);
1221	return NULL;
1222}
1223
1224
1225static 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
1253static 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
1282static 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
1330struct 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;
1473fail:
1474	wpabuf_free(pi);
1475	EVP_PKEY_CTX_free(ctx);
1476	dpp_auth_deinit(auth);
1477	return NULL;
1478}
1479
1480
1481struct 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
1535fail:
1536	wpabuf_free(clear);
1537	wpabuf_free(msg);
1538	return NULL;
1539}
1540
1541
1542static 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
1556static 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);
1626fail:
1627	wpabuf_free(pix);
1628	wpabuf_free(prx);
1629	wpabuf_free(bix);
1630	wpabuf_free(brx);
1631	return res;
1632}
1633
1634
1635static 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);
1709fail:
1710	wpabuf_free(pix);
1711	wpabuf_free(prx);
1712	wpabuf_free(bix);
1713	wpabuf_free(brx);
1714	return res;
1715}
1716
1717
1718static 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;
1780fail:
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
1793static 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;
1850fail:
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
1861static 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
2039fail:
2040	wpabuf_free(pr);
2041	return -1;
2042}
2043
2044
2045static 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
2138fail:
2139	return -1;
2140}
2141
2142
2143struct dpp_authentication *
2144dpp_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
2322not_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;
2336fail:
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
2345int 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
2365static 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
2438fail:
2439	return NULL;
2440}
2441
2442
2443static void
2444dpp_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	}
2525fail:
2526	bin_clear_free(unwrapped, unwrapped_len);
2527}
2528
2529
2530struct wpabuf *
2531dpp_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
2786fail:
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
2795int 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;
2926fail:
2927	bin_clear_free(unwrapped, unwrapped_len);
2928	return -1;
2929}
2930
2931
2932void 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
2941void 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
2964static struct wpabuf *
2965dpp_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
3001static 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
3015static 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;
3047fail:
3048	wpabuf_free(pub);
3049	os_free(x);
3050	os_free(y);
3051	return ret;
3052}
3053
3054
3055static struct wpabuf *
3056dpp_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
3119skip_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
3231out:
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;
3240fail:
3241	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
3242	wpabuf_free(buf);
3243	buf = NULL;
3244	goto out;
3245}
3246
3247
3248static struct wpabuf *
3249dpp_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
3290static struct wpabuf *
3291dpp_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
3317static struct wpabuf *
3318dpp_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;
3384fail:
3385	wpabuf_free(conf);
3386	wpabuf_free(clear);
3387	wpabuf_free(msg);
3388	return NULL;
3389}
3390
3391
3392struct wpabuf *
3393dpp_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
3503fail:
3504	json_free(root);
3505	os_free(unwrapped);
3506	return resp;
3507}
3508
3509
3510static struct wpabuf *
3511dpp_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
3584fail:
3585	json_free(root);
3586	return kid;
3587}
3588
3589
3590static 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
3627static 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
3697fail:
3698	wpabuf_free(x);
3699	wpabuf_free(y);
3700
3701	return pkey;
3702}
3703
3704
3705int 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
3784static 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	}
3824skip_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;
3873fail:
3874	EVP_PKEY_free(key);
3875	json_free(root);
3876	return ret;
3877}
3878
3879
3880static 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
3912static 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
3926static 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
3948struct dpp_signed_connector_info {
3949	unsigned char *payload;
3950	size_t payload_len;
3951};
3952
3953static int
3954dpp_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;
4093fail:
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
4107static 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;
4166fail:
4167	EVP_PKEY_free(csign_pub);
4168	os_free(info.payload);
4169	return ret;
4170}
4171
4172
4173static 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;
4246fail:
4247	json_free(root);
4248	return ret;
4249}
4250
4251
4252int 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
4345fail:
4346	os_free(unwrapped);
4347	return ret;
4348}
4349
4350
4351void 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
4361struct dpp_configurator *
4362dpp_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;
4413out:
4414	wpabuf_free(csign_pub);
4415	return conf;
4416fail:
4417	dpp_configurator_free(conf);
4418	conf = NULL;
4419	goto out;
4420}
4421
4422
4423int 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));
4460fail:
4461	wpabuf_free(conf_obj);
4462	auth->peer_protocol_key = NULL;
4463	return ret;
4464}
4465
4466
4467static 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
4474static 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
4508static 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
4550static 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
4578static 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;
4611fail:
4612	wpabuf_free(nkx);
4613	wpabuf_free(pkx);
4614	return ret;
4615}
4616
4617
4618int 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;
4771fail:
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
4789static 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
4832static 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	}
4899out:
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;
4906fail:
4907	EC_POINT_free(Qi);
4908	Qi = NULL;
4909	goto out;
4910}
4911
4912
4913static 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;
4976out:
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;
4983fail:
4984	EC_POINT_free(Qr);
4985	Qr = NULL;
4986	goto out;
4987}
4988
4989
4990static 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
5082out:
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;
5091fail:
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
5099struct 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;
5124fail:
5125	dpp_pkex_free(pkex);
5126	return NULL;
5127}
5128
5129
5130struct 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
5320out:
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;
5335fail:
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
5343static 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
5402struct 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
5597out:
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;
5611fail:
5612	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing faileed");
5613	wpabuf_free(msg);
5614	msg = NULL;
5615	goto out;
5616}
5617
5618
5619struct 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);
5840out:
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;
5849fail:
5850	wpabuf_free(msg);
5851	msg = NULL;
5852	goto out;
5853}
5854
5855
5856int 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;
5973out:
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;
5980fail:
5981	goto out;
5982}
5983
5984
5985void 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