/**************** * This is the interface to the public key decryption. * ALGO gives the algorithm to use and this implicitly determines * the size of the arrays. * result is a pointer to a mpi variable which will receive a * newly allocated mpi or NULL in case of an error. */ int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) { int i, rc; *result = NULL; /* so the caller can always do an mpi_free */ if( DBG_CIPHER ) { log_debug("pubkey_decrypt: algo=%d\n", algo ); for(i=0; i < pubkey_get_nskey(algo); i++ ) log_mpidump(" skey:", skey[i] ); for(i=0; i < pubkey_get_nenc(algo); i++ ) log_mpidump(" data:", data[i] ); } do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { rc = (*pubkey_table[i].decrypt)( algo, result, data, skey ); goto ready; } } while( load_pubkey_modules() ); rc = G10ERR_PUBKEY_ALGO; ready: if( !rc && DBG_CIPHER ) { log_mpidump(" plain:", *result ); } return rc; }
/**************** * This is the interface to the public key signing. * Sign data with skey and put the result into resarr which * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the * algorithm allows this - check with pubkey_get_nsig() ) */ int pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { int i, rc; if( DBG_CIPHER ) { log_debug("pubkey_sign: algo=%d\n", algo ); for(i=0; i < pubkey_get_nskey(algo); i++ ) log_mpidump(" skey:", skey[i] ); log_mpidump(" data:", data ); } do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { rc = (*pubkey_table[i].sign)( algo, resarr, data, skey ); goto ready; } } while( load_pubkey_modules() ); rc = G10ERR_PUBKEY_ALGO; ready: if( !rc && DBG_CIPHER ) { for(i=0; i < pubkey_get_nsig(algo); i++ ) log_mpidump(" sig:", resarr[i] ); } return rc; }
static void decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) { gcry_mpi_t t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); /* output = b/(a^x) mod p */ gcry_mpi_powm( t1, a, skey->x, skey->p ); mpi_invm( t1, t1, skey->p ); mpi_mulm( output, b, t1, skey->p ); #if 0 if( DBG_CIPHER ) { log_mpidump("elg decrypted x= ", skey->x); log_mpidump("elg decrypted p= ", skey->p); log_mpidump("elg decrypted a= ", a); log_mpidump("elg decrypted b= ", b); log_mpidump("elg decrypted M= ", output); } #endif mpi_free(t1); }
static void do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) { gcry_mpi_t k; /* Note: maybe we should change the interface, so that it * is possible to check that input is < p and return an * error code. */ k = gen_k( pkey->p, 1 ); gcry_mpi_powm( a, pkey->g, k, pkey->p ); /* b = (y^k * input) mod p * = ((y^k mod p) * (input mod p)) mod p * and because input is < p * = ((y^k mod p) * input) mod p */ gcry_mpi_powm( b, pkey->y, k, pkey->p ); gcry_mpi_mulm( b, b, input, pkey->p ); #if 0 if( DBG_CIPHER ) { log_mpidump("elg encrypted y= ", pkey->y); log_mpidump("elg encrypted p= ", pkey->p); log_mpidump("elg encrypted k= ", k); log_mpidump("elg encrypted M= ", input); log_mpidump("elg encrypted a= ", a); log_mpidump("elg encrypted b= ", b); } #endif mpi_free(k); }
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; }
/**************** * 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 ); }
/* * Check if R and S verifies INPUT. */ static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) { gpg_err_code_t err = 0; gcry_mpi_t h, h1, h2, x, y; mpi_point_t Q, Q1, Q2; mpi_ec_t ctx; if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) ) return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */ if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) ) return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */ h = mpi_alloc (0); h1 = mpi_alloc (0); h2 = mpi_alloc (0); x = mpi_alloc (0); y = mpi_alloc (0); point_init (&Q); point_init (&Q1); point_init (&Q2); ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a); /* h = s^(-1) (mod n) */ mpi_invm (h, s, pkey->E.n); /* log_mpidump (" h", h); */ /* h1 = hash * s^(-1) (mod n) */ mpi_mulm (h1, input, h, pkey->E.n); /* log_mpidump (" h1", h1); */ /* Q1 = [ hash * s^(-1) ]G */ _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx); /* log_mpidump ("Q1.x", Q1.x); */ /* log_mpidump ("Q1.y", Q1.y); */ /* log_mpidump ("Q1.z", Q1.z); */ /* h2 = r * s^(-1) (mod n) */ mpi_mulm (h2, r, h, pkey->E.n); /* log_mpidump (" h2", h2); */ /* Q2 = [ r * s^(-1) ]Q */ _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx); /* log_mpidump ("Q2.x", Q2.x); */ /* log_mpidump ("Q2.y", Q2.y); */ /* log_mpidump ("Q2.z", Q2.z); */ /* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */ _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx); /* log_mpidump (" Q.x", Q.x); */ /* log_mpidump (" Q.y", Q.y); */ /* log_mpidump (" Q.z", Q.z); */ if (!mpi_cmp_ui (Q.z, 0)) { if (DBG_CIPHER) log_debug ("ecc verify: Rejected\n"); err = GPG_ERR_BAD_SIGNATURE; goto leave; } if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx)) { if (DBG_CIPHER) log_debug ("ecc verify: Failed to get affine coordinates\n"); err = GPG_ERR_BAD_SIGNATURE; goto leave; } mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */ if (mpi_cmp (x, r)) /* x != r */ { if (DBG_CIPHER) { log_mpidump (" x", x); log_mpidump (" y", y); log_mpidump (" r", r); log_mpidump (" s", s); log_debug ("ecc verify: Not verified\n"); } err = GPG_ERR_BAD_SIGNATURE; goto leave; } if (DBG_CIPHER) log_debug ("ecc verify: Accepted\n"); leave: _gcry_mpi_ec_free (ctx); point_free (&Q2); point_free (&Q1); point_free (&Q); mpi_free (y); mpi_free (x); mpi_free (h2); mpi_free (h1); mpi_free (h); return err; }
/**************** * 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; }
/* * First obtain the setup. Over the finite field randomize an scalar * secret value, and calculate the public point. */ static gpg_err_code_t generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, gcry_mpi_t g_x, gcry_mpi_t g_y, gcry_mpi_t q_x, gcry_mpi_t q_y) { gpg_err_code_t err; elliptic_curve_t E; gcry_mpi_t d; mpi_point_t Q; mpi_ec_t ctx; err = generate_curve (nbits, name, &E, &nbits); if (err) return err; if (DBG_CIPHER) { log_mpidump ("ecc generation p", E.p); log_mpidump ("ecc generation a", E.a); log_mpidump ("ecc generation b", E.b); log_mpidump ("ecc generation n", E.n); log_mpidump ("ecc generation Gx", E.G.x); log_mpidump ("ecc generation Gy", E.G.y); log_mpidump ("ecc generation Gz", E.G.z); } if (DBG_CIPHER) log_debug ("choosing a random x of size %u\n", nbits); d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); /* Compute Q. */ point_init (&Q); ctx = _gcry_mpi_ec_init (E.p, E.a); _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx); /* Copy the stuff to the key structures. */ sk->E.p = mpi_copy (E.p); sk->E.a = mpi_copy (E.a); sk->E.b = mpi_copy (E.b); point_init (&sk->E.G); point_set (&sk->E.G, &E.G); sk->E.n = mpi_copy (E.n); point_init (&sk->Q); point_set (&sk->Q, &Q); sk->d = mpi_copy (d); /* We also return copies of G and Q in affine coordinates if requested. */ if (g_x && g_y) { if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) log_fatal ("ecc generate: Failed to get affine coordinates\n"); } if (q_x && q_y) { if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) log_fatal ("ecc generate: Failed to get affine coordinates\n"); } _gcry_mpi_ec_free (ctx); point_free (&Q); mpi_free (d); curve_free (&E); /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); return 0; }
/**************** * 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 ); }
/* Compute an ECDSA signature. * Return the signature struct (r,s) from the message hash. The caller * must have allocated R and S. */ gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, int flags, int hashalgo) { gpg_err_code_t err = 0; int extraloops = 0; gcry_mpi_t k, dr, sum, k_1, x; mpi_point_struct I; gcry_mpi_t hash; const void *abuf; unsigned int abits, qbits; mpi_ec_t ctx; if (DBG_CIPHER) log_mpidump ("ecdsa sign hash ", input ); qbits = mpi_get_nbits (skey->E.n); /* Convert the INPUT into an MPI if needed. */ if (mpi_is_opaque (input)) { abuf = gcry_mpi_get_opaque (input, &abits); err = gpg_err_code (gcry_mpi_scan (&hash, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL)); if (err) return err; if (abits > qbits) gcry_mpi_rshift (hash, hash, abits - qbits); } else hash = input; k = NULL; dr = mpi_alloc (0); sum = mpi_alloc (0); k_1 = mpi_alloc (0); x = mpi_alloc (0); point_init (&I); ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); /* Two loops to avoid R or S are zero. This is more of a joke than a real demand because the probability of them being zero is less than any hardware failure. Some specs however require it. */ do { do { mpi_free (k); k = NULL; if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo) { /* Use Pornin's method for deterministic DSA. If this flag is set, it is expected that HASH is an opaque MPI with the to be signed hash. That hash is also used as h1 from 3.2.a. */ if (!mpi_is_opaque (input)) { err = GPG_ERR_CONFLICT; goto leave; } abuf = gcry_mpi_get_opaque (input, &abits); err = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d, abuf, (abits+7)/8, hashalgo, extraloops); if (err) goto leave; extraloops++; } else k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM); _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx)) { if (DBG_CIPHER) log_debug ("ecc sign: Failed to get affine coordinates\n"); err = GPG_ERR_BAD_SIGNATURE; goto leave; } mpi_mod (r, x, skey->E.n); /* r = x mod n */ } while (!mpi_cmp_ui (r, 0)); mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n */ mpi_addm (sum, hash, dr, skey->E.n); /* sum = hash + (d*r) mod n */ mpi_invm (k_1, k, skey->E.n); /* k_1 = k^(-1) mod n */ mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } while (!mpi_cmp_ui (s, 0)); if (DBG_CIPHER) { log_mpidump ("ecdsa sign result r ", r); log_mpidump ("ecdsa sign result s ", s); } leave: _gcry_mpi_ec_free (ctx); point_free (&I); mpi_free (x); mpi_free (k_1); mpi_free (sum); mpi_free (dr); mpi_free (k); if (hash != input) mpi_free (hash); return err; }
/* Verify an ECDSA signature. * Check if R and S verifies INPUT. */ gpg_err_code_t _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) { gpg_err_code_t err = 0; gcry_mpi_t h, h1, h2, x; mpi_point_struct Q, Q1, Q2; mpi_ec_t ctx; if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) ) return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */ if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) ) return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */ h = mpi_alloc (0); h1 = mpi_alloc (0); h2 = mpi_alloc (0); x = mpi_alloc (0); point_init (&Q); point_init (&Q1); point_init (&Q2); ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, pkey->E.p, pkey->E.a, pkey->E.b); /* h = s^(-1) (mod n) */ mpi_invm (h, s, pkey->E.n); /* h1 = hash * s^(-1) (mod n) */ mpi_mulm (h1, input, h, pkey->E.n); /* Q1 = [ hash * s^(-1) ]G */ _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx); /* h2 = r * s^(-1) (mod n) */ mpi_mulm (h2, r, h, pkey->E.n); /* Q2 = [ r * s^(-1) ]Q */ _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx); /* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */ _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx); if (!mpi_cmp_ui (Q.z, 0)) { if (DBG_CIPHER) log_debug ("ecc verify: Rejected\n"); err = GPG_ERR_BAD_SIGNATURE; goto leave; } if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx)) { if (DBG_CIPHER) log_debug ("ecc verify: Failed to get affine coordinates\n"); err = GPG_ERR_BAD_SIGNATURE; goto leave; } mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */ if (mpi_cmp (x, r)) /* x != r */ { if (DBG_CIPHER) { log_mpidump (" x", x); log_mpidump (" r", r); log_mpidump (" s", s); } err = GPG_ERR_BAD_SIGNATURE; goto leave; } leave: _gcry_mpi_ec_free (ctx); point_free (&Q2); point_free (&Q1); point_free (&Q); mpi_free (x); mpi_free (h2); mpi_free (h1); mpi_free (h); return err; }
/**************** * 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; }