xref: /freebsd-src/contrib/wpa/src/common/dpp_crypto.c (revision 32a95656b51ebefcdf3e0b02c110825f59abd26f)
1c1d255d3SCy Schubert /*
2c1d255d3SCy Schubert  * DPP crypto functionality
3c1d255d3SCy Schubert  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4c1d255d3SCy Schubert  * Copyright (c) 2018-2020, The Linux Foundation
5c1d255d3SCy Schubert  *
6c1d255d3SCy Schubert  * This software may be distributed under the terms of the BSD license.
7c1d255d3SCy Schubert  * See README for more details.
8c1d255d3SCy Schubert  */
9c1d255d3SCy Schubert 
10c1d255d3SCy Schubert #include "utils/includes.h"
11c1d255d3SCy Schubert 
12c1d255d3SCy Schubert #include "utils/common.h"
13c1d255d3SCy Schubert #include "utils/base64.h"
14c1d255d3SCy Schubert #include "utils/json.h"
15c1d255d3SCy Schubert #include "common/ieee802_11_defs.h"
16c1d255d3SCy Schubert #include "crypto/crypto.h"
17c1d255d3SCy Schubert #include "crypto/random.h"
18c1d255d3SCy Schubert #include "crypto/sha384.h"
19c1d255d3SCy Schubert #include "crypto/sha512.h"
204b72b91aSCy Schubert #include "tls/asn1.h"
21c1d255d3SCy Schubert #include "dpp.h"
22c1d255d3SCy Schubert #include "dpp_i.h"
23c1d255d3SCy Schubert 
24c1d255d3SCy Schubert 
25c1d255d3SCy Schubert static const struct dpp_curve_params dpp_curves[] = {
26c1d255d3SCy Schubert 	/* The mandatory to support and the default NIST P-256 curve needs to
27c1d255d3SCy Schubert 	 * be the first entry on this list. */
28c1d255d3SCy Schubert 	{ "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
29c1d255d3SCy Schubert 	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
30c1d255d3SCy Schubert 	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
31c1d255d3SCy Schubert 	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
32c1d255d3SCy Schubert 	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
33c1d255d3SCy Schubert 	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
34c1d255d3SCy Schubert 	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
35c1d255d3SCy Schubert };
36c1d255d3SCy Schubert 
37c1d255d3SCy Schubert 
38c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_name(const char *name)
39c1d255d3SCy Schubert {
40c1d255d3SCy Schubert 	int i;
41c1d255d3SCy Schubert 
42c1d255d3SCy Schubert 	if (!name)
43c1d255d3SCy Schubert 		return &dpp_curves[0];
44c1d255d3SCy Schubert 
45c1d255d3SCy Schubert 	for (i = 0; dpp_curves[i].name; i++) {
46c1d255d3SCy Schubert 		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
47c1d255d3SCy Schubert 		    (dpp_curves[i].jwk_crv &&
48c1d255d3SCy Schubert 		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
49c1d255d3SCy Schubert 			return &dpp_curves[i];
50c1d255d3SCy Schubert 	}
51c1d255d3SCy Schubert 	return NULL;
52c1d255d3SCy Schubert }
53c1d255d3SCy Schubert 
54c1d255d3SCy Schubert 
55c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name)
56c1d255d3SCy Schubert {
57c1d255d3SCy Schubert 	int i;
58c1d255d3SCy Schubert 
59c1d255d3SCy Schubert 	for (i = 0; dpp_curves[i].name; i++) {
60c1d255d3SCy Schubert 		if (dpp_curves[i].jwk_crv &&
61c1d255d3SCy Schubert 		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
62c1d255d3SCy Schubert 			return &dpp_curves[i];
63c1d255d3SCy Schubert 	}
64c1d255d3SCy Schubert 	return NULL;
65c1d255d3SCy Schubert }
66c1d255d3SCy Schubert 
67c1d255d3SCy Schubert 
68c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
69c1d255d3SCy Schubert {
70c1d255d3SCy Schubert 	int i;
71c1d255d3SCy Schubert 
72c1d255d3SCy Schubert 	for (i = 0; dpp_curves[i].name; i++) {
73c1d255d3SCy Schubert 		if (dpp_curves[i].ike_group == group)
74c1d255d3SCy Schubert 			return &dpp_curves[i];
75c1d255d3SCy Schubert 	}
76c1d255d3SCy Schubert 	return NULL;
77c1d255d3SCy Schubert }
78c1d255d3SCy Schubert 
79c1d255d3SCy Schubert 
804b72b91aSCy Schubert void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
81c1d255d3SCy Schubert {
824b72b91aSCy Schubert 	struct wpabuf *der = NULL;
83c1d255d3SCy Schubert 
844b72b91aSCy Schubert 	crypto_ec_key_debug_print(key, title);
85c1d255d3SCy Schubert 
864b72b91aSCy Schubert 	der = crypto_ec_key_get_ecprivate_key(key, true);
874b72b91aSCy Schubert 	if (der) {
884b72b91aSCy Schubert 		wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
894b72b91aSCy Schubert 	} else {
904b72b91aSCy Schubert 		der = crypto_ec_key_get_subject_public_key(key);
914b72b91aSCy Schubert 		if (der)
924b72b91aSCy Schubert 			wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
93c1d255d3SCy Schubert 	}
94c1d255d3SCy Schubert 
954b72b91aSCy Schubert 	wpabuf_clear_free(der);
96c1d255d3SCy Schubert }
97c1d255d3SCy Schubert 
98c1d255d3SCy Schubert 
99c1d255d3SCy Schubert static int dpp_hash_vector(const struct dpp_curve_params *curve,
100c1d255d3SCy Schubert 			   size_t num_elem, const u8 *addr[], const size_t *len,
101c1d255d3SCy Schubert 			   u8 *mac)
102c1d255d3SCy Schubert {
103c1d255d3SCy Schubert 	if (curve->hash_len == 32)
104c1d255d3SCy Schubert 		return sha256_vector(num_elem, addr, len, mac);
105c1d255d3SCy Schubert 	if (curve->hash_len == 48)
106c1d255d3SCy Schubert 		return sha384_vector(num_elem, addr, len, mac);
107c1d255d3SCy Schubert 	if (curve->hash_len == 64)
108c1d255d3SCy Schubert 		return sha512_vector(num_elem, addr, len, mac);
109c1d255d3SCy Schubert 	return -1;
110c1d255d3SCy Schubert }
111c1d255d3SCy Schubert 
112c1d255d3SCy Schubert 
113c1d255d3SCy Schubert int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
114c1d255d3SCy Schubert 		    const char *label, u8 *out, size_t outlen)
115c1d255d3SCy Schubert {
116c1d255d3SCy Schubert 	if (hash_len == 32)
117c1d255d3SCy Schubert 		return hmac_sha256_kdf(secret, secret_len, NULL,
118c1d255d3SCy Schubert 				       (const u8 *) label, os_strlen(label),
119c1d255d3SCy Schubert 				       out, outlen);
120c1d255d3SCy Schubert 	if (hash_len == 48)
121c1d255d3SCy Schubert 		return hmac_sha384_kdf(secret, secret_len, NULL,
122c1d255d3SCy Schubert 				       (const u8 *) label, os_strlen(label),
123c1d255d3SCy Schubert 				       out, outlen);
124c1d255d3SCy Schubert 	if (hash_len == 64)
125c1d255d3SCy Schubert 		return hmac_sha512_kdf(secret, secret_len, NULL,
126c1d255d3SCy Schubert 				       (const u8 *) label, os_strlen(label),
127c1d255d3SCy Schubert 				       out, outlen);
128c1d255d3SCy Schubert 	return -1;
129c1d255d3SCy Schubert }
130c1d255d3SCy Schubert 
131c1d255d3SCy Schubert 
132c1d255d3SCy Schubert int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
133c1d255d3SCy Schubert 		    size_t num_elem, const u8 *addr[], const size_t *len,
134c1d255d3SCy Schubert 		    u8 *mac)
135c1d255d3SCy Schubert {
136c1d255d3SCy Schubert 	if (hash_len == 32)
137c1d255d3SCy Schubert 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
138c1d255d3SCy Schubert 					  mac);
139c1d255d3SCy Schubert 	if (hash_len == 48)
140c1d255d3SCy Schubert 		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
141c1d255d3SCy Schubert 					  mac);
142c1d255d3SCy Schubert 	if (hash_len == 64)
143c1d255d3SCy Schubert 		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
144c1d255d3SCy Schubert 					  mac);
145c1d255d3SCy Schubert 	return -1;
146c1d255d3SCy Schubert }
147c1d255d3SCy Schubert 
148c1d255d3SCy Schubert 
149c1d255d3SCy Schubert static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
150c1d255d3SCy Schubert 		    const u8 *data, size_t data_len, u8 *mac)
151c1d255d3SCy Schubert {
152c1d255d3SCy Schubert 	if (hash_len == 32)
153c1d255d3SCy Schubert 		return hmac_sha256(key, key_len, data, data_len, mac);
154c1d255d3SCy Schubert 	if (hash_len == 48)
155c1d255d3SCy Schubert 		return hmac_sha384(key, key_len, data, data_len, mac);
156c1d255d3SCy Schubert 	if (hash_len == 64)
157c1d255d3SCy Schubert 		return hmac_sha512(key, key_len, data, data_len, mac);
158c1d255d3SCy Schubert 	return -1;
159c1d255d3SCy Schubert }
160c1d255d3SCy Schubert 
161c1d255d3SCy Schubert 
162c1d255d3SCy Schubert #ifdef CONFIG_DPP2
163c1d255d3SCy Schubert 
164c1d255d3SCy Schubert static int dpp_pbkdf2_f(size_t hash_len,
165c1d255d3SCy Schubert 			const u8 *password, size_t password_len,
166c1d255d3SCy Schubert 			const u8 *salt, size_t salt_len,
167c1d255d3SCy Schubert 			unsigned int iterations, unsigned int count, u8 *digest)
168c1d255d3SCy Schubert {
169c1d255d3SCy Schubert 	unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN];
170c1d255d3SCy Schubert 	unsigned int i;
171c1d255d3SCy Schubert 	size_t j;
172c1d255d3SCy Schubert 	u8 count_buf[4];
173c1d255d3SCy Schubert 	const u8 *addr[2];
174c1d255d3SCy Schubert 	size_t len[2];
175c1d255d3SCy Schubert 
176c1d255d3SCy Schubert 	addr[0] = salt;
177c1d255d3SCy Schubert 	len[0] = salt_len;
178c1d255d3SCy Schubert 	addr[1] = count_buf;
179c1d255d3SCy Schubert 	len[1] = 4;
180c1d255d3SCy Schubert 
181c1d255d3SCy Schubert 	/* F(P, S, c, i) = U1 xor U2 xor ... Uc
182c1d255d3SCy Schubert 	 * U1 = PRF(P, S || i)
183c1d255d3SCy Schubert 	 * U2 = PRF(P, U1)
184c1d255d3SCy Schubert 	 * Uc = PRF(P, Uc-1)
185c1d255d3SCy Schubert 	 */
186c1d255d3SCy Schubert 
187c1d255d3SCy Schubert 	WPA_PUT_BE32(count_buf, count);
188c1d255d3SCy Schubert 	if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len,
189c1d255d3SCy Schubert 			    tmp))
190c1d255d3SCy Schubert 		return -1;
191c1d255d3SCy Schubert 	os_memcpy(digest, tmp, hash_len);
192c1d255d3SCy Schubert 
193c1d255d3SCy Schubert 	for (i = 1; i < iterations; i++) {
194c1d255d3SCy Schubert 		if (dpp_hmac(hash_len, password, password_len, tmp, hash_len,
195c1d255d3SCy Schubert 			     tmp2))
196c1d255d3SCy Schubert 			return -1;
197c1d255d3SCy Schubert 		os_memcpy(tmp, tmp2, hash_len);
198c1d255d3SCy Schubert 		for (j = 0; j < hash_len; j++)
199c1d255d3SCy Schubert 			digest[j] ^= tmp2[j];
200c1d255d3SCy Schubert 	}
201c1d255d3SCy Schubert 
202c1d255d3SCy Schubert 	return 0;
203c1d255d3SCy Schubert }
204c1d255d3SCy Schubert 
205c1d255d3SCy Schubert 
206c1d255d3SCy Schubert int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
207c1d255d3SCy Schubert 	       const u8 *salt, size_t salt_len, unsigned int iterations,
208c1d255d3SCy Schubert 	       u8 *buf, size_t buflen)
209c1d255d3SCy Schubert {
210c1d255d3SCy Schubert 	unsigned int count = 0;
211c1d255d3SCy Schubert 	unsigned char *pos = buf;
212c1d255d3SCy Schubert 	size_t left = buflen, plen;
213c1d255d3SCy Schubert 	unsigned char digest[DPP_MAX_HASH_LEN];
214c1d255d3SCy Schubert 
215c1d255d3SCy Schubert 	while (left > 0) {
216c1d255d3SCy Schubert 		count++;
217c1d255d3SCy Schubert 		if (dpp_pbkdf2_f(hash_len, password, password_len,
218c1d255d3SCy Schubert 				 salt, salt_len, iterations, count, digest))
219c1d255d3SCy Schubert 			return -1;
220c1d255d3SCy Schubert 		plen = left > hash_len ? hash_len : left;
221c1d255d3SCy Schubert 		os_memcpy(pos, digest, plen);
222c1d255d3SCy Schubert 		pos += plen;
223c1d255d3SCy Schubert 		left -= plen;
224c1d255d3SCy Schubert 	}
225c1d255d3SCy Schubert 
226c1d255d3SCy Schubert 	return 0;
227c1d255d3SCy Schubert }
228c1d255d3SCy Schubert 
229c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */
230c1d255d3SCy Schubert 
231c1d255d3SCy Schubert 
2324b72b91aSCy Schubert struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
2334b72b91aSCy Schubert 					    const u8 *buf, size_t len)
234c1d255d3SCy Schubert {
2354b72b91aSCy Schubert 	int ike_group = crypto_ec_key_group(group_key);
236c1d255d3SCy Schubert 
237c1d255d3SCy Schubert 	if (len & 1)
238c1d255d3SCy Schubert 		return NULL;
239c1d255d3SCy Schubert 
2404b72b91aSCy Schubert 	if (ike_group < 0) {
2414b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
242c1d255d3SCy Schubert 		return NULL;
243c1d255d3SCy Schubert 	}
244c1d255d3SCy Schubert 
2454b72b91aSCy Schubert 	return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
246c1d255d3SCy Schubert }
247c1d255d3SCy Schubert 
248c1d255d3SCy Schubert 
2494b72b91aSCy Schubert struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
250c1d255d3SCy Schubert {
2514b72b91aSCy Schubert 	struct crypto_ec_key *key;
252c1d255d3SCy Schubert 
253c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
254c1d255d3SCy Schubert 
2554b72b91aSCy Schubert 	key = crypto_ec_key_gen(curve->ike_group);
2564b72b91aSCy Schubert 	if (key && wpa_debug_show_keys)
257c1d255d3SCy Schubert 	    dpp_debug_print_key("Own generated key", key);
258c1d255d3SCy Schubert 
259c1d255d3SCy Schubert 	return key;
260c1d255d3SCy Schubert }
261c1d255d3SCy Schubert 
262c1d255d3SCy Schubert 
2634b72b91aSCy Schubert struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
264c1d255d3SCy Schubert 				       const u8 *privkey, size_t privkey_len)
265c1d255d3SCy Schubert {
2664b72b91aSCy Schubert 	struct crypto_ec_key *key;
2674b72b91aSCy Schubert 	int group;
268c1d255d3SCy Schubert 
2694b72b91aSCy Schubert 	key = crypto_ec_key_parse_priv(privkey, privkey_len);
2704b72b91aSCy Schubert 	if (!key) {
2714b72b91aSCy Schubert 		wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
272c1d255d3SCy Schubert 		return NULL;
273c1d255d3SCy Schubert 	}
2744b72b91aSCy Schubert 
2754b72b91aSCy Schubert 	group = crypto_ec_key_group(key);
2764b72b91aSCy Schubert 	if (group < 0) {
2774b72b91aSCy Schubert 		crypto_ec_key_deinit(key);
278c1d255d3SCy Schubert 		return NULL;
279c1d255d3SCy Schubert 	}
2804b72b91aSCy Schubert 
2814b72b91aSCy Schubert 	*curve = dpp_get_curve_ike_group(group);
282c1d255d3SCy Schubert 	if (!*curve) {
283c1d255d3SCy Schubert 		wpa_printf(MSG_INFO,
2844b72b91aSCy Schubert 			   "DPP: Unsupported curve (group=%d) in pre-assigned key",
2854b72b91aSCy Schubert 			   group);
2864b72b91aSCy Schubert 		crypto_ec_key_deinit(key);
287c1d255d3SCy Schubert 		return NULL;
288c1d255d3SCy Schubert 	}
289c1d255d3SCy Schubert 
2904b72b91aSCy Schubert 	return key;
291c1d255d3SCy Schubert }
292c1d255d3SCy Schubert 
293c1d255d3SCy Schubert 
294c1d255d3SCy Schubert int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
295c1d255d3SCy Schubert {
296c1d255d3SCy Schubert 	struct wpabuf *der;
297c1d255d3SCy Schubert 	int res;
298c1d255d3SCy Schubert 
2994b72b91aSCy Schubert 	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
300c1d255d3SCy Schubert 	if (!der)
301c1d255d3SCy Schubert 		return -1;
302c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
303c1d255d3SCy Schubert 			der);
304c1d255d3SCy Schubert 	res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
305c1d255d3SCy Schubert 	if (res < 0)
306c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
307c1d255d3SCy Schubert 	wpabuf_free(der);
308c1d255d3SCy Schubert 	return res;
309c1d255d3SCy Schubert }
310c1d255d3SCy Schubert 
311c1d255d3SCy Schubert 
312c1d255d3SCy Schubert int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
313c1d255d3SCy Schubert 	       const u8 *privkey, size_t privkey_len)
314c1d255d3SCy Schubert {
315c1d255d3SCy Schubert 	char *base64 = NULL;
316c1d255d3SCy Schubert 	char *pos, *end;
317c1d255d3SCy Schubert 	size_t len;
318c1d255d3SCy Schubert 	struct wpabuf *der = NULL;
319c1d255d3SCy Schubert 
320c1d255d3SCy Schubert 	bi->curve = dpp_get_curve_name(curve);
321c1d255d3SCy Schubert 	if (!bi->curve) {
322c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
323c1d255d3SCy Schubert 		return -1;
324c1d255d3SCy Schubert 	}
325c1d255d3SCy Schubert 
326c1d255d3SCy Schubert 	if (privkey)
327c1d255d3SCy Schubert 		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
328c1d255d3SCy Schubert 	else
329c1d255d3SCy Schubert 		bi->pubkey = dpp_gen_keypair(bi->curve);
330c1d255d3SCy Schubert 	if (!bi->pubkey)
331c1d255d3SCy Schubert 		goto fail;
332c1d255d3SCy Schubert 	bi->own = 1;
333c1d255d3SCy Schubert 
3344b72b91aSCy Schubert 	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
335c1d255d3SCy Schubert 	if (!der)
336c1d255d3SCy Schubert 		goto fail;
337c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
338c1d255d3SCy Schubert 			der);
339c1d255d3SCy Schubert 
340c1d255d3SCy Schubert 	if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
341c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
342c1d255d3SCy Schubert 		goto fail;
343c1d255d3SCy Schubert 	}
344c1d255d3SCy Schubert 
345c1d255d3SCy Schubert 	base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
346c1d255d3SCy Schubert 	wpabuf_free(der);
347c1d255d3SCy Schubert 	der = NULL;
348c1d255d3SCy Schubert 	if (!base64)
349c1d255d3SCy Schubert 		goto fail;
350c1d255d3SCy Schubert 	pos = base64;
351c1d255d3SCy Schubert 	end = pos + len;
352c1d255d3SCy Schubert 	for (;;) {
353c1d255d3SCy Schubert 		pos = os_strchr(pos, '\n');
354c1d255d3SCy Schubert 		if (!pos)
355c1d255d3SCy Schubert 			break;
356c1d255d3SCy Schubert 		os_memmove(pos, pos + 1, end - pos);
357c1d255d3SCy Schubert 	}
358c1d255d3SCy Schubert 	os_free(bi->pk);
359c1d255d3SCy Schubert 	bi->pk = base64;
360c1d255d3SCy Schubert 	return 0;
361c1d255d3SCy Schubert fail:
362c1d255d3SCy Schubert 	os_free(base64);
363c1d255d3SCy Schubert 	wpabuf_free(der);
364c1d255d3SCy Schubert 	return -1;
365c1d255d3SCy Schubert }
366c1d255d3SCy Schubert 
367c1d255d3SCy Schubert 
368c1d255d3SCy Schubert int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len)
369c1d255d3SCy Schubert {
370c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
371c1d255d3SCy Schubert 	const char *info = "first intermediate key";
372c1d255d3SCy Schubert 	int res;
373c1d255d3SCy Schubert 
374c1d255d3SCy Schubert 	/* k1 = HKDF(<>, "first intermediate key", M.x) */
375c1d255d3SCy Schubert 
376c1d255d3SCy Schubert 	/* HKDF-Extract(<>, M.x) */
377c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
378c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
379c1d255d3SCy Schubert 		return -1;
380c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
381c1d255d3SCy Schubert 			prk, hash_len);
382c1d255d3SCy Schubert 
383c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
384c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
385c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
386c1d255d3SCy Schubert 	if (res < 0)
387c1d255d3SCy Schubert 		return -1;
388c1d255d3SCy Schubert 
389c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
390c1d255d3SCy Schubert 			k1, hash_len);
391c1d255d3SCy Schubert 	return 0;
392c1d255d3SCy Schubert }
393c1d255d3SCy Schubert 
394c1d255d3SCy Schubert 
395c1d255d3SCy Schubert int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len)
396c1d255d3SCy Schubert {
397c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
398c1d255d3SCy Schubert 	const char *info = "second intermediate key";
399c1d255d3SCy Schubert 	int res;
400c1d255d3SCy Schubert 
401c1d255d3SCy Schubert 	/* k2 = HKDF(<>, "second intermediate key", N.x) */
402c1d255d3SCy Schubert 
403c1d255d3SCy Schubert 	/* HKDF-Extract(<>, N.x) */
404c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
405c1d255d3SCy Schubert 	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
406c1d255d3SCy Schubert 	if (res < 0)
407c1d255d3SCy Schubert 		return -1;
408c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
409c1d255d3SCy Schubert 			prk, hash_len);
410c1d255d3SCy Schubert 
411c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
412c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
413c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
414c1d255d3SCy Schubert 	if (res < 0)
415c1d255d3SCy Schubert 		return -1;
416c1d255d3SCy Schubert 
417c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
418c1d255d3SCy Schubert 			k2, hash_len);
419c1d255d3SCy Schubert 	return 0;
420c1d255d3SCy Schubert }
421c1d255d3SCy Schubert 
422c1d255d3SCy Schubert 
423c1d255d3SCy Schubert int dpp_derive_bk_ke(struct dpp_authentication *auth)
424c1d255d3SCy Schubert {
425c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
426c1d255d3SCy Schubert 	size_t nonce_len = auth->curve->nonce_len;
427c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
428c1d255d3SCy Schubert 	const char *info_ke = "DPP Key";
429c1d255d3SCy Schubert 	int res;
430c1d255d3SCy Schubert 	const u8 *addr[3];
431c1d255d3SCy Schubert 	size_t len[3];
432c1d255d3SCy Schubert 	size_t num_elem = 0;
433c1d255d3SCy Schubert 
434c1d255d3SCy Schubert 	if (!auth->Mx_len || !auth->Nx_len) {
435c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
436c1d255d3SCy Schubert 			   "DPP: Mx/Nx not available - cannot derive ke");
437c1d255d3SCy Schubert 		return -1;
438c1d255d3SCy Schubert 	}
439c1d255d3SCy Schubert 
440c1d255d3SCy Schubert 	/* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
441c1d255d3SCy Schubert 	os_memcpy(nonces, auth->i_nonce, nonce_len);
442c1d255d3SCy Schubert 	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
443c1d255d3SCy Schubert 	addr[num_elem] = auth->Mx;
444c1d255d3SCy Schubert 	len[num_elem] = auth->Mx_len;
445c1d255d3SCy Schubert 	num_elem++;
446c1d255d3SCy Schubert 	addr[num_elem] = auth->Nx;
447c1d255d3SCy Schubert 	len[num_elem] = auth->Nx_len;
448c1d255d3SCy Schubert 	num_elem++;
449c1d255d3SCy Schubert 	if (auth->peer_bi && auth->own_bi) {
450c1d255d3SCy Schubert 		if (!auth->Lx_len) {
451c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG,
452c1d255d3SCy Schubert 				   "DPP: Lx not available - cannot derive ke");
453c1d255d3SCy Schubert 			return -1;
454c1d255d3SCy Schubert 		}
455c1d255d3SCy Schubert 		addr[num_elem] = auth->Lx;
456c1d255d3SCy Schubert 		len[num_elem] = auth->secret_len;
457c1d255d3SCy Schubert 		num_elem++;
458c1d255d3SCy Schubert 	}
459c1d255d3SCy Schubert 	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
460c1d255d3SCy Schubert 			      num_elem, addr, len, auth->bk);
461c1d255d3SCy Schubert 	if (res < 0)
462c1d255d3SCy Schubert 		return -1;
463c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
464c1d255d3SCy Schubert 			"DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])",
465c1d255d3SCy Schubert 			auth->bk, hash_len);
466c1d255d3SCy Schubert 
467c1d255d3SCy Schubert 	/* ke = HKDF-Expand(bk, "DPP Key", length) */
468c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke,
469c1d255d3SCy Schubert 			      hash_len);
470c1d255d3SCy Schubert 	if (res < 0)
471c1d255d3SCy Schubert 		return -1;
472c1d255d3SCy Schubert 
473c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
474c1d255d3SCy Schubert 			"DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)",
475c1d255d3SCy Schubert 			auth->ke, hash_len);
476c1d255d3SCy Schubert 
477c1d255d3SCy Schubert 	return 0;
478c1d255d3SCy Schubert }
479c1d255d3SCy Schubert 
480c1d255d3SCy Schubert 
4814b72b91aSCy Schubert int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
4824b72b91aSCy Schubert 	     u8 *secret, size_t *secret_len)
483c1d255d3SCy Schubert {
4844b72b91aSCy Schubert 	struct crypto_ecdh *ecdh;
4854b72b91aSCy Schubert 	struct wpabuf *peer_pub, *secret_buf = NULL;
486c1d255d3SCy Schubert 	int ret = -1;
487c1d255d3SCy Schubert 
488c1d255d3SCy Schubert 	*secret_len = 0;
489c1d255d3SCy Schubert 
4904b72b91aSCy Schubert 	ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
4914b72b91aSCy Schubert 	if (!ecdh) {
4924b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
493c1d255d3SCy Schubert 		return -1;
494c1d255d3SCy Schubert 	}
495c1d255d3SCy Schubert 
4964b72b91aSCy Schubert 	peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
4974b72b91aSCy Schubert 	if (!peer_pub) {
498c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR,
4994b72b91aSCy Schubert 			   "DPP: crypto_ec_key_get_pubkey_point() failed");
500c1d255d3SCy Schubert 		goto fail;
501c1d255d3SCy Schubert 	}
502c1d255d3SCy Schubert 
5034b72b91aSCy Schubert 	secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
5044b72b91aSCy Schubert 					     wpabuf_len(peer_pub));
5054b72b91aSCy Schubert 	if (!secret_buf) {
5064b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
507c1d255d3SCy Schubert 		goto fail;
508c1d255d3SCy Schubert 	}
509c1d255d3SCy Schubert 
5104b72b91aSCy Schubert 	if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
5114b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
512c1d255d3SCy Schubert 		goto fail;
513c1d255d3SCy Schubert 	}
514c1d255d3SCy Schubert 
5154b72b91aSCy Schubert 	*secret_len = wpabuf_len(secret_buf);
5164b72b91aSCy Schubert 	os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
517c1d255d3SCy Schubert 	ret = 0;
518c1d255d3SCy Schubert 
519c1d255d3SCy Schubert fail:
5204b72b91aSCy Schubert 	wpabuf_clear_free(secret_buf);
5214b72b91aSCy Schubert 	wpabuf_free(peer_pub);
5224b72b91aSCy Schubert 	crypto_ecdh_deinit(ecdh);
523c1d255d3SCy Schubert 	return ret;
524c1d255d3SCy Schubert }
525c1d255d3SCy Schubert 
526c1d255d3SCy Schubert 
527c1d255d3SCy Schubert int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
528c1d255d3SCy Schubert 		       const u8 *data, size_t data_len)
529c1d255d3SCy Schubert {
530c1d255d3SCy Schubert 	const u8 *addr[2];
531c1d255d3SCy Schubert 	size_t len[2];
532c1d255d3SCy Schubert 
533c1d255d3SCy Schubert 	addr[0] = data;
534c1d255d3SCy Schubert 	len[0] = data_len;
535c1d255d3SCy Schubert 	if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
536c1d255d3SCy Schubert 		return -1;
537c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
538c1d255d3SCy Schubert 		    bi->pubkey_hash, SHA256_MAC_LEN);
539c1d255d3SCy Schubert 
540c1d255d3SCy Schubert 	addr[0] = (const u8 *) "chirp";
541c1d255d3SCy Schubert 	len[0] = 5;
542c1d255d3SCy Schubert 	addr[1] = data;
543c1d255d3SCy Schubert 	len[1] = data_len;
544c1d255d3SCy Schubert 	if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
545c1d255d3SCy Schubert 		return -1;
546c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
547c1d255d3SCy Schubert 		    bi->pubkey_hash_chirp, SHA256_MAC_LEN);
548c1d255d3SCy Schubert 
549c1d255d3SCy Schubert 	return 0;
550c1d255d3SCy Schubert }
551c1d255d3SCy Schubert 
552c1d255d3SCy Schubert 
553c1d255d3SCy Schubert int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
554c1d255d3SCy Schubert 			       const u8 *data, size_t data_len)
555c1d255d3SCy Schubert {
5564b72b91aSCy Schubert 	struct crypto_ec_key *key;
557c1d255d3SCy Schubert 
558c1d255d3SCy Schubert 	if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
559c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
560c1d255d3SCy Schubert 		return -1;
561c1d255d3SCy Schubert 	}
562c1d255d3SCy Schubert 
5634b72b91aSCy Schubert 	key = crypto_ec_key_parse_pub(data, data_len);
5644b72b91aSCy Schubert 	if (!key) {
565c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
566c1d255d3SCy Schubert 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
567c1d255d3SCy Schubert 		return -1;
568c1d255d3SCy Schubert 	}
569c1d255d3SCy Schubert 
5704b72b91aSCy Schubert 	bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
571db0ac6deSCy Schubert 	if (!bi->curve) {
572db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
5734b72b91aSCy Schubert 			   "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
5744b72b91aSCy Schubert 			   crypto_ec_key_group(key));
575db0ac6deSCy Schubert 		goto fail;
576db0ac6deSCy Schubert 	}
577db0ac6deSCy Schubert 
5784b72b91aSCy Schubert 	bi->pubkey = key;
579c1d255d3SCy Schubert 	return 0;
580c1d255d3SCy Schubert fail:
5814b72b91aSCy Schubert 	crypto_ec_key_deinit(key);
582c1d255d3SCy Schubert 	return -1;
583c1d255d3SCy Schubert }
584c1d255d3SCy Schubert 
585c1d255d3SCy Schubert 
586c1d255d3SCy Schubert static struct wpabuf *
587c1d255d3SCy Schubert dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
588c1d255d3SCy Schubert 		       const u8 *prot_hdr, u16 prot_hdr_len,
5894b72b91aSCy Schubert 		       int *hash_func)
590c1d255d3SCy Schubert {
591c1d255d3SCy Schubert 	struct json_token *root, *token;
592c1d255d3SCy Schubert 	struct wpabuf *kid = NULL;
593c1d255d3SCy Schubert 
594c1d255d3SCy Schubert 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
595c1d255d3SCy Schubert 	if (!root) {
596c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
597c1d255d3SCy Schubert 			   "DPP: JSON parsing failed for JWS Protected Header");
598c1d255d3SCy Schubert 		goto fail;
599c1d255d3SCy Schubert 	}
600c1d255d3SCy Schubert 
601c1d255d3SCy Schubert 	if (root->type != JSON_OBJECT) {
602c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
603c1d255d3SCy Schubert 			   "DPP: JWS Protected Header root is not an object");
604c1d255d3SCy Schubert 		goto fail;
605c1d255d3SCy Schubert 	}
606c1d255d3SCy Schubert 
607c1d255d3SCy Schubert 	token = json_get_member(root, "typ");
608c1d255d3SCy Schubert 	if (!token || token->type != JSON_STRING) {
609c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
610c1d255d3SCy Schubert 		goto fail;
611c1d255d3SCy Schubert 	}
612c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
613c1d255d3SCy Schubert 		   token->string);
614c1d255d3SCy Schubert 	if (os_strcmp(token->string, "dppCon") != 0) {
615c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
616c1d255d3SCy Schubert 			   "DPP: Unsupported JWS Protected Header typ=%s",
617c1d255d3SCy Schubert 			   token->string);
618c1d255d3SCy Schubert 		goto fail;
619c1d255d3SCy Schubert 	}
620c1d255d3SCy Schubert 
621c1d255d3SCy Schubert 	token = json_get_member(root, "alg");
622c1d255d3SCy Schubert 	if (!token || token->type != JSON_STRING) {
623c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
624c1d255d3SCy Schubert 		goto fail;
625c1d255d3SCy Schubert 	}
626c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
627c1d255d3SCy Schubert 		   token->string);
628c1d255d3SCy Schubert 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
629c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
630c1d255d3SCy Schubert 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
631c1d255d3SCy Schubert 			   token->string, curve->jws_alg);
632c1d255d3SCy Schubert 		goto fail;
633c1d255d3SCy Schubert 	}
634c1d255d3SCy Schubert 	if (os_strcmp(token->string, "ES256") == 0 ||
6354b72b91aSCy Schubert 	    os_strcmp(token->string, "BS256") == 0) {
6364b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA256;
6374b72b91aSCy Schubert 	} else if (os_strcmp(token->string, "ES384") == 0 ||
6384b72b91aSCy Schubert 		   os_strcmp(token->string, "BS384") == 0) {
6394b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA384;
6404b72b91aSCy Schubert 	} else if (os_strcmp(token->string, "ES512") == 0 ||
6414b72b91aSCy Schubert 		   os_strcmp(token->string, "BS512") == 0) {
6424b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA512;
6434b72b91aSCy Schubert 	} else {
6444b72b91aSCy Schubert 		*hash_func = -1;
645c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
646c1d255d3SCy Schubert 			   "DPP: Unsupported JWS Protected Header alg=%s",
647c1d255d3SCy Schubert 			   token->string);
648c1d255d3SCy Schubert 		goto fail;
649c1d255d3SCy Schubert 	}
650c1d255d3SCy Schubert 
651c1d255d3SCy Schubert 	kid = json_get_member_base64url(root, "kid");
652c1d255d3SCy Schubert 	if (!kid) {
653c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
654c1d255d3SCy Schubert 		goto fail;
655c1d255d3SCy Schubert 	}
656c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
657c1d255d3SCy Schubert 			kid);
658c1d255d3SCy Schubert 
659c1d255d3SCy Schubert fail:
660c1d255d3SCy Schubert 	json_free(root);
661c1d255d3SCy Schubert 	return kid;
662c1d255d3SCy Schubert }
663c1d255d3SCy Schubert 
664c1d255d3SCy Schubert 
6654b72b91aSCy Schubert static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
6664b72b91aSCy Schubert 				  struct wpabuf *r_hash)
667c1d255d3SCy Schubert {
668c1d255d3SCy Schubert 	struct wpabuf *uncomp;
669c1d255d3SCy Schubert 	int res;
670c1d255d3SCy Schubert 	u8 hash[SHA256_MAC_LEN];
671c1d255d3SCy Schubert 	const u8 *addr[1];
672c1d255d3SCy Schubert 	size_t len[1];
673c1d255d3SCy Schubert 
674c1d255d3SCy Schubert 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
675c1d255d3SCy Schubert 		return -1;
6764b72b91aSCy Schubert 	uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
677c1d255d3SCy Schubert 	if (!uncomp)
678c1d255d3SCy Schubert 		return -1;
679c1d255d3SCy Schubert 	addr[0] = wpabuf_head(uncomp);
680c1d255d3SCy Schubert 	len[0] = wpabuf_len(uncomp);
681c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
682c1d255d3SCy Schubert 		    addr[0], len[0]);
683c1d255d3SCy Schubert 	res = sha256_vector(1, addr, len, hash);
684c1d255d3SCy Schubert 	wpabuf_free(uncomp);
685c1d255d3SCy Schubert 	if (res < 0)
686c1d255d3SCy Schubert 		return -1;
687c1d255d3SCy Schubert 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
688c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
689c1d255d3SCy Schubert 			   "DPP: Received hash value does not match calculated public key hash value");
690c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
691c1d255d3SCy Schubert 			    hash, SHA256_MAC_LEN);
692c1d255d3SCy Schubert 		return -1;
693c1d255d3SCy Schubert 	}
694c1d255d3SCy Schubert 	return 0;
695c1d255d3SCy Schubert }
696c1d255d3SCy Schubert 
697c1d255d3SCy Schubert 
698c1d255d3SCy Schubert enum dpp_status_error
699c1d255d3SCy Schubert dpp_process_signed_connector(struct dpp_signed_connector_info *info,
7004b72b91aSCy Schubert 			     struct crypto_ec_key *csign_pub,
7014b72b91aSCy Schubert 			     const char *connector)
702c1d255d3SCy Schubert {
703c1d255d3SCy Schubert 	enum dpp_status_error ret = 255;
704c1d255d3SCy Schubert 	const char *pos, *end, *signed_start, *signed_end;
705c1d255d3SCy Schubert 	struct wpabuf *kid = NULL;
706c1d255d3SCy Schubert 	unsigned char *prot_hdr = NULL, *signature = NULL;
7074b72b91aSCy Schubert 	size_t prot_hdr_len = 0, signature_len = 0, signed_len;
7084b72b91aSCy Schubert 	int res, hash_func = -1;
709c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
7104b72b91aSCy Schubert 	u8 *hash = NULL;
711c1d255d3SCy Schubert 
7124b72b91aSCy Schubert 	curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
713c1d255d3SCy Schubert 	if (!curve)
714c1d255d3SCy Schubert 		goto fail;
715c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
716c1d255d3SCy Schubert 	os_memset(info, 0, sizeof(*info));
717c1d255d3SCy Schubert 
718c1d255d3SCy Schubert 	signed_start = pos = connector;
719c1d255d3SCy Schubert 	end = os_strchr(pos, '.');
720c1d255d3SCy Schubert 	if (!end) {
721c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
722c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
723c1d255d3SCy Schubert 		goto fail;
724c1d255d3SCy Schubert 	}
725c1d255d3SCy Schubert 	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
726c1d255d3SCy Schubert 	if (!prot_hdr) {
727c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
728c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
729c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
730c1d255d3SCy Schubert 		goto fail;
731c1d255d3SCy Schubert 	}
732c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG,
733c1d255d3SCy Schubert 			  "DPP: signedConnector - JWS Protected Header",
734c1d255d3SCy Schubert 			  prot_hdr, prot_hdr_len);
7354b72b91aSCy Schubert 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
736c1d255d3SCy Schubert 	if (!kid) {
737c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
738c1d255d3SCy Schubert 		goto fail;
739c1d255d3SCy Schubert 	}
740c1d255d3SCy Schubert 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
741c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
742c1d255d3SCy Schubert 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
743c1d255d3SCy Schubert 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
744c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
745c1d255d3SCy Schubert 		goto fail;
746c1d255d3SCy Schubert 	}
747c1d255d3SCy Schubert 
748c1d255d3SCy Schubert 	pos = end + 1;
749c1d255d3SCy Schubert 	end = os_strchr(pos, '.');
750c1d255d3SCy Schubert 	if (!end) {
751c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
752c1d255d3SCy Schubert 			   "DPP: Missing dot(2) in signedConnector");
753c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
754c1d255d3SCy Schubert 		goto fail;
755c1d255d3SCy Schubert 	}
756c1d255d3SCy Schubert 	signed_end = end - 1;
757c1d255d3SCy Schubert 	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
758c1d255d3SCy Schubert 	if (!info->payload) {
759c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
760c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
761c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
762c1d255d3SCy Schubert 		goto fail;
763c1d255d3SCy Schubert 	}
764c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG,
765c1d255d3SCy Schubert 			  "DPP: signedConnector - JWS Payload",
766c1d255d3SCy Schubert 			  info->payload, info->payload_len);
767c1d255d3SCy Schubert 	pos = end + 1;
768c1d255d3SCy Schubert 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
769c1d255d3SCy Schubert 	if (!signature) {
770c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
771c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector signature");
772c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
773c1d255d3SCy Schubert 		goto fail;
774c1d255d3SCy Schubert 		}
775c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
776c1d255d3SCy Schubert 		    signature, signature_len);
777c1d255d3SCy Schubert 
778c1d255d3SCy Schubert 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
779c1d255d3SCy Schubert 		ret = DPP_STATUS_NO_MATCH;
780c1d255d3SCy Schubert 		goto fail;
781c1d255d3SCy Schubert 	}
782c1d255d3SCy Schubert 
783c1d255d3SCy Schubert 	if (signature_len & 0x01) {
784c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
785c1d255d3SCy Schubert 			   "DPP: Unexpected signedConnector signature length (%d)",
786c1d255d3SCy Schubert 			   (int) signature_len);
787c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
788c1d255d3SCy Schubert 		goto fail;
789c1d255d3SCy Schubert 	}
790c1d255d3SCy Schubert 
7914b72b91aSCy Schubert 	hash = os_malloc(curve->hash_len);
7924b72b91aSCy Schubert 	if (!hash)
793c1d255d3SCy Schubert 		goto fail;
794c1d255d3SCy Schubert 
7954b72b91aSCy Schubert 	signed_len = signed_end - signed_start + 1;
7964b72b91aSCy Schubert 	if (hash_func == CRYPTO_HASH_ALG_SHA256)
7974b72b91aSCy Schubert 		res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
7984b72b91aSCy Schubert 				    hash);
7994b72b91aSCy Schubert 	else if (hash_func == CRYPTO_HASH_ALG_SHA384)
8004b72b91aSCy Schubert 		res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
8014b72b91aSCy Schubert 				    hash);
8024b72b91aSCy Schubert 	else if (hash_func == CRYPTO_HASH_ALG_SHA512)
8034b72b91aSCy Schubert 		res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
8044b72b91aSCy Schubert 				    hash);
8054b72b91aSCy Schubert 	else
806c1d255d3SCy Schubert 		goto fail;
8074b72b91aSCy Schubert 
8084b72b91aSCy Schubert 	if (res)
809c1d255d3SCy Schubert 		goto fail;
8104b72b91aSCy Schubert 
8114b72b91aSCy Schubert 	res = crypto_ec_key_verify_signature_r_s(csign_pub,
8124b72b91aSCy Schubert 						 hash, curve->hash_len,
8134b72b91aSCy Schubert 						 signature, signature_len / 2,
8144b72b91aSCy Schubert 						 signature + signature_len / 2,
8154b72b91aSCy Schubert 						 signature_len / 2);
816c1d255d3SCy Schubert 	if (res != 1) {
817c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
8184b72b91aSCy Schubert 			   "DPP: signedConnector signature check failed (res=%d)",
8194b72b91aSCy Schubert 			   res);
820c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
821c1d255d3SCy Schubert 		goto fail;
822c1d255d3SCy Schubert 	}
823c1d255d3SCy Schubert 
824c1d255d3SCy Schubert 	ret = DPP_STATUS_OK;
825c1d255d3SCy Schubert fail:
8264b72b91aSCy Schubert 	os_free(hash);
827c1d255d3SCy Schubert 	os_free(prot_hdr);
828c1d255d3SCy Schubert 	wpabuf_free(kid);
829c1d255d3SCy Schubert 	os_free(signature);
830c1d255d3SCy Schubert 	return ret;
831c1d255d3SCy Schubert }
832c1d255d3SCy Schubert 
833c1d255d3SCy Schubert 
834c1d255d3SCy Schubert enum dpp_status_error
835c1d255d3SCy Schubert dpp_check_signed_connector(struct dpp_signed_connector_info *info,
836c1d255d3SCy Schubert 			   const u8 *csign_key, size_t csign_key_len,
837c1d255d3SCy Schubert 			   const u8 *peer_connector, size_t peer_connector_len)
838c1d255d3SCy Schubert {
8394b72b91aSCy Schubert 	struct crypto_ec_key *csign;
840c1d255d3SCy Schubert 	char *signed_connector = NULL;
841c1d255d3SCy Schubert 	enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
842c1d255d3SCy Schubert 
8434b72b91aSCy Schubert 	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
844c1d255d3SCy Schubert 	if (!csign) {
845c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR,
846c1d255d3SCy Schubert 			   "DPP: Failed to parse local C-sign-key information");
847c1d255d3SCy Schubert 		goto fail;
848c1d255d3SCy Schubert 	}
849c1d255d3SCy Schubert 
850c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
851c1d255d3SCy Schubert 			  peer_connector, peer_connector_len);
852c1d255d3SCy Schubert 	signed_connector = os_malloc(peer_connector_len + 1);
853c1d255d3SCy Schubert 	if (!signed_connector)
854c1d255d3SCy Schubert 		goto fail;
855c1d255d3SCy Schubert 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
856c1d255d3SCy Schubert 	signed_connector[peer_connector_len] = '\0';
857c1d255d3SCy Schubert 	res = dpp_process_signed_connector(info, csign, signed_connector);
858c1d255d3SCy Schubert fail:
859c1d255d3SCy Schubert 	os_free(signed_connector);
8604b72b91aSCy Schubert 	crypto_ec_key_deinit(csign);
861c1d255d3SCy Schubert 	return res;
862c1d255d3SCy Schubert }
863c1d255d3SCy Schubert 
864c1d255d3SCy Schubert 
865c1d255d3SCy Schubert int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
866c1d255d3SCy Schubert {
867c1d255d3SCy Schubert 	struct wpabuf *pix, *prx, *bix, *brx;
868c1d255d3SCy Schubert 	const u8 *addr[7];
869c1d255d3SCy Schubert 	size_t len[7];
870c1d255d3SCy Schubert 	size_t i, num_elem = 0;
871c1d255d3SCy Schubert 	size_t nonce_len;
872c1d255d3SCy Schubert 	u8 zero = 0;
873c1d255d3SCy Schubert 	int res = -1;
874c1d255d3SCy Schubert 
875c1d255d3SCy Schubert 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
876c1d255d3SCy Schubert 	nonce_len = auth->curve->nonce_len;
877c1d255d3SCy Schubert 
878c1d255d3SCy Schubert 	if (auth->initiator) {
8794b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
8804b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
8814b72b91aSCy Schubert 						     0);
882c1d255d3SCy Schubert 		if (auth->own_bi)
8834b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
8844b72b91aSCy Schubert 				auth->own_bi->pubkey, 0);
885c1d255d3SCy Schubert 		else
886c1d255d3SCy Schubert 			bix = NULL;
8874b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
888c1d255d3SCy Schubert 	} else {
8894b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
8904b72b91aSCy Schubert 						     0);
8914b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
892c1d255d3SCy Schubert 		if (auth->peer_bi)
8934b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
8944b72b91aSCy Schubert 				auth->peer_bi->pubkey, 0);
895c1d255d3SCy Schubert 		else
896c1d255d3SCy Schubert 			bix = NULL;
8974b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
898c1d255d3SCy Schubert 	}
899c1d255d3SCy Schubert 	if (!pix || !prx || !brx)
900c1d255d3SCy Schubert 		goto fail;
901c1d255d3SCy Schubert 
902c1d255d3SCy Schubert 	addr[num_elem] = auth->i_nonce;
903c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
904c1d255d3SCy Schubert 	num_elem++;
905c1d255d3SCy Schubert 
906c1d255d3SCy Schubert 	addr[num_elem] = auth->r_nonce;
907c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
908c1d255d3SCy Schubert 	num_elem++;
909c1d255d3SCy Schubert 
910c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(pix);
911c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(pix) / 2;
912c1d255d3SCy Schubert 	num_elem++;
913c1d255d3SCy Schubert 
914c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(prx);
915c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(prx) / 2;
916c1d255d3SCy Schubert 	num_elem++;
917c1d255d3SCy Schubert 
918c1d255d3SCy Schubert 	if (bix) {
919c1d255d3SCy Schubert 		addr[num_elem] = wpabuf_head(bix);
920c1d255d3SCy Schubert 		len[num_elem] = wpabuf_len(bix) / 2;
921c1d255d3SCy Schubert 		num_elem++;
922c1d255d3SCy Schubert 	}
923c1d255d3SCy Schubert 
924c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(brx);
925c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(brx) / 2;
926c1d255d3SCy Schubert 	num_elem++;
927c1d255d3SCy Schubert 
928c1d255d3SCy Schubert 	addr[num_elem] = &zero;
929c1d255d3SCy Schubert 	len[num_elem] = 1;
930c1d255d3SCy Schubert 	num_elem++;
931c1d255d3SCy Schubert 
932c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
933c1d255d3SCy Schubert 	for (i = 0; i < num_elem; i++)
934c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
935c1d255d3SCy Schubert 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
936c1d255d3SCy Schubert 	if (res == 0)
937c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
938c1d255d3SCy Schubert 			    auth->curve->hash_len);
939c1d255d3SCy Schubert fail:
940c1d255d3SCy Schubert 	wpabuf_free(pix);
941c1d255d3SCy Schubert 	wpabuf_free(prx);
942c1d255d3SCy Schubert 	wpabuf_free(bix);
943c1d255d3SCy Schubert 	wpabuf_free(brx);
944c1d255d3SCy Schubert 	return res;
945c1d255d3SCy Schubert }
946c1d255d3SCy Schubert 
947c1d255d3SCy Schubert 
948c1d255d3SCy Schubert int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
949c1d255d3SCy Schubert {
950c1d255d3SCy Schubert 	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
951c1d255d3SCy Schubert 	const u8 *addr[7];
952c1d255d3SCy Schubert 	size_t len[7];
953c1d255d3SCy Schubert 	size_t i, num_elem = 0;
954c1d255d3SCy Schubert 	size_t nonce_len;
955c1d255d3SCy Schubert 	u8 one = 1;
956c1d255d3SCy Schubert 	int res = -1;
957c1d255d3SCy Schubert 
958c1d255d3SCy Schubert 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
959c1d255d3SCy Schubert 	nonce_len = auth->curve->nonce_len;
960c1d255d3SCy Schubert 
961c1d255d3SCy Schubert 	if (auth->initiator) {
9624b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
9634b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9644b72b91aSCy Schubert 						     0);
965c1d255d3SCy Schubert 		if (auth->own_bi)
9664b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
9674b72b91aSCy Schubert 				auth->own_bi->pubkey, 0);
968c1d255d3SCy Schubert 		else
969c1d255d3SCy Schubert 			bix = NULL;
970c1d255d3SCy Schubert 		if (!auth->peer_bi)
971c1d255d3SCy Schubert 			goto fail;
9724b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
973c1d255d3SCy Schubert 	} else {
9744b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9754b72b91aSCy Schubert 						     0);
9764b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
977c1d255d3SCy Schubert 		if (auth->peer_bi)
9784b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
9794b72b91aSCy Schubert 				auth->peer_bi->pubkey, 0);
980c1d255d3SCy Schubert 		else
981c1d255d3SCy Schubert 			bix = NULL;
982c1d255d3SCy Schubert 		if (!auth->own_bi)
983c1d255d3SCy Schubert 			goto fail;
9844b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
985c1d255d3SCy Schubert 	}
986c1d255d3SCy Schubert 	if (!pix || !prx || !brx)
987c1d255d3SCy Schubert 		goto fail;
988c1d255d3SCy Schubert 
989c1d255d3SCy Schubert 	addr[num_elem] = auth->r_nonce;
990c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
991c1d255d3SCy Schubert 	num_elem++;
992c1d255d3SCy Schubert 
993c1d255d3SCy Schubert 	addr[num_elem] = auth->i_nonce;
994c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
995c1d255d3SCy Schubert 	num_elem++;
996c1d255d3SCy Schubert 
997c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(prx);
998c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(prx) / 2;
999c1d255d3SCy Schubert 	num_elem++;
1000c1d255d3SCy Schubert 
1001c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(pix);
1002c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(pix) / 2;
1003c1d255d3SCy Schubert 	num_elem++;
1004c1d255d3SCy Schubert 
1005c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(brx);
1006c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(brx) / 2;
1007c1d255d3SCy Schubert 	num_elem++;
1008c1d255d3SCy Schubert 
1009c1d255d3SCy Schubert 	if (bix) {
1010c1d255d3SCy Schubert 		addr[num_elem] = wpabuf_head(bix);
1011c1d255d3SCy Schubert 		len[num_elem] = wpabuf_len(bix) / 2;
1012c1d255d3SCy Schubert 		num_elem++;
1013c1d255d3SCy Schubert 	}
1014c1d255d3SCy Schubert 
1015c1d255d3SCy Schubert 	addr[num_elem] = &one;
1016c1d255d3SCy Schubert 	len[num_elem] = 1;
1017c1d255d3SCy Schubert 	num_elem++;
1018c1d255d3SCy Schubert 
1019c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1020c1d255d3SCy Schubert 	for (i = 0; i < num_elem; i++)
1021c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1022c1d255d3SCy Schubert 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1023c1d255d3SCy Schubert 	if (res == 0)
1024c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1025c1d255d3SCy Schubert 			    auth->curve->hash_len);
1026c1d255d3SCy Schubert fail:
1027c1d255d3SCy Schubert 	wpabuf_free(pix);
1028c1d255d3SCy Schubert 	wpabuf_free(prx);
1029c1d255d3SCy Schubert 	wpabuf_free(bix);
1030c1d255d3SCy Schubert 	wpabuf_free(brx);
1031c1d255d3SCy Schubert 	return res;
1032c1d255d3SCy Schubert }
1033c1d255d3SCy Schubert 
1034c1d255d3SCy Schubert 
1035c1d255d3SCy Schubert int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1036c1d255d3SCy Schubert {
10374b72b91aSCy Schubert 	struct crypto_ec *ec;
10384b72b91aSCy Schubert 	struct crypto_ec_point *L = NULL;
10394b72b91aSCy Schubert 	const struct crypto_ec_point *BI;
10404b72b91aSCy Schubert 	const struct crypto_bignum *bR, *pR, *q;
10414b72b91aSCy Schubert 	struct crypto_bignum *sum = NULL, *lx = NULL;
1042c1d255d3SCy Schubert 	int ret = -1;
1043c1d255d3SCy Schubert 
1044c1d255d3SCy Schubert 	/* L = ((bR + pR) modulo q) * BI */
1045c1d255d3SCy Schubert 
10464b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
10474b72b91aSCy Schubert 	if (!ec)
1048c1d255d3SCy Schubert 		goto fail;
1049c1d255d3SCy Schubert 
10504b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
10514b72b91aSCy Schubert 	BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
10524b72b91aSCy Schubert 	bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
10534b72b91aSCy Schubert 	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
10544b72b91aSCy Schubert 	sum = crypto_bignum_init();
10554b72b91aSCy Schubert 	L = crypto_ec_point_init(ec);
10564b72b91aSCy Schubert 	lx = crypto_bignum_init();
10574b72b91aSCy Schubert 	if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
10584b72b91aSCy Schubert 	    crypto_bignum_addmod(bR, pR, q, sum) ||
10594b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, BI, sum, L) ||
10604b72b91aSCy Schubert 	    crypto_ec_point_x(ec, L, lx) ||
10614b72b91aSCy Schubert 	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
10624b72b91aSCy Schubert 				 auth->secret_len) < 0)
1063c1d255d3SCy Schubert 		goto fail;
1064c1d255d3SCy Schubert 
1065c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1066c1d255d3SCy Schubert 	auth->Lx_len = auth->secret_len;
1067c1d255d3SCy Schubert 	ret = 0;
1068c1d255d3SCy Schubert fail:
10694b72b91aSCy Schubert 	crypto_bignum_deinit(lx, 1);
10704b72b91aSCy Schubert 	crypto_bignum_deinit(sum, 1);
10714b72b91aSCy Schubert 	crypto_ec_point_deinit(L, 1);
10724b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1073c1d255d3SCy Schubert 	return ret;
1074c1d255d3SCy Schubert }
1075c1d255d3SCy Schubert 
1076c1d255d3SCy Schubert 
1077c1d255d3SCy Schubert int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1078c1d255d3SCy Schubert {
10794b72b91aSCy Schubert 	struct crypto_ec *ec;
10804b72b91aSCy Schubert 	struct crypto_ec_point *L = NULL, *sum = NULL;
10814b72b91aSCy Schubert 	const struct crypto_ec_point *BR, *PR;
10824b72b91aSCy Schubert 	const struct crypto_bignum *bI;
10834b72b91aSCy Schubert 	struct crypto_bignum *lx = NULL;
1084c1d255d3SCy Schubert 	int ret = -1;
1085c1d255d3SCy Schubert 
1086c1d255d3SCy Schubert 	/* L = bI * (BR + PR) */
1087c1d255d3SCy Schubert 
10884b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
10894b72b91aSCy Schubert 	if (!ec)
1090c1d255d3SCy Schubert 		goto fail;
1091c1d255d3SCy Schubert 
10924b72b91aSCy Schubert 	BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
10934b72b91aSCy Schubert 	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
10944b72b91aSCy Schubert 	bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
10954b72b91aSCy Schubert 	sum = crypto_ec_point_init(ec);
10964b72b91aSCy Schubert 	L = crypto_ec_point_init(ec);
10974b72b91aSCy Schubert 	lx = crypto_bignum_init();
10984b72b91aSCy Schubert 	if (!BR || !PR || !bI || !sum || !L || !lx ||
10994b72b91aSCy Schubert 	    crypto_ec_point_add(ec, BR, PR, sum) ||
11004b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, sum, bI, L) ||
11014b72b91aSCy Schubert 	    crypto_ec_point_x(ec, L, lx) ||
11024b72b91aSCy Schubert 	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
11034b72b91aSCy Schubert 				 auth->secret_len) < 0)
1104db0ac6deSCy Schubert 		goto fail;
1105db0ac6deSCy Schubert 
1106c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1107c1d255d3SCy Schubert 	auth->Lx_len = auth->secret_len;
1108c1d255d3SCy Schubert 	ret = 0;
1109c1d255d3SCy Schubert fail:
11104b72b91aSCy Schubert 	crypto_bignum_deinit(lx, 1);
11114b72b91aSCy Schubert 	crypto_ec_point_deinit(sum, 1);
11124b72b91aSCy Schubert 	crypto_ec_point_deinit(L, 1);
11134b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1114c1d255d3SCy Schubert 	return ret;
1115c1d255d3SCy Schubert }
1116c1d255d3SCy Schubert 
1117c1d255d3SCy Schubert 
1118c1d255d3SCy Schubert int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1119c1d255d3SCy Schubert {
1120c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1121c1d255d3SCy Schubert 	const char *info = "DPP PMK";
1122c1d255d3SCy Schubert 	int res;
1123c1d255d3SCy Schubert 
1124c1d255d3SCy Schubert 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
1125c1d255d3SCy Schubert 
1126c1d255d3SCy Schubert 	/* HKDF-Extract(<>, N.x) */
1127c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
1128c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1129c1d255d3SCy Schubert 		return -1;
1130c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1131c1d255d3SCy Schubert 			prk, hash_len);
1132c1d255d3SCy Schubert 
1133c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
1134c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1135c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
1136c1d255d3SCy Schubert 	if (res < 0)
1137c1d255d3SCy Schubert 		return -1;
1138c1d255d3SCy Schubert 
1139c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1140c1d255d3SCy Schubert 			pmk, hash_len);
1141c1d255d3SCy Schubert 	return 0;
1142c1d255d3SCy Schubert }
1143c1d255d3SCy Schubert 
1144c1d255d3SCy Schubert 
1145c1d255d3SCy Schubert int dpp_derive_pmkid(const struct dpp_curve_params *curve,
11464b72b91aSCy Schubert 		     struct crypto_ec_key *own_key,
11474b72b91aSCy Schubert 		     struct crypto_ec_key *peer_key, u8 *pmkid)
1148c1d255d3SCy Schubert {
1149c1d255d3SCy Schubert 	struct wpabuf *nkx, *pkx;
1150c1d255d3SCy Schubert 	int ret = -1, res;
1151c1d255d3SCy Schubert 	const u8 *addr[2];
1152c1d255d3SCy Schubert 	size_t len[2];
1153c1d255d3SCy Schubert 	u8 hash[SHA256_MAC_LEN];
1154c1d255d3SCy Schubert 
1155c1d255d3SCy Schubert 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
11564b72b91aSCy Schubert 	nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
11574b72b91aSCy Schubert 	pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
1158c1d255d3SCy Schubert 	if (!nkx || !pkx)
1159c1d255d3SCy Schubert 		goto fail;
1160c1d255d3SCy Schubert 	addr[0] = wpabuf_head(nkx);
1161c1d255d3SCy Schubert 	len[0] = wpabuf_len(nkx) / 2;
1162c1d255d3SCy Schubert 	addr[1] = wpabuf_head(pkx);
1163c1d255d3SCy Schubert 	len[1] = wpabuf_len(pkx) / 2;
1164c1d255d3SCy Schubert 	if (len[0] != len[1])
1165c1d255d3SCy Schubert 		goto fail;
1166c1d255d3SCy Schubert 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1167c1d255d3SCy Schubert 		addr[0] = wpabuf_head(pkx);
1168c1d255d3SCy Schubert 		addr[1] = wpabuf_head(nkx);
1169c1d255d3SCy Schubert 	}
1170c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1171c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1172c1d255d3SCy Schubert 	res = sha256_vector(2, addr, len, hash);
1173c1d255d3SCy Schubert 	if (res < 0)
1174c1d255d3SCy Schubert 		goto fail;
1175c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1176c1d255d3SCy Schubert 	os_memcpy(pmkid, hash, PMKID_LEN);
1177c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1178c1d255d3SCy Schubert 	ret = 0;
1179c1d255d3SCy Schubert fail:
1180c1d255d3SCy Schubert 	wpabuf_free(nkx);
1181c1d255d3SCy Schubert 	wpabuf_free(pkx);
1182c1d255d3SCy Schubert 	return ret;
1183c1d255d3SCy Schubert }
1184c1d255d3SCy Schubert 
1185c1d255d3SCy Schubert 
1186c1d255d3SCy Schubert /* Role-specific elements for PKEX */
1187c1d255d3SCy Schubert 
1188c1d255d3SCy Schubert /* NIST P-256 */
1189c1d255d3SCy Schubert static const u8 pkex_init_x_p256[32] = {
1190c1d255d3SCy Schubert 	0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1191c1d255d3SCy Schubert 	0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1192c1d255d3SCy Schubert 	0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1193c1d255d3SCy Schubert 	0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1194c1d255d3SCy Schubert  };
1195c1d255d3SCy Schubert static const u8 pkex_init_y_p256[32] = {
1196c1d255d3SCy Schubert 	0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1197c1d255d3SCy Schubert 	0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1198c1d255d3SCy Schubert 	0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1199c1d255d3SCy Schubert 	0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1200c1d255d3SCy Schubert  };
1201c1d255d3SCy Schubert static const u8 pkex_resp_x_p256[32] = {
1202c1d255d3SCy Schubert 	0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1203c1d255d3SCy Schubert 	0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1204c1d255d3SCy Schubert 	0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1205c1d255d3SCy Schubert 	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1206c1d255d3SCy Schubert };
1207c1d255d3SCy Schubert static const u8 pkex_resp_y_p256[32] = {
1208c1d255d3SCy Schubert 	0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1209c1d255d3SCy Schubert 	0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1210c1d255d3SCy Schubert 	0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1211c1d255d3SCy Schubert 	0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1212c1d255d3SCy Schubert };
1213c1d255d3SCy Schubert 
1214c1d255d3SCy Schubert /* NIST P-384 */
1215c1d255d3SCy Schubert static const u8 pkex_init_x_p384[48] = {
1216c1d255d3SCy Schubert 	0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1217c1d255d3SCy Schubert 	0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1218c1d255d3SCy Schubert 	0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1219c1d255d3SCy Schubert 	0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1220c1d255d3SCy Schubert 	0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1221c1d255d3SCy Schubert 	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1222c1d255d3SCy Schubert };
1223c1d255d3SCy Schubert static const u8 pkex_init_y_p384[48] = {
1224c1d255d3SCy Schubert 	0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1225c1d255d3SCy Schubert 	0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1226c1d255d3SCy Schubert 	0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1227c1d255d3SCy Schubert 	0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1228c1d255d3SCy Schubert 	0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1229c1d255d3SCy Schubert 	0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1230c1d255d3SCy Schubert };
1231c1d255d3SCy Schubert static const u8 pkex_resp_x_p384[48] = {
1232c1d255d3SCy Schubert 	0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1233c1d255d3SCy Schubert 	0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1234c1d255d3SCy Schubert 	0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1235c1d255d3SCy Schubert 	0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1236c1d255d3SCy Schubert 	0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1237c1d255d3SCy Schubert 	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1238c1d255d3SCy Schubert };
1239c1d255d3SCy Schubert static const u8 pkex_resp_y_p384[48] = {
1240c1d255d3SCy Schubert 	0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1241c1d255d3SCy Schubert 	0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1242c1d255d3SCy Schubert 	0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1243c1d255d3SCy Schubert 	0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1244c1d255d3SCy Schubert 	0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1245c1d255d3SCy Schubert 	0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1246c1d255d3SCy Schubert };
1247c1d255d3SCy Schubert 
1248c1d255d3SCy Schubert /* NIST P-521 */
1249c1d255d3SCy Schubert static const u8 pkex_init_x_p521[66] = {
1250c1d255d3SCy Schubert 	0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1251c1d255d3SCy Schubert 	0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1252c1d255d3SCy Schubert 	0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1253c1d255d3SCy Schubert 	0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1254c1d255d3SCy Schubert 	0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1255c1d255d3SCy Schubert 	0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1256c1d255d3SCy Schubert 	0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1257c1d255d3SCy Schubert 	0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1258c1d255d3SCy Schubert 	0x97, 0x76
1259c1d255d3SCy Schubert };
1260c1d255d3SCy Schubert static const u8 pkex_init_y_p521[66] = {
1261c1d255d3SCy Schubert 	0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1262c1d255d3SCy Schubert 	0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1263c1d255d3SCy Schubert 	0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1264c1d255d3SCy Schubert 	0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1265c1d255d3SCy Schubert 	0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1266c1d255d3SCy Schubert 	0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1267c1d255d3SCy Schubert 	0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1268c1d255d3SCy Schubert 	0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1269c1d255d3SCy Schubert 	0x03, 0xa8
1270c1d255d3SCy Schubert };
1271c1d255d3SCy Schubert static const u8 pkex_resp_x_p521[66] = {
1272c1d255d3SCy Schubert 	0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1273c1d255d3SCy Schubert 	0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1274c1d255d3SCy Schubert 	0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1275c1d255d3SCy Schubert 	0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1276c1d255d3SCy Schubert 	0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1277c1d255d3SCy Schubert 	0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1278c1d255d3SCy Schubert 	0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1279c1d255d3SCy Schubert 	0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1280c1d255d3SCy Schubert 	0x84, 0xb4
1281c1d255d3SCy Schubert };
1282c1d255d3SCy Schubert static const u8 pkex_resp_y_p521[66] = {
1283c1d255d3SCy Schubert 	0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1284c1d255d3SCy Schubert 	0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1285c1d255d3SCy Schubert 	0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1286c1d255d3SCy Schubert 	0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1287c1d255d3SCy Schubert 	0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1288c1d255d3SCy Schubert 	0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1289c1d255d3SCy Schubert 	0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1290c1d255d3SCy Schubert 	0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1291c1d255d3SCy Schubert 	0xce, 0xe1
1292c1d255d3SCy Schubert };
1293c1d255d3SCy Schubert 
1294c1d255d3SCy Schubert /* Brainpool P-256r1 */
1295c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p256r1[32] = {
1296c1d255d3SCy Schubert 	0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1297c1d255d3SCy Schubert 	0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1298c1d255d3SCy Schubert 	0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1299c1d255d3SCy Schubert 	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1300c1d255d3SCy Schubert };
1301c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p256r1[32] = {
1302c1d255d3SCy Schubert 	0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1303c1d255d3SCy Schubert 	0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1304c1d255d3SCy Schubert 	0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1305c1d255d3SCy Schubert 	0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1306c1d255d3SCy Schubert };
1307c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p256r1[32] = {
1308c1d255d3SCy Schubert 	0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1309c1d255d3SCy Schubert 	0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1310c1d255d3SCy Schubert 	0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1311c1d255d3SCy Schubert 	0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1312c1d255d3SCy Schubert };
1313c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p256r1[32] = {
1314c1d255d3SCy Schubert 	0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1315c1d255d3SCy Schubert 	0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1316c1d255d3SCy Schubert 	0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1317c1d255d3SCy Schubert 	0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1318c1d255d3SCy Schubert };
1319c1d255d3SCy Schubert 
1320c1d255d3SCy Schubert /* Brainpool P-384r1 */
1321c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p384r1[48] = {
1322c1d255d3SCy Schubert 	0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1323c1d255d3SCy Schubert 	0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1324c1d255d3SCy Schubert 	0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1325c1d255d3SCy Schubert 	0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1326c1d255d3SCy Schubert 	0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1327c1d255d3SCy Schubert 	0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1328c1d255d3SCy Schubert };
1329c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p384r1[48] = {
1330c1d255d3SCy Schubert 	0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1331c1d255d3SCy Schubert 	0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1332c1d255d3SCy Schubert 	0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1333c1d255d3SCy Schubert 	0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1334c1d255d3SCy Schubert 	0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1335c1d255d3SCy Schubert 	0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1336c1d255d3SCy Schubert };
1337c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p384r1[48] = {
1338c1d255d3SCy Schubert 	0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1339c1d255d3SCy Schubert 	0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1340c1d255d3SCy Schubert 	0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1341c1d255d3SCy Schubert 	0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1342c1d255d3SCy Schubert 	0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1343c1d255d3SCy Schubert 	0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1344c1d255d3SCy Schubert };
1345c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p384r1[48] = {
1346c1d255d3SCy Schubert 	0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1347c1d255d3SCy Schubert 	0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1348c1d255d3SCy Schubert 	0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1349c1d255d3SCy Schubert 	0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1350c1d255d3SCy Schubert 	0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1351c1d255d3SCy Schubert 	0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1352c1d255d3SCy Schubert };
1353c1d255d3SCy Schubert 
1354c1d255d3SCy Schubert /* Brainpool P-512r1 */
1355c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p512r1[64] = {
1356c1d255d3SCy Schubert 	0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1357c1d255d3SCy Schubert 	0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1358c1d255d3SCy Schubert 	0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1359c1d255d3SCy Schubert 	0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1360c1d255d3SCy Schubert 	0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1361c1d255d3SCy Schubert 	0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1362c1d255d3SCy Schubert 	0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1363c1d255d3SCy Schubert 	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1364c1d255d3SCy Schubert };
1365c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p512r1[64] = {
1366c1d255d3SCy Schubert 	0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1367c1d255d3SCy Schubert 	0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1368c1d255d3SCy Schubert 	0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1369c1d255d3SCy Schubert 	0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1370c1d255d3SCy Schubert 	0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1371c1d255d3SCy Schubert 	0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1372c1d255d3SCy Schubert 	0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1373c1d255d3SCy Schubert 	0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1374c1d255d3SCy Schubert };
1375c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p512r1[64] = {
1376c1d255d3SCy Schubert 	0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1377c1d255d3SCy Schubert 	0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1378c1d255d3SCy Schubert 	0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1379c1d255d3SCy Schubert 	0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1380c1d255d3SCy Schubert 	0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1381c1d255d3SCy Schubert 	0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1382c1d255d3SCy Schubert 	0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1383c1d255d3SCy Schubert 	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1384c1d255d3SCy Schubert };
1385c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p512r1[64] = {
1386c1d255d3SCy Schubert 	0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1387c1d255d3SCy Schubert 	0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1388c1d255d3SCy Schubert 	0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1389c1d255d3SCy Schubert 	0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1390c1d255d3SCy Schubert 	0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1391c1d255d3SCy Schubert 	0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1392c1d255d3SCy Schubert 	0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1393c1d255d3SCy Schubert 	0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1394c1d255d3SCy Schubert };
1395c1d255d3SCy Schubert 
1396c1d255d3SCy Schubert 
13974b72b91aSCy Schubert static struct crypto_ec_key *
13984b72b91aSCy Schubert dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
1399c1d255d3SCy Schubert {
1400c1d255d3SCy Schubert 	const u8 *x, *y;
1401c1d255d3SCy Schubert 
1402c1d255d3SCy Schubert 	switch (curve->ike_group) {
1403c1d255d3SCy Schubert 	case 19:
1404c1d255d3SCy Schubert 		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1405c1d255d3SCy Schubert 		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1406c1d255d3SCy Schubert 		break;
1407c1d255d3SCy Schubert 	case 20:
1408c1d255d3SCy Schubert 		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1409c1d255d3SCy Schubert 		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1410c1d255d3SCy Schubert 		break;
1411c1d255d3SCy Schubert 	case 21:
1412c1d255d3SCy Schubert 		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1413c1d255d3SCy Schubert 		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1414c1d255d3SCy Schubert 		break;
1415c1d255d3SCy Schubert 	case 28:
1416c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1417c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1418c1d255d3SCy Schubert 		break;
1419c1d255d3SCy Schubert 	case 29:
1420c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1421c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1422c1d255d3SCy Schubert 		break;
1423c1d255d3SCy Schubert 	case 30:
1424c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1425c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1426c1d255d3SCy Schubert 		break;
1427c1d255d3SCy Schubert 	default:
1428c1d255d3SCy Schubert 		return NULL;
1429c1d255d3SCy Schubert 	}
1430c1d255d3SCy Schubert 
14314b72b91aSCy Schubert 	return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
1432c1d255d3SCy Schubert }
1433c1d255d3SCy Schubert 
1434c1d255d3SCy Schubert 
14354b72b91aSCy Schubert struct crypto_ec_point *
14364b72b91aSCy Schubert dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
14374b72b91aSCy Schubert 		   const char *code, const char *identifier,
14384b72b91aSCy Schubert 		   struct crypto_ec **ret_ec)
1439c1d255d3SCy Schubert {
1440c1d255d3SCy Schubert 	u8 hash[DPP_MAX_HASH_LEN];
1441c1d255d3SCy Schubert 	const u8 *addr[3];
1442c1d255d3SCy Schubert 	size_t len[3];
1443c1d255d3SCy Schubert 	unsigned int num_elem = 0;
14444b72b91aSCy Schubert 	struct crypto_ec_point *Qi = NULL;
14454b72b91aSCy Schubert 	struct crypto_ec_key *Pi_key = NULL;
14464b72b91aSCy Schubert 	const struct crypto_ec_point *Pi = NULL;
14474b72b91aSCy Schubert 	struct crypto_bignum *hash_bn = NULL;
14484b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1449c1d255d3SCy Schubert 
1450*32a95656SCy Schubert 	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
1451c1d255d3SCy Schubert 
1452*32a95656SCy Schubert 	if (mac_init) {
1453*32a95656SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
1454*32a95656SCy Schubert 			   MAC2STR(mac_init));
1455c1d255d3SCy Schubert 		addr[num_elem] = mac_init;
1456c1d255d3SCy Schubert 		len[num_elem] = ETH_ALEN;
1457c1d255d3SCy Schubert 		num_elem++;
1458*32a95656SCy Schubert 	}
1459c1d255d3SCy Schubert 	if (identifier) {
1460c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1461c1d255d3SCy Schubert 			   identifier);
1462c1d255d3SCy Schubert 		addr[num_elem] = (const u8 *) identifier;
1463c1d255d3SCy Schubert 		len[num_elem] = os_strlen(identifier);
1464c1d255d3SCy Schubert 		num_elem++;
1465c1d255d3SCy Schubert 	}
1466c1d255d3SCy Schubert 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1467c1d255d3SCy Schubert 	addr[num_elem] = (const u8 *) code;
1468c1d255d3SCy Schubert 	len[num_elem] = os_strlen(code);
1469c1d255d3SCy Schubert 	num_elem++;
1470c1d255d3SCy Schubert 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1471c1d255d3SCy Schubert 		goto fail;
1472c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1473*32a95656SCy Schubert 			"DPP: H([MAC-Initiator |] [identifier |] code)",
1474c1d255d3SCy Schubert 			hash, curve->hash_len);
14754b72b91aSCy Schubert 	Pi_key = dpp_pkex_get_role_elem(curve, 1);
14764b72b91aSCy Schubert 	if (!Pi_key)
1477c1d255d3SCy Schubert 		goto fail;
14784b72b91aSCy Schubert 	dpp_debug_print_key("DPP: Pi", Pi_key);
1479266f97b5SCy Schubert 
14804b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
14814b72b91aSCy Schubert 	if (!ec)
1482c1d255d3SCy Schubert 		goto fail;
14834b72b91aSCy Schubert 
14844b72b91aSCy Schubert 	Pi = crypto_ec_key_get_public_key(Pi_key);
14854b72b91aSCy Schubert 	Qi = crypto_ec_point_init(ec);
14864b72b91aSCy Schubert 	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
14874b72b91aSCy Schubert 	if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
1488db0ac6deSCy Schubert 		goto fail;
14894b72b91aSCy Schubert 
14904b72b91aSCy Schubert 	if (crypto_ec_point_is_at_infinity(ec, Qi)) {
1491c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1492c1d255d3SCy Schubert 		goto fail;
1493c1d255d3SCy Schubert 	}
14944b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
1495c1d255d3SCy Schubert out:
14964b72b91aSCy Schubert 	crypto_ec_key_deinit(Pi_key);
14974b72b91aSCy Schubert 	crypto_bignum_deinit(hash_bn, 1);
14984b72b91aSCy Schubert 	if (ret_ec && Qi)
14994b72b91aSCy Schubert 		*ret_ec = ec;
1500c1d255d3SCy Schubert 	else
15014b72b91aSCy Schubert 		crypto_ec_deinit(ec);
1502c1d255d3SCy Schubert 	return Qi;
1503c1d255d3SCy Schubert fail:
15044b72b91aSCy Schubert 	crypto_ec_point_deinit(Qi, 1);
1505c1d255d3SCy Schubert 	Qi = NULL;
1506c1d255d3SCy Schubert 	goto out;
1507c1d255d3SCy Schubert }
1508c1d255d3SCy Schubert 
1509c1d255d3SCy Schubert 
15104b72b91aSCy Schubert struct crypto_ec_point *
15114b72b91aSCy Schubert dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
15124b72b91aSCy Schubert 		   const char *code, const char *identifier,
15134b72b91aSCy Schubert 		   struct crypto_ec **ret_ec)
1514c1d255d3SCy Schubert {
1515c1d255d3SCy Schubert 	u8 hash[DPP_MAX_HASH_LEN];
1516c1d255d3SCy Schubert 	const u8 *addr[3];
1517c1d255d3SCy Schubert 	size_t len[3];
1518c1d255d3SCy Schubert 	unsigned int num_elem = 0;
15194b72b91aSCy Schubert 	struct crypto_ec_point *Qr = NULL;
15204b72b91aSCy Schubert 	struct crypto_ec_key *Pr_key = NULL;
15214b72b91aSCy Schubert 	const struct crypto_ec_point *Pr = NULL;
15224b72b91aSCy Schubert 	struct crypto_bignum *hash_bn = NULL;
15234b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1524c1d255d3SCy Schubert 
1525*32a95656SCy Schubert 	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
1526c1d255d3SCy Schubert 
1527*32a95656SCy Schubert 	if (mac_resp) {
1528*32a95656SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
1529*32a95656SCy Schubert 			   MAC2STR(mac_resp));
1530c1d255d3SCy Schubert 		addr[num_elem] = mac_resp;
1531c1d255d3SCy Schubert 		len[num_elem] = ETH_ALEN;
1532c1d255d3SCy Schubert 		num_elem++;
1533*32a95656SCy Schubert 	}
1534c1d255d3SCy Schubert 	if (identifier) {
1535c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1536c1d255d3SCy Schubert 			   identifier);
1537c1d255d3SCy Schubert 		addr[num_elem] = (const u8 *) identifier;
1538c1d255d3SCy Schubert 		len[num_elem] = os_strlen(identifier);
1539c1d255d3SCy Schubert 		num_elem++;
1540c1d255d3SCy Schubert 	}
1541c1d255d3SCy Schubert 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
1542c1d255d3SCy Schubert 	addr[num_elem] = (const u8 *) code;
1543c1d255d3SCy Schubert 	len[num_elem] = os_strlen(code);
1544c1d255d3SCy Schubert 	num_elem++;
1545c1d255d3SCy Schubert 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1546c1d255d3SCy Schubert 		goto fail;
1547c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1548*32a95656SCy Schubert 			"DPP: H([MAC-Responder |] [identifier |] code)",
1549c1d255d3SCy Schubert 			hash, curve->hash_len);
15504b72b91aSCy Schubert 	Pr_key = dpp_pkex_get_role_elem(curve, 0);
15514b72b91aSCy Schubert 	if (!Pr_key)
1552c1d255d3SCy Schubert 		goto fail;
15534b72b91aSCy Schubert 	dpp_debug_print_key("DPP: Pr", Pr_key);
1554266f97b5SCy Schubert 
15554b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
15564b72b91aSCy Schubert 	if (!ec)
1557c1d255d3SCy Schubert 		goto fail;
15584b72b91aSCy Schubert 
15594b72b91aSCy Schubert 	Pr = crypto_ec_key_get_public_key(Pr_key);
15604b72b91aSCy Schubert 	Qr = crypto_ec_point_init(ec);
15614b72b91aSCy Schubert 	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
15624b72b91aSCy Schubert 	if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
1563db0ac6deSCy Schubert 		goto fail;
15644b72b91aSCy Schubert 
15654b72b91aSCy Schubert 	if (crypto_ec_point_is_at_infinity(ec, Qr)) {
1566c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1567c1d255d3SCy Schubert 		goto fail;
1568c1d255d3SCy Schubert 	}
15694b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
15704b72b91aSCy Schubert 
1571c1d255d3SCy Schubert out:
15724b72b91aSCy Schubert 	crypto_ec_key_deinit(Pr_key);
15734b72b91aSCy Schubert 	crypto_bignum_deinit(hash_bn, 1);
15744b72b91aSCy Schubert 	if (ret_ec && Qr)
15754b72b91aSCy Schubert 		*ret_ec = ec;
1576c1d255d3SCy Schubert 	else
15774b72b91aSCy Schubert 		crypto_ec_deinit(ec);
1578c1d255d3SCy Schubert 	return Qr;
1579c1d255d3SCy Schubert fail:
15804b72b91aSCy Schubert 	crypto_ec_point_deinit(Qr, 1);
1581c1d255d3SCy Schubert 	Qr = NULL;
1582c1d255d3SCy Schubert 	goto out;
1583c1d255d3SCy Schubert }
1584c1d255d3SCy Schubert 
1585c1d255d3SCy Schubert 
1586c1d255d3SCy Schubert int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
1587*32a95656SCy Schubert 		      u8 ver_init, u8 ver_resp,
1588c1d255d3SCy Schubert 		      const u8 *Mx, size_t Mx_len,
1589c1d255d3SCy Schubert 		      const u8 *Nx, size_t Nx_len,
1590c1d255d3SCy Schubert 		      const char *code,
1591c1d255d3SCy Schubert 		      const u8 *Kx, size_t Kx_len,
1592c1d255d3SCy Schubert 		      u8 *z, unsigned int hash_len)
1593c1d255d3SCy Schubert {
1594c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1595c1d255d3SCy Schubert 	int res;
1596c1d255d3SCy Schubert 	u8 *info, *pos;
1597c1d255d3SCy Schubert 	size_t info_len;
1598c1d255d3SCy Schubert 
1599*32a95656SCy Schubert 	/*
1600*32a95656SCy Schubert 	 * v1: info = MAC-Initiator | MAC-Responder
1601*32a95656SCy Schubert 	 * v2: info = Protocol Version-Initiator | Protocol Version-Responder
1602*32a95656SCy Schubert 	 * z = HKDF(<>, info | M.x | N.x | code, K.x)
1603c1d255d3SCy Schubert 	 */
1604c1d255d3SCy Schubert 
1605c1d255d3SCy Schubert 	/* HKDF-Extract(<>, IKM=K.x) */
1606c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
1607c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1608c1d255d3SCy Schubert 		return -1;
1609c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1610c1d255d3SCy Schubert 			prk, hash_len);
1611*32a95656SCy Schubert 	if (mac_init && mac_resp)
1612*32a95656SCy Schubert 		info_len = 2 * ETH_ALEN;
1613*32a95656SCy Schubert 	else
1614*32a95656SCy Schubert 		info_len = 2;
1615*32a95656SCy Schubert 	info_len += Mx_len + Nx_len + os_strlen(code);
1616c1d255d3SCy Schubert 	info = os_malloc(info_len);
1617c1d255d3SCy Schubert 	if (!info)
1618c1d255d3SCy Schubert 		return -1;
1619c1d255d3SCy Schubert 	pos = info;
1620*32a95656SCy Schubert 	if (mac_init && mac_resp) {
1621c1d255d3SCy Schubert 		os_memcpy(pos, mac_init, ETH_ALEN);
1622c1d255d3SCy Schubert 		pos += ETH_ALEN;
1623c1d255d3SCy Schubert 		os_memcpy(pos, mac_resp, ETH_ALEN);
1624c1d255d3SCy Schubert 		pos += ETH_ALEN;
1625*32a95656SCy Schubert 	} else {
1626*32a95656SCy Schubert 		*pos++ = ver_init;
1627*32a95656SCy Schubert 		*pos++ = ver_resp;
1628*32a95656SCy Schubert 	}
1629c1d255d3SCy Schubert 	os_memcpy(pos, Mx, Mx_len);
1630c1d255d3SCy Schubert 	pos += Mx_len;
1631c1d255d3SCy Schubert 	os_memcpy(pos, Nx, Nx_len);
1632c1d255d3SCy Schubert 	pos += Nx_len;
1633c1d255d3SCy Schubert 	os_memcpy(pos, code, os_strlen(code));
1634c1d255d3SCy Schubert 
1635c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
1636c1d255d3SCy Schubert 	if (hash_len == 32)
1637c1d255d3SCy Schubert 		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1638c1d255d3SCy Schubert 				      z, hash_len);
1639c1d255d3SCy Schubert 	else if (hash_len == 48)
1640c1d255d3SCy Schubert 		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1641c1d255d3SCy Schubert 				      z, hash_len);
1642c1d255d3SCy Schubert 	else if (hash_len == 64)
1643c1d255d3SCy Schubert 		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1644c1d255d3SCy Schubert 				      z, hash_len);
1645c1d255d3SCy Schubert 	else
1646c1d255d3SCy Schubert 		res = -1;
1647c1d255d3SCy Schubert 	os_free(info);
1648c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
1649c1d255d3SCy Schubert 	if (res < 0)
1650c1d255d3SCy Schubert 		return -1;
1651c1d255d3SCy Schubert 
1652c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1653c1d255d3SCy Schubert 			z, hash_len);
1654c1d255d3SCy Schubert 	return 0;
1655c1d255d3SCy Schubert }
1656c1d255d3SCy Schubert 
1657c1d255d3SCy Schubert 
1658c1d255d3SCy Schubert int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1659c1d255d3SCy Schubert 				     const u8 *net_access_key,
1660c1d255d3SCy Schubert 				     size_t net_access_key_len,
1661c1d255d3SCy Schubert 				     struct json_token *peer_net_access_key)
1662c1d255d3SCy Schubert {
16634b72b91aSCy Schubert 	struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
16644b72b91aSCy Schubert 	struct crypto_bignum *sum = NULL;
16654b72b91aSCy Schubert 	const struct crypto_bignum *q, *cR, *pR;
16664b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
16674b72b91aSCy Schubert 	struct crypto_ec_point *M = NULL;
16684b72b91aSCy Schubert 	const struct crypto_ec_point *CI;
1669c1d255d3SCy Schubert 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1670c1d255d3SCy Schubert 	u8 prk[DPP_MAX_HASH_LEN];
1671c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
1672c1d255d3SCy Schubert 	int res = -1;
1673c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
1674c1d255d3SCy Schubert 
1675c1d255d3SCy Schubert 	own_key = dpp_set_keypair(&auth->curve, net_access_key,
1676c1d255d3SCy Schubert 				  net_access_key_len);
1677c1d255d3SCy Schubert 	if (!own_key) {
1678c1d255d3SCy Schubert 		dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1679c1d255d3SCy Schubert 		goto fail;
1680c1d255d3SCy Schubert 	}
1681c1d255d3SCy Schubert 
1682c1d255d3SCy Schubert 	peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1683c1d255d3SCy Schubert 	if (!peer_key)
1684c1d255d3SCy Schubert 		goto fail;
1685c1d255d3SCy Schubert 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1686c1d255d3SCy Schubert 
1687c1d255d3SCy Schubert 	if (auth->curve != curve) {
1688c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
1689c1d255d3SCy Schubert 			   "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1690c1d255d3SCy Schubert 			   auth->curve->name, curve->name);
1691c1d255d3SCy Schubert 		goto fail;
1692c1d255d3SCy Schubert 	}
1693c1d255d3SCy Schubert 
1694c1d255d3SCy Schubert 	auth->own_protocol_key = dpp_gen_keypair(curve);
1695c1d255d3SCy Schubert 	if (!auth->own_protocol_key)
1696c1d255d3SCy Schubert 		goto fail;
1697c1d255d3SCy Schubert 
1698c1d255d3SCy Schubert 	if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1699c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1700c1d255d3SCy Schubert 		goto fail;
1701c1d255d3SCy Schubert 	}
1702c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1703c1d255d3SCy Schubert 			auth->e_nonce, auth->curve->nonce_len);
1704c1d255d3SCy Schubert 
1705c1d255d3SCy Schubert 	/* M = { cR + pR } * CI */
17064b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
17074b72b91aSCy Schubert 	if (!ec)
1708c1d255d3SCy Schubert 		goto fail;
17094b72b91aSCy Schubert 
17104b72b91aSCy Schubert 	sum = crypto_bignum_init();
17114b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
17124b72b91aSCy Schubert 	M = crypto_ec_point_init(ec);
17134b72b91aSCy Schubert 	cR = crypto_ec_key_get_private_key(own_key);
17144b72b91aSCy Schubert 	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
17154b72b91aSCy Schubert 	CI = crypto_ec_key_get_public_key(peer_key);
17164b72b91aSCy Schubert 	if (!sum || !q || !M || !cR || !pR || !CI ||
17174b72b91aSCy Schubert 	    crypto_bignum_addmod(cR, pR, q, sum) ||
17184b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, CI, sum, M) ||
17194b72b91aSCy Schubert 	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
17204b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1721c1d255d3SCy Schubert 		goto fail;
1722c1d255d3SCy Schubert 	}
1723c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1724c1d255d3SCy Schubert 
1725c1d255d3SCy Schubert 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1726c1d255d3SCy Schubert 
1727c1d255d3SCy Schubert 	/* HKDF-Extract(C-nonce | E-nonce, M.x) */
1728c1d255d3SCy Schubert 	os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1729c1d255d3SCy Schubert 	os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1730c1d255d3SCy Schubert 	if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1731c1d255d3SCy Schubert 		     Mx, curve->prime_len, prk) < 0)
1732c1d255d3SCy Schubert 		goto fail;
1733c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1734c1d255d3SCy Schubert 
1735c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, "dpp reconfig key", L) */
1736c1d255d3SCy Schubert 	if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1737c1d255d3SCy Schubert 			    "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1738c1d255d3SCy Schubert 		goto fail;
1739c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1740c1d255d3SCy Schubert 			"DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1741c1d255d3SCy Schubert 			auth->ke, curve->hash_len);
1742c1d255d3SCy Schubert 
1743c1d255d3SCy Schubert 	res = 0;
17444b72b91aSCy Schubert 	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1745c1d255d3SCy Schubert 	auth->reconfig_old_protocol_key = own_key;
1746c1d255d3SCy Schubert 	own_key = NULL;
1747c1d255d3SCy Schubert fail:
1748c1d255d3SCy Schubert 	forced_memzero(prk, sizeof(prk));
1749c1d255d3SCy Schubert 	forced_memzero(Mx, sizeof(Mx));
17504b72b91aSCy Schubert 	crypto_ec_point_deinit(M, 1);
17514b72b91aSCy Schubert 	crypto_bignum_deinit(sum, 1);
17524b72b91aSCy Schubert 	crypto_ec_key_deinit(own_key);
17534b72b91aSCy Schubert 	crypto_ec_key_deinit(peer_key);
17544b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1755c1d255d3SCy Schubert 	return res;
1756c1d255d3SCy Schubert }
1757c1d255d3SCy Schubert 
1758c1d255d3SCy Schubert 
1759c1d255d3SCy Schubert int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1760c1d255d3SCy Schubert 				     const u8 *r_proto, u16 r_proto_len,
1761c1d255d3SCy Schubert 				     struct json_token *net_access_key)
1762c1d255d3SCy Schubert {
17634b72b91aSCy Schubert 	struct crypto_ec_key *pr = NULL, *peer_key = NULL;
17644b72b91aSCy Schubert 	const struct crypto_ec_point *CR, *PR;
17654b72b91aSCy Schubert 	const struct crypto_bignum *cI;
17664b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
17674b72b91aSCy Schubert 	struct crypto_ec_point *sum = NULL, *M = NULL;
1768c1d255d3SCy Schubert 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1769c1d255d3SCy Schubert 	u8 prk[DPP_MAX_HASH_LEN];
1770c1d255d3SCy Schubert 	int res = -1;
1771c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
1772c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
1773c1d255d3SCy Schubert 
1774c1d255d3SCy Schubert 	pr = dpp_set_pubkey_point(auth->conf->connector_key,
1775c1d255d3SCy Schubert 				  r_proto, r_proto_len);
1776c1d255d3SCy Schubert 	if (!pr) {
1777c1d255d3SCy Schubert 		dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1778c1d255d3SCy Schubert 		goto fail;
1779c1d255d3SCy Schubert 	}
1780c1d255d3SCy Schubert 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
17814b72b91aSCy Schubert 	crypto_ec_key_deinit(auth->peer_protocol_key);
1782c1d255d3SCy Schubert 	auth->peer_protocol_key = pr;
1783c1d255d3SCy Schubert 	pr = NULL;
1784c1d255d3SCy Schubert 
1785c1d255d3SCy Schubert 	peer_key = dpp_parse_jwk(net_access_key, &curve);
1786c1d255d3SCy Schubert 	if (!peer_key)
1787c1d255d3SCy Schubert 		goto fail;
1788c1d255d3SCy Schubert 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1789c1d255d3SCy Schubert 	if (auth->curve != curve) {
1790c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
1791c1d255d3SCy Schubert 			   "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1792c1d255d3SCy Schubert 			   auth->curve->name, curve->name);
1793c1d255d3SCy Schubert 		goto fail;
1794c1d255d3SCy Schubert 	}
1795c1d255d3SCy Schubert 
1796c1d255d3SCy Schubert 	/* M = cI * { CR + PR } */
17974b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
17984b72b91aSCy Schubert 	if (!ec)
1799c1d255d3SCy Schubert 		goto fail;
1800c1d255d3SCy Schubert 
18014b72b91aSCy Schubert 	cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
18024b72b91aSCy Schubert 	sum = crypto_ec_point_init(ec);
18034b72b91aSCy Schubert 	M = crypto_ec_point_init(ec);
18044b72b91aSCy Schubert 	CR = crypto_ec_key_get_public_key(peer_key);
18054b72b91aSCy Schubert 	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
18064b72b91aSCy Schubert 	if (!cI || !sum || !M || !CR || !PR ||
18074b72b91aSCy Schubert 	    crypto_ec_point_add(ec, CR, PR, sum) ||
18084b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, sum, cI, M) ||
18094b72b91aSCy Schubert 	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
18104b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
18114b72b91aSCy Schubert 		goto fail;
18124b72b91aSCy Schubert 	}
18134b72b91aSCy Schubert 
1814c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1815c1d255d3SCy Schubert 
1816c1d255d3SCy Schubert 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1817c1d255d3SCy Schubert 
1818c1d255d3SCy Schubert 	/* HKDF-Extract(C-nonce | E-nonce, M.x) */
1819c1d255d3SCy Schubert 	os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1820c1d255d3SCy Schubert 	os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1821c1d255d3SCy Schubert 	if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1822c1d255d3SCy Schubert 		     Mx, curve->prime_len, prk) < 0)
1823c1d255d3SCy Schubert 		goto fail;
1824c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1825c1d255d3SCy Schubert 
1826c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, "dpp reconfig key", L) */
1827c1d255d3SCy Schubert 	if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1828c1d255d3SCy Schubert 			    "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1829c1d255d3SCy Schubert 		goto fail;
1830c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1831c1d255d3SCy Schubert 			"DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1832c1d255d3SCy Schubert 			auth->ke, curve->hash_len);
1833c1d255d3SCy Schubert 
1834c1d255d3SCy Schubert 	res = 0;
1835c1d255d3SCy Schubert fail:
1836c1d255d3SCy Schubert 	forced_memzero(prk, sizeof(prk));
1837c1d255d3SCy Schubert 	forced_memzero(Mx, sizeof(Mx));
18384b72b91aSCy Schubert 	crypto_ec_key_deinit(pr);
18394b72b91aSCy Schubert 	crypto_ec_key_deinit(peer_key);
18404b72b91aSCy Schubert 	crypto_ec_point_deinit(sum, 1);
18414b72b91aSCy Schubert 	crypto_ec_point_deinit(M, 1);
18424b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1843c1d255d3SCy Schubert 	return res;
1844c1d255d3SCy Schubert }
1845c1d255d3SCy Schubert 
1846c1d255d3SCy Schubert 
1847c1d255d3SCy Schubert static char *
1848c1d255d3SCy Schubert dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1849c1d255d3SCy Schubert {
1850c1d255d3SCy Schubert 	struct wpabuf *jws_prot_hdr;
1851c1d255d3SCy Schubert 	char *signed1;
1852c1d255d3SCy Schubert 
1853c1d255d3SCy Schubert 	jws_prot_hdr = wpabuf_alloc(100);
1854c1d255d3SCy Schubert 	if (!jws_prot_hdr)
1855c1d255d3SCy Schubert 		return NULL;
1856c1d255d3SCy Schubert 	json_start_object(jws_prot_hdr, NULL);
1857c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "typ", "dppCon");
1858c1d255d3SCy Schubert 	json_value_sep(jws_prot_hdr);
1859c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "kid", conf->kid);
1860c1d255d3SCy Schubert 	json_value_sep(jws_prot_hdr);
1861c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1862c1d255d3SCy Schubert 	json_end_object(jws_prot_hdr);
1863c1d255d3SCy Schubert 	signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1864c1d255d3SCy Schubert 				    wpabuf_len(jws_prot_hdr),
1865c1d255d3SCy Schubert 				    signed1_len);
1866c1d255d3SCy Schubert 	wpabuf_free(jws_prot_hdr);
1867c1d255d3SCy Schubert 	return signed1;
1868c1d255d3SCy Schubert }
1869c1d255d3SCy Schubert 
1870c1d255d3SCy Schubert 
1871c1d255d3SCy Schubert static char *
1872c1d255d3SCy Schubert dpp_build_conn_signature(struct dpp_configurator *conf,
1873c1d255d3SCy Schubert 			 const char *signed1, size_t signed1_len,
1874c1d255d3SCy Schubert 			 const char *signed2, size_t signed2_len,
1875c1d255d3SCy Schubert 			 size_t *signed3_len)
1876c1d255d3SCy Schubert {
1877c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
18784b72b91aSCy Schubert 	struct wpabuf *sig = NULL;
1879c1d255d3SCy Schubert 	char *signed3 = NULL;
1880c1d255d3SCy Schubert 	char *dot = ".";
18814b72b91aSCy Schubert 	const u8 *vector[3];
18824b72b91aSCy Schubert 	size_t vector_len[3];
18834b72b91aSCy Schubert 	u8 *hash;
18844b72b91aSCy Schubert 	int ret;
18854b72b91aSCy Schubert 
18864b72b91aSCy Schubert 	vector[0] = (const u8 *) signed1;
18874b72b91aSCy Schubert 	vector[1] = (const u8 *) dot;
18884b72b91aSCy Schubert 	vector[2] = (const u8 *) signed2;
18894b72b91aSCy Schubert 	vector_len[0] = signed1_len;
18904b72b91aSCy Schubert 	vector_len[1] = 1;
18914b72b91aSCy Schubert 	vector_len[2] = signed2_len;
1892c1d255d3SCy Schubert 
1893c1d255d3SCy Schubert 	curve = conf->curve;
18944b72b91aSCy Schubert 	hash = os_malloc(curve->hash_len);
18954b72b91aSCy Schubert 	if (!hash)
18964b72b91aSCy Schubert 		goto fail;
1897c1d255d3SCy Schubert 	if (curve->hash_len == SHA256_MAC_LEN) {
18984b72b91aSCy Schubert 		ret = sha256_vector(3, vector, vector_len, hash);
1899c1d255d3SCy Schubert 	} else if (curve->hash_len == SHA384_MAC_LEN) {
19004b72b91aSCy Schubert 		ret = sha384_vector(3, vector, vector_len, hash);
1901c1d255d3SCy Schubert 	} else if (curve->hash_len == SHA512_MAC_LEN) {
19024b72b91aSCy Schubert 		ret = sha512_vector(3, vector, vector_len, hash);
1903c1d255d3SCy Schubert 	} else {
1904c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1905c1d255d3SCy Schubert 		goto fail;
1906c1d255d3SCy Schubert 	}
19074b72b91aSCy Schubert 	if (ret) {
19084b72b91aSCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
19094b72b91aSCy Schubert 		goto fail;
19104b72b91aSCy Schubert 	}
19114b72b91aSCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
19124b72b91aSCy Schubert 		    hash, curve->hash_len);
1913db0ac6deSCy Schubert 
19144b72b91aSCy Schubert 	sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
19154b72b91aSCy Schubert 	if (!sig) {
19164b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
1917db0ac6deSCy Schubert 		goto fail;
19184b72b91aSCy Schubert 	}
1919db0ac6deSCy Schubert 
1920c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
19214b72b91aSCy Schubert 		    wpabuf_head(sig), wpabuf_len(sig));
19224b72b91aSCy Schubert 	signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
19234b72b91aSCy Schubert 				    signed3_len);
19244b72b91aSCy Schubert 
1925c1d255d3SCy Schubert fail:
19264b72b91aSCy Schubert 	os_free(hash);
19274b72b91aSCy Schubert 	wpabuf_free(sig);
1928c1d255d3SCy Schubert 	return signed3;
1929c1d255d3SCy Schubert }
1930c1d255d3SCy Schubert 
1931c1d255d3SCy Schubert char * dpp_sign_connector(struct dpp_configurator *conf,
1932c1d255d3SCy Schubert 			  const struct wpabuf *dppcon)
1933c1d255d3SCy Schubert {
1934c1d255d3SCy Schubert 	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1935c1d255d3SCy Schubert 	char *signed_conn = NULL, *pos;
1936c1d255d3SCy Schubert 	size_t signed1_len, signed2_len, signed3_len;
1937c1d255d3SCy Schubert 
1938c1d255d3SCy Schubert 	signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1939c1d255d3SCy Schubert 	signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1940c1d255d3SCy Schubert 				    &signed2_len);
1941c1d255d3SCy Schubert 	if (!signed1 || !signed2)
1942c1d255d3SCy Schubert 		goto fail;
1943c1d255d3SCy Schubert 
1944c1d255d3SCy Schubert 	signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1945c1d255d3SCy Schubert 					   signed2, signed2_len, &signed3_len);
1946c1d255d3SCy Schubert 	if (!signed3)
1947c1d255d3SCy Schubert 		goto fail;
1948c1d255d3SCy Schubert 
1949c1d255d3SCy Schubert 	signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1950c1d255d3SCy Schubert 	if (!signed_conn)
1951c1d255d3SCy Schubert 		goto fail;
1952c1d255d3SCy Schubert 	pos = signed_conn;
1953c1d255d3SCy Schubert 	os_memcpy(pos, signed1, signed1_len);
1954c1d255d3SCy Schubert 	pos += signed1_len;
1955c1d255d3SCy Schubert 	*pos++ = '.';
1956c1d255d3SCy Schubert 	os_memcpy(pos, signed2, signed2_len);
1957c1d255d3SCy Schubert 	pos += signed2_len;
1958c1d255d3SCy Schubert 	*pos++ = '.';
1959c1d255d3SCy Schubert 	os_memcpy(pos, signed3, signed3_len);
1960c1d255d3SCy Schubert 	pos += signed3_len;
1961c1d255d3SCy Schubert 	*pos = '\0';
1962c1d255d3SCy Schubert 
1963c1d255d3SCy Schubert fail:
1964c1d255d3SCy Schubert 	os_free(signed1);
1965c1d255d3SCy Schubert 	os_free(signed2);
1966c1d255d3SCy Schubert 	os_free(signed3);
1967c1d255d3SCy Schubert 	return signed_conn;
1968c1d255d3SCy Schubert }
1969c1d255d3SCy Schubert 
1970c1d255d3SCy Schubert 
1971c1d255d3SCy Schubert #ifdef CONFIG_DPP2
1972c1d255d3SCy Schubert 
1973c1d255d3SCy Schubert struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
1974c1d255d3SCy Schubert 			      size_t net_access_key_len)
1975c1d255d3SCy Schubert {
1976c1d255d3SCy Schubert 	struct wpabuf *pub = NULL;
19774b72b91aSCy Schubert 	struct crypto_ec_key *own_key;
1978c1d255d3SCy Schubert 	struct dpp_pfs *pfs;
1979c1d255d3SCy Schubert 
1980c1d255d3SCy Schubert 	pfs = os_zalloc(sizeof(*pfs));
1981c1d255d3SCy Schubert 	if (!pfs)
1982c1d255d3SCy Schubert 		return NULL;
1983c1d255d3SCy Schubert 
1984c1d255d3SCy Schubert 	own_key = dpp_set_keypair(&pfs->curve, net_access_key,
1985c1d255d3SCy Schubert 				  net_access_key_len);
1986c1d255d3SCy Schubert 	if (!own_key) {
1987c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
1988c1d255d3SCy Schubert 		goto fail;
1989c1d255d3SCy Schubert 	}
19904b72b91aSCy Schubert 	crypto_ec_key_deinit(own_key);
1991c1d255d3SCy Schubert 
1992c1d255d3SCy Schubert 	pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
1993c1d255d3SCy Schubert 	if (!pfs->ecdh)
1994c1d255d3SCy Schubert 		goto fail;
1995c1d255d3SCy Schubert 
1996c1d255d3SCy Schubert 	pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
1997c1d255d3SCy Schubert 	pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
1998c1d255d3SCy Schubert 	if (!pub)
1999c1d255d3SCy Schubert 		goto fail;
2000c1d255d3SCy Schubert 
2001c1d255d3SCy Schubert 	pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2002c1d255d3SCy Schubert 	if (!pfs->ie)
2003c1d255d3SCy Schubert 		goto fail;
2004c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2005c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2006c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2007c1d255d3SCy Schubert 	wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2008c1d255d3SCy Schubert 	wpabuf_put_buf(pfs->ie, pub);
2009c1d255d3SCy Schubert 	wpabuf_free(pub);
2010c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2011c1d255d3SCy Schubert 			pfs->ie);
2012c1d255d3SCy Schubert 
2013c1d255d3SCy Schubert 	return pfs;
2014c1d255d3SCy Schubert fail:
2015c1d255d3SCy Schubert 	wpabuf_free(pub);
2016c1d255d3SCy Schubert 	dpp_pfs_free(pfs);
2017c1d255d3SCy Schubert 	return NULL;
2018c1d255d3SCy Schubert }
2019c1d255d3SCy Schubert 
2020c1d255d3SCy Schubert 
2021c1d255d3SCy Schubert int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2022c1d255d3SCy Schubert {
2023c1d255d3SCy Schubert 	if (peer_ie_len < 2)
2024c1d255d3SCy Schubert 		return -1;
2025c1d255d3SCy Schubert 	if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2026c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2027c1d255d3SCy Schubert 		return -1;
2028c1d255d3SCy Schubert 	}
2029c1d255d3SCy Schubert 
2030c1d255d3SCy Schubert 	pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2031c1d255d3SCy Schubert 					      peer_ie_len - 2);
2032c1d255d3SCy Schubert 	pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2033c1d255d3SCy Schubert 	if (!pfs->secret) {
2034c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2035c1d255d3SCy Schubert 		return -1;
2036c1d255d3SCy Schubert 	}
2037c1d255d3SCy Schubert 	wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2038c1d255d3SCy Schubert 	return 0;
2039c1d255d3SCy Schubert }
2040c1d255d3SCy Schubert 
2041c1d255d3SCy Schubert 
2042c1d255d3SCy Schubert void dpp_pfs_free(struct dpp_pfs *pfs)
2043c1d255d3SCy Schubert {
2044c1d255d3SCy Schubert 	if (!pfs)
2045c1d255d3SCy Schubert 		return;
2046c1d255d3SCy Schubert 	crypto_ecdh_deinit(pfs->ecdh);
2047c1d255d3SCy Schubert 	wpabuf_free(pfs->ie);
2048c1d255d3SCy Schubert 	wpabuf_clear_free(pfs->secret);
2049c1d255d3SCy Schubert 	os_free(pfs);
2050c1d255d3SCy Schubert }
2051c1d255d3SCy Schubert 
2052c1d255d3SCy Schubert 
2053c1d255d3SCy Schubert struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2054c1d255d3SCy Schubert {
20554b72b91aSCy Schubert 	struct crypto_csr *csr = NULL;
2056c1d255d3SCy Schubert 	struct wpabuf *buf = NULL;
20574b72b91aSCy Schubert 	struct crypto_ec_key *key;
2058c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
20594b72b91aSCy Schubert 	struct wpabuf *priv_key;
2060c1d255d3SCy Schubert 	u8 cp[DPP_CP_LEN];
20614b72b91aSCy Schubert 	char *password = NULL;
2062c1d255d3SCy Schubert 	size_t password_len;
20634b72b91aSCy Schubert 	int hash_sign_algo;
2064c1d255d3SCy Schubert 
2065c1d255d3SCy Schubert 	/* TODO: use auth->csrattrs */
2066c1d255d3SCy Schubert 
2067c1d255d3SCy Schubert 	/* TODO: support generation of a new private key if csrAttrs requests
2068c1d255d3SCy Schubert 	 * a specific group to be used */
2069c1d255d3SCy Schubert 	key = auth->own_protocol_key;
2070c1d255d3SCy Schubert 
20714b72b91aSCy Schubert 	priv_key = crypto_ec_key_get_ecprivate_key(key, true);
20724b72b91aSCy Schubert 	if (!priv_key)
2073c1d255d3SCy Schubert 		goto fail;
2074c1d255d3SCy Schubert 	wpabuf_free(auth->priv_key);
20754b72b91aSCy Schubert 	auth->priv_key = priv_key;
20764b72b91aSCy Schubert 
20774b72b91aSCy Schubert 	csr = crypto_csr_init();
20784b72b91aSCy Schubert 	if (!csr || crypto_csr_set_ec_public_key(csr, key))
2079c1d255d3SCy Schubert 		goto fail;
2080c1d255d3SCy Schubert 
20814b72b91aSCy Schubert 	if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
2082c1d255d3SCy Schubert 		goto fail;
2083c1d255d3SCy Schubert 
2084c1d255d3SCy Schubert 	/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2085c1d255d3SCy Schubert 	if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2086c1d255d3SCy Schubert 			    "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2087c1d255d3SCy Schubert 		goto fail;
2088c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2089c1d255d3SCy Schubert 			"DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2090c1d255d3SCy Schubert 			cp, DPP_CP_LEN);
2091c1d255d3SCy Schubert 	password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2092c1d255d3SCy Schubert 	forced_memzero(cp, DPP_CP_LEN);
20934b72b91aSCy Schubert 	if (!password ||
20944b72b91aSCy Schubert 	    crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
20954b72b91aSCy Schubert 				     ASN1_TAG_UTF8STRING, (const u8 *) password,
20964b72b91aSCy Schubert 				     password_len))
2097c1d255d3SCy Schubert 		goto fail;
2098c1d255d3SCy Schubert 
2099c1d255d3SCy Schubert 	/* TODO: hash func selection based on csrAttrs */
2100c1d255d3SCy Schubert 	if (hash_len == SHA256_MAC_LEN) {
21014b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
2102c1d255d3SCy Schubert 	} else if (hash_len == SHA384_MAC_LEN) {
21034b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
2104c1d255d3SCy Schubert 	} else if (hash_len == SHA512_MAC_LEN) {
21054b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
2106c1d255d3SCy Schubert 	} else {
2107c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2108c1d255d3SCy Schubert 		goto fail;
2109c1d255d3SCy Schubert 	}
2110c1d255d3SCy Schubert 
21114b72b91aSCy Schubert 	buf = crypto_csr_sign(csr, key, hash_sign_algo);
21124b72b91aSCy Schubert 	if (!buf)
2113c1d255d3SCy Schubert 		goto fail;
2114c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2115c1d255d3SCy Schubert 
2116c1d255d3SCy Schubert fail:
21174b72b91aSCy Schubert 	bin_clear_free(password, password_len);
21184b72b91aSCy Schubert 	crypto_csr_deinit(csr);
2119c1d255d3SCy Schubert 	return buf;
2120c1d255d3SCy Schubert }
2121c1d255d3SCy Schubert 
2122c1d255d3SCy Schubert 
21234b72b91aSCy Schubert int dpp_validate_csr(struct dpp_authentication *auth,
21244b72b91aSCy Schubert 		     const struct wpabuf *csrbuf)
2125c1d255d3SCy Schubert {
21264b72b91aSCy Schubert 	struct crypto_csr *csr;
21274b72b91aSCy Schubert 	const u8 *attr;
21284b72b91aSCy Schubert 	size_t attr_len;
21294b72b91aSCy Schubert 	int attr_type;
2130c1d255d3SCy Schubert 	unsigned char *cp = NULL;
2131c1d255d3SCy Schubert 	size_t cp_len;
2132c1d255d3SCy Schubert 	u8 exp_cp[DPP_CP_LEN];
2133c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
21344b72b91aSCy Schubert 	int ret = -1;
2135c1d255d3SCy Schubert 
21364b72b91aSCy Schubert 	csr = crypto_csr_verify(csrbuf);
21374b72b91aSCy Schubert 	if (!csr) {
2138db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
21394b72b91aSCy Schubert 			   "DPP: CSR invalid or invalid signature");
2140db0ac6deSCy Schubert 		goto fail;
2141db0ac6deSCy Schubert 	}
2142db0ac6deSCy Schubert 
21434b72b91aSCy Schubert 	attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
21444b72b91aSCy Schubert 					&attr_len, &attr_type);
21454b72b91aSCy Schubert 	if (!attr) {
2146c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2147c1d255d3SCy Schubert 			   "DPP: CSR does not include challengePassword");
2148c1d255d3SCy Schubert 		goto fail;
2149c1d255d3SCy Schubert 	}
2150db0ac6deSCy Schubert 	/* This is supposed to be UTF8String, but allow other strings as well
2151db0ac6deSCy Schubert 	 * since challengePassword is using ASCII (base64 encoded). */
21524b72b91aSCy Schubert 	if (attr_type != ASN1_TAG_UTF8STRING &&
21534b72b91aSCy Schubert 	    attr_type != ASN1_TAG_PRINTABLESTRING &&
21544b72b91aSCy Schubert 	    attr_type != ASN1_TAG_IA5STRING) {
2155db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
2156db0ac6deSCy Schubert 			   "DPP: Unexpected challengePassword attribute type %d",
21574b72b91aSCy Schubert 			   attr_type);
2158db0ac6deSCy Schubert 		goto fail;
2159db0ac6deSCy Schubert 	}
2160db0ac6deSCy Schubert 
21614b72b91aSCy Schubert 	cp = base64_decode((const char *) attr, attr_len, &cp_len);
2162c1d255d3SCy Schubert 	if (!cp) {
2163c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2164c1d255d3SCy Schubert 			   "DPP: Could not base64 decode challengePassword");
2165c1d255d3SCy Schubert 		goto fail;
2166c1d255d3SCy Schubert 	}
2167c1d255d3SCy Schubert 	if (cp_len != DPP_CP_LEN) {
2168c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2169c1d255d3SCy Schubert 			   "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2170c1d255d3SCy Schubert 			   cp_len);
2171c1d255d3SCy Schubert 		goto fail;
2172c1d255d3SCy Schubert 	}
2173c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2174c1d255d3SCy Schubert 			cp, cp_len);
2175c1d255d3SCy Schubert 
2176c1d255d3SCy Schubert 	/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2177c1d255d3SCy Schubert 	if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2178c1d255d3SCy Schubert 			    "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2179c1d255d3SCy Schubert 		goto fail;
2180c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2181c1d255d3SCy Schubert 			"DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2182c1d255d3SCy Schubert 			exp_cp, DPP_CP_LEN);
2183c1d255d3SCy Schubert 	if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2184c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2185c1d255d3SCy Schubert 			   "DPP: CSR challengePassword does not match calculated cp");
2186c1d255d3SCy Schubert 		goto fail;
2187c1d255d3SCy Schubert 	}
2188c1d255d3SCy Schubert 
2189c1d255d3SCy Schubert 	ret = 0;
2190c1d255d3SCy Schubert fail:
2191c1d255d3SCy Schubert 	os_free(cp);
21924b72b91aSCy Schubert 	crypto_csr_deinit(csr);
2193c1d255d3SCy Schubert 	return ret;
2194c1d255d3SCy Schubert }
2195c1d255d3SCy Schubert 
2196c1d255d3SCy Schubert 
2197c1d255d3SCy Schubert struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2198c1d255d3SCy Schubert 					     size_t csign_key_len,
2199c1d255d3SCy Schubert 					     const u8 *pp_key,
2200c1d255d3SCy Schubert 					     size_t pp_key_len)
2201c1d255d3SCy Schubert {
22024b72b91aSCy Schubert 	struct crypto_ec_key *csign = NULL, *ppkey = NULL;
2203c1d255d3SCy Schubert 	struct dpp_reconfig_id *id = NULL;
22044b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
22054b72b91aSCy Schubert 	const struct crypto_bignum *q;
22064b72b91aSCy Schubert 	struct crypto_bignum *bn = NULL;
22074b72b91aSCy Schubert 	struct crypto_ec_point *e_id = NULL;
22084b72b91aSCy Schubert 	const struct crypto_ec_point *generator;
2209c1d255d3SCy Schubert 
22104b72b91aSCy Schubert 	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
2211c1d255d3SCy Schubert 	if (!csign)
2212c1d255d3SCy Schubert 		goto fail;
2213c1d255d3SCy Schubert 
2214c1d255d3SCy Schubert 	if (!pp_key)
2215c1d255d3SCy Schubert 		goto fail;
22164b72b91aSCy Schubert 	ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
2217c1d255d3SCy Schubert 	if (!ppkey)
2218c1d255d3SCy Schubert 		goto fail;
2219c1d255d3SCy Schubert 
22204b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(csign));
22214b72b91aSCy Schubert 	if (!ec)
2222c1d255d3SCy Schubert 		goto fail;
2223c1d255d3SCy Schubert 
22244b72b91aSCy Schubert 	e_id = crypto_ec_point_init(ec);
22254b72b91aSCy Schubert 	bn = crypto_bignum_init();
22264b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
22274b72b91aSCy Schubert 	generator = crypto_ec_get_generator(ec);
22284b72b91aSCy Schubert 	if (!e_id || !bn || !q || !generator ||
22294b72b91aSCy Schubert 	    crypto_bignum_rand(bn, q) ||
22304b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, generator, bn, e_id))
2231c1d255d3SCy Schubert 		goto fail;
2232c1d255d3SCy Schubert 
22334b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, e_id,
22344b72b91aSCy Schubert 				    "DPP: Generated random point E-id");
2235c1d255d3SCy Schubert 
2236c1d255d3SCy Schubert 	id = os_zalloc(sizeof(*id));
2237c1d255d3SCy Schubert 	if (!id)
2238c1d255d3SCy Schubert 		goto fail;
22394b72b91aSCy Schubert 
22404b72b91aSCy Schubert 	id->ec = ec;
22414b72b91aSCy Schubert 	ec = NULL;
2242c1d255d3SCy Schubert 	id->e_id = e_id;
2243c1d255d3SCy Schubert 	e_id = NULL;
2244c1d255d3SCy Schubert 	id->csign = csign;
2245c1d255d3SCy Schubert 	csign = NULL;
2246c1d255d3SCy Schubert 	id->pp_key = ppkey;
2247c1d255d3SCy Schubert 	ppkey = NULL;
2248c1d255d3SCy Schubert fail:
22494b72b91aSCy Schubert 	crypto_ec_point_deinit(e_id, 1);
22504b72b91aSCy Schubert 	crypto_ec_key_deinit(csign);
22514b72b91aSCy Schubert 	crypto_ec_key_deinit(ppkey);
22524b72b91aSCy Schubert 	crypto_bignum_deinit(bn, 1);
22534b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2254c1d255d3SCy Schubert 	return id;
2255c1d255d3SCy Schubert }
2256c1d255d3SCy Schubert 
2257c1d255d3SCy Schubert 
2258c1d255d3SCy Schubert int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2259c1d255d3SCy Schubert {
22604b72b91aSCy Schubert 	const struct crypto_bignum *q;
22614b72b91aSCy Schubert 	struct crypto_bignum *bn;
22624b72b91aSCy Schubert 	const struct crypto_ec_point *pp, *generator;
22634b72b91aSCy Schubert 	struct crypto_ec_point *e_prime_id, *a_nonce;
2264c1d255d3SCy Schubert 	int ret = -1;
2265c1d255d3SCy Schubert 
22664b72b91aSCy Schubert 	pp = crypto_ec_key_get_public_key(id->pp_key);
22674b72b91aSCy Schubert 	e_prime_id = crypto_ec_point_init(id->ec);
22684b72b91aSCy Schubert 	a_nonce = crypto_ec_point_init(id->ec);
22694b72b91aSCy Schubert 	bn = crypto_bignum_init();
22704b72b91aSCy Schubert 	q = crypto_ec_get_order(id->ec);
22714b72b91aSCy Schubert 	generator = crypto_ec_get_generator(id->ec);
22724b72b91aSCy Schubert 
2273c1d255d3SCy Schubert 	/* Generate random 0 <= a-nonce < q
2274c1d255d3SCy Schubert 	 * A-NONCE = a-nonce * G
2275c1d255d3SCy Schubert 	 * E'-id = E-id + a-nonce * P_pk */
22764b72b91aSCy Schubert 	if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
22774b72b91aSCy Schubert 	    crypto_bignum_rand(bn, q) || /* bn = a-nonce */
22784b72b91aSCy Schubert 	    crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
22794b72b91aSCy Schubert 	    crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
22804b72b91aSCy Schubert 	    crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
2281c1d255d3SCy Schubert 		goto fail;
2282c1d255d3SCy Schubert 
22834b72b91aSCy Schubert 	crypto_ec_point_debug_print(id->ec, a_nonce,
22844b72b91aSCy Schubert 				    "DPP: Generated A-NONCE");
22854b72b91aSCy Schubert 	crypto_ec_point_debug_print(id->ec, e_prime_id,
22864b72b91aSCy Schubert 				    "DPP: Encrypted E-id to E'-id");
2287c1d255d3SCy Schubert 
22884b72b91aSCy Schubert 	crypto_ec_key_deinit(id->a_nonce);
22894b72b91aSCy Schubert 	crypto_ec_key_deinit(id->e_prime_id);
22904b72b91aSCy Schubert 	id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
22914b72b91aSCy Schubert 	id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
2292c1d255d3SCy Schubert 	if (!id->a_nonce || !id->e_prime_id)
2293c1d255d3SCy Schubert 		goto fail;
2294c1d255d3SCy Schubert 
2295c1d255d3SCy Schubert 	ret = 0;
2296c1d255d3SCy Schubert 
2297c1d255d3SCy Schubert fail:
22984b72b91aSCy Schubert 	crypto_ec_point_deinit(e_prime_id, 1);
22994b72b91aSCy Schubert 	crypto_ec_point_deinit(a_nonce, 1);
23004b72b91aSCy Schubert 	crypto_bignum_deinit(bn, 1);
2301c1d255d3SCy Schubert 	return ret;
2302c1d255d3SCy Schubert }
2303c1d255d3SCy Schubert 
2304c1d255d3SCy Schubert 
2305c1d255d3SCy Schubert void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2306c1d255d3SCy Schubert {
2307c1d255d3SCy Schubert 	if (id) {
23084b72b91aSCy Schubert 		crypto_ec_point_deinit(id->e_id, 1);
23094b72b91aSCy Schubert 		crypto_ec_key_deinit(id->csign);
23104b72b91aSCy Schubert 		crypto_ec_key_deinit(id->a_nonce);
23114b72b91aSCy Schubert 		crypto_ec_key_deinit(id->e_prime_id);
23124b72b91aSCy Schubert 		crypto_ec_key_deinit(id->pp_key);
23134b72b91aSCy Schubert 		crypto_ec_deinit(id->ec);
2314c1d255d3SCy Schubert 		os_free(id);
2315c1d255d3SCy Schubert 	}
2316c1d255d3SCy Schubert }
2317c1d255d3SCy Schubert 
2318c1d255d3SCy Schubert 
23194b72b91aSCy Schubert struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
23204b72b91aSCy Schubert 					  struct crypto_ec_key *a_nonce,
23214b72b91aSCy Schubert 					  struct crypto_ec_key *e_prime_id)
2322c1d255d3SCy Schubert {
23234b72b91aSCy Schubert 	struct crypto_ec *ec;
23244b72b91aSCy Schubert 	const struct crypto_bignum *pp;
23254b72b91aSCy Schubert 	struct crypto_ec_point *e_id = NULL;
23264b72b91aSCy Schubert 	const struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
2327c1d255d3SCy Schubert 
2328c1d255d3SCy Schubert 	if (!ppkey)
2329c1d255d3SCy Schubert 		return NULL;
2330c1d255d3SCy Schubert 
2331c1d255d3SCy Schubert 	/* E-id = E'-id - s_C * A-NONCE */
23324b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(ppkey));
23334b72b91aSCy Schubert 	if (!ec)
2334c1d255d3SCy Schubert 		return NULL;
23354b72b91aSCy Schubert 
23364b72b91aSCy Schubert 	pp = crypto_ec_key_get_private_key(ppkey);
23374b72b91aSCy Schubert 	a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
23384b72b91aSCy Schubert 	e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
23394b72b91aSCy Schubert 	e_id = crypto_ec_point_init(ec);
23404b72b91aSCy Schubert 	if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
23414b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
23424b72b91aSCy Schubert 	    crypto_ec_point_invert(ec, e_id) ||
23434b72b91aSCy Schubert 	    crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
23444b72b91aSCy Schubert 		crypto_ec_point_deinit(e_id, 1);
2345c1d255d3SCy Schubert 		goto fail;
2346c1d255d3SCy Schubert 	}
2347c1d255d3SCy Schubert 
23484b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
2349c1d255d3SCy Schubert 
2350c1d255d3SCy Schubert fail:
23514b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2352c1d255d3SCy Schubert 	return e_id;
2353c1d255d3SCy Schubert }
2354c1d255d3SCy Schubert 
2355c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */
2356c1d255d3SCy Schubert 
2357c1d255d3SCy Schubert 
2358c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
2359c1d255d3SCy Schubert 
2360c1d255d3SCy Schubert int dpp_test_gen_invalid_key(struct wpabuf *msg,
2361c1d255d3SCy Schubert 			     const struct dpp_curve_params *curve)
2362c1d255d3SCy Schubert {
23634b72b91aSCy Schubert 	struct crypto_ec *ec;
23644b72b91aSCy Schubert 	struct crypto_ec_key *key = NULL;
23654b72b91aSCy Schubert 	const struct crypto_ec_point *pub_key;
23664b72b91aSCy Schubert 	struct crypto_ec_point *p = NULL;
23674b72b91aSCy Schubert 	u8 *x, *y;
2368c1d255d3SCy Schubert 	int ret = -1;
2369c1d255d3SCy Schubert 
23704b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
23714b72b91aSCy Schubert 	x = wpabuf_put(msg, curve->prime_len);
23724b72b91aSCy Schubert 	y = wpabuf_put(msg, curve->prime_len);
23734b72b91aSCy Schubert 	if (!ec)
2374c1d255d3SCy Schubert 		goto fail;
2375c1d255d3SCy Schubert 
23764b72b91aSCy Schubert retry:
23774b72b91aSCy Schubert 	/* Generate valid key pair */
23784b72b91aSCy Schubert 	key = crypto_ec_key_gen(curve->ike_group);
23794b72b91aSCy Schubert 	if (!key)
2380c1d255d3SCy Schubert 		goto fail;
2381c1d255d3SCy Schubert 
23824b72b91aSCy Schubert 	/* Retrieve public key coordinates */
23834b72b91aSCy Schubert 	pub_key = crypto_ec_key_get_public_key(key);
23844b72b91aSCy Schubert 	if (!pub_key)
2385c1d255d3SCy Schubert 		goto fail;
2386c1d255d3SCy Schubert 
23874b72b91aSCy Schubert 	crypto_ec_point_to_bin(ec, pub_key, x, y);
23884b72b91aSCy Schubert 
23894b72b91aSCy Schubert 	/* And corrupt them */
23904b72b91aSCy Schubert 	y[curve->prime_len - 1] ^= 0x01;
23914b72b91aSCy Schubert 	p = crypto_ec_point_from_bin(ec, x);
23924b72b91aSCy Schubert 	if (p && crypto_ec_point_is_on_curve(ec, p)) {
23934b72b91aSCy Schubert 		crypto_ec_point_deinit(p, 0);
23944b72b91aSCy Schubert 		p = NULL;
23954b72b91aSCy Schubert 		goto retry;
2396c1d255d3SCy Schubert 	}
2397c1d255d3SCy Schubert 
2398c1d255d3SCy Schubert 	ret = 0;
2399c1d255d3SCy Schubert fail:
24004b72b91aSCy Schubert 	crypto_ec_point_deinit(p, 0);
24014b72b91aSCy Schubert 	crypto_ec_key_deinit(key);
24024b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2403c1d255d3SCy Schubert 	return ret;
2404c1d255d3SCy Schubert }
2405c1d255d3SCy Schubert 
2406c1d255d3SCy Schubert 
2407c1d255d3SCy Schubert char * dpp_corrupt_connector_signature(const char *connector)
2408c1d255d3SCy Schubert {
2409c1d255d3SCy Schubert 	char *tmp, *pos, *signed3 = NULL;
2410c1d255d3SCy Schubert 	unsigned char *signature = NULL;
2411c1d255d3SCy Schubert 	size_t signature_len = 0, signed3_len;
2412c1d255d3SCy Schubert 
2413c1d255d3SCy Schubert 	tmp = os_zalloc(os_strlen(connector) + 5);
2414c1d255d3SCy Schubert 	if (!tmp)
2415c1d255d3SCy Schubert 		goto fail;
2416c1d255d3SCy Schubert 	os_memcpy(tmp, connector, os_strlen(connector));
2417c1d255d3SCy Schubert 
2418c1d255d3SCy Schubert 	pos = os_strchr(tmp, '.');
2419c1d255d3SCy Schubert 	if (!pos)
2420c1d255d3SCy Schubert 		goto fail;
2421c1d255d3SCy Schubert 
2422c1d255d3SCy Schubert 	pos = os_strchr(pos + 1, '.');
2423c1d255d3SCy Schubert 	if (!pos)
2424c1d255d3SCy Schubert 		goto fail;
2425c1d255d3SCy Schubert 	pos++;
2426c1d255d3SCy Schubert 
2427c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2428c1d255d3SCy Schubert 		   pos);
2429c1d255d3SCy Schubert 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2430c1d255d3SCy Schubert 	if (!signature || signature_len == 0)
2431c1d255d3SCy Schubert 		goto fail;
2432c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2433c1d255d3SCy Schubert 		    signature, signature_len);
2434c1d255d3SCy Schubert 	signature[signature_len - 1] ^= 0x01;
2435c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2436c1d255d3SCy Schubert 		    signature, signature_len);
2437c1d255d3SCy Schubert 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2438c1d255d3SCy Schubert 	if (!signed3)
2439c1d255d3SCy Schubert 		goto fail;
2440c1d255d3SCy Schubert 	os_memcpy(pos, signed3, signed3_len);
2441c1d255d3SCy Schubert 	pos[signed3_len] = '\0';
2442c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2443c1d255d3SCy Schubert 		   pos);
2444c1d255d3SCy Schubert 
2445c1d255d3SCy Schubert out:
2446c1d255d3SCy Schubert 	os_free(signature);
2447c1d255d3SCy Schubert 	os_free(signed3);
2448c1d255d3SCy Schubert 	return tmp;
2449c1d255d3SCy Schubert fail:
2450c1d255d3SCy Schubert 	os_free(tmp);
2451c1d255d3SCy Schubert 	tmp = NULL;
2452c1d255d3SCy Schubert 	goto out;
2453c1d255d3SCy Schubert }
2454c1d255d3SCy Schubert 
2455c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
2456