/**************** * Returns: true if this may be a prime */ static int check_prime( MPI prime, MPI val_2 ) { int i; unsigned x; int count=0; /* check against small primes */ for(i=0; (x = small_prime_numbers[i]); i++ ) { if( mpi_divisible_ui( prime, x ) ) return 0; } /* a quick fermat test */ { MPI result = mpi_alloc_like( prime ); MPI pminus1 = mpi_alloc_like( prime ); mpi_sub_ui( pminus1, prime, 1); mpi_powm( result, val_2, pminus1, prime ); mpi_free( pminus1 ); if( mpi_cmp_ui( result, 1 ) ) { /* if composite */ mpi_free( result ); progress('.'); return 0; } mpi_free( result ); } /* perform stronger tests */ if( is_prime(prime, 5, &count ) ) return 1; /* is probably a prime */ progress('.'); return 0; }
int mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) { int divisor_sign = divisor->sign; MPI temp_divisor = NULL; if( quot == divisor || rem == divisor ) { if (mpi_copy( &temp_divisor, divisor ) < 0) return -ENOMEM; divisor = temp_divisor; } if (mpi_tdiv_qr( quot, rem, dividend, divisor ) < 0) goto nomem; if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { if (mpi_sub_ui( quot, quot, 1 ) < 0) goto nomem; if (mpi_add( rem, rem, divisor) < 0) goto nomem; } if( temp_divisor ) mpi_free(temp_divisor); return 0; nomem: mpi_free(temp_divisor); return -ENOMEM; }
/* Accessor for helper variable. */ static int ec_get_a_is_pminus3 (mpi_ec_t ec) { gcry_mpi_t tmp; if (!ec->t.valid.a_is_pminus3) { ec->t.valid.a_is_pminus3 = 1; tmp = mpi_alloc_like (ec->p); mpi_sub_ui (tmp, ec->p, 3); ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp); mpi_free (tmp); } return ec->t.a_is_pminus3; }
/**************** * Returns: true if this may be a prime */ static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, gcry_prime_check_func_t cb_func, void *cb_arg) { int i; unsigned int x; unsigned int count=0; /* Check against small primes. */ for (i=0; (x = small_prime_numbers[i]); i++ ) { if ( mpi_divisible_ui( prime, x ) ) return 0; } /* A quick Fermat test. */ { gcry_mpi_t result = mpi_alloc_like( prime ); gcry_mpi_t pminus1 = mpi_alloc_like( prime ); mpi_sub_ui( pminus1, prime, 1); gcry_mpi_powm( result, val_2, pminus1, prime ); mpi_free( pminus1 ); if ( mpi_cmp_ui( result, 1 ) ) { /* Is composite. */ mpi_free( result ); progress('.'); return 0; } mpi_free( result ); } if (!cb_func || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_MAYBE_PRIME, prime)) { /* Perform stronger tests. */ if ( is_prime( prime, 5, &count ) ) { if (!cb_func || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_GOT_PRIME, prime)) return 1; /* Probably a prime. */ } } progress('.'); return 0; }
void _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) { int divisor_sign = divisor->sign; gcry_mpi_t temp_divisor = NULL; if( quot == divisor || rem == divisor ) { temp_divisor = mpi_copy( divisor ); divisor = temp_divisor; } _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor ); if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { mpi_sub_ui( quot, quot, 1 ); mpi_add( rem, rem, divisor); } if( temp_divisor ) mpi_free(temp_divisor); }
void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) { int divisor_sign = divisor->sign; MPI temp_divisor = NULL; if( quot == divisor || rem == divisor ) { temp_divisor = mpi_copy_gpg( divisor ); divisor = temp_divisor; } mpi_tdiv_qr( quot, rem, dividend, divisor ); if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { mpi_sub_ui( quot, quot, 1 ); mpi_add( rem, rem, divisor); } if( temp_divisor ) mpi_free_gpg(temp_divisor); }
static void sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) { gcry_mpi_t k; gcry_mpi_t t = mpi_alloc( mpi_get_nlimbs(a) ); gcry_mpi_t inv = mpi_alloc( mpi_get_nlimbs(a) ); gcry_mpi_t p_1 = mpi_copy(skey->p); /* * b = (t * inv) mod (p-1) * b = (t * inv(k,(p-1),(p-1)) mod (p-1) * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) * */ mpi_sub_ui(p_1, p_1, 1); k = gen_k( skey->p, 0 /* no small K ! */ ); gcry_mpi_powm( a, skey->g, k, skey->p ); mpi_mul(t, skey->x, a ); mpi_subm(t, input, t, p_1 ); mpi_invm(inv, k, p_1 ); mpi_mulm(b, t, inv, p_1 ); #if 0 if( DBG_CIPHER ) { log_mpidump("elg sign p= ", skey->p); log_mpidump("elg sign g= ", skey->g); log_mpidump("elg sign y= ", skey->y); log_mpidump("elg sign x= ", skey->x); log_mpidump("elg sign k= ", k); log_mpidump("elg sign M= ", input); log_mpidump("elg sign a= ", a); log_mpidump("elg sign b= ", b); } #endif mpi_free(k); mpi_free(t); mpi_free(inv); mpi_free(p_1); }
/* Generate a key pair with a key of size NBITS not using a random value for the secret key but the one given as X. This is useful to implement a passphrase based decryption for a public key based encryption. It has appliactions in backup systems. Returns: A structure filled with all needed values and an array with n-1 factors of (p-1). */ static gcry_err_code_t generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x, gcry_mpi_t **ret_factors ) { gcry_mpi_t p; /* The prime. */ gcry_mpi_t p_min1; /* The prime minus 1. */ gcry_mpi_t g; /* The generator. */ gcry_mpi_t y; /* g^x mod p. */ unsigned int qbits; unsigned int xbits; sk->p = NULL; sk->g = NULL; sk->y = NULL; sk->x = NULL; /* Do a quick check to see whether X is suitable. */ xbits = mpi_get_nbits (x); if ( xbits < 64 || xbits >= nbits ) return GPG_ERR_INV_VALUE; p_min1 = gcry_mpi_new ( nbits ); qbits = wiener_map ( nbits ); if ( (qbits & 1) ) /* Better have an even one. */ qbits++; g = mpi_alloc (1); p = _gcry_generate_elg_prime ( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui (p_min1, p, 1); if (DBG_CIPHER) log_debug ("using a supplied x of size %u", xbits ); if ( !(mpi_cmp_ui ( x, 0 ) > 0 && mpi_cmp ( x, p_min1 ) <0 ) ) { gcry_mpi_release ( p_min1 ); gcry_mpi_release ( p ); gcry_mpi_release ( g ); return GPG_ERR_INV_VALUE; } y = gcry_mpi_new (nbits); gcry_mpi_powm ( y, g, x, p ); if ( DBG_CIPHER ) { progress ('\n'); log_mpidump ("elg p= ", p ); log_mpidump ("elg g= ", g ); log_mpidump ("elg y= ", y ); log_mpidump ("elg x= ", x ); } /* Copy the stuff to the key structures */ sk->p = p; sk->g = g; sk->y = y; sk->x = gcry_mpi_copy (x); gcry_mpi_release ( p_min1 ); /* Now we can test our keys. */ if ( test_keys ( sk, nbits - 64, 1 ) ) { gcry_mpi_release ( sk->p ); sk->p = NULL; gcry_mpi_release ( sk->g ); sk->g = NULL; gcry_mpi_release ( sk->y ); sk->y = NULL; gcry_mpi_release ( sk->x ); sk->x = NULL; return GPG_ERR_BAD_SECKEY; } return 0; }
/**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. With ALL_FACTORS set to true all afcors of * prime-1 are returned in FACTORS. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ static gcry_err_code_t prime_generate_internal (int mode, gcry_mpi_t *prime_generated, unsigned int pbits, unsigned int qbits, gcry_mpi_t g, gcry_mpi_t **ret_factors, gcry_random_level_t randomlevel, unsigned int flags, int all_factors, gcry_prime_check_func_t cb_func, void *cb_arg) { gcry_err_code_t err = 0; gcry_mpi_t *factors_new = NULL; /* Factors to return to the caller. */ gcry_mpi_t *factors = NULL; /* Current factors. */ gcry_mpi_t *pool = NULL; /* Pool of primes. */ unsigned char *perms = NULL; /* Permutations of POOL. */ gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */ unsigned int fbits = 0; /* Length of prime factors. */ unsigned int n = 0; /* Number of factors. */ unsigned int m = 0; /* Number of primes in pool. */ gcry_mpi_t q = NULL; /* First prime factor. */ gcry_mpi_t prime = NULL; /* Prime candidate. */ unsigned int nprime = 0; /* Bits of PRIME. */ unsigned int req_qbits; /* The original QBITS value. */ gcry_mpi_t val_2; /* For check_prime(). */ unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET); unsigned int count1 = 0, count2 = 0; unsigned int i = 0, j = 0; if (pbits < 48) return GPG_ERR_INV_ARG; /* If QBITS is not given, assume a reasonable value. */ if (!qbits) qbits = pbits / 3; req_qbits = qbits; /* Find number of needed prime factors. */ for (n = 1; (pbits - qbits - 1) / n >= qbits; n++) ; n--; val_2 = mpi_alloc_set_ui (2); if ((! n) || ((mode == 1) && (n < 2))) { err = GPG_ERR_INV_ARG; goto leave; } if (mode == 1) { n--; fbits = (pbits - 2 * req_qbits -1) / n; qbits = pbits - req_qbits - n * fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n * fbits; } if (DBG_CIPHER) log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n); prime = gcry_mpi_new (pbits); /* Generate first prime factor. */ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); if (mode == 1) q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); /* Allocate an array to hold the factors + 2 for later usage. */ factors = gcry_calloc (n + 2, sizeof (*factors)); if (!factors) { err = gpg_err_code_from_errno (errno); goto leave; } /* Make a pool of 3n+5 primes (this is an arbitrary value). */ m = n * 3 + 5; if (mode == 1) /* Need some more (for e.g. DSA). */ m += 5; if (m < 25) m = 25; pool = gcry_calloc (m , sizeof (*pool)); if (! pool) { err = gpg_err_code_from_errno (errno); goto leave; } /* Permutate over the pool of primes. */ do { next_try: if (! perms) { /* Allocate new primes. */ for(i = 0; i < m; i++) { mpi_free (pool[i]); pool[i] = NULL; } /* Init m_out_of_n(). */ perms = gcry_calloc (1, m); if (! perms) { err = gpg_err_code_from_errno (errno); goto leave; } for(i = 0; i < n; i++) { perms[i] = 1; pool[i] = gen_prime (fbits, is_secret, randomlevel, NULL, NULL); factors[i] = pool[i]; } } else { m_out_of_n ((char*)perms, n, m); for (i = j = 0; (i < m) && (j < n); i++) if (perms[i]) { if(! pool[i]) pool[i] = gen_prime (fbits, 0, 1, NULL, NULL); factors[j++] = pool[i]; } if (i == n) { gcry_free (perms); perms = NULL; progress ('!'); goto next_try; /* Allocate new primes. */ } } /* Generate next prime candidate: p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. */ mpi_set (prime, q); mpi_mul_ui (prime, prime, 2); if (mode == 1) mpi_mul (prime, prime, q_factor); for(i = 0; i < n; i++) mpi_mul (prime, prime, factors[i]); mpi_add_ui (prime, prime, 1); nprime = mpi_get_nbits (prime); if (nprime < pbits) { if (++count1 > 20) { count1 = 0; qbits++; progress('>'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count1 = 0; if (nprime > pbits) { if (++count2 > 20) { count2 = 0; qbits--; progress('<'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count2 = 0; } while (! ((nprime == pbits) && check_prime (prime, val_2, cb_func, cb_arg))); if (DBG_CIPHER) { progress ('\n'); log_mpidump ("prime : ", prime); log_mpidump ("factor q: ", q); if (mode == 1) log_mpidump ("factor q0: ", q_factor); for (i = 0; i < n; i++) log_mpidump ("factor pi: ", factors[i]); log_debug ("bit sizes: prime=%u, q=%u", mpi_get_nbits (prime), mpi_get_nbits (q)); if (mode == 1) log_debug (", q0=%u", mpi_get_nbits (q_factor)); for (i = 0; i < n; i++) log_debug (", p%d=%u", i, mpi_get_nbits (factors[i])); progress('\n'); } if (ret_factors) { /* Caller wants the factors. */ factors_new = gcry_calloc (n + 4, sizeof (*factors_new)); if (! factors_new) { err = gpg_err_code_from_errno (errno); goto leave; } if (all_factors) { i = 0; factors_new[i++] = gcry_mpi_set_ui (NULL, 2); factors_new[i++] = mpi_copy (q); if (mode == 1) factors_new[i++] = mpi_copy (q_factor); for(j=0; j < n; j++) factors_new[i++] = mpi_copy (factors[j]); } else { i = 0; if (mode == 1) { factors_new[i++] = mpi_copy (q_factor); for (; i <= n; i++) factors_new[i] = mpi_copy (factors[i]); } else for (; i < n; i++ ) factors_new[i] = mpi_copy (factors[i]); } } if (g) { /* Create a generator (start with 3). */ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); if (mode == 1) err = GPG_ERR_NOT_IMPLEMENTED; else { factors[n] = q; factors[n + 1] = mpi_alloc_set_ui (2); mpi_sub_ui (pmin1, prime, 1); mpi_set_ui (g, 2); do { mpi_add_ui (g, g, 1); if (DBG_CIPHER) { log_debug ("checking g:"); gcry_mpi_dump (g); log_printf ("\n"); } else progress('^'); for (i = 0; i < n + 2; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); /* No mpi_pow(), but it is okay to use this with mod prime. */ gcry_mpi_powm (b, g, tmp, prime); if (! mpi_cmp_ui (b, 1)) break; } if (DBG_CIPHER) progress('\n'); } while (i < n + 2); mpi_free (factors[n+1]); mpi_free (tmp); mpi_free (b); mpi_free (pmin1); } } if (! DBG_CIPHER) progress ('\n'); leave: if (pool) { for(i = 0; i < m; i++) mpi_free (pool[i]); gcry_free (pool); } if (factors) gcry_free (factors); /* Factors are shallow copies. */ if (perms) gcry_free (perms); mpi_free (val_2); mpi_free (q); mpi_free (q_factor); if (! err) { *prime_generated = prime; if (ret_factors) *ret_factors = factors_new; } else { if (factors_new) { for (i = 0; factors_new[i]; i++) mpi_free (factors_new[i]); gcry_free (factors_new); } mpi_free (prime); } return err; }
/**************** * Generate a random secret exponent k from prime p, so that k is * relatively prime to p-1. With SMALL_K set, k will be selected for * better encryption performance - this must never be used signing! */ static gcry_mpi_t gen_k( gcry_mpi_t p, int small_k ) { gcry_mpi_t k = mpi_alloc_secure( 0 ); gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) ); gcry_mpi_t p_1 = mpi_copy(p); unsigned int orig_nbits = mpi_get_nbits(p); unsigned int nbits, nbytes; char *rndbuf = NULL; if (small_k) { /* Using a k much lesser than p is sufficient for encryption and * it greatly improves the encryption performance. We use * Wiener's table and add a large safety margin. */ nbits = wiener_map( orig_nbits ) * 3 / 2; if( nbits >= orig_nbits ) BUG(); } else nbits = orig_nbits; nbytes = (nbits+7)/8; if( DBG_CIPHER ) log_debug("choosing a random k "); mpi_sub_ui( p_1, p, 1); for(;;) { if( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); } else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use this the here maybe it is easier to do this directly in random.c Anyway, it is highly inlikely that we will ever reach this code. */ char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); memcpy( rndbuf, pp, 4 ); gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); for(;;) { if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ { if( DBG_CIPHER ) progress('+'); break; /* no */ } if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ { if( DBG_CIPHER ) progress('-'); break; /* no */ } if (gcry_mpi_gcd( temp, k, p_1 )) goto found; /* okay, k is relative prime to (p-1) */ mpi_add_ui( k, k, 1 ); if( DBG_CIPHER ) progress('.'); } } found: gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); mpi_free(p_1); mpi_free(temp); return k; }
/**************** * Generate a key pair with a key of size NBITS * Returns: 2 structures filled with all needed values * and an array with n-1 factors of (p-1) */ static void generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) { gcry_mpi_t p; /* the prime */ gcry_mpi_t p_min1; gcry_mpi_t g; gcry_mpi_t x; /* the secret exponent */ gcry_mpi_t y; unsigned int qbits; unsigned int xbits; byte *rndbuf; p_min1 = gcry_mpi_new ( nbits ); qbits = wiener_map( nbits ); if( qbits & 1 ) /* better have a even one */ qbits++; g = mpi_alloc(1); p = _gcry_generate_elg_prime( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui(p_min1, p, 1); /* Select a random number which has these properties: * 0 < x < p-1 * This must be a very good random number because this is the * secret part. The prime is public and may be shared anyway, * so a random generator level of 1 is used for the prime. * * I don't see a reason to have a x of about the same size * as the p. It should be sufficient to have one about the size * of q or the later used k plus a large safety margin. Decryption * will be much faster with such an x. */ xbits = qbits * 3 / 2; if( xbits >= nbits ) BUG(); x = gcry_mpi_snew ( xbits ); if( DBG_CIPHER ) log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; do { if( DBG_CIPHER ) progress('.'); if( rndbuf ) { /* Change only some of the higher bits */ if( xbits < 16 ) /* should never happen ... */ { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( (xbits+7)/8, GCRY_VERY_STRONG_RANDOM ); } else { char *r = gcry_random_bytes_secure( 2, GCRY_VERY_STRONG_RANDOM ); memcpy(rndbuf, r, 2 ); gcry_free(r); } } else { rndbuf = gcry_random_bytes_secure( (xbits+7)/8, GCRY_VERY_STRONG_RANDOM ); } _gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); mpi_clear_highbit( x, xbits+1 ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); gcry_free(rndbuf); y = gcry_mpi_new (nbits); gcry_mpi_powm( y, g, x, p ); if( DBG_CIPHER ) { progress('\n'); log_mpidump("elg p= ", p ); log_mpidump("elg g= ", g ); log_mpidump("elg y= ", y ); log_mpidump("elg x= ", x ); } /* Copy the stuff to the key structures */ sk->p = p; sk->g = g; sk->y = y; sk->x = x; gcry_mpi_release ( p_min1 ); /* Now we can test our keys (this should never fail!) */ test_keys ( sk, nbits - 64, 0 ); }
/* * Return true if n is probably a prime */ static int is_prime (gcry_mpi_t n, int steps, unsigned int *count) { gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t z = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t a2 = mpi_alloc_set_ui( 2 ); gcry_mpi_t q; unsigned i, j, k; int rc = 0; unsigned nbits = mpi_get_nbits( n ); mpi_sub_ui( nminus1, n, 1 ); /* Find q and k, so that n = 1 + 2^k * q . */ q = mpi_copy ( nminus1 ); k = mpi_trailing_zeros ( q ); mpi_tdiv_q_2exp (q, q, k); for (i=0 ; i < steps; i++ ) { ++*count; if( !i ) { mpi_set_ui( x, 2 ); } else { gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM ); /* Make sure that the number is smaller than the prime and keep the randomness of the high bit. */ if ( mpi_test_bit ( x, nbits-2) ) { mpi_set_highbit ( x, nbits-2); /* Clear all higher bits. */ } else { mpi_set_highbit( x, nbits-2 ); mpi_clear_bit( x, nbits-2 ); } assert ( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); } gcry_mpi_powm ( y, x, q, n); if ( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { for ( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { gcry_mpi_powm(y, y, a2, n); if( !mpi_cmp_ui( y, 1 ) ) goto leave; /* Not a prime. */ } if (mpi_cmp( y, nminus1 ) ) goto leave; /* Not a prime. */ } progress('+'); } rc = 1; /* May be a prime. */ leave: mpi_free( x ); mpi_free( y ); mpi_free( z ); mpi_free( nminus1 ); mpi_free( q ); mpi_free( a2 ); return rc; }
/* Recover X from Y and SIGN (which actually is a parity bit). */ gpg_err_code_t _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec) { gpg_err_code_t rc = 0; gcry_mpi_t u, v, v3, t; static gcry_mpi_t p58, seven; if (ec->dialect != ECC_DIALECT_ED25519) return GPG_ERR_NOT_IMPLEMENTED; if (!p58) p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD"); if (!seven) seven = mpi_set_ui (NULL, 7); u = mpi_new (0); v = mpi_new (0); v3 = mpi_new (0); t = mpi_new (0); /* Compute u and v */ /* u = y^2 */ mpi_mulm (u, y, y, ec->p); /* v = b*y^2 */ mpi_mulm (v, ec->b, u, ec->p); /* u = y^2-1 */ mpi_sub_ui (u, u, 1); /* v = b*y^2+1 */ mpi_add_ui (v, v, 1); /* Compute sqrt(u/v) */ /* v3 = v^3 */ mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p); /* t = v3 * v3 * u * v = u * v^7 */ mpi_powm (t, v, seven, ec->p); mpi_mulm (t, t, u, ec->p); /* t = t^((p-5)/8) = (u * v^7)^((p-5)/8) */ mpi_powm (t, t, p58, ec->p); /* x = t * u * v^3 = (u * v^3) * (u * v^7)^((p-5)/8) */ mpi_mulm (t, t, u, ec->p); mpi_mulm (x, t, v3, ec->p); /* Adjust if needed. */ /* t = v * x^2 */ mpi_mulm (t, x, x, ec->p); mpi_mulm (t, t, v, ec->p); /* -t == u ? x = x * sqrt(-1) */ mpi_neg (t, t); if (!mpi_cmp (t, u)) { static gcry_mpi_t m1; /* Fixme: this is not thread-safe. */ if (!m1) m1 = scanval ("2B8324804FC1DF0B2B4D00993DFBD7A7" "2F431806AD2FE478C4EE1B274A0EA0B0"); mpi_mulm (x, x, m1, ec->p); /* t = v * x^2 */ mpi_mulm (t, x, x, ec->p); mpi_mulm (t, t, v, ec->p); /* -t == u ? x = x * sqrt(-1) */ mpi_neg (t, t); if (!mpi_cmp (t, u)) rc = GPG_ERR_INV_OBJ; } /* Choose the desired square root according to parity */ if (mpi_test_bit (x, 0) != !!sign) mpi_sub (x, ec->p, x); mpi_free (t); mpi_free (v3); mpi_free (v); mpi_free (u); return rc; }
static MPI gen_prime( unsigned nbits, int secret, int randomlevel ) { unsigned nlimbs; MPI prime, ptest, pminus1, val_2, val_3, result; int i; unsigned x, step; unsigned count1, count2; int *mods; if( 0 && DBG_CIPHER ) log_debug("generate a prime of %u bits ", nbits ); if( !no_of_small_prime_numbers ) { for(i=0; small_prime_numbers[i]; i++ ) no_of_small_prime_numbers++; } mods = m_alloc( no_of_small_prime_numbers * sizeof *mods ); /* make nbits fit into MPI implementation */ nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; val_2 = mpi_alloc_set_ui( 2 ); val_3 = mpi_alloc_set_ui( 3); prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs ); result = mpi_alloc_like( prime ); pminus1= mpi_alloc_like( prime ); ptest = mpi_alloc_like( prime ); count1 = count2 = 0; for(;;) { /* try forvever */ int dotcount=0; /* generate a random number */ { char *p = get_random_bits( nbits, randomlevel, secret ); mpi_set_buffer( prime, p, (nbits+7)/8, 0 ); m_free(p); } /* set high order bit to 1, set low order bit to 1 */ mpi_set_highbit( prime, nbits-1 ); mpi_set_bit( prime, 0 ); /* calculate all remainders */ for(i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); /* now try some primes starting with prime */ for(step=0; step < 20000; step += 2 ) { /* check against all the small primes we have in mods */ count1++; for(i=0; (x = small_prime_numbers[i]); i++ ) { while( mods[i] + step >= x ) mods[i] -= x; if( !(mods[i] + step) ) break; } if( x ) continue; /* found a multiple of an already known prime */ mpi_add_ui( ptest, prime, step ); /* do a faster Fermat test */ count2++; mpi_sub_ui( pminus1, ptest, 1); mpi_powm( result, val_2, pminus1, ptest ); if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */ /* perform stronger tests */ if( is_prime(ptest, 5, &count2 ) ) { if( !mpi_test_bit( ptest, nbits-1 ) ) { progress('\n'); log_debug("overflow in prime generation\n"); break; /* step loop, continue with a new prime */ } mpi_free(val_2); mpi_free(val_3); mpi_free(result); mpi_free(pminus1); mpi_free(prime); m_free(mods); return ptest; } } if( ++dotcount == 10 ) { progress('.'); dotcount = 0; } } progress(':'); /* restart with a new random value */ } }
static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg) { gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result; int i; unsigned int x, step; unsigned int count1, count2; int *mods; /* if ( DBG_CIPHER ) */ /* log_debug ("generate a prime of %u bits ", nbits ); */ if (nbits < 16) log_fatal ("can't generate a prime with less than %d bits\n", 16); mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); /* Make nbits fit into gcry_mpi_t implementation. */ val_2 = mpi_alloc_set_ui( 2 ); val_3 = mpi_alloc_set_ui( 3); prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits ); result = mpi_alloc_like( prime ); pminus1= mpi_alloc_like( prime ); ptest = mpi_alloc_like( prime ); count1 = count2 = 0; for (;;) { /* try forvever */ int dotcount=0; /* generate a random number */ gcry_mpi_randomize( prime, nbits, randomlevel ); /* Set high order bit to 1, set low order bit to 1. If we are generating a secret prime we are most probably doing that for RSA, to make sure that the modulus does have the requested key size we set the 2 high order bits. */ mpi_set_highbit (prime, nbits-1); if (secret) mpi_set_bit (prime, nbits-2); mpi_set_bit(prime, 0); /* Calculate all remainders. */ for (i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); /* Now try some primes starting with prime. */ for(step=0; step < 20000; step += 2 ) { /* Check against all the small primes we have in mods. */ count1++; for (i=0; (x = small_prime_numbers[i]); i++ ) { while ( mods[i] + step >= x ) mods[i] -= x; if ( !(mods[i] + step) ) break; } if ( x ) continue; /* Found a multiple of an already known prime. */ mpi_add_ui( ptest, prime, step ); /* Do a fast Fermat test now. */ count2++; mpi_sub_ui( pminus1, ptest, 1); gcry_mpi_powm( result, val_2, pminus1, ptest ); if ( !mpi_cmp_ui( result, 1 ) ) { /* Not composite, perform stronger tests */ if (is_prime(ptest, 5, &count2 )) { if (!mpi_test_bit( ptest, nbits-1-secret )) { progress('\n'); log_debug ("overflow in prime generation\n"); break; /* Stop loop, continue with a new prime. */ } if (extra_check && extra_check (extra_check_arg, ptest)) { /* The extra check told us that this prime is not of the caller's taste. */ progress ('/'); } else { /* Got it. */ mpi_free(val_2); mpi_free(val_3); mpi_free(result); mpi_free(pminus1); mpi_free(prime); gcry_free(mods); return ptest; } } } if (++dotcount == 10 ) { progress('.'); dotcount = 0; } } progress(':'); /* restart with a new random value */ } }
/**************** * Return true if n is probably a prime */ static int is_prime( MPI n, int steps, int *count ) { MPI x = mpi_alloc( mpi_get_nlimbs( n ) ); MPI y = mpi_alloc( mpi_get_nlimbs( n ) ); MPI z = mpi_alloc( mpi_get_nlimbs( n ) ); MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); MPI a2 = mpi_alloc_set_ui( 2 ); MPI q; unsigned i, j, k; int rc = 0; unsigned nbits = mpi_get_nbits( n ); mpi_sub_ui( nminus1, n, 1 ); /* find q and k, so that n = 1 + 2^k * q */ q = mpi_copy( nminus1 ); k = mpi_trailing_zeros( q ); mpi_tdiv_q_2exp(q, q, k); for(i=0 ; i < steps; i++ ) { ++*count; if( !i ) { mpi_set_ui( x, 2 ); } else { /*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/ { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( x, p, (nbits+7)/8, 0 ); m_free(p); } /* make sure that the number is smaller than the prime * and keep the randomness of the high bit */ if( mpi_test_bit( x, nbits-2 ) ) { mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */ } else { mpi_set_highbit( x, nbits-2 ); mpi_clear_bit( x, nbits-2 ); } assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); } mpi_powm( y, x, q, n); if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { mpi_powm(y, y, a2, n); if( !mpi_cmp_ui( y, 1 ) ) goto leave; /* not a prime */ } if( mpi_cmp( y, nminus1 ) ) goto leave; /* not a prime */ } progress('+'); } rc = 1; /* may be a prime */ leave: mpi_free( x ); mpi_free( y ); mpi_free( z ); mpi_free( nminus1 ); mpi_free( q ); return rc; }
/**************** * Generate a key pair with a key of size NBITS * Returns: 2 structures filles with all needed values * and an array with n-1 factors of (p-1) */ static void generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors ) { MPI p; /* the prime */ MPI p_min1; MPI g; MPI x; /* the secret exponent */ MPI y; MPI temp; unsigned int qbits; unsigned int xbits; byte *rndbuf; p_min1 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); temp = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); qbits = wiener_map ( nbits ); if( qbits & 1 ) /* better have a even one */ qbits++; g = mpi_alloc(1); p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui(p_min1, p, 1); /* select a random number which has these properties: * 0 < x < p-1 * This must be a very good random number because this is the * secret part. The prime is public and may be shared anyway, * so a random generator level of 1 is used for the prime. * * I don't see a reason to have a x of about the same size as the * p. It should be sufficient to have one about the size of q or * the later used k plus a large safety margin. Decryption will be * much faster with such an x. Note that this is not optimal for * signing keys becuase it makes an attack using accidential small * K values even easier. Well, one should not use ElGamal signing * anyway. */ xbits = qbits * 3 / 2; if( xbits >= nbits ) BUG(); x = mpi_alloc_secure ( mpi_nlimb_hint_from_nbits (xbits) ); if( DBG_CIPHER ) log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; do { if( DBG_CIPHER ) progress('.'); if( rndbuf ) { /* change only some of the higher bits */ if( xbits < 16 ) {/* should never happen ... */ xfree(rndbuf); rndbuf = get_random_bits( xbits, 2, 1 ); } else { char *r = get_random_bits( 16, 2, 1 ); memcpy(rndbuf, r, 16/8 ); xfree(r); } } else rndbuf = get_random_bits( xbits, 2, 1 ); mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); mpi_clear_highbit( x, xbits+1 ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); xfree(rndbuf); y = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); mpi_powm( y, g, x, p ); if( DBG_CIPHER ) { progress('\n'); log_mpidump("elg p= ", p ); log_mpidump("elg g= ", g ); log_mpidump("elg y= ", y ); log_mpidump("elg x= ", x ); } /* copy the stuff to the key structures */ sk->p = p; sk->g = g; sk->y = y; sk->x = x; /* now we can test our keys (this should never fail!) */ test_keys( sk, nbits - 64 ); mpi_free( p_min1 ); mpi_free( temp ); }
/**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) { int n; /* number of factors */ int m; /* number of primes in pool */ unsigned fbits; /* length of prime factors */ MPI *factors; /* current factors */ MPI *pool; /* pool of primes */ MPI q; /* first prime factor (variable)*/ MPI prime; /* prime test value */ MPI q_factor; /* used for mode 1 */ byte *perms = NULL; int i, j; int count1, count2; unsigned nprime; unsigned req_qbits = qbits; /* the requested q bits size */ MPI val_2 = mpi_alloc_set_ui( 2 ); /* find number of needed prime factors */ for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) ; n--; if( !n || (mode==1 && n < 2) ) log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits ); if( mode == 1 ) { n--; fbits = (pbits - 2*req_qbits -1) / n; qbits = pbits - req_qbits - n*fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n*fbits; } if( DBG_CIPHER ) log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); q = gen_prime( qbits, 0, 0 ); q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = m_alloc_clear( (n+2) * sizeof *factors ); /* make a pool of 3n+5 primes (this is an arbitrary value) */ m = n*3+5; if( mode == 1 ) m += 5; /* need some more for DSA */ if( m < 25 ) m = 25; pool = m_alloc_clear( m * sizeof *pool ); /* permutate over the pool of primes */ count1=count2=0; do { next_try: if( !perms ) { /* allocate new primes */ for(i=0; i < m; i++ ) { mpi_free(pool[i]); pool[i] = NULL; } /* init m_out_of_n() */ perms = m_alloc_clear( m ); for(i=0; i < n; i++ ) { perms[i] = 1; pool[i] = gen_prime( fbits, 0, 0 ); factors[i] = pool[i]; } } else { m_out_of_n( perms, n, m ); for(i=j=0; i < m && j < n ; i++ ) if( perms[i] ) { if( !pool[i] ) pool[i] = gen_prime( fbits, 0, 0 ); factors[j++] = pool[i]; } if( i == n ) { m_free(perms); perms = NULL; progress('!'); goto next_try; /* allocate new primes */ } } mpi_set( prime, q ); mpi_mul_ui( prime, prime, 2 ); if( mode == 1 ) mpi_mul( prime, prime, q_factor ); for(i=0; i < n; i++ ) mpi_mul( prime, prime, factors[i] ); mpi_add_ui( prime, prime, 1 ); nprime = mpi_get_nbits(prime); if( nprime < pbits ) { if( ++count1 > 20 ) { count1 = 0; qbits++; progress('>'); mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count1 = 0; if( nprime > pbits ) { if( ++count2 > 20 ) { count2 = 0; qbits--; progress('<'); mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count2 = 0; } while( !(nprime == pbits && check_prime( prime, val_2 )) ); if( DBG_CIPHER ) { progress('\n'); log_mpidump( "prime : ", prime ); log_mpidump( "factor q: ", q ); if( mode == 1 ) log_mpidump( "factor q0: ", q_factor ); for(i=0; i < n; i++ ) log_mpidump( "factor pi: ", factors[i] ); log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); if( mode == 1 ) fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) ); for(i=0; i < n; i++ ) fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); progress('\n'); } if( ret_factors ) { /* caller wants the factors */ *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors); i = 0; if( mode == 1 ) { (*ret_factors)[i++] = mpi_copy( q_factor ); for(; i <= n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } else { for(; i < n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } } if( g ) { /* create a generator (start with 3)*/ MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); MPI b = mpi_alloc( mpi_get_nlimbs(prime) ); MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) ); if( mode == 1 ) BUG(); /* not yet implemented */ factors[n] = q; factors[n+1] = mpi_alloc_set_ui(2); mpi_sub_ui( pmin1, prime, 1 ); mpi_set_ui(g,2); do { mpi_add_ui(g, g, 1); if( DBG_CIPHER ) { log_debug("checking g: "); mpi_print( stderr, g, 1 ); } else progress('^'); for(i=0; i < n+2; i++ ) { /*fputc('~', stderr);*/ mpi_fdiv_q(tmp, pmin1, factors[i] ); /* (no mpi_pow(), but it is okay to use this with mod prime) */ mpi_powm(b, g, tmp, prime ); if( !mpi_cmp_ui(b, 1) ) break; } if( DBG_CIPHER ) progress('\n'); } while( i < n+2 ); mpi_free(factors[n+1]); mpi_free(tmp); mpi_free(b); mpi_free(pmin1); } if( !DBG_CIPHER ) progress('\n'); m_free( factors ); /* (factors are shallow copies) */ for(i=0; i < m; i++ ) mpi_free( pool[i] ); m_free( pool ); m_free(perms); mpi_free(val_2); mpi_free(q); return prime; }