|
24 | 24 | #else |
25 | 25 | #define assert(x) |
26 | 26 | #endif |
| 27 | +#include <inttypes.h> |
27 | 28 |
|
28 | 29 | #include "global.h" |
29 | 30 | #include "dtls_debug.h" |
30 | 31 | #include "numeric.h" |
31 | 32 | #include "dtls.h" |
32 | 33 | #include "crypto.h" |
33 | 34 | #include "ccm.h" |
34 | | -#include "ecc/micro-ecc/uECC.h" |
| 35 | +#ifdef DTLS_ECC |
| 36 | +#include "ext/micro-ecc/uECC.h" |
| 37 | +#endif /* DTLS_ECC */ |
35 | 38 | #include "dtls_prng.h" |
36 | 39 | #include "netq.h" |
37 | 40 |
|
@@ -356,6 +359,10 @@ dtls_psk_pre_master_secret(unsigned char *key, size_t keylen, |
356 | 359 | #endif /* DTLS_PSK */ |
357 | 360 |
|
358 | 361 | #ifdef DTLS_ECC |
| 362 | +#ifdef uECC_SUPPORTS_secp256r1 |
| 363 | +const dtls_ecdh_curve default_curve = TLS_EXT_ELLIPTIC_CURVES_SECP256R1; |
| 364 | +#endif /* uECC_SUPPORTS_secp256r1 */ |
| 365 | + |
359 | 366 | static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size, |
360 | 367 | uint32_t *result) { |
361 | 368 | int i; |
@@ -432,64 +439,148 @@ int dtls_ec_key_asn1_from_uint32(const uint32_t *key, size_t key_size, |
432 | 439 | return key_size + 2; |
433 | 440 | } |
434 | 441 |
|
| 442 | +static int get_uecc_curve(dtls_ecdh_curve curve, uECC_Curve *result) { |
| 443 | + struct { |
| 444 | + dtls_ecdh_curve curve; |
| 445 | + uECC_Curve uecc_curve; |
| 446 | + } known_curves[] = { |
| 447 | +#if uECC_SUPPORTS_secp256r1 |
| 448 | + { TLS_EXT_ELLIPTIC_CURVES_SECP256R1, uECC_secp256r1() }, |
| 449 | +#endif /* uECC_SUPPORTS_secp256r1 */ |
| 450 | + }; |
| 451 | + unsigned int index; |
| 452 | + |
| 453 | + for (index = 0; index < sizeof(known_curves)/sizeof(known_curves[0]); index++) { |
| 454 | + if (known_curves[index].curve == curve) { |
| 455 | + *result = known_curves[index].uecc_curve; |
| 456 | + return 1; |
| 457 | + } |
| 458 | + } |
| 459 | + return 0; |
| 460 | +} |
| 461 | + |
| 462 | +int dtls_ecdh_pre_master_secret2(const unsigned char *priv_key, |
| 463 | + const unsigned char *pub_key, |
| 464 | + size_t key_size, |
| 465 | + dtls_ecdh_curve curve, |
| 466 | + unsigned char *result, |
| 467 | + size_t result_len) { |
| 468 | + uECC_Curve uecc_curve; |
| 469 | + if (!get_uecc_curve(curve, &uecc_curve)) { |
| 470 | + dtls_warn("curve %" PRIu16 " not supported\n", curve); |
| 471 | + return -1; |
| 472 | + } |
| 473 | + |
| 474 | + if (result_len < key_size) { |
| 475 | + return -1; |
| 476 | + } |
| 477 | + |
| 478 | + if (!uECC_valid_public_key(pub_key, uecc_curve)) { |
| 479 | + dtls_warn("invalid public key\n"); |
| 480 | + } |
| 481 | + |
| 482 | + if (!uECC_shared_secret(pub_key, priv_key, result, uecc_curve)) { |
| 483 | + dtls_warn("cannot generate ECDH shared secret\n"); |
| 484 | + return 0; |
| 485 | + } |
| 486 | + |
| 487 | + return key_size; |
| 488 | +} |
| 489 | + |
435 | 490 | int dtls_ecdh_pre_master_secret(unsigned char *priv_key, |
436 | 491 | unsigned char *pub_key_x, |
437 | 492 | unsigned char *pub_key_y, |
438 | 493 | size_t key_size, |
439 | 494 | unsigned char *result, |
440 | 495 | size_t result_len) { |
| 496 | + const dtls_ecdh_curve curve = default_curve; |
441 | 497 | uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; |
442 | | - uint8_t priv[DTLS_EC_KEY_SIZE]; |
443 | 498 |
|
444 | 499 | if (result_len < key_size) { |
445 | 500 | return -1; |
446 | 501 | } |
447 | 502 |
|
448 | | - memcpy(priv, priv_key, DTLS_EC_KEY_SIZE); |
449 | 503 | memcpy(pub_key, pub_key_x, DTLS_EC_KEY_SIZE); |
450 | 504 | memcpy(pub_key + DTLS_EC_KEY_SIZE, pub_key_y, DTLS_EC_KEY_SIZE); |
451 | | - if (!uECC_valid_public_key(pub_key)) { |
452 | | - dtls_warn("invalid public key\n"); |
453 | | - } |
454 | | - |
455 | | - if (!uECC_shared_secret(pub_key, priv, result)) { |
456 | | - dtls_warn("cannot generate ECDH shared secret\n"); |
457 | | - return 0; |
458 | | - } |
459 | | - |
460 | | - return key_size; |
| 505 | + return dtls_ecdh_pre_master_secret2(priv_key, pub_key, key_size, curve, |
| 506 | + result, result_len); |
461 | 507 | } |
462 | 508 |
|
463 | 509 | void |
464 | 510 | dtls_ecdsa_generate_key(unsigned char *priv_key, |
465 | 511 | unsigned char *pub_key_x, |
466 | 512 | unsigned char *pub_key_y, |
467 | 513 | size_t key_size) { |
| 514 | + const dtls_ecdh_curve curve = default_curve; |
468 | 515 | uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; |
469 | 516 |
|
470 | | - assert(key_size == DTLS_EC_KEY_SIZE); |
471 | | - if (!uECC_make_key(pub_key, priv_key) |
472 | | - || !uECC_valid_public_key(pub_key)) { |
| 517 | + int res = dtls_ecdsa_generate_key2(priv_key, pub_key, key_size, curve); |
| 518 | + if (res > 0) { |
| 519 | + memcpy(pub_key_x, pub_key, res); |
| 520 | + memcpy(pub_key_y, pub_key + res, res); |
| 521 | + } |
| 522 | +} |
| 523 | + |
| 524 | +int |
| 525 | +dtls_ecdsa_generate_key2(unsigned char *priv_key, |
| 526 | + unsigned char *pub_key, |
| 527 | + size_t key_size, |
| 528 | + dtls_ecdh_curve curve) { |
| 529 | + uECC_Curve uecc_curve; |
| 530 | + if (!get_uecc_curve(curve, &uecc_curve)) { |
| 531 | + dtls_warn("curve %" PRIu16 " not supported\n", curve); |
| 532 | + return -1; |
| 533 | + } |
| 534 | + |
| 535 | + assert(key_size >= (unsigned int)uECC_curve_private_key_size(uecc_curve)); |
| 536 | + assert(2 * key_size >= (unsigned int)uECC_curve_public_key_size(uecc_curve)); |
| 537 | + |
| 538 | + if (!uECC_make_key(pub_key, priv_key, uecc_curve) |
| 539 | + || !uECC_valid_public_key(pub_key, uecc_curve)) { |
473 | 540 | dtls_crit("cannot generate ECC key pair\n"); |
| 541 | + return 0; |
474 | 542 | } |
475 | | - memcpy(pub_key_x, pub_key, key_size); |
476 | | - memcpy(pub_key_y, pub_key + key_size, key_size); |
| 543 | + return uECC_curve_private_key_size(uecc_curve); |
477 | 544 | } |
478 | 545 |
|
479 | 546 | /* rfc4492#section-5.4 */ |
480 | 547 | void |
481 | 548 | dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size, |
482 | 549 | const unsigned char *sign_hash, size_t sign_hash_size, |
483 | 550 | uint32_t point_r[9], uint32_t point_s[9]) { |
| 551 | + const dtls_ecdh_curve curve = default_curve; |
| 552 | + dtls_ecdsa_create_sig_hash2(priv_key, key_size, |
| 553 | + sign_hash, sign_hash_size, |
| 554 | + curve, point_r, point_s); |
| 555 | + |
| 556 | +} |
| 557 | + |
| 558 | +int |
| 559 | +dtls_ecdsa_create_sig_hash2(const unsigned char *priv_key, size_t key_size, |
| 560 | + const unsigned char *sign_hash, size_t sign_hash_size, |
| 561 | + dtls_ecdh_curve curve, |
| 562 | + uint32_t point_r[9], uint32_t point_s[9]) { |
484 | 563 | uint8_t sign[2 * DTLS_EC_KEY_SIZE]; |
| 564 | + uECC_Curve uecc_curve; |
| 565 | + int curve_size; |
| 566 | + if (!get_uecc_curve(curve, &uecc_curve)) { |
| 567 | + dtls_warn("curve %" PRIu16 " not supported\n", curve); |
| 568 | + return -1; |
| 569 | + } |
| 570 | + |
| 571 | + curve_size = uECC_curve_private_key_size(uecc_curve); |
485 | 572 |
|
486 | | - assert(key_size == DTLS_EC_KEY_SIZE); |
487 | | - assert(sign_hash_size >= uECC_BYTES); |
488 | | - assert(sizeof(sign) >= 2 * uECC_BYTES); |
489 | | - uECC_sign(priv_key, sign_hash, sign); |
| 573 | + assert(key_size >= (unsigned int)curve_size); |
| 574 | + assert(sign_hash_size >= (unsigned int)curve_size); |
| 575 | + assert(sizeof(sign) >= 2 * (unsigned int)curve_size); |
| 576 | + if (!uECC_sign(priv_key, sign_hash, sign_hash_size, sign, uecc_curve)) { |
| 577 | + dtls_warn("cannot create signature\n"); |
| 578 | + return -1; |
| 579 | + } |
490 | 580 |
|
491 | | - dtls_ec_key_to_uint32(sign, DTLS_EC_KEY_SIZE, point_r); |
492 | | - dtls_ec_key_to_uint32(sign + DTLS_EC_KEY_SIZE, DTLS_EC_KEY_SIZE, point_s); |
| 581 | + dtls_ec_key_to_uint32(sign, curve_size, point_r); |
| 582 | + dtls_ec_key_to_uint32(sign + curve_size, curve_size, point_s); |
| 583 | + return 2 * curve_size; |
493 | 584 | } |
494 | 585 |
|
495 | 586 | void |
@@ -517,20 +608,39 @@ dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x, |
517 | 608 | const unsigned char *pub_key_y, size_t key_size, |
518 | 609 | const unsigned char *sign_hash, size_t sign_hash_size, |
519 | 610 | unsigned char *result_r, unsigned char *result_s) { |
| 611 | + const dtls_ecdh_curve curve = default_curve; |
520 | 612 | uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; |
| 613 | + memcpy(pub_key, pub_key_x, key_size); |
| 614 | + memcpy(pub_key + key_size, pub_key_y, key_size); |
| 615 | + return dtls_ecdsa_verify_sig_hash2(pub_key, key_size, |
| 616 | + sign_hash, sign_hash_size, |
| 617 | + curve, |
| 618 | + result_r, result_s); |
| 619 | +} |
| 620 | + |
| 621 | +int |
| 622 | +dtls_ecdsa_verify_sig_hash2(const unsigned char *pub_key, size_t key_size, |
| 623 | + const unsigned char *sign_hash, size_t sign_hash_size, |
| 624 | + dtls_ecdh_curve curve, |
| 625 | + unsigned char *result_r, unsigned char *result_s) { |
521 | 626 | uint8_t sign[2 * DTLS_EC_KEY_SIZE]; |
| 627 | + uECC_Curve uecc_curve; |
| 628 | + int curve_size; |
| 629 | + if (!get_uecc_curve(curve, &uecc_curve)) { |
| 630 | + dtls_warn("curve %" PRIu16 " not supported\n", curve); |
| 631 | + return -1; |
| 632 | + } |
522 | 633 | (void)result_r; |
523 | 634 | (void)result_s; |
524 | 635 |
|
525 | | - assert(key_size == DTLS_EC_KEY_SIZE); |
526 | | - assert(sign_hash_size >= uECC_BYTES); |
527 | | - assert(sizeof(sign) >= 2 * uECC_BYTES); |
| 636 | + curve_size = uECC_curve_public_key_size(uecc_curve); |
| 637 | + |
| 638 | + assert(key_size == (unsigned int)curve_size); |
| 639 | + assert(sizeof(sign) >= (unsigned int)curve_size); |
528 | 640 |
|
529 | 641 | /* clear sign to avoid maybe-unitialized warning */ |
530 | 642 | memset(sign, 0, sizeof(sign)); |
531 | | - memcpy(pub_key, pub_key_x, key_size); |
532 | | - memcpy(pub_key + key_size, pub_key_y, key_size); |
533 | | - return uECC_verify(pub_key, sign_hash, sign); |
| 643 | + return uECC_verify(pub_key, sign_hash, sign_hash_size, sign, uecc_curve); |
534 | 644 | } |
535 | 645 |
|
536 | 646 | int |
|
0 commit comments