summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2021-07-23 14:20:20 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2021-07-23 14:20:20 +0900
commit285b4cb70df1553c60fb5da6c94e1106694d4f9e (patch)
tree013fe5efc9cf2a74db8b4139747c74a06b639a3c
parent51307b1ceaa752d5a737b06ab0217d310faea403 (diff)
downloadlibgcrypt-285b4cb70df1553c60fb5da6c94e1106694d4f9e.tar.gz
cipher: Extend RSA-PSS internal function for verify, too.
* cipher/pubkey-internal.h (_gcry_rsa_pss_verify): Support internal hashing. * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Use opaque MPI for RSA-PSS. * cipher/rsa-common.c (_gcry_rsa_pss_verify): Support internal hashing. * cipher/rsa.c (rsa_verify): Allow opaque MPI for RSA-PSS. -- Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/pubkey-internal.h2
-rw-r--r--cipher/pubkey-util.c7
-rw-r--r--cipher/rsa-common.c48
-rw-r--r--cipher/rsa.c2
4 files changed, 42 insertions, 17 deletions
diff --git a/cipher/pubkey-internal.h b/cipher/pubkey-internal.h
index 8445e44a..2806fa8b 100644
--- a/cipher/pubkey-internal.h
+++ b/cipher/pubkey-internal.h
@@ -79,7 +79,7 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
const unsigned char *value, size_t valuelen,
const void *random_override);
gpg_err_code_t
-_gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
+_gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already, gcry_mpi_t encoded,
unsigned int nbits, int algo, size_t saltlen);
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index 9c6c1e16..02f7909e 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -39,9 +39,10 @@ static int
pss_verify_cmp (void *opaque, gcry_mpi_t tmp)
{
struct pk_encoding_ctx *ctx = opaque;
- gcry_mpi_t hash = ctx->verify_arg;
+ gcry_mpi_t value = ctx->verify_arg;
- return _gcry_rsa_pss_verify (hash, tmp, ctx->nbits - 1,
+ return _gcry_rsa_pss_verify (value, !(ctx->flags & PUBKEY_FLAG_PREHASH),
+ tmp, ctx->nbits - 1,
ctx->hash_algo, ctx->saltlen);
}
@@ -1129,7 +1130,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
sexp_release (list);
}
- *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
+ *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_OPAQUE);
if (!*ret_mpi)
rc = GPG_ERR_INV_OBJ;
ctx->verify_cmp = pss_verify_cmp;
diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c
index e69a069c..233ddb2d 100644
--- a/cipher/rsa-common.c
+++ b/cipher/rsa-common.c
@@ -912,17 +912,21 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
}
-/* Verify a signature assuming PSS padding. VALUE is the hash of the
- message (mHash) encoded as an MPI; its length must match the digest
- length of ALGO. ENCODED is the output of the RSA public key
- function (EM). NBITS is the size of the public key. ALGO is the
- hash algorithm and SALTLEN is the length of the used salt. The
+/* Verify a signature assuming PSS padding. When HASHED_ALREADY is
+ set, VALUE is the hash of the message (mHash); its length must
+ match the digest length of ALGO. Otherwise, its M (before mHash).
+ VALUE is an opaque MPI. ENCODED is the output of the RSA public
+ key function (EM). NBITS is the size of the public key. ALGO is
+ the hash algorithm and SALTLEN is the length of the used salt. The
function returns 0 on success or on error code. */
gpg_err_code_t
-_gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
+_gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already,
+ gcry_mpi_t encoded,
unsigned int nbits, int algo, size_t saltlen)
{
gcry_err_code_t rc = 0;
+ gcry_md_hd_t hd = NULL;
+ unsigned char *digest;
size_t hlen; /* Length of the hash digest. */
unsigned char *em = NULL; /* Encoded message. */
size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */
@@ -934,9 +938,14 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
unsigned char *mhash; /* Points into BUF. */
unsigned char *p;
size_t n;
+ unsigned int input_nbits;
/* This code is implemented as described by rfc-3447 9.1.2. */
+ rc = _gcry_md_open (&hd, algo, 0);
+ if (rc)
+ return rc;
+
/* Get the length of the digest. */
hlen = _gcry_md_get_algo_dlen (algo);
gcry_assert (hlen); /* We expect a valid ALGO here. */
@@ -966,11 +975,23 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
dbmask = buf;
mhash = buf + buflen - hlen;
- /* Step 2: That would be: mHash = Hash(M) but our input is already
- mHash thus we only need to convert VALUE into MHASH. */
- rc = octet_string_from_mpi (NULL, mhash, value, hlen);
- if (rc)
- goto leave;
+ /* Step 2: mHash = Hash(M) (or copy input to mHash, if already hashed). */
+ p = mpi_get_opaque (value, &input_nbits);
+ if (!p)
+ {
+ rc = GPG_ERR_INV_ARG;
+ goto leave;
+ }
+
+ if (!hashed_already)
+ {
+ _gcry_md_write (hd, p, (input_nbits+7)/8);
+ digest = _gcry_md_read (hd, 0);
+ memcpy (mhash, digest, hlen);
+ _gcry_md_reset (hd);
+ }
+ else
+ memcpy (mhash, p, hlen);
/* Convert the signature into an octet string. */
rc = octet_string_from_mpi (&em, NULL, encoded, emlen);
@@ -1034,12 +1055,15 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
memcpy (buf+8+hlen, salt, saltlen);
/* Step 13: H' = Hash(M'). */
- _gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen);
+ _gcry_md_write (hd, buf, 8 + hlen + saltlen);
+ digest = _gcry_md_read (hd, 0);
+ memcpy (buf, digest, hlen);
/* Step 14: Check H == H'. */
rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR;
leave:
+ _gcry_md_close (hd);
if (em)
{
wipememory (em, emlen);
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 575ea949..d97746a2 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -1582,7 +1582,7 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
goto leave;
if (DBG_CIPHER)
log_printmpi ("rsa_verify data", data);
- if (mpi_is_opaque (data))
+ if (ctx.encoding != PUBKEY_ENC_PSS && mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;