From 246f86f129a09761d2fa1bcea4fc5301e6e67f58 Mon Sep 17 00:00:00 2001 From: Russ Williams <37781645+rmw42@users.noreply.github.com> Date: Sat, 19 Jan 2019 19:44:29 +0000 Subject: [PATCH 1/2] Update makefiles --- libtomcrypt_VS2008.vcproj | 4 ++++ makefile.mingw | 8 ++++---- makefile.msvc | 8 ++++---- makefile.unix | 8 ++++---- makefile_include.mk | 8 ++++---- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index a0b5ddfc8..dc0ee5980 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -2382,6 +2382,10 @@ RelativePath="src\pk\ecc\ecc_recover_key.c" > + + diff --git a/makefile.mingw b/makefile.mingw index 04296fc41..50ebebcad 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -184,10 +184,10 @@ src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o src/pk/ecc/ecc_find_curv src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o src/pk/ecc/ecc_get_size.o \ src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o src/pk/ecc/ecc_import_pkcs8.o \ src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_recover_key.o \ -src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o \ -src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ diff --git a/makefile.msvc b/makefile.msvc index b9bb484fb..6e377baab 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -177,10 +177,10 @@ src/pk/ecc/ecc_export.obj src/pk/ecc/ecc_export_openssl.obj src/pk/ecc/ecc_find_ src/pk/ecc/ecc_free.obj src/pk/ecc/ecc_get_key.obj src/pk/ecc/ecc_get_oid_str.obj src/pk/ecc/ecc_get_size.obj \ src/pk/ecc/ecc_import.obj src/pk/ecc/ecc_import_openssl.obj src/pk/ecc/ecc_import_pkcs8.obj \ src/pk/ecc/ecc_import_x509.obj src/pk/ecc/ecc_make_key.obj src/pk/ecc/ecc_recover_key.obj \ -src/pk/ecc/ecc_set_curve.obj src/pk/ecc/ecc_set_curve_internal.obj src/pk/ecc/ecc_set_key.obj \ -src/pk/ecc/ecc_shared_secret.obj src/pk/ecc/ecc_sign_hash.obj src/pk/ecc/ecc_sizes.obj \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj src/pk/ecc/ltc_ecc_export_point.obj \ -src/pk/ecc/ltc_ecc_import_point.obj src/pk/ecc/ltc_ecc_is_point.obj \ +src/pk/ecc/ecc_rfc6979_key.obj src/pk/ecc/ecc_set_curve.obj src/pk/ecc/ecc_set_curve_internal.obj \ +src/pk/ecc/ecc_set_key.obj src/pk/ecc/ecc_shared_secret.obj src/pk/ecc/ecc_sign_hash.obj \ +src/pk/ecc/ecc_sizes.obj src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj \ +src/pk/ecc/ltc_ecc_export_point.obj src/pk/ecc/ltc_ecc_import_point.obj src/pk/ecc/ltc_ecc_is_point.obj \ src/pk/ecc/ltc_ecc_is_point_at_infinity.obj src/pk/ecc/ltc_ecc_map.obj src/pk/ecc/ltc_ecc_mul2add.obj \ src/pk/ecc/ltc_ecc_mulmod.obj src/pk/ecc/ltc_ecc_mulmod_timing.obj src/pk/ecc/ltc_ecc_points.obj \ src/pk/ecc/ltc_ecc_projective_add_point.obj src/pk/ecc/ltc_ecc_projective_dbl_point.obj \ diff --git a/makefile.unix b/makefile.unix index b0a57b673..30690ef5d 100644 --- a/makefile.unix +++ b/makefile.unix @@ -194,10 +194,10 @@ src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o src/pk/ecc/ecc_find_curv src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o src/pk/ecc/ecc_get_size.o \ src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o src/pk/ecc/ecc_import_pkcs8.o \ src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_recover_key.o \ -src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o \ -src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ diff --git a/makefile_include.mk b/makefile_include.mk index 791d5cc3b..13b46201a 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -354,10 +354,10 @@ src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o src/pk/ecc/ecc_find_curv src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o src/pk/ecc/ecc_get_size.o \ src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o src/pk/ecc/ecc_import_pkcs8.o \ src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_recover_key.o \ -src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o \ -src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ From 969c524747ba1bf497ae2397f03d2d3fce649718 Mon Sep 17 00:00:00 2001 From: Russ Williams <37781645+rmw42@users.noreply.github.com> Date: Sat, 19 Jan 2019 19:45:20 +0000 Subject: [PATCH 2/2] RFC6979: implementation, tests, docs --- doc/crypt.tex | 7 +- src/headers/tomcrypt_pk.h | 1 + src/pk/ecc/ecc_rfc6979_key.c | 143 +++++++++++++++++++++++++++++++++++ src/pk/ecc/ecc_sign_hash.c | 37 ++++++--- tests/ecc_test.c | 9 +++ 5 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 src/pk/ecc/ecc_rfc6979_key.c diff --git a/doc/crypt.tex b/doc/crypt.tex index 2347062c9..89be85c45 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -5518,8 +5518,11 @@ \subsection{Signature Generation} \end{verbatim} This function will ECDSA sign the message digest stored in the array pointed to by \textit{in} of length \textit{inlen} octets. The signature -will be stored in the array pointed to by \textit{out} of length \textit{outlen} octets. The function requires a properly seeded PRNG, and -the ECC \textit{key} provided must be a private key. +will be stored in the array pointed to by \textit{out} of length \textit{outlen} octets. The function requires that the ECC +\textit{key} provided must be a private key. + +It requires a properly seeded PRNG for standard ECDSA, or if \textit{prng} is NULL and/or \textit{wprng} is less than zero, +the private key and the message itself will be used to create a deterministic signature according to RFC6979. \index{ecc\_sign\_hash\_rfc7518()} \begin{verbatim} diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index fc196d01a..04394c473 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -265,6 +265,7 @@ int ecc_get_size(const ecc_key *key); int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu); int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key); int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); +int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc_key *key); int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key); diff --git a/src/pk/ecc/ecc_rfc6979_key.c b/src/pk/ecc/ecc_rfc6979_key.c new file mode 100644 index 000000000..a13b9f8f0 --- /dev/null +++ b/src/pk/ecc/ecc_rfc6979_key.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +/** + @file ecc_rfc6979_key.c + ECC Crypto, Russ Williams +*/ + +#ifdef LTC_MECC +#ifdef LTC_SHA256 + +/** + Make deterministic ECC key using the RFC6979 method + @param priv [in] Private key for HMAC + @param in Message to sign for HMAC + @param inlen Length of the message + @param key [out] Newly created deterministic key + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc_key *key) +{ + int err, hash, i; + unsigned char v[32], k[32], digest[32]; /* No way to determine hash so always use SHA256 */ + unsigned char buffer[256]; + unsigned long outlen, buflen, qlen; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->dp.size > 0); + + hash = find_hash("sha256"); + if (hash == -1) {err = CRYPT_ERROR; goto error;} + + /* Length, in bytes, of key */ + i = mp_count_bits(key->dp.order); + qlen = (i+7) >> 3; + + /* RFC6979 3.2b, set V */ + for (i=0; i<32; i++) v[i] = 0x01; + + /* RFC6979 3.2c, set K */ + for (i=0; i<32; i++) k[i] = 0x00; + + /* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */ + XMEMCPY(&buffer[0], v, 32); + buffer[32] = 0x00; + if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; } + XMEMCPY(&buffer[33+qlen], in, inlen); + buflen = 32 + 1 + qlen + inlen; + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(k, digest, 32); + + /* RFC6979 3.2e, set V = HMAC_K(V) */ + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(v, digest, 32); + + /* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */ + XMEMCPY(&buffer[0], v, 32); + buffer[32] = 0x01; + if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; } + XMEMCPY(&buffer[33+qlen], in, inlen); + buflen = 32 + 1 + qlen + inlen; + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(k, digest, 32); + + /* RFC6979 3.2g, set V = HMAC_K(V) */ + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(v, digest, 32); + + /* RFC6979 3.2h, generate and check key */ + do { + /* concatenate hash bits into T */ + buflen = 0; + while (buflen < qlen) { + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(v, digest, 32); + XMEMCPY(&buffer[buflen], v, 32); + buflen += 32; + } + + /* key->k = bits2int(T) */ + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buffer, qlen)) != CRYPT_OK) { goto error; } + + /* make the public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) { + goto error; + } + + /* check that k is in range [1,q-1] */ + if (mp_cmp_d(key->k, 0) == LTC_MP_GT && mp_cmp(key->k, key->dp.order) == LTC_MP_LT) { + /* TODO: Check that pubkey.x != 0 (mod p) */ + + /* if we have a valid key, exit loop */ + break; + } else { + /* K = HMAC_K(V::0x00) */ + XMEMCPY(&buffer[0], v, 32); + buffer[32] = 0x00; + buflen = 32 + 1; + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(k, digest, 32); + + /* V = HMAC_K(V) */ + outlen = sizeof(digest); + if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; } + XMEMCPY(v, digest, 32); + + /* ... and try again! */ + } + } while (1); + + key->type = PK_PRIVATE; + + /* success */ + err = CRYPT_OK; + goto cleanup; + +error: + ecc_free(key); +cleanup: + return err; +} + +#endif +#endif +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ + diff --git a/src/pk/ecc/ecc_sign_hash.c b/src/pk/ecc/ecc_sign_hash.c index c7a808d8d..84780b685 100644 --- a/src/pk/ecc/ecc_sign_hash.c +++ b/src/pk/ecc/ecc_sign_hash.c @@ -22,8 +22,8 @@ @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use + @param prng An active PRNG state, NULL for RFC6979 deterministic signatures + @param wprng The index of the PRNG you wish to use, -1 for RFC6979 deterministic signatures @param sigformat The format of the signature to generate (ecc_signature_type) @param recid [out] The recovery ID for this signature (optional) @param key A private ECC key @@ -37,6 +37,7 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, ecc_key pubkey; void *r, *s, *e, *p, *b; int v = 0; + int blinding = 1; int err, max_iterations = LTC_PK_MAX_RETRIES; unsigned long pbits, pbytes, i, shift_right; unsigned char ch, buf[MAXBLOCKSIZE]; @@ -79,7 +80,13 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, /* make up a key and export the public copy */ do { if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } - if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } + + if (wprng < 0 || prng == NULL) { + blinding = 0; + if ((err = ecc_rfc6979_key(key, in, inlen, &pubkey)) != CRYPT_OK) { goto errnokey; } + } else { + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } + } /* find r = x1 mod n */ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } @@ -99,15 +106,23 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, if (mp_iszero(r) == LTC_MP_YES) { ecc_free(&pubkey); } else { - if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ /* find s = (e + xr)/k */ - if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ - if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ - if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ - if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ - if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ - if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ - if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ + if (blinding) { + if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ + if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ + if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ + if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ + if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ + if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ + if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ + if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ + } else { + if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */ + if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ + if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/k */ + if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/k */ + if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = (e + xr)/k */ + } ecc_free(&pubkey); if (mp_iszero(s) == LTC_MP_NO) { break; diff --git a/tests/ecc_test.c b/tests/ecc_test.c index 880ded55b..57801335f 100644 --- a/tests/ecc_test.c +++ b/tests/ecc_test.c @@ -605,6 +605,15 @@ static int _ecc_new_api(void) } #endif +#ifdef LTC_SHA256 + /* test RFC6979 signature */ + len = sizeof(buf); + DO(ecc_sign_hash(data16, 16, buf, &len, NULL, -1, &privkey)); + stat = 0; + DO(ecc_verify_hash(buf, len, data16, 16, &stat, &pubkey)); + if (stat != 1) return CRYPT_FAIL_TESTVECTOR; +#endif + /* test encryption */ len = sizeof(buf); DO(ecc_encrypt_key(data16, 16, buf, &len, &yarrow_prng, find_prng("yarrow"), find_hash("sha256"), &pubkey));