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