xref: /freebsd/contrib/wpa/src/common/dpp_crypto.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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 
dpp_get_curve_name(const char * name)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 
dpp_get_curve_jwk_crv(const char * name)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 
dpp_get_curve_ike_group(u16 group)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 
dpp_debug_print_key(const char * title,struct crypto_ec_key * key)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 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)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 
dpp_hmac_vector(size_t hash_len,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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 
dpp_pbkdf2_f(size_t hash_len,const u8 * password,size_t password_len,const u8 * salt,size_t salt_len,unsigned int iterations,unsigned int count,u8 * digest)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 
dpp_pbkdf2(size_t hash_len,const u8 * password,size_t password_len,const u8 * salt,size_t salt_len,unsigned int iterations,u8 * buf,size_t buflen)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 
dpp_set_pubkey_point(struct crypto_ec_key * group_key,const u8 * buf,size_t len)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 
dpp_get_pubkey_hash(struct crypto_ec_key * key,u8 * hash)249*a90b9d01SCy Schubert int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash)
250*a90b9d01SCy Schubert {
251*a90b9d01SCy Schubert 	struct wpabuf *uncomp;
252*a90b9d01SCy Schubert 	const u8 *addr[1];
253*a90b9d01SCy Schubert 	size_t len[1];
254*a90b9d01SCy Schubert 	int res;
255*a90b9d01SCy Schubert 
256*a90b9d01SCy Schubert 	if (!key)
257*a90b9d01SCy Schubert 		return -1;
258*a90b9d01SCy Schubert 
259*a90b9d01SCy Schubert 	uncomp = crypto_ec_key_get_pubkey_point(key, 1);
260*a90b9d01SCy Schubert 	if (!uncomp)
261*a90b9d01SCy Schubert 		return -1;
262*a90b9d01SCy Schubert 	addr[0] = wpabuf_head(uncomp);
263*a90b9d01SCy Schubert 	len[0] = wpabuf_len(uncomp);
264*a90b9d01SCy Schubert 	res = sha256_vector(1, addr, len, hash);
265*a90b9d01SCy Schubert 	wpabuf_free(uncomp);
266*a90b9d01SCy Schubert 	return res;
267*a90b9d01SCy Schubert }
268*a90b9d01SCy Schubert 
269*a90b9d01SCy Schubert 
dpp_gen_keypair(const struct dpp_curve_params * curve)2704b72b91aSCy Schubert struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
271c1d255d3SCy Schubert {
2724b72b91aSCy Schubert 	struct crypto_ec_key *key;
273c1d255d3SCy Schubert 
274c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
275c1d255d3SCy Schubert 
2764b72b91aSCy Schubert 	key = crypto_ec_key_gen(curve->ike_group);
2774b72b91aSCy Schubert 	if (key && wpa_debug_show_keys)
278c1d255d3SCy Schubert 	    dpp_debug_print_key("Own generated key", key);
279c1d255d3SCy Schubert 
280c1d255d3SCy Schubert 	return key;
281c1d255d3SCy Schubert }
282c1d255d3SCy Schubert 
283c1d255d3SCy Schubert 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)2844b72b91aSCy Schubert struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
285c1d255d3SCy Schubert 				       const u8 *privkey, size_t privkey_len)
286c1d255d3SCy Schubert {
2874b72b91aSCy Schubert 	struct crypto_ec_key *key;
2884b72b91aSCy Schubert 	int group;
289c1d255d3SCy Schubert 
2904b72b91aSCy Schubert 	key = crypto_ec_key_parse_priv(privkey, privkey_len);
2914b72b91aSCy Schubert 	if (!key) {
2924b72b91aSCy Schubert 		wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
293c1d255d3SCy Schubert 		return NULL;
294c1d255d3SCy Schubert 	}
2954b72b91aSCy Schubert 
2964b72b91aSCy Schubert 	group = crypto_ec_key_group(key);
2974b72b91aSCy Schubert 	if (group < 0) {
2984b72b91aSCy Schubert 		crypto_ec_key_deinit(key);
299c1d255d3SCy Schubert 		return NULL;
300c1d255d3SCy Schubert 	}
3014b72b91aSCy Schubert 
3024b72b91aSCy Schubert 	*curve = dpp_get_curve_ike_group(group);
303c1d255d3SCy Schubert 	if (!*curve) {
304c1d255d3SCy Schubert 		wpa_printf(MSG_INFO,
3054b72b91aSCy Schubert 			   "DPP: Unsupported curve (group=%d) in pre-assigned key",
3064b72b91aSCy Schubert 			   group);
3074b72b91aSCy Schubert 		crypto_ec_key_deinit(key);
308c1d255d3SCy Schubert 		return NULL;
309c1d255d3SCy Schubert 	}
310c1d255d3SCy Schubert 
3114b72b91aSCy Schubert 	return key;
312c1d255d3SCy Schubert }
313c1d255d3SCy Schubert 
314c1d255d3SCy Schubert 
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)315c1d255d3SCy Schubert int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
316c1d255d3SCy Schubert {
317c1d255d3SCy Schubert 	struct wpabuf *der;
318c1d255d3SCy Schubert 	int res;
319c1d255d3SCy Schubert 
3204b72b91aSCy Schubert 	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
321c1d255d3SCy Schubert 	if (!der)
322c1d255d3SCy Schubert 		return -1;
323c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
324c1d255d3SCy Schubert 			der);
325c1d255d3SCy Schubert 	res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
326c1d255d3SCy Schubert 	if (res < 0)
327c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
328c1d255d3SCy Schubert 	wpabuf_free(der);
329c1d255d3SCy Schubert 	return res;
330c1d255d3SCy Schubert }
331c1d255d3SCy Schubert 
332c1d255d3SCy Schubert 
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,const u8 * privkey,size_t privkey_len)333c1d255d3SCy Schubert int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
334c1d255d3SCy Schubert 	       const u8 *privkey, size_t privkey_len)
335c1d255d3SCy Schubert {
336c1d255d3SCy Schubert 	char *base64 = NULL;
337c1d255d3SCy Schubert 	char *pos, *end;
338c1d255d3SCy Schubert 	size_t len;
339c1d255d3SCy Schubert 	struct wpabuf *der = NULL;
340c1d255d3SCy Schubert 
341c1d255d3SCy Schubert 	bi->curve = dpp_get_curve_name(curve);
342c1d255d3SCy Schubert 	if (!bi->curve) {
343c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
344c1d255d3SCy Schubert 		return -1;
345c1d255d3SCy Schubert 	}
346c1d255d3SCy Schubert 
347c1d255d3SCy Schubert 	if (privkey)
348c1d255d3SCy Schubert 		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
349c1d255d3SCy Schubert 	else
350c1d255d3SCy Schubert 		bi->pubkey = dpp_gen_keypair(bi->curve);
351c1d255d3SCy Schubert 	if (!bi->pubkey)
352c1d255d3SCy Schubert 		goto fail;
353c1d255d3SCy Schubert 	bi->own = 1;
354c1d255d3SCy Schubert 
3554b72b91aSCy Schubert 	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
356c1d255d3SCy Schubert 	if (!der)
357c1d255d3SCy Schubert 		goto fail;
358c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
359c1d255d3SCy Schubert 			der);
360c1d255d3SCy Schubert 
361c1d255d3SCy Schubert 	if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
362c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
363c1d255d3SCy Schubert 		goto fail;
364c1d255d3SCy Schubert 	}
365c1d255d3SCy Schubert 
366c1d255d3SCy Schubert 	base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
367c1d255d3SCy Schubert 	wpabuf_free(der);
368c1d255d3SCy Schubert 	der = NULL;
369c1d255d3SCy Schubert 	if (!base64)
370c1d255d3SCy Schubert 		goto fail;
371c1d255d3SCy Schubert 	pos = base64;
372c1d255d3SCy Schubert 	end = pos + len;
373c1d255d3SCy Schubert 	for (;;) {
374c1d255d3SCy Schubert 		pos = os_strchr(pos, '\n');
375c1d255d3SCy Schubert 		if (!pos)
376c1d255d3SCy Schubert 			break;
377c1d255d3SCy Schubert 		os_memmove(pos, pos + 1, end - pos);
378c1d255d3SCy Schubert 	}
379c1d255d3SCy Schubert 	os_free(bi->pk);
380c1d255d3SCy Schubert 	bi->pk = base64;
381c1d255d3SCy Schubert 	return 0;
382c1d255d3SCy Schubert fail:
383c1d255d3SCy Schubert 	os_free(base64);
384c1d255d3SCy Schubert 	wpabuf_free(der);
385c1d255d3SCy Schubert 	return -1;
386c1d255d3SCy Schubert }
387c1d255d3SCy Schubert 
388c1d255d3SCy Schubert 
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)389c1d255d3SCy Schubert int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len)
390c1d255d3SCy Schubert {
391c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
392c1d255d3SCy Schubert 	const char *info = "first intermediate key";
393c1d255d3SCy Schubert 	int res;
394c1d255d3SCy Schubert 
395c1d255d3SCy Schubert 	/* k1 = HKDF(<>, "first intermediate key", M.x) */
396c1d255d3SCy Schubert 
397c1d255d3SCy Schubert 	/* HKDF-Extract(<>, M.x) */
398c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
399c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
400c1d255d3SCy Schubert 		return -1;
401c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
402c1d255d3SCy Schubert 			prk, hash_len);
403c1d255d3SCy Schubert 
404c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
405c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
406c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
407c1d255d3SCy Schubert 	if (res < 0)
408c1d255d3SCy Schubert 		return -1;
409c1d255d3SCy Schubert 
410c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
411c1d255d3SCy Schubert 			k1, hash_len);
412c1d255d3SCy Schubert 	return 0;
413c1d255d3SCy Schubert }
414c1d255d3SCy Schubert 
415c1d255d3SCy Schubert 
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)416c1d255d3SCy Schubert int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len)
417c1d255d3SCy Schubert {
418c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
419c1d255d3SCy Schubert 	const char *info = "second intermediate key";
420c1d255d3SCy Schubert 	int res;
421c1d255d3SCy Schubert 
422c1d255d3SCy Schubert 	/* k2 = HKDF(<>, "second intermediate key", N.x) */
423c1d255d3SCy Schubert 
424c1d255d3SCy Schubert 	/* HKDF-Extract(<>, N.x) */
425c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
426c1d255d3SCy Schubert 	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
427c1d255d3SCy Schubert 	if (res < 0)
428c1d255d3SCy Schubert 		return -1;
429c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
430c1d255d3SCy Schubert 			prk, hash_len);
431c1d255d3SCy Schubert 
432c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
433c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
434c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
435c1d255d3SCy Schubert 	if (res < 0)
436c1d255d3SCy Schubert 		return -1;
437c1d255d3SCy Schubert 
438c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
439c1d255d3SCy Schubert 			k2, hash_len);
440c1d255d3SCy Schubert 	return 0;
441c1d255d3SCy Schubert }
442c1d255d3SCy Schubert 
443c1d255d3SCy Schubert 
dpp_derive_bk_ke(struct dpp_authentication * auth)444c1d255d3SCy Schubert int dpp_derive_bk_ke(struct dpp_authentication *auth)
445c1d255d3SCy Schubert {
446c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
447c1d255d3SCy Schubert 	size_t nonce_len = auth->curve->nonce_len;
448c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
449c1d255d3SCy Schubert 	const char *info_ke = "DPP Key";
450c1d255d3SCy Schubert 	int res;
451c1d255d3SCy Schubert 	const u8 *addr[3];
452c1d255d3SCy Schubert 	size_t len[3];
453c1d255d3SCy Schubert 	size_t num_elem = 0;
454c1d255d3SCy Schubert 
455c1d255d3SCy Schubert 	if (!auth->Mx_len || !auth->Nx_len) {
456c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
457c1d255d3SCy Schubert 			   "DPP: Mx/Nx not available - cannot derive ke");
458c1d255d3SCy Schubert 		return -1;
459c1d255d3SCy Schubert 	}
460c1d255d3SCy Schubert 
461c1d255d3SCy Schubert 	/* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
462c1d255d3SCy Schubert 	os_memcpy(nonces, auth->i_nonce, nonce_len);
463c1d255d3SCy Schubert 	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
464c1d255d3SCy Schubert 	addr[num_elem] = auth->Mx;
465c1d255d3SCy Schubert 	len[num_elem] = auth->Mx_len;
466c1d255d3SCy Schubert 	num_elem++;
467c1d255d3SCy Schubert 	addr[num_elem] = auth->Nx;
468c1d255d3SCy Schubert 	len[num_elem] = auth->Nx_len;
469c1d255d3SCy Schubert 	num_elem++;
470c1d255d3SCy Schubert 	if (auth->peer_bi && auth->own_bi) {
471c1d255d3SCy Schubert 		if (!auth->Lx_len) {
472c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG,
473c1d255d3SCy Schubert 				   "DPP: Lx not available - cannot derive ke");
474c1d255d3SCy Schubert 			return -1;
475c1d255d3SCy Schubert 		}
476c1d255d3SCy Schubert 		addr[num_elem] = auth->Lx;
477c1d255d3SCy Schubert 		len[num_elem] = auth->secret_len;
478c1d255d3SCy Schubert 		num_elem++;
479c1d255d3SCy Schubert 	}
480c1d255d3SCy Schubert 	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
481c1d255d3SCy Schubert 			      num_elem, addr, len, auth->bk);
482c1d255d3SCy Schubert 	if (res < 0)
483c1d255d3SCy Schubert 		return -1;
484c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
485c1d255d3SCy Schubert 			"DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])",
486c1d255d3SCy Schubert 			auth->bk, hash_len);
487c1d255d3SCy Schubert 
488c1d255d3SCy Schubert 	/* ke = HKDF-Expand(bk, "DPP Key", length) */
489c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke,
490c1d255d3SCy Schubert 			      hash_len);
491c1d255d3SCy Schubert 	if (res < 0)
492c1d255d3SCy Schubert 		return -1;
493c1d255d3SCy Schubert 
494c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
495c1d255d3SCy Schubert 			"DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)",
496c1d255d3SCy Schubert 			auth->ke, hash_len);
497c1d255d3SCy Schubert 
498c1d255d3SCy Schubert 	return 0;
499c1d255d3SCy Schubert }
500c1d255d3SCy Schubert 
501c1d255d3SCy Schubert 
dpp_ecdh(struct crypto_ec_key * own,struct crypto_ec_key * peer,u8 * secret,size_t * secret_len)5024b72b91aSCy Schubert int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
5034b72b91aSCy Schubert 	     u8 *secret, size_t *secret_len)
504c1d255d3SCy Schubert {
5054b72b91aSCy Schubert 	struct crypto_ecdh *ecdh;
5064b72b91aSCy Schubert 	struct wpabuf *peer_pub, *secret_buf = NULL;
507c1d255d3SCy Schubert 	int ret = -1;
508c1d255d3SCy Schubert 
509c1d255d3SCy Schubert 	*secret_len = 0;
510c1d255d3SCy Schubert 
5114b72b91aSCy Schubert 	ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
5124b72b91aSCy Schubert 	if (!ecdh) {
5134b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
514c1d255d3SCy Schubert 		return -1;
515c1d255d3SCy Schubert 	}
516c1d255d3SCy Schubert 
5174b72b91aSCy Schubert 	peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
5184b72b91aSCy Schubert 	if (!peer_pub) {
519c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR,
5204b72b91aSCy Schubert 			   "DPP: crypto_ec_key_get_pubkey_point() failed");
521c1d255d3SCy Schubert 		goto fail;
522c1d255d3SCy Schubert 	}
523c1d255d3SCy Schubert 
5244b72b91aSCy Schubert 	secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
5254b72b91aSCy Schubert 					     wpabuf_len(peer_pub));
5264b72b91aSCy Schubert 	if (!secret_buf) {
5274b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
528c1d255d3SCy Schubert 		goto fail;
529c1d255d3SCy Schubert 	}
530c1d255d3SCy Schubert 
5314b72b91aSCy Schubert 	if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
5324b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
533c1d255d3SCy Schubert 		goto fail;
534c1d255d3SCy Schubert 	}
535c1d255d3SCy Schubert 
5364b72b91aSCy Schubert 	*secret_len = wpabuf_len(secret_buf);
5374b72b91aSCy Schubert 	os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
538c1d255d3SCy Schubert 	ret = 0;
539c1d255d3SCy Schubert 
540c1d255d3SCy Schubert fail:
5414b72b91aSCy Schubert 	wpabuf_clear_free(secret_buf);
5424b72b91aSCy Schubert 	wpabuf_free(peer_pub);
5434b72b91aSCy Schubert 	crypto_ecdh_deinit(ecdh);
544c1d255d3SCy Schubert 	return ret;
545c1d255d3SCy Schubert }
546c1d255d3SCy Schubert 
547c1d255d3SCy Schubert 
dpp_bi_pubkey_hash(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)548c1d255d3SCy Schubert int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
549c1d255d3SCy Schubert 		       const u8 *data, size_t data_len)
550c1d255d3SCy Schubert {
551c1d255d3SCy Schubert 	const u8 *addr[2];
552c1d255d3SCy Schubert 	size_t len[2];
553c1d255d3SCy Schubert 
554c1d255d3SCy Schubert 	addr[0] = data;
555c1d255d3SCy Schubert 	len[0] = data_len;
556c1d255d3SCy Schubert 	if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
557c1d255d3SCy Schubert 		return -1;
558c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
559c1d255d3SCy Schubert 		    bi->pubkey_hash, SHA256_MAC_LEN);
560c1d255d3SCy Schubert 
561c1d255d3SCy Schubert 	addr[0] = (const u8 *) "chirp";
562c1d255d3SCy Schubert 	len[0] = 5;
563c1d255d3SCy Schubert 	addr[1] = data;
564c1d255d3SCy Schubert 	len[1] = data_len;
565c1d255d3SCy Schubert 	if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
566c1d255d3SCy Schubert 		return -1;
567c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
568c1d255d3SCy Schubert 		    bi->pubkey_hash_chirp, SHA256_MAC_LEN);
569c1d255d3SCy Schubert 
570c1d255d3SCy Schubert 	return 0;
571c1d255d3SCy Schubert }
572c1d255d3SCy Schubert 
573c1d255d3SCy Schubert 
dpp_get_subject_public_key(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)574c1d255d3SCy Schubert int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
575c1d255d3SCy Schubert 			       const u8 *data, size_t data_len)
576c1d255d3SCy Schubert {
5774b72b91aSCy Schubert 	struct crypto_ec_key *key;
578c1d255d3SCy Schubert 
579c1d255d3SCy Schubert 	if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
580c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
581c1d255d3SCy Schubert 		return -1;
582c1d255d3SCy Schubert 	}
583c1d255d3SCy Schubert 
5844b72b91aSCy Schubert 	key = crypto_ec_key_parse_pub(data, data_len);
5854b72b91aSCy Schubert 	if (!key) {
586c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
587c1d255d3SCy Schubert 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
588c1d255d3SCy Schubert 		return -1;
589c1d255d3SCy Schubert 	}
590c1d255d3SCy Schubert 
5914b72b91aSCy Schubert 	bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
592db0ac6deSCy Schubert 	if (!bi->curve) {
593db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
5944b72b91aSCy Schubert 			   "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
5954b72b91aSCy Schubert 			   crypto_ec_key_group(key));
596db0ac6deSCy Schubert 		goto fail;
597db0ac6deSCy Schubert 	}
598db0ac6deSCy Schubert 
5994b72b91aSCy Schubert 	bi->pubkey = key;
600c1d255d3SCy Schubert 	return 0;
601c1d255d3SCy Schubert fail:
6024b72b91aSCy Schubert 	crypto_ec_key_deinit(key);
603c1d255d3SCy Schubert 	return -1;
604c1d255d3SCy Schubert }
605c1d255d3SCy Schubert 
606c1d255d3SCy Schubert 
607c1d255d3SCy Schubert static struct wpabuf *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params * curve,const u8 * prot_hdr,u16 prot_hdr_len,int * hash_func)608c1d255d3SCy Schubert dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
609c1d255d3SCy Schubert 		       const u8 *prot_hdr, u16 prot_hdr_len,
6104b72b91aSCy Schubert 		       int *hash_func)
611c1d255d3SCy Schubert {
612c1d255d3SCy Schubert 	struct json_token *root, *token;
613c1d255d3SCy Schubert 	struct wpabuf *kid = NULL;
614c1d255d3SCy Schubert 
615c1d255d3SCy Schubert 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
616c1d255d3SCy Schubert 	if (!root) {
617c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
618c1d255d3SCy Schubert 			   "DPP: JSON parsing failed for JWS Protected Header");
619c1d255d3SCy Schubert 		goto fail;
620c1d255d3SCy Schubert 	}
621c1d255d3SCy Schubert 
622c1d255d3SCy Schubert 	if (root->type != JSON_OBJECT) {
623c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
624c1d255d3SCy Schubert 			   "DPP: JWS Protected Header root is not an object");
625c1d255d3SCy Schubert 		goto fail;
626c1d255d3SCy Schubert 	}
627c1d255d3SCy Schubert 
628c1d255d3SCy Schubert 	token = json_get_member(root, "typ");
629c1d255d3SCy Schubert 	if (!token || token->type != JSON_STRING) {
630c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
631c1d255d3SCy Schubert 		goto fail;
632c1d255d3SCy Schubert 	}
633c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
634c1d255d3SCy Schubert 		   token->string);
635c1d255d3SCy Schubert 	if (os_strcmp(token->string, "dppCon") != 0) {
636c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
637c1d255d3SCy Schubert 			   "DPP: Unsupported JWS Protected Header typ=%s",
638c1d255d3SCy Schubert 			   token->string);
639c1d255d3SCy Schubert 		goto fail;
640c1d255d3SCy Schubert 	}
641c1d255d3SCy Schubert 
642c1d255d3SCy Schubert 	token = json_get_member(root, "alg");
643c1d255d3SCy Schubert 	if (!token || token->type != JSON_STRING) {
644c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
645c1d255d3SCy Schubert 		goto fail;
646c1d255d3SCy Schubert 	}
647c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
648c1d255d3SCy Schubert 		   token->string);
649c1d255d3SCy Schubert 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
650c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
651c1d255d3SCy Schubert 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
652c1d255d3SCy Schubert 			   token->string, curve->jws_alg);
653c1d255d3SCy Schubert 		goto fail;
654c1d255d3SCy Schubert 	}
655c1d255d3SCy Schubert 	if (os_strcmp(token->string, "ES256") == 0 ||
6564b72b91aSCy Schubert 	    os_strcmp(token->string, "BS256") == 0) {
6574b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA256;
6584b72b91aSCy Schubert 	} else if (os_strcmp(token->string, "ES384") == 0 ||
6594b72b91aSCy Schubert 		   os_strcmp(token->string, "BS384") == 0) {
6604b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA384;
6614b72b91aSCy Schubert 	} else if (os_strcmp(token->string, "ES512") == 0 ||
6624b72b91aSCy Schubert 		   os_strcmp(token->string, "BS512") == 0) {
6634b72b91aSCy Schubert 		*hash_func = CRYPTO_HASH_ALG_SHA512;
6644b72b91aSCy Schubert 	} else {
6654b72b91aSCy Schubert 		*hash_func = -1;
666c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
667c1d255d3SCy Schubert 			   "DPP: Unsupported JWS Protected Header alg=%s",
668c1d255d3SCy Schubert 			   token->string);
669c1d255d3SCy Schubert 		goto fail;
670c1d255d3SCy Schubert 	}
671c1d255d3SCy Schubert 
672c1d255d3SCy Schubert 	kid = json_get_member_base64url(root, "kid");
673c1d255d3SCy Schubert 	if (!kid) {
674c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
675c1d255d3SCy Schubert 		goto fail;
676c1d255d3SCy Schubert 	}
677c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
678c1d255d3SCy Schubert 			kid);
679c1d255d3SCy Schubert 
680c1d255d3SCy Schubert fail:
681c1d255d3SCy Schubert 	json_free(root);
682c1d255d3SCy Schubert 	return kid;
683c1d255d3SCy Schubert }
684c1d255d3SCy Schubert 
685c1d255d3SCy Schubert 
dpp_check_pubkey_match(struct crypto_ec_key * pub,struct wpabuf * r_hash)6864b72b91aSCy Schubert static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
6874b72b91aSCy Schubert 				  struct wpabuf *r_hash)
688c1d255d3SCy Schubert {
689c1d255d3SCy Schubert 	struct wpabuf *uncomp;
690c1d255d3SCy Schubert 	int res;
691c1d255d3SCy Schubert 	u8 hash[SHA256_MAC_LEN];
692c1d255d3SCy Schubert 	const u8 *addr[1];
693c1d255d3SCy Schubert 	size_t len[1];
694c1d255d3SCy Schubert 
695c1d255d3SCy Schubert 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
696c1d255d3SCy Schubert 		return -1;
6974b72b91aSCy Schubert 	uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
698c1d255d3SCy Schubert 	if (!uncomp)
699c1d255d3SCy Schubert 		return -1;
700c1d255d3SCy Schubert 	addr[0] = wpabuf_head(uncomp);
701c1d255d3SCy Schubert 	len[0] = wpabuf_len(uncomp);
702c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
703c1d255d3SCy Schubert 		    addr[0], len[0]);
704c1d255d3SCy Schubert 	res = sha256_vector(1, addr, len, hash);
705c1d255d3SCy Schubert 	wpabuf_free(uncomp);
706c1d255d3SCy Schubert 	if (res < 0)
707c1d255d3SCy Schubert 		return -1;
708c1d255d3SCy Schubert 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
709c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
710c1d255d3SCy Schubert 			   "DPP: Received hash value does not match calculated public key hash value");
711c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
712c1d255d3SCy Schubert 			    hash, SHA256_MAC_LEN);
713c1d255d3SCy Schubert 		return -1;
714c1d255d3SCy Schubert 	}
715c1d255d3SCy Schubert 	return 0;
716c1d255d3SCy Schubert }
717c1d255d3SCy Schubert 
718c1d255d3SCy Schubert 
719c1d255d3SCy Schubert enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_ec_key * csign_pub,const char * connector)720c1d255d3SCy Schubert dpp_process_signed_connector(struct dpp_signed_connector_info *info,
7214b72b91aSCy Schubert 			     struct crypto_ec_key *csign_pub,
7224b72b91aSCy Schubert 			     const char *connector)
723c1d255d3SCy Schubert {
724c1d255d3SCy Schubert 	enum dpp_status_error ret = 255;
725c1d255d3SCy Schubert 	const char *pos, *end, *signed_start, *signed_end;
726c1d255d3SCy Schubert 	struct wpabuf *kid = NULL;
727c1d255d3SCy Schubert 	unsigned char *prot_hdr = NULL, *signature = NULL;
7284b72b91aSCy Schubert 	size_t prot_hdr_len = 0, signature_len = 0, signed_len;
7294b72b91aSCy Schubert 	int res, hash_func = -1;
730c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
7314b72b91aSCy Schubert 	u8 *hash = NULL;
732c1d255d3SCy Schubert 
7334b72b91aSCy Schubert 	curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
734c1d255d3SCy Schubert 	if (!curve)
735c1d255d3SCy Schubert 		goto fail;
736c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
737c1d255d3SCy Schubert 	os_memset(info, 0, sizeof(*info));
738c1d255d3SCy Schubert 
739c1d255d3SCy Schubert 	signed_start = pos = connector;
740c1d255d3SCy Schubert 	end = os_strchr(pos, '.');
741c1d255d3SCy Schubert 	if (!end) {
742c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
743c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
744c1d255d3SCy Schubert 		goto fail;
745c1d255d3SCy Schubert 	}
746c1d255d3SCy Schubert 	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
747c1d255d3SCy Schubert 	if (!prot_hdr) {
748c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
749c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
750c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
751c1d255d3SCy Schubert 		goto fail;
752c1d255d3SCy Schubert 	}
753c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG,
754c1d255d3SCy Schubert 			  "DPP: signedConnector - JWS Protected Header",
755c1d255d3SCy Schubert 			  prot_hdr, prot_hdr_len);
7564b72b91aSCy Schubert 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
757c1d255d3SCy Schubert 	if (!kid) {
758c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
759c1d255d3SCy Schubert 		goto fail;
760c1d255d3SCy Schubert 	}
761c1d255d3SCy Schubert 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
762c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
763c1d255d3SCy Schubert 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
764c1d255d3SCy Schubert 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
765c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
766c1d255d3SCy Schubert 		goto fail;
767c1d255d3SCy Schubert 	}
768c1d255d3SCy Schubert 
769c1d255d3SCy Schubert 	pos = end + 1;
770c1d255d3SCy Schubert 	end = os_strchr(pos, '.');
771c1d255d3SCy Schubert 	if (!end) {
772c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
773c1d255d3SCy Schubert 			   "DPP: Missing dot(2) in signedConnector");
774c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
775c1d255d3SCy Schubert 		goto fail;
776c1d255d3SCy Schubert 	}
777c1d255d3SCy Schubert 	signed_end = end - 1;
778c1d255d3SCy Schubert 	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
779c1d255d3SCy Schubert 	if (!info->payload) {
780c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
781c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
782c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
783c1d255d3SCy Schubert 		goto fail;
784c1d255d3SCy Schubert 	}
785c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG,
786c1d255d3SCy Schubert 			  "DPP: signedConnector - JWS Payload",
787c1d255d3SCy Schubert 			  info->payload, info->payload_len);
788c1d255d3SCy Schubert 	pos = end + 1;
789c1d255d3SCy Schubert 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
790c1d255d3SCy Schubert 	if (!signature) {
791c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
792c1d255d3SCy Schubert 			   "DPP: Failed to base64url decode signedConnector signature");
793c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
794c1d255d3SCy Schubert 		goto fail;
795c1d255d3SCy Schubert 		}
796c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
797c1d255d3SCy Schubert 		    signature, signature_len);
798c1d255d3SCy Schubert 
799c1d255d3SCy Schubert 	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
800c1d255d3SCy Schubert 		ret = DPP_STATUS_NO_MATCH;
801c1d255d3SCy Schubert 		goto fail;
802c1d255d3SCy Schubert 	}
803c1d255d3SCy Schubert 
804c1d255d3SCy Schubert 	if (signature_len & 0x01) {
805c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
806c1d255d3SCy Schubert 			   "DPP: Unexpected signedConnector signature length (%d)",
807c1d255d3SCy Schubert 			   (int) signature_len);
808c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
809c1d255d3SCy Schubert 		goto fail;
810c1d255d3SCy Schubert 	}
811c1d255d3SCy Schubert 
8124b72b91aSCy Schubert 	hash = os_malloc(curve->hash_len);
8134b72b91aSCy Schubert 	if (!hash)
814c1d255d3SCy Schubert 		goto fail;
815c1d255d3SCy Schubert 
8164b72b91aSCy Schubert 	signed_len = signed_end - signed_start + 1;
8174b72b91aSCy Schubert 	if (hash_func == CRYPTO_HASH_ALG_SHA256)
8184b72b91aSCy Schubert 		res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
8194b72b91aSCy Schubert 				    hash);
8204b72b91aSCy Schubert 	else if (hash_func == CRYPTO_HASH_ALG_SHA384)
8214b72b91aSCy Schubert 		res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
8224b72b91aSCy Schubert 				    hash);
8234b72b91aSCy Schubert 	else if (hash_func == CRYPTO_HASH_ALG_SHA512)
8244b72b91aSCy Schubert 		res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
8254b72b91aSCy Schubert 				    hash);
8264b72b91aSCy Schubert 	else
827c1d255d3SCy Schubert 		goto fail;
8284b72b91aSCy Schubert 
8294b72b91aSCy Schubert 	if (res)
830c1d255d3SCy Schubert 		goto fail;
8314b72b91aSCy Schubert 
8324b72b91aSCy Schubert 	res = crypto_ec_key_verify_signature_r_s(csign_pub,
8334b72b91aSCy Schubert 						 hash, curve->hash_len,
8344b72b91aSCy Schubert 						 signature, signature_len / 2,
8354b72b91aSCy Schubert 						 signature + signature_len / 2,
8364b72b91aSCy Schubert 						 signature_len / 2);
837c1d255d3SCy Schubert 	if (res != 1) {
838c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
8394b72b91aSCy Schubert 			   "DPP: signedConnector signature check failed (res=%d)",
8404b72b91aSCy Schubert 			   res);
841c1d255d3SCy Schubert 		ret = DPP_STATUS_INVALID_CONNECTOR;
842c1d255d3SCy Schubert 		goto fail;
843c1d255d3SCy Schubert 	}
844c1d255d3SCy Schubert 
845c1d255d3SCy Schubert 	ret = DPP_STATUS_OK;
846c1d255d3SCy Schubert fail:
8474b72b91aSCy Schubert 	os_free(hash);
848c1d255d3SCy Schubert 	os_free(prot_hdr);
849c1d255d3SCy Schubert 	wpabuf_free(kid);
850c1d255d3SCy Schubert 	os_free(signature);
851c1d255d3SCy Schubert 	return ret;
852c1d255d3SCy Schubert }
853c1d255d3SCy Schubert 
854c1d255d3SCy Schubert 
855c1d255d3SCy Schubert enum dpp_status_error
dpp_check_signed_connector(struct dpp_signed_connector_info * info,const u8 * csign_key,size_t csign_key_len,const u8 * peer_connector,size_t peer_connector_len)856c1d255d3SCy Schubert dpp_check_signed_connector(struct dpp_signed_connector_info *info,
857c1d255d3SCy Schubert 			   const u8 *csign_key, size_t csign_key_len,
858c1d255d3SCy Schubert 			   const u8 *peer_connector, size_t peer_connector_len)
859c1d255d3SCy Schubert {
8604b72b91aSCy Schubert 	struct crypto_ec_key *csign;
861c1d255d3SCy Schubert 	char *signed_connector = NULL;
862c1d255d3SCy Schubert 	enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
863c1d255d3SCy Schubert 
8644b72b91aSCy Schubert 	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
865c1d255d3SCy Schubert 	if (!csign) {
866c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR,
867c1d255d3SCy Schubert 			   "DPP: Failed to parse local C-sign-key information");
868c1d255d3SCy Schubert 		goto fail;
869c1d255d3SCy Schubert 	}
870c1d255d3SCy Schubert 
871c1d255d3SCy Schubert 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
872c1d255d3SCy Schubert 			  peer_connector, peer_connector_len);
873c1d255d3SCy Schubert 	signed_connector = os_malloc(peer_connector_len + 1);
874c1d255d3SCy Schubert 	if (!signed_connector)
875c1d255d3SCy Schubert 		goto fail;
876c1d255d3SCy Schubert 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
877c1d255d3SCy Schubert 	signed_connector[peer_connector_len] = '\0';
878c1d255d3SCy Schubert 	res = dpp_process_signed_connector(info, csign, signed_connector);
879c1d255d3SCy Schubert fail:
880c1d255d3SCy Schubert 	os_free(signed_connector);
8814b72b91aSCy Schubert 	crypto_ec_key_deinit(csign);
882c1d255d3SCy Schubert 	return res;
883c1d255d3SCy Schubert }
884c1d255d3SCy Schubert 
885c1d255d3SCy Schubert 
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)886c1d255d3SCy Schubert int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
887c1d255d3SCy Schubert {
888c1d255d3SCy Schubert 	struct wpabuf *pix, *prx, *bix, *brx;
889c1d255d3SCy Schubert 	const u8 *addr[7];
890c1d255d3SCy Schubert 	size_t len[7];
891c1d255d3SCy Schubert 	size_t i, num_elem = 0;
892c1d255d3SCy Schubert 	size_t nonce_len;
893c1d255d3SCy Schubert 	u8 zero = 0;
894c1d255d3SCy Schubert 	int res = -1;
895c1d255d3SCy Schubert 
896c1d255d3SCy Schubert 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
897c1d255d3SCy Schubert 	nonce_len = auth->curve->nonce_len;
898c1d255d3SCy Schubert 
899c1d255d3SCy Schubert 	if (auth->initiator) {
9004b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
9014b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9024b72b91aSCy Schubert 						     0);
903c1d255d3SCy Schubert 		if (auth->own_bi)
9044b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
9054b72b91aSCy Schubert 				auth->own_bi->pubkey, 0);
906c1d255d3SCy Schubert 		else
907c1d255d3SCy Schubert 			bix = NULL;
9084b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
909c1d255d3SCy Schubert 	} else {
9104b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9114b72b91aSCy Schubert 						     0);
9124b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
913c1d255d3SCy Schubert 		if (auth->peer_bi)
9144b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
9154b72b91aSCy Schubert 				auth->peer_bi->pubkey, 0);
916c1d255d3SCy Schubert 		else
917c1d255d3SCy Schubert 			bix = NULL;
9184b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
919c1d255d3SCy Schubert 	}
920c1d255d3SCy Schubert 	if (!pix || !prx || !brx)
921c1d255d3SCy Schubert 		goto fail;
922c1d255d3SCy Schubert 
923c1d255d3SCy Schubert 	addr[num_elem] = auth->i_nonce;
924c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
925c1d255d3SCy Schubert 	num_elem++;
926c1d255d3SCy Schubert 
927c1d255d3SCy Schubert 	addr[num_elem] = auth->r_nonce;
928c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
929c1d255d3SCy Schubert 	num_elem++;
930c1d255d3SCy Schubert 
931c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(pix);
932c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(pix) / 2;
933c1d255d3SCy Schubert 	num_elem++;
934c1d255d3SCy Schubert 
935c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(prx);
936c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(prx) / 2;
937c1d255d3SCy Schubert 	num_elem++;
938c1d255d3SCy Schubert 
939c1d255d3SCy Schubert 	if (bix) {
940c1d255d3SCy Schubert 		addr[num_elem] = wpabuf_head(bix);
941c1d255d3SCy Schubert 		len[num_elem] = wpabuf_len(bix) / 2;
942c1d255d3SCy Schubert 		num_elem++;
943c1d255d3SCy Schubert 	}
944c1d255d3SCy Schubert 
945c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(brx);
946c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(brx) / 2;
947c1d255d3SCy Schubert 	num_elem++;
948c1d255d3SCy Schubert 
949c1d255d3SCy Schubert 	addr[num_elem] = &zero;
950c1d255d3SCy Schubert 	len[num_elem] = 1;
951c1d255d3SCy Schubert 	num_elem++;
952c1d255d3SCy Schubert 
953c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
954c1d255d3SCy Schubert 	for (i = 0; i < num_elem; i++)
955c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
956c1d255d3SCy Schubert 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
957c1d255d3SCy Schubert 	if (res == 0)
958c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
959c1d255d3SCy Schubert 			    auth->curve->hash_len);
960c1d255d3SCy Schubert fail:
961c1d255d3SCy Schubert 	wpabuf_free(pix);
962c1d255d3SCy Schubert 	wpabuf_free(prx);
963c1d255d3SCy Schubert 	wpabuf_free(bix);
964c1d255d3SCy Schubert 	wpabuf_free(brx);
965c1d255d3SCy Schubert 	return res;
966c1d255d3SCy Schubert }
967c1d255d3SCy Schubert 
968c1d255d3SCy Schubert 
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)969c1d255d3SCy Schubert int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
970c1d255d3SCy Schubert {
971c1d255d3SCy Schubert 	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
972c1d255d3SCy Schubert 	const u8 *addr[7];
973c1d255d3SCy Schubert 	size_t len[7];
974c1d255d3SCy Schubert 	size_t i, num_elem = 0;
975c1d255d3SCy Schubert 	size_t nonce_len;
976c1d255d3SCy Schubert 	u8 one = 1;
977c1d255d3SCy Schubert 	int res = -1;
978c1d255d3SCy Schubert 
979c1d255d3SCy Schubert 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
980c1d255d3SCy Schubert 	nonce_len = auth->curve->nonce_len;
981c1d255d3SCy Schubert 
982c1d255d3SCy Schubert 	if (auth->initiator) {
9834b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
9844b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9854b72b91aSCy Schubert 						     0);
986c1d255d3SCy Schubert 		if (auth->own_bi)
9874b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
9884b72b91aSCy Schubert 				auth->own_bi->pubkey, 0);
989c1d255d3SCy Schubert 		else
990c1d255d3SCy Schubert 			bix = NULL;
991c1d255d3SCy Schubert 		if (!auth->peer_bi)
992c1d255d3SCy Schubert 			goto fail;
9934b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
994c1d255d3SCy Schubert 	} else {
9954b72b91aSCy Schubert 		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
9964b72b91aSCy Schubert 						     0);
9974b72b91aSCy Schubert 		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
998c1d255d3SCy Schubert 		if (auth->peer_bi)
9994b72b91aSCy Schubert 			bix = crypto_ec_key_get_pubkey_point(
10004b72b91aSCy Schubert 				auth->peer_bi->pubkey, 0);
1001c1d255d3SCy Schubert 		else
1002c1d255d3SCy Schubert 			bix = NULL;
1003c1d255d3SCy Schubert 		if (!auth->own_bi)
1004c1d255d3SCy Schubert 			goto fail;
10054b72b91aSCy Schubert 		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
1006c1d255d3SCy Schubert 	}
1007c1d255d3SCy Schubert 	if (!pix || !prx || !brx)
1008c1d255d3SCy Schubert 		goto fail;
1009c1d255d3SCy Schubert 
1010c1d255d3SCy Schubert 	addr[num_elem] = auth->r_nonce;
1011c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
1012c1d255d3SCy Schubert 	num_elem++;
1013c1d255d3SCy Schubert 
1014c1d255d3SCy Schubert 	addr[num_elem] = auth->i_nonce;
1015c1d255d3SCy Schubert 	len[num_elem] = nonce_len;
1016c1d255d3SCy Schubert 	num_elem++;
1017c1d255d3SCy Schubert 
1018c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(prx);
1019c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(prx) / 2;
1020c1d255d3SCy Schubert 	num_elem++;
1021c1d255d3SCy Schubert 
1022c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(pix);
1023c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(pix) / 2;
1024c1d255d3SCy Schubert 	num_elem++;
1025c1d255d3SCy Schubert 
1026c1d255d3SCy Schubert 	addr[num_elem] = wpabuf_head(brx);
1027c1d255d3SCy Schubert 	len[num_elem] = wpabuf_len(brx) / 2;
1028c1d255d3SCy Schubert 	num_elem++;
1029c1d255d3SCy Schubert 
1030c1d255d3SCy Schubert 	if (bix) {
1031c1d255d3SCy Schubert 		addr[num_elem] = wpabuf_head(bix);
1032c1d255d3SCy Schubert 		len[num_elem] = wpabuf_len(bix) / 2;
1033c1d255d3SCy Schubert 		num_elem++;
1034c1d255d3SCy Schubert 	}
1035c1d255d3SCy Schubert 
1036c1d255d3SCy Schubert 	addr[num_elem] = &one;
1037c1d255d3SCy Schubert 	len[num_elem] = 1;
1038c1d255d3SCy Schubert 	num_elem++;
1039c1d255d3SCy Schubert 
1040c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1041c1d255d3SCy Schubert 	for (i = 0; i < num_elem; i++)
1042c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1043c1d255d3SCy Schubert 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1044c1d255d3SCy Schubert 	if (res == 0)
1045c1d255d3SCy Schubert 		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1046c1d255d3SCy Schubert 			    auth->curve->hash_len);
1047c1d255d3SCy Schubert fail:
1048c1d255d3SCy Schubert 	wpabuf_free(pix);
1049c1d255d3SCy Schubert 	wpabuf_free(prx);
1050c1d255d3SCy Schubert 	wpabuf_free(bix);
1051c1d255d3SCy Schubert 	wpabuf_free(brx);
1052c1d255d3SCy Schubert 	return res;
1053c1d255d3SCy Schubert }
1054c1d255d3SCy Schubert 
1055c1d255d3SCy Schubert 
dpp_auth_derive_l_responder(struct dpp_authentication * auth)1056c1d255d3SCy Schubert int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1057c1d255d3SCy Schubert {
10584b72b91aSCy Schubert 	struct crypto_ec *ec;
1059*a90b9d01SCy Schubert 	struct crypto_ec_point *L = NULL, *BI = NULL;
1060*a90b9d01SCy Schubert 	const struct crypto_bignum *q;
1061*a90b9d01SCy Schubert 	struct crypto_bignum *sum = NULL, *lx = NULL, *bR = NULL, *pR = NULL;
1062c1d255d3SCy Schubert 	int ret = -1;
1063c1d255d3SCy Schubert 
1064c1d255d3SCy Schubert 	/* L = ((bR + pR) modulo q) * BI */
1065c1d255d3SCy Schubert 
10664b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
10674b72b91aSCy Schubert 	if (!ec)
1068c1d255d3SCy Schubert 		goto fail;
1069c1d255d3SCy Schubert 
10704b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
10714b72b91aSCy Schubert 	BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
10724b72b91aSCy Schubert 	bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
10734b72b91aSCy Schubert 	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
10744b72b91aSCy Schubert 	sum = crypto_bignum_init();
10754b72b91aSCy Schubert 	L = crypto_ec_point_init(ec);
10764b72b91aSCy Schubert 	lx = crypto_bignum_init();
10774b72b91aSCy Schubert 	if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
10784b72b91aSCy Schubert 	    crypto_bignum_addmod(bR, pR, q, sum) ||
10794b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, BI, sum, L) ||
10804b72b91aSCy Schubert 	    crypto_ec_point_x(ec, L, lx) ||
10814b72b91aSCy Schubert 	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
10824b72b91aSCy Schubert 				 auth->secret_len) < 0)
1083c1d255d3SCy Schubert 		goto fail;
1084c1d255d3SCy Schubert 
1085c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1086c1d255d3SCy Schubert 	auth->Lx_len = auth->secret_len;
1087c1d255d3SCy Schubert 	ret = 0;
1088c1d255d3SCy Schubert fail:
10894b72b91aSCy Schubert 	crypto_bignum_deinit(lx, 1);
10904b72b91aSCy Schubert 	crypto_bignum_deinit(sum, 1);
1091*a90b9d01SCy Schubert 	crypto_bignum_deinit(bR, 1);
1092*a90b9d01SCy Schubert 	crypto_bignum_deinit(pR, 1);
10934b72b91aSCy Schubert 	crypto_ec_point_deinit(L, 1);
1094*a90b9d01SCy Schubert 	crypto_ec_point_deinit(BI, 1);
10954b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1096c1d255d3SCy Schubert 	return ret;
1097c1d255d3SCy Schubert }
1098c1d255d3SCy Schubert 
1099c1d255d3SCy Schubert 
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)1100c1d255d3SCy Schubert int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1101c1d255d3SCy Schubert {
11024b72b91aSCy Schubert 	struct crypto_ec *ec;
1103*a90b9d01SCy Schubert 	struct crypto_ec_point *L = NULL, *sum = NULL, *BR = NULL, *PR = NULL;
1104*a90b9d01SCy Schubert 	struct crypto_bignum *lx = NULL, *bI = NULL;
1105c1d255d3SCy Schubert 	int ret = -1;
1106c1d255d3SCy Schubert 
1107c1d255d3SCy Schubert 	/* L = bI * (BR + PR) */
1108c1d255d3SCy Schubert 
11094b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
11104b72b91aSCy Schubert 	if (!ec)
1111c1d255d3SCy Schubert 		goto fail;
1112c1d255d3SCy Schubert 
11134b72b91aSCy Schubert 	BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
11144b72b91aSCy Schubert 	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
11154b72b91aSCy Schubert 	bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
11164b72b91aSCy Schubert 	sum = crypto_ec_point_init(ec);
11174b72b91aSCy Schubert 	L = crypto_ec_point_init(ec);
11184b72b91aSCy Schubert 	lx = crypto_bignum_init();
11194b72b91aSCy Schubert 	if (!BR || !PR || !bI || !sum || !L || !lx ||
11204b72b91aSCy Schubert 	    crypto_ec_point_add(ec, BR, PR, sum) ||
11214b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, sum, bI, L) ||
11224b72b91aSCy Schubert 	    crypto_ec_point_x(ec, L, lx) ||
11234b72b91aSCy Schubert 	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
11244b72b91aSCy Schubert 				 auth->secret_len) < 0)
1125db0ac6deSCy Schubert 		goto fail;
1126db0ac6deSCy Schubert 
1127c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1128c1d255d3SCy Schubert 	auth->Lx_len = auth->secret_len;
1129c1d255d3SCy Schubert 	ret = 0;
1130c1d255d3SCy Schubert fail:
11314b72b91aSCy Schubert 	crypto_bignum_deinit(lx, 1);
1132*a90b9d01SCy Schubert 	crypto_bignum_deinit(bI, 1);
11334b72b91aSCy Schubert 	crypto_ec_point_deinit(sum, 1);
11344b72b91aSCy Schubert 	crypto_ec_point_deinit(L, 1);
1135*a90b9d01SCy Schubert 	crypto_ec_point_deinit(BR, 1);
1136*a90b9d01SCy Schubert 	crypto_ec_point_deinit(PR, 1);
11374b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1138c1d255d3SCy Schubert 	return ret;
1139c1d255d3SCy Schubert }
1140c1d255d3SCy Schubert 
1141c1d255d3SCy Schubert 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)1142c1d255d3SCy Schubert int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1143c1d255d3SCy Schubert {
1144c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1145c1d255d3SCy Schubert 	const char *info = "DPP PMK";
1146c1d255d3SCy Schubert 	int res;
1147c1d255d3SCy Schubert 
1148c1d255d3SCy Schubert 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
1149c1d255d3SCy Schubert 
1150c1d255d3SCy Schubert 	/* HKDF-Extract(<>, N.x) */
1151c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
1152c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1153c1d255d3SCy Schubert 		return -1;
1154c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1155c1d255d3SCy Schubert 			prk, hash_len);
1156c1d255d3SCy Schubert 
1157c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
1158c1d255d3SCy Schubert 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1159c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
1160c1d255d3SCy Schubert 	if (res < 0)
1161c1d255d3SCy Schubert 		return -1;
1162c1d255d3SCy Schubert 
1163c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1164c1d255d3SCy Schubert 			pmk, hash_len);
1165c1d255d3SCy Schubert 	return 0;
1166c1d255d3SCy Schubert }
1167c1d255d3SCy Schubert 
1168c1d255d3SCy Schubert 
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_ec_key * own_key,struct crypto_ec_key * peer_key,u8 * pmkid)1169c1d255d3SCy Schubert int dpp_derive_pmkid(const struct dpp_curve_params *curve,
11704b72b91aSCy Schubert 		     struct crypto_ec_key *own_key,
11714b72b91aSCy Schubert 		     struct crypto_ec_key *peer_key, u8 *pmkid)
1172c1d255d3SCy Schubert {
1173c1d255d3SCy Schubert 	struct wpabuf *nkx, *pkx;
1174c1d255d3SCy Schubert 	int ret = -1, res;
1175c1d255d3SCy Schubert 	const u8 *addr[2];
1176c1d255d3SCy Schubert 	size_t len[2];
1177c1d255d3SCy Schubert 	u8 hash[SHA256_MAC_LEN];
1178c1d255d3SCy Schubert 
1179c1d255d3SCy Schubert 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
11804b72b91aSCy Schubert 	nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
11814b72b91aSCy Schubert 	pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
1182c1d255d3SCy Schubert 	if (!nkx || !pkx)
1183c1d255d3SCy Schubert 		goto fail;
1184c1d255d3SCy Schubert 	addr[0] = wpabuf_head(nkx);
1185c1d255d3SCy Schubert 	len[0] = wpabuf_len(nkx) / 2;
1186c1d255d3SCy Schubert 	addr[1] = wpabuf_head(pkx);
1187c1d255d3SCy Schubert 	len[1] = wpabuf_len(pkx) / 2;
1188c1d255d3SCy Schubert 	if (len[0] != len[1])
1189c1d255d3SCy Schubert 		goto fail;
1190c1d255d3SCy Schubert 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1191c1d255d3SCy Schubert 		addr[0] = wpabuf_head(pkx);
1192c1d255d3SCy Schubert 		addr[1] = wpabuf_head(nkx);
1193c1d255d3SCy Schubert 	}
1194c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1195c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1196c1d255d3SCy Schubert 	res = sha256_vector(2, addr, len, hash);
1197c1d255d3SCy Schubert 	if (res < 0)
1198c1d255d3SCy Schubert 		goto fail;
1199c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1200c1d255d3SCy Schubert 	os_memcpy(pmkid, hash, PMKID_LEN);
1201c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1202c1d255d3SCy Schubert 	ret = 0;
1203c1d255d3SCy Schubert fail:
1204c1d255d3SCy Schubert 	wpabuf_free(nkx);
1205c1d255d3SCy Schubert 	wpabuf_free(pkx);
1206c1d255d3SCy Schubert 	return ret;
1207c1d255d3SCy Schubert }
1208c1d255d3SCy Schubert 
1209c1d255d3SCy Schubert 
1210c1d255d3SCy Schubert /* Role-specific elements for PKEX */
1211c1d255d3SCy Schubert 
1212c1d255d3SCy Schubert /* NIST P-256 */
1213c1d255d3SCy Schubert static const u8 pkex_init_x_p256[32] = {
1214c1d255d3SCy Schubert 	0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1215c1d255d3SCy Schubert 	0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1216c1d255d3SCy Schubert 	0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1217c1d255d3SCy Schubert 	0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1218c1d255d3SCy Schubert  };
1219c1d255d3SCy Schubert static const u8 pkex_init_y_p256[32] = {
1220c1d255d3SCy Schubert 	0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1221c1d255d3SCy Schubert 	0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1222c1d255d3SCy Schubert 	0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1223c1d255d3SCy Schubert 	0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1224c1d255d3SCy Schubert  };
1225c1d255d3SCy Schubert static const u8 pkex_resp_x_p256[32] = {
1226c1d255d3SCy Schubert 	0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1227c1d255d3SCy Schubert 	0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1228c1d255d3SCy Schubert 	0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1229c1d255d3SCy Schubert 	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1230c1d255d3SCy Schubert };
1231c1d255d3SCy Schubert static const u8 pkex_resp_y_p256[32] = {
1232c1d255d3SCy Schubert 	0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1233c1d255d3SCy Schubert 	0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1234c1d255d3SCy Schubert 	0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1235c1d255d3SCy Schubert 	0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1236c1d255d3SCy Schubert };
1237c1d255d3SCy Schubert 
1238c1d255d3SCy Schubert /* NIST P-384 */
1239c1d255d3SCy Schubert static const u8 pkex_init_x_p384[48] = {
1240c1d255d3SCy Schubert 	0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1241c1d255d3SCy Schubert 	0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1242c1d255d3SCy Schubert 	0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1243c1d255d3SCy Schubert 	0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1244c1d255d3SCy Schubert 	0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1245c1d255d3SCy Schubert 	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1246c1d255d3SCy Schubert };
1247c1d255d3SCy Schubert static const u8 pkex_init_y_p384[48] = {
1248c1d255d3SCy Schubert 	0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1249c1d255d3SCy Schubert 	0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1250c1d255d3SCy Schubert 	0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1251c1d255d3SCy Schubert 	0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1252c1d255d3SCy Schubert 	0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1253c1d255d3SCy Schubert 	0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1254c1d255d3SCy Schubert };
1255c1d255d3SCy Schubert static const u8 pkex_resp_x_p384[48] = {
1256c1d255d3SCy Schubert 	0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1257c1d255d3SCy Schubert 	0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1258c1d255d3SCy Schubert 	0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1259c1d255d3SCy Schubert 	0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1260c1d255d3SCy Schubert 	0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1261c1d255d3SCy Schubert 	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1262c1d255d3SCy Schubert };
1263c1d255d3SCy Schubert static const u8 pkex_resp_y_p384[48] = {
1264c1d255d3SCy Schubert 	0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1265c1d255d3SCy Schubert 	0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1266c1d255d3SCy Schubert 	0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1267c1d255d3SCy Schubert 	0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1268c1d255d3SCy Schubert 	0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1269c1d255d3SCy Schubert 	0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1270c1d255d3SCy Schubert };
1271c1d255d3SCy Schubert 
1272c1d255d3SCy Schubert /* NIST P-521 */
1273c1d255d3SCy Schubert static const u8 pkex_init_x_p521[66] = {
1274c1d255d3SCy Schubert 	0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1275c1d255d3SCy Schubert 	0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1276c1d255d3SCy Schubert 	0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1277c1d255d3SCy Schubert 	0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1278c1d255d3SCy Schubert 	0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1279c1d255d3SCy Schubert 	0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1280c1d255d3SCy Schubert 	0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1281c1d255d3SCy Schubert 	0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1282c1d255d3SCy Schubert 	0x97, 0x76
1283c1d255d3SCy Schubert };
1284c1d255d3SCy Schubert static const u8 pkex_init_y_p521[66] = {
1285c1d255d3SCy Schubert 	0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1286c1d255d3SCy Schubert 	0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1287c1d255d3SCy Schubert 	0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1288c1d255d3SCy Schubert 	0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1289c1d255d3SCy Schubert 	0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1290c1d255d3SCy Schubert 	0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1291c1d255d3SCy Schubert 	0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1292c1d255d3SCy Schubert 	0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1293c1d255d3SCy Schubert 	0x03, 0xa8
1294c1d255d3SCy Schubert };
1295c1d255d3SCy Schubert static const u8 pkex_resp_x_p521[66] = {
1296c1d255d3SCy Schubert 	0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1297c1d255d3SCy Schubert 	0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1298c1d255d3SCy Schubert 	0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1299c1d255d3SCy Schubert 	0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1300c1d255d3SCy Schubert 	0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1301c1d255d3SCy Schubert 	0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1302c1d255d3SCy Schubert 	0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1303c1d255d3SCy Schubert 	0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1304c1d255d3SCy Schubert 	0x84, 0xb4
1305c1d255d3SCy Schubert };
1306c1d255d3SCy Schubert static const u8 pkex_resp_y_p521[66] = {
1307c1d255d3SCy Schubert 	0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1308c1d255d3SCy Schubert 	0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1309c1d255d3SCy Schubert 	0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1310c1d255d3SCy Schubert 	0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1311c1d255d3SCy Schubert 	0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1312c1d255d3SCy Schubert 	0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1313c1d255d3SCy Schubert 	0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1314c1d255d3SCy Schubert 	0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1315c1d255d3SCy Schubert 	0xce, 0xe1
1316c1d255d3SCy Schubert };
1317c1d255d3SCy Schubert 
1318c1d255d3SCy Schubert /* Brainpool P-256r1 */
1319c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p256r1[32] = {
1320c1d255d3SCy Schubert 	0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1321c1d255d3SCy Schubert 	0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1322c1d255d3SCy Schubert 	0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1323c1d255d3SCy Schubert 	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1324c1d255d3SCy Schubert };
1325c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p256r1[32] = {
1326c1d255d3SCy Schubert 	0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1327c1d255d3SCy Schubert 	0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1328c1d255d3SCy Schubert 	0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1329c1d255d3SCy Schubert 	0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1330c1d255d3SCy Schubert };
1331c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p256r1[32] = {
1332c1d255d3SCy Schubert 	0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1333c1d255d3SCy Schubert 	0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1334c1d255d3SCy Schubert 	0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1335c1d255d3SCy Schubert 	0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1336c1d255d3SCy Schubert };
1337c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p256r1[32] = {
1338c1d255d3SCy Schubert 	0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1339c1d255d3SCy Schubert 	0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1340c1d255d3SCy Schubert 	0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1341c1d255d3SCy Schubert 	0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1342c1d255d3SCy Schubert };
1343c1d255d3SCy Schubert 
1344c1d255d3SCy Schubert /* Brainpool P-384r1 */
1345c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p384r1[48] = {
1346c1d255d3SCy Schubert 	0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1347c1d255d3SCy Schubert 	0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1348c1d255d3SCy Schubert 	0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1349c1d255d3SCy Schubert 	0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1350c1d255d3SCy Schubert 	0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1351c1d255d3SCy Schubert 	0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1352c1d255d3SCy Schubert };
1353c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p384r1[48] = {
1354c1d255d3SCy Schubert 	0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1355c1d255d3SCy Schubert 	0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1356c1d255d3SCy Schubert 	0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1357c1d255d3SCy Schubert 	0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1358c1d255d3SCy Schubert 	0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1359c1d255d3SCy Schubert 	0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1360c1d255d3SCy Schubert };
1361c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p384r1[48] = {
1362c1d255d3SCy Schubert 	0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1363c1d255d3SCy Schubert 	0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1364c1d255d3SCy Schubert 	0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1365c1d255d3SCy Schubert 	0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1366c1d255d3SCy Schubert 	0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1367c1d255d3SCy Schubert 	0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1368c1d255d3SCy Schubert };
1369c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p384r1[48] = {
1370c1d255d3SCy Schubert 	0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1371c1d255d3SCy Schubert 	0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1372c1d255d3SCy Schubert 	0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1373c1d255d3SCy Schubert 	0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1374c1d255d3SCy Schubert 	0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1375c1d255d3SCy Schubert 	0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1376c1d255d3SCy Schubert };
1377c1d255d3SCy Schubert 
1378c1d255d3SCy Schubert /* Brainpool P-512r1 */
1379c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p512r1[64] = {
1380c1d255d3SCy Schubert 	0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1381c1d255d3SCy Schubert 	0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1382c1d255d3SCy Schubert 	0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1383c1d255d3SCy Schubert 	0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1384c1d255d3SCy Schubert 	0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1385c1d255d3SCy Schubert 	0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1386c1d255d3SCy Schubert 	0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1387c1d255d3SCy Schubert 	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1388c1d255d3SCy Schubert };
1389c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p512r1[64] = {
1390c1d255d3SCy Schubert 	0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1391c1d255d3SCy Schubert 	0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1392c1d255d3SCy Schubert 	0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1393c1d255d3SCy Schubert 	0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1394c1d255d3SCy Schubert 	0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1395c1d255d3SCy Schubert 	0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1396c1d255d3SCy Schubert 	0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1397c1d255d3SCy Schubert 	0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1398c1d255d3SCy Schubert };
1399c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p512r1[64] = {
1400c1d255d3SCy Schubert 	0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1401c1d255d3SCy Schubert 	0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1402c1d255d3SCy Schubert 	0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1403c1d255d3SCy Schubert 	0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1404c1d255d3SCy Schubert 	0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1405c1d255d3SCy Schubert 	0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1406c1d255d3SCy Schubert 	0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1407c1d255d3SCy Schubert 	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1408c1d255d3SCy Schubert };
1409c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p512r1[64] = {
1410c1d255d3SCy Schubert 	0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1411c1d255d3SCy Schubert 	0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1412c1d255d3SCy Schubert 	0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1413c1d255d3SCy Schubert 	0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1414c1d255d3SCy Schubert 	0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1415c1d255d3SCy Schubert 	0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1416c1d255d3SCy Schubert 	0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1417c1d255d3SCy Schubert 	0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1418c1d255d3SCy Schubert };
1419c1d255d3SCy Schubert 
1420c1d255d3SCy Schubert 
14214b72b91aSCy Schubert static struct crypto_ec_key *
dpp_pkex_get_role_elem(const struct dpp_curve_params * curve,int init)14224b72b91aSCy Schubert dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
1423c1d255d3SCy Schubert {
1424c1d255d3SCy Schubert 	const u8 *x, *y;
1425c1d255d3SCy Schubert 
1426c1d255d3SCy Schubert 	switch (curve->ike_group) {
1427c1d255d3SCy Schubert 	case 19:
1428c1d255d3SCy Schubert 		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1429c1d255d3SCy Schubert 		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1430c1d255d3SCy Schubert 		break;
1431c1d255d3SCy Schubert 	case 20:
1432c1d255d3SCy Schubert 		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1433c1d255d3SCy Schubert 		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1434c1d255d3SCy Schubert 		break;
1435c1d255d3SCy Schubert 	case 21:
1436c1d255d3SCy Schubert 		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1437c1d255d3SCy Schubert 		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1438c1d255d3SCy Schubert 		break;
1439c1d255d3SCy Schubert 	case 28:
1440c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1441c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1442c1d255d3SCy Schubert 		break;
1443c1d255d3SCy Schubert 	case 29:
1444c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1445c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1446c1d255d3SCy Schubert 		break;
1447c1d255d3SCy Schubert 	case 30:
1448c1d255d3SCy Schubert 		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1449c1d255d3SCy Schubert 		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1450c1d255d3SCy Schubert 		break;
1451c1d255d3SCy Schubert 	default:
1452c1d255d3SCy Schubert 		return NULL;
1453c1d255d3SCy Schubert 	}
1454c1d255d3SCy Schubert 
14554b72b91aSCy Schubert 	return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
1456c1d255d3SCy Schubert }
1457c1d255d3SCy Schubert 
1458c1d255d3SCy Schubert 
14594b72b91aSCy Schubert struct crypto_ec_point *
dpp_pkex_derive_Qi(const struct dpp_curve_params * curve,const u8 * mac_init,const char * code,size_t code_len,const char * identifier,struct crypto_ec ** ret_ec)14604b72b91aSCy Schubert dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
1461*a90b9d01SCy Schubert 		   const char *code, size_t code_len, const char *identifier,
14624b72b91aSCy Schubert 		   struct crypto_ec **ret_ec)
1463c1d255d3SCy Schubert {
1464c1d255d3SCy Schubert 	u8 hash[DPP_MAX_HASH_LEN];
1465c1d255d3SCy Schubert 	const u8 *addr[3];
1466c1d255d3SCy Schubert 	size_t len[3];
1467c1d255d3SCy Schubert 	unsigned int num_elem = 0;
1468*a90b9d01SCy Schubert 	struct crypto_ec_point *Qi = NULL, *Pi = NULL;
14694b72b91aSCy Schubert 	struct crypto_ec_key *Pi_key = NULL;
14704b72b91aSCy Schubert 	struct crypto_bignum *hash_bn = NULL;
14714b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1472c1d255d3SCy Schubert 
147332a95656SCy Schubert 	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
1474c1d255d3SCy Schubert 
147532a95656SCy Schubert 	if (mac_init) {
147632a95656SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
147732a95656SCy Schubert 			   MAC2STR(mac_init));
1478c1d255d3SCy Schubert 		addr[num_elem] = mac_init;
1479c1d255d3SCy Schubert 		len[num_elem] = ETH_ALEN;
1480c1d255d3SCy Schubert 		num_elem++;
148132a95656SCy Schubert 	}
1482c1d255d3SCy Schubert 	if (identifier) {
1483c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1484c1d255d3SCy Schubert 			   identifier);
1485c1d255d3SCy Schubert 		addr[num_elem] = (const u8 *) identifier;
1486c1d255d3SCy Schubert 		len[num_elem] = os_strlen(identifier);
1487c1d255d3SCy Schubert 		num_elem++;
1488c1d255d3SCy Schubert 	}
1489*a90b9d01SCy Schubert 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1490c1d255d3SCy Schubert 	addr[num_elem] = (const u8 *) code;
1491*a90b9d01SCy Schubert 	len[num_elem] = code_len;
1492c1d255d3SCy Schubert 	num_elem++;
1493c1d255d3SCy Schubert 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1494c1d255d3SCy Schubert 		goto fail;
1495c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
149632a95656SCy Schubert 			"DPP: H([MAC-Initiator |] [identifier |] code)",
1497c1d255d3SCy Schubert 			hash, curve->hash_len);
14984b72b91aSCy Schubert 	Pi_key = dpp_pkex_get_role_elem(curve, 1);
14994b72b91aSCy Schubert 	if (!Pi_key)
1500c1d255d3SCy Schubert 		goto fail;
15014b72b91aSCy Schubert 	dpp_debug_print_key("DPP: Pi", Pi_key);
1502266f97b5SCy Schubert 
15034b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
15044b72b91aSCy Schubert 	if (!ec)
1505c1d255d3SCy Schubert 		goto fail;
15064b72b91aSCy Schubert 
15074b72b91aSCy Schubert 	Pi = crypto_ec_key_get_public_key(Pi_key);
15084b72b91aSCy Schubert 	Qi = crypto_ec_point_init(ec);
15094b72b91aSCy Schubert 	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
15104b72b91aSCy Schubert 	if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
1511db0ac6deSCy Schubert 		goto fail;
15124b72b91aSCy Schubert 
15134b72b91aSCy Schubert 	if (crypto_ec_point_is_at_infinity(ec, Qi)) {
1514c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1515c1d255d3SCy Schubert 		goto fail;
1516c1d255d3SCy Schubert 	}
15174b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
1518c1d255d3SCy Schubert out:
15194b72b91aSCy Schubert 	crypto_ec_key_deinit(Pi_key);
1520*a90b9d01SCy Schubert 	crypto_ec_point_deinit(Pi, 1);
15214b72b91aSCy Schubert 	crypto_bignum_deinit(hash_bn, 1);
15224b72b91aSCy Schubert 	if (ret_ec && Qi)
15234b72b91aSCy Schubert 		*ret_ec = ec;
1524c1d255d3SCy Schubert 	else
15254b72b91aSCy Schubert 		crypto_ec_deinit(ec);
1526c1d255d3SCy Schubert 	return Qi;
1527c1d255d3SCy Schubert fail:
15284b72b91aSCy Schubert 	crypto_ec_point_deinit(Qi, 1);
1529c1d255d3SCy Schubert 	Qi = NULL;
1530c1d255d3SCy Schubert 	goto out;
1531c1d255d3SCy Schubert }
1532c1d255d3SCy Schubert 
1533c1d255d3SCy Schubert 
15344b72b91aSCy Schubert struct crypto_ec_point *
dpp_pkex_derive_Qr(const struct dpp_curve_params * curve,const u8 * mac_resp,const char * code,size_t code_len,const char * identifier,struct crypto_ec ** ret_ec)15354b72b91aSCy Schubert dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
1536*a90b9d01SCy Schubert 		   const char *code, size_t code_len, const char *identifier,
15374b72b91aSCy Schubert 		   struct crypto_ec **ret_ec)
1538c1d255d3SCy Schubert {
1539c1d255d3SCy Schubert 	u8 hash[DPP_MAX_HASH_LEN];
1540c1d255d3SCy Schubert 	const u8 *addr[3];
1541c1d255d3SCy Schubert 	size_t len[3];
1542c1d255d3SCy Schubert 	unsigned int num_elem = 0;
1543*a90b9d01SCy Schubert 	struct crypto_ec_point *Qr = NULL, *Pr = NULL;
15444b72b91aSCy Schubert 	struct crypto_ec_key *Pr_key = NULL;
15454b72b91aSCy Schubert 	struct crypto_bignum *hash_bn = NULL;
15464b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1547c1d255d3SCy Schubert 
154832a95656SCy Schubert 	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
1549c1d255d3SCy Schubert 
155032a95656SCy Schubert 	if (mac_resp) {
155132a95656SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
155232a95656SCy Schubert 			   MAC2STR(mac_resp));
1553c1d255d3SCy Schubert 		addr[num_elem] = mac_resp;
1554c1d255d3SCy Schubert 		len[num_elem] = ETH_ALEN;
1555c1d255d3SCy Schubert 		num_elem++;
155632a95656SCy Schubert 	}
1557c1d255d3SCy Schubert 	if (identifier) {
1558c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1559c1d255d3SCy Schubert 			   identifier);
1560c1d255d3SCy Schubert 		addr[num_elem] = (const u8 *) identifier;
1561c1d255d3SCy Schubert 		len[num_elem] = os_strlen(identifier);
1562c1d255d3SCy Schubert 		num_elem++;
1563c1d255d3SCy Schubert 	}
1564*a90b9d01SCy Schubert 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1565c1d255d3SCy Schubert 	addr[num_elem] = (const u8 *) code;
1566*a90b9d01SCy Schubert 	len[num_elem] = code_len;
1567c1d255d3SCy Schubert 	num_elem++;
1568c1d255d3SCy Schubert 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1569c1d255d3SCy Schubert 		goto fail;
1570c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
157132a95656SCy Schubert 			"DPP: H([MAC-Responder |] [identifier |] code)",
1572c1d255d3SCy Schubert 			hash, curve->hash_len);
15734b72b91aSCy Schubert 	Pr_key = dpp_pkex_get_role_elem(curve, 0);
15744b72b91aSCy Schubert 	if (!Pr_key)
1575c1d255d3SCy Schubert 		goto fail;
15764b72b91aSCy Schubert 	dpp_debug_print_key("DPP: Pr", Pr_key);
1577266f97b5SCy Schubert 
15784b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
15794b72b91aSCy Schubert 	if (!ec)
1580c1d255d3SCy Schubert 		goto fail;
15814b72b91aSCy Schubert 
15824b72b91aSCy Schubert 	Pr = crypto_ec_key_get_public_key(Pr_key);
15834b72b91aSCy Schubert 	Qr = crypto_ec_point_init(ec);
15844b72b91aSCy Schubert 	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
15854b72b91aSCy Schubert 	if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
1586db0ac6deSCy Schubert 		goto fail;
15874b72b91aSCy Schubert 
15884b72b91aSCy Schubert 	if (crypto_ec_point_is_at_infinity(ec, Qr)) {
1589c1d255d3SCy Schubert 		wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1590c1d255d3SCy Schubert 		goto fail;
1591c1d255d3SCy Schubert 	}
15924b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
15934b72b91aSCy Schubert 
1594c1d255d3SCy Schubert out:
15954b72b91aSCy Schubert 	crypto_ec_key_deinit(Pr_key);
1596*a90b9d01SCy Schubert 	crypto_ec_point_deinit(Pr, 1);
15974b72b91aSCy Schubert 	crypto_bignum_deinit(hash_bn, 1);
15984b72b91aSCy Schubert 	if (ret_ec && Qr)
15994b72b91aSCy Schubert 		*ret_ec = ec;
1600c1d255d3SCy Schubert 	else
16014b72b91aSCy Schubert 		crypto_ec_deinit(ec);
1602c1d255d3SCy Schubert 	return Qr;
1603c1d255d3SCy Schubert fail:
16044b72b91aSCy Schubert 	crypto_ec_point_deinit(Qr, 1);
1605c1d255d3SCy Schubert 	Qr = NULL;
1606c1d255d3SCy Schubert 	goto out;
1607c1d255d3SCy Schubert }
1608c1d255d3SCy Schubert 
1609c1d255d3SCy Schubert 
dpp_pkex_derive_z(const u8 * mac_init,const u8 * mac_resp,u8 ver_init,u8 ver_resp,const u8 * Mx,size_t Mx_len,const u8 * Nx,size_t Nx_len,const char * code,size_t code_len,const u8 * Kx,size_t Kx_len,u8 * z,unsigned int hash_len)1610c1d255d3SCy Schubert int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
161132a95656SCy Schubert 		      u8 ver_init, u8 ver_resp,
1612c1d255d3SCy Schubert 		      const u8 *Mx, size_t Mx_len,
1613c1d255d3SCy Schubert 		      const u8 *Nx, size_t Nx_len,
1614*a90b9d01SCy Schubert 		      const char *code, size_t code_len,
1615c1d255d3SCy Schubert 		      const u8 *Kx, size_t Kx_len,
1616c1d255d3SCy Schubert 		      u8 *z, unsigned int hash_len)
1617c1d255d3SCy Schubert {
1618c1d255d3SCy Schubert 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1619c1d255d3SCy Schubert 	int res;
1620c1d255d3SCy Schubert 	u8 *info, *pos;
1621c1d255d3SCy Schubert 	size_t info_len;
1622c1d255d3SCy Schubert 
162332a95656SCy Schubert 	/*
162432a95656SCy Schubert 	 * v1: info = MAC-Initiator | MAC-Responder
162532a95656SCy Schubert 	 * v2: info = Protocol Version-Initiator | Protocol Version-Responder
162632a95656SCy Schubert 	 * z = HKDF(<>, info | M.x | N.x | code, K.x)
1627c1d255d3SCy Schubert 	 */
1628c1d255d3SCy Schubert 
1629c1d255d3SCy Schubert 	/* HKDF-Extract(<>, IKM=K.x) */
1630c1d255d3SCy Schubert 	os_memset(salt, 0, hash_len);
1631c1d255d3SCy Schubert 	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1632c1d255d3SCy Schubert 		return -1;
1633c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1634c1d255d3SCy Schubert 			prk, hash_len);
163532a95656SCy Schubert 	if (mac_init && mac_resp)
163632a95656SCy Schubert 		info_len = 2 * ETH_ALEN;
163732a95656SCy Schubert 	else
163832a95656SCy Schubert 		info_len = 2;
1639*a90b9d01SCy Schubert 	info_len += Mx_len + Nx_len + code_len;
1640c1d255d3SCy Schubert 	info = os_malloc(info_len);
1641c1d255d3SCy Schubert 	if (!info)
1642c1d255d3SCy Schubert 		return -1;
1643c1d255d3SCy Schubert 	pos = info;
164432a95656SCy Schubert 	if (mac_init && mac_resp) {
1645c1d255d3SCy Schubert 		os_memcpy(pos, mac_init, ETH_ALEN);
1646c1d255d3SCy Schubert 		pos += ETH_ALEN;
1647c1d255d3SCy Schubert 		os_memcpy(pos, mac_resp, ETH_ALEN);
1648c1d255d3SCy Schubert 		pos += ETH_ALEN;
164932a95656SCy Schubert 	} else {
165032a95656SCy Schubert 		*pos++ = ver_init;
165132a95656SCy Schubert 		*pos++ = ver_resp;
165232a95656SCy Schubert 	}
1653c1d255d3SCy Schubert 	os_memcpy(pos, Mx, Mx_len);
1654c1d255d3SCy Schubert 	pos += Mx_len;
1655c1d255d3SCy Schubert 	os_memcpy(pos, Nx, Nx_len);
1656c1d255d3SCy Schubert 	pos += Nx_len;
1657*a90b9d01SCy Schubert 	os_memcpy(pos, code, code_len);
1658c1d255d3SCy Schubert 
1659c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, info, L) */
1660c1d255d3SCy Schubert 	if (hash_len == 32)
1661c1d255d3SCy Schubert 		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1662c1d255d3SCy Schubert 				      z, hash_len);
1663c1d255d3SCy Schubert 	else if (hash_len == 48)
1664c1d255d3SCy Schubert 		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1665c1d255d3SCy Schubert 				      z, hash_len);
1666c1d255d3SCy Schubert 	else if (hash_len == 64)
1667c1d255d3SCy Schubert 		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1668c1d255d3SCy Schubert 				      z, hash_len);
1669c1d255d3SCy Schubert 	else
1670c1d255d3SCy Schubert 		res = -1;
1671c1d255d3SCy Schubert 	os_free(info);
1672c1d255d3SCy Schubert 	os_memset(prk, 0, hash_len);
1673c1d255d3SCy Schubert 	if (res < 0)
1674c1d255d3SCy Schubert 		return -1;
1675c1d255d3SCy Schubert 
1676c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1677c1d255d3SCy Schubert 			z, hash_len);
1678c1d255d3SCy Schubert 	return 0;
1679c1d255d3SCy Schubert }
1680c1d255d3SCy Schubert 
1681c1d255d3SCy Schubert 
dpp_reconfig_derive_ke_responder(struct dpp_authentication * auth,const u8 * net_access_key,size_t net_access_key_len,struct json_token * peer_net_access_key)1682c1d255d3SCy Schubert int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1683c1d255d3SCy Schubert 				     const u8 *net_access_key,
1684c1d255d3SCy Schubert 				     size_t net_access_key_len,
1685c1d255d3SCy Schubert 				     struct json_token *peer_net_access_key)
1686c1d255d3SCy Schubert {
16874b72b91aSCy Schubert 	struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
1688*a90b9d01SCy Schubert 	struct crypto_bignum *sum = NULL, *cR = NULL, *pR = NULL;
1689*a90b9d01SCy Schubert 	const struct crypto_bignum *q;
16904b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1691*a90b9d01SCy Schubert 	struct crypto_ec_point *M = NULL, *CI = NULL;
1692c1d255d3SCy Schubert 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1693c1d255d3SCy Schubert 	u8 prk[DPP_MAX_HASH_LEN];
1694c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
1695c1d255d3SCy Schubert 	int res = -1;
1696c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
1697c1d255d3SCy Schubert 
1698c1d255d3SCy Schubert 	own_key = dpp_set_keypair(&auth->curve, net_access_key,
1699c1d255d3SCy Schubert 				  net_access_key_len);
1700c1d255d3SCy Schubert 	if (!own_key) {
1701c1d255d3SCy Schubert 		dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1702c1d255d3SCy Schubert 		goto fail;
1703c1d255d3SCy Schubert 	}
1704c1d255d3SCy Schubert 
1705c1d255d3SCy Schubert 	peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1706c1d255d3SCy Schubert 	if (!peer_key)
1707c1d255d3SCy Schubert 		goto fail;
1708c1d255d3SCy Schubert 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1709c1d255d3SCy Schubert 
1710c1d255d3SCy Schubert 	if (auth->curve != curve) {
1711c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
1712c1d255d3SCy Schubert 			   "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1713c1d255d3SCy Schubert 			   auth->curve->name, curve->name);
1714c1d255d3SCy Schubert 		goto fail;
1715c1d255d3SCy Schubert 	}
1716c1d255d3SCy Schubert 
1717c1d255d3SCy Schubert 	auth->own_protocol_key = dpp_gen_keypair(curve);
1718c1d255d3SCy Schubert 	if (!auth->own_protocol_key)
1719c1d255d3SCy Schubert 		goto fail;
1720c1d255d3SCy Schubert 
1721c1d255d3SCy Schubert 	if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1722c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1723c1d255d3SCy Schubert 		goto fail;
1724c1d255d3SCy Schubert 	}
1725c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1726c1d255d3SCy Schubert 			auth->e_nonce, auth->curve->nonce_len);
1727c1d255d3SCy Schubert 
1728c1d255d3SCy Schubert 	/* M = { cR + pR } * CI */
17294b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
17304b72b91aSCy Schubert 	if (!ec)
1731c1d255d3SCy Schubert 		goto fail;
17324b72b91aSCy Schubert 
17334b72b91aSCy Schubert 	sum = crypto_bignum_init();
17344b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
17354b72b91aSCy Schubert 	M = crypto_ec_point_init(ec);
17364b72b91aSCy Schubert 	cR = crypto_ec_key_get_private_key(own_key);
17374b72b91aSCy Schubert 	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
17384b72b91aSCy Schubert 	CI = crypto_ec_key_get_public_key(peer_key);
17394b72b91aSCy Schubert 	if (!sum || !q || !M || !cR || !pR || !CI ||
17404b72b91aSCy Schubert 	    crypto_bignum_addmod(cR, pR, q, sum) ||
17414b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, CI, sum, M) ||
17424b72b91aSCy Schubert 	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
17434b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1744c1d255d3SCy Schubert 		goto fail;
1745c1d255d3SCy Schubert 	}
1746c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1747c1d255d3SCy Schubert 
1748c1d255d3SCy Schubert 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1749c1d255d3SCy Schubert 
1750c1d255d3SCy Schubert 	/* HKDF-Extract(C-nonce | E-nonce, M.x) */
1751c1d255d3SCy Schubert 	os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1752c1d255d3SCy Schubert 	os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1753c1d255d3SCy Schubert 	if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1754c1d255d3SCy Schubert 		     Mx, curve->prime_len, prk) < 0)
1755c1d255d3SCy Schubert 		goto fail;
1756c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1757c1d255d3SCy Schubert 
1758c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, "dpp reconfig key", L) */
1759c1d255d3SCy Schubert 	if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1760c1d255d3SCy Schubert 			    "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1761c1d255d3SCy Schubert 		goto fail;
1762c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1763c1d255d3SCy Schubert 			"DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1764c1d255d3SCy Schubert 			auth->ke, curve->hash_len);
1765c1d255d3SCy Schubert 
1766c1d255d3SCy Schubert 	res = 0;
17674b72b91aSCy Schubert 	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1768c1d255d3SCy Schubert 	auth->reconfig_old_protocol_key = own_key;
1769c1d255d3SCy Schubert 	own_key = NULL;
1770c1d255d3SCy Schubert fail:
1771c1d255d3SCy Schubert 	forced_memzero(prk, sizeof(prk));
1772c1d255d3SCy Schubert 	forced_memzero(Mx, sizeof(Mx));
17734b72b91aSCy Schubert 	crypto_ec_point_deinit(M, 1);
1774*a90b9d01SCy Schubert 	crypto_ec_point_deinit(CI, 1);
17754b72b91aSCy Schubert 	crypto_bignum_deinit(sum, 1);
1776*a90b9d01SCy Schubert 	crypto_bignum_deinit(cR, 1);
1777*a90b9d01SCy Schubert 	crypto_bignum_deinit(pR, 1);
17784b72b91aSCy Schubert 	crypto_ec_key_deinit(own_key);
17794b72b91aSCy Schubert 	crypto_ec_key_deinit(peer_key);
17804b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1781c1d255d3SCy Schubert 	return res;
1782c1d255d3SCy Schubert }
1783c1d255d3SCy Schubert 
1784c1d255d3SCy Schubert 
dpp_reconfig_derive_ke_initiator(struct dpp_authentication * auth,const u8 * r_proto,u16 r_proto_len,struct json_token * net_access_key)1785c1d255d3SCy Schubert int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1786c1d255d3SCy Schubert 				     const u8 *r_proto, u16 r_proto_len,
1787c1d255d3SCy Schubert 				     struct json_token *net_access_key)
1788c1d255d3SCy Schubert {
17894b72b91aSCy Schubert 	struct crypto_ec_key *pr = NULL, *peer_key = NULL;
1790*a90b9d01SCy Schubert 	struct crypto_bignum *cI = NULL;
17914b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
1792*a90b9d01SCy Schubert 	struct crypto_ec_point *sum = NULL, *M = NULL, *CR = NULL, *PR = NULL;
1793c1d255d3SCy Schubert 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1794c1d255d3SCy Schubert 	u8 prk[DPP_MAX_HASH_LEN];
1795c1d255d3SCy Schubert 	int res = -1;
1796c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
1797c1d255d3SCy Schubert 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
1798c1d255d3SCy Schubert 
1799c1d255d3SCy Schubert 	pr = dpp_set_pubkey_point(auth->conf->connector_key,
1800c1d255d3SCy Schubert 				  r_proto, r_proto_len);
1801c1d255d3SCy Schubert 	if (!pr) {
1802c1d255d3SCy Schubert 		dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1803c1d255d3SCy Schubert 		goto fail;
1804c1d255d3SCy Schubert 	}
1805c1d255d3SCy Schubert 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
18064b72b91aSCy Schubert 	crypto_ec_key_deinit(auth->peer_protocol_key);
1807c1d255d3SCy Schubert 	auth->peer_protocol_key = pr;
1808c1d255d3SCy Schubert 	pr = NULL;
1809c1d255d3SCy Schubert 
1810c1d255d3SCy Schubert 	peer_key = dpp_parse_jwk(net_access_key, &curve);
1811c1d255d3SCy Schubert 	if (!peer_key)
1812c1d255d3SCy Schubert 		goto fail;
1813c1d255d3SCy Schubert 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1814c1d255d3SCy Schubert 	if (auth->curve != curve) {
1815c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
1816c1d255d3SCy Schubert 			   "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1817c1d255d3SCy Schubert 			   auth->curve->name, curve->name);
1818c1d255d3SCy Schubert 		goto fail;
1819c1d255d3SCy Schubert 	}
1820c1d255d3SCy Schubert 
1821c1d255d3SCy Schubert 	/* M = cI * { CR + PR } */
18224b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
18234b72b91aSCy Schubert 	if (!ec)
1824c1d255d3SCy Schubert 		goto fail;
1825c1d255d3SCy Schubert 
18264b72b91aSCy Schubert 	cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
18274b72b91aSCy Schubert 	sum = crypto_ec_point_init(ec);
18284b72b91aSCy Schubert 	M = crypto_ec_point_init(ec);
18294b72b91aSCy Schubert 	CR = crypto_ec_key_get_public_key(peer_key);
18304b72b91aSCy Schubert 	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
18314b72b91aSCy Schubert 	if (!cI || !sum || !M || !CR || !PR ||
18324b72b91aSCy Schubert 	    crypto_ec_point_add(ec, CR, PR, sum) ||
18334b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, sum, cI, M) ||
18344b72b91aSCy Schubert 	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
18354b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
18364b72b91aSCy Schubert 		goto fail;
18374b72b91aSCy Schubert 	}
18384b72b91aSCy Schubert 
1839c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1840c1d255d3SCy Schubert 
1841c1d255d3SCy Schubert 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1842c1d255d3SCy Schubert 
1843c1d255d3SCy Schubert 	/* HKDF-Extract(C-nonce | E-nonce, M.x) */
1844c1d255d3SCy Schubert 	os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1845c1d255d3SCy Schubert 	os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1846c1d255d3SCy Schubert 	if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1847c1d255d3SCy Schubert 		     Mx, curve->prime_len, prk) < 0)
1848c1d255d3SCy Schubert 		goto fail;
1849c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1850c1d255d3SCy Schubert 
1851c1d255d3SCy Schubert 	/* HKDF-Expand(PRK, "dpp reconfig key", L) */
1852c1d255d3SCy Schubert 	if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1853c1d255d3SCy Schubert 			    "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1854c1d255d3SCy Schubert 		goto fail;
1855c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
1856c1d255d3SCy Schubert 			"DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1857c1d255d3SCy Schubert 			auth->ke, curve->hash_len);
1858c1d255d3SCy Schubert 
1859c1d255d3SCy Schubert 	res = 0;
1860c1d255d3SCy Schubert fail:
1861c1d255d3SCy Schubert 	forced_memzero(prk, sizeof(prk));
1862c1d255d3SCy Schubert 	forced_memzero(Mx, sizeof(Mx));
1863*a90b9d01SCy Schubert 	crypto_bignum_deinit(cI, 1);
18644b72b91aSCy Schubert 	crypto_ec_key_deinit(pr);
18654b72b91aSCy Schubert 	crypto_ec_key_deinit(peer_key);
18664b72b91aSCy Schubert 	crypto_ec_point_deinit(sum, 1);
18674b72b91aSCy Schubert 	crypto_ec_point_deinit(M, 1);
1868*a90b9d01SCy Schubert 	crypto_ec_point_deinit(CR, 1);
1869*a90b9d01SCy Schubert 	crypto_ec_point_deinit(PR, 1);
18704b72b91aSCy Schubert 	crypto_ec_deinit(ec);
1871c1d255d3SCy Schubert 	return res;
1872c1d255d3SCy Schubert }
1873c1d255d3SCy Schubert 
1874c1d255d3SCy Schubert 
1875c1d255d3SCy Schubert static char *
dpp_build_jws_prot_hdr(struct dpp_configurator * conf,size_t * signed1_len)1876c1d255d3SCy Schubert dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1877c1d255d3SCy Schubert {
1878c1d255d3SCy Schubert 	struct wpabuf *jws_prot_hdr;
1879c1d255d3SCy Schubert 	char *signed1;
1880c1d255d3SCy Schubert 
1881c1d255d3SCy Schubert 	jws_prot_hdr = wpabuf_alloc(100);
1882c1d255d3SCy Schubert 	if (!jws_prot_hdr)
1883c1d255d3SCy Schubert 		return NULL;
1884c1d255d3SCy Schubert 	json_start_object(jws_prot_hdr, NULL);
1885c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "typ", "dppCon");
1886c1d255d3SCy Schubert 	json_value_sep(jws_prot_hdr);
1887c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "kid", conf->kid);
1888c1d255d3SCy Schubert 	json_value_sep(jws_prot_hdr);
1889c1d255d3SCy Schubert 	json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1890c1d255d3SCy Schubert 	json_end_object(jws_prot_hdr);
1891c1d255d3SCy Schubert 	signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1892c1d255d3SCy Schubert 				    wpabuf_len(jws_prot_hdr),
1893c1d255d3SCy Schubert 				    signed1_len);
1894c1d255d3SCy Schubert 	wpabuf_free(jws_prot_hdr);
1895c1d255d3SCy Schubert 	return signed1;
1896c1d255d3SCy Schubert }
1897c1d255d3SCy Schubert 
1898c1d255d3SCy Schubert 
1899c1d255d3SCy Schubert static char *
dpp_build_conn_signature(struct dpp_configurator * conf,const char * signed1,size_t signed1_len,const char * signed2,size_t signed2_len,size_t * signed3_len)1900c1d255d3SCy Schubert dpp_build_conn_signature(struct dpp_configurator *conf,
1901c1d255d3SCy Schubert 			 const char *signed1, size_t signed1_len,
1902c1d255d3SCy Schubert 			 const char *signed2, size_t signed2_len,
1903c1d255d3SCy Schubert 			 size_t *signed3_len)
1904c1d255d3SCy Schubert {
1905c1d255d3SCy Schubert 	const struct dpp_curve_params *curve;
19064b72b91aSCy Schubert 	struct wpabuf *sig = NULL;
1907c1d255d3SCy Schubert 	char *signed3 = NULL;
1908c1d255d3SCy Schubert 	char *dot = ".";
19094b72b91aSCy Schubert 	const u8 *vector[3];
19104b72b91aSCy Schubert 	size_t vector_len[3];
19114b72b91aSCy Schubert 	u8 *hash;
19124b72b91aSCy Schubert 	int ret;
19134b72b91aSCy Schubert 
19144b72b91aSCy Schubert 	vector[0] = (const u8 *) signed1;
19154b72b91aSCy Schubert 	vector[1] = (const u8 *) dot;
19164b72b91aSCy Schubert 	vector[2] = (const u8 *) signed2;
19174b72b91aSCy Schubert 	vector_len[0] = signed1_len;
19184b72b91aSCy Schubert 	vector_len[1] = 1;
19194b72b91aSCy Schubert 	vector_len[2] = signed2_len;
1920c1d255d3SCy Schubert 
1921c1d255d3SCy Schubert 	curve = conf->curve;
19224b72b91aSCy Schubert 	hash = os_malloc(curve->hash_len);
19234b72b91aSCy Schubert 	if (!hash)
19244b72b91aSCy Schubert 		goto fail;
1925c1d255d3SCy Schubert 	if (curve->hash_len == SHA256_MAC_LEN) {
19264b72b91aSCy Schubert 		ret = sha256_vector(3, vector, vector_len, hash);
1927c1d255d3SCy Schubert 	} else if (curve->hash_len == SHA384_MAC_LEN) {
19284b72b91aSCy Schubert 		ret = sha384_vector(3, vector, vector_len, hash);
1929c1d255d3SCy Schubert 	} else if (curve->hash_len == SHA512_MAC_LEN) {
19304b72b91aSCy Schubert 		ret = sha512_vector(3, vector, vector_len, hash);
1931c1d255d3SCy Schubert 	} else {
1932c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1933c1d255d3SCy Schubert 		goto fail;
1934c1d255d3SCy Schubert 	}
19354b72b91aSCy Schubert 	if (ret) {
19364b72b91aSCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
19374b72b91aSCy Schubert 		goto fail;
19384b72b91aSCy Schubert 	}
19394b72b91aSCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
19404b72b91aSCy Schubert 		    hash, curve->hash_len);
1941db0ac6deSCy Schubert 
19424b72b91aSCy Schubert 	sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
19434b72b91aSCy Schubert 	if (!sig) {
19444b72b91aSCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
1945db0ac6deSCy Schubert 		goto fail;
19464b72b91aSCy Schubert 	}
1947db0ac6deSCy Schubert 
1948c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
19494b72b91aSCy Schubert 		    wpabuf_head(sig), wpabuf_len(sig));
19504b72b91aSCy Schubert 	signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
19514b72b91aSCy Schubert 				    signed3_len);
19524b72b91aSCy Schubert 
1953c1d255d3SCy Schubert fail:
19544b72b91aSCy Schubert 	os_free(hash);
19554b72b91aSCy Schubert 	wpabuf_free(sig);
1956c1d255d3SCy Schubert 	return signed3;
1957c1d255d3SCy Schubert }
1958c1d255d3SCy Schubert 
dpp_sign_connector(struct dpp_configurator * conf,const struct wpabuf * dppcon)1959c1d255d3SCy Schubert char * dpp_sign_connector(struct dpp_configurator *conf,
1960c1d255d3SCy Schubert 			  const struct wpabuf *dppcon)
1961c1d255d3SCy Schubert {
1962c1d255d3SCy Schubert 	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1963c1d255d3SCy Schubert 	char *signed_conn = NULL, *pos;
1964c1d255d3SCy Schubert 	size_t signed1_len, signed2_len, signed3_len;
1965c1d255d3SCy Schubert 
1966c1d255d3SCy Schubert 	signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1967c1d255d3SCy Schubert 	signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1968c1d255d3SCy Schubert 				    &signed2_len);
1969c1d255d3SCy Schubert 	if (!signed1 || !signed2)
1970c1d255d3SCy Schubert 		goto fail;
1971c1d255d3SCy Schubert 
1972c1d255d3SCy Schubert 	signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1973c1d255d3SCy Schubert 					   signed2, signed2_len, &signed3_len);
1974c1d255d3SCy Schubert 	if (!signed3)
1975c1d255d3SCy Schubert 		goto fail;
1976c1d255d3SCy Schubert 
1977c1d255d3SCy Schubert 	signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1978c1d255d3SCy Schubert 	if (!signed_conn)
1979c1d255d3SCy Schubert 		goto fail;
1980c1d255d3SCy Schubert 	pos = signed_conn;
1981c1d255d3SCy Schubert 	os_memcpy(pos, signed1, signed1_len);
1982c1d255d3SCy Schubert 	pos += signed1_len;
1983c1d255d3SCy Schubert 	*pos++ = '.';
1984c1d255d3SCy Schubert 	os_memcpy(pos, signed2, signed2_len);
1985c1d255d3SCy Schubert 	pos += signed2_len;
1986c1d255d3SCy Schubert 	*pos++ = '.';
1987c1d255d3SCy Schubert 	os_memcpy(pos, signed3, signed3_len);
1988c1d255d3SCy Schubert 	pos += signed3_len;
1989c1d255d3SCy Schubert 	*pos = '\0';
1990c1d255d3SCy Schubert 
1991c1d255d3SCy Schubert fail:
1992c1d255d3SCy Schubert 	os_free(signed1);
1993c1d255d3SCy Schubert 	os_free(signed2);
1994c1d255d3SCy Schubert 	os_free(signed3);
1995c1d255d3SCy Schubert 	return signed_conn;
1996c1d255d3SCy Schubert }
1997c1d255d3SCy Schubert 
1998c1d255d3SCy Schubert 
1999c1d255d3SCy Schubert #ifdef CONFIG_DPP2
2000c1d255d3SCy Schubert 
dpp_pfs_init(const u8 * net_access_key,size_t net_access_key_len)2001c1d255d3SCy Schubert struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
2002c1d255d3SCy Schubert 			      size_t net_access_key_len)
2003c1d255d3SCy Schubert {
2004c1d255d3SCy Schubert 	struct wpabuf *pub = NULL;
20054b72b91aSCy Schubert 	struct crypto_ec_key *own_key;
2006c1d255d3SCy Schubert 	struct dpp_pfs *pfs;
2007c1d255d3SCy Schubert 
2008c1d255d3SCy Schubert 	pfs = os_zalloc(sizeof(*pfs));
2009c1d255d3SCy Schubert 	if (!pfs)
2010c1d255d3SCy Schubert 		return NULL;
2011c1d255d3SCy Schubert 
2012c1d255d3SCy Schubert 	own_key = dpp_set_keypair(&pfs->curve, net_access_key,
2013c1d255d3SCy Schubert 				  net_access_key_len);
2014c1d255d3SCy Schubert 	if (!own_key) {
2015c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2016c1d255d3SCy Schubert 		goto fail;
2017c1d255d3SCy Schubert 	}
20184b72b91aSCy Schubert 	crypto_ec_key_deinit(own_key);
2019c1d255d3SCy Schubert 
2020c1d255d3SCy Schubert 	pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
2021c1d255d3SCy Schubert 	if (!pfs->ecdh)
2022c1d255d3SCy Schubert 		goto fail;
2023c1d255d3SCy Schubert 
2024c1d255d3SCy Schubert 	pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
2025c1d255d3SCy Schubert 	pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
2026c1d255d3SCy Schubert 	if (!pub)
2027c1d255d3SCy Schubert 		goto fail;
2028c1d255d3SCy Schubert 
2029c1d255d3SCy Schubert 	pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2030c1d255d3SCy Schubert 	if (!pfs->ie)
2031c1d255d3SCy Schubert 		goto fail;
2032c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2033c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2034c1d255d3SCy Schubert 	wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2035c1d255d3SCy Schubert 	wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2036c1d255d3SCy Schubert 	wpabuf_put_buf(pfs->ie, pub);
2037c1d255d3SCy Schubert 	wpabuf_free(pub);
2038c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2039c1d255d3SCy Schubert 			pfs->ie);
2040c1d255d3SCy Schubert 
2041c1d255d3SCy Schubert 	return pfs;
2042c1d255d3SCy Schubert fail:
2043c1d255d3SCy Schubert 	wpabuf_free(pub);
2044c1d255d3SCy Schubert 	dpp_pfs_free(pfs);
2045c1d255d3SCy Schubert 	return NULL;
2046c1d255d3SCy Schubert }
2047c1d255d3SCy Schubert 
2048c1d255d3SCy Schubert 
dpp_pfs_process(struct dpp_pfs * pfs,const u8 * peer_ie,size_t peer_ie_len)2049c1d255d3SCy Schubert int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2050c1d255d3SCy Schubert {
2051c1d255d3SCy Schubert 	if (peer_ie_len < 2)
2052c1d255d3SCy Schubert 		return -1;
2053c1d255d3SCy Schubert 	if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2054c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2055c1d255d3SCy Schubert 		return -1;
2056c1d255d3SCy Schubert 	}
2057c1d255d3SCy Schubert 
2058c1d255d3SCy Schubert 	pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2059c1d255d3SCy Schubert 					      peer_ie_len - 2);
2060c1d255d3SCy Schubert 	pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2061c1d255d3SCy Schubert 	if (!pfs->secret) {
2062c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2063c1d255d3SCy Schubert 		return -1;
2064c1d255d3SCy Schubert 	}
2065c1d255d3SCy Schubert 	wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2066c1d255d3SCy Schubert 	return 0;
2067c1d255d3SCy Schubert }
2068c1d255d3SCy Schubert 
2069c1d255d3SCy Schubert 
dpp_pfs_free(struct dpp_pfs * pfs)2070c1d255d3SCy Schubert void dpp_pfs_free(struct dpp_pfs *pfs)
2071c1d255d3SCy Schubert {
2072c1d255d3SCy Schubert 	if (!pfs)
2073c1d255d3SCy Schubert 		return;
2074c1d255d3SCy Schubert 	crypto_ecdh_deinit(pfs->ecdh);
2075c1d255d3SCy Schubert 	wpabuf_free(pfs->ie);
2076c1d255d3SCy Schubert 	wpabuf_clear_free(pfs->secret);
2077c1d255d3SCy Schubert 	os_free(pfs);
2078c1d255d3SCy Schubert }
2079c1d255d3SCy Schubert 
2080c1d255d3SCy Schubert 
dpp_build_csr(struct dpp_authentication * auth,const char * name)2081c1d255d3SCy Schubert struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2082c1d255d3SCy Schubert {
20834b72b91aSCy Schubert 	struct crypto_csr *csr = NULL;
2084c1d255d3SCy Schubert 	struct wpabuf *buf = NULL;
20854b72b91aSCy Schubert 	struct crypto_ec_key *key;
2086c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
20874b72b91aSCy Schubert 	struct wpabuf *priv_key;
2088c1d255d3SCy Schubert 	u8 cp[DPP_CP_LEN];
20894b72b91aSCy Schubert 	char *password = NULL;
2090*a90b9d01SCy Schubert 	size_t password_len = 0;
20914b72b91aSCy Schubert 	int hash_sign_algo;
2092c1d255d3SCy Schubert 
2093c1d255d3SCy Schubert 	/* TODO: use auth->csrattrs */
2094c1d255d3SCy Schubert 
2095c1d255d3SCy Schubert 	/* TODO: support generation of a new private key if csrAttrs requests
2096c1d255d3SCy Schubert 	 * a specific group to be used */
2097c1d255d3SCy Schubert 	key = auth->own_protocol_key;
2098c1d255d3SCy Schubert 
20994b72b91aSCy Schubert 	priv_key = crypto_ec_key_get_ecprivate_key(key, true);
21004b72b91aSCy Schubert 	if (!priv_key)
2101c1d255d3SCy Schubert 		goto fail;
2102c1d255d3SCy Schubert 	wpabuf_free(auth->priv_key);
21034b72b91aSCy Schubert 	auth->priv_key = priv_key;
21044b72b91aSCy Schubert 
21054b72b91aSCy Schubert 	csr = crypto_csr_init();
21064b72b91aSCy Schubert 	if (!csr || crypto_csr_set_ec_public_key(csr, key))
2107c1d255d3SCy Schubert 		goto fail;
2108c1d255d3SCy Schubert 
21094b72b91aSCy Schubert 	if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
2110c1d255d3SCy Schubert 		goto fail;
2111c1d255d3SCy Schubert 
2112c1d255d3SCy Schubert 	/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2113c1d255d3SCy Schubert 	if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2114c1d255d3SCy Schubert 			    "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2115c1d255d3SCy Schubert 		goto fail;
2116c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2117c1d255d3SCy Schubert 			"DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2118c1d255d3SCy Schubert 			cp, DPP_CP_LEN);
2119c1d255d3SCy Schubert 	password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2120c1d255d3SCy Schubert 	forced_memzero(cp, DPP_CP_LEN);
21214b72b91aSCy Schubert 	if (!password ||
21224b72b91aSCy Schubert 	    crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
21234b72b91aSCy Schubert 				     ASN1_TAG_UTF8STRING, (const u8 *) password,
21244b72b91aSCy Schubert 				     password_len))
2125c1d255d3SCy Schubert 		goto fail;
2126c1d255d3SCy Schubert 
2127c1d255d3SCy Schubert 	/* TODO: hash func selection based on csrAttrs */
2128c1d255d3SCy Schubert 	if (hash_len == SHA256_MAC_LEN) {
21294b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
2130c1d255d3SCy Schubert 	} else if (hash_len == SHA384_MAC_LEN) {
21314b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
2132c1d255d3SCy Schubert 	} else if (hash_len == SHA512_MAC_LEN) {
21334b72b91aSCy Schubert 		hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
2134c1d255d3SCy Schubert 	} else {
2135c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2136c1d255d3SCy Schubert 		goto fail;
2137c1d255d3SCy Schubert 	}
2138c1d255d3SCy Schubert 
21394b72b91aSCy Schubert 	buf = crypto_csr_sign(csr, key, hash_sign_algo);
21404b72b91aSCy Schubert 	if (!buf)
2141c1d255d3SCy Schubert 		goto fail;
2142c1d255d3SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2143c1d255d3SCy Schubert 
2144c1d255d3SCy Schubert fail:
21454b72b91aSCy Schubert 	bin_clear_free(password, password_len);
21464b72b91aSCy Schubert 	crypto_csr_deinit(csr);
2147c1d255d3SCy Schubert 	return buf;
2148c1d255d3SCy Schubert }
2149c1d255d3SCy Schubert 
2150c1d255d3SCy Schubert 
dpp_validate_csr(struct dpp_authentication * auth,const struct wpabuf * csrbuf)21514b72b91aSCy Schubert int dpp_validate_csr(struct dpp_authentication *auth,
21524b72b91aSCy Schubert 		     const struct wpabuf *csrbuf)
2153c1d255d3SCy Schubert {
21544b72b91aSCy Schubert 	struct crypto_csr *csr;
21554b72b91aSCy Schubert 	const u8 *attr;
21564b72b91aSCy Schubert 	size_t attr_len;
21574b72b91aSCy Schubert 	int attr_type;
2158c1d255d3SCy Schubert 	unsigned char *cp = NULL;
2159c1d255d3SCy Schubert 	size_t cp_len;
2160c1d255d3SCy Schubert 	u8 exp_cp[DPP_CP_LEN];
2161c1d255d3SCy Schubert 	unsigned int hash_len = auth->curve->hash_len;
21624b72b91aSCy Schubert 	int ret = -1;
2163c1d255d3SCy Schubert 
21644b72b91aSCy Schubert 	csr = crypto_csr_verify(csrbuf);
21654b72b91aSCy Schubert 	if (!csr) {
2166db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
21674b72b91aSCy Schubert 			   "DPP: CSR invalid or invalid signature");
2168db0ac6deSCy Schubert 		goto fail;
2169db0ac6deSCy Schubert 	}
2170db0ac6deSCy Schubert 
21714b72b91aSCy Schubert 	attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
21724b72b91aSCy Schubert 					&attr_len, &attr_type);
21734b72b91aSCy Schubert 	if (!attr) {
2174c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2175c1d255d3SCy Schubert 			   "DPP: CSR does not include challengePassword");
2176c1d255d3SCy Schubert 		goto fail;
2177c1d255d3SCy Schubert 	}
2178db0ac6deSCy Schubert 	/* This is supposed to be UTF8String, but allow other strings as well
2179db0ac6deSCy Schubert 	 * since challengePassword is using ASCII (base64 encoded). */
21804b72b91aSCy Schubert 	if (attr_type != ASN1_TAG_UTF8STRING &&
21814b72b91aSCy Schubert 	    attr_type != ASN1_TAG_PRINTABLESTRING &&
21824b72b91aSCy Schubert 	    attr_type != ASN1_TAG_IA5STRING) {
2183db0ac6deSCy Schubert 		wpa_printf(MSG_DEBUG,
2184db0ac6deSCy Schubert 			   "DPP: Unexpected challengePassword attribute type %d",
21854b72b91aSCy Schubert 			   attr_type);
2186db0ac6deSCy Schubert 		goto fail;
2187db0ac6deSCy Schubert 	}
2188db0ac6deSCy Schubert 
21894b72b91aSCy Schubert 	cp = base64_decode((const char *) attr, attr_len, &cp_len);
2190c1d255d3SCy Schubert 	if (!cp) {
2191c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2192c1d255d3SCy Schubert 			   "DPP: Could not base64 decode challengePassword");
2193c1d255d3SCy Schubert 		goto fail;
2194c1d255d3SCy Schubert 	}
2195c1d255d3SCy Schubert 	if (cp_len != DPP_CP_LEN) {
2196c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2197c1d255d3SCy Schubert 			   "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2198c1d255d3SCy Schubert 			   cp_len);
2199c1d255d3SCy Schubert 		goto fail;
2200c1d255d3SCy Schubert 	}
2201c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2202c1d255d3SCy Schubert 			cp, cp_len);
2203c1d255d3SCy Schubert 
2204c1d255d3SCy Schubert 	/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2205c1d255d3SCy Schubert 	if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2206c1d255d3SCy Schubert 			    "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2207c1d255d3SCy Schubert 		goto fail;
2208c1d255d3SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2209c1d255d3SCy Schubert 			"DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2210c1d255d3SCy Schubert 			exp_cp, DPP_CP_LEN);
2211c1d255d3SCy Schubert 	if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2212c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
2213c1d255d3SCy Schubert 			   "DPP: CSR challengePassword does not match calculated cp");
2214c1d255d3SCy Schubert 		goto fail;
2215c1d255d3SCy Schubert 	}
2216c1d255d3SCy Schubert 
2217c1d255d3SCy Schubert 	ret = 0;
2218c1d255d3SCy Schubert fail:
2219c1d255d3SCy Schubert 	os_free(cp);
22204b72b91aSCy Schubert 	crypto_csr_deinit(csr);
2221c1d255d3SCy Schubert 	return ret;
2222c1d255d3SCy Schubert }
2223c1d255d3SCy Schubert 
2224c1d255d3SCy Schubert 
dpp_gen_reconfig_id(const u8 * csign_key,size_t csign_key_len,const u8 * pp_key,size_t pp_key_len)2225c1d255d3SCy Schubert struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2226c1d255d3SCy Schubert 					     size_t csign_key_len,
2227c1d255d3SCy Schubert 					     const u8 *pp_key,
2228c1d255d3SCy Schubert 					     size_t pp_key_len)
2229c1d255d3SCy Schubert {
22304b72b91aSCy Schubert 	struct crypto_ec_key *csign = NULL, *ppkey = NULL;
2231c1d255d3SCy Schubert 	struct dpp_reconfig_id *id = NULL;
22324b72b91aSCy Schubert 	struct crypto_ec *ec = NULL;
22334b72b91aSCy Schubert 	const struct crypto_bignum *q;
22344b72b91aSCy Schubert 	struct crypto_bignum *bn = NULL;
22354b72b91aSCy Schubert 	struct crypto_ec_point *e_id = NULL;
22364b72b91aSCy Schubert 	const struct crypto_ec_point *generator;
2237c1d255d3SCy Schubert 
22384b72b91aSCy Schubert 	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
2239c1d255d3SCy Schubert 	if (!csign)
2240c1d255d3SCy Schubert 		goto fail;
2241c1d255d3SCy Schubert 
2242c1d255d3SCy Schubert 	if (!pp_key)
2243c1d255d3SCy Schubert 		goto fail;
22444b72b91aSCy Schubert 	ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
2245c1d255d3SCy Schubert 	if (!ppkey)
2246c1d255d3SCy Schubert 		goto fail;
2247c1d255d3SCy Schubert 
22484b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(csign));
22494b72b91aSCy Schubert 	if (!ec)
2250c1d255d3SCy Schubert 		goto fail;
2251c1d255d3SCy Schubert 
22524b72b91aSCy Schubert 	e_id = crypto_ec_point_init(ec);
22534b72b91aSCy Schubert 	bn = crypto_bignum_init();
22544b72b91aSCy Schubert 	q = crypto_ec_get_order(ec);
22554b72b91aSCy Schubert 	generator = crypto_ec_get_generator(ec);
22564b72b91aSCy Schubert 	if (!e_id || !bn || !q || !generator ||
22574b72b91aSCy Schubert 	    crypto_bignum_rand(bn, q) ||
22584b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, generator, bn, e_id))
2259c1d255d3SCy Schubert 		goto fail;
2260c1d255d3SCy Schubert 
22614b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, e_id,
22624b72b91aSCy Schubert 				    "DPP: Generated random point E-id");
2263c1d255d3SCy Schubert 
2264c1d255d3SCy Schubert 	id = os_zalloc(sizeof(*id));
2265c1d255d3SCy Schubert 	if (!id)
2266c1d255d3SCy Schubert 		goto fail;
22674b72b91aSCy Schubert 
22684b72b91aSCy Schubert 	id->ec = ec;
22694b72b91aSCy Schubert 	ec = NULL;
2270c1d255d3SCy Schubert 	id->e_id = e_id;
2271c1d255d3SCy Schubert 	e_id = NULL;
2272c1d255d3SCy Schubert 	id->csign = csign;
2273c1d255d3SCy Schubert 	csign = NULL;
2274c1d255d3SCy Schubert 	id->pp_key = ppkey;
2275c1d255d3SCy Schubert 	ppkey = NULL;
2276c1d255d3SCy Schubert fail:
22774b72b91aSCy Schubert 	crypto_ec_point_deinit(e_id, 1);
22784b72b91aSCy Schubert 	crypto_ec_key_deinit(csign);
22794b72b91aSCy Schubert 	crypto_ec_key_deinit(ppkey);
22804b72b91aSCy Schubert 	crypto_bignum_deinit(bn, 1);
22814b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2282c1d255d3SCy Schubert 	return id;
2283c1d255d3SCy Schubert }
2284c1d255d3SCy Schubert 
2285c1d255d3SCy Schubert 
dpp_update_reconfig_id(struct dpp_reconfig_id * id)2286c1d255d3SCy Schubert int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2287c1d255d3SCy Schubert {
22884b72b91aSCy Schubert 	const struct crypto_bignum *q;
22894b72b91aSCy Schubert 	struct crypto_bignum *bn;
2290*a90b9d01SCy Schubert 	const struct crypto_ec_point *generator;
2291*a90b9d01SCy Schubert 	struct crypto_ec_point *e_prime_id, *a_nonce, *pp;
2292c1d255d3SCy Schubert 	int ret = -1;
2293c1d255d3SCy Schubert 
22944b72b91aSCy Schubert 	pp = crypto_ec_key_get_public_key(id->pp_key);
22954b72b91aSCy Schubert 	e_prime_id = crypto_ec_point_init(id->ec);
22964b72b91aSCy Schubert 	a_nonce = crypto_ec_point_init(id->ec);
22974b72b91aSCy Schubert 	bn = crypto_bignum_init();
22984b72b91aSCy Schubert 	q = crypto_ec_get_order(id->ec);
22994b72b91aSCy Schubert 	generator = crypto_ec_get_generator(id->ec);
23004b72b91aSCy Schubert 
2301c1d255d3SCy Schubert 	/* Generate random 0 <= a-nonce < q
2302c1d255d3SCy Schubert 	 * A-NONCE = a-nonce * G
2303c1d255d3SCy Schubert 	 * E'-id = E-id + a-nonce * P_pk */
23044b72b91aSCy Schubert 	if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
23054b72b91aSCy Schubert 	    crypto_bignum_rand(bn, q) || /* bn = a-nonce */
23064b72b91aSCy Schubert 	    crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
23074b72b91aSCy Schubert 	    crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
23084b72b91aSCy Schubert 	    crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
2309c1d255d3SCy Schubert 		goto fail;
2310c1d255d3SCy Schubert 
23114b72b91aSCy Schubert 	crypto_ec_point_debug_print(id->ec, a_nonce,
23124b72b91aSCy Schubert 				    "DPP: Generated A-NONCE");
23134b72b91aSCy Schubert 	crypto_ec_point_debug_print(id->ec, e_prime_id,
23144b72b91aSCy Schubert 				    "DPP: Encrypted E-id to E'-id");
2315c1d255d3SCy Schubert 
23164b72b91aSCy Schubert 	crypto_ec_key_deinit(id->a_nonce);
23174b72b91aSCy Schubert 	crypto_ec_key_deinit(id->e_prime_id);
23184b72b91aSCy Schubert 	id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
23194b72b91aSCy Schubert 	id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
2320c1d255d3SCy Schubert 	if (!id->a_nonce || !id->e_prime_id)
2321c1d255d3SCy Schubert 		goto fail;
2322c1d255d3SCy Schubert 
2323c1d255d3SCy Schubert 	ret = 0;
2324c1d255d3SCy Schubert 
2325c1d255d3SCy Schubert fail:
23264b72b91aSCy Schubert 	crypto_ec_point_deinit(e_prime_id, 1);
23274b72b91aSCy Schubert 	crypto_ec_point_deinit(a_nonce, 1);
2328*a90b9d01SCy Schubert 	crypto_ec_point_deinit(pp, 1);
23294b72b91aSCy Schubert 	crypto_bignum_deinit(bn, 1);
2330c1d255d3SCy Schubert 	return ret;
2331c1d255d3SCy Schubert }
2332c1d255d3SCy Schubert 
2333c1d255d3SCy Schubert 
dpp_free_reconfig_id(struct dpp_reconfig_id * id)2334c1d255d3SCy Schubert void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2335c1d255d3SCy Schubert {
2336c1d255d3SCy Schubert 	if (id) {
23374b72b91aSCy Schubert 		crypto_ec_point_deinit(id->e_id, 1);
23384b72b91aSCy Schubert 		crypto_ec_key_deinit(id->csign);
23394b72b91aSCy Schubert 		crypto_ec_key_deinit(id->a_nonce);
23404b72b91aSCy Schubert 		crypto_ec_key_deinit(id->e_prime_id);
23414b72b91aSCy Schubert 		crypto_ec_key_deinit(id->pp_key);
23424b72b91aSCy Schubert 		crypto_ec_deinit(id->ec);
2343c1d255d3SCy Schubert 		os_free(id);
2344c1d255d3SCy Schubert 	}
2345c1d255d3SCy Schubert }
2346c1d255d3SCy Schubert 
2347c1d255d3SCy Schubert 
dpp_decrypt_e_id(struct crypto_ec_key * ppkey,struct crypto_ec_key * a_nonce,struct crypto_ec_key * e_prime_id)23484b72b91aSCy Schubert struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
23494b72b91aSCy Schubert 					  struct crypto_ec_key *a_nonce,
23504b72b91aSCy Schubert 					  struct crypto_ec_key *e_prime_id)
2351c1d255d3SCy Schubert {
23524b72b91aSCy Schubert 	struct crypto_ec *ec;
2353*a90b9d01SCy Schubert 	struct crypto_bignum *pp = NULL;
23544b72b91aSCy Schubert 	struct crypto_ec_point *e_id = NULL;
2355*a90b9d01SCy Schubert 	struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
2356c1d255d3SCy Schubert 
2357c1d255d3SCy Schubert 	if (!ppkey)
2358c1d255d3SCy Schubert 		return NULL;
2359c1d255d3SCy Schubert 
2360c1d255d3SCy Schubert 	/* E-id = E'-id - s_C * A-NONCE */
23614b72b91aSCy Schubert 	ec = crypto_ec_init(crypto_ec_key_group(ppkey));
23624b72b91aSCy Schubert 	if (!ec)
2363c1d255d3SCy Schubert 		return NULL;
23644b72b91aSCy Schubert 
23654b72b91aSCy Schubert 	pp = crypto_ec_key_get_private_key(ppkey);
23664b72b91aSCy Schubert 	a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
23674b72b91aSCy Schubert 	e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
23684b72b91aSCy Schubert 	e_id = crypto_ec_point_init(ec);
23694b72b91aSCy Schubert 	if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
23704b72b91aSCy Schubert 	    crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
23714b72b91aSCy Schubert 	    crypto_ec_point_invert(ec, e_id) ||
23724b72b91aSCy Schubert 	    crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
23734b72b91aSCy Schubert 		crypto_ec_point_deinit(e_id, 1);
2374c1d255d3SCy Schubert 		goto fail;
2375c1d255d3SCy Schubert 	}
2376c1d255d3SCy Schubert 
23774b72b91aSCy Schubert 	crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
2378c1d255d3SCy Schubert 
2379c1d255d3SCy Schubert fail:
2380*a90b9d01SCy Schubert 	crypto_ec_point_deinit(a_nonce_point, 1);
2381*a90b9d01SCy Schubert 	crypto_ec_point_deinit(e_prime_id_point, 1);
2382*a90b9d01SCy Schubert 	crypto_bignum_deinit(pp, 1);
23834b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2384c1d255d3SCy Schubert 	return e_id;
2385c1d255d3SCy Schubert }
2386c1d255d3SCy Schubert 
2387c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */
2388c1d255d3SCy Schubert 
2389c1d255d3SCy Schubert 
2390*a90b9d01SCy Schubert #ifdef CONFIG_DPP3
2391*a90b9d01SCy Schubert 
dpp_derive_auth_i(struct dpp_authentication * auth,u8 * auth_i)2392*a90b9d01SCy Schubert int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
2393*a90b9d01SCy Schubert {
2394*a90b9d01SCy Schubert 	int ret = -1, res;
2395*a90b9d01SCy Schubert 	u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
2396*a90b9d01SCy Schubert 	size_t Sx_len;
2397*a90b9d01SCy Schubert 	unsigned int hash_len;
2398*a90b9d01SCy Schubert 	const char *info = "New DPP Protocol Key";
2399*a90b9d01SCy Schubert 	const u8 *addr[3];
2400*a90b9d01SCy Schubert 	size_t len[3];
2401*a90b9d01SCy Schubert 	u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
2402*a90b9d01SCy Schubert 	struct wpabuf *pcx = NULL, *pex = NULL;
2403*a90b9d01SCy Schubert 
2404*a90b9d01SCy Schubert 	hash_len = auth->curve->hash_len;
2405*a90b9d01SCy Schubert 
2406*a90b9d01SCy Schubert 	/*
2407*a90b9d01SCy Schubert 	 * Configurator: S = pc * Pe
2408*a90b9d01SCy Schubert 	 * Enrollee: S = pe * Pc
2409*a90b9d01SCy Schubert 	 * k = HKDF(bk, "New DPP Protocol Key", S.x)
2410*a90b9d01SCy Schubert 	 *   = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
2411*a90b9d01SCy Schubert 	 *                 len(new-curve-hash-out))
2412*a90b9d01SCy Schubert 	 * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)
2413*a90b9d01SCy Schubert 	 *
2414*a90b9d01SCy Schubert 	 * auth->own_protocol_key and auth->peer_protocol_key have already been
2415*a90b9d01SCy Schubert 	 * updated to use the new keys. The new curve determines the size of
2416*a90b9d01SCy Schubert 	 * the (new) protocol keys and S.x. The other parameters (bk, hash
2417*a90b9d01SCy Schubert 	 * algorithm, k) are determined based on the initially determined curve
2418*a90b9d01SCy Schubert 	 * during the (re)authentication exchange.
2419*a90b9d01SCy Schubert 	 */
2420*a90b9d01SCy Schubert 
2421*a90b9d01SCy Schubert 	if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2422*a90b9d01SCy Schubert 		     Sx, &Sx_len) < 0)
2423*a90b9d01SCy Schubert 		goto fail;
2424*a90b9d01SCy Schubert 
2425*a90b9d01SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
2426*a90b9d01SCy Schubert 
2427*a90b9d01SCy Schubert 	/* tmp = HKDF-Extract(bk, S.x) */
2428*a90b9d01SCy Schubert 	addr[0] = Sx;
2429*a90b9d01SCy Schubert 	len[0] = Sx_len;
2430*a90b9d01SCy Schubert 	res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp);
2431*a90b9d01SCy Schubert 	if (res < 0)
2432*a90b9d01SCy Schubert 		goto fail;
2433*a90b9d01SCy Schubert 	wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
2434*a90b9d01SCy Schubert 			tmp, hash_len);
2435*a90b9d01SCy Schubert 	/* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output))
2436*a90b9d01SCy Schubert 	 */
2437*a90b9d01SCy Schubert 	res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
2438*a90b9d01SCy Schubert 	if (res < 0)
2439*a90b9d01SCy Schubert 		return -1;
2440*a90b9d01SCy Schubert 
2441*a90b9d01SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2442*a90b9d01SCy Schubert 			"DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
2443*a90b9d01SCy Schubert 			k, hash_len);
2444*a90b9d01SCy Schubert 
2445*a90b9d01SCy Schubert 	/* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */
2446*a90b9d01SCy Schubert 	addr[0] = auth->e_nonce;
2447*a90b9d01SCy Schubert 	len[0] = auth->curve->nonce_len;
2448*a90b9d01SCy Schubert 
2449*a90b9d01SCy Schubert 	if (auth->configurator) {
2450*a90b9d01SCy Schubert 		pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2451*a90b9d01SCy Schubert 		pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2452*a90b9d01SCy Schubert 						     0);
2453*a90b9d01SCy Schubert 	} else {
2454*a90b9d01SCy Schubert 		pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2455*a90b9d01SCy Schubert 						     0);
2456*a90b9d01SCy Schubert 		pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2457*a90b9d01SCy Schubert 	}
2458*a90b9d01SCy Schubert 	if (!pcx || !pex)
2459*a90b9d01SCy Schubert 		goto fail;
2460*a90b9d01SCy Schubert 	addr[1] = wpabuf_head(pcx);
2461*a90b9d01SCy Schubert 	len[1] = wpabuf_len(pcx) / 2;
2462*a90b9d01SCy Schubert 	addr[2] = wpabuf_head(pex);
2463*a90b9d01SCy Schubert 	len[2] = wpabuf_len(pex) / 2;
2464*a90b9d01SCy Schubert 
2465*a90b9d01SCy Schubert 	if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0)
2466*a90b9d01SCy Schubert 		goto fail;
2467*a90b9d01SCy Schubert 	wpa_hexdump_key(MSG_DEBUG,
2468*a90b9d01SCy Schubert 			"DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)",
2469*a90b9d01SCy Schubert 			auth_i, hash_len);
2470*a90b9d01SCy Schubert 	ret = 0;
2471*a90b9d01SCy Schubert fail:
2472*a90b9d01SCy Schubert 	forced_memzero(Sx, sizeof(Sx));
2473*a90b9d01SCy Schubert 	forced_memzero(tmp, sizeof(tmp));
2474*a90b9d01SCy Schubert 	forced_memzero(k, sizeof(k));
2475*a90b9d01SCy Schubert 	wpabuf_free(pcx);
2476*a90b9d01SCy Schubert 	wpabuf_free(pex);
2477*a90b9d01SCy Schubert 	return ret;
2478*a90b9d01SCy Schubert }
2479*a90b9d01SCy Schubert 
2480*a90b9d01SCy Schubert 
dpp_hpke_suite(int iana_group,enum hpke_kem_id * kem_id,enum hpke_kdf_id * kdf_id,enum hpke_aead_id * aead_id)2481*a90b9d01SCy Schubert int dpp_hpke_suite(int iana_group, enum hpke_kem_id *kem_id,
2482*a90b9d01SCy Schubert 		   enum hpke_kdf_id *kdf_id, enum hpke_aead_id *aead_id)
2483*a90b9d01SCy Schubert {
2484*a90b9d01SCy Schubert 	switch (iana_group) {
2485*a90b9d01SCy Schubert 	case 19:
2486*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2487*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA256;
2488*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_128_GCM;
2489*a90b9d01SCy Schubert 		return 0;
2490*a90b9d01SCy Schubert 	case 20:
2491*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2492*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA384;
2493*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_256_GCM;
2494*a90b9d01SCy Schubert 		return 0;
2495*a90b9d01SCy Schubert 	case 21:
2496*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2497*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA512;
2498*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_256_GCM;
2499*a90b9d01SCy Schubert 		return 0;
2500*a90b9d01SCy Schubert 	case 28:
2501*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2502*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA256;
2503*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_128_GCM;
2504*a90b9d01SCy Schubert 		return 0;
2505*a90b9d01SCy Schubert 	case 29:
2506*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2507*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA384;
2508*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_256_GCM;
2509*a90b9d01SCy Schubert 		return 0;
2510*a90b9d01SCy Schubert 	case 30:
2511*a90b9d01SCy Schubert 		*kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2512*a90b9d01SCy Schubert 		*kdf_id = HPKE_KDF_HKDF_SHA512;
2513*a90b9d01SCy Schubert 		*aead_id = HPKE_AEAD_AES_256_GCM;
2514*a90b9d01SCy Schubert 		return 0;
2515*a90b9d01SCy Schubert 	}
2516*a90b9d01SCy Schubert 
2517*a90b9d01SCy Schubert 	return -1;
2518*a90b9d01SCy Schubert }
2519*a90b9d01SCy Schubert 
2520*a90b9d01SCy Schubert #endif /* CONFIG_DPP3 */
2521*a90b9d01SCy Schubert 
2522*a90b9d01SCy Schubert 
2523c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
2524c1d255d3SCy Schubert 
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)2525c1d255d3SCy Schubert int dpp_test_gen_invalid_key(struct wpabuf *msg,
2526c1d255d3SCy Schubert 			     const struct dpp_curve_params *curve)
2527c1d255d3SCy Schubert {
25284b72b91aSCy Schubert 	struct crypto_ec *ec;
25294b72b91aSCy Schubert 	struct crypto_ec_key *key = NULL;
2530*a90b9d01SCy Schubert 	struct crypto_ec_point *p = NULL, *pub_key = NULL;
25314b72b91aSCy Schubert 	u8 *x, *y;
2532c1d255d3SCy Schubert 	int ret = -1;
2533c1d255d3SCy Schubert 
25344b72b91aSCy Schubert 	ec = crypto_ec_init(curve->ike_group);
25354b72b91aSCy Schubert 	x = wpabuf_put(msg, curve->prime_len);
25364b72b91aSCy Schubert 	y = wpabuf_put(msg, curve->prime_len);
25374b72b91aSCy Schubert 	if (!ec)
2538c1d255d3SCy Schubert 		goto fail;
2539c1d255d3SCy Schubert 
25404b72b91aSCy Schubert retry:
25414b72b91aSCy Schubert 	/* Generate valid key pair */
25424b72b91aSCy Schubert 	key = crypto_ec_key_gen(curve->ike_group);
25434b72b91aSCy Schubert 	if (!key)
2544c1d255d3SCy Schubert 		goto fail;
2545c1d255d3SCy Schubert 
25464b72b91aSCy Schubert 	/* Retrieve public key coordinates */
25474b72b91aSCy Schubert 	pub_key = crypto_ec_key_get_public_key(key);
2548*a90b9d01SCy Schubert 	if (!pub_key || crypto_ec_point_to_bin(ec, pub_key, x, y))
2549c1d255d3SCy Schubert 		goto fail;
2550c1d255d3SCy Schubert 
25514b72b91aSCy Schubert 	/* And corrupt them */
25524b72b91aSCy Schubert 	y[curve->prime_len - 1] ^= 0x01;
25534b72b91aSCy Schubert 	p = crypto_ec_point_from_bin(ec, x);
25544b72b91aSCy Schubert 	if (p && crypto_ec_point_is_on_curve(ec, p)) {
25554b72b91aSCy Schubert 		crypto_ec_point_deinit(p, 0);
25564b72b91aSCy Schubert 		p = NULL;
25574b72b91aSCy Schubert 		goto retry;
2558c1d255d3SCy Schubert 	}
2559c1d255d3SCy Schubert 
2560c1d255d3SCy Schubert 	ret = 0;
2561c1d255d3SCy Schubert fail:
25624b72b91aSCy Schubert 	crypto_ec_point_deinit(p, 0);
2563*a90b9d01SCy Schubert 	crypto_ec_point_deinit(pub_key, 0);
25644b72b91aSCy Schubert 	crypto_ec_key_deinit(key);
25654b72b91aSCy Schubert 	crypto_ec_deinit(ec);
2566c1d255d3SCy Schubert 	return ret;
2567c1d255d3SCy Schubert }
2568c1d255d3SCy Schubert 
2569c1d255d3SCy Schubert 
dpp_corrupt_connector_signature(const char * connector)2570c1d255d3SCy Schubert char * dpp_corrupt_connector_signature(const char *connector)
2571c1d255d3SCy Schubert {
2572c1d255d3SCy Schubert 	char *tmp, *pos, *signed3 = NULL;
2573c1d255d3SCy Schubert 	unsigned char *signature = NULL;
2574c1d255d3SCy Schubert 	size_t signature_len = 0, signed3_len;
2575c1d255d3SCy Schubert 
2576c1d255d3SCy Schubert 	tmp = os_zalloc(os_strlen(connector) + 5);
2577c1d255d3SCy Schubert 	if (!tmp)
2578c1d255d3SCy Schubert 		goto fail;
2579c1d255d3SCy Schubert 	os_memcpy(tmp, connector, os_strlen(connector));
2580c1d255d3SCy Schubert 
2581c1d255d3SCy Schubert 	pos = os_strchr(tmp, '.');
2582c1d255d3SCy Schubert 	if (!pos)
2583c1d255d3SCy Schubert 		goto fail;
2584c1d255d3SCy Schubert 
2585c1d255d3SCy Schubert 	pos = os_strchr(pos + 1, '.');
2586c1d255d3SCy Schubert 	if (!pos)
2587c1d255d3SCy Schubert 		goto fail;
2588c1d255d3SCy Schubert 	pos++;
2589c1d255d3SCy Schubert 
2590c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2591c1d255d3SCy Schubert 		   pos);
2592c1d255d3SCy Schubert 	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2593c1d255d3SCy Schubert 	if (!signature || signature_len == 0)
2594c1d255d3SCy Schubert 		goto fail;
2595c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2596c1d255d3SCy Schubert 		    signature, signature_len);
2597c1d255d3SCy Schubert 	signature[signature_len - 1] ^= 0x01;
2598c1d255d3SCy Schubert 	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2599c1d255d3SCy Schubert 		    signature, signature_len);
2600c1d255d3SCy Schubert 	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2601c1d255d3SCy Schubert 	if (!signed3)
2602c1d255d3SCy Schubert 		goto fail;
2603c1d255d3SCy Schubert 	os_memcpy(pos, signed3, signed3_len);
2604c1d255d3SCy Schubert 	pos[signed3_len] = '\0';
2605c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2606c1d255d3SCy Schubert 		   pos);
2607c1d255d3SCy Schubert 
2608c1d255d3SCy Schubert out:
2609c1d255d3SCy Schubert 	os_free(signature);
2610c1d255d3SCy Schubert 	os_free(signed3);
2611c1d255d3SCy Schubert 	return tmp;
2612c1d255d3SCy Schubert fail:
2613c1d255d3SCy Schubert 	os_free(tmp);
2614c1d255d3SCy Schubert 	tmp = NULL;
2615c1d255d3SCy Schubert 	goto out;
2616c1d255d3SCy Schubert }
2617c1d255d3SCy Schubert 
2618c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
2619