summaryrefslogtreecommitdiff
path: root/cipher/ecc.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/ecc.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/ecc.c')
-rw-r--r--cipher/ecc.c159
1 files changed, 109 insertions, 50 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 051308f0..17724e82 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1949,70 +1949,115 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
* see ecc_encrypt_raw for details.
*/
static gcry_err_code_t
-ecc_decrypt_raw (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)
+ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gpg_err_code_t rc;
+ struct pk_encoding_ctx ctx;
+ gcry_sexp_t l1 = NULL;
+ gcry_mpi_t data_e = NULL;
ECC_secret_key sk;
- mpi_point_struct R; /* Result that we return. */
+ gcry_mpi_t mpi_g = NULL;
+ char *curvename = NULL;
+ mpi_ec_t ec = NULL;
mpi_point_struct kG;
- mpi_ec_t ctx;
- gcry_mpi_t r;
-
- (void)algo;
- (void)flags;
- (void)encoding;
- (void)hash_algo;
- (void)label;
- (void)labellen;
-
- if (!data || !data[0]
- || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
- || !skey[5] || !skey[6] )
- return GPG_ERR_BAD_MPI;
+ mpi_point_struct R;
+ gcry_mpi_t r = NULL;
+ memset (&sk, 0, sizeof sk);
point_init (&kG);
- rc = _gcry_ecc_os2ec (&kG, data[0]);
+ point_init (&R);
+
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
+ ecc_get_nbits (keyparms));
+
+ /*
+ * Extract the data.
+ */
+ rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx);
if (rc)
+ goto leave;
+ rc = _gcry_pk_util_extract_mpis (l1, "e", &data_e, NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ log_printmpi ("ecc_decrypt d_e", data_e);
+ if (mpi_is_opaque (data_e))
{
- point_free (&kG);
- return rc;
+ rc = GPG_ERR_INV_DATA;
+ goto leave;
}
- sk.E.model = MPI_EC_WEIERSTRASS;
- sk.E.p = skey[0];
- sk.E.a = skey[1];
- sk.E.b = skey[2];
- point_init (&sk.E.G);
- rc = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
+ /*
+ * Extract the key.
+ */
+ rc = _gcry_pk_util_extract_mpis (keyparms, "-p?a?b?g?n?+d",
+ &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
+ &sk.d, NULL);
if (rc)
+ goto leave;
+ if (mpi_g)
{
- point_free (&kG);
- point_free (&sk.E.G);
- return rc;
+ point_init (&sk.E.G);
+ rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
+ if (rc)
+ goto leave;
}
- sk.E.n = skey[4];
- point_init (&sk.Q);
- rc = _gcry_ecc_os2ec (&sk.Q, skey[5]);
+ /* Add missing parameters using the optional curve parameter. */
+ gcry_sexp_release (l1);
+ l1 = gcry_sexp_find_token (keyparms, "curve", 5);
+ if (l1)
+ {
+ curvename = gcry_sexp_nth_string (l1, 1);
+ if (curvename)
+ {
+ rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
+ if (rc)
+ return rc;
+ }
+ }
+ /* Guess required fields if a curve parameter has not been given. */
+ if (!curvename)
+ {
+ sk.E.model = MPI_EC_WEIERSTRASS;
+ sk.E.dialect = ECC_DIALECT_STANDARD;
+ }
+ if (DBG_CIPHER)
+ {
+ log_debug ("ecc_decrypt info: %s/%s\n",
+ _gcry_ecc_model2str (sk.E.model),
+ _gcry_ecc_dialect2str (sk.E.dialect));
+ if (sk.E.name)
+ log_debug ("ecc_decrypt name: %s\n", sk.E.name);
+ log_printmpi ("ecc_decrypt p", sk.E.p);
+ log_printmpi ("ecc_decrypt a", sk.E.a);
+ log_printmpi ("ecc_decrypt b", sk.E.b);
+ log_printpnt ("ecc_decrypt g", &sk.E.G, NULL);
+ log_printmpi ("ecc_decrypt n", sk.E.n);
+ if (!fips_mode ())
+ log_printmpi ("ecc_decrypt d", sk.d);
+ }
+ if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+ {
+ rc = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+
+
+ /*
+ * Compute the plaintext.
+ */
+ rc = _gcry_ecc_os2ec (&kG, data_e);
if (rc)
{
point_free (&kG);
- point_free (&sk.E.G);
- point_free (&sk.Q);
return rc;
}
- sk.d = skey[6];
- ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect,
- sk.E.p, sk.E.a, sk.E.b);
+ ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect,
+ sk.E.p, sk.E.a, sk.E.b);
/* R = dkG */
- point_init (&R);
- _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx);
-
- point_free (&kG);
+ _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
/* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */
{
@@ -2021,7 +2066,7 @@ ecc_decrypt_raw (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data,
x = mpi_new (0);
y = mpi_new (0);
- if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
+ if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
log_fatal ("ecdh: Failed to get affine coordinates\n");
r = _gcry_ecc_ec2os (x, y, sk.E.p);
@@ -2032,16 +2077,30 @@ ecc_decrypt_raw (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data,
mpi_free (x);
mpi_free (y);
}
+ if (DBG_CIPHER)
+ log_printmpi ("ecc_decrypt res", r);
+
+ if (!rc)
+ rc = gcry_sexp_build (r_plain, NULL, "(value %m)", r);
+ leave:
point_free (&R);
- _gcry_mpi_ec_free (ctx);
point_free (&kG);
+ gcry_mpi_release (r);
+ gcry_mpi_release (sk.E.p);
+ gcry_mpi_release (sk.E.a);
+ gcry_mpi_release (sk.E.b);
+ gcry_mpi_release (mpi_g);
point_free (&sk.E.G);
- point_free (&sk.Q);
-
- if (!rc)
- rc = gcry_sexp_build (r_plain, NULL, "(value %m)", r);
- mpi_free (r);
+ gcry_mpi_release (sk.E.n);
+ gcry_mpi_release (sk.d);
+ gcry_mpi_release (data_e);
+ gcry_free (curvename);
+ gcry_sexp_release (l1);
+ _gcry_mpi_ec_free (ec);
+ _gcry_pk_util_free_encoding_ctx (&ctx);
+ if (DBG_CIPHER)
+ log_debug ("ecc_decrypt => %s\n", gpg_strerror (rc));
return rc;
}