diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2021-07-23 14:20:20 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2021-07-23 14:20:20 +0900 |
commit | 285b4cb70df1553c60fb5da6c94e1106694d4f9e (patch) | |
tree | 013fe5efc9cf2a74db8b4139747c74a06b639a3c /cipher/rsa-common.c | |
parent | 51307b1ceaa752d5a737b06ab0217d310faea403 (diff) | |
download | libgcrypt-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>
Diffstat (limited to 'cipher/rsa-common.c')
-rw-r--r-- | cipher/rsa-common.c | 48 |
1 files changed, 36 insertions, 12 deletions
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); |