/**************** * Returns true if the signature composed of A and B is valid. */ static int verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) { int rc; gcry_mpi_t t1; gcry_mpi_t t2; gcry_mpi_t base[4]; gcry_mpi_t ex[4]; if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) return 0; /* assertion 0 < a < p failed */ t1 = mpi_alloc( mpi_get_nlimbs(a) ); t2 = mpi_alloc( mpi_get_nlimbs(a) ); #if 0 /* t1 = (y^a mod p) * (a^b mod p) mod p */ gcry_mpi_powm( t1, pkey->y, a, pkey->p ); gcry_mpi_powm( t2, a, b, pkey->p ); mpi_mulm( t1, t1, t2, pkey->p ); /* t2 = g ^ input mod p */ gcry_mpi_powm( t2, pkey->g, input, pkey->p ); rc = !mpi_cmp( t1, t2 ); #elif 0 /* t1 = (y^a mod p) * (a^b mod p) mod p */ base[0] = pkey->y; ex[0] = a; base[1] = a; ex[1] = b; base[2] = NULL; ex[2] = NULL; mpi_mulpowm( t1, base, ex, pkey->p ); /* t2 = g ^ input mod p */ gcry_mpi_powm( t2, pkey->g, input, pkey->p ); rc = !mpi_cmp( t1, t2 ); #else /* t1 = g ^ - input * y ^ a * a ^ b mod p */ mpi_invm(t2, pkey->g, pkey->p ); base[0] = t2 ; ex[0] = input; base[1] = pkey->y; ex[1] = a; base[2] = a; ex[2] = b; base[3] = NULL; ex[3] = NULL; mpi_mulpowm( t1, base, ex, pkey->p ); rc = !mpi_cmp_ui( t1, 1 ); #endif mpi_free(t1); mpi_free(t2); return rc; }
/* XXX ignore sign of arguments and sets sign of result to sign of A */ void mpi_mod(const mpi *a, const mpi *m, mpi *r) { ASSERT(a != m); ASSERT(m != r); ASSERT(m->size != 0); /* If A = 0 or A = M, then A % M = 0 */ if (a->size == 0 || a == m) { mpi_zero(r); return; } /* If A < M, R = 0 */ /* FIXME: there is a bug here when A is negative. */ if (mpi_cmp(a, m) < 0) { mpi_set_mpi(r, a); return; } if (a == r) { /* A = R, so compute the modulus in-place on R. */ mp_modi(r->digits, r->size, m->digits, m->size); } else { MPI_MIN_ALLOC(r, m->size); mp_mod(a->digits, a->size, m->digits, m->size, r->digits); } r->size = mp_rsize(r->digits, m->size); r->sign = a->sign; /* XXX */ }
/* Connert the bit string BITS of length NBITS into an octet string with a length of (QBITS+7)/8 bytes. On success store the result at R_FRAME. */ static gpg_err_code_t bits2octets (unsigned char **r_frame, const void *bits, unsigned int nbits, gcry_mpi_t q, unsigned int qbits) { gpg_err_code_t rc; gcry_mpi_t z1; /* z1 = bits2int (b) */ rc = _gcry_mpi_scan (&z1, GCRYMPI_FMT_USG, bits, (nbits+7)/8, NULL); if (rc) return rc; if (nbits > qbits) mpi_rshift (z1, z1, nbits - qbits); /* z2 - z1 mod q */ if (mpi_cmp (z1, q) >= 0) mpi_sub (z1, z1, q); /* Convert to an octet string. */ rc = int2octets (r_frame, z1, (qbits+7)/8); mpi_free (z1); return rc; }
/* R = X mod M Using Barrett reduction. Before using this function _gcry_mpi_barrett_init must have been called to do the precalculations. CTX is the context created by this precalculation and also conveys M. If the Barret reduction could no be done a straightforward reduction method is used. We assume that these conditions are met: Input: x =(x_2k-1 ...x_0)_b m =(m_k-1 ....m_0)_b with m_k-1 != 0 Output: r = x mod m */ void _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) { gcry_mpi_t m = ctx->m; int k = ctx->k; gcry_mpi_t y = ctx->y; gcry_mpi_t r1 = ctx->r1; gcry_mpi_t r2 = ctx->r2; int sign; mpi_normalize (x); if (mpi_get_nlimbs (x) > 2*k ) { mpi_mod (r, x, m); return; } sign = x->sign; x->sign = 0; /* 1. q1 = floor( x / b^k-1) * q2 = q1 * y * q3 = floor( q2 / b^k+1 ) * Actually, we don't need qx, we can work direct on r2 */ mpi_set ( r2, x ); mpi_rshift_limbs ( r2, k-1 ); mpi_mul ( r2, r2, y ); mpi_rshift_limbs ( r2, k+1 ); /* 2. r1 = x mod b^k+1 * r2 = q3 * m mod b^k+1 * r = r1 - r2 * 3. if r < 0 then r = r + b^k+1 */ mpi_set ( r1, x ); if ( r1->nlimbs > k+1 ) /* Quick modulo operation. */ r1->nlimbs = k+1; mpi_mul ( r2, r2, m ); if ( r2->nlimbs > k+1 ) /* Quick modulo operation. */ r2->nlimbs = k+1; mpi_sub ( r, r1, r2 ); if ( mpi_has_sign ( r ) ) { if (!ctx->r3) { ctx->r3 = mpi_alloc ( k + 2 ); mpi_set_ui (ctx->r3, 1); mpi_lshift_limbs (ctx->r3, k + 1 ); } mpi_add ( r, r, ctx->r3 ); } /* 4. while r >= m do r = r - m */ while ( mpi_cmp( r, m ) >= 0 ) mpi_sub ( r, r, m ); x->sign = sign; }
/* * RSAVP1() function [RFC3447 sec 5.2.2] */ static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) { MPI m; int ret; /* (1) Validate 0 <= s < n */ if (mpi_cmp_ui(s, 0) < 0) { kleave(" = -EBADMSG [s < 0]"); return -EBADMSG; } if (mpi_cmp(s, key->rsa.n) >= 0) { kleave(" = -EBADMSG [s >= n]"); return -EBADMSG; } m = mpi_alloc(0); if (!m) return -ENOMEM; /* (2) m = s^e mod n */ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); if (ret < 0) { mpi_free(m); return ret; } *_m = m; return 0; }
static void test_keys( ELG_secret_key *sk, unsigned int nbits ) { ELG_public_key pk; MPI test = mpi_alloc( 0 ); MPI out1_a = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out1_b = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out2 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); pk.p = sk->p; pk.g = sk->g; pk.y = sk->y; /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( test, p, (nbits+7)/8, 0 ); xfree(p); } do_encrypt( out1_a, out1_b, test, &pk ); decrypt( out2, out1_a, out1_b, sk ); if( mpi_cmp( test, out2 ) ) log_fatal("Elgamal operation: encrypt, decrypt failed\n"); mpi_free( test ); mpi_free( out1_a ); mpi_free( out1_b ); mpi_free( out2 ); }
/**************** * To check the validity of the value, recalculate the correspondence * between the public value and the secret one. */ static int check_secret_key (ECC_secret_key * sk) { mpi_point_t Q; gcry_mpi_t y_2, y2 = mpi_alloc (0); mpi_ec_t ctx; /* ?primarity test of 'p' */ /* (...) //!! */ /* G in E(F_p) */ y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */ mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */ if (mpi_cmp (y_2, y2)) { if (DBG_CIPHER) log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n"); return (1); } /* G != PaI */ if (!mpi_cmp_ui (sk->E.G.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: 'G' cannot be Point at Infinity!\n"); return (1); } point_init (&Q); ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a); _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); if (mpi_cmp_ui (Q.z, 0)) { if (DBG_CIPHER) log_debug ("check_secret_key: E is not a curve of order n\n"); point_free (&Q); _gcry_mpi_ec_free (ctx); return 1; } /* pubkey cannot be PaI */ if (!mpi_cmp_ui (sk->Q.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: Q can not be a Point at Infinity!\n"); _gcry_mpi_ec_free (ctx); return (1); } /* pubkey = [d]G over E */ _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z)) { if (DBG_CIPHER) log_debug ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); _gcry_mpi_ec_free (ctx); return (1); } _gcry_mpi_ec_free (ctx); point_free (&Q); return 0; }
/* * RSAEP function [RFC3447 sec 5.1.1] * c = m^e mod n; */ static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m) { /* (1) Validate 0 <= m < n */ if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) return -EINVAL; /* (2) c = m^e mod n */ return mpi_powm(c, m, key->e, key->n); }
/* * RSAVP1 function [RFC3447 sec 5.2.2] * m = s^e mod n; */ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s) { /* (1) Validate 0 <= s < n */ if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0) return -EINVAL; /* (2) m = s^e mod n */ return mpi_powm(m, s, key->e, key->n); }
/* * RSASP1 function [RFC3447 sec 5.2.1] * s = m^d mod n */ static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) { /* (1) Validate 0 <= m < n */ if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) return -EINVAL; /* (2) s = m^d mod n */ return mpi_powm(s, m, key->d, key->n); }
/* * RSADP function [RFC3447 sec 5.1.2] * m = c^d mod n; */ static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c) { /* (1) Validate 0 <= c < n */ if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0) return -EINVAL; /* (2) m = c^d mod n */ return mpi_powm(m, c, key->d, key->n); }
/**************** * Test whether the secret key is valid. * Returns: if this is a valid key. */ static int check_secret_key( ELG_secret_key *sk ) { int rc; gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) ); gcry_mpi_powm( y, sk->g, sk->x, sk->p ); rc = !mpi_cmp( y, sk->y ); mpi_free( y ); return rc; }
int mpi_cmp_s32(const mpi *p, int32_t q) { int r; mpi_t qq; mpi_init_s32(qq, q); r = mpi_cmp(p, qq); mpi_free(qq); return r; }
int mpi_cmp_s64(const mpi *p, int64_t q) { int r; mpi_t qq; mpi_init_s64(qq, q); r = mpi_cmp(p, qq); mpi_free(qq); return r; }
/**************** * Test whether the secret key is valid. * Returns: true if this is a valid key. */ static int 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; }
/**************** * Barrett reduction: We assume that these conditions are met: * Given x =(x_2k-1 ...x_0)_b * m =(m_k-1 ....m_0)_b with m_k-1 != 0 * Output r = x mod m * Before using this function init_barret must be used to calucalte y and k. * Returns: false = no error * true = can't perform barret reduction */ static int calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ) { int xx = k > 3 ? k-3:0; mpi_normalize( x ); if( mpi_get_nlimbs(x) > 2*k ) return 1; /* can't do it */ /* 1. q1 = floor( x / b^k-1) * q2 = q1 * y * q3 = floor( q2 / b^k+1 ) * Actually, we don't need qx, we can work direct on r2 */ mpi_set( r2, x ); mpi_rshift_limbs( r2, k-1 ); mpi_mul( r2, r2, y ); mpi_rshift_limbs( r2, k+1 ); /* 2. r1 = x mod b^k+1 * r2 = q3 * m mod b^k+1 * r = r1 - r2 * 3. if r < 0 then r = r + b^k+1 */ mpi_set( r1, x ); if( r1->nlimbs > k+1 ) /* quick modulo operation */ r1->nlimbs = k+1; mpi_mul( r2, r2, m ); if( r2->nlimbs > k+1 ) /* quick modulo operation */ r2->nlimbs = k+1; mpi_sub( r, r1, r2 ); if( mpi_has_sign (r) ) { gcry_mpi_t tmp; tmp = mpi_alloc( k + 2 ); mpi_set_ui( tmp, 1 ); mpi_lshift_limbs( tmp, k+1 ); mpi_add( r, r, tmp ); mpi_free(tmp); } /* 4. while r >= m do r = r - m */ while( mpi_cmp( r, m ) >= 0 ) mpi_sub( r, r, m ); return 0; }
/* 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; }
/* Find multiplicative inverse B^-1 of B (mod M) such that B*B^-1 (mod M) = 1. * If such an inverse exists, stores the inverse in INV and returns 1. * Returns 0 otherwise. */ int mpi_modinv(const mpi *m, const mpi *b, mpi *inv) { ASSERT(mpi_cmp(b, m) < 0); mpi_t v, g; mpi_init(v); mpi_init(g); mpi_gcdext(b, m, inv, v, g); mpi_free(v); int g_is_one = mpi_is_one(g); mpi_free(g); if (g_is_one) { if (mpi_is_neg(inv)) mpi_add(inv, m, inv); return 1; } else { return 0; } }
static int test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie ) { ELG_public_key pk; gcry_mpi_t test = gcry_mpi_new ( 0 ); gcry_mpi_t out1_a = gcry_mpi_new ( nbits ); gcry_mpi_t out1_b = gcry_mpi_new ( nbits ); gcry_mpi_t out2 = gcry_mpi_new ( nbits ); int failed = 0; pk.p = sk->p; pk.g = sk->g; pk.y = sk->y; gcry_mpi_randomize ( test, nbits, GCRY_WEAK_RANDOM ); do_encrypt ( out1_a, out1_b, test, &pk ); decrypt ( out2, out1_a, out1_b, sk ); if ( mpi_cmp( test, out2 ) ) failed |= 1; sign ( out1_a, out1_b, test, sk ); if ( !verify( out1_a, out1_b, test, &pk ) ) failed |= 2; gcry_mpi_release ( test ); gcry_mpi_release ( out1_a ); gcry_mpi_release ( out1_b ); gcry_mpi_release ( out2 ); if (failed && !nodie) log_fatal ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); if (failed && DBG_CIPHER) log_debug ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); return failed; }
/* * 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; }
/* 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; }
/**************** * 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 ); }
/* 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 ); }
/**************** * 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; }
/* RESULT = P1 + P2 */ void _gcry_mpi_ec_add_points (mpi_point_t result, mpi_point_t p1, mpi_point_t p2, mpi_ec_t ctx) { #define x1 (p1->x ) #define y1 (p1->y ) #define z1 (p1->z ) #define x2 (p2->x ) #define y2 (p2->y ) #define z2 (p2->z ) #define x3 (result->x) #define y3 (result->y) #define z3 (result->z) #define l1 (ctx->t.scratch[0]) #define l2 (ctx->t.scratch[1]) #define l3 (ctx->t.scratch[2]) #define l4 (ctx->t.scratch[3]) #define l5 (ctx->t.scratch[4]) #define l6 (ctx->t.scratch[5]) #define l7 (ctx->t.scratch[6]) #define l8 (ctx->t.scratch[7]) #define l9 (ctx->t.scratch[8]) #define t1 (ctx->t.scratch[9]) #define t2 (ctx->t.scratch[10]) if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) ) { /* Same point; need to call the duplicate function. */ _gcry_mpi_ec_dup_point (result, p1, ctx); } else if (!mpi_cmp_ui (z1, 0)) { /* P1 is at infinity. */ mpi_set (x3, p2->x); mpi_set (y3, p2->y); mpi_set (z3, p2->z); } else if (!mpi_cmp_ui (z2, 0)) { /* P2 is at infinity. */ mpi_set (x3, p1->x); mpi_set (y3, p1->y); mpi_set (z3, p1->z); } else { int z1_is_one = !mpi_cmp_ui (z1, 1); int z2_is_one = !mpi_cmp_ui (z2, 1); /* l1 = x1 z2^2 */ /* l2 = x2 z1^2 */ if (z2_is_one) mpi_set (l1, x1); else { ec_powm (l1, z2, mpi_const (MPI_C_TWO), ctx); ec_mulm (l1, l1, x1, ctx); } if (z1_is_one) mpi_set (l2, x2); else { ec_powm (l2, z1, mpi_const (MPI_C_TWO), ctx); ec_mulm (l2, l2, x2, ctx); } /* l3 = l1 - l2 */ ec_subm (l3, l1, l2, ctx); /* l4 = y1 z2^3 */ ec_powm (l4, z2, mpi_const (MPI_C_THREE), ctx); ec_mulm (l4, l4, y1, ctx); /* l5 = y2 z1^3 */ ec_powm (l5, z1, mpi_const (MPI_C_THREE), ctx); ec_mulm (l5, l5, y2, ctx); /* l6 = l4 - l5 */ ec_subm (l6, l4, l5, ctx); if (!mpi_cmp_ui (l3, 0)) { if (!mpi_cmp_ui (l6, 0)) { /* P1 and P2 are the same - use duplicate function. */ _gcry_mpi_ec_dup_point (result, p1, ctx); } else { /* P1 is the inverse of P2. */ mpi_set_ui (x3, 1); mpi_set_ui (y3, 1); mpi_set_ui (z3, 0); } } else { /* l7 = l1 + l2 */ ec_addm (l7, l1, l2, ctx); /* l8 = l4 + l5 */ ec_addm (l8, l4, l5, ctx); /* z3 = z1 z2 l3 */ ec_mulm (z3, z1, z2, ctx); ec_mulm (z3, z3, l3, ctx); /* x3 = l6^2 - l7 l3^2 */ ec_powm (t1, l6, mpi_const (MPI_C_TWO), ctx); ec_powm (t2, l3, mpi_const (MPI_C_TWO), ctx); ec_mulm (t2, t2, l7, ctx); ec_subm (x3, t1, t2, ctx); /* l9 = l7 l3^2 - 2 x3 */ ec_mulm (t1, x3, mpi_const (MPI_C_TWO), ctx); ec_subm (l9, t2, t1, ctx); /* y3 = (l9 l6 - l8 l3^3)/2 */ ec_mulm (l9, l9, l6, ctx); ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/ ec_mulm (t1, t1, l8, ctx); ec_subm (y3, l9, t1, ctx); ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx); } } #undef x1 #undef y1 #undef z1 #undef x2 #undef y2 #undef z2 #undef x3 #undef y3 #undef z3 #undef l1 #undef l2 #undef l3 #undef l4 #undef l5 #undef l6 #undef l7 #undef l8 #undef l9 #undef t1 #undef t2 }
/* * Generate a deterministic secret exponent K less than DSA_Q. H1 is * the to be signed digest with a length of HLEN bytes. HALGO is the * algorithm used to create the hash. On success the value for K is * stored at R_K. */ gpg_err_code_t _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k, gcry_mpi_t dsa_q, gcry_mpi_t dsa_x, const unsigned char *h1, unsigned int hlen, int halgo, unsigned int extraloops) { gpg_err_code_t rc; unsigned char *V = NULL; unsigned char *K = NULL; unsigned char *x_buf = NULL; unsigned char *h1_buf = NULL; gcry_md_hd_t hd = NULL; unsigned char *t = NULL; gcry_mpi_t k = NULL; unsigned int tbits, qbits; int i; qbits = mpi_get_nbits (dsa_q); if (!qbits || !h1 || !hlen) return GPG_ERR_EINVAL; if (_gcry_md_get_algo_dlen (halgo) != hlen) return GPG_ERR_DIGEST_ALGO; /* Step b: V = 0x01 0x01 0x01 ... 0x01 */ V = xtrymalloc (hlen); if (!V) { rc = gpg_err_code_from_syserror (); goto leave; } for (i=0; i < hlen; i++) V[i] = 1; /* Step c: K = 0x00 0x00 0x00 ... 0x00 */ K = xtrycalloc (1, hlen); if (!K) { rc = gpg_err_code_from_syserror (); goto leave; } rc = int2octets (&x_buf, dsa_x, (qbits+7)/8); if (rc) goto leave; rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits); if (rc) goto leave; /* Create a handle to compute the HMACs. */ rc = _gcry_md_open (&hd, halgo, (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)); if (rc) goto leave; /* Step d: K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); _gcry_md_write (hd, "", 1); _gcry_md_write (hd, x_buf, (qbits+7)/8); _gcry_md_write (hd, h1_buf, (qbits+7)/8); memcpy (K, _gcry_md_read (hd, 0), hlen); /* Step e: V = HMAC_K(V) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); memcpy (V, _gcry_md_read (hd, 0), hlen); /* Step f: K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); _gcry_md_write (hd, "\x01", 1); _gcry_md_write (hd, x_buf, (qbits+7)/8); _gcry_md_write (hd, h1_buf, (qbits+7)/8); memcpy (K, _gcry_md_read (hd, 0), hlen); /* Step g: V = HMAC_K(V) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); memcpy (V, _gcry_md_read (hd, 0), hlen); /* Step h. */ t = xtrymalloc ((qbits+7)/8+hlen); if (!t) { rc = gpg_err_code_from_syserror (); goto leave; } again: for (tbits = 0; tbits < qbits;) { /* V = HMAC_K(V) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); memcpy (V, _gcry_md_read (hd, 0), hlen); /* T = T || V */ memcpy (t+(tbits+7)/8, V, hlen); tbits += 8*hlen; } /* k = bits2int (T) */ mpi_free (k); k = NULL; rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL); if (rc) goto leave; if (tbits > qbits) mpi_rshift (k, k, tbits - qbits); /* Check: k < q and k > 1 */ if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0)) { /* K = HMAC_K(V || 0x00) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); _gcry_md_write (hd, "", 1); memcpy (K, _gcry_md_read (hd, 0), hlen); /* V = HMAC_K(V) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); memcpy (V, _gcry_md_read (hd, 0), hlen); goto again; } /* The caller may have requested that we introduce some extra loops. This is for example useful if the caller wants another value for K because the last returned one yielded an R of 0. Because this is very unlikely we implement it in a straightforward way. */ if (extraloops) { extraloops--; /* K = HMAC_K(V || 0x00) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); _gcry_md_write (hd, "", 1); memcpy (K, _gcry_md_read (hd, 0), hlen); /* V = HMAC_K(V) */ rc = _gcry_md_setkey (hd, K, hlen); if (rc) goto leave; _gcry_md_write (hd, V, hlen); memcpy (V, _gcry_md_read (hd, 0), hlen); goto again; } /* log_mpidump (" k", k); */ leave: xfree (t); _gcry_md_close (hd); xfree (h1_buf); xfree (x_buf); xfree (K); xfree (V); if (rc) mpi_free (k); else *r_k = k; return rc; }
static void ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) { #if 0 /* NOTE: This code works only for limb sizes of 32 bit. */ mpi_limb_t *wp, *sp; if (ctx->nist_nbits == 192) { mpi_mul (w, u, v); mpi_resize (w, 12); wp = w->d; sp = ctx->s[0]->d; sp[0*2+0] = wp[0*2+0]; sp[0*2+1] = wp[0*2+1]; sp[1*2+0] = wp[1*2+0]; sp[1*2+1] = wp[1*2+1]; sp[2*2+0] = wp[2*2+0]; sp[2*2+1] = wp[2*2+1]; sp = ctx->s[1]->d; sp[0*2+0] = wp[3*2+0]; sp[0*2+1] = wp[3*2+1]; sp[1*2+0] = wp[3*2+0]; sp[1*2+1] = wp[3*2+1]; sp[2*2+0] = 0; sp[2*2+1] = 0; sp = ctx->s[2]->d; sp[0*2+0] = 0; sp[0*2+1] = 0; sp[1*2+0] = wp[4*2+0]; sp[1*2+1] = wp[4*2+1]; sp[2*2+0] = wp[4*2+0]; sp[2*2+1] = wp[4*2+1]; sp = ctx->s[3]->d; sp[0*2+0] = wp[5*2+0]; sp[0*2+1] = wp[5*2+1]; sp[1*2+0] = wp[5*2+0]; sp[1*2+1] = wp[5*2+1]; sp[2*2+0] = wp[5*2+0]; sp[2*2+1] = wp[5*2+1]; ctx->s[0]->nlimbs = 6; ctx->s[1]->nlimbs = 6; ctx->s[2]->nlimbs = 6; ctx->s[3]->nlimbs = 6; mpi_add (ctx->c, ctx->s[0], ctx->s[1]); mpi_add (ctx->c, ctx->c, ctx->s[2]); mpi_add (ctx->c, ctx->c, ctx->s[3]); while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) mpi_sub ( ctx->c, ctx->c, ctx->p ); mpi_set (w, ctx->c); } else if (ctx->nist_nbits == 384) { int i; mpi_mul (w, u, v); mpi_resize (w, 24); wp = w->d; #define NEXT(a) do { ctx->s[(a)]->nlimbs = 12; \ sp = ctx->s[(a)]->d; \ i = 0; } while (0) #define X(a) do { sp[i++] = wp[(a)];} while (0) #define X0(a) do { sp[i++] = 0; } while (0) NEXT(0); X(0);X(1);X(2);X(3);X(4);X(5);X(6);X(7);X(8);X(9);X(10);X(11); NEXT(1); X0();X0();X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0(); NEXT(2); X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22);X(23); NEXT(3); X(21);X(22);X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20); NEXT(4); X0();X(23);X0();X(20);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19); NEXT(5); X0();X0();X0();X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0(); NEXT(6); X(20);X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0();X0(); NEXT(7); X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22); NEXT(8); X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0();X0();X0();X0(); NEXT(9); X0();X0();X0();X(23);X(23);X0();X0();X0();X0();X0();X0();X0(); #undef X0 #undef X #undef NEXT mpi_add (ctx->c, ctx->s[0], ctx->s[1]); mpi_add (ctx->c, ctx->c, ctx->s[1]); mpi_add (ctx->c, ctx->c, ctx->s[2]); mpi_add (ctx->c, ctx->c, ctx->s[3]); mpi_add (ctx->c, ctx->c, ctx->s[4]); mpi_add (ctx->c, ctx->c, ctx->s[5]); mpi_add (ctx->c, ctx->c, ctx->s[6]); mpi_sub (ctx->c, ctx->c, ctx->s[7]); mpi_sub (ctx->c, ctx->c, ctx->s[8]); mpi_sub (ctx->c, ctx->c, ctx->s[9]); while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) mpi_sub ( ctx->c, ctx->c, ctx->p ); while ( ctx->c->sign ) mpi_add ( ctx->c, ctx->c, ctx->p ); mpi_set (w, ctx->c); } else #endif /*0*/ mpi_mulm (w, u, v, ctx->p); }
/* * Generate a random secret exponent K less than Q. * Note that ECDSA uses this code also to generate D. */ gcry_mpi_t _gcry_dsa_gen_k (gcry_mpi_t q, int security_level) { gcry_mpi_t k = mpi_alloc_secure (mpi_get_nlimbs (q)); unsigned int nbits = mpi_get_nbits (q); unsigned int nbytes = (nbits+7)/8; char *rndbuf = NULL; /* To learn why we don't use mpi_mod to get the requested bit size, read the paper: "The Insecurity of the Digital Signature Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ if (DBG_CIPHER) log_debug ("choosing a random k of %u bits at seclevel %d\n", nbits, security_level); for (;;) { if ( !rndbuf || nbits < 32 ) { xfree (rndbuf); rndbuf = _gcry_random_bytes_secure (nbytes, security_level); } 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 these extra bytes here. However the required management code is more complex and thus we better use this simple method. */ char *pp = _gcry_random_bytes_secure (4, security_level); memcpy (rndbuf, pp, 4); xfree (pp); } _gcry_mpi_set_buffer (k, rndbuf, nbytes, 0); /* Make sure we have the requested number of bits. This code looks a bit funny but it is easy to understand if you consider that mpi_set_highbit clears all higher bits. We don't have a clear_highbit, thus we first set the high bit and then clear it again. */ if (mpi_test_bit (k, nbits-1)) mpi_set_highbit (k, nbits-1); else { mpi_set_highbit (k, nbits-1); mpi_clear_bit (k, nbits-1); } if (!(mpi_cmp (k, q) < 0)) /* check: k < q */ { if (DBG_CIPHER) log_debug ("\tk too large - again\n"); continue; /* no */ } if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */ { if (DBG_CIPHER) log_debug ("\tk is zero - again\n"); continue; /* no */ } break; /* okay */ } xfree (rndbuf); return k; }
/* * 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; }