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