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 | |
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>
-rw-r--r-- | cipher/pubkey-internal.h | 2 | ||||
-rw-r--r-- | cipher/pubkey-util.c | 7 | ||||
-rw-r--r-- | cipher/rsa-common.c | 48 | ||||
-rw-r--r-- | cipher/rsa.c | 2 |
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; |