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