diff options
-rw-r--r-- | cipher/ecc.c | 155 | ||||
-rw-r--r-- | cipher/elgamal.c | 63 | ||||
-rw-r--r-- | cipher/pubkey.c | 48 | ||||
-rw-r--r-- | cipher/rsa.c | 61 | ||||
-rw-r--r-- | src/cipher-proto.h | 8 | ||||
-rw-r--r-- | tests/basic.c | 4 |
6 files changed, 215 insertions, 124 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: diff --git a/cipher/elgamal.c b/cipher/elgamal.c index a4f5ce3d..37182874 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -755,30 +755,57 @@ elg_check_secret_key (int algo, gcry_mpi_t *skey) static gcry_err_code_t -elg_encrypt (int algo, gcry_sexp_t *r_result, - gcry_mpi_t data, gcry_mpi_t *pkey, int flags) +elg_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) { gcry_err_code_t rc; - ELG_public_key pk; - gcry_mpi_t a, b; + struct pk_encoding_ctx ctx; + gcry_mpi_t mpi_a = NULL; + gcry_mpi_t mpi_b = NULL; + gcry_mpi_t data = NULL; + ELG_public_key pk = { NULL, NULL, NULL }; - (void)algo; - (void)flags; + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, + elg_get_nbits (keyparms)); - if ((! data) || (! pkey[0]) || (! pkey[1]) || (! pkey[2])) - rc = GPG_ERR_BAD_MPI; - else + /* Extract the data. */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); + if (rc) + goto leave; + if (DBG_CIPHER) + log_mpidump ("elg_encrypt data", data); + if (mpi_is_opaque (data)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + + /* Extract the key. */ + rc = _gcry_pk_util_extract_mpis (keyparms, "pgy", &pk.p, &pk.g, &pk.y, NULL); + if (rc) + return rc; + if (DBG_CIPHER) { - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - a = mpi_alloc (mpi_get_nlimbs (pk.p)); - b = mpi_alloc (mpi_get_nlimbs (pk.p)); - do_encrypt (a, b, data, &pk); - rc = gcry_sexp_build (r_result, NULL, "(enc-val(elg(a%m)(b%m)))", a, b); - mpi_free (a); - mpi_free (b); + log_mpidump ("elg_encrypt p", pk.p); + log_mpidump ("elg_encrypt g", pk.g); + log_mpidump ("elg_encrypt y", pk.y); } + + /* Do Elgamal computation and build result. */ + mpi_a = gcry_mpi_new (0); + mpi_b = gcry_mpi_new (0); + do_encrypt (mpi_a, mpi_b, data, &pk); + rc = gcry_sexp_build (r_ciph, NULL, "(enc-val(elg(a%m)(b%m)))", mpi_a, mpi_b); + + leave: + gcry_mpi_release (mpi_a); + gcry_mpi_release (mpi_b); + gcry_mpi_release (pk.p); + gcry_mpi_release (pk.g); + gcry_mpi_release (pk.y); + gcry_mpi_release (data); + _gcry_pk_util_free_encoding_ctx (&ctx); + if (DBG_CIPHER) + log_debug ("elg_encrypt => %s\n", gpg_strerror (rc)); return rc; } diff --git a/cipher/pubkey.c b/cipher/pubkey.c index c0f4ab27..8a46e4e5 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -926,60 +926,22 @@ gcry_error_t gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) { gcry_err_code_t rc; - gcry_mpi_t *pkey = NULL; - gcry_mpi_t data = NULL; - struct pk_encoding_ctx ctx; - gcry_pk_spec_t *spec = NULL; - int i; + gcry_pk_spec_t *spec; + gcry_sexp_t keyparms; *r_ciph = NULL; - /* Get the key. */ - rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_ENCR, NULL, &pkey, &spec, NULL); - if (rc) - goto leave; - - gcry_assert (spec); - - /* Get the stuff we want to encrypt. */ - _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey)); - rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); + rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; - /* In fips mode DBG_CIPHER will never evaluate to true but as an - extra failsafe protection we explicitly test for fips mode - here. */ - if (DBG_CIPHER && !fips_mode ()) - { - log_debug ("pubkey_encrypt: algo=%d\n", spec->algo); - for(i = 0; i < pubkey_get_npkey (spec->algo); i++) - log_mpidump (" pkey", pkey[i]); - log_mpidump (" data", data); - } - if (spec->encrypt) - rc = spec->encrypt (spec->algo, r_ciph, data, pkey, ctx.flags); + rc = spec->encrypt (r_ciph, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; - - /* if (DBG_CIPHER && !fips_mode ()) */ - /* { */ - /* for (i = 0; i < pubkey_get_nenc (spec->algo); i++) */ - /* log_mpidump (" encr", ciph[i]); */ - /* } */ - leave: - mpi_free (data); - if (pkey) - { - release_mpi_array (pkey); - gcry_free (pkey); - } - - gcry_free (ctx.label); - + gcry_sexp_release (keyparms); return gcry_error (rc); } diff --git a/cipher/rsa.c b/cipher/rsa.c index db644520..51480df3 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -861,39 +861,68 @@ rsa_check_secret_key (int algo, gcry_mpi_t *skey) static gcry_err_code_t -rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, - gcry_mpi_t *pkey, int flags) +rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) { - gpg_err_code_t rc; - RSA_public_key pk; - gcry_mpi_t result; + gcry_err_code_t rc; + struct pk_encoding_ctx ctx; + gcry_mpi_t data = NULL; + RSA_public_key pk = {NULL, NULL}; + gcry_mpi_t ciph = NULL; - (void)algo; - (void)flags; + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, + rsa_get_nbits (keyparms)); - pk.n = pkey[0]; - pk.e = pkey[1]; - result = mpi_alloc (mpi_get_nlimbs (pk.n)); - public (result, data, &pk); - if ((flags & PUBKEY_FLAG_FIXEDLEN)) + /* Extract the data. */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); + if (rc) + goto leave; + if (DBG_CIPHER) + log_mpidump ("rsa_encrypt data", data); + if (mpi_is_opaque (data)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + + /* Extract the key. */ + rc = _gcry_pk_util_extract_mpis (keyparms, "ne", &pk.n, &pk.e, NULL); + if (rc) + return rc; + if (DBG_CIPHER) + { + log_mpidump ("rsa_encrypt n", pk.n); + log_mpidump ("rsa_encrypt e", pk.e); + } + + /* Do RSA computation and build result. */ + ciph = gcry_mpi_new (0); + public (ciph, data, &pk); + if ((ctx.flags & PUBKEY_FLAG_FIXEDLEN)) { /* We need to make sure to return the correct length to avoid problems with missing leading zeroes. */ unsigned char *em; size_t emlen = (mpi_get_nbits (pk.n)+7)/8; - rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen); + rc = _gcry_mpi_to_octet_string (&em, NULL, ciph, emlen); if (!rc) { - rc = gcry_sexp_build (r_result, NULL, + rc = gcry_sexp_build (r_ciph, NULL, "(enc-val(rsa(a%b)))", (int)emlen, em); gcry_free (em); } } else - rc = gcry_sexp_build (r_result, NULL, "(enc-val(rsa(a%m)))", result); + rc = gcry_sexp_build (r_ciph, NULL, "(enc-val(rsa(a%m)))", ciph); - mpi_free (result); + leave: + gcry_mpi_release (ciph); + gcry_mpi_release (pk.n); + gcry_mpi_release (pk.e); + gcry_mpi_release (data); + _gcry_pk_util_free_encoding_ctx (&ctx); + if (DBG_CIPHER) + log_debug ("rsa_encrypt => %s\n", gpg_strerror (rc)); return rc; } diff --git a/src/cipher-proto.h b/src/cipher-proto.h index 8892ddfe..c570e5ff 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -58,11 +58,9 @@ typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, gcry_mpi_t *skey); /* Type for the pk_encrypt function. */ -typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, - gcry_sexp_t *r_result, - gcry_mpi_t data, - gcry_mpi_t *pkey, - int flags); +typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph, + gcry_sexp_t s_data, + gcry_sexp_t keyparms); /* Type for the pk_decrypt function. */ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, diff --git a/tests/basic.c b/tests/basic.c index 13a8600b..ee049006 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -3486,7 +3486,9 @@ static void check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) { gcry_error_t rc; - gcry_sexp_t plain, ciph, data; + gcry_sexp_t plain = NULL; + gcry_sexp_t ciph = NULL; + gcry_sexp_t data = NULL; int dataidx; static struct { |