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