Index: b/cipher/ecc-ecdsa.c =================================================================== --- b/cipher/ecc-ecdsa.c +++ b/cipher/ecc-ecdsa.c @@ -67,7 +67,16 @@ mpi_rshift (hash, hash, abits - qbits); } else - hash = input; + { + abits = mpi_get_nbits (input); + if (abits > qbits) + { + hash = _gcry_mpi_copy (input); + mpi_rshift (hash, hash, mpi_get_nbits (input) - qbits); + } + else + hash = input; + } k = NULL; @@ -164,6 +173,7 @@ gcry_mpi_t h, h1, h2, x; mpi_point_struct Q, Q1, Q2; mpi_ec_t ctx; + unsigned int abits, nbits; if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) ) return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */ @@ -183,8 +193,16 @@ /* h = s^(-1) (mod n) */ mpi_invm (h, s, pkey->E.n); + abits = mpi_get_nbits (input); + nbits = mpi_get_nbits (pkey->E.n); /* h1 = hash * s^(-1) (mod n) */ - mpi_mulm (h1, input, h, pkey->E.n); + if (abits > nbits) + { + mpi_rshift (h1, input, abits - nbits); + mpi_mulm (h1, h1, h, pkey->E.n); + } + else + mpi_mulm (h1, input, h, pkey->E.n); /* Q1 = [ hash * s^(-1) ]G */ _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx); /* h2 = r * s^(-1) (mod n) */ Index: b/tests/pubkey.c =================================================================== --- b/tests/pubkey.c +++ b/tests/pubkey.c @@ -980,9 +980,23 @@ "(data (flags raw)\n" " (value #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; + static const char hash2_string[] = + "(data (flags raw)\n" + " (value #00112233445566778899AABBCCDDEEFF" + /* */ "000102030405060708090A0B0C0D0E0F" + /* */ "000102030405060708090A0B0C0D0E0F" + /* */ "00112233445566778899AABBCCDDEEFF#))"; + /* hash2, but longer than curve length, so it will be truncated */ + static const char hash3_string[] = + "(data (flags raw)\n" + " (value #00112233445566778899AABBCCDDEEFF" + /* */ "000102030405060708090A0B0C0D0E0F" + /* */ "000102030405060708090A0B0C0D0E0F" + /* */ "00112233445566778899AABBCCDDEEFF" + /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; - gcry_sexp_t key, hash, sig; + gcry_sexp_t key, hash, hash2, hash3, sig, sig2; if (verbose) fprintf (stderr, "Checking sample ECC key.\n"); @@ -990,6 +1004,12 @@ if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); + if ((err = gcry_sexp_new (&hash2, hash2_string, 0, 1))) + die ("line %d: %s", __LINE__, gpg_strerror (err)); + + if ((err = gcry_sexp_new (&hash3, hash3_string, 0, 1))) + die ("line %d: %s", __LINE__, gpg_strerror (err)); + if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); @@ -1003,6 +1023,27 @@ if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); + /* Verify hash truncation */ + gcry_sexp_release (key); + if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) + die ("line %d: %s", __LINE__, gpg_strerror (err)); + + if ((err = gcry_pk_sign (&sig2, hash2, key))) + die ("gcry_pk_sign failed: %s", gpg_strerror (err)); + + if ((err = gcry_pk_sign (&sig, hash3, key))) + die ("gcry_pk_sign failed: %s", gpg_strerror (err)); + + gcry_sexp_release (key); + if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) + die ("line %d: %s", __LINE__, gpg_strerror (err)); + + if ((err = gcry_pk_verify (sig, hash2, key))) + die ("gcry_pk_verify failed 2: %s", gpg_strerror (err)); + + if ((err = gcry_pk_verify (sig2, hash3, key))) + die ("gcry_pk_verify failed 3: %s", gpg_strerror (err)); + /* Now try signing without the Q parameter. */ gcry_sexp_release (key); @@ -1021,8 +1062,10 @@ die ("gcry_pk_verify signed without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); + gcry_sexp_release (sig2); gcry_sexp_release (key); gcry_sexp_release (hash); + gcry_sexp_release (hash2); }