summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2021-09-13 11:47:04 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2021-09-13 11:47:04 +0900
commit5af468db3a665a29137e8d4a38f67437d700c046 (patch)
tree3f753e6addd2d4376a78fcb7d20c95b33c4270f9
parentfa04f89b6a17d81db2b3344826e6287d5117ff7b (diff)
downloadlibgcrypt-5af468db3a665a29137e8d4a38f67437d700c046.tar.gz
cipher: Fix ECDSA to support supplied K input.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/ecc-common.h2
-rw-r--r--cipher/ecc-ecdsa.c76
-rw-r--r--cipher/ecc.c11
3 files changed, 58 insertions, 31 deletions
diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index c128aeb3..01fb9042 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -87,7 +87,7 @@ gpg_err_code_t _gcry_ecc_mont_encodepoint (gcry_mpi_t x, unsigned int nbits,
/*-- ecc.c --*/
/*-- ecc-ecdsa.c --*/
-gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
+gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, gcry_mpi_t k, mpi_ec_t ec,
gcry_mpi_t r, gcry_mpi_t s,
int flags, int hashalgo);
gpg_err_code_t _gcry_ecc_ecdsa_verify (gcry_mpi_t input, mpi_ec_t ec,
diff --git a/cipher/ecc-ecdsa.c b/cipher/ecc-ecdsa.c
index c7f4c8d5..3f3ef97b 100644
--- a/cipher/ecc-ecdsa.c
+++ b/cipher/ecc-ecdsa.c
@@ -38,7 +38,7 @@
* must have allocated R and S.
*/
gpg_err_code_t
-_gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
+_gcry_ecc_ecdsa_sign (gcry_mpi_t input, gcry_mpi_t k_supplied, mpi_ec_t ec,
gcry_mpi_t r, gcry_mpi_t s,
int flags, int hashalgo)
{
@@ -94,34 +94,39 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
/* Two loops to avoid R or S are zero. This is more of a joke than
a real demand because the probability of them being zero is less
than any hardware failure. Some specs however require it. */
- do
+ while (1)
{
- do
+ while (1)
{
- mpi_free (k);
- k = NULL;
- if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
+ if (k_supplied)
+ k = k_supplied;
+ else
{
- /* Use Pornin's method for deterministic DSA. If this
- flag is set, it is expected that HASH is an opaque
- MPI with the to be signed hash. That hash is also
- used as h1 from 3.2.a. */
- if (!mpi_is_opaque (input))
+ mpi_free (k);
+ k = NULL;
+ if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
{
- rc = GPG_ERR_CONFLICT;
- goto leave;
+ /* Use Pornin's method for deterministic DSA. If this
+ flag is set, it is expected that HASH is an opaque
+ MPI with the to be signed hash. That hash is also
+ used as h1 from 3.2.a. */
+ if (!mpi_is_opaque (input))
+ {
+ rc = GPG_ERR_CONFLICT;
+ goto leave;
+ }
+
+ abuf = mpi_get_opaque (input, &abits);
+ rc = _gcry_dsa_gen_rfc6979_k (&k, ec->n, ec->d,
+ abuf, (abits+7)/8,
+ hashalgo, extraloops);
+ if (rc)
+ goto leave;
+ extraloops++;
}
-
- abuf = mpi_get_opaque (input, &abits);
- rc = _gcry_dsa_gen_rfc6979_k (&k, ec->n, ec->d,
- abuf, (abits+7)/8,
- hashalgo, extraloops);
- if (rc)
- goto leave;
- extraloops++;
+ else
+ k = _gcry_dsa_gen_k (ec->n, GCRY_STRONG_RANDOM);
}
- else
- k = _gcry_dsa_gen_k (ec->n, GCRY_STRONG_RANDOM);
mpi_invm (k_1, k, ec->n); /* k_1 = k^(-1) mod n */
@@ -136,8 +141,16 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
goto leave;
}
mpi_mod (r, x, ec->n); /* r = x mod n */
+
+ if (mpi_cmp_ui (r, 0))
+ break;
+
+ if (k_supplied)
+ {
+ rc = GPG_ERR_INV_VALUE;
+ goto leave;
+ }
}
- while (!mpi_cmp_ui (r, 0));
/* Computation of dr, sum, and s are blinded with b. */
mpi_mulm (dr, b, ec->d, ec->n);
@@ -147,8 +160,15 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
mpi_mulm (s, k_1, sum, ec->n); /* s = k^(-1)*(hash+(d*r)) mod n */
/* Undo blinding by b^-1 */
mpi_mulm (s, bi, s, ec->n);
+ if (mpi_cmp_ui (s, 0))
+ break;
+
+ if (k_supplied)
+ {
+ rc = GPG_ERR_INV_VALUE;
+ break;
+ }
}
- while (!mpi_cmp_ui (s, 0));
if (DBG_CIPHER)
{
@@ -164,7 +184,8 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
mpi_free (k_1);
mpi_free (sum);
mpi_free (dr);
- mpi_free (k);
+ if (!k_supplied)
+ mpi_free (k);
if (hash != input)
mpi_free (hash);
@@ -179,8 +200,7 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ec,
*/
gpg_err_code_t
_gcry_ecc_ecdsa_verify (gcry_mpi_t input, mpi_ec_t ec,
- gcry_mpi_t r, gcry_mpi_t s,
- int flags, int hashalgo)
+ gcry_mpi_t r, gcry_mpi_t s, int flags, int hashalgo)
{
gpg_err_code_t err = 0;
gcry_mpi_t hash, h, h1, h2, x;
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 77f9417f..9f0e7b11 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -285,7 +285,7 @@ test_keys (mpi_ec_t ec, unsigned int nbits)
_gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
- if (_gcry_ecc_ecdsa_sign (test, ec, r, s, 0, 0) )
+ if (_gcry_ecc_ecdsa_sign (test, NULL, ec, r, s, 0, 0) )
log_fatal ("ECDSA operation: sign failed\n");
if (_gcry_ecc_ecdsa_verify (test, ec, r, s, 0, 0))
@@ -683,6 +683,7 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
gcry_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_mpi_t data = NULL;
+ gcry_mpi_t k = NULL;
gcry_mpi_t sig_r = NULL;
gcry_mpi_t sig_s = NULL;
mpi_ec_t ec = NULL;
@@ -716,6 +717,11 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
if (DBG_CIPHER)
log_mpidump ("ecc_sign data", data);
+ if (ctx.label)
+ rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, ctx.label, ctx.labellen, NULL);
+ if (rc)
+ goto leave;
+
/* Hash algo is determined by curve in EdDSA. Fill it if not specified. */
if ((ctx.flags & PUBKEY_FLAG_EDDSA) && !ctx.hash_algo)
{
@@ -752,7 +758,7 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
}
else
{
- rc = _gcry_ecc_ecdsa_sign (data, ec, sig_r, sig_s,
+ rc = _gcry_ecc_ecdsa_sign (data, k, ec, sig_r, sig_s,
ctx.flags, ctx.hash_algo);
if (!rc)
rc = sexp_build (r_sig, NULL,
@@ -763,6 +769,7 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
_gcry_mpi_release (sig_r);
_gcry_mpi_release (sig_s);
_gcry_mpi_release (data);
+ _gcry_mpi_release (k);
_gcry_mpi_ec_free (ec);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)