diff options
author | Werner Koch <wk@gnupg.org> | 2013-10-11 21:13:12 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-10-11 21:13:12 +0200 |
commit | 07950c865a901afc48acb46f0695040cadfd5068 (patch) | |
tree | d608acf3116831d6a8874caa4686efcd44f87b9e /cipher/ecc.c | |
parent | 6bd5d18c45a4a3ce8f0f66f56c83b80594877f53 (diff) | |
download | libgcrypt-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.c | 159 |
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; } |