From d6256453381d4d7a1a521c96a590d35324b77584 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 16 Feb 2017 16:30:30 -0800 Subject: [PATCH] =?UTF-8?q?Refactor=20to=20combine=20ECC-CDH=20with=20exis?= =?UTF-8?q?ting=20=E2=80=9Cwc=5Fecc=5Fshared=5Fsecret()=E2=80=9D=20and=20u?= =?UTF-8?q?se=20flag=20to=20perform=20cofactor=20computation=20on=20privat?= =?UTF-8?q?e=20key.=20Added=20new=20API=20=E2=80=9Cwc=5Fecc=5Fset=5Fflags(?= =?UTF-8?q?)=E2=80=9D=20and=20flag=20=E2=80=9CWC=5FECC=5FFLAG=5FCOFACTOR?= =?UTF-8?q?=E2=80=9D=20to=20indicate=20key=20should=20use=20cofactor.=20Ad?= =?UTF-8?q?ded=20NIST=20CAVS=20test=20vector=20for=20ECC=20CDH=20Primitive?= =?UTF-8?q?=20with=20P-256.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wolfcrypt/src/ecc.c | 152 ++++++++++------------------------------ wolfcrypt/test/test.c | 69 +++++++++++++++++- wolfssl/wolfcrypt/ecc.h | 19 ++--- 3 files changed, 113 insertions(+), 127 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 73bd6c00d..8d0e697be 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2579,6 +2579,29 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, int err; ecc_point* result = NULL; word32 x = 0; + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; + + /* if cofactor flag has been set */ + if (private_key->flags & WC_ECC_FLAG_COFACTOR) { + int cofactor = private_key->dp->cofactor; + /* only perform cofactor calc if not equal to 1 */ + if (cofactor != 1) { + k = &k_lcl; + if (mp_init(k) != MP_OKAY) + return MEMORY_E; + /* multiple cofactor times private key "k" */ + err = mp_set_int(k, cofactor); + if (err == MP_OKAY) + err = mp_mul(k, &private_key->k, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } + } + } +#endif /* make new point */ result = wc_ecc_new_point_h(private_key->heap); @@ -2586,7 +2609,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, return MEMORY_E; } - err = wc_ecc_mulmod_ex(&private_key->k, point, result, + err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 1, private_key->heap); if (err == MP_OKAY) { x = mp_unsigned_bin_size(curve->prime); @@ -2603,6 +2626,10 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, *outlen = x; wc_ecc_del_point_h(result, private_key->heap); +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif return err; } @@ -2695,121 +2722,6 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #endif /* HAVE_ECC_DHE */ -#ifdef HAVE_ECC_CDH -/* -Elliptic Curve Cryptography Cofactor Diffie-Hellman (ECC CDH) - -A shared secret Z is computed using the domain parameters: - (q, FR, a, b{, SEED}, G, n, h), the other party’s public key, - and one’s own private key. - -Input: -1. (q, FR, a, b{, SEED}, G, n, h): Domain parameters, -2. dA : One’s own private key, and -3. QB : The other party’s public key. -*/ - -int wc_ecc_cdh_ex(ecc_key* private_key, ecc_point* public_point, - byte* out, word32 *outlen) -{ - int err; - int cofactor; - ecc_point* result = NULL; - mp_int k_lcl; - mp_int* k; - word32 x = 0; - DECLARE_CURVE_SPECS(2) - - if (private_key == NULL || public_point == NULL || out == NULL || - outlen == NULL) { - return BAD_FUNC_ARG; - } - - /* type valid? */ - if (private_key->type != ECC_PRIVATEKEY) { - return ECC_BAD_ARG_E; - } - - /* load curve info */ - cofactor = private_key->dp->cofactor; - err = wc_ecc_curve_load(private_key->dp, &curve, - (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); - if (err != MP_OKAY) { - return err; - } - - /* multiple cofactor times private key "k" */ - if (cofactor != 1) { - k = &k_lcl; - if (mp_init(k) != MP_OKAY) { - return MEMORY_E; - } - - mp_set_int(k, cofactor); - mp_mul(k, &private_key->k, k); - } - else { - k = &private_key->k; - } - - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } - - /* multiple public and private points */ - err = wc_ecc_mulmod_ex(k, public_point, result, - curve->Af, curve->prime, 1, private_key->heap); - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(curve->prime); - if (*outlen < x) { - err = BUFFER_E; - } - } - - /* return output */ - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x, - out + (x - mp_unsigned_bin_size(result->x))); - } - *outlen = x; - - /* clean up */ - wc_ecc_del_point_h(result, private_key->heap); - if (cofactor != 1) { - mp_clear(k); - } - wc_ecc_curve_free(curve); - - return err; -} - -int wc_ecc_cdh(ecc_key* private_key, ecc_key* public_key, - byte* out, word32* outlen) -{ - if (private_key == NULL || public_key == NULL) { - return BAD_FUNC_ARG; - } - - /* Verify domain params supplied */ - if (wc_ecc_is_valid_idx(private_key->idx) == 0 || - wc_ecc_is_valid_idx(public_key->idx) == 0) { - return ECC_BAD_ARG_E; - } - - /* Verify curve id matches */ - if (private_key->dp->id != public_key->dp->id) { - return ECC_BAD_ARG_E; - } - - return wc_ecc_cdh_ex(private_key, &public_key->pubkey, out, outlen); -} - -#endif /* HAVE_ECC_CDH */ - - #ifndef WOLFSSL_ATECC508A /* return 1 if point is at infinity, 0 if not, < 0 on error */ int wc_ecc_point_is_at_infinity(ecc_point* p) @@ -3141,6 +3053,14 @@ int wc_ecc_init(ecc_key* key) return wc_ecc_init_ex(key, NULL, INVALID_DEVID); } +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; + return 0; +} #ifdef HAVE_ECC_SIGN diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 2935fcb90..d109d549a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8198,6 +8198,56 @@ static int ecc_test_vector(int keySize) return 0; } +#ifdef HAVE_ECC_CDH +static int ecc_test_cdh_vectors(void) +{ + int ret; + ecc_key pub_key, priv_key; + byte sharedA[32] = {0}, sharedB[32] = {0}; + word32 x; + mp_int z; + + const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; + const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; + const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; + const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; + const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; + const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; + + /* setup private and public keys */ + wc_ecc_init(&pub_key); + wc_ecc_init(&priv_key); + wc_ecc_set_flags(&pub_key, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR); + ret = wc_ecc_import_raw(&pub_key, QCAVSx, QCAVSy, NULL, "SECP256R1"); + if (ret != 0) + goto done; + ret = wc_ecc_import_raw(&priv_key, QIUTx, QIUTy, dIUT, "SECP256R1"); + if (ret != 0) + goto done; + + /* compute ECC Cofactor shared secret */ + x = sizeof(sharedA); + ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &x); + if (ret != 0) { + goto done; + } + + /* read in expected Z */ + mp_init(&z); + mp_read_radix(&z, ZIUT, 16); + mp_to_unsigned_bin(&z, sharedB); + mp_clear(&z); + + /* compare results */ + if (XMEMCMP(sharedA, sharedB, x)) { + ERROR_OUT(-1007, done); + } + +done: + return ret; +} +#endif /* HAVE_ECC_CDH */ #endif /* HAVE_ECC_VECTOR_TEST */ #ifdef WOLFSSL_KEY_GEN @@ -8344,14 +8394,18 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, #endif /* HAVE_ECC_DHE */ #ifdef HAVE_ECC_CDH + /* add cofactor flag */ + wc_ecc_set_flags(&userA, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&userB, WC_ECC_FLAG_COFACTOR); + x = sizeof(sharedA); - ret = wc_ecc_cdh(&userA, &userB, sharedA, &x); + ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); if (ret != 0) { goto done; } y = sizeof(sharedB); - ret = wc_ecc_cdh(&userB, &userA, sharedB, &y); + ret = wc_ecc_shared_secret(&userB, &userA, sharedB, &y); if (ret != 0) goto done; @@ -8360,6 +8414,10 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, if (XMEMCMP(sharedA, sharedB, x)) ERROR_OUT(-1007, done); + + /* remove cofactor flag */ + wc_ecc_set_flags(&userA, 0); + wc_ecc_set_flags(&userB, 0); #endif /* HAVE_ECC_CDH */ #ifdef HAVE_ECC_KEY_EXPORT @@ -8598,6 +8656,13 @@ int ecc_test(void) #endif #endif +#ifdef HAVE_ECC_CDH + ret = ecc_test_cdh_vectors(); + if (ret != 0) { + printf("ecc_test_cdh_vectors failed! %d\n", ret); + } +#endif + done: wc_FreeRng(&rng); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 286647fe5..b9edabff9 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -248,6 +248,13 @@ typedef struct { #endif } ecc_point; +/* ECC Flags */ +enum { + WC_ECC_FLAG_NONE = 0x00, +#ifdef HAVE_ECC_CDH + WC_ECC_FLAG_COFACTOR = 0x01, +#endif +}; /* An ECC Key */ typedef struct ecc_key { @@ -256,6 +263,7 @@ typedef struct ecc_key { this curve if -1, this key is using user supplied curve in dp */ int state; + word32 flags; const ecc_set_type* dp; /* domain parameters, either points to NIST curves (idx >= 0) or user supplied */ void* heap; /* heap hint */ @@ -302,15 +310,6 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */ #endif /* HAVE_ECC_DHE */ -#ifdef HAVE_ECC_CDH -WOLFSSL_API -int wc_ecc_cdh(ecc_key* private_key, ecc_key* public_key, - byte* out, word32* outlen); -WOLFSSL_API -int wc_ecc_cdh_ex(ecc_key* private_key, ecc_point* public_point, - byte* out, word32 *outlen); -#endif /* HAVE_ECC_CDH */ - #ifdef HAVE_ECC_SIGN WOLFSSL_API int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, @@ -336,6 +335,8 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); WOLFSSL_API void wc_ecc_free(ecc_key* key); WOLFSSL_API +int wc_ecc_set_flags(ecc_key* key, word32 flags); +WOLFSSL_API void wc_ecc_fp_free(void); WOLFSSL_API