Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / util / test_crypto_rsa.c
index 6a2c1b3553d34fd4356f78707b45503cebf64f44..c64c0acf9190f892bf50b6b7b403a07348f04cdb 100644 (file)
 /*
-     This file is part of GNUnet.
-     (C) 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
+  This file is part of GNUnet
+  Copyright (C) 2014,2015 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+  GNUnet is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
 
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+  GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 
+  You should have received a copy of the GNU General Public License along with
+  GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
 */
+
 /**
  * @file util/test_crypto_rsa.c
- * @brief testcase for RSA public key crypto
- * @author Christian Grothoff
+ * @brief testcase for utility functions for RSA cryptography
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Jeffrey Burdges <burdges@gnunet.org>
  */
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_time_lib.h"
-
-#define TESTSTRING "Hello World\0"
-#define MAX_TESTVAL sizeof(struct GNUNET_CRYPTO_AesSessionKey)
-#define ITER 25
-#define KEYFILE "/tmp/test-gnunet-crypto-rsa.key"
-
-#define PERF GNUNET_YES
-
-static int
-testEncryptDecrypt ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  struct GNUNET_CRYPTO_RsaEncryptedData target;
-  char result[MAX_TESTVAL];
-  int i;
-  struct GNUNET_TIME_Absolute start;
-  int ok;
-
-  fprintf (stderr, "W");
-  hostkey = GNUNET_CRYPTO_rsa_key_create ();
-  GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
-
-  ok = 0;
-  start = GNUNET_TIME_absolute_get ();
-  for (i = 0; i < ITER; i++)
-    {
-      fprintf (stderr, ".");
-      if (GNUNET_SYSERR ==
-         GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
-                                    &pkey, &target))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
-         ok++;
-         continue;
-       }
-      if (-1 ==
-         GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, result,
-                                    strlen (TESTSTRING) + 1))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
-         ok++;
-         continue;
-
-       }
-      if (strncmp (TESTSTRING, result, strlen (TESTSTRING)) != 0)
-       {
-         printf ("%s != %.*s - testEncryptDecrypt failed!\n", TESTSTRING,
-                 (int) MAX_TESTVAL, result);
-         ok++;
-         continue;
-       }
-    }
-  printf ("%d RSA encrypt/decrypt operations %llums (%d failures)\n", ITER,
-         (unsigned long long)
-         GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
-  GNUNET_CRYPTO_rsa_key_free (hostkey);
-  if (ok == 0)
-    return GNUNET_OK;
-  else
-    return GNUNET_SYSERR;
-}
-
-#if PERF
-static int
-testEncryptPerformance ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  struct GNUNET_CRYPTO_RsaEncryptedData target;
-  int i;
-  struct GNUNET_TIME_Absolute start;
-  int ok;
-
-  fprintf (stderr, "W");
-  hostkey = GNUNET_CRYPTO_rsa_key_create ();
-  GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
-
-  ok = 0;
-  start = GNUNET_TIME_absolute_get ();
-  for (i = 0; i < ITER; i++)
-    {
-      fprintf (stderr, ".");
-      if (GNUNET_SYSERR ==
-         GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
-                                    &pkey, &target))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
-         ok++;
-         continue;
-       }
-    }
-  printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER,
-         (unsigned long long)
-         GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
-  GNUNET_CRYPTO_rsa_key_free (hostkey);
-  if (ok != 0)
-    return GNUNET_SYSERR;
-  return GNUNET_OK;
-}
-#endif
-
-static int
-testEncryptDecryptSK ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  struct GNUNET_CRYPTO_RsaEncryptedData target;
-  struct GNUNET_CRYPTO_AesSessionKey insk;
-  struct GNUNET_CRYPTO_AesSessionKey outsk;
-  int i;
-  struct GNUNET_TIME_Absolute start;
-  int ok;
-
-  fprintf (stderr, "W");
-  hostkey = GNUNET_CRYPTO_rsa_key_create ();
-  GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
-
-  ok = 0;
-  start = GNUNET_TIME_absolute_get ();
-  for (i = 0; i < ITER; i++)
-    {
-      fprintf (stderr, ".");
-      GNUNET_CRYPTO_aes_create_session_key (&insk);
-      if (GNUNET_SYSERR ==
-         GNUNET_CRYPTO_rsa_encrypt (&insk,
-                                    sizeof (struct
-                                            GNUNET_CRYPTO_AesSessionKey),
-                                    &pkey, &target))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
-         ok++;
-         continue;
-       }
-      if (-1 ==
-         GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, &outsk,
-                                    sizeof (struct
-                                            GNUNET_CRYPTO_AesSessionKey)))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
-         ok++;
-         continue;
-       }
-      if (0 !=
-         memcmp (&insk, &outsk, sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
-       {
-         printf ("testEncryptDecryptSK failed!\n");
-         ok++;
-         continue;
-       }
-    }
-  printf ("%d RSA encrypt/decrypt SK operations %llums (%d failures)\n", ITER,
-         (unsigned long long)
-         GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
-  GNUNET_CRYPTO_rsa_key_free (hostkey);
-  if (ok != 0)
-    return GNUNET_SYSERR;
-  return GNUNET_OK;
-}
-
-
-static int
-testSignVerify ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
-  struct GNUNET_CRYPTO_RsaSignature sig;
-  struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  int i;
-  struct GNUNET_TIME_Absolute start;
-  int ok = GNUNET_OK;
-
-  fprintf (stderr, "W");
-  hostkey = GNUNET_CRYPTO_rsa_key_create ();
-  GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
-  start = GNUNET_TIME_absolute_get ();
-  purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
-  purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
-
-  for (i = 0; i < ITER; i++)
-    {
-      fprintf (stderr, ".");
-      if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
-         ok = GNUNET_SYSERR;
-         continue;
-       }
-      if (GNUNET_SYSERR ==
-         GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp,
-                                   &sig, &pkey))
-       {
-         printf ("GNUNET_CRYPTO_rsa_verify failed!\n");
-         ok = GNUNET_SYSERR;
-         continue;
-       }
-      if (GNUNET_SYSERR !=
-         GNUNET_CRYPTO_rsa_verify
-         (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &purp, &sig, &pkey))
-       {
-         printf ("GNUNET_CRYPTO_rsa_verify failed to fail!\n");
-         ok = GNUNET_SYSERR;
-         continue;
-       }
-    }
-  printf ("%d RSA sign/verify operations %llums\n", ITER,
-         (unsigned long long)
-         GNUNET_TIME_absolute_get_duration (start).rel_value);
-  GNUNET_CRYPTO_rsa_key_free (hostkey);
-  return ok;
-}
+#include <gcrypt.h>
+#include "gnunet_util_lib.h"
 
-
-#if PERF
-static int
-testSignPerformance ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
-  struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
-  struct GNUNET_CRYPTO_RsaSignature sig;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  int i;
-  struct GNUNET_TIME_Absolute start;
-  int ok = GNUNET_OK;
-
-  purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
-  purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
-  fprintf (stderr, "W");
-  hostkey = GNUNET_CRYPTO_rsa_key_create ();
-  GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
-  start = GNUNET_TIME_absolute_get ();
-  for (i = 0; i < ITER; i++)
-    {
-      fprintf (stderr, ".");
-      if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig))
-       {
-         fprintf (stderr, "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
-         ok = GNUNET_SYSERR;
-         continue;
-       }
-    }
-  printf ("%d RSA sign operations %llu ms\n", ITER,
-         (unsigned long long)
-         GNUNET_TIME_absolute_get_duration (start).rel_value);
-  GNUNET_CRYPTO_rsa_key_free (hostkey);
-  return ok;
-}
-#endif
-
-
-static int
-testCreateFromFile ()
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *key;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2;
-
-  key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
-  GNUNET_assert (NULL != key);
-  GNUNET_CRYPTO_rsa_key_get_public (key, &p1);
-  GNUNET_CRYPTO_rsa_key_free (key);
-  key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
-  GNUNET_assert (NULL != key);
-  GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
-  GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1)));
-  GNUNET_CRYPTO_rsa_key_free (key);
-  GNUNET_assert (0 == UNLINK (KEYFILE));
-  key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
-  GNUNET_assert (NULL != key);
-  GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
-  GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1)));
-  GNUNET_CRYPTO_rsa_key_free (key);
-  GNUNET_assert (0 == UNLINK (KEYFILE));
-  return GNUNET_OK;
-}
+#define KEY_SIZE 1024
 
 
 int
-main (int argc, char *argv[])
+main (int argc,
+      char *argv[])
 {
-  int failureCount = 0;
-
-  GNUNET_log_setup ("test-crypto-rsa", "WARNING", NULL);
-  GNUNET_CRYPTO_random_disable_entropy_gathering ();
-  if (GNUNET_OK != testCreateFromFile ())
-    failureCount++;
-#if PERF
-  if (GNUNET_OK != testEncryptPerformance ())
-    failureCount++;
-  if (GNUNET_OK != testSignPerformance ())
-    failureCount++;
-#endif
-  if (GNUNET_OK != testEncryptDecryptSK ())
-    failureCount++;
-  if (GNUNET_OK != testEncryptDecrypt ())
-    failureCount++;
-  if (GNUNET_OK != testSignVerify ())
-    failureCount++;
-
-  if (failureCount != 0)
-    {
-      printf ("\n\n%d TESTS FAILED!\n\n", failureCount);
-      return -1;
-    }
+#define RND_BLK_SIZE 4096
+  unsigned char rnd_blk[RND_BLK_SIZE];
+  struct GNUNET_CRYPTO_RsaPrivateKey *priv;
+  struct GNUNET_CRYPTO_RsaPrivateKey *priv_copy;
+  struct GNUNET_CRYPTO_RsaPublicKey *pub;
+  struct GNUNET_CRYPTO_RsaPublicKey *pub_copy;
+  struct GNUNET_CRYPTO_RsaSignature *sig;
+  struct GNUNET_CRYPTO_RsaSignature *sig_copy;
+  struct GNUNET_CRYPTO_RsaSignature *bsig;
+  struct GNUNET_CRYPTO_RsaBlindingKeySecret bsec;
+  struct GNUNET_HashCode hash;
+  char *blind_buf;
+  size_t bsize;
+
+  GNUNET_log_setup ("test-rsa", "WARNING", NULL);
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              rnd_blk,
+                              RND_BLK_SIZE);
+  GNUNET_CRYPTO_hash (rnd_blk,
+                      RND_BLK_SIZE,
+                      &hash);
+  priv = GNUNET_CRYPTO_rsa_private_key_create (KEY_SIZE);
+  priv_copy = GNUNET_CRYPTO_rsa_private_key_dup (priv);
+  GNUNET_assert (NULL != priv_copy);
+  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv, priv_copy));
+  pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
+
+  /* Encoding */
+  size_t size;
+  char *enc;
+  enc = NULL;
+  size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &enc);
+
+  /* Decoding */
+  GNUNET_CRYPTO_rsa_private_key_free (priv);
+  priv = NULL;
+  priv = GNUNET_CRYPTO_rsa_private_key_decode (enc, size);
+  GNUNET_assert (NULL != priv);
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              enc, size);
+  GNUNET_assert (NULL == GNUNET_CRYPTO_rsa_private_key_decode (enc, size));
+  (void) fprintf (stderr, "The above warning is expected.\n");
+  GNUNET_free (enc);
+
+  /* try ordinary sig first */
+  sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
+                                    &hash);
+  sig_copy = GNUNET_CRYPTO_rsa_signature_dup (sig);
+  GNUNET_assert (NULL != sig);
+  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig_copy));
+  pub_copy = GNUNET_CRYPTO_rsa_public_key_dup (pub);
+  GNUNET_assert (NULL != pub_copy);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub_copy));
+  /* corrupt our hash and see if the signature is still valid */
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &hash,
+                              sizeof (struct GNUNET_HashCode));
+  GNUNET_assert (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&hash,
+                                                        sig,
+                                                        pub));
+  (void) fprintf (stderr, "The above warning is expected.\n");
+  GNUNET_CRYPTO_rsa_signature_free (sig);
+
+  /* test blind signing */
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                             &bsec,
+                             sizeof (bsec));
+  GNUNET_CRYPTO_rsa_blind (&hash,
+                          &bsec,
+                          pub,
+                          &blind_buf,&bsize);
+  GNUNET_assert (0 != bsize);
+  bsig = GNUNET_CRYPTO_rsa_sign_blinded (priv,
+                                         blind_buf,
+                                         bsize);
+  GNUNET_free (blind_buf);
+  sig = GNUNET_CRYPTO_rsa_unblind (bsig,
+                                  &bsec,
+                                  pub);
+  GNUNET_CRYPTO_rsa_signature_free (bsig);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
+  GNUNET_CRYPTO_rsa_signature_free (sig);
+  GNUNET_CRYPTO_rsa_signature_free (sig_copy);
+  GNUNET_CRYPTO_rsa_private_key_free (priv);
+  GNUNET_CRYPTO_rsa_private_key_free (priv_copy);
+  GNUNET_CRYPTO_rsa_public_key_free (pub);
+  GNUNET_CRYPTO_rsa_public_key_free (pub_copy);
   return 0;
-}                              /* end of main */
+}