diff options
author | Werner Koch <wk@gnupg.org> | 2013-10-11 15:39:22 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-10-11 15:39:22 +0200 |
commit | 6bd5d18c45a4a3ce8f0f66f56c83b80594877f53 (patch) | |
tree | 610dd1f7881729aa98ee1795e66303bc8e4ae8ce /cipher/ecc.c | |
parent | d0ae6635e4e6ae273c3a137c513d518f28f6eab3 (diff) | |
download | libgcrypt-6bd5d18c45a4a3ce8f0f66f56c83b80594877f53.tar.gz |
pubkey: Move sexp parsing for gcry_pk_encrypt to the modules.
* cipher/rsa.c (rsa_encrypt): Revamp.
* cipher/elgamal.c (elg_encrypt): Revamp.
* cipher/ecc.c (ecc_encrypt_raw): Revamp.
* cipher/pubkey.c (gcry_pk_encrypt): Simplify.
* tests/basic.c (check_pubkey_crypt): Init plain, ciph, and data so
that they are initialized even after an encrypt failure.
--
Note that we do not have a regression test for ecc_encrypt_raw. Thus
it is possible that a bug has been introduced. Should be tested using
GnuPG master.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/ecc.c')
-rw-r--r-- | cipher/ecc.c | 155 |
1 files changed, 114 insertions, 41 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c index f98a5cc2..051308f0 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1786,46 +1786,106 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) * result[0] : shared point (kdG) */ static gcry_err_code_t -ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k, - gcry_mpi_t *pkey, int flags) +ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) { - gpg_err_code_t rc; + gcry_err_code_t rc; + struct pk_encoding_ctx ctx; + gcry_sexp_t l1 = NULL; + char *curvename = NULL; + gcry_mpi_t mpi_g = NULL; + gcry_mpi_t mpi_q = NULL; + gcry_mpi_t mpi_s = NULL; + gcry_mpi_t mpi_e = NULL; + gcry_mpi_t data = NULL; ECC_public_key pk; - mpi_ec_t ctx; - gcry_mpi_t s, e; - - (void)algo; - (void)flags; + mpi_ec_t ec = NULL; - if (!k - || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) - return GPG_ERR_BAD_MPI; + memset (&pk, 0, sizeof pk); + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, + ecc_get_nbits (keyparms)); - pk.E.model = MPI_EC_WEIERSTRASS; - pk.E.p = pkey[0]; - pk.E.a = pkey[1]; - pk.E.b = pkey[2]; - point_init (&pk.E.G); - rc = _gcry_ecc_os2ec (&pk.E.G, pkey[3]); + /* + * Extract the data. + */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); if (rc) + goto leave; + if (DBG_CIPHER) + log_mpidump ("ecc_encrypt data", data); + if (mpi_is_opaque (data)) { - point_free (&pk.E.G); - return rc; + rc = GPG_ERR_INV_DATA; + goto leave; } - pk.E.n = pkey[4]; - point_init (&pk.Q); - rc = _gcry_ecc_os2ec (&pk.Q, pkey[5]); + + + /* + * Extract the key. + */ + rc = _gcry_pk_util_extract_mpis (keyparms, "-p?a?b?g?n?+q", + &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, + &mpi_q, NULL); if (rc) + goto leave; + if (mpi_g) { - point_free (&pk.E.G); - point_free (&pk.Q); - return rc; + point_init (&pk.E.G); + rc = _gcry_ecc_os2ec (&pk.E.G, mpi_g); + if (rc) + goto leave; + } + /* 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, &pk.E, NULL); + if (rc) + return rc; + } + } + /* Guess required fields if a curve parameter has not been given. */ + if (!curvename) + { + pk.E.model = MPI_EC_WEIERSTRASS; + pk.E.dialect = ECC_DIALECT_STANDARD; } - ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, - pk.E.p, pk.E.a, pk.E.b); - s = mpi_alloc (mpi_get_nlimbs (pk.E.p)); - e = mpi_alloc (mpi_get_nlimbs (pk.E.p)); + if (DBG_CIPHER) + { + log_debug ("ecc_encrypt info: %s/%s\n", + _gcry_ecc_model2str (pk.E.model), + _gcry_ecc_dialect2str (pk.E.dialect)); + if (pk.E.name) + log_debug ("ecc_encrypt name: %s\n", pk.E.name); + log_printmpi ("ecc_encrypt p", pk.E.p); + log_printmpi ("ecc_encrypt a", pk.E.a); + log_printmpi ("ecc_encrypt b", pk.E.b); + log_printpnt ("ecc_encrypt g", &pk.E.G, NULL); + log_printmpi ("ecc_encrypt n", pk.E.n); + log_printmpi ("ecc_encrypt q", mpi_q); + } + if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !mpi_q) + { + rc = GPG_ERR_NO_OBJ; + goto leave; + } + + /* Convert the public key. */ + if (mpi_q) + { + point_init (&pk.Q); + rc = _gcry_ecc_os2ec (&pk.Q, mpi_q); + if (rc) + goto leave; + } + + /* Compute the encrypted value. */ + ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, + pk.E.p, pk.E.a, pk.E.b); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { @@ -1838,18 +1898,18 @@ ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k, point_init (&R); /* R = kQ <=> R = kdG */ - _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx); + _gcry_mpi_ec_mul_point (&R, data, &pk.Q, ec); - 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 for kdG\n"); - s = _gcry_ecc_ec2os (x, y, pk.E.p); + mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p); /* R = kG */ - _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); + _gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec); - 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 for kG\n"); - e = _gcry_ecc_ec2os (x, y, pk.E.p); + mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p); mpi_free (x); mpi_free (y); @@ -1857,17 +1917,30 @@ ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k, point_free (&R); } - _gcry_mpi_ec_free (ctx); + rc = gcry_sexp_build (r_ciph, NULL, "(enc-val(ecdh(s%m)(e%m)))", + mpi_s, mpi_e); + + leave: + gcry_mpi_release (pk.E.p); + gcry_mpi_release (pk.E.a); + gcry_mpi_release (pk.E.b); + gcry_mpi_release (mpi_g); point_free (&pk.E.G); + gcry_mpi_release (pk.E.n); + gcry_mpi_release (mpi_q); point_free (&pk.Q); - - rc = gcry_sexp_build (r_result, NULL, "(enc-val(ecdh(s%m)(e%m)))", s, e); - mpi_free (s); - mpi_free (e); - + gcry_mpi_release (data); + gcry_mpi_release (mpi_s); + gcry_mpi_release (mpi_e); + gcry_free (curvename); + _gcry_mpi_ec_free (ec); + _gcry_pk_util_free_encoding_ctx (&ctx); + if (DBG_CIPHER) + log_debug ("ecc_encrypt => %s\n", gpg_strerror (rc)); return rc; } + /* input: * data[0] : a point kG (ephemeral public key) * output: |