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