/**
 * This function will generate a new pair of prime and generator for use in
 * the Diffie-Hellman key exchange.
 * The bits value should be one of 768, 1024, 2048, 3072 or 4096.
 **/
static int dh_params_generate (unsigned int bits) {

    int result, times = 0, qbits;
    gcry_mpi_t *factors = NULL;
    gcry_error_t err;

    /* Version check should be the very first call because it
       makes sure that important subsystems are intialized. */
    if (!gcry_check_version (GCRYPT_VERSION)) {
        LOG(log_error, logtype_uams, "PAM DHX2: libgcrypt versions mismatch. Need: %s", GCRYPT_VERSION);
        result = AFPERR_MISC;
        goto error;
    }

    if (bits < 256)
        qbits = bits / 2;
    else
        qbits = (bits / 40) + 105;

    if (qbits & 1) /* better have an even number */
        qbits++;

    /* find a prime number of size bits. */
    do {
        if (times) {
            gcry_mpi_release(p);
            gcry_prime_release_factors (factors);
        }
        err = gcry_prime_generate(&p, bits, qbits, &factors, NULL, NULL,
                                  GCRY_STRONG_RANDOM, GCRY_PRIME_FLAG_SPECIAL_FACTOR);
        if (err != 0) {
            result = AFPERR_MISC;
            goto error;
        }
        err = gcry_prime_check(p, 0);
        times++;
    } while (err != 0 && times < 10);

    if (err != 0) {
        result = AFPERR_MISC;
        goto error;
    }

    /* generate the group generator. */
    err = gcry_prime_group_generator(&g, p, factors, NULL);
    if (err != 0) {
        result = AFPERR_MISC;
        goto error;
    }

    gcry_prime_release_factors(factors);

    return 0;

error:
    gcry_prime_release_factors(factors);

    return result;
}
Exemple #2
0
static void
check_primes (void)
{
  gcry_error_t err = GPG_ERR_NO_ERROR;
  gcry_mpi_t *factors = NULL;
  gcry_mpi_t prime = NULL;
  gcry_mpi_t g;
  unsigned int i = 0;
  struct prime_spec
  {
    unsigned int prime_bits;
    unsigned int factor_bits;
    unsigned int flags;
  } prime_specs[] =
    {
      { 1024, 100, GCRY_PRIME_FLAG_SPECIAL_FACTOR },
      { 128, 0, 0 },
      { 0 },
    };

  for (i = 0; prime_specs[i].prime_bits; i++)
    {
      err = gcry_prime_generate (&prime,
				 prime_specs[i].prime_bits,
				 prime_specs[i].factor_bits,
				 &factors,
				 NULL, NULL,
				 GCRY_WEAK_RANDOM,
				 prime_specs[i].flags);
      assert (! err);
      if (verbose)
        {
          fprintf (stderr, "test %d: p = ", i);
          gcry_mpi_dump (prime);
          putc ('\n', stderr);
        }

      err = gcry_prime_check (prime, 0);
      assert (! err);

      err = gcry_prime_group_generator (&g, prime, factors, NULL);
      assert (!err);
      gcry_prime_release_factors (factors); factors = NULL;
      
      if (verbose)
        {
          fprintf (stderr, "     %d: g = ", i);
          gcry_mpi_dump (g);
          putc ('\n', stderr);
        }
      gcry_mpi_release (g);


      gcry_mpi_add_ui (prime, prime, 1);
      err = gcry_prime_check (prime, 0);
      assert (err);
    }
}
Exemple #3
0
static int
wrap_gcry_generate_group (gnutls_group_st * group, unsigned int bits)
{
  gcry_mpi_t g = NULL, prime = NULL;
  gcry_error_t err;
  int times = 0, qbits;
  gcry_mpi_t *factors = NULL;

  /* Calculate the size of a prime factor of (prime-1)/2.
   * This is an emulation of the values in "Selecting Cryptographic Key Sizes" paper.
   */
  if (bits < 256)
    qbits = bits / 2;
  else
    {
      qbits = (bits / 40) + 105;
    }

  if (qbits & 1)		/* better have an even number */
    qbits++;

  /* find a prime number of size bits.
   */
  do
    {
      if (times)
	{
	  gcry_mpi_release (prime);
	  gcry_prime_release_factors (factors);
	}

      err = gcry_prime_generate (&prime, bits, qbits, &factors,
				 NULL, NULL, GCRY_STRONG_RANDOM,
				 GCRY_PRIME_FLAG_SPECIAL_FACTOR);
      if (err != 0)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      err = gcry_prime_check (prime, 0);

      times++;
    }
  while (err != 0 && times < 10);

  if (err != 0)
    {
      gnutls_assert ();
      gcry_mpi_release (prime);
      gcry_prime_release_factors (factors);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  /* generate the group generator.
   */
  err = gcry_prime_group_generator (&g, prime, factors, NULL);
  gcry_prime_release_factors (factors);
  if (err != 0)
    {
      gnutls_assert ();
      gcry_mpi_release (prime);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  group->g = g;
  group->p = prime;

  return 0;
}