Skip to content

Commit 3dc62b1

Browse files
committed
crypto.[hc]: Use micro-ecc for ECC support
This change provides support for the curve secp256r1 from micro-ecc. Change-Id: I2d272e2ddb498016a2d6e85af7af8247010768d8
1 parent 0e068ec commit 3dc62b1

2 files changed

Lines changed: 215 additions & 33 deletions

File tree

crypto.c

Lines changed: 140 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@
2424
#else
2525
#define assert(x)
2626
#endif
27+
#include <inttypes.h>
2728

2829
#include "global.h"
2930
#include "dtls_debug.h"
3031
#include "numeric.h"
3132
#include "dtls.h"
3233
#include "crypto.h"
3334
#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 */
3538
#include "dtls_prng.h"
3639
#include "netq.h"
3740

@@ -356,6 +359,10 @@ dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,
356359
#endif /* DTLS_PSK */
357360

358361
#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+
359366
static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size,
360367
uint32_t *result) {
361368
int i;
@@ -432,64 +439,148 @@ int dtls_ec_key_asn1_from_uint32(const uint32_t *key, size_t key_size,
432439
return key_size + 2;
433440
}
434441

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+
435490
int dtls_ecdh_pre_master_secret(unsigned char *priv_key,
436491
unsigned char *pub_key_x,
437492
unsigned char *pub_key_y,
438493
size_t key_size,
439494
unsigned char *result,
440495
size_t result_len) {
496+
const dtls_ecdh_curve curve = default_curve;
441497
uint8_t pub_key[2 * DTLS_EC_KEY_SIZE];
442-
uint8_t priv[DTLS_EC_KEY_SIZE];
443498

444499
if (result_len < key_size) {
445500
return -1;
446501
}
447502

448-
memcpy(priv, priv_key, DTLS_EC_KEY_SIZE);
449503
memcpy(pub_key, pub_key_x, DTLS_EC_KEY_SIZE);
450504
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);
461507
}
462508

463509
void
464510
dtls_ecdsa_generate_key(unsigned char *priv_key,
465511
unsigned char *pub_key_x,
466512
unsigned char *pub_key_y,
467513
size_t key_size) {
514+
const dtls_ecdh_curve curve = default_curve;
468515
uint8_t pub_key[2 * DTLS_EC_KEY_SIZE];
469516

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)) {
473540
dtls_crit("cannot generate ECC key pair\n");
541+
return 0;
474542
}
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);
477544
}
478545

479546
/* rfc4492#section-5.4 */
480547
void
481548
dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
482549
const unsigned char *sign_hash, size_t sign_hash_size,
483550
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]) {
484563
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);
485572

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+
}
490580

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;
493584
}
494585

495586
void
@@ -517,20 +608,39 @@ dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x,
517608
const unsigned char *pub_key_y, size_t key_size,
518609
const unsigned char *sign_hash, size_t sign_hash_size,
519610
unsigned char *result_r, unsigned char *result_s) {
611+
const dtls_ecdh_curve curve = default_curve;
520612
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) {
521626
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+
}
522633
(void)result_r;
523634
(void)result_s;
524635

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);
528640

529641
/* clear sign to avoid maybe-unitialized warning */
530642
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);
534644
}
535645

536646
int

crypto.h

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,18 @@ typedef uint8_t dtls_cipher_index_t;
6060
typedef enum { AES128=0
6161
} dtls_crypto_alg;
6262

63-
typedef enum {
64-
DTLS_ECDH_CURVE_SECP256R1
65-
} dtls_ecdh_curve;
63+
/**
64+
* Curve type as specified in the TLS supported elliptic curves
65+
* extension (@see [RFC 8422, Section 5.1.1](https://www.rfc-editor.org/rfc/rfc8422#section-5.1.1).
66+
*
67+
* The only supported value so far is TLS_EXT_ELLIPTIC_CURVES_SECP256R1
68+
*/
69+
typedef uint16_t dtls_ecdh_curve;
70+
71+
/**
72+
* @deprecated {Defined for backwards compatibility.}
73+
*/
74+
#define DTLS_ECDH_CURVE_SECP256R1 TLS_EXT_ELLIPTIC_CURVES_SECP256R1
6675

6776
/** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */
6877
typedef struct {
@@ -454,15 +463,70 @@ int dtls_ecdh_pre_master_secret(unsigned char *priv_key,
454463
unsigned char *result,
455464
size_t result_len);
456465

466+
/**
467+
* Generates the pre_master_sercet from given own private key @p
468+
* priv_key and remote public key @p pub_key for the curve @p curve.
469+
* This function returns the generated shared secret in @p result of
470+
* size @p result_len. On success, the return value give the actual
471+
* number of bytes written to @p result. The return @c 0 indicates
472+
* an error.
473+
*
474+
* @param priv_key The own private key. The size of this key is
475+
* defined by the selected @p curve and is passed
476+
* in @p key_size.
477+
* @param pub_key The remote public key. The size of this key is
478+
* defined by the selected @p curve (usually twice
479+
* @p key_size.
480+
* @param key_size Length of @p priv_key in bytes.
481+
* @param curve The elliptic curve to use.
482+
* @param result The derived pre master secret.
483+
* @param result_len The maximum length of the derived pre master secret.
484+
* in @p result.
485+
* @return The actual length of @p result or <= 0 on error.
486+
*/
487+
int dtls_ecdh_pre_master_secret2(const unsigned char *priv_key,
488+
const unsigned char *pub_key,
489+
size_t key_size,
490+
dtls_ecdh_curve curve,
491+
unsigned char *result,
492+
size_t result_len);
493+
457494
void dtls_ecdsa_generate_key(unsigned char *priv_key,
458495
unsigned char *pub_key_x,
459496
unsigned char *pub_key_y,
460497
size_t key_size);
461498

499+
/**
500+
* Generates a key pair for the given curve @p curve and stores the
501+
* private part in @p priv_key and the public part in @p pub_key. The
502+
* storage that must be provided for @p priv_key and @p pub_key is
503+
* determined by @p curve. Usually, @p pub_key requires 2 * @p
504+
* key_size. This function returns the actual number of bytes written
505+
* into @p priv_key on success, or @c 0 otherwise.
506+
*
507+
* @param priv_key Storage for the generated private key.
508+
* @param pub_key Storage for the generated public key.
509+
* @param key_size The amount of storage for @p priv_key.
510+
* @param curve Storage for the generated public key.
511+
* @return The number of bytes written into @p priv_key, or @c 0 on error.
512+
*/
513+
int dtls_ecdsa_generate_key2(unsigned char *priv_key,
514+
unsigned char *pub_key,
515+
size_t key_size,
516+
dtls_ecdh_curve curve);
517+
462518
void dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
463519
const unsigned char *sign_hash, size_t sign_hash_size,
464520
uint32_t point_r[9], uint32_t point_s[9]);
465521

522+
/**
523+
* FIXME: document function
524+
*/
525+
int dtls_ecdsa_create_sig_hash2(const unsigned char *priv_key, size_t key_size,
526+
const unsigned char *sign_hash, size_t sign_hash_size,
527+
dtls_ecdh_curve curve,
528+
uint32_t point_r[9], uint32_t point_s[9]);
529+
466530
void dtls_ecdsa_create_sig(const unsigned char *priv_key, size_t key_size,
467531
const unsigned char *client_random, size_t client_random_size,
468532
const unsigned char *server_random, size_t server_random_size,
@@ -474,6 +538,14 @@ int dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x,
474538
const unsigned char *sign_hash, size_t sign_hash_size,
475539
unsigned char *result_r, unsigned char *result_s);
476540

541+
/**
542+
* FIXME: document function
543+
*/
544+
int dtls_ecdsa_verify_sig_hash2(const unsigned char *pub_key, size_t key_size,
545+
const unsigned char *sign_hash, size_t sign_hash_size,
546+
dtls_ecdh_curve curve,
547+
unsigned char *result_r, unsigned char *result_s);
548+
477549
int dtls_ecdsa_verify_sig(const unsigned char *pub_key_x,
478550
const unsigned char *pub_key_y, size_t key_size,
479551
const unsigned char *client_random, size_t client_random_size,

0 commit comments

Comments
 (0)