[cryptography] blinding is in libgcrypt but NOT in gnupg?

Jake jake at spaz.org
Thu Aug 22 23:56:53 EDT 2013


as you all know, I have been trying to find blinding for GnuPG, and 
someone to help implement it as a seperate (external) operation.

I was told that blinding was used in RSA decryption to repel timing 
attacks.  But I couldn't find it anywhere in the GnuPG source code.

   /* 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.  */

I found it in libgcrypt.  I don't understand why it's not in gnupg.
It looks to my untrained eye that gnupg and libgcrypt had a common 
ancestor, but i'm not sure when that was.  Anyway, here is what I found.

Does anyone have any idea why it's not in gnupg, and is that a problem? 
Does anyone want to help me merge it in and get it reviewed and pulled?

from libgcrypt-1.5.0/cipher/rsa.c (NOT present in gnupg/cipher/rsa.c)

/* 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;
}

static gcry_err_code_t
rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
              gcry_mpi_t *skey, int flags)
{
   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.  */

   (void)algo;

   /* 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. */

   y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));

   /* 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))
     {
       /* 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
          following test fails, thus we do not add code to release
          allocated resources.  */
       if (!gcry_mpi_invm (ri, r, sk.n))
         return GPG_ERR_INTERNAL;
     }

   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
     x = rsa_blind (data[0], r, sk.e, sk.n);
   else
     x = data[0];

   /* Do the encryption.  */
   secret (y, x, &sk);

   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);

       gcry_mpi_release (a);
     }

   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
     {
       /* Deallocate resources needed for blinding.  */
       gcry_mpi_release (x);
       gcry_mpi_release (r);
       gcry_mpi_release (ri);
     }

   /* Copy out result.  */
   *result = y;

   return GPG_ERR_NO_ERROR;
}


More information about the cryptography mailing list