summaryrefslogtreecommitdiff
path: root/cipher/rsa.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-09-12 11:40:22 +0000
committerWerner Koch <wk@gnupg.org>2008-09-12 11:40:22 +0000
commit882a6037f4560a7f157947c135cc72174db6d57f (patch)
tree90fadddfeb70a6a1eb4a9b278d0841da0e1f3bd5 /cipher/rsa.c
parent13897adce415a26c749380c1b3a5bed541438de2 (diff)
downloadlibgcrypt-882a6037f4560a7f157947c135cc72174db6d57f.tar.gz
Improve selftest done after key generation.
Diffstat (limited to 'cipher/rsa.c')
-rw-r--r--cipher/rsa.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 26e19cf7..00384975 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -84,7 +84,7 @@ static const char sample_public_key[] =
-static void test_keys (RSA_secret_key *sk, unsigned nbits);
+static int test_keys (RSA_secret_key *sk, unsigned nbits);
static gpg_err_code_t generate (RSA_secret_key *sk,
unsigned int nbits, unsigned long use_e,
int transient_key);
@@ -93,29 +93,57 @@ 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 void
-test_keys( RSA_secret_key *sk, unsigned nbits )
+/* Check that a freshly generated key actually works. Returns 0 on success. */
+static int
+test_keys (RSA_secret_key *sk, unsigned int nbits)
{
+ int result = -1; /* Default to failure. */
RSA_public_key pk;
- gcry_mpi_t test = gcry_mpi_new ( nbits );
- gcry_mpi_t out1 = gcry_mpi_new ( nbits );
- gcry_mpi_t out2 = gcry_mpi_new ( nbits );
+ 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);
+ /* Put the relevant parameters into a public key structure. */
pk.n = sk->n;
pk.e = sk->e;
- gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM );
-
- public( out1, test, &pk );
- secret( out2, out1, sk );
- if( mpi_cmp( test, out2 ) )
- log_fatal("RSA operation: public, secret failed\n");
- secret( out1, test, sk );
- public( out2, out1, &pk );
- if( mpi_cmp( test, out2 ) )
- log_fatal("RSA operation: secret, public failed\n");
- gcry_mpi_release ( test );
- gcry_mpi_release ( out1 );
- gcry_mpi_release ( out2 );
+
+ /* Create a random plaintext. */
+ 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))
+ 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))
+ goto leave; /* Plaintext does not match. */
+
+ /* Create another random plaintext as data for signature checking. */
+ 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))
+ goto leave; /* Signature does not match. */
+
+ result = 0; /* All tests succeeded. */
+
+ leave:
+ gcry_mpi_release (signature);
+ gcry_mpi_release (decr_plaintext);
+ gcry_mpi_release (ciphertext);
+ gcry_mpi_release (plaintext);
+ return result;
}
@@ -279,8 +307,17 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
sk->d = d;
sk->u = u;
- /* now we can test our keys (this should never fail!) */
- test_keys( sk, nbits - 64 );
+ /* 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;
+ return GPG_ERR_SELFTEST_FAILED;
+ }
return 0;
}