-code deduplication in rsa sign/verify code
[oweals/gnunet.git] / src / util / crypto_ksk.c
index bec87c803a0817b334bca33900da9b805f29ebb8..0c091099e6954aaa2e73a57c835692d1840061e4 100644 (file)
 #include <gcrypt.h>
 #include <limits.h>
 
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
 /**
  * Log an error message at log-level 'level' that indicates
  * a failure of the command 'cmd' with the message given
  * by gcry_strerror(rc).
  */
-#define LOG_GCRY(level, cmd, rc) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0);
+#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0);
 
 
 typedef struct
@@ -68,11 +70,11 @@ struct GNUNET_CRYPTO_RsaPrivateKey
 
 
 static void
-mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd)
+mpz_randomize (gcry_mpi_t n, unsigned int nbits, struct GNUNET_HashCode * rnd)
 {
-  GNUNET_HashCode hc;
-  GNUNET_HashCode tmp;
-  int bits_per_hc = sizeof (GNUNET_HashCode) * 8;
+  struct GNUNET_HashCode hc;
+  struct GNUNET_HashCode tmp;
+  int bits_per_hc = sizeof (struct GNUNET_HashCode) * 8;
   int cnt;
   int i;
 
@@ -86,8 +88,8 @@ mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd)
     int j;
 
     if (i > 0)
-      GNUNET_CRYPTO_hash (&hc, sizeof (GNUNET_HashCode), &tmp);
-    for (j = 0; j < sizeof (GNUNET_HashCode) / sizeof (uint32_t); j++)
+      GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), &tmp);
+    for (j = 0; j < sizeof (struct GNUNET_HashCode) / sizeof (uint32_t); j++)
     {
 #if HAVE_GCRY_MPI_LSHIFT
       gcry_mpi_lshift (n, n, sizeof (uint32_t) * 8);
@@ -99,7 +101,7 @@ mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd)
     }
     hc = tmp;
   }
-  GNUNET_CRYPTO_hash (&hc, sizeof (GNUNET_HashCode), rnd);
+  GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), rnd);
   i = gcry_mpi_get_nbits (n);
   while (i > nbits)
     gcry_mpi_clear_bit (n, --i);
@@ -135,7 +137,7 @@ mpz_tdiv_q_2exp (gcry_mpi_t q, gcry_mpi_t n, unsigned int b)
  * Return true if n is probably a prime
  */
 static int
-is_prime (gcry_mpi_t n, int steps, GNUNET_HashCode * hc)
+is_prime (gcry_mpi_t n, int steps, struct GNUNET_HashCode * hc)
 {
   gcry_mpi_t x;
   gcry_mpi_t y;
@@ -216,7 +218,7 @@ adjust (unsigned char *buf, size_t size, size_t target)
 
 
 static void
-gen_prime (gcry_mpi_t * ptest, unsigned int nbits, GNUNET_HashCode * hc)
+gen_prime (gcry_mpi_t * ptest, unsigned int nbits, struct GNUNET_HashCode * hc)
 {
   /* Note: 2 is not included because it can be tested more easily by
    * looking at bit 0. The last entry in this list is marked by a zero */
@@ -398,7 +400,7 @@ gen_prime (gcry_mpi_t * ptest, unsigned int nbits, GNUNET_HashCode * hc)
  */
 static void
 generate_kblock_key (KBlock_secret_key *sk, unsigned int nbits,
-                     GNUNET_HashCode * hc)
+                     struct GNUNET_HashCode * hc)
 {
   gcry_mpi_t t1, t2;
   gcry_mpi_t phi;               /* helper: (p-1)(q-1) */
@@ -461,6 +463,7 @@ generate_kblock_key (KBlock_secret_key *sk, unsigned int nbits,
   gcry_mpi_release (g);
 }
 
+GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
  * Internal representation of the private key.
@@ -480,17 +483,17 @@ struct KskRsaPrivateKeyBinaryEncoded
   uint16_t sizedmq1 GNUNET_PACKED;      /*  in big-endian! */
   /* followed by the actual values */
 };
-
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Deterministically (!) create a hostkey using only the
  * given HashCode as input to the PRNG.
  */
 static struct KskRsaPrivateKeyBinaryEncoded *
-makeKblockKeyInternal (const GNUNET_HashCode * hc)
+makeKblockKeyInternal (const struct GNUNET_HashCode * hc)
 {
   KBlock_secret_key sk;
-  GNUNET_HashCode hx;
+  struct GNUNET_HashCode hx;
   unsigned char *pbu[6];
   gcry_mpi_t *pkv[6];
   size_t sizes[6];
@@ -554,202 +557,65 @@ makeKblockKeyInternal (const GNUNET_HashCode * hc)
 
 
 /**
- * Decode the internal format into the format used
- * by libgcrypt.
+ * Entry in the KSK cache.
  */
-static struct GNUNET_CRYPTO_RsaPrivateKey *
-ksk_decode_key (const struct KskRsaPrivateKeyBinaryEncoded *encoding)
-{
-  struct GNUNET_CRYPTO_RsaPrivateKey *ret;
-  gcry_sexp_t res;
-  gcry_mpi_t n, e, d, p, q, u;
-  int rc;
-  size_t size;
-  int pos;
-
-  pos = 0;
-  size = ntohs (encoding->sizen);
-  rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG,
-                      &((const unsigned char *) (&encoding[1]))[pos], size,
-                      &size);
-  pos += ntohs (encoding->sizen);
-  if (rc)
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-    return NULL;
-  }
-  size = ntohs (encoding->sizee);
-  rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
-                      &((const unsigned char *) (&encoding[1]))[pos], size,
-                      &size);
-  pos += ntohs (encoding->sizee);
-  if (rc)
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-    gcry_mpi_release (n);
-    return NULL;
-  }
-  size = ntohs (encoding->sized);
-  rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
-                      &((const unsigned char *) (&encoding[1]))[pos], size,
-                      &size);
-  pos += ntohs (encoding->sized);
-  if (rc)
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-    gcry_mpi_release (n);
-    gcry_mpi_release (e);
-    return NULL;
-  }
-  /* swap p and q! */
-  size = ntohs (encoding->sizep);
-  if (size > 0)
-  {
-    rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
-                        &((const unsigned char *) (&encoding[1]))[pos], size,
-                        &size);
-    pos += ntohs (encoding->sizep);
-    if (rc)
-    {
-      LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-      gcry_mpi_release (n);
-      gcry_mpi_release (e);
-      gcry_mpi_release (d);
-      return NULL;
-    }
-  }
-  else
-    q = NULL;
-  size = ntohs (encoding->sizeq);
-  if (size > 0)
-  {
-    rc = gcry_mpi_scan (&p, GCRYMPI_FMT_USG,
-                        &((const unsigned char *) (&encoding[1]))[pos], size,
-                        &size);
-    pos += ntohs (encoding->sizeq);
-    if (rc)
-    {
-      LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-      gcry_mpi_release (n);
-      gcry_mpi_release (e);
-      gcry_mpi_release (d);
-      if (q != NULL)
-        gcry_mpi_release (q);
-      return NULL;
-    }
-  }
-  else
-    p = NULL;
-  pos += ntohs (encoding->sizedmp1);
-  pos += ntohs (encoding->sizedmq1);
-  size =
-      ntohs (encoding->len) - sizeof (struct KskRsaPrivateKeyBinaryEncoded) -
-      pos;
-  if (size > 0)
-  {
-    rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG,
-                        &((const unsigned char *) (&encoding[1]))[pos], size,
-                        &size);
-    if (rc)
-    {
-      LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-      gcry_mpi_release (n);
-      gcry_mpi_release (e);
-      gcry_mpi_release (d);
-      if (p != NULL)
-        gcry_mpi_release (p);
-      if (q != NULL)
-        gcry_mpi_release (q);
-      return NULL;
-    }
-  }
-  else
-    u = NULL;
-
-  if ((p != NULL) && (q != NULL) && (u != NULL))
-  {
-    rc = gcry_sexp_build (&res, &size,  /* erroff */
-                          "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))",
-                          n, e, d, p, q, u);
-  }
-  else
-  {
-    if ((p != NULL) && (q != NULL))
-    {
-      rc = gcry_sexp_build (&res, &size,        /* erroff */
-                            "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))",
-                            n, e, d, p, q);
-    }
-    else
-    {
-      rc = gcry_sexp_build (&res, &size,        /* erroff */
-                            "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d);
-    }
-  }
-  gcry_mpi_release (n);
-  gcry_mpi_release (e);
-  gcry_mpi_release (d);
-  if (p != NULL)
-    gcry_mpi_release (p);
-  if (q != NULL)
-    gcry_mpi_release (q);
-  if (u != NULL)
-    gcry_mpi_release (u);
-
-  if (rc)
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
-#if EXTRA_CHECKS
-  if (gcry_pk_testkey (res))
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
-    return NULL;
-  }
-#endif
-  ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
-  ret->sexp = res;
-  return ret;
-}
-
-
 struct KBlockKeyCacheLine
 {
-  GNUNET_HashCode hc;
+  /**
+   * Hash from which the key was generated.
+   */
+  struct GNUNET_HashCode hc;
+
+  /**
+   * The encoded key.
+   */
   struct KskRsaPrivateKeyBinaryEncoded *pke;
 };
 
+
+/**
+ * Cached KSK keys so that we don't have to recompute them
+ * all the time.
+ */
 static struct KBlockKeyCacheLine **cache;
 
+
+/**
+ * Size of the 'cache' array.
+ */
 static unsigned int cacheSize;
 
+
 /**
  * Deterministically (!) create a hostkey using only the
  * given HashCode as input to the PRNG.
+ *
+ * @param hc hash code to generate the key from
+ * @return corresponding private key; must not be freed!
  */
 struct GNUNET_CRYPTO_RsaPrivateKey *
-GNUNET_CRYPTO_rsa_key_create_from_hash (const GNUNET_HashCode * hc)
+GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode * hc)
 {
-  struct GNUNET_CRYPTO_RsaPrivateKey *ret;
   struct KBlockKeyCacheLine *line;
   unsigned int i;
 
-  for (i = 0; i < cacheSize; i++)
-  {
-    if (0 == memcmp (hc, &cache[i]->hc, sizeof (GNUNET_HashCode)))
-    {
-      ret = ksk_decode_key (cache[i]->pke);
-      return ret;
-    }
-  }
-
+  for (i = 0; i < cacheSize; i++)  
+    if (0 == memcmp (hc, &cache[i]->hc, sizeof (struct GNUNET_HashCode)))
+      return GNUNET_CRYPTO_rsa_decode_key ((const char*) cache[i]->pke,
+                                          ntohs (cache[i]->pke->len));  
   line = GNUNET_malloc (sizeof (struct KBlockKeyCacheLine));
   line->hc = *hc;
   line->pke = makeKblockKeyInternal (hc);
   GNUNET_array_grow (cache, cacheSize, cacheSize + 1);
   cache[cacheSize - 1] = line;
-  return ksk_decode_key (line->pke);
+  return GNUNET_CRYPTO_rsa_decode_key ((const char*) line->pke,
+                                      ntohs (line->pke->len));
 }
 
 
+/**
+ * Destructor that frees the KSK cache.
+ */
 void __attribute__ ((destructor)) GNUNET_CRYPTO_ksk_fini ()
 {
   unsigned int i;