diff options
-rw-r--r-- | cipher/ecc-common.h | 2 | ||||
-rw-r--r-- | cipher/ecc-ecdsa.c | 76 | ||||
-rw-r--r-- | cipher/ecc.c | 11 |
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) |