diff options
| -rw-r--r-- | configure.ac | 7 | ||||
| -rw-r--r-- | src/util/crypto.c | 423 | 
2 files changed, 6 insertions, 424 deletions
diff --git a/configure.ac b/configure.ac index 6194f835..bd18a430 100644 --- a/configure.ac +++ b/configure.ac @@ -129,11 +129,16 @@ AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_util_lib.h],   [AC_CHECK_LIB([gnunetutil], [GNUNET_SCHEDULER_run], libgnunetutil=1)],    [], [#ifdef HAVE_GNUNET_PLATFORM_H          #include <gnunet/platform.h> +       #endif +        #include <gnunet/gnunet_common.h> +       #if GNUNET_UTIL_VERSION < 0x00A0104 +        #fail libgnunetutil is too old         #endif])  AS_IF([test $libgnunetutil != 1],    [AC_MSG_ERROR([[  *** -*** You need libgnunetutil to build this program. +*** You need libgnunetutil > 0.14.0 to build this program. +*** (Yes, ">", libgnunetutil 0.14.0 is NOT enough.)  *** This library is part of GNUnet, available at  ***   https://gnunet.org  *** ]])]) diff --git a/src/util/crypto.c b/src/util/crypto.c index 4f084b19..a7ea4f4c 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -25,18 +25,6 @@  #include "taler_util.h"  #include <gcrypt.h> -/** - * Should we use the RSA blind signing implementation from libgnunetutil?  The - * blinding only works correctly with a current version of libgnunetutil. - * - * Only applies to blinding and unblinding, but - * not to blind signing. - * - * FIXME: Can we define some macro for this in configure.ac - * to detect the version? - */ -#define USE_GNUNET_RSA_BLINDING 0 -  /**   * Function called by libgcrypt on serious errors. @@ -312,280 +300,6 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,  } -#if ! USE_GNUNET_RSA_BLINDING - - -/** - * The private information of an RSA key pair. - * - * FIXME: This declaration is evil, as it defines - * an opaque struct that is "owned" by GNUnet. - */ -struct GNUNET_CRYPTO_RsaPrivateKey -{ -  /** -   * Libgcrypt S-expression for the RSA private key. -   */ -  gcry_sexp_t sexp; -}; - - -/** - * The public information of an RSA key pair. - * - * FIXME: This declaration is evil, as it defines - * an opaque struct that is "owned" by GNUnet. - */ -struct GNUNET_CRYPTO_RsaPublicKey -{ -  /** -   * Libgcrypt S-expression for the RSA public key. -   */ -  gcry_sexp_t sexp; -}; - -/** - * @brief an RSA signature - * - * FIXME: This declaration is evil, as it defines - * an opaque struct that is "owned" by GNUnet. - */ -struct GNUNET_CRYPTO_RsaSignature -{ -  /** -   * Libgcrypt S-expression for the RSA signature. -   */ -  gcry_sexp_t sexp; -}; - -/** - * @brief RSA blinding key - */ -struct RsaBlindingKey -{ -  /** -   * Random value used for blinding. -   */ -  gcry_mpi_t r; -}; - - -/** - * Destroy a blinding key - * - * @param bkey the blinding key to destroy - */ -static void -rsa_blinding_key_free (struct RsaBlindingKey *bkey) -{ -  gcry_mpi_release (bkey->r); -  GNUNET_free (bkey); -} - - -/** - * Extract values from an S-expression. - * - * @param array where to store the result(s) - * @param sexp S-expression to parse - * @param topname top-level name in the S-expression that is of interest - * @param elems names of the elements to extract - * @return 0 on success - */ -static int -key_from_sexp (gcry_mpi_t *array, -               gcry_sexp_t sexp, -               const char *topname, -               const char *elems) -{ -  gcry_sexp_t list; -  gcry_sexp_t l2; -  const char *s; -  unsigned int idx; - -  if (! (list = gcry_sexp_find_token (sexp, topname, 0))) -    return 1; -  l2 = gcry_sexp_cadr (list); -  gcry_sexp_release (list); -  list = l2; -  if (! list) -    return 2; -  idx = 0; -  for (s = elems; *s; s++, idx++) -  { -    if (! (l2 = gcry_sexp_find_token (list, s, 1))) -    { -      for (unsigned int i = 0; i < idx; i++) -      { -        gcry_free (array[i]); -        array[i] = NULL; -      } -      gcry_sexp_release (list); -      return 3;                 /* required parameter not found */ -    } -    array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); -    gcry_sexp_release (l2); -    if (! array[idx]) -    { -      for (unsigned int i = 0; i < idx; i++) -      { -        gcry_free (array[i]); -        array[i] = NULL; -      } -      gcry_sexp_release (list); -      return 4;                 /* required parameter is invalid */ -    } -  } -  gcry_sexp_release (list); -  return 0; -} - - -/** - * Test for malicious RSA key. - * - * Assuming n is an RSA modulous and r is generated using a call to - * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a - * malicious RSA key designed to deanomize the user. - * - * @param r KDF result - * @param n RSA modulus - * @return True if gcd(r,n) = 1, False means RSA key is malicious - */ -static int -rsa_gcd_validate (gcry_mpi_t r, gcry_mpi_t n) -{ -  gcry_mpi_t g; -  int t; - -  g = gcry_mpi_new (0); -  t = gcry_mpi_gcd (g, r, n); -  gcry_mpi_release (g); -  return t; -} - - -/** - * Computes a full domain hash seeded by the given public key. - * This gives a measure of provable security to the Taler exchange - * against one-more forgery attacks.  See: - *   https://eprint.iacr.org/2001/002.pdf - *   http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf - * - * @param hash initial hash of the message to sign - * @param pkey the public key of the signer - * @return MPI value set to the FDH, NULL if RSA key is malicious - */ -static gcry_mpi_t -rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, -                      const struct GNUNET_HashCode *hash) -{ -  gcry_mpi_t r, n; -  void *xts; -  size_t xts_len; -  int ok; - -  /* Extract the composite n from the RSA public key */ -  GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); -  /* Assert that it at least looks like an RSA key */ -  GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); - -  /* We key with the public denomination key as a homage to RSA-PSS by  * -  * Mihir Bellare and Phillip Rogaway.  Doing this lowers the degree   * -  * of the hypothetical polyomial-time attack on RSA-KTI created by a  * -  * polynomial-time one-more forgary attack.  Yey seeding!             */ -  xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts); - -  GNUNET_CRYPTO_kdf_mod_mpi (&r, -                             n, -                             xts, xts_len, -                             hash, sizeof(*hash), -                             "RSA-FDA FTpsW!"); -  GNUNET_free (xts); - -  ok = rsa_gcd_validate (r, n); -  gcry_mpi_release (n); -  if (ok) -    return r; -  gcry_mpi_release (r); -  return NULL; -} - - -/** - * Create a blinding key - * - * @param pkey the public key to blind for - * @param bks pre-secret to use to derive the blinding key - * @return the newly created blinding key, NULL if RSA key is malicious - */ -static struct RsaBlindingKey * -rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, -                         const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) -{ -  char *xts = "Blinding KDF extractor HMAC key";  /* Trusts bks' randomness more */ -  struct RsaBlindingKey *blind; -  gcry_mpi_t n; - -  blind = GNUNET_new (struct RsaBlindingKey); -  GNUNET_assert (NULL != blind); - -  /* Extract the composite n from the RSA public key */ -  GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); -  /* Assert that it at least looks like an RSA key */ -  GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); - -  GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, -                             n, -                             xts, strlen (xts), -                             bks, sizeof(*bks), -                             "Blinding KDF"); -  if (0 == rsa_gcd_validate (blind->r, n)) -  { -    GNUNET_free (blind); -    blind = NULL; -  } - -  gcry_mpi_release (n); -  return blind; -} - - -/** - * Print an MPI to a newly created buffer - * - * @param v MPI to print. - * @param[out] buffer newly allocated buffer containing the result - * @return number of bytes stored in @a buffer - */ -static size_t -numeric_mpi_alloc_n_print (gcry_mpi_t v, -                           char **buffer) -{ -  size_t n; -  char *b; -  size_t rsize; - -  gcry_mpi_print (GCRYMPI_FMT_USG, -                  NULL, -                  0, -                  &n, -                  v); -  b = GNUNET_malloc (n); -  GNUNET_assert (0 == -                 gcry_mpi_print (GCRYMPI_FMT_USG, -                                 (unsigned char *) b, -                                 n, -                                 &rsize, -                                 v)); -  *buffer = b; -  return n; -} - - -#endif /* ! USE_GNUNET_RSA_BLINDING */ - -  enum GNUNET_GenericReturnValue  TALER_rsa_blind (const struct GNUNET_HashCode *hash,                   const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, @@ -593,75 +307,11 @@ TALER_rsa_blind (const struct GNUNET_HashCode *hash,                   void **buf,                   size_t *buf_size)  { -#if USE_GNUNET_RSA_BLINDING    return GNUNET_CRYPTO_rsa_blind (hash,                                    bks,                                    pkey,                                    buf,                                    buf_size); -#else -  struct RsaBlindingKey *bkey; -  gcry_mpi_t data; -  gcry_mpi_t ne[2]; -  gcry_mpi_t r_e; -  gcry_mpi_t data_r_e; -  int ret; - -  GNUNET_assert (buf != NULL); -  GNUNET_assert (buf_size != NULL); -  ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne"); -  if (0 != ret) -    ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne"); -  if (0 != ret) -  { -    GNUNET_break (0); -    *buf = NULL; -    *buf_size = 0; -    return GNUNET_NO; -  } - -  data = rsa_full_domain_hash (pkey, hash); -  if (NULL == data) -    goto rsa_gcd_validate_failure; - -  bkey = rsa_blinding_key_derive (pkey, bks); -  if (NULL == bkey) -  { -    gcry_mpi_release (data); -    goto rsa_gcd_validate_failure; -  } - -  r_e = gcry_mpi_new (0); -  gcry_mpi_powm (r_e, -                 bkey->r, -                 ne[1], -                 ne[0]); -  data_r_e = gcry_mpi_new (0); -  gcry_mpi_mulm (data_r_e, -                 data, -                 r_e, -                 ne[0]); -  gcry_mpi_release (data); -  gcry_mpi_release (ne[0]); -  gcry_mpi_release (ne[1]); -  gcry_mpi_release (r_e); -  rsa_blinding_key_free (bkey); - -  *buf_size = numeric_mpi_alloc_n_print (data_r_e, -                                         (char **) buf); -  gcry_mpi_release (data_r_e); - -  return GNUNET_YES; - -rsa_gcd_validate_failure: -  /* We know the RSA key is malicious here, so warn the wallet. */ -  /* GNUNET_break_op (0); */ -  gcry_mpi_release (ne[0]); -  gcry_mpi_release (ne[1]); -  *buf = NULL; -  *buf_size = 0; -  return GNUNET_NO; -#endif  } @@ -670,82 +320,9 @@ TALER_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,                     const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,                     struct GNUNET_CRYPTO_RsaPublicKey *pkey)  { -#if USE_GNUNET_RSA_BLINDING    return GNUNET_CRYPTO_rsa_unblind (sig,                                      bks,                                      pkey); -#else -  struct RsaBlindingKey *bkey; -  gcry_mpi_t n; -  gcry_mpi_t s; -  gcry_mpi_t r_inv; -  gcry_mpi_t ubsig; -  int ret; -  struct GNUNET_CRYPTO_RsaSignature *sret; - -  ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); -  if (0 != ret) -    ret = key_from_sexp (&n, pkey->sexp, "rsa", "n"); -  if (0 != ret) -  { -    GNUNET_break_op (0); -    return NULL; -  } -  ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); -  if (0 != ret) -    ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); -  if (0 != ret) -  { -    gcry_mpi_release (n); -    GNUNET_break_op (0); -    return NULL; -  } - -  bkey = rsa_blinding_key_derive (pkey, bks); -  if (NULL == bkey) -  { -    /* RSA key is malicious since rsa_gcd_validate failed here. -     * It should have failed during GNUNET_CRYPTO_rsa_blind too though, -     * so the exchange is being malicious in an unfamilair way, maybe -     * just trying to crash us.  */ -    GNUNET_break_op (0); -    gcry_mpi_release (n); -    gcry_mpi_release (s); -    return NULL; -  } - -  r_inv = gcry_mpi_new (0); -  if (1 != -      gcry_mpi_invm (r_inv, -                     bkey->r, -                     n)) -  { -    /* We cannot find r mod n, so gcd(r,n) != 1, which should get * -    * caught above, but we handle it the same here.              */ -    GNUNET_break_op (0); -    gcry_mpi_release (r_inv); -    rsa_blinding_key_free (bkey); -    gcry_mpi_release (n); -    gcry_mpi_release (s); -    return NULL; -  } - -  ubsig = gcry_mpi_new (0); -  gcry_mpi_mulm (ubsig, s, r_inv, n); -  gcry_mpi_release (n); -  gcry_mpi_release (r_inv); -  gcry_mpi_release (s); -  rsa_blinding_key_free (bkey); - -  sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); -  GNUNET_assert (0 == -                 gcry_sexp_build (&sret->sexp, -                                  NULL, -                                  "(sig-val (rsa (s %M)))", -                                  ubsig)); -  gcry_mpi_release (ubsig); -  return sret; -#endif  }  | 
