summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/Libgcrypt/cipher/rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/rsa.c')
-rw-r--r--plugins/MirOTR/Libgcrypt/cipher/rsa.c1045
1 files changed, 637 insertions, 408 deletions
diff --git a/plugins/MirOTR/Libgcrypt/cipher/rsa.c b/plugins/MirOTR/Libgcrypt/cipher/rsa.c
index cf278c2532..9a8d235b9a 100644
--- a/plugins/MirOTR/Libgcrypt/cipher/rsa.c
+++ b/plugins/MirOTR/Libgcrypt/cipher/rsa.c
@@ -32,6 +32,7 @@
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
+#include "pubkey-internal.h"
typedef struct
@@ -52,6 +53,15 @@ typedef struct
} RSA_secret_key;
+static const char *rsa_names[] =
+ {
+ "rsa",
+ "openpgp-rsa",
+ "oid.1.2.840.113549.1.1.1",
+ NULL,
+ };
+
+
/* A sample 1024 bit RSA key used for the selftests. */
static const char sample_secret_key[] =
"(private-key"
@@ -72,7 +82,7 @@ static const char sample_secret_key[] =
" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))";
/* A sample 1024 bit RSA key used for the selftests (public only). */
-static const char sample_public_key[] =
+static const char sample_public_key[] =
"(public-key"
" (rsa"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
@@ -88,6 +98,7 @@ static int test_keys (RSA_secret_key *sk, unsigned nbits);
static int check_secret_key (RSA_secret_key *sk);
static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey);
static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey);
+static unsigned int rsa_get_nbits (gcry_sexp_t parms);
/* Check that a freshly generated key actually works. Returns 0 on success. */
@@ -96,56 +107,56 @@ test_keys (RSA_secret_key *sk, unsigned int nbits)
{
int result = -1; /* Default to failure. */
RSA_public_key pk;
- gcry_mpi_t plaintext = gcry_mpi_new (nbits);
- gcry_mpi_t ciphertext = gcry_mpi_new (nbits);
- gcry_mpi_t decr_plaintext = gcry_mpi_new (nbits);
- gcry_mpi_t signature = gcry_mpi_new (nbits);
+ gcry_mpi_t plaintext = mpi_new (nbits);
+ gcry_mpi_t ciphertext = mpi_new (nbits);
+ gcry_mpi_t decr_plaintext = mpi_new (nbits);
+ gcry_mpi_t signature = mpi_new (nbits);
/* Put the relevant parameters into a public key structure. */
pk.n = sk->n;
pk.e = sk->e;
/* Create a random plaintext. */
- gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
+ _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
/* Encrypt using the public key. */
public (ciphertext, plaintext, &pk);
/* Check that the cipher text does not match the plaintext. */
- if (!gcry_mpi_cmp (ciphertext, plaintext))
+ if (!mpi_cmp (ciphertext, plaintext))
goto leave; /* Ciphertext is identical to the plaintext. */
/* Decrypt using the secret key. */
secret (decr_plaintext, ciphertext, sk);
/* Check that the decrypted plaintext matches the original plaintext. */
- if (gcry_mpi_cmp (decr_plaintext, plaintext))
+ if (mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Plaintext does not match. */
/* Create another random plaintext as data for signature checking. */
- gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
+ _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
/* Use the RSA secret function to create a signature of the plaintext. */
secret (signature, plaintext, sk);
-
+
/* Use the RSA public function to verify this signature. */
public (decr_plaintext, signature, &pk);
- if (gcry_mpi_cmp (decr_plaintext, plaintext))
+ if (mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Signature does not match. */
/* Modify the signature and check that the signing fails. */
- gcry_mpi_add_ui (signature, signature, 1);
+ mpi_add_ui (signature, signature, 1);
public (decr_plaintext, signature, &pk);
- if (!gcry_mpi_cmp (decr_plaintext, plaintext))
+ if (!mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Signature matches but should not. */
result = 0; /* All tests succeeded. */
leave:
- gcry_mpi_release (signature);
- gcry_mpi_release (decr_plaintext);
- gcry_mpi_release (ciphertext);
- gcry_mpi_release (plaintext);
+ _gcry_mpi_release (signature);
+ _gcry_mpi_release (decr_plaintext);
+ _gcry_mpi_release (ciphertext);
+ _gcry_mpi_release (plaintext);
return result;
}
@@ -158,22 +169,22 @@ check_exponent (void *arg, gcry_mpi_t a)
gcry_mpi_t e = arg;
gcry_mpi_t tmp;
int result;
-
+
mpi_sub_ui (a, a, 1);
tmp = _gcry_mpi_alloc_like (a);
- result = !gcry_mpi_gcd(tmp, e, a); /* GCD is not 1. */
- gcry_mpi_release (tmp);
+ result = !mpi_gcd(tmp, e, a); /* GCD is not 1. */
+ _gcry_mpi_release (tmp);
mpi_add_ui (a, a, 1);
return result;
}
/****************
- * Generate a key pair with a key of size NBITS.
+ * Generate a key pair with a key of size NBITS.
* USE_E = 0 let Libcgrypt decide what exponent to use.
- * = 1 request the use of a "secure" exponent; this is required by some
+ * = 1 request the use of a "secure" exponent; this is required by some
* specification to be 65537.
* > 2 Use this public exponent. If the given exponent
- * is not odd one is internally added to it.
+ * is not odd one is internally added to it.
* TRANSIENT_KEY: If true, generate the primes using the standard RNG.
* Returns: 2 structures filled with all needed values
*/
@@ -205,7 +216,7 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
/* Make sure that nbits is even so that we generate p, q of equal size. */
if ( (nbits&1) )
- nbits++;
+ nbits++;
if (use_e == 1) /* Alias for a secure value */
use_e = 65537; /* as demanded by Sphinx. */
@@ -213,7 +224,7 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
/* Public exponent:
In general we use 41 as this is quite fast and more secure than the
commonly used 17. Benchmarking the RSA verify function
- with a 1024 bit key yields (2001-11-08):
+ with a 1024 bit key yields (2001-11-08):
e=17 0.54 ms
e=41 0.75 ms
e=257 0.95 ms
@@ -222,22 +233,22 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
if (!use_e)
mpi_set_ui (e, 41); /* This is a reasonable secure and fast value */
- else
+ else
{
use_e |= 1; /* make sure this is odd */
- mpi_set_ui (e, use_e);
+ mpi_set_ui (e, use_e);
}
-
- n = gcry_mpi_new (nbits);
+
+ n = mpi_new (nbits);
p = q = NULL;
do
{
/* select two (very secret) primes */
if (p)
- gcry_mpi_release (p);
+ _gcry_mpi_release (p);
if (q)
- gcry_mpi_release (q);
+ _gcry_mpi_release (q);
if (use_e)
{ /* Do an extra test to ensure that the given exponent is
suitable. */
@@ -261,16 +272,16 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
/* calculate Euler totient: phi = (p-1)(q-1) */
t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
- phi = gcry_mpi_snew ( nbits );
- g = gcry_mpi_snew ( nbits );
- f = gcry_mpi_snew ( nbits );
+ phi = mpi_snew ( nbits );
+ g = mpi_snew ( nbits );
+ f = mpi_snew ( nbits );
mpi_sub_ui( t1, p, 1 );
mpi_sub_ui( t2, q, 1 );
mpi_mul( phi, t1, t2 );
- gcry_mpi_gcd(g, t1, t2);
+ mpi_gcd (g, t1, t2);
mpi_fdiv_q(f, phi, g);
- while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
+ while (!mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
{
if (use_e)
BUG (); /* The prime generator already made sure that we
@@ -279,10 +290,10 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
}
/* calculate the secret key d = e^1 mod phi */
- d = gcry_mpi_snew ( nbits );
- mpi_invm(d, e, f );
+ d = mpi_snew ( nbits );
+ mpi_invm (d, e, f );
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
- u = gcry_mpi_snew ( nbits );
+ u = mpi_snew ( nbits );
mpi_invm(u, p, q );
if( DBG_CIPHER )
@@ -298,11 +309,11 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
log_mpidump(" u= ", u );
}
- gcry_mpi_release (t1);
- gcry_mpi_release (t2);
- gcry_mpi_release (phi);
- gcry_mpi_release (f);
- gcry_mpi_release (g);
+ _gcry_mpi_release (t1);
+ _gcry_mpi_release (t2);
+ _gcry_mpi_release (phi);
+ _gcry_mpi_release (f);
+ _gcry_mpi_release (g);
sk->n = n;
sk->e = e;
@@ -314,12 +325,12 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
/* Now we can test our keys. */
if (test_keys (sk, nbits - 64))
{
- gcry_mpi_release (sk->n); sk->n = NULL;
- gcry_mpi_release (sk->e); sk->e = NULL;
- gcry_mpi_release (sk->p); sk->p = NULL;
- gcry_mpi_release (sk->q); sk->q = NULL;
- gcry_mpi_release (sk->d); sk->d = NULL;
- gcry_mpi_release (sk->u); sk->u = NULL;
+ _gcry_mpi_release (sk->n); sk->n = NULL;
+ _gcry_mpi_release (sk->e); sk->e = NULL;
+ _gcry_mpi_release (sk->p); sk->p = NULL;
+ _gcry_mpi_release (sk->q); sk->q = NULL;
+ _gcry_mpi_release (sk->d); sk->d = NULL;
+ _gcry_mpi_release (sk->u); sk->u = NULL;
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
@@ -329,14 +340,14 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
/* Helper for generate_x931. */
-static gcry_mpi_t
+static gcry_mpi_t
gen_x931_parm_xp (unsigned int nbits)
{
gcry_mpi_t xp;
- xp = gcry_mpi_snew (nbits);
- gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM);
-
+ xp = mpi_snew (nbits);
+ _gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM);
+
/* The requirement for Xp is:
sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1
@@ -347,24 +358,24 @@ gen_x931_parm_xp (unsigned int nbits)
mpi_set_highbit (xp, nbits-1);
mpi_set_bit (xp, nbits-2);
gcry_assert ( mpi_get_nbits (xp) == nbits );
-
+
return xp;
-}
+}
/* Helper for generate_x931. */
-static gcry_mpi_t
+static gcry_mpi_t
gen_x931_parm_xi (void)
{
gcry_mpi_t xi;
- xi = gcry_mpi_snew (101);
- gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM);
+ xi = mpi_snew (101);
+ _gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM);
mpi_set_highbit (xi, 100);
gcry_assert ( mpi_get_nbits (xi) == 101 );
-
+
return xi;
-}
+}
@@ -389,19 +400,19 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
*swapped = 0;
if (e_value == 1) /* Alias for a secure value. */
- e_value = 65537;
+ e_value = 65537;
/* Point 1 of section 4.1: k = 1024 + 256s with S >= 0 */
if (nbits < 1024 || (nbits % 256))
return GPG_ERR_INV_VALUE;
-
+
/* Point 2: 2 <= bitlength(e) < 2^{k-2}
Note that we do not need to check the upper bound because we use
an unsigned long for E and thus there is no way for E to reach
that limit. */
if (e_value < 3)
return GPG_ERR_INV_VALUE;
-
+
/* Our implementaion requires E to be odd. */
if (!(e_value & 1))
return GPG_ERR_INV_VALUE;
@@ -425,15 +436,15 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
/* Not given: Generate them. */
xp = gen_x931_parm_xp (nbits/2);
/* Make sure that |xp - xq| > 2^{nbits - 100} holds. */
- tmpval = gcry_mpi_snew (nbits/2);
+ tmpval = mpi_snew (nbits/2);
do
{
- gcry_mpi_release (xq);
+ _gcry_mpi_release (xq);
xq = gen_x931_parm_xp (nbits/2);
mpi_sub (tmpval, xp, xq);
}
while (mpi_get_nbits (tmpval) <= (nbits/2 - 100));
- gcry_mpi_release (tmpval);
+ _gcry_mpi_release (tmpval);
xp1 = gen_x931_parm_xi ();
xp2 = gen_x931_parm_xi ();
@@ -444,26 +455,35 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
else
{
/* Parameters to derive the key are given. */
+ /* Note that we explicitly need to setup the values of tbl
+ because some compilers (e.g. OpenWatcom, IRIX) don't allow
+ to initialize a structure with automatic variables. */
struct { const char *name; gcry_mpi_t *value; } tbl[] = {
- { "Xp1", &xp1 },
- { "Xp2", &xp2 },
- { "Xp", &xp },
- { "Xq1", &xq1 },
- { "Xq2", &xq2 },
- { "Xq", &xq },
- { NULL, NULL }
+ { "Xp1" },
+ { "Xp2" },
+ { "Xp" },
+ { "Xq1" },
+ { "Xq2" },
+ { "Xq" },
+ { NULL }
};
int idx;
gcry_sexp_t oneparm;
-
+
+ tbl[0].value = &xp1;
+ tbl[1].value = &xp2;
+ tbl[2].value = &xp;
+ tbl[3].value = &xq1;
+ tbl[4].value = &xq2;
+ tbl[5].value = &xq;
+
for (idx=0; tbl[idx].name; idx++)
{
- oneparm = gcry_sexp_find_token (deriveparms, tbl[idx].name, 0);
+ oneparm = sexp_find_token (deriveparms, tbl[idx].name, 0);
if (oneparm)
{
- *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1,
- GCRYMPI_FMT_USG);
- gcry_sexp_release (oneparm);
+ *tbl[idx].value = sexp_nth_mpi (oneparm, 1, GCRYMPI_FMT_USG);
+ sexp_release (oneparm);
}
}
for (idx=0; tbl[idx].name; idx++)
@@ -473,27 +493,27 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
{
/* At least one parameter is missing. */
for (idx=0; tbl[idx].name; idx++)
- gcry_mpi_release (*tbl[idx].value);
+ _gcry_mpi_release (*tbl[idx].value);
return GPG_ERR_MISSING_VALUE;
}
}
-
- e = mpi_alloc_set_ui (e_value);
+
+ e = mpi_alloc_set_ui (e_value);
/* Find two prime numbers. */
p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL);
q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL);
- gcry_mpi_release (xp); xp = NULL;
- gcry_mpi_release (xp1); xp1 = NULL;
- gcry_mpi_release (xp2); xp2 = NULL;
- gcry_mpi_release (xq); xq = NULL;
- gcry_mpi_release (xq1); xq1 = NULL;
- gcry_mpi_release (xq2); xq2 = NULL;
+ _gcry_mpi_release (xp); xp = NULL;
+ _gcry_mpi_release (xp1); xp1 = NULL;
+ _gcry_mpi_release (xp2); xp2 = NULL;
+ _gcry_mpi_release (xq); xq = NULL;
+ _gcry_mpi_release (xq1); xq1 = NULL;
+ _gcry_mpi_release (xq2); xq2 = NULL;
if (!p || !q)
{
- gcry_mpi_release (p);
- gcry_mpi_release (q);
- gcry_mpi_release (e);
+ _gcry_mpi_release (p);
+ _gcry_mpi_release (q);
+ _gcry_mpi_release (e);
return GPG_ERR_NO_PRIME;
}
}
@@ -506,26 +526,26 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
mpi_swap (p, q);
*swapped = 1;
}
- n = gcry_mpi_new (nbits);
+ n = mpi_new (nbits);
mpi_mul (n, p, q);
/* Compute the Euler totient: phi = (p-1)(q-1) */
- pm1 = gcry_mpi_snew (nbits/2);
- qm1 = gcry_mpi_snew (nbits/2);
- phi = gcry_mpi_snew (nbits);
+ pm1 = mpi_snew (nbits/2);
+ qm1 = mpi_snew (nbits/2);
+ phi = mpi_snew (nbits);
mpi_sub_ui (pm1, p, 1);
mpi_sub_ui (qm1, q, 1);
mpi_mul (phi, pm1, qm1);
- g = gcry_mpi_snew (nbits);
- gcry_assert (gcry_mpi_gcd (g, e, phi));
+ g = mpi_snew (nbits);
+ gcry_assert (mpi_gcd (g, e, phi));
/* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
- gcry_mpi_gcd (g, pm1, qm1);
+ mpi_gcd (g, pm1, qm1);
f = pm1; pm1 = NULL;
- gcry_mpi_release (qm1); qm1 = NULL;
+ _gcry_mpi_release (qm1); qm1 = NULL;
mpi_fdiv_q (f, phi, g);
- gcry_mpi_release (phi); phi = NULL;
+ _gcry_mpi_release (phi); phi = NULL;
d = g; g = NULL;
/* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */
mpi_invm (d, e, f);
@@ -557,12 +577,12 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
/* Now we can test our keys. */
if (test_keys (sk, nbits - 64))
{
- gcry_mpi_release (sk->n); sk->n = NULL;
- gcry_mpi_release (sk->e); sk->e = NULL;
- gcry_mpi_release (sk->p); sk->p = NULL;
- gcry_mpi_release (sk->q); sk->q = NULL;
- gcry_mpi_release (sk->d); sk->d = NULL;
- gcry_mpi_release (sk->u); sk->u = NULL;
+ _gcry_mpi_release (sk->n); sk->n = NULL;
+ _gcry_mpi_release (sk->e); sk->e = NULL;
+ _gcry_mpi_release (sk->p); sk->p = NULL;
+ _gcry_mpi_release (sk->q); sk->q = NULL;
+ _gcry_mpi_release (sk->d); sk->d = NULL;
+ _gcry_mpi_release (sk->u); sk->u = NULL;
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
@@ -572,7 +592,7 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
/****************
- * Test wether the secret key is valid.
+ * Test whether the secret key is valid.
* Returns: true if this is a valid key.
*/
static int
@@ -580,7 +600,7 @@ check_secret_key( RSA_secret_key *sk )
{
int rc;
gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
-
+
mpi_mul(temp, sk->p, sk->q );
rc = mpi_cmp( temp, sk->n );
mpi_free(temp);
@@ -652,7 +672,7 @@ stronger_key_check ( RSA_secret_key *skey )
{
log_info ( "RSA Oops: d is wrong - fixed\n");
mpi_set (skey->d, t);
- _gcry_log_mpidump (" fixed d", skey->d);
+ log_printmpi (" fixed d", skey->d);
}
/* check for correctness of u */
@@ -661,7 +681,7 @@ stronger_key_check ( RSA_secret_key *skey )
{
log_info ( "RSA Oops: u is wrong - fixed\n");
mpi_set (skey->u, t);
- _gcry_log_mpidump (" fixed u", skey->u);
+ log_printmpi (" fixed u", skey->u);
}
log_info ( "RSA secret key check finished\n");
@@ -682,16 +702,19 @@ stronger_key_check ( RSA_secret_key *skey )
*
* Or faster:
*
- * m1 = c ^ (d mod (p-1)) mod p
- * m2 = c ^ (d mod (q-1)) mod q
- * h = u * (m2 - m1) mod q
+ * m1 = c ^ (d mod (p-1)) mod p
+ * m2 = c ^ (d mod (q-1)) mod q
+ * h = u * (m2 - m1) mod q
* m = m1 + h * p
*
* Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY.
*/
static void
-secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
+secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
{
+ /* Remove superfluous leading zeroes from INPUT. */
+ mpi_normalize (input);
+
if (!skey->p || !skey->q || !skey->u)
{
mpi_powm (output, input, skey->d, skey->n);
@@ -701,10 +724,10 @@ secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
gcry_mpi_t m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
gcry_mpi_t m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
gcry_mpi_t h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
-
+
/* m1 = c ^ (d mod (p-1)) mod p */
mpi_sub_ui( h, skey->p, 1 );
- mpi_fdiv_r( h, skey->d, h );
+ mpi_fdiv_r( h, skey->d, h );
mpi_powm( m1, input, h, skey->p );
/* m2 = c ^ (d mod (q-1)) mod q */
mpi_sub_ui( h, skey->q, 1 );
@@ -712,13 +735,13 @@ secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
mpi_powm( m2, input, h, skey->q );
/* h = u * ( m2 - m1 ) mod q */
mpi_sub( h, m2, m1 );
- if ( mpi_is_neg( h ) )
+ if ( mpi_has_sign ( h ) )
mpi_add ( h, h, skey->q );
- mpi_mulm( h, skey->u, h, skey->q );
+ mpi_mulm( h, skey->u, h, skey->q );
/* m = m2 + h * p */
mpi_mul ( h, h, skey->p );
mpi_add ( output, m1, h );
-
+
mpi_free ( h );
mpi_free ( m1 );
mpi_free ( m2 );
@@ -727,319 +750,540 @@ 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 ******************
*********************************************/
static gcry_err_code_t
-rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
- const gcry_sexp_t genparms,
- gcry_mpi_t *skey, gcry_mpi_t **retfactors,
- gcry_sexp_t *r_extrainfo)
+rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
{
- RSA_secret_key sk;
gpg_err_code_t ec;
+ unsigned int nbits;
+ unsigned long evalue;
+ RSA_secret_key sk;
gcry_sexp_t deriveparms;
- int transient_key = 0;
- int use_x931 = 0;
+ int flags = 0;
gcry_sexp_t l1;
+ gcry_sexp_t swap_info = NULL;
+
+ memset (&sk, 0, sizeof sk);
+
+ ec = _gcry_pk_util_get_nbits (genparms, &nbits);
+ if (ec)
+ return ec;
+
+ ec = _gcry_pk_util_get_rsa_use_e (genparms, &evalue);
+ if (ec)
+ return ec;
- (void)algo;
-
- *retfactors = NULL; /* We don't return them. */
+ /* Parse the optional flags list. */
+ l1 = sexp_find_token (genparms, "flags", 0);
+ if (l1)
+ {
+ ec = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
+ sexp_release (l1);
+ if (ec)
+ return ec;
+ }
deriveparms = (genparms?
- gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
+ sexp_find_token (genparms, "derive-parms", 0) : NULL);
if (!deriveparms)
{
/* Parse the optional "use-x931" flag. */
- l1 = gcry_sexp_find_token (genparms, "use-x931", 0);
+ l1 = sexp_find_token (genparms, "use-x931", 0);
if (l1)
{
- use_x931 = 1;
- gcry_sexp_release (l1);
+ flags |= PUBKEY_FLAG_USE_X931;
+ sexp_release (l1);
}
}
- if (deriveparms || use_x931 || fips_mode ())
+ if (deriveparms || (flags & PUBKEY_FLAG_USE_X931) || fips_mode ())
{
int swapped;
ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
- gcry_sexp_release (deriveparms);
- if (!ec && r_extrainfo && swapped)
- {
- ec = gcry_sexp_new (r_extrainfo,
- "(misc-key-info(p-q-swapped))", 0, 1);
- if (ec)
- {
- gcry_mpi_release (sk.n); sk.n = NULL;
- gcry_mpi_release (sk.e); sk.e = NULL;
- gcry_mpi_release (sk.p); sk.p = NULL;
- gcry_mpi_release (sk.q); sk.q = NULL;
- gcry_mpi_release (sk.d); sk.d = NULL;
- gcry_mpi_release (sk.u); sk.u = NULL;
- }
- }
+ sexp_release (deriveparms);
+ if (!ec && swapped)
+ ec = sexp_new (&swap_info, "(misc-key-info(p-q-swapped))", 0, 1);
}
else
{
/* Parse the optional "transient-key" flag. */
- l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
- if (l1)
+ if (!(flags & PUBKEY_FLAG_TRANSIENT_KEY))
{
- transient_key = 1;
- gcry_sexp_release (l1);
+ l1 = sexp_find_token (genparms, "transient-key", 0);
+ if (l1)
+ {
+ flags |= PUBKEY_FLAG_TRANSIENT_KEY;
+ sexp_release (l1);
+ }
}
/* Generate. */
- ec = generate_std (&sk, nbits, evalue, transient_key);
+ ec = generate_std (&sk, nbits, evalue,
+ !!(flags & PUBKEY_FLAG_TRANSIENT_KEY));
}
if (!ec)
{
- skey[0] = sk.n;
- skey[1] = sk.e;
- skey[2] = sk.d;
- skey[3] = sk.p;
- skey[4] = sk.q;
- skey[5] = sk.u;
+ ec = sexp_build (r_skey, NULL,
+ "(key-data"
+ " (public-key"
+ " (rsa(n%m)(e%m)))"
+ " (private-key"
+ " (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"
+ " %S)",
+ sk.n, sk.e,
+ sk.n, sk.e, sk.d, sk.p, sk.q, sk.u,
+ swap_info);
}
-
- return ec;
-}
+ mpi_free (sk.n);
+ mpi_free (sk.e);
+ mpi_free (sk.p);
+ mpi_free (sk.q);
+ mpi_free (sk.d);
+ mpi_free (sk.u);
+ sexp_release (swap_info);
-static gcry_err_code_t
-rsa_generate (int algo, unsigned int nbits, unsigned long evalue,
- gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
- return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors, NULL);
+ return ec;
}
static gcry_err_code_t
-rsa_check_secret_key (int algo, gcry_mpi_t *skey)
+rsa_check_secret_key (gcry_sexp_t keyparms)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- RSA_secret_key sk;
-
- (void)algo;
+ gcry_err_code_t rc;
+ RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
- sk.n = skey[0];
- sk.e = skey[1];
- sk.d = skey[2];
- sk.p = skey[3];
- sk.q = skey[4];
- sk.u = skey[5];
+ /* To check the key we need the optional parameters. */
+ rc = sexp_extract_param (keyparms, NULL, "nedpqu",
+ &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+ NULL);
+ if (rc)
+ goto leave;
- if (!sk.p || !sk.q || !sk.u)
- err = GPG_ERR_NO_OBJ; /* To check the key we need the optional
- parameters. */
- else if (!check_secret_key (&sk))
- err = GPG_ERR_PUBKEY_ALGO;
+ if (!check_secret_key (&sk))
+ rc = GPG_ERR_BAD_SECKEY;
- return err;
+ leave:
+ _gcry_mpi_release (sk.n);
+ _gcry_mpi_release (sk.e);
+ _gcry_mpi_release (sk.d);
+ _gcry_mpi_release (sk.p);
+ _gcry_mpi_release (sk.q);
+ _gcry_mpi_release (sk.u);
+ if (DBG_CIPHER)
+ log_debug ("rsa_testkey => %s\n", gpg_strerror (rc));
+ return rc;
}
static gcry_err_code_t
-rsa_encrypt (int algo, gcry_mpi_t *resarr, 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)
{
- RSA_public_key pk;
+ 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;
+
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
+ rsa_get_nbits (keyparms));
+
+ /* 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 = sexp_extract_param (keyparms, NULL, "ne", &pk.n, &pk.e, NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ {
+ log_mpidump ("rsa_encrypt n", pk.n);
+ log_mpidump ("rsa_encrypt e", pk.e);
+ }
+
+ /* Do RSA computation and build result. */
+ ciph = mpi_new (0);
+ public (ciph, data, &pk);
+ if (DBG_CIPHER)
+ log_mpidump ("rsa_encrypt res", ciph);
+ 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;
- (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);
-
- return GPG_ERR_NO_ERROR;
+ rc = _gcry_mpi_to_octet_string (&em, NULL, ciph, emlen);
+ if (!rc)
+ {
+ rc = sexp_build (r_ciph, NULL, "(enc-val(rsa(a%b)))", (int)emlen, em);
+ xfree (em);
+ }
+ }
+ else
+ rc = sexp_build (r_ciph, NULL, "(enc-val(rsa(a%m)))", ciph);
+
+ 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;
}
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 (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
+
{
- 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. */
+ gpg_err_code_t rc;
+ struct pk_encoding_ctx ctx;
+ gcry_sexp_t l1 = NULL;
+ gcry_mpi_t data = NULL;
+ RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
+ gcry_mpi_t plain = NULL;
+ gcry_mpi_t r = NULL; /* Random number needed for blinding. */
+ gcry_mpi_t ri = NULL; /* Modular multiplicative inverse of r. */
+ gcry_mpi_t bldata = NULL;/* Blinded data to decrypt. */
+ unsigned char *unpad = NULL;
+ size_t unpadlen = 0;
+
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
+ rsa_get_nbits (keyparms));
+
+ /* Extract the data. */
+ rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx);
+ if (rc)
+ goto leave;
+ rc = sexp_extract_param (l1, NULL, "a", &data, NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_decrypt data", data);
+ if (mpi_is_opaque (data))
+ {
+ rc = GPG_ERR_INV_DATA;
+ goto leave;
+ }
- (void)algo;
+ /* Extract the key. */
+ rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?",
+ &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+ NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ {
+ log_printmpi ("rsa_decrypt n", sk.n);
+ log_printmpi ("rsa_decrypt e", sk.e);
+ if (!fips_mode ())
+ {
+ log_printmpi ("rsa_decrypt d", sk.d);
+ log_printmpi ("rsa_decrypt p", sk.p);
+ log_printmpi ("rsa_decrypt q", sk.q);
+ log_printmpi ("rsa_decrypt u", sk.u);
+ }
+ }
- /* Extract private key. */
- sk.n = skey[0];
- sk.e = skey[1];
- sk.d = skey[2];
- sk.p = skey[3]; /* Optional. */
- sk.q = skey[4]; /* Optional. */
- sk.u = skey[5]; /* Optional. */
+ /* Better make sure that there are no superfluous leading zeroes in
+ the input and it has not been "padded" using multiples of N.
+ This mitigates side-channel attacks (CVE-2013-4576). */
+ mpi_normalize (data);
+ mpi_fdiv_r (data, data, sk.n);
- y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
+ /* Allocate MPI for the plaintext. */
+ plain = mpi_snew (ctx.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))
+ Boney in 2003. */
+ if (!(ctx.flags & PUBKEY_FLAG_NO_BLINDING))
{
- /* Initialize blinding. */
-
/* 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));
-
- gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), GCRY_WEAK_RANDOM);
- gcry_mpi_mod (r, r, sk.n);
-
- /* Calculate inverse of r. It practically impossible that the
- follwing test fails, thus we do not add code to release
- allocated resources. */
- if (!gcry_mpi_invm (ri, r, sk.n))
- return GPG_ERR_INTERNAL;
- }
+ r = mpi_snew (ctx.nbits);
+ ri = mpi_snew (ctx.nbits);
+ bldata = mpi_snew (ctx.nbits);
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
- x = rsa_blind (data[0], r, sk.e, sk.n);
- else
- x = data[0];
+ do
+ {
+ _gcry_mpi_randomize (r, ctx.nbits, GCRY_WEAK_RANDOM);
+ mpi_mod (r, r, sk.n);
+ }
+ while (!mpi_invm (ri, r, sk.n));
- /* 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. */
+ mpi_powm (bldata, r, sk.e, sk.n);
+ mpi_mulm (bldata, bldata, data, sk.n);
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
- {
- /* Undo blinding. */
- gcry_mpi_t a = gcry_mpi_copy (y);
-
- gcry_mpi_release (y);
- y = rsa_unblind (a, ri, sk.n);
+ /* Perform decryption. */
+ secret (plain, bldata, &sk);
+ _gcry_mpi_release (bldata); bldata = NULL;
- gcry_mpi_release (a);
+ /* 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. */
+ mpi_mulm (plain, plain, ri, sk.n);
+
+ _gcry_mpi_release (r); r = NULL;
+ _gcry_mpi_release (ri); ri = NULL;
}
+ else
+ secret (plain, data, &sk);
- if (! (flags & PUBKEY_FLAG_NO_BLINDING))
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_decrypt res", plain);
+
+ /* Reverse the encoding and build the s-expression. */
+ switch (ctx.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, ctx.nbits, plain);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
+ break;
+
+ case PUBKEY_ENC_OAEP:
+ rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
+ ctx.nbits, ctx.hash_algo,
+ plain, ctx.label, ctx.labellen);
+ mpi_free (plain);
+ plain = NULL;
+ if (!rc)
+ rc = 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 = sexp_build (r_plain, NULL,
+ (ctx.flags & PUBKEY_FLAG_LEGACYRESULT)
+ ? "%m":"(value %m)", plain);
+ break;
}
- /* Copy out result. */
- *result = y;
-
- return GPG_ERR_NO_ERROR;
+ leave:
+ xfree (unpad);
+ _gcry_mpi_release (plain);
+ _gcry_mpi_release (sk.n);
+ _gcry_mpi_release (sk.e);
+ _gcry_mpi_release (sk.d);
+ _gcry_mpi_release (sk.p);
+ _gcry_mpi_release (sk.q);
+ _gcry_mpi_release (sk.u);
+ _gcry_mpi_release (data);
+ _gcry_mpi_release (r);
+ _gcry_mpi_release (ri);
+ _gcry_mpi_release (bldata);
+ sexp_release (l1);
+ _gcry_pk_util_free_encoding_ctx (&ctx);
+ if (DBG_CIPHER)
+ log_debug ("rsa_decrypt => %s\n", gpg_strerror (rc));
+ return rc;
}
static gcry_err_code_t
-rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
+rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
- RSA_secret_key sk;
+ gpg_err_code_t rc;
+ struct pk_encoding_ctx ctx;
+ gcry_mpi_t data = NULL;
+ RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
+ gcry_mpi_t sig = NULL;
+
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
+ rsa_get_nbits (keyparms));
+
+ /* Extract the data. */
+ rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_sign data", data);
+ if (mpi_is_opaque (data))
+ {
+ rc = GPG_ERR_INV_DATA;
+ goto leave;
+ }
+
+ /* Extract the key. */
+ rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?",
+ &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+ NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ {
+ log_printmpi ("rsa_sign n", sk.n);
+ log_printmpi ("rsa_sign e", sk.e);
+ if (!fips_mode ())
+ {
+ log_printmpi ("rsa_sign d", sk.d);
+ log_printmpi ("rsa_sign p", sk.p);
+ log_printmpi ("rsa_sign q", sk.q);
+ log_printmpi ("rsa_sign u", sk.u);
+ }
+ }
+
+ /* Do RSA computation and build the result. */
+ sig = mpi_new (0);
+ secret (sig, data, &sk);
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_sign res", sig);
+ 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 (sk.n)+7)/8;
- (void)algo;
-
- sk.n = skey[0];
- sk.e = skey[1];
- sk.d = skey[2];
- 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);
-
- return GPG_ERR_NO_ERROR;
+ rc = _gcry_mpi_to_octet_string (&em, NULL, sig, emlen);
+ if (!rc)
+ {
+ rc = sexp_build (r_sig, NULL, "(sig-val(rsa(s%b)))", (int)emlen, em);
+ xfree (em);
+ }
+ }
+ else
+ rc = sexp_build (r_sig, NULL, "(sig-val(rsa(s%M)))", sig);
+
+
+ leave:
+ _gcry_mpi_release (sig);
+ _gcry_mpi_release (sk.n);
+ _gcry_mpi_release (sk.e);
+ _gcry_mpi_release (sk.d);
+ _gcry_mpi_release (sk.p);
+ _gcry_mpi_release (sk.q);
+ _gcry_mpi_release (sk.u);
+ _gcry_mpi_release (data);
+ _gcry_pk_util_free_encoding_ctx (&ctx);
+ if (DBG_CIPHER)
+ log_debug ("rsa_sign => %s\n", gpg_strerror (rc));
+ return rc;
}
static gcry_err_code_t
-rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
- int (*cmp) (void *opaque, gcry_mpi_t tmp),
- void *opaquev)
+rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
- RSA_public_key pk;
- gcry_mpi_t result;
gcry_err_code_t rc;
+ struct pk_encoding_ctx ctx;
+ gcry_sexp_t l1 = NULL;
+ gcry_mpi_t sig = NULL;
+ gcry_mpi_t data = NULL;
+ RSA_public_key pk = { NULL, NULL };
+ gcry_mpi_t result = NULL;
+
+ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
+ rsa_get_nbits (keyparms));
+
+ /* Extract the data. */
+ rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_verify data", data);
+ if (mpi_is_opaque (data))
+ {
+ rc = GPG_ERR_INV_DATA;
+ goto leave;
+ }
- (void)algo;
- (void)cmp;
- (void)opaquev;
+ /* Extract the signature value. */
+ rc = _gcry_pk_util_preparse_sigval (s_sig, rsa_names, &l1, NULL);
+ if (rc)
+ goto leave;
+ rc = sexp_extract_param (l1, NULL, "s", &sig, NULL);
+ if (rc)
+ goto leave;
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_verify sig", sig);
- pk.n = pkey[0];
- pk.e = pkey[1];
- result = gcry_mpi_new ( 160 );
- public( result, data[0], &pk );
-#ifdef IS_DEVELOPMENT_VERSION
+ /* Extract the key. */
+ rc = sexp_extract_param (keyparms, NULL, "ne", &pk.n, &pk.e, NULL);
+ if (rc)
+ goto leave;
if (DBG_CIPHER)
{
- log_mpidump ("rsa verify result:", result );
- log_mpidump (" hash:", hash );
+ log_printmpi ("rsa_verify n", pk.n);
+ log_printmpi ("rsa_verify e", pk.e);
}
-#endif /*IS_DEVELOPMENT_VERSION*/
- /*rc = (*cmp)( opaquev, result );*/
- rc = mpi_cmp (result, hash) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR;
- gcry_mpi_release (result);
-
+
+ /* Do RSA computation and compare. */
+ result = mpi_new (0);
+ public (result, sig, &pk);
+ if (DBG_CIPHER)
+ log_printmpi ("rsa_verify cmp", result);
+ if (ctx.verify_cmp)
+ rc = ctx.verify_cmp (&ctx, result);
+ else
+ rc = mpi_cmp (result, data) ? GPG_ERR_BAD_SIGNATURE : 0;
+
+ leave:
+ _gcry_mpi_release (result);
+ _gcry_mpi_release (pk.n);
+ _gcry_mpi_release (pk.e);
+ _gcry_mpi_release (data);
+ _gcry_mpi_release (sig);
+ sexp_release (l1);
+ _gcry_pk_util_free_encoding_ctx (&ctx);
+ if (DBG_CIPHER)
+ log_debug ("rsa_verify => %s\n", rc?gpg_strerror (rc):"Good");
return rc;
}
+
+/* Return the number of bits for the key described by PARMS. On error
+ * 0 is returned. The format of PARMS starts with the algorithm name;
+ * for example:
+ *
+ * (rsa
+ * (n <mpi>)
+ * (e <mpi>))
+ *
+ * More parameters may be given but we only need N here.
+ */
static unsigned int
-rsa_get_nbits (int algo, gcry_mpi_t *pkey)
+rsa_get_nbits (gcry_sexp_t parms)
{
- (void)algo;
+ gcry_sexp_t l1;
+ gcry_mpi_t n;
+ unsigned int nbits;
+
+ l1 = sexp_find_token (parms, "n", 1);
+ if (!l1)
+ return 0; /* Parameter N not found. */
- return mpi_get_nbits (pkey[0]);
+ n = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+ sexp_release (l1);
+ nbits = n? mpi_get_nbits (n) : 0;
+ _gcry_mpi_release (n);
+ return nbits;
}
@@ -1051,9 +1295,9 @@ rsa_get_nbits (int algo, gcry_mpi_t *pkey)
(rsa
(n #00B...#)
(e #010001#))
-
+
PKCS-15 says that for RSA only the modulus should be hashed -
- however, it is not clear wether this is meant to use the raw bytes
+ however, it is not clear whether this is meant to use the raw bytes
(assuming this is an unsigned integer) or whether the DER required
0 should be prefixed. We hash the raw bytes. */
static gpg_err_code_t
@@ -1063,19 +1307,19 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
const char *data;
size_t datalen;
- l1 = gcry_sexp_find_token (keyparam, "n", 1);
+ l1 = sexp_find_token (keyparam, "n", 1);
if (!l1)
return GPG_ERR_NO_OBJ;
- data = gcry_sexp_nth_data (l1, 1, &datalen);
+ data = sexp_nth_data (l1, 1, &datalen);
if (!data)
{
- gcry_sexp_release (l1);
+ sexp_release (l1);
return GPG_ERR_NO_OBJ;
}
- gcry_md_write (md, data, datalen);
- gcry_sexp_release (l1);
+ _gcry_md_write (md, data, datalen);
+ sexp_release (l1);
return 0;
}
@@ -1083,17 +1327,17 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
-/*
+/*
Self-test section.
*/
static const char *
selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
{
- static const char sample_data[] =
+ static const char sample_data[] =
"(data (flags pkcs1)"
" (hash sha1 #11223344556677889900aabbccddeeff10203040#))";
- static const char sample_data_bad[] =
+ static const char sample_data_bad[] =
"(data (flags pkcs1)"
" (hash sha1 #11223344556677889900aabbccddeeff80203040#))";
@@ -1103,30 +1347,29 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
gcry_sexp_t data_bad = NULL;
gcry_sexp_t sig = NULL;
- err = gcry_sexp_sscan (&data, NULL,
- sample_data, strlen (sample_data));
+ err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
if (!err)
- err = gcry_sexp_sscan (&data_bad, NULL,
- sample_data_bad, strlen (sample_data_bad));
+ err = sexp_sscan (&data_bad, NULL,
+ sample_data_bad, strlen (sample_data_bad));
if (err)
{
errtxt = "converting data failed";
goto leave;
}
- err = gcry_pk_sign (&sig, data, skey);
+ err = _gcry_pk_sign (&sig, data, skey);
if (err)
{
errtxt = "signing failed";
goto leave;
}
- err = gcry_pk_verify (sig, data, pkey);
+ err = _gcry_pk_verify (sig, data, pkey);
if (err)
{
errtxt = "verify failed";
goto leave;
}
- err = gcry_pk_verify (sig, data_bad, pkey);
+ err = _gcry_pk_verify (sig, data_bad, pkey);
if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
{
errtxt = "bad signature not detected";
@@ -1135,9 +1378,9 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
leave:
- gcry_sexp_release (sig);
- gcry_sexp_release (data_bad);
- gcry_sexp_release (data);
+ sexp_release (sig);
+ sexp_release (data_bad);
+ sexp_release (data);
return errtxt;
}
@@ -1157,19 +1400,19 @@ extract_a_from_sexp (gcry_sexp_t encr_data)
gcry_sexp_t l1, l2, l3;
gcry_mpi_t a_value;
- l1 = gcry_sexp_find_token (encr_data, "enc-val", 0);
+ l1 = sexp_find_token (encr_data, "enc-val", 0);
if (!l1)
return NULL;
- l2 = gcry_sexp_find_token (l1, "rsa", 0);
- gcry_sexp_release (l1);
+ l2 = sexp_find_token (l1, "rsa", 0);
+ sexp_release (l1);
if (!l2)
return NULL;
- l3 = gcry_sexp_find_token (l2, "a", 0);
- gcry_sexp_release (l2);
+ l3 = sexp_find_token (l2, "a", 0);
+ sexp_release (l2);
if (!l3)
return NULL;
- a_value = gcry_sexp_nth_mpi (l3, 1, 0);
- gcry_sexp_release (l3);
+ a_value = sexp_nth_mpi (l3, 1, 0);
+ sexp_release (l3);
return a_value;
}
@@ -1190,12 +1433,11 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
gcry_sexp_t tmplist = NULL;
/* Create plaintext. The plaintext is actually a big integer number. */
- plaintext = gcry_mpi_new (nbits);
- gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
-
+ plaintext = mpi_new (nbits);
+ _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
+
/* Put the plaintext into an S-expression. */
- err = gcry_sexp_build (&plain, NULL,
- "(data (flags raw) (value %m))", plaintext);
+ err = sexp_build (&plain, NULL, "(data (flags raw) (value %m))", plaintext);
if (err)
{
errtxt = "converting data failed";
@@ -1203,7 +1445,7 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
}
/* Encrypt. */
- err = gcry_pk_encrypt (&encr, plain, pkey);
+ err = _gcry_pk_encrypt (&encr, plain, pkey);
if (err)
{
errtxt = "encrypt failed";
@@ -1211,7 +1453,7 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
}
/* Extraxt the ciphertext from the returned S-expression. */
- /*gcry_sexp_dump (encr);*/
+ /*sexp_dump (encr);*/
ciphertext = extract_a_from_sexp (encr);
if (!ciphertext)
{
@@ -1220,16 +1462,16 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
}
/* Check that the ciphertext does no match the plaintext. */
- /* _gcry_log_mpidump ("plaintext", plaintext); */
- /* _gcry_log_mpidump ("ciphertxt", ciphertext); */
- if (!gcry_mpi_cmp (plaintext, ciphertext))
+ /* _gcry_log_printmpi ("plaintext", plaintext); */
+ /* _gcry_log_printmpi ("ciphertxt", ciphertext); */
+ if (!mpi_cmp (plaintext, ciphertext))
{
errtxt = "ciphertext matches plaintext";
goto leave;
}
/* Decrypt. */
- err = gcry_pk_decrypt (&decr, encr, skey);
+ err = _gcry_pk_decrypt (&decr, encr, skey);
if (err)
{
errtxt = "decrypt failed";
@@ -1242,32 +1484,32 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
gcry_pk_encrypt directly to gcry_pk_decrypt, such a flag value
won't be there as of today. To be prepared for future changes we
take care of it anyway. */
- tmplist = gcry_sexp_find_token (decr, "value", 0);
+ tmplist = sexp_find_token (decr, "value", 0);
if (tmplist)
- decr_plaintext = gcry_sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG);
+ decr_plaintext = sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG);
else
- decr_plaintext = gcry_sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG);
+ decr_plaintext = sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG);
if (!decr_plaintext)
{
errtxt = "decrypt returned no plaintext";
goto leave;
}
-
+
/* Check that the decrypted plaintext matches the original plaintext. */
- if (gcry_mpi_cmp (plaintext, decr_plaintext))
+ if (mpi_cmp (plaintext, decr_plaintext))
{
errtxt = "mismatch";
goto leave;
}
leave:
- gcry_sexp_release (tmplist);
- gcry_mpi_release (decr_plaintext);
- gcry_sexp_release (decr);
- gcry_mpi_release (ciphertext);
- gcry_sexp_release (encr);
- gcry_sexp_release (plain);
- gcry_mpi_release (plaintext);
+ sexp_release (tmplist);
+ _gcry_mpi_release (decr_plaintext);
+ sexp_release (decr);
+ _gcry_mpi_release (ciphertext);
+ sexp_release (encr);
+ sexp_release (plain);
+ _gcry_mpi_release (plaintext);
return errtxt;
}
@@ -1280,25 +1522,24 @@ selftests_rsa (selftest_report_func_t report)
gcry_error_t err;
gcry_sexp_t skey = NULL;
gcry_sexp_t pkey = NULL;
-
+
/* Convert the S-expressions into the internal representation. */
what = "convert";
- err = gcry_sexp_sscan (&skey, NULL,
- sample_secret_key, strlen (sample_secret_key));
+ err = sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key));
if (!err)
- err = gcry_sexp_sscan (&pkey, NULL,
- sample_public_key, strlen (sample_public_key));
+ err = sexp_sscan (&pkey, NULL,
+ sample_public_key, strlen (sample_public_key));
if (err)
{
- errtxt = gcry_strerror (err);
+ errtxt = _gcry_strerror (err);
goto failed;
}
what = "key consistency";
- err = gcry_pk_testkey (skey);
+ err = _gcry_pk_testkey (skey);
if (err)
{
- errtxt = gcry_strerror (err);
+ errtxt = _gcry_strerror (err);
goto failed;
}
@@ -1312,13 +1553,13 @@ selftests_rsa (selftest_report_func_t report)
if (errtxt)
goto failed;
- gcry_sexp_release (pkey);
- gcry_sexp_release (skey);
+ sexp_release (pkey);
+ sexp_release (skey);
return 0; /* Succeeded. */
failed:
- gcry_sexp_release (pkey);
- gcry_sexp_release (skey);
+ sexp_release (pkey);
+ sexp_release (skey);
if (report)
report ("pubkey", GCRY_PK_RSA, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
@@ -1341,7 +1582,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
default:
ec = GPG_ERR_PUBKEY_ALGO;
break;
-
+
}
return ec;
}
@@ -1349,19 +1590,12 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
-static const char *rsa_names[] =
- {
- "rsa",
- "openpgp-rsa",
- "oid.1.2.840.113549.1.1.1",
- NULL,
- };
-
gcry_pk_spec_t _gcry_pubkey_spec_rsa =
{
+ GCRY_PK_RSA, { 0, 1 },
+ (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
"RSA", rsa_names,
"ne", "nedpqu", "a", "s", "n",
- GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR,
rsa_generate,
rsa_check_secret_key,
rsa_encrypt,
@@ -1369,11 +1603,6 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa =
rsa_sign,
rsa_verify,
rsa_get_nbits,
- };
-pk_extra_spec_t _gcry_pubkey_extraspec_rsa =
- {
run_selftests,
- rsa_generate_ext,
compute_keygrip
};
-