diff options
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/rsa.c')
-rw-r--r-- | plugins/MirOTR/Libgcrypt/cipher/rsa.c | 1045 |
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 }; - |