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 0aabb65c2..513712319 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 @@ -2578,14 +2579,39 @@ 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) { + mp_digit cofactor = (mp_digit)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; + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } + } + } +#endif /* make new point */ result = wc_ecc_new_point_h(private_key->heap); if (result == NULL) { +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif 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); @@ -2602,6 +2628,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; } @@ -2693,6 +2723,7 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ + #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) @@ -3024,6 +3055,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 @@ -4861,6 +4900,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) { 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 0f10251df..fb560b6fe 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8198,6 +8198,63 @@ 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, 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 */ + 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"); + 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 */ + z = sizeof(sharedB); + ret = Base16_Decode((const byte*)ZIUT, (word32)XSTRLEN(ZIUT), sharedB, &z); + if (ret != 0) + goto done; + + /* compare results */ + if (x != z || XMEMCMP(sharedA, sharedB, x)) { + ERROR_OUT(-1007, done); + } + +done: + wc_ecc_free(&priv_key); + wc_ecc_free(&pub_key); + return ret; +} +#endif /* HAVE_ECC_CDH */ #endif /* HAVE_ECC_VECTOR_TEST */ #ifdef WOLFSSL_KEY_GEN @@ -8343,6 +8400,33 @@ 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 + /* 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_shared_secret(&userA, &userB, sharedA, &x); + if (ret != 0) { + goto done; + } + + y = sizeof(sharedB); + ret = wc_ecc_shared_secret(&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); + + /* remove cofactor flag */ + wc_ecc_set_flags(&userA, 0); + wc_ecc_set_flags(&userB, 0); +#endif /* HAVE_ECC_CDH */ + #ifdef HAVE_ECC_KEY_EXPORT x = sizeof(exportBuf); ret = wc_ecc_export_x963(&userA, exportBuf, &x); @@ -8579,6 +8663,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/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/ecc.h b/wolfssl/wolfcrypt/ecc.h index ea8b4285f..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 */ @@ -327,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 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);