summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/ecc.c48
-rw-r--r--cipher/elgamal.c63
-rw-r--r--cipher/pubkey.c58
-rw-r--r--cipher/rsa.c145
-rw-r--r--src/cipher-proto.h8
-rw-r--r--src/cipher.h1
-rw-r--r--tests/basic.c13
7 files changed, 179 insertions, 157 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 9a9c21b9..cf054f83 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1661,20 +1661,24 @@ ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k,
* see ecc_encrypt_raw for details.
*/
static gcry_err_code_t
-ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags)
+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)
{
+ gpg_err_code_t rc;
ECC_secret_key sk;
mpi_point_struct R; /* Result that we return. */
mpi_point_struct kG;
mpi_ec_t ctx;
gcry_mpi_t r;
- int err;
(void)algo;
(void)flags;
-
- *result = NULL;
+ (void)encoding;
+ (void)hash_algo;
+ (void)label;
+ (void)labellen;
if (!data || !data[0]
|| !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
@@ -1682,11 +1686,11 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
return GPG_ERR_BAD_MPI;
point_init (&kG);
- err = _gcry_ecc_os2ec (&kG, data[0]);
- if (err)
+ rc = _gcry_ecc_os2ec (&kG, data[0]);
+ if (rc)
{
point_free (&kG);
- return err;
+ return rc;
}
sk.E.model = MPI_EC_WEIERSTRASS;
@@ -1694,22 +1698,22 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
sk.E.a = skey[1];
sk.E.b = skey[2];
point_init (&sk.E.G);
- err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
- if (err)
+ rc = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
+ if (rc)
{
point_free (&kG);
point_free (&sk.E.G);
- return err;
+ return rc;
}
sk.E.n = skey[4];
point_init (&sk.Q);
- err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
- if (err)
+ rc = _gcry_ecc_os2ec (&sk.Q, skey[5]);
+ if (rc)
{
point_free (&kG);
point_free (&sk.E.G);
point_free (&sk.Q);
- return err;
+ return rc;
}
sk.d = skey[6];
@@ -1733,6 +1737,10 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
log_fatal ("ecdh: Failed to get affine coordinates\n");
r = _gcry_ecc_ec2os (x, y, sk.E.p);
+ if (!r)
+ rc = gpg_err_code_from_syserror ();
+ else
+ rc = 0;
mpi_free (x);
mpi_free (y);
}
@@ -1743,14 +1751,10 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
point_free (&sk.E.G);
point_free (&sk.Q);
- if (!r)
- return GPG_ERR_ENOMEM;
-
- /* Success. */
-
- *result = r;
-
- return 0;
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %m)", r));
+ mpi_free (r);
+ return rc;
}
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index c2a953bd..ecbac756 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -30,6 +30,8 @@
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
+#include "pubkey-internal.h"
+
typedef struct
{
@@ -777,28 +779,73 @@ elg_encrypt (int algo, gcry_sexp_t *r_result,
static gcry_err_code_t
-elg_decrypt (int algo, gcry_mpi_t *result,
- gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
+elg_decrypt (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)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_err_code_t rc;
ELG_secret_key sk;
+ gcry_mpi_t plain;
(void)algo;
- (void)flags;
if ((! data[0]) || (! data[1])
|| (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
- err = GPG_ERR_BAD_MPI;
+ rc = GPG_ERR_BAD_MPI;
else
{
+ unsigned char *unpad = NULL;
+ size_t unpadlen = 0;
+ unsigned int nbits;
+
sk.p = skey[0];
sk.g = skey[1];
sk.y = skey[2];
sk.x = skey[3];
- *result = mpi_alloc_secure (mpi_get_nlimbs (sk.p));
- decrypt (*result, data[0], data[1], &sk);
+
+ nbits = gcry_mpi_get_nbits (sk.p);
+
+ plain = mpi_snew (nbits);
+ decrypt (plain, data[0], data[1], &sk);
+
+ /* Reverse the encoding and build the s-expression. */
+ switch (encoding)
+ {
+ case PUBKEY_ENC_PKCS1:
+ rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad));
+ break;
+
+ case PUBKEY_ENC_OAEP:
+ rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
+ nbits, hash_algo, plain, label, labellen);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad));
+ break;
+
+ default:
+ /* Raw format. For backward compatibility we need to assume a
+ signed mpi by using the sexp format string "%m". */
+ rc = gcry_err_code
+ (gcry_sexp_build (r_plain, NULL,
+ (flags & PUBKEY_FLAG_LEGACYRESULT)
+ ? "%m" : "(value %m)",
+ plain));
+ break;
+ }
+
+ gcry_free (unpad);
+ mpi_free (plain);
}
- return err;
+ return rc;
}
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 7085b25f..99b9ba8a 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -714,7 +714,7 @@ get_hash_algo (const char *s, size_t n)
*/
static gcry_err_code_t
sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec,
- int *ret_modern, int *flags, struct pk_encoding_ctx *ctx)
+ int *flags, struct pk_encoding_ctx *ctx)
{
gcry_err_code_t err = 0;
gcry_sexp_t list = NULL;
@@ -726,8 +726,6 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec,
const char *elems;
gcry_mpi_t *array = NULL;
- *ret_modern = 0;
-
/* Check that the first element is valid. */
list = gcry_sexp_find_token (sexp, "enc-val" , 0);
if (!list)
@@ -757,7 +755,6 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec,
const char *s;
int i;
- *ret_modern = 1;
for (i = gcry_sexp_length (l2) - 1; i > 0; i--)
{
s = gcry_sexp_nth_data (l2, i, &n);
@@ -863,6 +860,8 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec,
list = l2;
l2 = NULL;
}
+ else
+ parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;
spec = spec_from_name (name);
if (!spec)
@@ -1533,11 +1532,8 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
gcry_err_code_t rc;
gcry_mpi_t *skey = NULL;
gcry_mpi_t *data = NULL;
- gcry_mpi_t plain = NULL;
- unsigned char *unpad = NULL;
- size_t unpadlen = 0;
int i;
- int modern, flags;
+ int flags;
struct pk_encoding_ctx ctx;
gcry_pk_spec_t *spec = NULL;
gcry_pk_spec_t *spec_enc = NULL;
@@ -1551,7 +1547,7 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
goto leave;
init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, gcry_pk_get_nbits (s_skey));
- rc = sexp_to_enc (s_data, &data, &spec_enc, &modern, &flags, &ctx);
+ rc = sexp_to_enc (s_data, &data, &spec_enc, &flags, &ctx);
if (rc)
goto leave;
@@ -1571,59 +1567,25 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
}
if (spec->decrypt)
- rc = spec->decrypt (spec->algo, &plain, data, skey, flags);
+ rc = spec->decrypt (spec->algo, r_plain, data, skey, flags,
+ ctx.encoding, ctx.hash_algo,
+ ctx.label, ctx.labellen);
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)
- {
- case PUBKEY_ENC_PKCS1:
- rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen,
- gcry_pk_get_nbits (s_skey),
- plain);
- mpi_free (plain);
- plain = NULL;
- if (!rc)
- rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
- (int)unpadlen, unpad));
- break;
-
- case PUBKEY_ENC_OAEP:
- rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
- gcry_pk_get_nbits (s_skey), ctx.hash_algo,
- plain, ctx.label, ctx.labellen);
- mpi_free (plain);
- plain = NULL;
- if (!rc)
- rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
- (int)unpadlen, unpad));
- break;
+ /* if (DBG_CIPHER && !fips_mode ()) */
+ /* log_mpidump (" plain", plain); */
- default:
- /* Raw format. For backward compatibility we need to assume a
- signed mpi by using the sexp format string "%m". */
- rc = gcry_err_code (gcry_sexp_build
- (r_plain, NULL, modern? "(value %m)" : "%m", plain));
- break;
- }
leave:
- gcry_free (unpad);
-
if (skey)
{
release_mpi_array (skey);
gcry_free (skey);
}
- mpi_free (plain);
-
if (data)
{
release_mpi_array (data);
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 5754e438..71052711 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -32,6 +32,7 @@
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
+#include "pubkey-internal.h"
typedef struct
@@ -737,47 +738,6 @@ secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
-/* Perform RSA blinding. */
-static gcry_mpi_t
-rsa_blind (gcry_mpi_t x, gcry_mpi_t r, gcry_mpi_t e, gcry_mpi_t n)
-{
- /* A helper. */
- gcry_mpi_t a;
-
- /* Result. */
- gcry_mpi_t y;
-
- a = gcry_mpi_snew (gcry_mpi_get_nbits (n));
- y = gcry_mpi_snew (gcry_mpi_get_nbits (n));
-
- /* Now we calculate: y = (x * r^e) mod n, where r is the random
- number, e is the public exponent, x is the non-blinded data and n
- is the RSA modulus. */
- gcry_mpi_powm (a, r, e, n);
- gcry_mpi_mulm (y, a, x, n);
-
- gcry_mpi_release (a);
-
- return y;
-}
-
-/* Undo RSA blinding. */
-static gcry_mpi_t
-rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n)
-{
- gcry_mpi_t y;
-
- y = gcry_mpi_snew (gcry_mpi_get_nbits (n));
-
- /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded
- decrypted data, ri is the modular multiplicative inverse of r and
- n is the RSA modulus. */
-
- gcry_mpi_mulm (y, ri, x, n);
-
- return y;
-}
-
/*********************************************
************** interface ******************
*********************************************/
@@ -926,15 +886,18 @@ rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data,
static gcry_err_code_t
-rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags)
+rsa_decrypt (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)
+
{
+ gpg_err_code_t rc;
RSA_secret_key sk;
- gcry_mpi_t r = MPI_NULL; /* Random number needed for blinding. */
- gcry_mpi_t ri = MPI_NULL; /* Modular multiplicative inverse of
- r. */
- gcry_mpi_t x = MPI_NULL; /* Data to decrypt. */
- gcry_mpi_t y; /* Result. */
+ gcry_mpi_t plain; /* Decrypted data. */
+ unsigned char *unpad = NULL;
+ size_t unpadlen = 0;
+ unsigned int nbits;
(void)algo;
@@ -946,24 +909,29 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
sk.q = skey[4]; /* Optional. */
sk.u = skey[5]; /* Optional. */
- y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
+ nbits = gcry_mpi_get_nbits (sk.n);
+
+ plain = gcry_mpi_snew (nbits);
/* We use blinding by default to mitigate timing attacks which can
be practically mounted over the network as shown by Brumley and
Boney in 2003. */
if (! (flags & PUBKEY_FLAG_NO_BLINDING))
{
- /* Initialize blinding. */
+ gcry_mpi_t r; /* Random number needed for blinding. */
+ gcry_mpi_t ri; /* Modular multiplicative inverse of r. */
+ gcry_mpi_t ciph; /* Blinded data to decrypt. */
/* First, we need a random number r between 0 and n - 1, which
is relatively prime to n (i.e. it is neither p nor q). The
random number needs to be only unpredictable, thus we employ
the gcry_create_nonce function by using GCRY_WEAK_RANDOM with
gcry_mpi_randomize. */
- r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
- ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
+ r = gcry_mpi_snew (nbits);
+ ri = gcry_mpi_snew (nbits);
+ ciph = gcry_mpi_snew (nbits);
- gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), GCRY_WEAK_RANDOM);
+ gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM);
gcry_mpi_mod (r, r, sk.n);
/* Calculate inverse of r. It practically impossible that the
@@ -971,39 +939,64 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
allocated resources. */
if (!gcry_mpi_invm (ri, r, sk.n))
return GPG_ERR_INTERNAL;
- }
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
- x = rsa_blind (data[0], r, sk.e, sk.n);
- else
- x = data[0];
-
- /* Do the encryption. */
- secret (y, x, &sk);
+ /* Do blinding. We calculate: y = (x * r^e) mod n, where r is
+ the random number, e is the public exponent, x is the
+ non-blinded data and n is the RSA modulus. */
+ gcry_mpi_powm (ciph, r, sk.e, sk.n);
+ gcry_mpi_mulm (ciph, ciph, data[0], sk.n);
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
- {
- /* Undo blinding. */
- gcry_mpi_t a = gcry_mpi_copy (y);
+ /* Perform decryption. */
+ secret (plain, ciph, &sk);
- gcry_mpi_release (y);
- y = rsa_unblind (a, ri, sk.n);
+ /* Undo blinding. Here we calculate: y = (x * r^-1) mod n,
+ where x is the blinded decrypted data, ri is the modular
+ multiplicative inverse of r and n is the RSA modulus. */
+ gcry_mpi_mulm (plain, plain, ri, sk.n);
- gcry_mpi_release (a);
+ gcry_mpi_release (ciph);
+ gcry_mpi_release (r);
+ gcry_mpi_release (ri);
}
+ else
+ secret (plain, data[0], &sk);
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
+ /* Reverse the encoding and build the s-expression. */
+ switch (encoding)
{
- /* Deallocate resources needed for blinding. */
- gcry_mpi_release (x);
- gcry_mpi_release (r);
- gcry_mpi_release (ri);
+ case PUBKEY_ENC_PKCS1:
+ rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad));
+ break;
+
+ case PUBKEY_ENC_OAEP:
+ rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
+ nbits, hash_algo, plain, label, labellen);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)",
+ (int)unpadlen, unpad));
+ break;
+
+ default:
+ /* Raw format. For backward compatibility we need to assume a
+ signed mpi by using the sexp format string "%m". */
+ rc = gcry_err_code
+ (gcry_sexp_build (r_plain, NULL,
+ (flags & PUBKEY_FLAG_LEGACYRESULT)? "%m":"(value %m)",
+ plain));
+ break;
}
- /* Copy out result. */
- *result = y;
+ gcry_free (unpad);
+ mpi_free (plain);
- return GPG_ERR_NO_ERROR;
+ return rc;
}
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 1285fe85..212857b8 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -67,10 +67,14 @@ typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo,
/* Type for the pk_decrypt function. */
typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo,
- gcry_mpi_t *result,
+ gcry_sexp_t *r_result,
gcry_mpi_t *data,
gcry_mpi_t *skey,
- int flags);
+ int flags,
+ enum pk_encoding encoding,
+ int hash_algo,
+ unsigned char *label,
+ size_t labellen);
/* Type for the pk_sign function. */
typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo,
diff --git a/src/cipher.h b/src/cipher.h
index 9fe30a66..e3a2fe0c 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -30,6 +30,7 @@
#define PUBKEY_FLAG_RFC6979 (1 << 1)
#define PUBKEY_FLAG_EDDSA (1 << 2)
#define PUBKEY_FLAG_FIXEDLEN (1 << 3)
+#define PUBKEY_FLAG_LEGACYRESULT (1 << 4)
enum pk_operation
{
diff --git a/tests/basic.c b/tests/basic.c
index 14ceea4e..e9709d5c 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -3654,7 +3654,18 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
}
rc = gcry_pk_decrypt (&plain, ciph, skey);
if (gcry_err_code (rc) != datas[dataidx].decrypt_expected_rc)
- fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (rc));
+ {
+ if (verbose)
+ {
+ show_sexp (" data:\n", data);
+ show_sexp (" ciph:\n", ciph);
+ show_sexp (" key:\n", skey);
+ }
+ fail ("gcry_pk_decrypt failed: expected %d (%s), got %d (%s)\n",
+ datas[dataidx].decrypt_expected_rc,
+ gpg_strerror (datas[dataidx].decrypt_expected_rc),
+ rc, gpg_strerror (rc));
+ }
if (!rc && datas[dataidx].unpadded)
{