diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2021-09-08 11:35:27 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2021-09-14 11:15:16 +0900 |
commit | 422031a5943f2e698036e3c0df5955c585f22c16 (patch) | |
tree | 7a1b849ef582a96a1b1ebcfc7eab9d9af9272108 | |
parent | df4fe02794bb3511f7006d641e99736bad091c58 (diff) | |
download | libgcrypt-422031a5943f2e698036e3c0df5955c585f22c16.tar.gz |
cipher: Support internal hashing with "prehash" for RSA PKCS#1.
* cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Support internal
hashing.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r-- | cipher/pubkey-util.c | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 970d9d97..17816ef9 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -939,29 +939,81 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, xfree (random_override); } } - else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash + else if (ctx->encoding == PUBKEY_ENC_PKCS1 + && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH))) && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY)) { - if (sexp_length (lhash) != 3) - rc = GPG_ERR_INV_OBJ; - else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n ) - rc = GPG_ERR_INV_OBJ; - else + if (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)) { - const void * value; + void * value; size_t valuelen; + gcry_sexp_t list; - ctx->hash_algo = get_hash_algo (s, n); + /* Get HASH-ALGO. */ + list = sexp_find_token (ldata, "hash-algo", 0); + if (list) + { + s = sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else + { + ctx->hash_algo = get_hash_algo (s, n); + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + } + sexp_release (list); + if (rc) + goto leave; + } + + if ( !(value=sexp_nth_buffer (lvalue, 1, &valuelen)) || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else if ((valuelen * 8) < valuelen) + { + xfree (value); + rc = GPG_ERR_TOO_LARGE; + } + else + { + void *hash; - if (!ctx->hash_algo) - rc = GPG_ERR_DIGEST_ALGO; - else if ( !(value=sexp_nth_data (lhash, 2, &valuelen)) - || !valuelen ) + n = _gcry_md_get_algo_dlen (ctx->hash_algo); + hash = xtrymalloc (n); + if (!hash) + rc = gpg_err_code_from_syserror (); + else + { + _gcry_md_hash_buffer (ctx->hash_algo, hash, value, valuelen); + rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits, + hash, n, ctx->hash_algo); + xfree (hash); + } + } + } + else if (lhash) + { + if (sexp_length (lhash) != 3) + rc = GPG_ERR_INV_OBJ; + else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n ) rc = GPG_ERR_INV_OBJ; else - rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits, - value, valuelen, - ctx->hash_algo); + { + const void * value; + size_t valuelen; + + ctx->hash_algo = get_hash_algo (s, n); + + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + else if ( !(value=sexp_nth_data (lhash, 2, &valuelen)) + || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits, + value, valuelen, + ctx->hash_algo); + } } } else if (ctx->encoding == PUBKEY_ENC_PKCS1_RAW && lvalue |