From 39607984f764d95d5eab4fead5fd23386bc68558 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 16 Feb 2017 13:17:08 -0800 Subject: [PATCH 1/6] =?UTF-8?q?Added=20ECC=20Cofactor=20DH=20(ECC-CDH)=20s?= =?UTF-8?q?upport=20with=20new=20=E2=80=9Cwc=5Fecc=5Fcdh()=E2=80=9D=20and?= =?UTF-8?q?=20=E2=80=9Cwc=5Fecc=5Fcdh=5Fex()=E2=80=9D=20API=E2=80=99s.=20E?= =?UTF-8?q?nable=20using=20=E2=80=9CHAVE=5FECC=5FCDH=E2=80=9D=20define.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wolfcrypt/src/ecc.c | 117 ++++++++++++++++++++++++++++++++++++++++ wolfcrypt/test/test.c | 19 +++++++ wolfssl/wolfcrypt/ecc.h | 9 ++++ 3 files changed, 145 insertions(+) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index f5a9b2d42..73bd6c00d 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -35,6 +35,7 @@ Possible ECC enable options: * HAVE_ECC_SIGN: ECC sign default: on * HAVE_ECC_VERIFY: ECC verify default: on * HAVE_ECC_DHE: ECC build shared secret default: on + * HAVE_ECC_CDH: ECC cofactor DH shared secret default: off * HAVE_ECC_KEY_IMPORT: ECC Key import default: on * HAVE_ECC_KEY_EXPORT: ECC Key export default: on * ECC_SHAMIR: Enables Shamir calc method default: on @@ -2693,6 +2694,122 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #endif /* !WOLFSSL_ATECC508A */ #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) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0f10251df..2935fcb90 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8343,6 +8343,25 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ERROR_OUT(-1005, done); #endif /* HAVE_ECC_DHE */ +#ifdef HAVE_ECC_CDH + x = sizeof(sharedA); + ret = wc_ecc_cdh(&userA, &userB, sharedA, &x); + if (ret != 0) { + goto done; + } + + y = sizeof(sharedB); + ret = wc_ecc_cdh(&userB, &userA, sharedB, &y); + if (ret != 0) + goto done; + + if (y != x) + ERROR_OUT(-1006, done); + + if (XMEMCMP(sharedA, sharedB, x)) + ERROR_OUT(-1007, done); +#endif /* HAVE_ECC_CDH */ + #ifdef HAVE_ECC_KEY_EXPORT x = sizeof(exportBuf); ret = wc_ecc_export_x963(&userA, exportBuf, &x); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ea8b4285f..286647fe5 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -302,6 +302,15 @@ 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, From d6256453381d4d7a1a521c96a590d35324b77584 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 16 Feb 2017 16:30:30 -0800 Subject: [PATCH 2/6] =?UTF-8?q?Refactor=20to=20combine=20ECC-CDH=20with=20?= =?UTF-8?q?existing=20=E2=80=9Cwc=5Fecc=5Fshared=5Fsecret()=E2=80=9D=20and?= =?UTF-8?q?=20use=20flag=20to=20perform=20cofactor=20computation=20on=20pr?= =?UTF-8?q?ivate=20key.=20Added=20new=20API=20=E2=80=9Cwc=5Fecc=5Fset=5Ffl?= =?UTF-8?q?ags()=E2=80=9D=20and=20flag=20=E2=80=9CWC=5FECC=5FFLAG=5FCOFACT?= =?UTF-8?q?OR=E2=80=9D=20to=20indicate=20key=20should=20use=20cofactor.=20?= =?UTF-8?q?Added=20NIST=20CAVS=20test=20vector=20for=20ECC=20CDH=20Primiti?= =?UTF-8?q?ve=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 From 24cd46f1f117a1d387292ba2e65c749fb7a13e54 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 17 Feb 2017 11:05:29 -0800 Subject: [PATCH 3/6] Fixes from code review --- wolfcrypt/src/coding.c | 3 ++- wolfcrypt/src/ecc.c | 7 +++---- wolfcrypt/src/tfm.c | 6 ++++++ wolfcrypt/test/test.c | 13 ++++++------- wolfssl/wolfcrypt/coding.h | 3 ++- wolfssl/wolfcrypt/tfm.h | 1 + 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index f144b1130..43cb45d06 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -347,7 +347,8 @@ int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) #endif /* defined(WOLFSSL_BASE64_ENCODE) */ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 8d0e697be..51d310a7a 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2591,10 +2591,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, 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); + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); if (err != MP_OKAY) { mp_clear(k); return err; @@ -2606,6 +2604,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, /* make new point */ result = wc_ecc_new_point_h(private_key->heap); if (result == NULL) { + mp_clear(k); return MEMORY_E; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index cfb647fb1..0656f760c 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2254,6 +2254,12 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c) return MP_OKAY; } +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + fp_mul_d(a, b, c); + return MP_OKAY; +} + /* d = a * b (mod c) */ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index d109d549a..216b317b2 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8204,8 +8204,7 @@ 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; + word32 x, z; const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; @@ -8234,13 +8233,13 @@ static int ecc_test_cdh_vectors(void) } /* read in expected Z */ - mp_init(&z); - mp_read_radix(&z, ZIUT, 16); - mp_to_unsigned_bin(&z, sharedB); - mp_clear(&z); + z = sizeof(sharedB); + ret = Base16_Decode((const byte*)ZIUT, (word32)XSTRLEN(ZIUT), sharedB, &z); + if (ret != 0) + goto done; /* compare results */ - if (XMEMCMP(sharedA, sharedB, x)) { + if (x != z || XMEMCMP(sharedA, sharedB, x)) { ERROR_OUT(-1007, done); } diff --git a/wolfssl/wolfcrypt/coding.h b/wolfssl/wolfcrypt/coding.h index 5395cc2f4..427f3a6cb 100644 --- a/wolfssl/wolfcrypt/coding.h +++ b/wolfssl/wolfcrypt/coding.h @@ -61,7 +61,8 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) WOLFSSL_API int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index fc88149d7..f5df3bf12 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -622,6 +622,7 @@ int mp_sub (mp_int * a, mp_int * b, mp_int * c); int mp_add_d (mp_int * a, mp_digit b, mp_int * c); int mp_mul (mp_int * a, mp_int * b, mp_int * c); +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); From 09bae9da3ef6e414d7efd6d86c87940a18061c48 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 17 Feb 2017 11:18:05 -0800 Subject: [PATCH 4/6] Fixup from review --- wolfcrypt/src/ecc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 51d310a7a..8d861fa6c 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2585,7 +2585,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, /* if cofactor flag has been set */ if (private_key->flags & WC_ECC_FLAG_COFACTOR) { - int cofactor = private_key->dp->cofactor; + mp_digit cofactor = (mp_digit)private_key->dp->cofactor; /* only perform cofactor calc if not equal to 1 */ if (cofactor != 1) { k = &k_lcl; @@ -2604,7 +2604,10 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, /* make new point */ result = wc_ecc_new_point_h(private_key->heap); if (result == NULL) { - mp_clear(k); +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif return MEMORY_E; } From 3e6ef835b16ace701c7d110e1ecd34dbf8689a38 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 17 Feb 2017 12:06:27 -0800 Subject: [PATCH 5/6] Free the ecc keys --- wolfcrypt/test/test.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 216b317b2..fb560b6fe 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8214,8 +8214,14 @@ static int ecc_test_cdh_vectors(void) const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; /* setup private and public keys */ - wc_ecc_init(&pub_key); - wc_ecc_init(&priv_key); + ret = wc_ecc_init(&pub_key); + if (ret != 0) + return ret; + ret = wc_ecc_init(&priv_key); + if (ret != 0) { + wc_ecc_free(&pub_key); + goto done; + } 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"); @@ -8244,6 +8250,8 @@ static int ecc_test_cdh_vectors(void) } done: + wc_ecc_free(&priv_key); + wc_ecc_free(&pub_key); return ret; } #endif /* HAVE_ECC_CDH */ From bdd3f2be41fa5bf825a9481a184cb1aaa437e184 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 17 Feb 2017 12:15:18 -0800 Subject: [PATCH 6/6] Make sure ecc key is always memset to 0 --- wolfcrypt/src/ecc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 8d861fa6c..06b91d04a 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4899,6 +4899,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, return BAD_FUNC_ARG; } + XMEMSET(key, 0, sizeof(ecc_key)); /* set curve type and index */ err = wc_ecc_set_curve(key, 0, curve_id); if (err != 0) {