1 /*
2  * DPP crypto functionality
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2020, The Linux Foundation
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "utils/includes.h"
11 
12 #include "utils/common.h"
13 #include "utils/base64.h"
14 #include "utils/json.h"
15 #include "common/ieee802_11_defs.h"
16 #include "crypto/crypto.h"
17 #include "crypto/random.h"
18 #include "crypto/sha384.h"
19 #include "crypto/sha512.h"
20 #include "tls/asn1.h"
21 #include "dpp.h"
22 #include "dpp_i.h"
23 
24 
25 static const struct dpp_curve_params dpp_curves[] = {
26           /* The mandatory to support and the default NIST P-256 curve needs to
27            * be the first entry on this list. */
28           { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
29           { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
30           { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
31           { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
32           { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
33           { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
34           { NULL, 0, 0, 0, 0, NULL, 0, NULL }
35 };
36 
37 
dpp_get_curve_name(const char * name)38 const struct dpp_curve_params * dpp_get_curve_name(const char *name)
39 {
40           int i;
41 
42           if (!name)
43                     return &dpp_curves[0];
44 
45           for (i = 0; dpp_curves[i].name; i++) {
46                     if (os_strcmp(name, dpp_curves[i].name) == 0 ||
47                         (dpp_curves[i].jwk_crv &&
48                          os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
49                               return &dpp_curves[i];
50           }
51           return NULL;
52 }
53 
54 
dpp_get_curve_jwk_crv(const char * name)55 const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name)
56 {
57           int i;
58 
59           for (i = 0; dpp_curves[i].name; i++) {
60                     if (dpp_curves[i].jwk_crv &&
61                         os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
62                               return &dpp_curves[i];
63           }
64           return NULL;
65 }
66 
67 
dpp_get_curve_ike_group(u16 group)68 const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
69 {
70           int i;
71 
72           for (i = 0; dpp_curves[i].name; i++) {
73                     if (dpp_curves[i].ike_group == group)
74                               return &dpp_curves[i];
75           }
76           return NULL;
77 }
78 
79 
dpp_debug_print_key(const char * title,struct crypto_ec_key * key)80 void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
81 {
82           struct wpabuf *der = NULL;
83 
84           crypto_ec_key_debug_print(key, title);
85 
86           der = crypto_ec_key_get_ecprivate_key(key, true);
87           if (der) {
88                     wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
89           } else {
90                     der = crypto_ec_key_get_subject_public_key(key);
91                     if (der)
92                               wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
93           }
94 
95           wpabuf_clear_free(der);
96 }
97 
98 
dpp_hash_vector(const struct dpp_curve_params * curve,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)99 static int dpp_hash_vector(const struct dpp_curve_params *curve,
100                                  size_t num_elem, const u8 *addr[], const size_t *len,
101                                  u8 *mac)
102 {
103           if (curve->hash_len == 32)
104                     return sha256_vector(num_elem, addr, len, mac);
105           if (curve->hash_len == 48)
106                     return sha384_vector(num_elem, addr, len, mac);
107           if (curve->hash_len == 64)
108                     return sha512_vector(num_elem, addr, len, mac);
109           return -1;
110 }
111 
112 
dpp_hkdf_expand(size_t hash_len,const u8 * secret,size_t secret_len,const char * label,u8 * out,size_t outlen)113 int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
114                         const char *label, u8 *out, size_t outlen)
115 {
116           if (hash_len == 32)
117                     return hmac_sha256_kdf(secret, secret_len, NULL,
118                                                (const u8 *) label, os_strlen(label),
119                                                out, outlen);
120           if (hash_len == 48)
121                     return hmac_sha384_kdf(secret, secret_len, NULL,
122                                                (const u8 *) label, os_strlen(label),
123                                                out, outlen);
124           if (hash_len == 64)
125                     return hmac_sha512_kdf(secret, secret_len, NULL,
126                                                (const u8 *) label, os_strlen(label),
127                                                out, outlen);
128           return -1;
129 }
130 
131 
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)132 int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
133                         size_t num_elem, const u8 *addr[], const size_t *len,
134                         u8 *mac)
135 {
136           if (hash_len == 32)
137                     return hmac_sha256_vector(key, key_len, num_elem, addr, len,
138                                                     mac);
139           if (hash_len == 48)
140                     return hmac_sha384_vector(key, key_len, num_elem, addr, len,
141                                                     mac);
142           if (hash_len == 64)
143                     return hmac_sha512_vector(key, key_len, num_elem, addr, len,
144                                                     mac);
145           return -1;
146 }
147 
148 
dpp_hmac(size_t hash_len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)149 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
150                         const u8 *data, size_t data_len, u8 *mac)
151 {
152           if (hash_len == 32)
153                     return hmac_sha256(key, key_len, data, data_len, mac);
154           if (hash_len == 48)
155                     return hmac_sha384(key, key_len, data, data_len, mac);
156           if (hash_len == 64)
157                     return hmac_sha512(key, key_len, data, data_len, mac);
158           return -1;
159 }
160 
161 
162 #ifdef CONFIG_DPP2
163 
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)164 static int dpp_pbkdf2_f(size_t hash_len,
165                               const u8 *password, size_t password_len,
166                               const u8 *salt, size_t salt_len,
167                               unsigned int iterations, unsigned int count, u8 *digest)
168 {
169           unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN];
170           unsigned int i;
171           size_t j;
172           u8 count_buf[4];
173           const u8 *addr[2];
174           size_t len[2];
175 
176           addr[0] = salt;
177           len[0] = salt_len;
178           addr[1] = count_buf;
179           len[1] = 4;
180 
181           /* F(P, S, c, i) = U1 xor U2 xor ... Uc
182            * U1 = PRF(P, S || i)
183            * U2 = PRF(P, U1)
184            * Uc = PRF(P, Uc-1)
185            */
186 
187           WPA_PUT_BE32(count_buf, count);
188           if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len,
189                                   tmp))
190                     return -1;
191           os_memcpy(digest, tmp, hash_len);
192 
193           for (i = 1; i < iterations; i++) {
194                     if (dpp_hmac(hash_len, password, password_len, tmp, hash_len,
195                                    tmp2))
196                               return -1;
197                     os_memcpy(tmp, tmp2, hash_len);
198                     for (j = 0; j < hash_len; j++)
199                               digest[j] ^= tmp2[j];
200           }
201 
202           return 0;
203 }
204 
205 
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)206 int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
207                  const u8 *salt, size_t salt_len, unsigned int iterations,
208                  u8 *buf, size_t buflen)
209 {
210           unsigned int count = 0;
211           unsigned char *pos = buf;
212           size_t left = buflen, plen;
213           unsigned char digest[DPP_MAX_HASH_LEN];
214 
215           while (left > 0) {
216                     count++;
217                     if (dpp_pbkdf2_f(hash_len, password, password_len,
218                                          salt, salt_len, iterations, count, digest))
219                               return -1;
220                     plen = left > hash_len ? hash_len : left;
221                     os_memcpy(pos, digest, plen);
222                     pos += plen;
223                     left -= plen;
224           }
225 
226           return 0;
227 }
228 
229 #endif /* CONFIG_DPP2 */
230 
231 
dpp_set_pubkey_point(struct crypto_ec_key * group_key,const u8 * buf,size_t len)232 struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
233                                                       const u8 *buf, size_t len)
234 {
235           int ike_group = crypto_ec_key_group(group_key);
236 
237           if (len & 1)
238                     return NULL;
239 
240           if (ike_group < 0) {
241                     wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
242                     return NULL;
243           }
244 
245           return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
246 }
247 
248 
dpp_get_pubkey_hash(struct crypto_ec_key * key,u8 * hash)249 int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash)
250 {
251           struct wpabuf *uncomp;
252           const u8 *addr[1];
253           size_t len[1];
254           int res;
255 
256           if (!key)
257                     return -1;
258 
259           uncomp = crypto_ec_key_get_pubkey_point(key, 1);
260           if (!uncomp)
261                     return -1;
262           addr[0] = wpabuf_head(uncomp);
263           len[0] = wpabuf_len(uncomp);
264           res = sha256_vector(1, addr, len, hash);
265           wpabuf_free(uncomp);
266           return res;
267 }
268 
269 
dpp_gen_keypair(const struct dpp_curve_params * curve)270 struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
271 {
272           struct crypto_ec_key *key;
273 
274           wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
275 
276           key = crypto_ec_key_gen(curve->ike_group);
277           if (key && wpa_debug_show_keys)
278               dpp_debug_print_key("Own generated key", key);
279 
280           return key;
281 }
282 
283 
dpp_set_keypair(const struct dpp_curve_params ** curve,const u8 * privkey,size_t privkey_len)284 struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
285                                                const u8 *privkey, size_t privkey_len)
286 {
287           struct crypto_ec_key *key;
288           int group;
289 
290           key = crypto_ec_key_parse_priv(privkey, privkey_len);
291           if (!key) {
292                     wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
293                     return NULL;
294           }
295 
296           group = crypto_ec_key_group(key);
297           if (group < 0) {
298                     crypto_ec_key_deinit(key);
299                     return NULL;
300           }
301 
302           *curve = dpp_get_curve_ike_group(group);
303           if (!*curve) {
304                     wpa_printf(MSG_INFO,
305                                  "DPP: Unsupported curve (group=%d) in pre-assigned key",
306                                  group);
307                     crypto_ec_key_deinit(key);
308                     return NULL;
309           }
310 
311           return key;
312 }
313 
314 
dpp_bootstrap_key_hash(struct dpp_bootstrap_info * bi)315 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
316 {
317           struct wpabuf *der;
318           int res;
319 
320           der = crypto_ec_key_get_subject_public_key(bi->pubkey);
321           if (!der)
322                     return -1;
323           wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
324                               der);
325           res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
326           if (res < 0)
327                     wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
328           wpabuf_free(der);
329           return res;
330 }
331 
332 
dpp_keygen(struct dpp_bootstrap_info * bi,const char * curve,const u8 * privkey,size_t privkey_len)333 int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
334                  const u8 *privkey, size_t privkey_len)
335 {
336           char *base64 = NULL;
337           char *pos, *end;
338           size_t len;
339           struct wpabuf *der = NULL;
340 
341           bi->curve = dpp_get_curve_name(curve);
342           if (!bi->curve) {
343                     wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
344                     return -1;
345           }
346 
347           if (privkey)
348                     bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
349           else
350                     bi->pubkey = dpp_gen_keypair(bi->curve);
351           if (!bi->pubkey)
352                     goto fail;
353           bi->own = 1;
354 
355           der = crypto_ec_key_get_subject_public_key(bi->pubkey);
356           if (!der)
357                     goto fail;
358           wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
359                               der);
360 
361           if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
362                     wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
363                     goto fail;
364           }
365 
366           base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
367           wpabuf_free(der);
368           der = NULL;
369           if (!base64)
370                     goto fail;
371           pos = base64;
372           end = pos + len;
373           for (;;) {
374                     pos = os_strchr(pos, '\n');
375                     if (!pos)
376                               break;
377                     os_memmove(pos, pos + 1, end - pos);
378           }
379           os_free(bi->pk);
380           bi->pk = base64;
381           return 0;
382 fail:
383           os_free(base64);
384           wpabuf_free(der);
385           return -1;
386 }
387 
388 
dpp_derive_k1(const u8 * Mx,size_t Mx_len,u8 * k1,unsigned int hash_len)389 int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len)
390 {
391           u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
392           const char *info = "first intermediate key";
393           int res;
394 
395           /* k1 = HKDF(<>, "first intermediate key", M.x) */
396 
397           /* HKDF-Extract(<>, M.x) */
398           os_memset(salt, 0, hash_len);
399           if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
400                     return -1;
401           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
402                               prk, hash_len);
403 
404           /* HKDF-Expand(PRK, info, L) */
405           res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
406           os_memset(prk, 0, hash_len);
407           if (res < 0)
408                     return -1;
409 
410           wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
411                               k1, hash_len);
412           return 0;
413 }
414 
415 
dpp_derive_k2(const u8 * Nx,size_t Nx_len,u8 * k2,unsigned int hash_len)416 int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len)
417 {
418           u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
419           const char *info = "second intermediate key";
420           int res;
421 
422           /* k2 = HKDF(<>, "second intermediate key", N.x) */
423 
424           /* HKDF-Extract(<>, N.x) */
425           os_memset(salt, 0, hash_len);
426           res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
427           if (res < 0)
428                     return -1;
429           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
430                               prk, hash_len);
431 
432           /* HKDF-Expand(PRK, info, L) */
433           res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
434           os_memset(prk, 0, hash_len);
435           if (res < 0)
436                     return -1;
437 
438           wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
439                               k2, hash_len);
440           return 0;
441 }
442 
443 
dpp_derive_bk_ke(struct dpp_authentication * auth)444 int dpp_derive_bk_ke(struct dpp_authentication *auth)
445 {
446           unsigned int hash_len = auth->curve->hash_len;
447           size_t nonce_len = auth->curve->nonce_len;
448           u8 nonces[2 * DPP_MAX_NONCE_LEN];
449           const char *info_ke = "DPP Key";
450           int res;
451           const u8 *addr[3];
452           size_t len[3];
453           size_t num_elem = 0;
454 
455           if (!auth->Mx_len || !auth->Nx_len) {
456                     wpa_printf(MSG_DEBUG,
457                                  "DPP: Mx/Nx not available - cannot derive ke");
458                     return -1;
459           }
460 
461           /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
462           os_memcpy(nonces, auth->i_nonce, nonce_len);
463           os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
464           addr[num_elem] = auth->Mx;
465           len[num_elem] = auth->Mx_len;
466           num_elem++;
467           addr[num_elem] = auth->Nx;
468           len[num_elem] = auth->Nx_len;
469           num_elem++;
470           if (auth->peer_bi && auth->own_bi) {
471                     if (!auth->Lx_len) {
472                               wpa_printf(MSG_DEBUG,
473                                            "DPP: Lx not available - cannot derive ke");
474                               return -1;
475                     }
476                     addr[num_elem] = auth->Lx;
477                     len[num_elem] = auth->secret_len;
478                     num_elem++;
479           }
480           res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
481                                     num_elem, addr, len, auth->bk);
482           if (res < 0)
483                     return -1;
484           wpa_hexdump_key(MSG_DEBUG,
485                               "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])",
486                               auth->bk, hash_len);
487 
488           /* ke = HKDF-Expand(bk, "DPP Key", length) */
489           res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke,
490                                     hash_len);
491           if (res < 0)
492                     return -1;
493 
494           wpa_hexdump_key(MSG_DEBUG,
495                               "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)",
496                               auth->ke, hash_len);
497 
498           return 0;
499 }
500 
501 
dpp_ecdh(struct crypto_ec_key * own,struct crypto_ec_key * peer,u8 * secret,size_t * secret_len)502 int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
503                u8 *secret, size_t *secret_len)
504 {
505           struct crypto_ecdh *ecdh;
506           struct wpabuf *peer_pub, *secret_buf = NULL;
507           int ret = -1;
508 
509           *secret_len = 0;
510 
511           ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
512           if (!ecdh) {
513                     wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
514                     return -1;
515           }
516 
517           peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
518           if (!peer_pub) {
519                     wpa_printf(MSG_ERROR,
520                                  "DPP: crypto_ec_key_get_pubkey_point() failed");
521                     goto fail;
522           }
523 
524           secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
525                                                        wpabuf_len(peer_pub));
526           if (!secret_buf) {
527                     wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
528                     goto fail;
529           }
530 
531           if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
532                     wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
533                     goto fail;
534           }
535 
536           *secret_len = wpabuf_len(secret_buf);
537           os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
538           ret = 0;
539 
540 fail:
541           wpabuf_clear_free(secret_buf);
542           wpabuf_free(peer_pub);
543           crypto_ecdh_deinit(ecdh);
544           return ret;
545 }
546 
547 
dpp_bi_pubkey_hash(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)548 int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
549                            const u8 *data, size_t data_len)
550 {
551           const u8 *addr[2];
552           size_t len[2];
553 
554           addr[0] = data;
555           len[0] = data_len;
556           if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
557                     return -1;
558           wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
559                         bi->pubkey_hash, SHA256_MAC_LEN);
560 
561           addr[0] = (const u8 *) "chirp";
562           len[0] = 5;
563           addr[1] = data;
564           len[1] = data_len;
565           if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
566                     return -1;
567           wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
568                         bi->pubkey_hash_chirp, SHA256_MAC_LEN);
569 
570           return 0;
571 }
572 
573 
dpp_get_subject_public_key(struct dpp_bootstrap_info * bi,const u8 * data,size_t data_len)574 int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
575                                      const u8 *data, size_t data_len)
576 {
577           struct crypto_ec_key *key;
578 
579           if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
580                     wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
581                     return -1;
582           }
583 
584           key = crypto_ec_key_parse_pub(data, data_len);
585           if (!key) {
586                     wpa_printf(MSG_DEBUG,
587                                  "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
588                     return -1;
589           }
590 
591           bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
592           if (!bi->curve) {
593                     wpa_printf(MSG_DEBUG,
594                                  "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
595                                  crypto_ec_key_group(key));
596                     goto fail;
597           }
598 
599           bi->pubkey = key;
600           return 0;
601 fail:
602           crypto_ec_key_deinit(key);
603           return -1;
604 }
605 
606 
607 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)608 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
609                            const u8 *prot_hdr, u16 prot_hdr_len,
610                            int *hash_func)
611 {
612           struct json_token *root, *token;
613           struct wpabuf *kid = NULL;
614 
615           root = json_parse((const char *) prot_hdr, prot_hdr_len);
616           if (!root) {
617                     wpa_printf(MSG_DEBUG,
618                                  "DPP: JSON parsing failed for JWS Protected Header");
619                     goto fail;
620           }
621 
622           if (root->type != JSON_OBJECT) {
623                     wpa_printf(MSG_DEBUG,
624                                  "DPP: JWS Protected Header root is not an object");
625                     goto fail;
626           }
627 
628           token = json_get_member(root, "typ");
629           if (!token || token->type != JSON_STRING) {
630                     wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
631                     goto fail;
632           }
633           wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
634                        token->string);
635           if (os_strcmp(token->string, "dppCon") != 0) {
636                     wpa_printf(MSG_DEBUG,
637                                  "DPP: Unsupported JWS Protected Header typ=%s",
638                                  token->string);
639                     goto fail;
640           }
641 
642           token = json_get_member(root, "alg");
643           if (!token || token->type != JSON_STRING) {
644                     wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
645                     goto fail;
646           }
647           wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
648                        token->string);
649           if (os_strcmp(token->string, curve->jws_alg) != 0) {
650                     wpa_printf(MSG_DEBUG,
651                                  "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
652                                  token->string, curve->jws_alg);
653                     goto fail;
654           }
655           if (os_strcmp(token->string, "ES256") == 0 ||
656               os_strcmp(token->string, "BS256") == 0) {
657                     *hash_func = CRYPTO_HASH_ALG_SHA256;
658           } else if (os_strcmp(token->string, "ES384") == 0 ||
659                        os_strcmp(token->string, "BS384") == 0) {
660                     *hash_func = CRYPTO_HASH_ALG_SHA384;
661           } else if (os_strcmp(token->string, "ES512") == 0 ||
662                        os_strcmp(token->string, "BS512") == 0) {
663                     *hash_func = CRYPTO_HASH_ALG_SHA512;
664           } else {
665                     *hash_func = -1;
666                     wpa_printf(MSG_DEBUG,
667                                  "DPP: Unsupported JWS Protected Header alg=%s",
668                                  token->string);
669                     goto fail;
670           }
671 
672           kid = json_get_member_base64url(root, "kid");
673           if (!kid) {
674                     wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
675                     goto fail;
676           }
677           wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
678                               kid);
679 
680 fail:
681           json_free(root);
682           return kid;
683 }
684 
685 
dpp_check_pubkey_match(struct crypto_ec_key * pub,struct wpabuf * r_hash)686 static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
687                                           struct wpabuf *r_hash)
688 {
689           struct wpabuf *uncomp;
690           int res;
691           u8 hash[SHA256_MAC_LEN];
692           const u8 *addr[1];
693           size_t len[1];
694 
695           if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
696                     return -1;
697           uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
698           if (!uncomp)
699                     return -1;
700           addr[0] = wpabuf_head(uncomp);
701           len[0] = wpabuf_len(uncomp);
702           wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
703                         addr[0], len[0]);
704           res = sha256_vector(1, addr, len, hash);
705           wpabuf_free(uncomp);
706           if (res < 0)
707                     return -1;
708           if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
709                     wpa_printf(MSG_DEBUG,
710                                  "DPP: Received hash value does not match calculated public key hash value");
711                     wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
712                                   hash, SHA256_MAC_LEN);
713                     return -1;
714           }
715           return 0;
716 }
717 
718 
719 enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info * info,struct crypto_ec_key * csign_pub,const char * connector)720 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
721                                    struct crypto_ec_key *csign_pub,
722                                    const char *connector)
723 {
724           enum dpp_status_error ret = 255;
725           const char *pos, *end, *signed_start, *signed_end;
726           struct wpabuf *kid = NULL;
727           unsigned char *prot_hdr = NULL, *signature = NULL;
728           size_t prot_hdr_len = 0, signature_len = 0, signed_len;
729           int res, hash_func = -1;
730           const struct dpp_curve_params *curve;
731           u8 *hash = NULL;
732 
733           curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
734           if (!curve)
735                     goto fail;
736           wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
737           os_memset(info, 0, sizeof(*info));
738 
739           signed_start = pos = connector;
740           end = os_strchr(pos, '.');
741           if (!end) {
742                     wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
743                     ret = DPP_STATUS_INVALID_CONNECTOR;
744                     goto fail;
745           }
746           prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
747           if (!prot_hdr) {
748                     wpa_printf(MSG_DEBUG,
749                                  "DPP: Failed to base64url decode signedConnector JWS Protected Header");
750                     ret = DPP_STATUS_INVALID_CONNECTOR;
751                     goto fail;
752           }
753           wpa_hexdump_ascii(MSG_DEBUG,
754                                 "DPP: signedConnector - JWS Protected Header",
755                                 prot_hdr, prot_hdr_len);
756           kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
757           if (!kid) {
758                     ret = DPP_STATUS_INVALID_CONNECTOR;
759                     goto fail;
760           }
761           if (wpabuf_len(kid) != SHA256_MAC_LEN) {
762                     wpa_printf(MSG_DEBUG,
763                                  "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
764                                  (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
765                     ret = DPP_STATUS_INVALID_CONNECTOR;
766                     goto fail;
767           }
768 
769           pos = end + 1;
770           end = os_strchr(pos, '.');
771           if (!end) {
772                     wpa_printf(MSG_DEBUG,
773                                  "DPP: Missing dot(2) in signedConnector");
774                     ret = DPP_STATUS_INVALID_CONNECTOR;
775                     goto fail;
776           }
777           signed_end = end - 1;
778           info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
779           if (!info->payload) {
780                     wpa_printf(MSG_DEBUG,
781                                  "DPP: Failed to base64url decode signedConnector JWS Payload");
782                     ret = DPP_STATUS_INVALID_CONNECTOR;
783                     goto fail;
784           }
785           wpa_hexdump_ascii(MSG_DEBUG,
786                                 "DPP: signedConnector - JWS Payload",
787                                 info->payload, info->payload_len);
788           pos = end + 1;
789           signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
790           if (!signature) {
791                     wpa_printf(MSG_DEBUG,
792                                  "DPP: Failed to base64url decode signedConnector signature");
793                     ret = DPP_STATUS_INVALID_CONNECTOR;
794                     goto fail;
795                     }
796           wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
797                         signature, signature_len);
798 
799           if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
800                     ret = DPP_STATUS_NO_MATCH;
801                     goto fail;
802           }
803 
804           if (signature_len & 0x01) {
805                     wpa_printf(MSG_DEBUG,
806                                  "DPP: Unexpected signedConnector signature length (%d)",
807                                  (int) signature_len);
808                     ret = DPP_STATUS_INVALID_CONNECTOR;
809                     goto fail;
810           }
811 
812           hash = os_malloc(curve->hash_len);
813           if (!hash)
814                     goto fail;
815 
816           signed_len = signed_end - signed_start + 1;
817           if (hash_func == CRYPTO_HASH_ALG_SHA256)
818                     res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
819                                             hash);
820           else if (hash_func == CRYPTO_HASH_ALG_SHA384)
821                     res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
822                                             hash);
823           else if (hash_func == CRYPTO_HASH_ALG_SHA512)
824                     res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
825                                             hash);
826           else
827                     goto fail;
828 
829           if (res)
830                     goto fail;
831 
832           res = crypto_ec_key_verify_signature_r_s(csign_pub,
833                                                              hash, curve->hash_len,
834                                                              signature, signature_len / 2,
835                                                              signature + signature_len / 2,
836                                                              signature_len / 2);
837           if (res != 1) {
838                     wpa_printf(MSG_DEBUG,
839                                  "DPP: signedConnector signature check failed (res=%d)",
840                                  res);
841                     ret = DPP_STATUS_INVALID_CONNECTOR;
842                     goto fail;
843           }
844 
845           ret = DPP_STATUS_OK;
846 fail:
847           os_free(hash);
848           os_free(prot_hdr);
849           wpabuf_free(kid);
850           os_free(signature);
851           return ret;
852 }
853 
854 
855 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)856 dpp_check_signed_connector(struct dpp_signed_connector_info *info,
857                                  const u8 *csign_key, size_t csign_key_len,
858                                  const u8 *peer_connector, size_t peer_connector_len)
859 {
860           struct crypto_ec_key *csign;
861           char *signed_connector = NULL;
862           enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
863 
864           csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
865           if (!csign) {
866                     wpa_printf(MSG_ERROR,
867                                  "DPP: Failed to parse local C-sign-key information");
868                     goto fail;
869           }
870 
871           wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
872                                 peer_connector, peer_connector_len);
873           signed_connector = os_malloc(peer_connector_len + 1);
874           if (!signed_connector)
875                     goto fail;
876           os_memcpy(signed_connector, peer_connector, peer_connector_len);
877           signed_connector[peer_connector_len] = '\0';
878           res = dpp_process_signed_connector(info, csign, signed_connector);
879 fail:
880           os_free(signed_connector);
881           crypto_ec_key_deinit(csign);
882           return res;
883 }
884 
885 
dpp_gen_r_auth(struct dpp_authentication * auth,u8 * r_auth)886 int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
887 {
888           struct wpabuf *pix, *prx, *bix, *brx;
889           const u8 *addr[7];
890           size_t len[7];
891           size_t i, num_elem = 0;
892           size_t nonce_len;
893           u8 zero = 0;
894           int res = -1;
895 
896           /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
897           nonce_len = auth->curve->nonce_len;
898 
899           if (auth->initiator) {
900                     pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
901                     prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
902                                                                  0);
903                     if (auth->own_bi)
904                               bix = crypto_ec_key_get_pubkey_point(
905                                         auth->own_bi->pubkey, 0);
906                     else
907                               bix = NULL;
908                     brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
909           } else {
910                     pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
911                                                                  0);
912                     prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
913                     if (auth->peer_bi)
914                               bix = crypto_ec_key_get_pubkey_point(
915                                         auth->peer_bi->pubkey, 0);
916                     else
917                               bix = NULL;
918                     brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
919           }
920           if (!pix || !prx || !brx)
921                     goto fail;
922 
923           addr[num_elem] = auth->i_nonce;
924           len[num_elem] = nonce_len;
925           num_elem++;
926 
927           addr[num_elem] = auth->r_nonce;
928           len[num_elem] = nonce_len;
929           num_elem++;
930 
931           addr[num_elem] = wpabuf_head(pix);
932           len[num_elem] = wpabuf_len(pix) / 2;
933           num_elem++;
934 
935           addr[num_elem] = wpabuf_head(prx);
936           len[num_elem] = wpabuf_len(prx) / 2;
937           num_elem++;
938 
939           if (bix) {
940                     addr[num_elem] = wpabuf_head(bix);
941                     len[num_elem] = wpabuf_len(bix) / 2;
942                     num_elem++;
943           }
944 
945           addr[num_elem] = wpabuf_head(brx);
946           len[num_elem] = wpabuf_len(brx) / 2;
947           num_elem++;
948 
949           addr[num_elem] = &zero;
950           len[num_elem] = 1;
951           num_elem++;
952 
953           wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
954           for (i = 0; i < num_elem; i++)
955                     wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
956           res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
957           if (res == 0)
958                     wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
959                                   auth->curve->hash_len);
960 fail:
961           wpabuf_free(pix);
962           wpabuf_free(prx);
963           wpabuf_free(bix);
964           wpabuf_free(brx);
965           return res;
966 }
967 
968 
dpp_gen_i_auth(struct dpp_authentication * auth,u8 * i_auth)969 int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
970 {
971           struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
972           const u8 *addr[7];
973           size_t len[7];
974           size_t i, num_elem = 0;
975           size_t nonce_len;
976           u8 one = 1;
977           int res = -1;
978 
979           /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
980           nonce_len = auth->curve->nonce_len;
981 
982           if (auth->initiator) {
983                     pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
984                     prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
985                                                                  0);
986                     if (auth->own_bi)
987                               bix = crypto_ec_key_get_pubkey_point(
988                                         auth->own_bi->pubkey, 0);
989                     else
990                               bix = NULL;
991                     if (!auth->peer_bi)
992                               goto fail;
993                     brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
994           } else {
995                     pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
996                                                                  0);
997                     prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
998                     if (auth->peer_bi)
999                               bix = crypto_ec_key_get_pubkey_point(
1000                                         auth->peer_bi->pubkey, 0);
1001                     else
1002                               bix = NULL;
1003                     if (!auth->own_bi)
1004                               goto fail;
1005                     brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
1006           }
1007           if (!pix || !prx || !brx)
1008                     goto fail;
1009 
1010           addr[num_elem] = auth->r_nonce;
1011           len[num_elem] = nonce_len;
1012           num_elem++;
1013 
1014           addr[num_elem] = auth->i_nonce;
1015           len[num_elem] = nonce_len;
1016           num_elem++;
1017 
1018           addr[num_elem] = wpabuf_head(prx);
1019           len[num_elem] = wpabuf_len(prx) / 2;
1020           num_elem++;
1021 
1022           addr[num_elem] = wpabuf_head(pix);
1023           len[num_elem] = wpabuf_len(pix) / 2;
1024           num_elem++;
1025 
1026           addr[num_elem] = wpabuf_head(brx);
1027           len[num_elem] = wpabuf_len(brx) / 2;
1028           num_elem++;
1029 
1030           if (bix) {
1031                     addr[num_elem] = wpabuf_head(bix);
1032                     len[num_elem] = wpabuf_len(bix) / 2;
1033                     num_elem++;
1034           }
1035 
1036           addr[num_elem] = &one;
1037           len[num_elem] = 1;
1038           num_elem++;
1039 
1040           wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
1041           for (i = 0; i < num_elem; i++)
1042                     wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
1043           res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
1044           if (res == 0)
1045                     wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
1046                                   auth->curve->hash_len);
1047 fail:
1048           wpabuf_free(pix);
1049           wpabuf_free(prx);
1050           wpabuf_free(bix);
1051           wpabuf_free(brx);
1052           return res;
1053 }
1054 
1055 
dpp_auth_derive_l_responder(struct dpp_authentication * auth)1056 int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
1057 {
1058           struct crypto_ec *ec;
1059           struct crypto_ec_point *L = NULL, *BI = NULL;
1060           const struct crypto_bignum *q;
1061           struct crypto_bignum *sum = NULL, *lx = NULL, *bR = NULL, *pR = NULL;
1062           int ret = -1;
1063 
1064           /* L = ((bR + pR) modulo q) * BI */
1065 
1066           ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1067           if (!ec)
1068                     goto fail;
1069 
1070           q = crypto_ec_get_order(ec);
1071           BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1072           bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1073           pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1074           sum = crypto_bignum_init();
1075           L = crypto_ec_point_init(ec);
1076           lx = crypto_bignum_init();
1077           if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
1078               crypto_bignum_addmod(bR, pR, q, sum) ||
1079               crypto_ec_point_mul(ec, BI, sum, L) ||
1080               crypto_ec_point_x(ec, L, lx) ||
1081               crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1082                                          auth->secret_len) < 0)
1083                     goto fail;
1084 
1085           wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1086           auth->Lx_len = auth->secret_len;
1087           ret = 0;
1088 fail:
1089           crypto_bignum_deinit(lx, 1);
1090           crypto_bignum_deinit(sum, 1);
1091           crypto_bignum_deinit(bR, 1);
1092           crypto_bignum_deinit(pR, 1);
1093           crypto_ec_point_deinit(L, 1);
1094           crypto_ec_point_deinit(BI, 1);
1095           crypto_ec_deinit(ec);
1096           return ret;
1097 }
1098 
1099 
dpp_auth_derive_l_initiator(struct dpp_authentication * auth)1100 int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
1101 {
1102           struct crypto_ec *ec;
1103           struct crypto_ec_point *L = NULL, *sum = NULL, *BR = NULL, *PR = NULL;
1104           struct crypto_bignum *lx = NULL, *bI = NULL;
1105           int ret = -1;
1106 
1107           /* L = bI * (BR + PR) */
1108 
1109           ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
1110           if (!ec)
1111                     goto fail;
1112 
1113           BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
1114           PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1115           bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
1116           sum = crypto_ec_point_init(ec);
1117           L = crypto_ec_point_init(ec);
1118           lx = crypto_bignum_init();
1119           if (!BR || !PR || !bI || !sum || !L || !lx ||
1120               crypto_ec_point_add(ec, BR, PR, sum) ||
1121               crypto_ec_point_mul(ec, sum, bI, L) ||
1122               crypto_ec_point_x(ec, L, lx) ||
1123               crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
1124                                          auth->secret_len) < 0)
1125                     goto fail;
1126 
1127           wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
1128           auth->Lx_len = auth->secret_len;
1129           ret = 0;
1130 fail:
1131           crypto_bignum_deinit(lx, 1);
1132           crypto_bignum_deinit(bI, 1);
1133           crypto_ec_point_deinit(sum, 1);
1134           crypto_ec_point_deinit(L, 1);
1135           crypto_ec_point_deinit(BR, 1);
1136           crypto_ec_point_deinit(PR, 1);
1137           crypto_ec_deinit(ec);
1138           return ret;
1139 }
1140 
1141 
dpp_derive_pmk(const u8 * Nx,size_t Nx_len,u8 * pmk,unsigned int hash_len)1142 int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len)
1143 {
1144           u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1145           const char *info = "DPP PMK";
1146           int res;
1147 
1148           /* PMK = HKDF(<>, "DPP PMK", N.x) */
1149 
1150           /* HKDF-Extract(<>, N.x) */
1151           os_memset(salt, 0, hash_len);
1152           if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
1153                     return -1;
1154           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
1155                               prk, hash_len);
1156 
1157           /* HKDF-Expand(PRK, info, L) */
1158           res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
1159           os_memset(prk, 0, hash_len);
1160           if (res < 0)
1161                     return -1;
1162 
1163           wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
1164                               pmk, hash_len);
1165           return 0;
1166 }
1167 
1168 
dpp_derive_pmkid(const struct dpp_curve_params * curve,struct crypto_ec_key * own_key,struct crypto_ec_key * peer_key,u8 * pmkid)1169 int dpp_derive_pmkid(const struct dpp_curve_params *curve,
1170                          struct crypto_ec_key *own_key,
1171                          struct crypto_ec_key *peer_key, u8 *pmkid)
1172 {
1173           struct wpabuf *nkx, *pkx;
1174           int ret = -1, res;
1175           const u8 *addr[2];
1176           size_t len[2];
1177           u8 hash[SHA256_MAC_LEN];
1178 
1179           /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
1180           nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
1181           pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
1182           if (!nkx || !pkx)
1183                     goto fail;
1184           addr[0] = wpabuf_head(nkx);
1185           len[0] = wpabuf_len(nkx) / 2;
1186           addr[1] = wpabuf_head(pkx);
1187           len[1] = wpabuf_len(pkx) / 2;
1188           if (len[0] != len[1])
1189                     goto fail;
1190           if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
1191                     addr[0] = wpabuf_head(pkx);
1192                     addr[1] = wpabuf_head(nkx);
1193           }
1194           wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
1195           wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
1196           res = sha256_vector(2, addr, len, hash);
1197           if (res < 0)
1198                     goto fail;
1199           wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
1200           os_memcpy(pmkid, hash, PMKID_LEN);
1201           wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
1202           ret = 0;
1203 fail:
1204           wpabuf_free(nkx);
1205           wpabuf_free(pkx);
1206           return ret;
1207 }
1208 
1209 
1210 /* Role-specific elements for PKEX */
1211 
1212 /* NIST P-256 */
1213 static const u8 pkex_init_x_p256[32] = {
1214           0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
1215           0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
1216           0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
1217           0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
1218  };
1219 static const u8 pkex_init_y_p256[32] = {
1220           0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
1221           0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
1222           0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
1223           0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
1224  };
1225 static const u8 pkex_resp_x_p256[32] = {
1226           0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
1227           0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
1228           0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
1229           0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
1230 };
1231 static const u8 pkex_resp_y_p256[32] = {
1232           0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
1233           0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
1234           0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
1235           0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
1236 };
1237 
1238 /* NIST P-384 */
1239 static const u8 pkex_init_x_p384[48] = {
1240           0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
1241           0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
1242           0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
1243           0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
1244           0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
1245           0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
1246 };
1247 static const u8 pkex_init_y_p384[48] = {
1248           0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
1249           0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
1250           0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
1251           0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
1252           0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
1253           0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
1254 };
1255 static const u8 pkex_resp_x_p384[48] = {
1256           0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
1257           0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
1258           0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
1259           0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
1260           0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
1261           0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
1262 };
1263 static const u8 pkex_resp_y_p384[48] = {
1264           0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
1265           0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
1266           0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
1267           0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
1268           0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
1269           0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
1270 };
1271 
1272 /* NIST P-521 */
1273 static const u8 pkex_init_x_p521[66] = {
1274           0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
1275           0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
1276           0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
1277           0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
1278           0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
1279           0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
1280           0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
1281           0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
1282           0x97, 0x76
1283 };
1284 static const u8 pkex_init_y_p521[66] = {
1285           0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
1286           0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
1287           0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
1288           0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
1289           0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
1290           0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
1291           0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
1292           0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
1293           0x03, 0xa8
1294 };
1295 static const u8 pkex_resp_x_p521[66] = {
1296           0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
1297           0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
1298           0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
1299           0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
1300           0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
1301           0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
1302           0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
1303           0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
1304           0x84, 0xb4
1305 };
1306 static const u8 pkex_resp_y_p521[66] = {
1307           0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
1308           0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
1309           0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
1310           0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
1311           0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
1312           0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
1313           0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
1314           0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
1315           0xce, 0xe1
1316 };
1317 
1318 /* Brainpool P-256r1 */
1319 static const u8 pkex_init_x_bp_p256r1[32] = {
1320           0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
1321           0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
1322           0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
1323           0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
1324 };
1325 static const u8 pkex_init_y_bp_p256r1[32] = {
1326           0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
1327           0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
1328           0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
1329           0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
1330 };
1331 static const u8 pkex_resp_x_bp_p256r1[32] = {
1332           0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
1333           0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
1334           0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
1335           0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
1336 };
1337 static const u8 pkex_resp_y_bp_p256r1[32] = {
1338           0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
1339           0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
1340           0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
1341           0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
1342 };
1343 
1344 /* Brainpool P-384r1 */
1345 static const u8 pkex_init_x_bp_p384r1[48] = {
1346           0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
1347           0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
1348           0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
1349           0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
1350           0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
1351           0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
1352 };
1353 static const u8 pkex_init_y_bp_p384r1[48] = {
1354           0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
1355           0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
1356           0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
1357           0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
1358           0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
1359           0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
1360 };
1361 static const u8 pkex_resp_x_bp_p384r1[48] = {
1362           0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
1363           0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
1364           0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
1365           0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
1366           0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
1367           0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
1368 };
1369 static const u8 pkex_resp_y_bp_p384r1[48] = {
1370           0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
1371           0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
1372           0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
1373           0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
1374           0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
1375           0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
1376 };
1377 
1378 /* Brainpool P-512r1 */
1379 static const u8 pkex_init_x_bp_p512r1[64] = {
1380           0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
1381           0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
1382           0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
1383           0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
1384           0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
1385           0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
1386           0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
1387           0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
1388 };
1389 static const u8 pkex_init_y_bp_p512r1[64] = {
1390           0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
1391           0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
1392           0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
1393           0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
1394           0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
1395           0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
1396           0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
1397           0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
1398 };
1399 static const u8 pkex_resp_x_bp_p512r1[64] = {
1400           0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
1401           0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
1402           0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
1403           0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
1404           0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
1405           0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
1406           0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
1407           0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
1408 };
1409 static const u8 pkex_resp_y_bp_p512r1[64] = {
1410           0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
1411           0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
1412           0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
1413           0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
1414           0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
1415           0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
1416           0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
1417           0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
1418 };
1419 
1420 
1421 static struct crypto_ec_key *
dpp_pkex_get_role_elem(const struct dpp_curve_params * curve,int init)1422 dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
1423 {
1424           const u8 *x, *y;
1425 
1426           switch (curve->ike_group) {
1427           case 19:
1428                     x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
1429                     y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
1430                     break;
1431           case 20:
1432                     x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
1433                     y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
1434                     break;
1435           case 21:
1436                     x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
1437                     y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
1438                     break;
1439           case 28:
1440                     x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
1441                     y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
1442                     break;
1443           case 29:
1444                     x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
1445                     y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
1446                     break;
1447           case 30:
1448                     x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
1449                     y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
1450                     break;
1451           default:
1452                     return NULL;
1453           }
1454 
1455           return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
1456 }
1457 
1458 
1459 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)1460 dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
1461                        const char *code, size_t code_len, const char *identifier,
1462                        struct crypto_ec **ret_ec)
1463 {
1464           u8 hash[DPP_MAX_HASH_LEN];
1465           const u8 *addr[3];
1466           size_t len[3];
1467           unsigned int num_elem = 0;
1468           struct crypto_ec_point *Qi = NULL, *Pi = NULL;
1469           struct crypto_ec_key *Pi_key = NULL;
1470           struct crypto_bignum *hash_bn = NULL;
1471           struct crypto_ec *ec = NULL;
1472 
1473           /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
1474 
1475           if (mac_init) {
1476                     wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
1477                                  MAC2STR(mac_init));
1478                     addr[num_elem] = mac_init;
1479                     len[num_elem] = ETH_ALEN;
1480                     num_elem++;
1481           }
1482           if (identifier) {
1483                     wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1484                                  identifier);
1485                     addr[num_elem] = (const u8 *) identifier;
1486                     len[num_elem] = os_strlen(identifier);
1487                     num_elem++;
1488           }
1489           wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1490           addr[num_elem] = (const u8 *) code;
1491           len[num_elem] = code_len;
1492           num_elem++;
1493           if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1494                     goto fail;
1495           wpa_hexdump_key(MSG_DEBUG,
1496                               "DPP: H([MAC-Initiator |] [identifier |] code)",
1497                               hash, curve->hash_len);
1498           Pi_key = dpp_pkex_get_role_elem(curve, 1);
1499           if (!Pi_key)
1500                     goto fail;
1501           dpp_debug_print_key("DPP: Pi", Pi_key);
1502 
1503           ec = crypto_ec_init(curve->ike_group);
1504           if (!ec)
1505                     goto fail;
1506 
1507           Pi = crypto_ec_key_get_public_key(Pi_key);
1508           Qi = crypto_ec_point_init(ec);
1509           hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1510           if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
1511                     goto fail;
1512 
1513           if (crypto_ec_point_is_at_infinity(ec, Qi)) {
1514                     wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
1515                     goto fail;
1516           }
1517           crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
1518 out:
1519           crypto_ec_key_deinit(Pi_key);
1520           crypto_ec_point_deinit(Pi, 1);
1521           crypto_bignum_deinit(hash_bn, 1);
1522           if (ret_ec && Qi)
1523                     *ret_ec = ec;
1524           else
1525                     crypto_ec_deinit(ec);
1526           return Qi;
1527 fail:
1528           crypto_ec_point_deinit(Qi, 1);
1529           Qi = NULL;
1530           goto out;
1531 }
1532 
1533 
1534 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)1535 dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
1536                        const char *code, size_t code_len, const char *identifier,
1537                        struct crypto_ec **ret_ec)
1538 {
1539           u8 hash[DPP_MAX_HASH_LEN];
1540           const u8 *addr[3];
1541           size_t len[3];
1542           unsigned int num_elem = 0;
1543           struct crypto_ec_point *Qr = NULL, *Pr = NULL;
1544           struct crypto_ec_key *Pr_key = NULL;
1545           struct crypto_bignum *hash_bn = NULL;
1546           struct crypto_ec *ec = NULL;
1547 
1548           /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
1549 
1550           if (mac_resp) {
1551                     wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
1552                                  MAC2STR(mac_resp));
1553                     addr[num_elem] = mac_resp;
1554                     len[num_elem] = ETH_ALEN;
1555                     num_elem++;
1556           }
1557           if (identifier) {
1558                     wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
1559                                  identifier);
1560                     addr[num_elem] = (const u8 *) identifier;
1561                     len[num_elem] = os_strlen(identifier);
1562                     num_elem++;
1563           }
1564           wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
1565           addr[num_elem] = (const u8 *) code;
1566           len[num_elem] = code_len;
1567           num_elem++;
1568           if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
1569                     goto fail;
1570           wpa_hexdump_key(MSG_DEBUG,
1571                               "DPP: H([MAC-Responder |] [identifier |] code)",
1572                               hash, curve->hash_len);
1573           Pr_key = dpp_pkex_get_role_elem(curve, 0);
1574           if (!Pr_key)
1575                     goto fail;
1576           dpp_debug_print_key("DPP: Pr", Pr_key);
1577 
1578           ec = crypto_ec_init(curve->ike_group);
1579           if (!ec)
1580                     goto fail;
1581 
1582           Pr = crypto_ec_key_get_public_key(Pr_key);
1583           Qr = crypto_ec_point_init(ec);
1584           hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
1585           if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
1586                     goto fail;
1587 
1588           if (crypto_ec_point_is_at_infinity(ec, Qr)) {
1589                     wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
1590                     goto fail;
1591           }
1592           crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
1593 
1594 out:
1595           crypto_ec_key_deinit(Pr_key);
1596           crypto_ec_point_deinit(Pr, 1);
1597           crypto_bignum_deinit(hash_bn, 1);
1598           if (ret_ec && Qr)
1599                     *ret_ec = ec;
1600           else
1601                     crypto_ec_deinit(ec);
1602           return Qr;
1603 fail:
1604           crypto_ec_point_deinit(Qr, 1);
1605           Qr = NULL;
1606           goto out;
1607 }
1608 
1609 
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)1610 int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
1611                           u8 ver_init, u8 ver_resp,
1612                           const u8 *Mx, size_t Mx_len,
1613                           const u8 *Nx, size_t Nx_len,
1614                           const char *code, size_t code_len,
1615                           const u8 *Kx, size_t Kx_len,
1616                           u8 *z, unsigned int hash_len)
1617 {
1618           u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
1619           int res;
1620           u8 *info, *pos;
1621           size_t info_len;
1622 
1623           /*
1624            * v1: info = MAC-Initiator | MAC-Responder
1625            * v2: info = Protocol Version-Initiator | Protocol Version-Responder
1626            * z = HKDF(<>, info | M.x | N.x | code, K.x)
1627            */
1628 
1629           /* HKDF-Extract(<>, IKM=K.x) */
1630           os_memset(salt, 0, hash_len);
1631           if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
1632                     return -1;
1633           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
1634                               prk, hash_len);
1635           if (mac_init && mac_resp)
1636                     info_len = 2 * ETH_ALEN;
1637           else
1638                     info_len = 2;
1639           info_len += Mx_len + Nx_len + code_len;
1640           info = os_malloc(info_len);
1641           if (!info)
1642                     return -1;
1643           pos = info;
1644           if (mac_init && mac_resp) {
1645                     os_memcpy(pos, mac_init, ETH_ALEN);
1646                     pos += ETH_ALEN;
1647                     os_memcpy(pos, mac_resp, ETH_ALEN);
1648                     pos += ETH_ALEN;
1649           } else {
1650                     *pos++ = ver_init;
1651                     *pos++ = ver_resp;
1652           }
1653           os_memcpy(pos, Mx, Mx_len);
1654           pos += Mx_len;
1655           os_memcpy(pos, Nx, Nx_len);
1656           pos += Nx_len;
1657           os_memcpy(pos, code, code_len);
1658 
1659           /* HKDF-Expand(PRK, info, L) */
1660           if (hash_len == 32)
1661                     res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
1662                                               z, hash_len);
1663           else if (hash_len == 48)
1664                     res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
1665                                               z, hash_len);
1666           else if (hash_len == 64)
1667                     res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
1668                                               z, hash_len);
1669           else
1670                     res = -1;
1671           os_free(info);
1672           os_memset(prk, 0, hash_len);
1673           if (res < 0)
1674                     return -1;
1675 
1676           wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
1677                               z, hash_len);
1678           return 0;
1679 }
1680 
1681 
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)1682 int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
1683                                              const u8 *net_access_key,
1684                                              size_t net_access_key_len,
1685                                              struct json_token *peer_net_access_key)
1686 {
1687           struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
1688           struct crypto_bignum *sum = NULL, *cR = NULL, *pR = NULL;
1689           const struct crypto_bignum *q;
1690           struct crypto_ec *ec = NULL;
1691           struct crypto_ec_point *M = NULL, *CI = NULL;
1692           u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1693           u8 prk[DPP_MAX_HASH_LEN];
1694           const struct dpp_curve_params *curve;
1695           int res = -1;
1696           u8 nonces[2 * DPP_MAX_NONCE_LEN];
1697 
1698           own_key = dpp_set_keypair(&auth->curve, net_access_key,
1699                                           net_access_key_len);
1700           if (!own_key) {
1701                     dpp_auth_fail(auth, "Failed to parse own netAccessKey");
1702                     goto fail;
1703           }
1704 
1705           peer_key = dpp_parse_jwk(peer_net_access_key, &curve);
1706           if (!peer_key)
1707                     goto fail;
1708           dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1709 
1710           if (auth->curve != curve) {
1711                     wpa_printf(MSG_DEBUG,
1712                                  "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1713                                  auth->curve->name, curve->name);
1714                     goto fail;
1715           }
1716 
1717           auth->own_protocol_key = dpp_gen_keypair(curve);
1718           if (!auth->own_protocol_key)
1719                     goto fail;
1720 
1721           if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) {
1722                     wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
1723                     goto fail;
1724           }
1725           wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce",
1726                               auth->e_nonce, auth->curve->nonce_len);
1727 
1728           /* M = { cR + pR } * CI */
1729           ec = crypto_ec_init(curve->ike_group);
1730           if (!ec)
1731                     goto fail;
1732 
1733           sum = crypto_bignum_init();
1734           q = crypto_ec_get_order(ec);
1735           M = crypto_ec_point_init(ec);
1736           cR = crypto_ec_key_get_private_key(own_key);
1737           pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
1738           CI = crypto_ec_key_get_public_key(peer_key);
1739           if (!sum || !q || !M || !cR || !pR || !CI ||
1740               crypto_bignum_addmod(cR, pR, q, sum) ||
1741               crypto_ec_point_mul(ec, CI, sum, M) ||
1742               crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1743                     wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1744                     goto fail;
1745           }
1746           wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1747 
1748           /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1749 
1750           /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1751           os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1752           os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1753           if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1754                          Mx, curve->prime_len, prk) < 0)
1755                     goto fail;
1756           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1757 
1758           /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1759           if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1760                                   "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1761                     goto fail;
1762           wpa_hexdump_key(MSG_DEBUG,
1763                               "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1764                               auth->ke, curve->hash_len);
1765 
1766           res = 0;
1767           crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1768           auth->reconfig_old_protocol_key = own_key;
1769           own_key = NULL;
1770 fail:
1771           forced_memzero(prk, sizeof(prk));
1772           forced_memzero(Mx, sizeof(Mx));
1773           crypto_ec_point_deinit(M, 1);
1774           crypto_ec_point_deinit(CI, 1);
1775           crypto_bignum_deinit(sum, 1);
1776           crypto_bignum_deinit(cR, 1);
1777           crypto_bignum_deinit(pR, 1);
1778           crypto_ec_key_deinit(own_key);
1779           crypto_ec_key_deinit(peer_key);
1780           crypto_ec_deinit(ec);
1781           return res;
1782 }
1783 
1784 
dpp_reconfig_derive_ke_initiator(struct dpp_authentication * auth,const u8 * r_proto,u16 r_proto_len,struct json_token * net_access_key)1785 int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
1786                                              const u8 *r_proto, u16 r_proto_len,
1787                                              struct json_token *net_access_key)
1788 {
1789           struct crypto_ec_key *pr = NULL, *peer_key = NULL;
1790           struct crypto_bignum *cI = NULL;
1791           struct crypto_ec *ec = NULL;
1792           struct crypto_ec_point *sum = NULL, *M = NULL, *CR = NULL, *PR = NULL;
1793           u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
1794           u8 prk[DPP_MAX_HASH_LEN];
1795           int res = -1;
1796           const struct dpp_curve_params *curve;
1797           u8 nonces[2 * DPP_MAX_NONCE_LEN];
1798 
1799           pr = dpp_set_pubkey_point(auth->conf->connector_key,
1800                                           r_proto, r_proto_len);
1801           if (!pr) {
1802                     dpp_auth_fail(auth, "Invalid Responder Protocol Key");
1803                     goto fail;
1804           }
1805           dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
1806           crypto_ec_key_deinit(auth->peer_protocol_key);
1807           auth->peer_protocol_key = pr;
1808           pr = NULL;
1809 
1810           peer_key = dpp_parse_jwk(net_access_key, &curve);
1811           if (!peer_key)
1812                     goto fail;
1813           dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
1814           if (auth->curve != curve) {
1815                     wpa_printf(MSG_DEBUG,
1816                                  "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)",
1817                                  auth->curve->name, curve->name);
1818                     goto fail;
1819           }
1820 
1821           /* M = cI * { CR + PR } */
1822           ec = crypto_ec_init(curve->ike_group);
1823           if (!ec)
1824                     goto fail;
1825 
1826           cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
1827           sum = crypto_ec_point_init(ec);
1828           M = crypto_ec_point_init(ec);
1829           CR = crypto_ec_key_get_public_key(peer_key);
1830           PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
1831           if (!cI || !sum || !M || !CR || !PR ||
1832               crypto_ec_point_add(ec, CR, PR, sum) ||
1833               crypto_ec_point_mul(ec, sum, cI, M) ||
1834               crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
1835                     wpa_printf(MSG_ERROR, "DPP: Error during M computation");
1836                     goto fail;
1837           }
1838 
1839           wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
1840 
1841           /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
1842 
1843           /* HKDF-Extract(C-nonce | E-nonce, M.x) */
1844           os_memcpy(nonces, auth->c_nonce, curve->nonce_len);
1845           os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len);
1846           if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len,
1847                          Mx, curve->prime_len, prk) < 0)
1848                     goto fail;
1849           wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len);
1850 
1851           /* HKDF-Expand(PRK, "dpp reconfig key", L) */
1852           if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len,
1853                                   "dpp reconfig key", auth->ke, curve->hash_len) < 0)
1854                     goto fail;
1855           wpa_hexdump_key(MSG_DEBUG,
1856                               "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)",
1857                               auth->ke, curve->hash_len);
1858 
1859           res = 0;
1860 fail:
1861           forced_memzero(prk, sizeof(prk));
1862           forced_memzero(Mx, sizeof(Mx));
1863           crypto_bignum_deinit(cI, 1);
1864           crypto_ec_key_deinit(pr);
1865           crypto_ec_key_deinit(peer_key);
1866           crypto_ec_point_deinit(sum, 1);
1867           crypto_ec_point_deinit(M, 1);
1868           crypto_ec_point_deinit(CR, 1);
1869           crypto_ec_point_deinit(PR, 1);
1870           crypto_ec_deinit(ec);
1871           return res;
1872 }
1873 
1874 
1875 static char *
dpp_build_jws_prot_hdr(struct dpp_configurator * conf,size_t * signed1_len)1876 dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
1877 {
1878           struct wpabuf *jws_prot_hdr;
1879           char *signed1;
1880 
1881           jws_prot_hdr = wpabuf_alloc(100);
1882           if (!jws_prot_hdr)
1883                     return NULL;
1884           json_start_object(jws_prot_hdr, NULL);
1885           json_add_string(jws_prot_hdr, "typ", "dppCon");
1886           json_value_sep(jws_prot_hdr);
1887           json_add_string(jws_prot_hdr, "kid", conf->kid);
1888           json_value_sep(jws_prot_hdr);
1889           json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
1890           json_end_object(jws_prot_hdr);
1891           signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
1892                                             wpabuf_len(jws_prot_hdr),
1893                                             signed1_len);
1894           wpabuf_free(jws_prot_hdr);
1895           return signed1;
1896 }
1897 
1898 
1899 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)1900 dpp_build_conn_signature(struct dpp_configurator *conf,
1901                                const char *signed1, size_t signed1_len,
1902                                const char *signed2, size_t signed2_len,
1903                                size_t *signed3_len)
1904 {
1905           const struct dpp_curve_params *curve;
1906           struct wpabuf *sig = NULL;
1907           char *signed3 = NULL;
1908           char *dot = ".";
1909           const u8 *vector[3];
1910           size_t vector_len[3];
1911           u8 *hash;
1912           int ret;
1913 
1914           vector[0] = (const u8 *) signed1;
1915           vector[1] = (const u8 *) dot;
1916           vector[2] = (const u8 *) signed2;
1917           vector_len[0] = signed1_len;
1918           vector_len[1] = 1;
1919           vector_len[2] = signed2_len;
1920 
1921           curve = conf->curve;
1922           hash = os_malloc(curve->hash_len);
1923           if (!hash)
1924                     goto fail;
1925           if (curve->hash_len == SHA256_MAC_LEN) {
1926                     ret = sha256_vector(3, vector, vector_len, hash);
1927           } else if (curve->hash_len == SHA384_MAC_LEN) {
1928                     ret = sha384_vector(3, vector, vector_len, hash);
1929           } else if (curve->hash_len == SHA512_MAC_LEN) {
1930                     ret = sha512_vector(3, vector, vector_len, hash);
1931           } else {
1932                     wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
1933                     goto fail;
1934           }
1935           if (ret) {
1936                     wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
1937                     goto fail;
1938           }
1939           wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
1940                         hash, curve->hash_len);
1941 
1942           sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
1943           if (!sig) {
1944                     wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
1945                     goto fail;
1946           }
1947 
1948           wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
1949                         wpabuf_head(sig), wpabuf_len(sig));
1950           signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
1951                                             signed3_len);
1952 
1953 fail:
1954           os_free(hash);
1955           wpabuf_free(sig);
1956           return signed3;
1957 }
1958 
dpp_sign_connector(struct dpp_configurator * conf,const struct wpabuf * dppcon)1959 char * dpp_sign_connector(struct dpp_configurator *conf,
1960                                 const struct wpabuf *dppcon)
1961 {
1962           char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
1963           char *signed_conn = NULL, *pos;
1964           size_t signed1_len, signed2_len, signed3_len;
1965 
1966           signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
1967           signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
1968                                             &signed2_len);
1969           if (!signed1 || !signed2)
1970                     goto fail;
1971 
1972           signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
1973                                                      signed2, signed2_len, &signed3_len);
1974           if (!signed3)
1975                     goto fail;
1976 
1977           signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
1978           if (!signed_conn)
1979                     goto fail;
1980           pos = signed_conn;
1981           os_memcpy(pos, signed1, signed1_len);
1982           pos += signed1_len;
1983           *pos++ = '.';
1984           os_memcpy(pos, signed2, signed2_len);
1985           pos += signed2_len;
1986           *pos++ = '.';
1987           os_memcpy(pos, signed3, signed3_len);
1988           pos += signed3_len;
1989           *pos = '\0';
1990 
1991 fail:
1992           os_free(signed1);
1993           os_free(signed2);
1994           os_free(signed3);
1995           return signed_conn;
1996 }
1997 
1998 
1999 #ifdef CONFIG_DPP2
2000 
dpp_pfs_init(const u8 * net_access_key,size_t net_access_key_len)2001 struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
2002                                     size_t net_access_key_len)
2003 {
2004           struct wpabuf *pub = NULL;
2005           struct crypto_ec_key *own_key;
2006           struct dpp_pfs *pfs;
2007 
2008           pfs = os_zalloc(sizeof(*pfs));
2009           if (!pfs)
2010                     return NULL;
2011 
2012           own_key = dpp_set_keypair(&pfs->curve, net_access_key,
2013                                           net_access_key_len);
2014           if (!own_key) {
2015                     wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2016                     goto fail;
2017           }
2018           crypto_ec_key_deinit(own_key);
2019 
2020           pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
2021           if (!pfs->ecdh)
2022                     goto fail;
2023 
2024           pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
2025           pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
2026           if (!pub)
2027                     goto fail;
2028 
2029           pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
2030           if (!pfs->ie)
2031                     goto fail;
2032           wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
2033           wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
2034           wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
2035           wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
2036           wpabuf_put_buf(pfs->ie, pub);
2037           wpabuf_free(pub);
2038           wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
2039                               pfs->ie);
2040 
2041           return pfs;
2042 fail:
2043           wpabuf_free(pub);
2044           dpp_pfs_free(pfs);
2045           return NULL;
2046 }
2047 
2048 
dpp_pfs_process(struct dpp_pfs * pfs,const u8 * peer_ie,size_t peer_ie_len)2049 int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
2050 {
2051           if (peer_ie_len < 2)
2052                     return -1;
2053           if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
2054                     wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
2055                     return -1;
2056           }
2057 
2058           pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
2059                                                         peer_ie_len - 2);
2060           pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
2061           if (!pfs->secret) {
2062                     wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
2063                     return -1;
2064           }
2065           wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
2066           return 0;
2067 }
2068 
2069 
dpp_pfs_free(struct dpp_pfs * pfs)2070 void dpp_pfs_free(struct dpp_pfs *pfs)
2071 {
2072           if (!pfs)
2073                     return;
2074           crypto_ecdh_deinit(pfs->ecdh);
2075           wpabuf_free(pfs->ie);
2076           wpabuf_clear_free(pfs->secret);
2077           os_free(pfs);
2078 }
2079 
2080 
dpp_build_csr(struct dpp_authentication * auth,const char * name)2081 struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
2082 {
2083           struct crypto_csr *csr = NULL;
2084           struct wpabuf *buf = NULL;
2085           struct crypto_ec_key *key;
2086           unsigned int hash_len = auth->curve->hash_len;
2087           struct wpabuf *priv_key;
2088           u8 cp[DPP_CP_LEN];
2089           char *password = NULL;
2090           size_t password_len = 0;
2091           int hash_sign_algo;
2092 
2093           /* TODO: use auth->csrattrs */
2094 
2095           /* TODO: support generation of a new private key if csrAttrs requests
2096            * a specific group to be used */
2097           key = auth->own_protocol_key;
2098 
2099           priv_key = crypto_ec_key_get_ecprivate_key(key, true);
2100           if (!priv_key)
2101                     goto fail;
2102           wpabuf_free(auth->priv_key);
2103           auth->priv_key = priv_key;
2104 
2105           csr = crypto_csr_init();
2106           if (!csr || crypto_csr_set_ec_public_key(csr, key))
2107                     goto fail;
2108 
2109           if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
2110                     goto fail;
2111 
2112           /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2113           if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2114                                   "CSR challengePassword", cp, DPP_CP_LEN) < 0)
2115                     goto fail;
2116           wpa_hexdump_key(MSG_DEBUG,
2117                               "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2118                               cp, DPP_CP_LEN);
2119           password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
2120           forced_memzero(cp, DPP_CP_LEN);
2121           if (!password ||
2122               crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2123                                              ASN1_TAG_UTF8STRING, (const u8 *) password,
2124                                              password_len))
2125                     goto fail;
2126 
2127           /* TODO: hash func selection based on csrAttrs */
2128           if (hash_len == SHA256_MAC_LEN) {
2129                     hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
2130           } else if (hash_len == SHA384_MAC_LEN) {
2131                     hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
2132           } else if (hash_len == SHA512_MAC_LEN) {
2133                     hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
2134           } else {
2135                     wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
2136                     goto fail;
2137           }
2138 
2139           buf = crypto_csr_sign(csr, key, hash_sign_algo);
2140           if (!buf)
2141                     goto fail;
2142           wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
2143 
2144 fail:
2145           bin_clear_free(password, password_len);
2146           crypto_csr_deinit(csr);
2147           return buf;
2148 }
2149 
2150 
dpp_validate_csr(struct dpp_authentication * auth,const struct wpabuf * csrbuf)2151 int dpp_validate_csr(struct dpp_authentication *auth,
2152                          const struct wpabuf *csrbuf)
2153 {
2154           struct crypto_csr *csr;
2155           const u8 *attr;
2156           size_t attr_len;
2157           int attr_type;
2158           unsigned char *cp = NULL;
2159           size_t cp_len;
2160           u8 exp_cp[DPP_CP_LEN];
2161           unsigned int hash_len = auth->curve->hash_len;
2162           int ret = -1;
2163 
2164           csr = crypto_csr_verify(csrbuf);
2165           if (!csr) {
2166                     wpa_printf(MSG_DEBUG,
2167                                  "DPP: CSR invalid or invalid signature");
2168                     goto fail;
2169           }
2170 
2171           attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
2172                                                   &attr_len, &attr_type);
2173           if (!attr) {
2174                     wpa_printf(MSG_DEBUG,
2175                                  "DPP: CSR does not include challengePassword");
2176                     goto fail;
2177           }
2178           /* This is supposed to be UTF8String, but allow other strings as well
2179            * since challengePassword is using ASCII (base64 encoded). */
2180           if (attr_type != ASN1_TAG_UTF8STRING &&
2181               attr_type != ASN1_TAG_PRINTABLESTRING &&
2182               attr_type != ASN1_TAG_IA5STRING) {
2183                     wpa_printf(MSG_DEBUG,
2184                                  "DPP: Unexpected challengePassword attribute type %d",
2185                                  attr_type);
2186                     goto fail;
2187           }
2188 
2189           cp = base64_decode((const char *) attr, attr_len, &cp_len);
2190           if (!cp) {
2191                     wpa_printf(MSG_DEBUG,
2192                                  "DPP: Could not base64 decode challengePassword");
2193                     goto fail;
2194           }
2195           if (cp_len != DPP_CP_LEN) {
2196                     wpa_printf(MSG_DEBUG,
2197                                  "DPP: Unexpected cp length (%zu) in CSR challengePassword",
2198                                  cp_len);
2199                     goto fail;
2200           }
2201           wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
2202                               cp, cp_len);
2203 
2204           /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
2205           if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
2206                                   "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
2207                     goto fail;
2208           wpa_hexdump_key(MSG_DEBUG,
2209                               "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
2210                               exp_cp, DPP_CP_LEN);
2211           if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
2212                     wpa_printf(MSG_DEBUG,
2213                                  "DPP: CSR challengePassword does not match calculated cp");
2214                     goto fail;
2215           }
2216 
2217           ret = 0;
2218 fail:
2219           os_free(cp);
2220           crypto_csr_deinit(csr);
2221           return ret;
2222 }
2223 
2224 
dpp_gen_reconfig_id(const u8 * csign_key,size_t csign_key_len,const u8 * pp_key,size_t pp_key_len)2225 struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
2226                                                        size_t csign_key_len,
2227                                                        const u8 *pp_key,
2228                                                        size_t pp_key_len)
2229 {
2230           struct crypto_ec_key *csign = NULL, *ppkey = NULL;
2231           struct dpp_reconfig_id *id = NULL;
2232           struct crypto_ec *ec = NULL;
2233           const struct crypto_bignum *q;
2234           struct crypto_bignum *bn = NULL;
2235           struct crypto_ec_point *e_id = NULL;
2236           const struct crypto_ec_point *generator;
2237 
2238           csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
2239           if (!csign)
2240                     goto fail;
2241 
2242           if (!pp_key)
2243                     goto fail;
2244           ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
2245           if (!ppkey)
2246                     goto fail;
2247 
2248           ec = crypto_ec_init(crypto_ec_key_group(csign));
2249           if (!ec)
2250                     goto fail;
2251 
2252           e_id = crypto_ec_point_init(ec);
2253           bn = crypto_bignum_init();
2254           q = crypto_ec_get_order(ec);
2255           generator = crypto_ec_get_generator(ec);
2256           if (!e_id || !bn || !q || !generator ||
2257               crypto_bignum_rand(bn, q) ||
2258               crypto_ec_point_mul(ec, generator, bn, e_id))
2259                     goto fail;
2260 
2261           crypto_ec_point_debug_print(ec, e_id,
2262                                             "DPP: Generated random point E-id");
2263 
2264           id = os_zalloc(sizeof(*id));
2265           if (!id)
2266                     goto fail;
2267 
2268           id->ec = ec;
2269           ec = NULL;
2270           id->e_id = e_id;
2271           e_id = NULL;
2272           id->csign = csign;
2273           csign = NULL;
2274           id->pp_key = ppkey;
2275           ppkey = NULL;
2276 fail:
2277           crypto_ec_point_deinit(e_id, 1);
2278           crypto_ec_key_deinit(csign);
2279           crypto_ec_key_deinit(ppkey);
2280           crypto_bignum_deinit(bn, 1);
2281           crypto_ec_deinit(ec);
2282           return id;
2283 }
2284 
2285 
dpp_update_reconfig_id(struct dpp_reconfig_id * id)2286 int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
2287 {
2288           const struct crypto_bignum *q;
2289           struct crypto_bignum *bn;
2290           const struct crypto_ec_point *generator;
2291           struct crypto_ec_point *e_prime_id, *a_nonce, *pp;
2292           int ret = -1;
2293 
2294           pp = crypto_ec_key_get_public_key(id->pp_key);
2295           e_prime_id = crypto_ec_point_init(id->ec);
2296           a_nonce = crypto_ec_point_init(id->ec);
2297           bn = crypto_bignum_init();
2298           q = crypto_ec_get_order(id->ec);
2299           generator = crypto_ec_get_generator(id->ec);
2300 
2301           /* Generate random 0 <= a-nonce < q
2302            * A-NONCE = a-nonce * G
2303            * E'-id = E-id + a-nonce * P_pk */
2304           if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
2305               crypto_bignum_rand(bn, q) || /* bn = a-nonce */
2306               crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
2307               crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
2308               crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
2309                     goto fail;
2310 
2311           crypto_ec_point_debug_print(id->ec, a_nonce,
2312                                             "DPP: Generated A-NONCE");
2313           crypto_ec_point_debug_print(id->ec, e_prime_id,
2314                                             "DPP: Encrypted E-id to E'-id");
2315 
2316           crypto_ec_key_deinit(id->a_nonce);
2317           crypto_ec_key_deinit(id->e_prime_id);
2318           id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
2319           id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
2320           if (!id->a_nonce || !id->e_prime_id)
2321                     goto fail;
2322 
2323           ret = 0;
2324 
2325 fail:
2326           crypto_ec_point_deinit(e_prime_id, 1);
2327           crypto_ec_point_deinit(a_nonce, 1);
2328           crypto_ec_point_deinit(pp, 1);
2329           crypto_bignum_deinit(bn, 1);
2330           return ret;
2331 }
2332 
2333 
dpp_free_reconfig_id(struct dpp_reconfig_id * id)2334 void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
2335 {
2336           if (id) {
2337                     crypto_ec_point_deinit(id->e_id, 1);
2338                     crypto_ec_key_deinit(id->csign);
2339                     crypto_ec_key_deinit(id->a_nonce);
2340                     crypto_ec_key_deinit(id->e_prime_id);
2341                     crypto_ec_key_deinit(id->pp_key);
2342                     crypto_ec_deinit(id->ec);
2343                     os_free(id);
2344           }
2345 }
2346 
2347 
dpp_decrypt_e_id(struct crypto_ec_key * ppkey,struct crypto_ec_key * a_nonce,struct crypto_ec_key * e_prime_id)2348 struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
2349                                                     struct crypto_ec_key *a_nonce,
2350                                                     struct crypto_ec_key *e_prime_id)
2351 {
2352           struct crypto_ec *ec;
2353           struct crypto_bignum *pp = NULL;
2354           struct crypto_ec_point *e_id = NULL;
2355           struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
2356 
2357           if (!ppkey)
2358                     return NULL;
2359 
2360           /* E-id = E'-id - s_C * A-NONCE */
2361           ec = crypto_ec_init(crypto_ec_key_group(ppkey));
2362           if (!ec)
2363                     return NULL;
2364 
2365           pp = crypto_ec_key_get_private_key(ppkey);
2366           a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
2367           e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
2368           e_id = crypto_ec_point_init(ec);
2369           if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
2370               crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
2371               crypto_ec_point_invert(ec, e_id) ||
2372               crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
2373                     crypto_ec_point_deinit(e_id, 1);
2374                     goto fail;
2375           }
2376 
2377           crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
2378 
2379 fail:
2380           crypto_ec_point_deinit(a_nonce_point, 1);
2381           crypto_ec_point_deinit(e_prime_id_point, 1);
2382           crypto_bignum_deinit(pp, 1);
2383           crypto_ec_deinit(ec);
2384           return e_id;
2385 }
2386 
2387 #endif /* CONFIG_DPP2 */
2388 
2389 
2390 #ifdef CONFIG_DPP3
2391 
dpp_derive_auth_i(struct dpp_authentication * auth,u8 * auth_i)2392 int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
2393 {
2394           int ret = -1, res;
2395           u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
2396           size_t Sx_len;
2397           unsigned int hash_len;
2398           const char *info = "New DPP Protocol Key";
2399           const u8 *addr[3];
2400           size_t len[3];
2401           u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
2402           struct wpabuf *pcx = NULL, *pex = NULL;
2403 
2404           hash_len = auth->curve->hash_len;
2405 
2406           /*
2407            * Configurator: S = pc * Pe
2408            * Enrollee: S = pe * Pc
2409            * k = HKDF(bk, "New DPP Protocol Key", S.x)
2410            *   = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
2411            *                 len(new-curve-hash-out))
2412            * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)
2413            *
2414            * auth->own_protocol_key and auth->peer_protocol_key have already been
2415            * updated to use the new keys. The new curve determines the size of
2416            * the (new) protocol keys and S.x. The other parameters (bk, hash
2417            * algorithm, k) are determined based on the initially determined curve
2418            * during the (re)authentication exchange.
2419            */
2420 
2421           if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
2422                          Sx, &Sx_len) < 0)
2423                     goto fail;
2424 
2425           wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
2426 
2427           /* tmp = HKDF-Extract(bk, S.x) */
2428           addr[0] = Sx;
2429           len[0] = Sx_len;
2430           res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp);
2431           if (res < 0)
2432                     goto fail;
2433           wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
2434                               tmp, hash_len);
2435           /* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output))
2436            */
2437           res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
2438           if (res < 0)
2439                     return -1;
2440 
2441           wpa_hexdump_key(MSG_DEBUG,
2442                               "DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
2443                               k, hash_len);
2444 
2445           /* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */
2446           addr[0] = auth->e_nonce;
2447           len[0] = auth->curve->nonce_len;
2448 
2449           if (auth->configurator) {
2450                     pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2451                     pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2452                                                                  0);
2453           } else {
2454                     pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
2455                                                                  0);
2456                     pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
2457           }
2458           if (!pcx || !pex)
2459                     goto fail;
2460           addr[1] = wpabuf_head(pcx);
2461           len[1] = wpabuf_len(pcx) / 2;
2462           addr[2] = wpabuf_head(pex);
2463           len[2] = wpabuf_len(pex) / 2;
2464 
2465           if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0)
2466                     goto fail;
2467           wpa_hexdump_key(MSG_DEBUG,
2468                               "DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)",
2469                               auth_i, hash_len);
2470           ret = 0;
2471 fail:
2472           forced_memzero(Sx, sizeof(Sx));
2473           forced_memzero(tmp, sizeof(tmp));
2474           forced_memzero(k, sizeof(k));
2475           wpabuf_free(pcx);
2476           wpabuf_free(pex);
2477           return ret;
2478 }
2479 
2480 
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 int dpp_hpke_suite(int iana_group, enum hpke_kem_id *kem_id,
2482                        enum hpke_kdf_id *kdf_id, enum hpke_aead_id *aead_id)
2483 {
2484           switch (iana_group) {
2485           case 19:
2486                     *kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2487                     *kdf_id = HPKE_KDF_HKDF_SHA256;
2488                     *aead_id = HPKE_AEAD_AES_128_GCM;
2489                     return 0;
2490           case 20:
2491                     *kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2492                     *kdf_id = HPKE_KDF_HKDF_SHA384;
2493                     *aead_id = HPKE_AEAD_AES_256_GCM;
2494                     return 0;
2495           case 21:
2496                     *kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2497                     *kdf_id = HPKE_KDF_HKDF_SHA512;
2498                     *aead_id = HPKE_AEAD_AES_256_GCM;
2499                     return 0;
2500           case 28:
2501                     *kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
2502                     *kdf_id = HPKE_KDF_HKDF_SHA256;
2503                     *aead_id = HPKE_AEAD_AES_128_GCM;
2504                     return 0;
2505           case 29:
2506                     *kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
2507                     *kdf_id = HPKE_KDF_HKDF_SHA384;
2508                     *aead_id = HPKE_AEAD_AES_256_GCM;
2509                     return 0;
2510           case 30:
2511                     *kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
2512                     *kdf_id = HPKE_KDF_HKDF_SHA512;
2513                     *aead_id = HPKE_AEAD_AES_256_GCM;
2514                     return 0;
2515           }
2516 
2517           return -1;
2518 }
2519 
2520 #endif /* CONFIG_DPP3 */
2521 
2522 
2523 #ifdef CONFIG_TESTING_OPTIONS
2524 
dpp_test_gen_invalid_key(struct wpabuf * msg,const struct dpp_curve_params * curve)2525 int dpp_test_gen_invalid_key(struct wpabuf *msg,
2526                                    const struct dpp_curve_params *curve)
2527 {
2528           struct crypto_ec *ec;
2529           struct crypto_ec_key *key = NULL;
2530           struct crypto_ec_point *p = NULL, *pub_key = NULL;
2531           u8 *x, *y;
2532           int ret = -1;
2533 
2534           ec = crypto_ec_init(curve->ike_group);
2535           x = wpabuf_put(msg, curve->prime_len);
2536           y = wpabuf_put(msg, curve->prime_len);
2537           if (!ec)
2538                     goto fail;
2539 
2540 retry:
2541           /* Generate valid key pair */
2542           key = crypto_ec_key_gen(curve->ike_group);
2543           if (!key)
2544                     goto fail;
2545 
2546           /* Retrieve public key coordinates */
2547           pub_key = crypto_ec_key_get_public_key(key);
2548           if (!pub_key || crypto_ec_point_to_bin(ec, pub_key, x, y))
2549                     goto fail;
2550 
2551           /* And corrupt them */
2552           y[curve->prime_len - 1] ^= 0x01;
2553           p = crypto_ec_point_from_bin(ec, x);
2554           if (p && crypto_ec_point_is_on_curve(ec, p)) {
2555                     crypto_ec_point_deinit(p, 0);
2556                     p = NULL;
2557                     goto retry;
2558           }
2559 
2560           ret = 0;
2561 fail:
2562           crypto_ec_point_deinit(p, 0);
2563           crypto_ec_point_deinit(pub_key, 0);
2564           crypto_ec_key_deinit(key);
2565           crypto_ec_deinit(ec);
2566           return ret;
2567 }
2568 
2569 
dpp_corrupt_connector_signature(const char * connector)2570 char * dpp_corrupt_connector_signature(const char *connector)
2571 {
2572           char *tmp, *pos, *signed3 = NULL;
2573           unsigned char *signature = NULL;
2574           size_t signature_len = 0, signed3_len;
2575 
2576           tmp = os_zalloc(os_strlen(connector) + 5);
2577           if (!tmp)
2578                     goto fail;
2579           os_memcpy(tmp, connector, os_strlen(connector));
2580 
2581           pos = os_strchr(tmp, '.');
2582           if (!pos)
2583                     goto fail;
2584 
2585           pos = os_strchr(pos + 1, '.');
2586           if (!pos)
2587                     goto fail;
2588           pos++;
2589 
2590           wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
2591                        pos);
2592           signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
2593           if (!signature || signature_len == 0)
2594                     goto fail;
2595           wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
2596                         signature, signature_len);
2597           signature[signature_len - 1] ^= 0x01;
2598           wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
2599                         signature, signature_len);
2600           signed3 = base64_url_encode(signature, signature_len, &signed3_len);
2601           if (!signed3)
2602                     goto fail;
2603           os_memcpy(pos, signed3, signed3_len);
2604           pos[signed3_len] = '\0';
2605           wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
2606                        pos);
2607 
2608 out:
2609           os_free(signature);
2610           os_free(signed3);
2611           return tmp;
2612 fail:
2613           os_free(tmp);
2614           tmp = NULL;
2615           goto out;
2616 }
2617 
2618 #endif /* CONFIG_TESTING_OPTIONS */
2619