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