summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/dsa.c15
-rw-r--r--cipher/ecc.c101
-rw-r--r--cipher/elgamal.c40
-rw-r--r--cipher/pubkey.c487
-rw-r--r--cipher/rsa.c62
-rw-r--r--mpi/mpicoder.c58
-rw-r--r--src/cipher-proto.h4
-rw-r--r--src/cipher.h1
-rw-r--r--src/mpi.h3
-rw-r--r--tests/t-ed25519.c2
10 files changed, 298 insertions, 475 deletions
diff --git a/cipher/dsa.c b/cipher/dsa.c
index ca9a4f68..13a4fc26 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -974,11 +974,12 @@ dsa_check_secret_key (int algo, gcry_mpi_t *skey)
static gcry_err_code_t
-dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+dsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
int flags, int hashalgo)
{
gcry_err_code_t rc;
DSA_secret_key sk;
+ gcry_mpi_t r, s;
(void)algo;
(void)flags;
@@ -995,9 +996,15 @@ dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
sk.g = skey[2];
sk.y = skey[3];
sk.x = skey[4];
- resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p));
- resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p));
- rc = sign (resarr[0], resarr[1], data, &sk, flags, hashalgo);
+ r = mpi_alloc (mpi_get_nlimbs (sk.p));
+ s = mpi_alloc (mpi_get_nlimbs (sk.p));
+ rc = sign (r, s, data, &sk, flags, hashalgo);
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(sig-val(dsa(r%M)(s%M)))",
+ r, s));
+ mpi_free (r);
+ mpi_free (s);
}
return rc;
}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 66cd342d..b7d62397 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1375,11 +1375,12 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey)
static gcry_err_code_t
-ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+ecc_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
int flags, int hashalgo)
{
- gpg_err_code_t err;
+ gpg_err_code_t rc;
ECC_secret_key sk;
+ gcry_mpi_t r, s;
(void)algo;
@@ -1397,16 +1398,17 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
sk.Q.x = NULL;
sk.Q.y = NULL;
sk.Q.z = NULL;
- err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
- if (err)
+ rc = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
+ if (rc)
{
point_free (&sk.E.G);
- return err;
+ return rc;
}
sk.E.n = skey[4];
- resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
- resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+ r = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+ s = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+
{
const unsigned char *buf;
unsigned int n;
@@ -1415,35 +1417,42 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
buf = gcry_mpi_get_opaque (skey[6], &n);
if (!buf)
- err = GPG_ERR_INV_OBJ;
+ rc = GPG_ERR_INV_OBJ;
else
{
n = (n + 7)/8;
sk.d = NULL;
- err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
- if (!err)
+ rc = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
+ if (!rc)
{
if ((flags & PUBKEY_FLAG_EDDSA))
- err = sign_eddsa (data, &sk, resarr[0], resarr[1],
- hashalgo, skey[5]);
+ {
+ rc = sign_eddsa (data, &sk, r, s, hashalgo, skey[5]);
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build
+ (r_result, NULL,
+ "(sig-val(eddsa(r%M)(s%M)))", r, s));
+ }
else
- err = sign_ecdsa (data, &sk, resarr[0], resarr[1],
- flags, hashalgo);
+ {
+ rc = sign_ecdsa (data, &sk, r, s, flags, hashalgo);
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build
+ (r_result, NULL,
+ "(sig-val(ecdsa(r%M)(s%M)))", r, s));
+ }
gcry_mpi_release (sk.d);
sk.d = NULL;
}
}
}
- if (err)
- {
- mpi_free (resarr[0]);
- mpi_free (resarr[1]);
- resarr[0] = NULL; /* Mark array as released. */
- }
+
+ mpi_free (r);
+ mpi_free (s);
point_free (&sk.E.G);
if (sk.Q.x)
point_free (&sk.Q);
- return err;
+ return rc;
}
@@ -1544,9 +1553,9 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
* ecc_encrypt_raw description:
* input:
* data[0] : private scalar (k)
- * output:
- * result[0] : shared point (kdG)
- * result[1] : generated ephemeral public key (kG)
+ * output: A new S-expression with the parameters:
+ * s : shared point (kdG)
+ * e : generated ephemeral public key (kG)
*
* ecc_decrypt_raw description:
* input:
@@ -1555,13 +1564,13 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
* result[0] : shared point (kdG)
*/
static gcry_err_code_t
-ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
+ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k,
gcry_mpi_t *pkey, int flags)
{
+ gpg_err_code_t rc;
ECC_public_key pk;
mpi_ec_t ctx;
- gcry_mpi_t result[2];
- int err;
+ gcry_mpi_t s, e;
(void)algo;
(void)flags;
@@ -1575,24 +1584,26 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
pk.E.a = pkey[1];
pk.E.b = pkey[2];
point_init (&pk.E.G);
- err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
- if (err)
+ rc = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
+ if (rc)
{
point_free (&pk.E.G);
- return err;
+ return rc;
}
pk.E.n = pkey[4];
point_init (&pk.Q);
- err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
- if (err)
+ rc = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
+ if (rc)
{
point_free (&pk.E.G);
point_free (&pk.Q);
- return err;
+ return rc;
}
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));
/* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
{
@@ -1609,16 +1620,14 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
-
- result[0] = _gcry_ecc_ec2os (x, y, pk.E.p);
+ s = _gcry_ecc_ec2os (x, y, pk.E.p);
/* R = kG */
_gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
-
- result[1] = _gcry_ecc_ec2os (x, y, pk.E.p);
+ e = _gcry_ecc_ec2os (x, y, pk.E.p);
mpi_free (x);
mpi_free (y);
@@ -1630,18 +1639,13 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
point_free (&pk.E.G);
point_free (&pk.Q);
- if (!result[0] || !result[1])
- {
- mpi_free (result[0]);
- mpi_free (result[1]);
- return GPG_ERR_ENOMEM;
- }
-
- /* Success. */
- resarr[0] = result[0];
- resarr[1] = result[1];
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(enc-val(ecdh(s%m)(e%m)))",
+ s, e));
+ mpi_free (s);
+ mpi_free (e);
- return 0;
+ return rc;
}
/* input:
@@ -1991,6 +1995,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
static const char *ecdsa_names[] =
{
"ecdsa",
+ "eddsa",
"ecc",
NULL,
};
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 65448e0a..447d089d 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -705,27 +705,33 @@ elg_check_secret_key (int algo, gcry_mpi_t *skey)
static gcry_err_code_t
-elg_encrypt (int algo, gcry_mpi_t *resarr,
+elg_encrypt (int algo, gcry_sexp_t *r_result,
gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_err_code_t rc;
ELG_public_key pk;
+ gcry_mpi_t a, b;
(void)algo;
(void)flags;
if ((! data) || (! pkey[0]) || (! pkey[1]) || (! pkey[2]))
- err = GPG_ERR_BAD_MPI;
+ rc = GPG_ERR_BAD_MPI;
else
{
pk.p = pkey[0];
pk.g = pkey[1];
pk.y = pkey[2];
- resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.p));
- resarr[1] = mpi_alloc (mpi_get_nlimbs (pk.p));
- do_encrypt (resarr[0], resarr[1], data, &pk);
+ a = mpi_alloc (mpi_get_nlimbs (pk.p));
+ b = mpi_alloc (mpi_get_nlimbs (pk.p));
+ do_encrypt (a, b, data, &pk);
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(enc-val(elg(a%m)(b%m)))",
+ a, b));
+ mpi_free (a);
+ mpi_free (b);
}
- return err;
+ return rc;
}
@@ -756,11 +762,12 @@ elg_decrypt (int algo, gcry_mpi_t *result,
static gcry_err_code_t
-elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+elg_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
int flags, int hashalgo)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_err_code_t rc;
ELG_secret_key sk;
+ gcry_mpi_t r, s;
(void)algo;
(void)flags;
@@ -771,19 +778,24 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
if ((! data)
|| (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
- err = GPG_ERR_BAD_MPI;
+ rc = GPG_ERR_BAD_MPI;
else
{
sk.p = skey[0];
sk.g = skey[1];
sk.y = skey[2];
sk.x = skey[3];
- resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p));
- resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p));
- sign (resarr[0], resarr[1], data, &sk);
+ r = mpi_alloc (mpi_get_nlimbs (sk.p));
+ s = mpi_alloc (mpi_get_nlimbs (sk.p));
+ sign (r, s, data, &sk);
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(sig-val(elg(r%M)(s%M)))",
+ r, s));
+ mpi_free (r);
+ mpi_free (s);
}
- return err;
+ return rc;
}
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index c7557299..dc56cc31 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -33,17 +33,6 @@
#include "pubkey-internal.h"
-static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
- gcry_mpi_t *data, gcry_mpi_t *skey,
- int flags);
-static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
- gcry_mpi_t hash, gcry_mpi_t *skey,
- struct pk_encoding_ctx *ctx);
-static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
- gcry_mpi_t *data, gcry_mpi_t *pkey,
- struct pk_encoding_ctx *ctx);
-
-
/* This is the list of the public-key algorithms included in
Libgcrypt. */
static gcry_pk_spec_t *pubkey_list[] =
@@ -308,161 +297,6 @@ pubkey_check_secret_key (int algo, gcry_mpi_t *skey)
}
-/****************
- * This is the interface to the public key encryption. Encrypt DATA
- * with PKEY and put it into RESARR which should be an array of MPIs
- * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
- * check with pubkey_get_nenc() )
- */
-static gcry_err_code_t
-pubkey_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *pkey, int flags)
-{
- gcry_err_code_t rc;
- gcry_pk_spec_t *spec;
- int i;
-
- /* Note: In fips mode DBG_CIPHER will enver 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", algo);
- for(i = 0; i < pubkey_get_npkey (algo); i++)
- log_mpidump (" pkey", pkey[i]);
- log_mpidump (" data", data);
- }
-
- spec = spec_from_algo (algo);
- if (spec && spec->encrypt)
- rc = spec->encrypt (algo, resarr, data, pkey, flags);
- else if (spec)
- rc = GPG_ERR_NOT_IMPLEMENTED;
- else
- rc = GPG_ERR_PUBKEY_ALGO;
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- {
- for(i = 0; i < pubkey_get_nenc (algo); i++)
- log_mpidump(" encr", resarr[i] );
- }
- return rc;
-}
-
-
-/****************
- * This is the interface to the public key decryption.
- * ALGO gives the algorithm to use and this implicitly determines
- * the size of the arrays.
- * result is a pointer to a mpi variable which will receive a
- * newly allocated mpi or NULL in case of an error.
- */
-static gcry_err_code_t
-pubkey_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags)
-{
- gcry_err_code_t rc;
- gcry_pk_spec_t *spec;
- int i;
-
- *result = NULL; /* So the caller can always do a mpi_free. */
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_decrypt: algo=%d\n", algo);
- for(i = 0; i < pubkey_get_nskey (algo); i++)
- log_mpidump (" skey", skey[i]);
- for(i = 0; i < pubkey_get_nenc (algo); i++)
- log_mpidump (" data", data[i]);
- }
-
- spec = spec_from_algo (algo);
- if (spec && spec->decrypt)
- rc = spec->decrypt (algo, result, data, skey, flags);
- else if (spec)
- rc = GPG_ERR_NOT_IMPLEMENTED;
- else
- rc = GPG_ERR_PUBKEY_ALGO;
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- log_mpidump (" plain", *result);
-
- return rc;
-}
-
-
-/****************
- * This is the interface to the public key signing.
- * Sign data with skey and put the result into resarr which
- * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
- * algorithm allows this - check with pubkey_get_nsig() )
- */
-static gcry_err_code_t
-pubkey_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *skey, struct pk_encoding_ctx *ctx)
-{
- gcry_err_code_t rc;
- gcry_pk_spec_t *spec;
- int i;
-
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_sign: algo=%d\n", algo);
- for(i = 0; i < pubkey_get_nskey (algo); i++)
- log_mpidump (" skey", skey[i]);
- log_mpidump(" data", data );
- }
-
- spec = spec_from_algo (algo);
- if (spec && spec->sign)
- rc = spec->sign (algo, resarr, data, skey, ctx->flags, ctx->hash_algo);
- else if (spec)
- rc = GPG_ERR_NOT_IMPLEMENTED;
- else
- rc = GPG_ERR_PUBKEY_ALGO;
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- for (i = 0; i < pubkey_get_nsig (algo); i++)
- log_mpidump (" sig", resarr[i]);
-
- return rc;
-}
-
-
-/****************
- * Verify a public key signature.
- * Return 0 if the signature is good
- */
-static gcry_err_code_t
-pubkey_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
- gcry_mpi_t *pkey, struct pk_encoding_ctx *ctx)
-{
- gcry_err_code_t rc;
- gcry_pk_spec_t *spec;
- int i;
-
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_verify: algo=%d\n", algo);
- for (i = 0; i < pubkey_get_npkey (algo); i++)
- log_mpidump (" pkey", pkey[i]);
- for (i = 0; i < pubkey_get_nsig (algo); i++)
- log_mpidump (" sig", data[i]);
- log_mpidump (" hash", hash);
- }
-
- spec = spec_from_algo (algo);
- if (spec && spec->verify)
- rc = spec->verify (algo, hash, data, pkey,
- ctx->verify_cmp, ctx, ctx->flags, ctx->hash_algo);
- else if (spec)
- rc = GPG_ERR_NOT_IMPLEMENTED;
- else
- rc = GPG_ERR_PUBKEY_ALGO;
-
- return rc;
-}
-
-
/* Turn VALUE into an octet string and store it in an allocated buffer
at R_FRAME or - if R_RAME is NULL - copy it into the caller
provided buffer SPACE; either SPACE or R_FRAME may be used. If
@@ -474,50 +308,7 @@ static gpg_err_code_t
octet_string_from_mpi (unsigned char **r_frame, void *space,
gcry_mpi_t value, size_t nbytes)
{
- gpg_err_code_t rc;
- size_t nframe, noff, n;
- unsigned char *frame;
-
- if (!r_frame == !space)
- return GPG_ERR_INV_ARG; /* Only one may be used. */
-
- if (r_frame)
- *r_frame = NULL;
-
- rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
- NULL, 0, &nframe, value));
- if (rc)
- return rc;
- if (nframe > nbytes)
- return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */
-
- noff = (nframe < nbytes)? nbytes - nframe : 0;
- n = nframe + noff;
- if (space)
- frame = space;
- else
- {
- frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n);
- if (!frame)
- {
- rc = gpg_err_code_from_syserror ();
- return rc;
- }
- }
- if (noff)
- memset (frame, 0, noff);
- nframe += noff;
- rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
- frame+noff, nframe-noff, NULL, value));
- if (rc)
- {
- gcry_free (frame);
- return rc;
- }
-
- if (r_frame)
- *r_frame = frame;
- return 0;
+ return _gcry_mpi_to_octet_string (r_frame, space, value, nbytes);
}
@@ -2210,13 +2001,22 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
}
else if ( n == 5 && !memcmp (s, "pkcs1", 5)
&& ctx->encoding == PUBKEY_ENC_UNKNOWN)
- ctx->encoding = PUBKEY_ENC_PKCS1;
+ {
+ ctx->encoding = PUBKEY_ENC_PKCS1;
+ parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+ }
else if ( n == 4 && !memcmp (s, "oaep", 4)
&& ctx->encoding == PUBKEY_ENC_UNKNOWN)
- ctx->encoding = PUBKEY_ENC_OAEP;
+ {
+ ctx->encoding = PUBKEY_ENC_OAEP;
+ parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+ }
else if ( n == 3 && !memcmp (s, "pss", 3)
&& ctx->encoding == PUBKEY_ENC_UNKNOWN)
- ctx->encoding = PUBKEY_ENC_PSS;
+ {
+ ctx->encoding = PUBKEY_ENC_PSS;
+ parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+ }
else if (n == 11 && ! memcmp (s, "no-blinding", 11))
parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
else
@@ -2646,11 +2446,12 @@ init_encoding_ctx (struct pk_encoding_ctx *ctx, enum pk_operation op,
gcry_error_t
gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
{
- gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
- const char *algo_name, *algo_elems;
- struct pk_encoding_ctx ctx;
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;
*r_ciph = NULL;
@@ -2661,116 +2462,43 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
gcry_assert (spec);
- /* If aliases for the algorithm name exists, take the first one
- instead of the regular name to adhere to SPKI conventions. We
- assume that the first alias name is the lowercase version of the
- regular one. This change is required for compatibility with
- 1.1.12 generated S-expressions. */
- algo_name = spec->aliases? *spec->aliases : NULL;
- if (!algo_name || !*algo_name)
- algo_name = spec->name;
-
- algo_elems = spec->elements_enc;
-
/* Get the stuff we want to encrypt. */
init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey));
rc = sexp_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
- /* Now we can encrypt DATA to CIPH. */
- ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
- if (!ciph)
+ /* 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 ())
{
- rc = gpg_err_code_from_syserror ();
- goto leave;
+ 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);
}
- rc = pubkey_encrypt (spec->algo, ciph, data, pkey, ctx.flags);
- mpi_free (data);
- data = NULL;
- if (rc)
- goto leave;
- /* We did it. Now build the return list */
- if (ctx.encoding == PUBKEY_ENC_OAEP
- || ctx.encoding == PUBKEY_ENC_PKCS1)
- {
- /* We need to make sure to return the correct length to avoid
- problems with missing leading zeroes. We know that this
- encoding does only make sense with RSA thus we don't need to
- build the S-expression on the fly. */
- unsigned char *em;
- size_t emlen = (ctx.nbits+7)/8;
-
- rc = octet_string_from_mpi (&em, NULL, ciph[0], emlen);
- if (rc)
- goto leave;
- rc = gcry_err_code (gcry_sexp_build (r_ciph, NULL,
- "(enc-val(%s(a%b)))",
- algo_name, (int)emlen, em));
- gcry_free (em);
- if (rc)
- goto leave;
- }
+ if (spec->encrypt)
+ rc = spec->encrypt (spec->algo, r_ciph, data, pkey, ctx.flags);
else
- {
- char *string, *p;
- int i;
- size_t nelem = strlen (algo_elems);
- size_t needed = 19 + strlen (algo_name) + (nelem * 5);
- void **arg_list;
-
- /* Build the string. */
- string = p = gcry_malloc (needed);
- if (!string)
- {
- rc = gpg_err_code_from_syserror ();
- goto leave;
- }
- p = stpcpy ( p, "(enc-val(" );
- p = stpcpy ( p, algo_name );
- for (i=0; algo_elems[i]; i++ )
- {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy ( p, "%m)" );
- }
- strcpy ( p, "))" );
-
- /* And now the ugly part: We don't have a function to pass an
- * array to a format string, so we have to do it this way :-(. */
- /* FIXME: There is now such a format specifier, so we can
- change the code to be more clear. */
- arg_list = malloc (nelem * sizeof *arg_list);
- if (!arg_list)
- {
- rc = gpg_err_code_from_syserror ();
- goto leave;
- }
+ rc = GPG_ERR_NOT_IMPLEMENTED;
- for (i = 0; i < nelem; i++)
- arg_list[i] = ciph + i;
- rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
- free (arg_list);
- if (rc)
- BUG ();
- gcry_free (string);
- }
+ /* 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);
}
- if (ciph)
- {
- release_mpi_array (ciph);
- gcry_free (ciph);
- }
-
gcry_free (ctx.label);
return gcry_error (rc);
@@ -2814,16 +2542,17 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
gcry_mpi_t plain = NULL;
unsigned char *unpad = NULL;
size_t unpadlen = 0;
+ int i;
int modern, flags;
struct pk_encoding_ctx ctx;
+ gcry_pk_spec_t *spec = NULL;
gcry_pk_spec_t *spec_enc = NULL;
- gcry_pk_spec_t *spec_key = NULL;
*r_plain = NULL;
ctx.label = NULL;
rc = sexp_to_key (s_skey, 1, GCRY_PK_USAGE_ENCR, NULL,
- &skey, &spec_key, NULL);
+ &skey, &spec, NULL);
if (rc)
goto leave;
@@ -2832,16 +2561,31 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
if (rc)
goto leave;
- if (spec_key->algo != spec_enc->algo)
+ if (spec->algo != spec_enc->algo)
{
rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */
goto leave;
}
- rc = pubkey_decrypt (spec_key->algo, &plain, data, skey, flags);
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("gcry_pk_decrypt: algo=%d\n", spec->algo);
+ for(i = 0; i < pubkey_get_nskey (spec->algo); i++)
+ log_mpidump (" skey", skey[i]);
+ for(i = 0; i < pubkey_get_nenc (spec->algo); i++)
+ log_mpidump (" data", data[i]);
+ }
+
+ if (spec->decrypt)
+ rc = spec->decrypt (spec->algo, &plain, data, skey, flags);
+ else
+ rc = GPG_ERR_NOT_IMPLEMENTED;
if (rc)
goto leave;
+ if (DBG_CIPHER && !fips_mode ())
+ log_mpidump (" plain", plain);
+
/* Do un-padding if necessary. */
switch (ctx.encoding)
{
@@ -2931,9 +2675,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
{
gcry_mpi_t *skey = NULL;
gcry_mpi_t hash = NULL;
- gcry_mpi_t *result = NULL;
gcry_pk_spec_t *spec = NULL;
- const char *algo_name, *algo_elems;
struct pk_encoding_ctx ctx;
int i;
int is_ecc;
@@ -2947,11 +2689,6 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
goto leave;
gcry_assert (spec);
- algo_name = spec->aliases? *spec->aliases : NULL;
- if (!algo_name || !*algo_name)
- algo_name = spec->name;
-
- algo_elems = spec->elements_sig;
/* Get the stuff we want to sign. Note that pk_get_nbits does also
work on a private key. We don't need the number of bits for ECC
@@ -2962,81 +2699,26 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
if (rc)
goto leave;
- result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
- if (!result)
+ if (DBG_CIPHER && !fips_mode ())
{
- rc = gpg_err_code_from_syserror ();
- goto leave;
+ log_debug ("gcry_pk_sign: algo=%d\n", spec->algo);
+ for(i = 0; i < pubkey_get_nskey (spec->algo); i++)
+ log_mpidump (" skey", skey[i]);
+ log_mpidump(" data", hash);
}
- rc = pubkey_sign (spec->algo, result, hash, skey, &ctx);
- if (rc)
- goto leave;
- if (ctx.encoding == PUBKEY_ENC_PSS
- || ctx.encoding == PUBKEY_ENC_PKCS1)
- {
- /* We need to make sure to return the correct length to avoid
- problems with missing leading zeroes. We know that this
- encoding does only make sense with RSA thus we don't need to
- build the S-expression on the fly. */
- unsigned char *em;
- size_t emlen = (ctx.nbits+7)/8;
-
- rc = octet_string_from_mpi (&em, NULL, result[0], emlen);
- if (rc)
- goto leave;
- rc = gcry_err_code (gcry_sexp_build (r_sig, NULL,
- "(sig-val(%s(s%b)))",
- algo_name, (int)emlen, em));
- gcry_free (em);
- if (rc)
- goto leave;
- }
+ if (spec->sign)
+ rc = spec->sign (spec->algo, r_sig, hash, skey, ctx.flags, ctx.hash_algo);
else
- {
- /* General purpose output encoding. Do it on the fly. */
- char *string, *p;
- size_t nelem, needed = strlen (algo_name) + 20;
- void **arg_list;
-
- nelem = strlen (algo_elems);
-
- /* Count elements, so that we can allocate enough space. */
- needed += 10 * nelem;
-
- /* Build the string. */
- string = p = gcry_malloc (needed);
- if (!string)
- {
- rc = gpg_err_code_from_syserror ();
- goto leave;
- }
- p = stpcpy (p, "(sig-val(");
- p = stpcpy (p, algo_name);
- for (i = 0; algo_elems[i]; i++)
- {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy (p, "%M)");
- }
- strcpy (p, "))");
-
- arg_list = malloc (nelem * sizeof *arg_list);
- if (!arg_list)
- {
- rc = gpg_err_code_from_syserror ();
- goto leave;
- }
+ rc = GPG_ERR_NOT_IMPLEMENTED;
- for (i = 0; i < nelem; i++)
- arg_list[i] = result + i;
+ if (rc)
+ goto leave;
- rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
- free (arg_list);
- if (rc)
- BUG ();
- gcry_free (string);
- }
+ /* Fixme: To print the result we need to print an sexp. */
+ /* if (!rc && DBG_CIPHER && !fips_mode ()) */
+ /* for (i = 0; i < pubkey_get_nsig (algo); i++) */
+ /* log_mpidump (" sig", resarr[i]); */
leave:
if (skey)
@@ -3054,14 +2736,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
gcry_free (skey);
}
- if (hash)
- mpi_free (hash);
-
- if (result)
- {
- release_mpi_array (result);
- gcry_free (result);
- }
+ mpi_free (hash);
return gcry_error (rc);
}
@@ -3078,15 +2753,16 @@ gcry_error_t
gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
{
gcry_err_code_t rc;
- gcry_pk_spec_t *spec_key = NULL;
+ gcry_pk_spec_t *spec = NULL;
gcry_pk_spec_t *spec_sig = NULL;
gcry_mpi_t *pkey = NULL;
gcry_mpi_t hash = NULL;
gcry_mpi_t *sig = NULL;
struct pk_encoding_ctx ctx;
+ int i;
rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_SIGN, NULL,
- &pkey, &spec_key, NULL);
+ &pkey, &spec, NULL);
if (rc)
goto leave;
@@ -3104,13 +2780,28 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
/* Fixme: Check that the algorithm of S_SIG is compatible to the one
of S_PKEY. */
- if (spec_key->algo != spec_sig->algo)
+ if (spec->algo != spec_sig->algo)
{
rc = GPG_ERR_CONFLICT;
goto leave;
}
- rc = pubkey_verify (spec_key->algo, hash, sig, pkey, &ctx);
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("gcry_pk_verify: algo=%d\n", spec->algo);
+ for (i = 0; i < pubkey_get_npkey (spec->algo); i++)
+ log_mpidump (" pkey", pkey[i]);
+ for (i = 0; i < pubkey_get_nsig (spec->algo); i++)
+ log_mpidump (" sig", sig[i]);
+ log_mpidump (" hash", hash);
+ }
+
+ if (spec->verify)
+ rc = spec->verify (spec->algo, hash, sig, pkey,
+ ctx.verify_cmp, &ctx, ctx.flags, ctx.hash_algo);
+ else
+ rc = GPG_ERR_NOT_IMPLEMENTED;
+
leave:
if (pkey)
diff --git a/cipher/rsa.c b/cipher/rsa.c
index e495cd85..91349db1 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -893,20 +893,43 @@ rsa_check_secret_key (int algo, gcry_mpi_t *skey)
static gcry_err_code_t
-rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data,
gcry_mpi_t *pkey, int flags)
{
+ gpg_err_code_t rc;
RSA_public_key pk;
+ gcry_mpi_t result;
(void)algo;
(void)flags;
pk.n = pkey[0];
pk.e = pkey[1];
- resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n));
- public (resarr[0], data, &pk);
+ result = mpi_alloc (mpi_get_nlimbs (pk.n));
+ public (result, data, &pk);
+ if ((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;
- return GPG_ERR_NO_ERROR;
+ rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen);
+ if (!rc)
+ {
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(enc-val(rsa(a%b)))",
+ (int)emlen, em));
+ gcry_free (em);
+ }
+ }
+ else
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(enc-val(rsa(a%m)))",
+ result));
+
+ mpi_free (result);
+ return rc;
}
@@ -993,10 +1016,12 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
static gcry_err_code_t
-rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+rsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
int flags, int hashalgo)
{
+ gpg_err_code_t rc;
RSA_secret_key sk;
+ gcry_mpi_t result;
(void)algo;
(void)flags;
@@ -1011,10 +1036,31 @@ rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
sk.p = skey[3];
sk.q = skey[4];
sk.u = skey[5];
- resarr[0] = mpi_alloc( mpi_get_nlimbs (sk.n));
- secret (resarr[0], data, &sk);
+ result = mpi_alloc (mpi_get_nlimbs (sk.n));
+ secret (result, data, &sk);
+ if ((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 (sk.n)+7)/8;
- return GPG_ERR_NO_ERROR;
+ rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen);
+ if (!rc)
+ {
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(sig-val(rsa(s%b)))",
+ (int)emlen, em));
+ gcry_free (em);
+ }
+ }
+ else
+ rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+ "(sig-val(rsa(s%M)))",
+ result));
+ mpi_free (result);
+
+ return rc;
}
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index 07e91c63..1d2c87e0 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -836,3 +836,61 @@ gcry_mpi_aprint (enum gcry_mpi_format format,
*nwritten = n;
return rc;
}
+
+
+/* Turn VALUE into an octet string and store it in an allocated buffer
+ at R_FRAME or - if R_RAME is NULL - copy it into the caller
+ provided buffer SPACE; either SPACE or R_FRAME may be used. If
+ SPACE if not NULL, the caller must provide a buffer of at least
+ NBYTES. If the resulting octet string is shorter than NBYTES pad
+ it to the left with zeroes. If VALUE does not fit into NBYTES
+ return an error code. */
+gpg_err_code_t
+_gcry_mpi_to_octet_string (unsigned char **r_frame, void *space,
+ gcry_mpi_t value, size_t nbytes)
+{
+ gpg_err_code_t rc;
+ size_t nframe, noff, n;
+ unsigned char *frame;
+
+ if (!r_frame == !space)
+ return GPG_ERR_INV_ARG; /* Only one may be used. */
+
+ if (r_frame)
+ *r_frame = NULL;
+
+ rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
+ NULL, 0, &nframe, value));
+ if (rc)
+ return rc;
+ if (nframe > nbytes)
+ return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */
+
+ noff = (nframe < nbytes)? nbytes - nframe : 0;
+ n = nframe + noff;
+ if (space)
+ frame = space;
+ else
+ {
+ frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n);
+ if (!frame)
+ {
+ rc = gpg_err_code_from_syserror ();
+ return rc;
+ }
+ }
+ if (noff)
+ memset (frame, 0, noff);
+ nframe += noff;
+ rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
+ frame+noff, nframe-noff, NULL, value));
+ if (rc)
+ {
+ gcry_free (frame);
+ return rc;
+ }
+
+ if (r_frame)
+ *r_frame = frame;
+ return 0;
+}
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index a641a079..121d9f57 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -68,7 +68,7 @@ typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
/* Type for the pk_encrypt function. */
typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo,
- gcry_mpi_t *resarr,
+ gcry_sexp_t *r_result,
gcry_mpi_t data,
gcry_mpi_t *pkey,
int flags);
@@ -82,7 +82,7 @@ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo,
/* Type for the pk_sign function. */
typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo,
- gcry_mpi_t *resarr,
+ gcry_sexp_t *r_result,
gcry_mpi_t data,
gcry_mpi_t *skey,
int flags,
diff --git a/src/cipher.h b/src/cipher.h
index 8d3afbfa..dde24ceb 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -29,6 +29,7 @@
#define PUBKEY_FLAG_NO_BLINDING (1 << 0)
#define PUBKEY_FLAG_RFC6979 (1 << 1)
#define PUBKEY_FLAG_EDDSA (1 << 2)
+#define PUBKEY_FLAG_FIXEDLEN (1 << 3)
enum pk_operation
{
diff --git a/src/mpi.h b/src/mpi.h
index f24e9681..34669517 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -167,6 +167,9 @@ byte *_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
unsigned *r_nbytes, int *sign);
void _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer,
unsigned int nbytes, int sign );
+gpg_err_code_t _gcry_mpi_to_octet_string (unsigned char **r_frame,
+ void *space,
+ gcry_mpi_t value, size_t nbytes);
/*-- mpi-add.c --*/
#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c
index e1139136..baa6a7ad 100644
--- a/tests/t-ed25519.c
+++ b/tests/t-ed25519.c
@@ -326,7 +326,7 @@ one_test (int testno, const char *sk, const char *pk,
if (s_tmp)
{
s_tmp2 = s_tmp;
- s_tmp = gcry_sexp_find_token (s_tmp2, "ecdsa", 0);
+ s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0);
if (s_tmp)
{
gcry_sexp_release (s_tmp2);