Commit message: None
CVE: CVE-2017-7526
CWE: CWE-310
Vulnerability description: libgcrypt before version 1.7.8 is vulnerable to a cache side-channel attack resulting into a complete break of RSA-1024 while using the left-to-right method for computing the sliding-window expansion. The same attack is believed to work on RSA-2048 with moderately more computation. This side-channel requires that attacker can run arbitrary software on the hardware where the private RSA key is used.

Project: gnupg
File: rsa.c

check_exponent (void *arg, gcry_mpi_t a)
{
  gcry_mpi_t e = arg;
  gcry_mpi_t tmp;
  int result;

  mpi_sub_ui (a, a, 1);
  tmp = _gcry_mpi_alloc_like (a);
  result = !mpi_gcd(tmp, e, a); /* GCD is not 1. */
  _gcry_mpi_release (tmp);
  mpi_add_ui (a, a, 1);
  return result;
}

Project: gnupg
File: rsa.c

check_secret_key( RSA_secret_key *sk )
{
  int rc;
  gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );

  mpi_mul(temp, sk->p, sk->q );
  rc = mpi_cmp( temp, sk->n );
  mpi_free(temp);
  return !rc;
}

Project: gnupg
File: rsa.c

compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
{
  gcry_sexp_t l1;
  const char *data;
  size_t datalen;

  l1 = sexp_find_token (keyparam, "n", 1);
  if (!l1)
    return GPG_ERR_NO_OBJ;

  data = sexp_nth_data (l1, 1, &datalen);
  if (!data)
    {
      sexp_release (l1);
      return GPG_ERR_NO_OBJ;
    }

  _gcry_md_write (md, data, datalen);
  sexp_release (l1);

  return 0;
}

Project: gnupg
File: rsa.c

extract_a_from_sexp (gcry_sexp_t encr_data)
{
  gcry_sexp_t l1, l2, l3;
  gcry_mpi_t a_value;

  l1 = sexp_find_token (encr_data, "enc-val", 0);
  if (!l1)
    return NULL;
  l2 = sexp_find_token (l1, "rsa", 0);
  sexp_release (l1);
  if (!l2)
    return NULL;
  l3 = sexp_find_token (l2, "a", 0);
  sexp_release (l2);
  if (!l3)
    return NULL;
  a_value = sexp_nth_mpi (l3, 1, 0);
  sexp_release (l3);

  return a_value;
}

Project: gnupg
File: rsa.c

gen_x931_parm_xp (unsigned int nbits)
{
  gcry_mpi_t xp;

  xp = mpi_snew (nbits);
  _gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM);

  /* The requirement for Xp is:

       sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1

     We set the two high order bits to 1 to satisfy the lower bound.
     By using mpi_set_highbit we make sure that the upper bound is
     satisfied as well.  */
  mpi_set_highbit (xp, nbits-1);
  mpi_set_bit (xp, nbits-2);
  gcry_assert ( mpi_get_nbits (xp) == nbits );

  return xp;
}

Project: gnupg
File: rsa.c

generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
               gcry_sexp_t testparms, int transient_key)
{
  gcry_mpi_t p, q; /* the two primes */
  gcry_mpi_t d;    /* the private key */
  gcry_mpi_t u;
  gcry_mpi_t p1, q1;
  gcry_mpi_t n;    /* the public key */
  gcry_mpi_t e;    /* the exponent */
  gcry_mpi_t g;
  gcry_mpi_t minp;
  gcry_mpi_t diff, mindiff;
  gcry_random_level_t random_level;
  unsigned int pbits = nbits/2;
  unsigned int i;
  int pqswitch;
  gpg_err_code_t ec = GPG_ERR_NO_PRIME;

  if (nbits < 1024 || (nbits & 0x1FF))
    return GPG_ERR_INV_VALUE;
  if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072)
      return GPG_ERR_INV_VALUE;

  /* The random quality depends on the transient_key flag.  */
  random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;

  if (testparms)
    {
      /* Parameters to derive the key are given.  */
      /* Note that we explicitly need to setup the values of tbl
         because some compilers (e.g. OpenWatcom, IRIX) don't allow to
         initialize a structure with automatic variables.  */
      struct { const char *name; gcry_mpi_t *value; } tbl[] = {
        { "e" },
        { "p" },
        { "q" },
        { NULL }
      };
      int idx;
      gcry_sexp_t oneparm;

      tbl[0].value = &e;
      tbl[1].value = &p;
      tbl[2].value = &q;

      for (idx=0; tbl[idx].name; idx++)
        {
          oneparm = sexp_find_token (testparms, tbl[idx].name, 0);
          if (oneparm)
            {
              *tbl[idx].value = sexp_nth_mpi (oneparm, 1, GCRYMPI_FMT_USG);
              sexp_release (oneparm);
            }
        }
      for (idx=0; tbl[idx].name; idx++)
        if (!*tbl[idx].value)
          break;
      if (tbl[idx].name)
        {
          /* At least one parameter is missing.  */
          for (idx=0; tbl[idx].name; idx++)
            _gcry_mpi_release (*tbl[idx].value);
          return GPG_ERR_MISSING_VALUE;
        }
    }
  else
    {
      if (use_e < 65537)
        use_e = 65537;  /* This is the smallest value allowed by FIPS */

      e = mpi_alloc ((32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB);

      use_e |= 1; /* make sure this is odd */
      mpi_set_ui (e, use_e);

      p = mpi_snew (pbits);
      q = mpi_snew (pbits);
    }

  n = mpi_new (nbits);
  d = mpi_snew (nbits);
  u = mpi_snew (nbits);

  /* prepare approximate minimum p and q */
  minp = mpi_new (pbits);
  mpi_set_ui (minp, 0xB504F334);
  mpi_lshift (minp, minp, pbits - 32);

  /* prepare minimum p and q difference */
  diff = mpi_new (pbits);
  mindiff = mpi_new (pbits - 99);
  mpi_set_ui (mindiff, 1);
  mpi_lshift (mindiff, mindiff, pbits - 100);

  p1 = mpi_snew (pbits);
  q1 = mpi_snew (pbits);
  g  = mpi_snew (pbits);

 retry:
  /* generate p and q */
  for (i = 0; i < 5 * pbits; i++)
    {
    ploop:
      if (!testparms)
        {
          _gcry_mpi_randomize (p, pbits, random_level);
        }
      if (mpi_cmp (p, minp) < 0)
        {
          if (testparms)
            goto err;
          goto ploop;
        }

      mpi_sub_ui (p1, p, 1);
      if (mpi_gcd (g, p1, e))
        {
          if (_gcry_fips186_4_prime_check (p, pbits) != GPG_ERR_NO_ERROR)
            {
              /* not a prime */
              if (testparms)
                goto err;
            }
          else
            break;
        }
      else if (testparms)
        goto err;
    }
  if (i >= 5 * pbits)
    goto err;

  for (i = 0; i < 5 * pbits; i++)
    {
    qloop:
      if (!testparms)
        {
          _gcry_mpi_randomize (q, pbits, random_level);
        }
      if (mpi_cmp (q, minp) < 0)
        {
          if (testparms)
            goto err;
          goto qloop;
        }
      if (mpi_cmp (p, q) > 0)
        {
          pqswitch = 1;
          mpi_sub (diff, p, q);
        }
      else
        {
          pqswitch = 0;
          mpi_sub (diff, q, p);
        }
      if (mpi_cmp (diff, mindiff) < 0)
        {
          if (testparms)
            goto err;
          goto qloop;
        }

      mpi_sub_ui (q1, q, 1);
      if (mpi_gcd (g, q1, e))
        {
          if (_gcry_fips186_4_prime_check (q, pbits) != GPG_ERR_NO_ERROR)
            {
              /* not a prime */
              if (testparms)
                goto err;
            }
          else
            break;
        }
      else if (testparms)
        goto err;
    }
  if (i >= 5 * pbits)
    goto err;

  if (testparms)
    {
      mpi_clear (p);
      mpi_clear (q);
    }
  else
    {
      gcry_mpi_t f;

      if (pqswitch)
        {
          gcry_mpi_t tmp;

          tmp = p;
          p = q;
          q = tmp;
        }

      f = mpi_snew (nbits);

      /* calculate the modulus */
      mpi_mul (n, p, q);

      /* calculate the secret key d = e^1 mod phi */
      mpi_gcd (g, p1, q1);
      mpi_fdiv_q (f, p1, g);
      mpi_mul (f, f, q1);

      mpi_invm (d, e, f);

      _gcry_mpi_release (f);

      if (mpi_get_nbits (d) < pbits)
        goto retry;

      /* calculate the inverse of p and q (used for chinese remainder theorem)*/
      mpi_invm (u, p, q );
    }

  ec = 0;

  if (DBG_CIPHER)
    {
      log_mpidump("  p= ", p );
      log_mpidump("  q= ", q );
      log_mpidump("  n= ", n );
      log_mpidump("  e= ", e );
      log_mpidump("  d= ", d );
      log_mpidump("  u= ", u );
    }

 err:

  _gcry_mpi_release (p1);
  _gcry_mpi_release (q1);
  _gcry_mpi_release (g);
  _gcry_mpi_release (minp);
  _gcry_mpi_release (mindiff);
  _gcry_mpi_release (diff);

  sk->n = n;
  sk->e = e;
  sk->p = p;
  sk->q = q;
  sk->d = d;
  sk->u = u;

  /* Now we can test our keys. */
  if (ec || (!testparms && 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;
      if (!ec)
        {
          fips_signal_error ("self-test after key generation failed");
          return GPG_ERR_SELFTEST_FAILED;
        }
    }

  return ec;
}

Project: gnupg
File: rsa.c

generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
              int transient_key)
{
  gcry_mpi_t p, q; /* the two primes */
  gcry_mpi_t d;    /* the private key */
  gcry_mpi_t u;
  gcry_mpi_t t1, t2;
  gcry_mpi_t n;    /* the public key */
  gcry_mpi_t e;    /* the exponent */
  gcry_mpi_t phi;  /* helper: (p-1)(q-1) */
  gcry_mpi_t g;
  gcry_mpi_t f;
  gcry_random_level_t random_level;

  if (fips_mode ())
    {
      if (nbits < 1024)
        return GPG_ERR_INV_VALUE;
      if (transient_key)
        return GPG_ERR_INV_VALUE;
    }

  /* The random quality depends on the transient_key flag.  */
  random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;

  /* Make sure that nbits is even so that we generate p, q of equal size. */
  if ( (nbits&1) )
    nbits++;

  if (use_e == 1)   /* Alias for a secure value */
    use_e = 65537;  /* as demanded by Sphinx. */

  /* Public exponent:
     In general we use 41 as this is quite fast and more secure than the
     commonly used 17.  Benchmarking the RSA verify function
     with a 1024 bit key yields (2001-11-08):
     e=17    0.54 ms
     e=41    0.75 ms
     e=257   0.95 ms
     e=65537 1.80 ms
  */
  e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
  if (!use_e)
    mpi_set_ui (e, 41);     /* This is a reasonable secure and fast value */
  else
    {
      use_e |= 1; /* make sure this is odd */
      mpi_set_ui (e, use_e);
    }

  n = mpi_new (nbits);

  p = q = NULL;
  do
    {
      /* select two (very secret) primes */
      if (p)
        _gcry_mpi_release (p);
      if (q)
        _gcry_mpi_release (q);
      if (use_e)
        { /* Do an extra test to ensure that the given exponent is
             suitable. */
          p = _gcry_generate_secret_prime (nbits/2, random_level,
                                           check_exponent, e);
          q = _gcry_generate_secret_prime (nbits/2, random_level,
                                           check_exponent, e);
        }
      else
        { /* We check the exponent later. */
          p = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
          q = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
        }
      if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/
        mpi_swap(p,q);
      /* calculate the modulus */
      mpi_mul( n, p, q );
    }
  while ( mpi_get_nbits(n) != nbits );

  /* calculate Euler totient: phi = (p-1)(q-1) */
  t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
  t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
  phi   = mpi_snew ( nbits );
  g	= mpi_snew ( nbits );
  f	= mpi_snew ( nbits );
  mpi_sub_ui( t1, p, 1 );
  mpi_sub_ui( t2, q, 1 );
  mpi_mul( phi, t1, t2 );
  mpi_gcd (g, t1, t2);
  mpi_fdiv_q(f, phi, g);

  while (!mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
    {
      if (use_e)
        BUG (); /* The prime generator already made sure that we
                   never can get to here. */
      mpi_add_ui (e, e, 2);
    }

  /* calculate the secret key d = e^-1 mod phi */
  d = mpi_snew ( nbits );
  mpi_invm (d, e, f );
  /* calculate the inverse of p and q (used for chinese remainder theorem)*/
  u = mpi_snew ( nbits );
  mpi_invm(u, p, q );

  if( DBG_CIPHER )
    {
      log_mpidump("  p= ", p );
      log_mpidump("  q= ", q );
      log_mpidump("phi= ", phi );
      log_mpidump("  g= ", g );
      log_mpidump("  f= ", f );
      log_mpidump("  n= ", n );
      log_mpidump("  e= ", e );
      log_mpidump("  d= ", d );
      log_mpidump("  u= ", u );
    }

  _gcry_mpi_release (t1);
  _gcry_mpi_release (t2);
  _gcry_mpi_release (phi);
  _gcry_mpi_release (f);
  _gcry_mpi_release (g);

  sk->n = n;
  sk->e = e;
  sk->p = p;
  sk->q = q;
  sk->d = d;
  sk->u = u;

  /* 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;
      fips_signal_error ("self-test after key generation failed");
      return GPG_ERR_SELFTEST_FAILED;
    }

  return 0;
}

Project: gnupg
File: rsa.c

generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
               gcry_sexp_t deriveparms, int *swapped)
{
  gcry_mpi_t p, q; /* The two primes.  */
  gcry_mpi_t e;    /* The public exponent.  */
  gcry_mpi_t n;    /* The public key.  */
  gcry_mpi_t d;    /* The private key */
  gcry_mpi_t u;    /* The inverse of p and q.  */
  gcry_mpi_t pm1;  /* p - 1  */
  gcry_mpi_t qm1;  /* q - 1  */
  gcry_mpi_t phi;  /* Euler totient.  */
  gcry_mpi_t f, g; /* Helper.  */

  *swapped = 0;

  if (e_value == 1)   /* Alias for a secure value. */
    e_value = 65537;

  /* Point 1 of section 4.1:  k = 1024 + 256s with S >= 0  */
  if (nbits < 1024 || (nbits % 256))
    return GPG_ERR_INV_VALUE;

  /* Point 2:  2 <= bitlength(e) < 2^{k-2}
     Note that we do not need to check the upper bound because we use
     an unsigned long for E and thus there is no way for E to reach
     that limit.  */
  if (e_value < 3)
    return GPG_ERR_INV_VALUE;

  /* Our implementation requires E to be odd.  */
  if (!(e_value & 1))
    return GPG_ERR_INV_VALUE;

  /* Point 3:  e > 0 or e 0 if it is to be randomly generated.
     We support only a fixed E and thus there is no need for an extra test.  */


  /* Compute or extract the derive parameters.  */
  {
    gcry_mpi_t xp1 = NULL;
    gcry_mpi_t xp2 = NULL;
    gcry_mpi_t xp  = NULL;
    gcry_mpi_t xq1 = NULL;
    gcry_mpi_t xq2 = NULL;
    gcry_mpi_t xq  = NULL;
    gcry_mpi_t tmpval;

    if (!deriveparms)
      {
        /* Not given: Generate them.  */
        xp = gen_x931_parm_xp (nbits/2);
        /* Make sure that |xp - xq| > 2^{nbits - 100} holds.  */
        tmpval = mpi_snew (nbits/2);
        do
          {
            _gcry_mpi_release (xq);
            xq = gen_x931_parm_xp (nbits/2);
            mpi_sub (tmpval, xp, xq);
          }
        while (mpi_get_nbits (tmpval) <= (nbits/2 - 100));
        _gcry_mpi_release (tmpval);

        xp1 = gen_x931_parm_xi ();
        xp2 = gen_x931_parm_xi ();
        xq1 = gen_x931_parm_xi ();
        xq2 = gen_x931_parm_xi ();

      }
    else
      {
        /* Parameters to derive the key are given.  */
        /* Note that we explicitly need to setup the values of tbl
           because some compilers (e.g. OpenWatcom, IRIX) don't allow
           to initialize a structure with automatic variables.  */
        struct { const char *name; gcry_mpi_t *value; } tbl[] = {
          { "Xp1" },
          { "Xp2" },
          { "Xp"  },
          { "Xq1" },
          { "Xq2" },
          { "Xq"  },
          { NULL }
        };
        int idx;
        gcry_sexp_t oneparm;

        tbl[0].value = &xp1;
        tbl[1].value = &xp2;
        tbl[2].value = &xp;
        tbl[3].value = &xq1;
        tbl[4].value = &xq2;
        tbl[5].value = &xq;

        for (idx=0; tbl[idx].name; idx++)
          {
            oneparm = sexp_find_token (deriveparms, tbl[idx].name, 0);
            if (oneparm)
              {
                *tbl[idx].value = sexp_nth_mpi (oneparm, 1, GCRYMPI_FMT_USG);
                sexp_release (oneparm);
              }
          }
        for (idx=0; tbl[idx].name; idx++)
          if (!*tbl[idx].value)
            break;
        if (tbl[idx].name)
          {
            /* At least one parameter is missing.  */
            for (idx=0; tbl[idx].name; idx++)
              _gcry_mpi_release (*tbl[idx].value);
            return GPG_ERR_MISSING_VALUE;
          }
      }

    e = mpi_alloc_set_ui (e_value);

    /* Find two prime numbers.  */
    p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL);
    q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL);
    _gcry_mpi_release (xp);  xp  = NULL;
    _gcry_mpi_release (xp1); xp1 = NULL;
    _gcry_mpi_release (xp2); xp2 = NULL;
    _gcry_mpi_release (xq);  xq  = NULL;
    _gcry_mpi_release (xq1); xq1 = NULL;
    _gcry_mpi_release (xq2); xq2 = NULL;
    if (!p || !q)
      {
        _gcry_mpi_release (p);
        _gcry_mpi_release (q);
        _gcry_mpi_release (e);
        return GPG_ERR_NO_PRIME;
      }
  }


  /* Compute the public modulus.  We make sure that p is smaller than
     q to allow the use of the CRT.  */
  if (mpi_cmp (p, q) > 0 )
    {
      mpi_swap (p, q);
      *swapped = 1;
    }
  n = mpi_new (nbits);
  mpi_mul (n, p, q);

  /* Compute the Euler totient:  phi = (p-1)(q-1)  */
  pm1 = mpi_snew (nbits/2);
  qm1 = mpi_snew (nbits/2);
  phi = mpi_snew (nbits);
  mpi_sub_ui (pm1, p, 1);
  mpi_sub_ui (qm1, q, 1);
  mpi_mul (phi, pm1, qm1);

  g = mpi_snew (nbits);
  gcry_assert (mpi_gcd (g, e, phi));

  /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
  mpi_gcd (g, pm1, qm1);
  f = pm1; pm1 = NULL;
  _gcry_mpi_release (qm1); qm1 = NULL;
  mpi_fdiv_q (f, phi, g);
  _gcry_mpi_release (phi); phi = NULL;
  d = g; g = NULL;
  /* Compute the secret key:  d = e^{-1} mod lcm(p-1,q-1) */
  mpi_invm (d, e, f);

  /* Compute the inverse of p and q.  */
  u = f; f = NULL;
  mpi_invm (u, p, q );

  if( DBG_CIPHER )
    {
      if (*swapped)
        log_debug ("p and q are swapped\n");
      log_mpidump("  p", p );
      log_mpidump("  q", q );
      log_mpidump("  n", n );
      log_mpidump("  e", e );
      log_mpidump("  d", d );
      log_mpidump("  u", u );
    }


  sk->n = n;
  sk->e = e;
  sk->p = p;
  sk->q = q;
  sk->d = d;
  sk->u = u;

  /* 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;
      fips_signal_error ("self-test after key generation failed");
      return GPG_ERR_SELFTEST_FAILED;
    }

  return 0;
}

Project: gnupg
File: rsa.c

rsa_check_secret_key (gcry_sexp_t keyparms)
{
  gcry_err_code_t rc;
  RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};

  /* To check the key we need the optional parameters. */
  rc = sexp_extract_param (keyparms, NULL, "nedpqu",
                           &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
                           NULL);
  if (rc)
    goto leave;

  if (!check_secret_key (&sk))
    rc = GPG_ERR_BAD_SECKEY;

 leave:
  _gcry_mpi_release (sk.n);
  _gcry_mpi_release (sk.e);
  _gcry_mpi_release (sk.d);
  _gcry_mpi_release (sk.p);
  _gcry_mpi_release (sk.q);
  _gcry_mpi_release (sk.u);
  if (DBG_CIPHER)
    log_debug ("rsa_testkey    => %s\n", gpg_strerror (rc));
  return rc;
}

Project: gnupg
File: rsa.c

rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)

{
  gpg_err_code_t rc;
  struct pk_encoding_ctx ctx;
  gcry_sexp_t l1 = NULL;
  gcry_mpi_t data = NULL;
  RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
  gcry_mpi_t plain = NULL;
  unsigned char *unpad = NULL;
  size_t unpadlen = 0;

  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
                                   rsa_get_nbits (keyparms));

  /* Extract the data.  */
  rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx);
  if (rc)
    goto leave;
  rc = sexp_extract_param (l1, NULL, "a", &data, NULL);
  if (rc)
    goto leave;
  if (DBG_CIPHER)
    log_printmpi ("rsa_decrypt data", data);
  if (mpi_is_opaque (data))
    {
      rc = GPG_ERR_INV_DATA;
      goto leave;
    }

  /* Extract the key.  */
  rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?",
                           &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
                           NULL);
  if (rc)
    goto leave;
  if (DBG_CIPHER)
    {
      log_printmpi ("rsa_decrypt    n", sk.n);
      log_printmpi ("rsa_decrypt    e", sk.e);
      if (!fips_mode ())
        {
          log_printmpi ("rsa_decrypt    d", sk.d);
          log_printmpi ("rsa_decrypt    p", sk.p);
          log_printmpi ("rsa_decrypt    q", sk.q);
          log_printmpi ("rsa_decrypt    u", sk.u);
        }
    }

  /* Better make sure that there are no superfluous leading zeroes in
     the input and it has not been "padded" using multiples of N.
     This mitigates side-channel attacks (CVE-2013-4576).  */
  mpi_normalize (data);
  mpi_fdiv_r (data, data, sk.n);

  /* Allocate MPI for the plaintext.  */
  plain = mpi_snew (ctx.nbits);

  /* 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 ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
    secret (plain, data, &sk);
  else
    secret_blinded (plain, data, &sk, ctx.nbits);

  if (DBG_CIPHER)
    log_printmpi ("rsa_decrypt  res", plain);

  /* Reverse the encoding and build the s-expression.  */
  switch (ctx.encoding)
    {
    case PUBKEY_ENC_PKCS1:
      rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
      mpi_free (plain);
      plain = NULL;
      if (!rc)
        rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
      break;

    case PUBKEY_ENC_OAEP:
      rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
                                  ctx.nbits, ctx.hash_algo,
                                  plain, ctx.label, ctx.labellen);
      mpi_free (plain);
      plain = NULL;
      if (!rc)
        rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
      break;

    default:
      /* Raw format.  For backward compatibility we need to assume a
         signed mpi by using the sexp format string "%m".  */
      rc = sexp_build (r_plain, NULL,
                       (ctx.flags & PUBKEY_FLAG_LEGACYRESULT)
                       ? "%m":"(value %m)", plain);
      break;
    }

 leave:
  xfree (unpad);
  _gcry_mpi_release (plain);
  _gcry_mpi_release (sk.n);
  _gcry_mpi_release (sk.e);
  _gcry_mpi_release (sk.d);
  _gcry_mpi_release (sk.p);
  _gcry_mpi_release (sk.q);
  _gcry_mpi_release (sk.u);
  _gcry_mpi_release (data);
  sexp_release (l1);
  _gcry_pk_util_free_encoding_ctx (&ctx);
  if (DBG_CIPHER)
    log_debug ("rsa_decrypt    => %s\n", gpg_strerror (rc));
  return rc;
}

Project: gnupg
File: rsa.c

rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
{
  gpg_err_code_t ec;
  unsigned int nbits;
  unsigned long evalue;
  RSA_secret_key sk;
  gcry_sexp_t deriveparms;
  int flags = 0;
  gcry_sexp_t l1;
  gcry_sexp_t swap_info = NULL;

  memset (&sk, 0, sizeof sk);

  ec = _gcry_pk_util_get_nbits (genparms, &nbits);
  if (ec)
    return ec;

  ec = _gcry_pk_util_get_rsa_use_e (genparms, &evalue);
  if (ec)
    return ec;

  /* Parse the optional flags list.  */
  l1 = sexp_find_token (genparms, "flags", 0);
  if (l1)
    {
      ec = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
      sexp_release (l1);
      if (ec)
        return ec;
    }

  deriveparms = (genparms?
                 sexp_find_token (genparms, "derive-parms", 0) : NULL);
  if (!deriveparms)
    {
      /* Parse the optional "use-x931" flag. */
      l1 = sexp_find_token (genparms, "use-x931", 0);
      if (l1)
        {
          flags |= PUBKEY_FLAG_USE_X931;
          sexp_release (l1);
        }
    }

  if (deriveparms || (flags & PUBKEY_FLAG_USE_X931))
    {
      int swapped;
      ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
      sexp_release (deriveparms);
      if (!ec && swapped)
        ec = sexp_new (&swap_info, "(misc-key-info(p-q-swapped))", 0, 1);
    }
  else
    {
      /* Parse the optional "transient-key" flag. */
      if (!(flags & PUBKEY_FLAG_TRANSIENT_KEY))
        {
          l1 = sexp_find_token (genparms, "transient-key", 0);
          if (l1)
            {
              flags |= PUBKEY_FLAG_TRANSIENT_KEY;
              sexp_release (l1);
            }
        }
      deriveparms = (genparms? sexp_find_token (genparms, "test-parms", 0)
                     /**/    : NULL);

      /* Generate.  */
      if (deriveparms || fips_mode())
        {
          ec = generate_fips (&sk, nbits, evalue, deriveparms,
                              !!(flags & PUBKEY_FLAG_TRANSIENT_KEY));
        }
      else
        {
          ec = generate_std (&sk, nbits, evalue,
                             !!(flags & PUBKEY_FLAG_TRANSIENT_KEY));
        }
      sexp_release (deriveparms);
    }

  if (!ec)
    {
      ec = sexp_build (r_skey, NULL,
                       "(key-data"
                       " (public-key"
                       "  (rsa(n%m)(e%m)))"
                       " (private-key"
                       "  (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"
                       " %S)",
                       sk.n, sk.e,
                       sk.n, sk.e, sk.d, sk.p, sk.q, sk.u,
                       swap_info);
    }

  mpi_free (sk.n);
  mpi_free (sk.e);
  mpi_free (sk.p);
  mpi_free (sk.q);
  mpi_free (sk.d);
  mpi_free (sk.u);
  sexp_release (swap_info);

  return ec;
}

Project: gnupg
File: rsa.c

rsa_get_nbits (gcry_sexp_t parms)
{
  gcry_sexp_t l1;
  gcry_mpi_t n;
  unsigned int nbits;

  l1 = sexp_find_token (parms, "n", 1);
  if (!l1)
    return 0; /* Parameter N not found.  */

  n = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
  sexp_release (l1);
  nbits = n? mpi_get_nbits (n) : 0;
  _gcry_mpi_release (n);
  return nbits;
}

Project: gnupg
File: rsa.c

rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
  gcry_err_code_t rc;
  struct pk_encoding_ctx ctx;
  gcry_sexp_t l1 = NULL;
  gcry_mpi_t sig = NULL;
  gcry_mpi_t data = NULL;
  RSA_public_key pk = { NULL, NULL };
  gcry_mpi_t result = NULL;

  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
                                   rsa_get_nbits (keyparms));

  /* Extract the data.  */
  rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
  if (rc)
    goto leave;
  if (DBG_CIPHER)
    log_printmpi ("rsa_verify data", data);
  if (mpi_is_opaque (data))
    {
      rc = GPG_ERR_INV_DATA;
      goto leave;
    }

  /* Extract the signature value.  */
  rc = _gcry_pk_util_preparse_sigval (s_sig, rsa_names, &l1, NULL);
  if (rc)
    goto leave;
  rc = sexp_extract_param (l1, NULL, "s", &sig, NULL);
  if (rc)
    goto leave;
  if (DBG_CIPHER)
    log_printmpi ("rsa_verify  sig", sig);

  /* Extract the key.  */
  rc = sexp_extract_param (keyparms, NULL, "ne", &pk.n, &pk.e, NULL);
  if (rc)
    goto leave;
  if (DBG_CIPHER)
    {
      log_printmpi ("rsa_verify    n", pk.n);
      log_printmpi ("rsa_verify    e", pk.e);
    }

  /* Do RSA computation and compare.  */
  result = mpi_new (0);
  public (result, sig, &pk);
  if (DBG_CIPHER)
    log_printmpi ("rsa_verify  cmp", result);
  if (ctx.verify_cmp)
    rc = ctx.verify_cmp (&ctx, result);
  else
    rc = mpi_cmp (result, data) ? GPG_ERR_BAD_SIGNATURE : 0;

 leave:
  _gcry_mpi_release (result);
  _gcry_mpi_release (pk.n);
  _gcry_mpi_release (pk.e);
  _gcry_mpi_release (data);
  _gcry_mpi_release (sig);
  sexp_release (l1);
  _gcry_pk_util_free_encoding_ctx (&ctx);
  if (DBG_CIPHER)
    log_debug ("rsa_verify    => %s\n", rc?gpg_strerror (rc):"Good");
  return rc;
}

Project: gnupg
File: rsa.c

secret_blinded (gcry_mpi_t output, gcry_mpi_t input,
                RSA_secret_key *sk, unsigned int nbits)
{
  gcry_mpi_t r;	           /* Random number needed for blinding.  */
  gcry_mpi_t ri;	   /* Modular multiplicative inverse of r.  */
  gcry_mpi_t bldata;       /* Blinded data to decrypt.  */

  /* 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  = mpi_snew (nbits);
  ri = mpi_snew (nbits);
  bldata = mpi_snew (nbits);

  do
    {
      _gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM);
      mpi_mod (r, r, sk->n);
    }
  while (!mpi_invm (ri, r, sk->n));

  /* Do blinding.  We calculate: y = (x * r^e) mod n, where r is the
   * random number, e is the public exponent, x is the non-blinded
   * input data and n is the RSA modulus.  */
  mpi_powm (bldata, r, sk->e, sk->n);
  mpi_mulm (bldata, bldata, input, sk->n);

  /* Perform decryption.  */
  secret (output, bldata, sk);
  _gcry_mpi_release (bldata);

  /* Undo blinding.  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.  */
  mpi_mulm (output, output, ri, sk->n);

  _gcry_mpi_release (r);
  _gcry_mpi_release (ri);
}

Project: gnupg
File: rsa.c

secret_core_std (gcry_mpi_t M, gcry_mpi_t C,
                 gcry_mpi_t D, gcry_mpi_t N)
{
  mpi_powm (M, C, D, N);
}

Project: gnupg
File: rsa.c

selftest_encr_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
{
  const char *errtxt = NULL;
  gcry_error_t err;
  static const char plaintext[] =
    "Jim quickly realized that the beautiful gowns are expensive.";
  gcry_sexp_t plain = NULL;
  gcry_sexp_t encr  = NULL;
  gcry_mpi_t  ciphertext = NULL;
  gcry_sexp_t decr  = NULL;
  char *decr_plaintext = NULL;
  gcry_sexp_t tmplist = NULL;
  /* expected result of encrypting the plaintext with sample_secret_key */
  static const char ref_data[] =
    "18022e2593a402a737caaa93b4c7e750e20ca265452980e1d6b7710fbd3e"
    "7dce72be5c2110fb47691cb38f42170ee3b4a37f2498d4a51567d762585e"
    "4cb81d04fbc7df4144f8e5eac2d4b8688521b64011f11d7ad53f4c874004"
    "819856f2e2a6f83d1c9c4e73ac26089789c14482b0b8d44139133c88c4a5"
    "2dba9dd6d6ffc622666b7d129168333d999706af30a2d7d272db7734e5ed"
    "fb8c64ea3018af3ad20f4a013a5060cb0f5e72753967bebe294280a6ed0d"
    "dbd3c4f11d0a8696e9d32a0dc03deb0b5e49b2cbd1503392642d4e1211f3"
    "e8e2ee38abaa3671ccd57fcde8ca76e85fd2cb77c35706a970a213a27352"
    "cec92a9604d543ddb5fc478ff50e0622";
  gcry_mpi_t ref_mpi = NULL;

  /* Put the plaintext into an S-expression.  */
  err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext);
  if (err)
    {
      errtxt = "converting data failed";
      goto leave;
    }

  /* Encrypt.  */
  err = _gcry_pk_encrypt (&encr, plain, pkey);
  if (err)
    {
      errtxt = "encrypt failed";
      goto leave;
    }

  err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
  if (err)
    {
      errtxt = "converting encrydata to mpi failed";
      goto leave;
    }

  /* Extraxt the ciphertext from the returned S-expression.  */
  /*sexp_dump (encr);*/
  ciphertext = extract_a_from_sexp (encr);
  if (!ciphertext)
    {
      errtxt = "gcry_pk_decrypt returned garbage";
      goto leave;
    }

  /* Check that the ciphertext does no match the plaintext.  */
  /* _gcry_log_printmpi ("plaintext", plaintext); */
  /* _gcry_log_printmpi ("ciphertxt", ciphertext); */
  if (mpi_cmp (ref_mpi, ciphertext))
    {
      errtxt = "ciphertext doesn't match reference data";
      goto leave;
    }

  /* Decrypt.  */
  err = _gcry_pk_decrypt (&decr, encr, skey);
  if (err)
    {
      errtxt = "decrypt failed";
      goto leave;
    }

  /* Extract the decrypted data from the S-expression.  Note that the
     output of gcry_pk_decrypt depends on whether a flags lists occurs
     in its input data.  Because we passed the output of
     gcry_pk_encrypt directly to gcry_pk_decrypt, such a flag value
     won't be there as of today.  To be prepared for future changes we
     take care of it anyway.  */
  tmplist = sexp_find_token (decr, "value", 0);
  if (tmplist)
    decr_plaintext = sexp_nth_string (tmplist, 1);
  else
    decr_plaintext = sexp_nth_string (decr, 0);
  if (!decr_plaintext)
    {
      errtxt = "decrypt returned no plaintext";
      goto leave;
    }

  /* Check that the decrypted plaintext matches the original  plaintext.  */
  if (strcmp (plaintext, decr_plaintext))
    {
      errtxt = "mismatch";
      goto leave;
    }

 leave:
  sexp_release (tmplist);
  xfree (decr_plaintext);
  sexp_release (decr);
  _gcry_mpi_release (ciphertext);
  _gcry_mpi_release (ref_mpi);
  sexp_release (encr);
  sexp_release (plain);
  return errtxt;
}

Project: gnupg
File: rsa.c

selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
{
  static const char sample_data[] =
    "(data (flags pkcs1)"
    " (hash sha256 #11223344556677889900aabbccddeeff"
    /**/           "102030405060708090a0b0c0d0f01121#))";
  static const char sample_data_bad[] =
    "(data (flags pkcs1)"
    " (hash sha256 #11223344556677889900aabbccddeeff"
    /**/           "802030405060708090a0b0c0d0f01121#))";

  const char *errtxt = NULL;
  gcry_error_t err;
  gcry_sexp_t data = NULL;
  gcry_sexp_t data_bad = NULL;
  gcry_sexp_t sig = NULL;
  /* raw signature data reference */
  const char ref_data[] =
    "6252a19a11e1d5155ed9376036277193d644fa239397fff03e9b92d6f86415d6"
    "d30da9273775f290e580d038295ff8ff89522becccfa6ae870bf76b76df402a8"
    "54f69347e3db3de8e1e7d4dada281ec556810c7a8ecd0b5f51f9b1c0e7aa7557"
    "61aa2b8ba5f811304acc6af0eca41fe49baf33bf34eddaf44e21e036ac7f0b68"
    "03cdef1c60021fb7b5b97ebacdd88ab755ce29af568dbc5728cc6e6eff42618d"
    "62a0386ca8beed46402bdeeef29b6a3feded906bace411a06a39192bf516ae10"
    "67e4320fa8ea113968525f4574d022a3ceeaafdc41079efe1f22cc94bf59d8d3"
    "328085da9674857db56de5978a62394aab48aa3b72e23a1b16260cfd9daafe65";
  gcry_mpi_t ref_mpi = NULL;
  gcry_mpi_t sig_mpi = NULL;

  err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
  if (!err)
    err = sexp_sscan (&data_bad, NULL,
                      sample_data_bad, strlen (sample_data_bad));
  if (err)
    {
      errtxt = "converting data failed";
      goto leave;
    }

  err = _gcry_pk_sign (&sig, data, skey);
  if (err)
    {
      errtxt = "signing failed";
      goto leave;
    }

  err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
  if (err)
    {
      errtxt = "converting ref_data to mpi failed";
      goto leave;
    }

  err = _gcry_sexp_extract_param(sig, "sig-val!rsa", "s", &sig_mpi, NULL);
  if (err)
    {
      errtxt = "extracting signature data failed";
      goto leave;
    }

  if (mpi_cmp (sig_mpi, ref_mpi))
    {
      errtxt = "signature does not match reference data";
      goto leave;
    }

  err = _gcry_pk_verify (sig, data, pkey);
  if (err)
    {
      errtxt = "verify failed";
      goto leave;
    }
  err = _gcry_pk_verify (sig, data_bad, pkey);
  if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
    {
      errtxt = "bad signature not detected";
      goto leave;
    }


 leave:
  sexp_release (sig);
  sexp_release (data_bad);
  sexp_release (data);
  _gcry_mpi_release (ref_mpi);
  _gcry_mpi_release (sig_mpi);
  return errtxt;
}

Project: gnupg
File: rsa.c

test_keys (RSA_secret_key *sk, unsigned int nbits)
{
  int result = -1; /* Default to failure.  */
  RSA_public_key pk;
  gcry_mpi_t plaintext = mpi_new (nbits);
  gcry_mpi_t ciphertext = mpi_new (nbits);
  gcry_mpi_t decr_plaintext = mpi_new (nbits);
  gcry_mpi_t signature = mpi_new (nbits);

  /* Put the relevant parameters into a public key structure.  */
  pk.n = sk->n;
  pk.e = sk->e;

  /* 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 (!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 (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 (mpi_cmp (decr_plaintext, plaintext))
    goto leave; /* Signature does not match.  */

  /* Modify the signature and check that the signing fails.  */
  mpi_add_ui (signature, signature, 1);
  public (decr_plaintext, signature, &pk);
  if (!mpi_cmp (decr_plaintext, plaintext))
    goto leave; /* Signature matches but should not.  */

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