summaryrefslogtreecommitdiff
path: root/cipher/elgamal.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-10-11 21:13:12 +0200
committerWerner Koch <wk@gnupg.org>2013-10-11 21:13:12 +0200
commit07950c865a901afc48acb46f0695040cadfd5068 (patch)
treed608acf3116831d6a8874caa4686efcd44f87b9e /cipher/elgamal.c
parent6bd5d18c45a4a3ce8f0f66f56c83b80594877f53 (diff)
downloadlibgcrypt-07950c865a901afc48acb46f0695040cadfd5068.tar.gz
pubkey: Move sexp parsing for gcry_pk_decrypt to the modules.
* cipher/rsa.c (rsa_decrypt): Revamp. * cipher/elgamal.c (elg_decrypt): Revamp. * cipher/ecc.c (ecc_decrypt_raw): Revamp. * cipher/pubkey.c (gcry_pk_decrypt): Simplify. (sexp_to_enc): Remove. * cipher/pubkey-util.c (_gcry_pk_util_preparse_encval): New. -- Note that we do not have a regression test for ecc_decrypt_raw. Even GnuPG does not use it. we also better check whether the interface is really usable; for example GnuPG implements way to much low-level ECC code. Maybe we should move the OpenPGP ECC encryption code into Libgcrypt. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/elgamal.c')
-rw-r--r--cipher/elgamal.c145
1 files changed, 89 insertions, 56 deletions
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 37182874..7fedc7bf 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -811,71 +811,104 @@ elg_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
static gcry_err_code_t
-elg_decrypt (int algo, gcry_sexp_t *r_plain,
- gcry_mpi_t *data, gcry_mpi_t *skey, int flags,
- enum pk_encoding encoding, int hash_algo,
- unsigned char *label, size_t labellen)
+elg_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
- gcry_err_code_t rc;
- ELG_secret_key sk;
- gcry_mpi_t plain;
+ gpg_err_code_t rc;
+ struct pk_encoding_ctx ctx;
+ gcry_sexp_t l1 = NULL;
+ gcry_mpi_t data_a = NULL;
+ gcry_mpi_t data_b = NULL;
+ ELG_secret_key sk = {NULL, NULL, NULL, NULL};
+ gcry_mpi_t plain = NULL;
+ unsigned char *unpad = NULL;
+ size_t unpadlen = 0;
- (void)algo;
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
+ elg_get_nbits (keyparms));
- if ((! data[0]) || (! data[1])
- || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
- rc = GPG_ERR_BAD_MPI;
- else
+ /* Extract the data. */
+ rc = _gcry_pk_util_preparse_encval (s_data, elg_names, &l1, &ctx);
+ if (rc)
+ goto leave;
+ rc = _gcry_pk_util_extract_mpis (l1, "ab", &data_a, &data_b, NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
{
- unsigned char *unpad = NULL;
- size_t unpadlen = 0;
- unsigned int nbits;
+ log_printmpi ("elg_decrypt d_a", data_a);
+ log_printmpi ("elg_decrypt d_b", data_b);
+ }
+ if (mpi_is_opaque (data_a) || mpi_is_opaque (data_b))
+ {
+ rc = GPG_ERR_INV_DATA;
+ goto leave;
+ }
- sk.p = skey[0];
- sk.g = skey[1];
- sk.y = skey[2];
- sk.x = skey[3];
+ /* Extract the key. */
+ rc = _gcry_pk_util_extract_mpis (keyparms, "pgyx",
+ &sk.p, &sk.g, &sk.y, &sk.x,
+ NULL);
+ if (rc)
+ return rc;
+ if (DBG_CIPHER)
+ {
+ log_printmpi ("elg_decrypt p", sk.p);
+ log_printmpi ("elg_decrypt g", sk.g);
+ log_printmpi ("elg_decrypt y", sk.y);
+ if (!fips_mode ())
+ log_printmpi ("elg_decrypt x", sk.x);
+ }
- nbits = gcry_mpi_get_nbits (sk.p);
+ plain = gcry_mpi_snew (ctx.nbits);
+ decrypt (plain, data_a, data_b, &sk);
+ if (DBG_CIPHER)
+ log_printmpi ("elg_decrypt res", plain);
- plain = mpi_snew (nbits);
- decrypt (plain, data[0], data[1], &sk);
+ /* Reverse the encoding and build the s-expression. */
+ switch (ctx.encoding)
+ {
+ case PUBKEY_ENC_PKCS1:
+ rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
+ mpi_free (plain); plain = NULL;
+ if (!rc)
+ rc = gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad);
+ break;
+
+ case PUBKEY_ENC_OAEP:
+ rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
+ ctx.nbits, ctx.hash_algo, plain,
+ ctx.label, ctx.labellen);
+ mpi_free (plain); plain = NULL;
+ if (!rc)
+ rc = gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad);
+ break;
+
+ default:
+ /* Raw format. For backward compatibility we need to assume a
+ signed mpi by using the sexp format string "%m". */
+ rc = gcry_sexp_build (r_plain, NULL,
+ (ctx.flags & PUBKEY_FLAG_LEGACYRESULT)
+ ? "%m" : "(value %m)",
+ plain);
+ break;
+ }
- /* Reverse the encoding and build the s-expression. */
- switch (encoding)
- {
- case PUBKEY_ENC_PKCS1:
- rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain);
- mpi_free (plain);
- plain = NULL;
- if (!rc)
- rc = gcry_sexp_build (r_plain, NULL, "(value %b)",
- (int)unpadlen, unpad);
- break;
-
- case PUBKEY_ENC_OAEP:
- rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
- nbits, hash_algo, plain, label, labellen);
- mpi_free (plain);
- plain = NULL;
- if (!rc)
- rc = gcry_sexp_build (r_plain, NULL, "(value %b)",
- (int)unpadlen, unpad);
- break;
-
- default:
- /* Raw format. For backward compatibility we need to assume a
- signed mpi by using the sexp format string "%m". */
- rc = gcry_sexp_build (r_plain, NULL,
- (flags & PUBKEY_FLAG_LEGACYRESULT)
- ? "%m" : "(value %m)",
- plain);
- break;
- }
- gcry_free (unpad);
- mpi_free (plain);
- }
+ leave:
+ gcry_free (unpad);
+ gcry_mpi_release (plain);
+ gcry_mpi_release (sk.p);
+ gcry_mpi_release (sk.g);
+ gcry_mpi_release (sk.y);
+ gcry_mpi_release (sk.x);
+ gcry_mpi_release (data_a);
+ gcry_mpi_release (data_b);
+ gcry_sexp_release (l1);
+ _gcry_pk_util_free_encoding_ctx (&ctx);
+ if (DBG_CIPHER)
+ log_debug ("elg_decrypt => %s\n", gpg_strerror (rc));
return rc;
}