static void check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain; gcry_mpi_t x; int rc; /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); gcry_mpi_release (x); /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %m))", x); gcry_mpi_release (x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); }
/* Check that right shifting actually works for an amount larger than the number of bits per limb. */ static void test_rshift (int pass) { gcry_mpi_t a, b; char *result, *result2; int i; wherestr = "test_rshift"; show ("checking that rshift works as expected (pass %d)\n", pass); a = gcry_mpi_new (0); b = gcry_mpi_new (0); gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); for (i=0; i < 75; i++) { gcry_mpi_rshift (b, a, i); result = mpi2bitstr (b, 72); result2 = mpi2bitstr (a, 72); rshiftbitstring (result2, i); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("rshift by %d failed\n", i); } xfree (result); xfree (result2); } /* Again. This time using in-place operation. */ gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); for (i=0; i < 75; i++) { gcry_mpi_release (b); b = gcry_mpi_copy (a); gcry_mpi_rshift (b, b, i); result = mpi2bitstr (b, 72); result2 = mpi2bitstr (a, 72); rshiftbitstring (result2, i); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("in-place rshift by %d failed\n", i); } xfree (result2); xfree (result); } gcry_mpi_release (b); gcry_mpi_release (a); }
ZrtpDH::ZrtpDH(const char* type){ // Well - the algo type is only 4 char thus cast to int32 and compare if (*(int32_t*)type == *(int32_t*)dh2k) { pkType = DH2K; } else if (*(int32_t*)type == *(int32_t*)dh3k) { pkType = DH3K; } else { fprintf(stderr, "Unknown pubkey algo: %d\n", pkType); } ctx = static_cast<void*>(new gcryptCtx); gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx); tmpCtx->privKey = NULL; tmpCtx->pubKey = NULL; initializeGcrypt(); if (!dhinit) { gcry_mpi_scan(&bnP2048, GCRYMPI_FMT_USG, P2048, sizeof(P2048), NULL); gcry_mpi_scan(&bnP3072, GCRYMPI_FMT_USG, P3072, sizeof(P3072), NULL); // gcry_mpi_scan(&bnP4096, GCRYMPI_FMT_USG, P4096, sizeof(P4096), NULL); two = gcry_mpi_set_ui(NULL, 2); bnP2048MinusOne = gcry_mpi_new(sizeof(P2048)*8); gcry_mpi_sub_ui(bnP2048MinusOne, bnP2048, 1); bnP3072MinusOne = gcry_mpi_new(sizeof(P3072)*8); gcry_mpi_sub_ui(bnP3072MinusOne, bnP3072, 1); // bnP4096MinusOne = gcry_mpi_new(sizeof(P4096)*8); // gcry_mpi_sub_ui(bnP4096MinusOne, bnP4096, 1); dhinit = 1; } if (pkType == DH3K) { tmpCtx->privKey = gcry_mpi_new(256); gcry_mpi_randomize(tmpCtx->privKey, 256, GCRY_STRONG_RANDOM); } else if (pkType == DH2K) { tmpCtx->privKey = gcry_mpi_new(512); gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM); } // else { // tmpCtx->privKey = gcry_mpi_new(512); // gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM); // } }
/* This is to check a bug reported by bpgcrypt at itaparica.org on 2006-07-31 against libgcrypt 1.2.2. */ static void one_bit_only (int highbit) { gcry_mpi_t a; char *result; int i; wherestr = "one_bit_only"; show ("checking that set_%sbit does only set one bit\n", highbit?"high":""); a = gcry_mpi_new (0); gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); gcry_mpi_set_ui (a, 0); if (highbit) gcry_mpi_set_highbit (a, 42); else gcry_mpi_set_bit (a, 42); if (!gcry_mpi_test_bit (a, 42)) fail ("failed to set a bit\n"); gcry_mpi_clear_bit (a, 42); if (gcry_mpi_test_bit (a, 42)) fail ("failed to clear a bit\n"); result = mpi2bitstr (a, 70); assert (strlen (result) == 70); for (i=0; result[i]; i++) if ( result[i] != '0' ) break; if (result[i]) fail ("spurious bits detected\n"); xfree (result); gcry_mpi_release (a); }
/** * Generate a random value mod n. * * @param edc ECC context * @return random value mod n. */ gcry_mpi_t GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc) { gcry_mpi_t n; unsigned int highbit; gcry_mpi_t r; n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); /* check public key for number of bits, bail out if key is all zeros */ highbit = 256; /* Curve25519 */ while ( (! gcry_mpi_test_bit (n, highbit)) && (0 != highbit) ) highbit--; GNUNET_assert (0 != highbit); /* generate fact < n (without bias) */ GNUNET_assert (NULL != (r = gcry_mpi_new (0))); do { gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM); } while (gcry_mpi_cmp (r, n) >= 0); gcry_mpi_release (n); return r; }
/* Choose a random value x and calculate e = g^x mod p. Returns e and if ret_x is not NULL x. */ static gcry_mpi_t calc_dh_secret (gcry_mpi_t gex_g, gcry_mpi_t gex_p, gcry_mpi_t * ret_x) { gcry_mpi_t e, g, x, prime; size_t n = sizeof diffie_hellman_group1_prime; if (gex_p) prime = gcry_mpi_copy (gex_p); else if (gcry_mpi_scan (&prime, GCRYMPI_FMT_STD, diffie_hellman_group1_prime, n, NULL)) abort (); /*_gsti_dump_mpi( "prime=", prime );*/ if (gex_g) g = gcry_mpi_copy (gex_g); else g = gcry_mpi_set_ui (NULL, 2); /* FIXME: we n bits for the private exponent, where n is 2*derrived_key_material */ x = gcry_mpi_snew (200); gcry_mpi_randomize (x, 200, GCRY_STRONG_RANDOM); n = gcry_mpi_get_nbits (prime); e = gcry_mpi_new (n+1); gcry_mpi_powm (e, g, x, prime); if (ret_x) *ret_x = x; else gcry_mpi_release (x); gcry_mpi_release (g); gcry_mpi_release (prime); return e; }
nuts_mpi_t nuts_mpi_new_random(const unsigned int nbits) { gcry_check(); gcry_mpi_t mpi = gcry_mpi_new(nbits); gcry_mpi_randomize(mpi, nbits, GCRY_STRONG_RANDOM); gcry_mpi_set_bit(mpi, nbits - 1); gcry_mpi_set_bit(mpi, 0); return nuts_mpi_alloc(mpi); }
gcry_mpi_t get_random_exponent(const struct curve_params *cp) { int bits = gcry_mpi_get_nbits(cp->dp.order); gcry_mpi_t a; a = gcry_mpi_snew(0); do { gcry_mpi_randomize(a, bits, GCRY_STRONG_RANDOM); gcry_mpi_clear_highbit(a, bits); } while (! gcry_mpi_cmp_ui(a, 0) || gcry_mpi_cmp(a, cp->dp.order) >= 0); return a; }
/** * Create a blinding key * * @param len length of the key in bits (i.e. 2048) * @return the newly created blinding key */ struct GNUNET_CRYPTO_rsa_BlindingKey * GNUNET_CRYPTO_rsa_blinding_key_create (unsigned int len) { struct GNUNET_CRYPTO_rsa_BlindingKey *blind; blind = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey); blind->r = gcry_mpi_new (len); gcry_mpi_randomize (blind->r, len, GCRY_STRONG_RANDOM); return blind; }
static void test_keys( RSA_secret_key *sk, unsigned nbits ) { RSA_public_key pk; gcry_mpi_t test = gcry_mpi_new ( nbits ); gcry_mpi_t out1 = gcry_mpi_new ( nbits ); gcry_mpi_t out2 = gcry_mpi_new ( nbits ); pk.n = sk->n; pk.e = sk->e; gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM ); public( out1, test, &pk );
/* Generate a random secret scalar k with an order of p At the beginning this was identical to the code is in elgamal.c. Later imporved by mmr. Further simplified by wk. */ static gcry_mpi_t gen_k (gcry_mpi_t p, int security_level) { gcry_mpi_t k; unsigned int nbits; nbits = mpi_get_nbits (p); k = mpi_snew (nbits); if (DBG_CIPHER) log_debug ("choosing a random k of %u bits\n", nbits); gcry_mpi_randomize (k, nbits, security_level); mpi_mod (k, k, p); /* k = k mod p */ return k; }
gboolean egg_dh_gen_pair (gcry_mpi_t prime, gcry_mpi_t base, guint bits, gcry_mpi_t *pub, gcry_mpi_t *priv) { guint pbits; g_return_val_if_fail (prime, FALSE); g_return_val_if_fail (base, FALSE); g_return_val_if_fail (pub, FALSE); g_return_val_if_fail (priv, FALSE); pbits = gcry_mpi_get_nbits (prime); g_return_val_if_fail (pbits > 1, FALSE); if (bits == 0) { bits = pbits; } else if (bits > pbits) { g_return_val_if_reached (FALSE); } /* * Generate a strong random number of bits, and not zero. * gcry_mpi_randomize bumps up to the next byte. Since we * need to have a value less than half of prime, we make sure * we bump down. */ *priv = gcry_mpi_snew (bits); g_return_val_if_fail (*priv, FALSE); while (gcry_mpi_cmp_ui (*priv, 0) == 0) gcry_mpi_randomize (*priv, bits, GCRY_STRONG_RANDOM); /* Secret key value must be less than half of p */ if (gcry_mpi_get_nbits (*priv) > bits) gcry_mpi_clear_highbit (*priv, bits); if (gcry_mpi_get_nbits (*priv) > pbits - 1) gcry_mpi_clear_highbit (*priv, pbits - 1); g_assert (gcry_mpi_cmp (prime, *priv) > 0); *pub = gcry_mpi_new (gcry_mpi_get_nbits (*priv)); g_return_val_if_fail (*pub, FALSE); gcry_mpi_powm (*pub, base, *priv, prime); return TRUE; }
/**************** * To verify correct skey it use a random information. * First, encrypt and decrypt this dummy value, * test if the information is recuperated. * Second, test with the sign and verify functions. */ static void test_keys (ECC_secret_key *sk, unsigned int nbits) { ECC_public_key pk; gcry_mpi_t test = mpi_new (nbits); mpi_point_t R_; gcry_mpi_t c = mpi_new (nbits); gcry_mpi_t out = mpi_new (nbits); gcry_mpi_t r = mpi_new (nbits); gcry_mpi_t s = mpi_new (nbits); if (DBG_CIPHER) log_debug ("Testing key.\n"); point_init (&R_); pk.E = curve_copy (sk->E); point_init (&pk.Q); point_set (&pk.Q, &sk->Q); gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); if (sign (test, sk, r, s) ) log_fatal ("ECDSA operation: sign failed\n"); if (verify (test, &pk, r, s)) { log_fatal ("ECDSA operation: sign, verify failed\n"); } if (DBG_CIPHER) log_debug ("ECDSA operation: sign, verify ok.\n"); point_free (&pk.Q); curve_free (&pk.E); point_free (&R_); mpi_free (s); mpi_free (r); mpi_free (out); mpi_free (c); mpi_free (test); }
/* Check that a freshly generated key actually works. Returns 0 on success. */ static int test_keys (RSA_secret_key *sk, unsigned int nbits) { int result = -1; /* Default to failure. */ RSA_public_key pk; gcry_mpi_t plaintext = gcry_mpi_new (nbits); gcry_mpi_t ciphertext = gcry_mpi_new (nbits); gcry_mpi_t decr_plaintext = gcry_mpi_new (nbits); gcry_mpi_t signature = gcry_mpi_new (nbits); /* Put the relevant parameters into a public key structure. */ pk.n = sk->n; pk.e = sk->e; /* Create a random plaintext. */ gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); /* Encrypt using the public key. */ public (ciphertext, plaintext, &pk);
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; }
static void test_asn1_integers (Test *test, gconstpointer unused) { GNode *asn; gcry_mpi_t mpi, mpt; GBytes *data; gboolean ret; asn = egg_asn1x_create (test_asn1_tab, "TestIntegers"); g_assert ("asn test structure is null" && asn != NULL); /* Make a random number */ mpi = gcry_mpi_new (512); g_return_if_fail (mpi); gcry_mpi_randomize (mpi, 512, GCRY_WEAK_RANDOM); /* Write the mpi out */ ret = gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "mpi", NULL), mpi); g_assert ("couldn't write mpi to asn1" && ret); /* Now encode the whole caboodle */ data = egg_asn1x_encode (asn, NULL); g_assert ("encoding asn1 didn't work" && data != NULL); egg_asn1x_destroy (asn); /* Now decode it all nicely */ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestIntegers", data); g_assert (asn != NULL); ret = gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "mpi", NULL), &mpt); egg_asn1x_destroy (asn); g_assert ("couldn't read mpi from asn1" && ret); g_assert ("mpi returned is null" && mpt != NULL); g_assert ("mpi is wrong number" && gcry_mpi_cmp (mpi, mpt) == 0); g_bytes_unref (data); gcry_mpi_release (mpi); gcry_mpi_release (mpt); }
/* * 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; }
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 */ } }
char * irc_sasl_mechanism_dh_blowfish (const char *data_base64, const char *sasl_username, const char *sasl_password) { char *data, *answer, *ptr_answer, *answer_base64; unsigned char *ptr_data, *secret_bin, *public_bin; unsigned char *password_clear, *password_crypted; int length_data, size, num_bits_prime_number, length_key; int length_username, length_password, length_answer; size_t num_written; gcry_mpi_t data_prime_number, data_generator_number, data_server_pub_key; gcry_mpi_t pub_key, priv_key, secret_mpi; gcry_cipher_hd_t gcrypt_handle; data = NULL; secret_bin = NULL; public_bin = NULL; password_clear = NULL; password_crypted = NULL; answer = NULL; answer_base64 = NULL; data_prime_number = NULL; data_generator_number = NULL; data_server_pub_key = NULL; pub_key = NULL; priv_key = NULL; secret_mpi = NULL; /* decode data */ data = malloc (strlen (data_base64) + 1); length_data = weechat_string_decode_base64 (data_base64, data); ptr_data = (unsigned char *)data; /* extract prime number */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto end; data_prime_number = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_prime_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); num_bits_prime_number = gcry_mpi_get_nbits (data_prime_number); ptr_data += size; length_data -= size; /* extract generator number */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto end; data_generator_number = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_generator_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); ptr_data += size; length_data -= size; /* extract server-generated public key */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto end; data_server_pub_key = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_server_pub_key, GCRYMPI_FMT_USG, ptr_data, size, NULL); /* generate keys */ pub_key = gcry_mpi_new (num_bits_prime_number); priv_key = gcry_mpi_new (num_bits_prime_number); gcry_mpi_randomize (priv_key, num_bits_prime_number, GCRY_STRONG_RANDOM); /* pub_key = (g ^ priv_key) % p */ gcry_mpi_powm (pub_key, data_generator_number, priv_key, data_prime_number); /* compute secret_bin */ length_key = num_bits_prime_number / 8; secret_bin = malloc (length_key); secret_mpi = gcry_mpi_new (num_bits_prime_number); /* secret_mpi = (y ^ priv_key) % p */ gcry_mpi_powm (secret_mpi, data_server_pub_key, priv_key, data_prime_number); gcry_mpi_print (GCRYMPI_FMT_USG, secret_bin, length_key, &num_written, secret_mpi); /* create public_bin */ public_bin = malloc (length_key); gcry_mpi_print (GCRYMPI_FMT_USG, public_bin, length_key, &num_written, pub_key); /* create password buffers (clear and crypted) */ length_password = strlen (sasl_password) + ((8 - (strlen (sasl_password) % 8)) % 8); password_clear = malloc (length_password); password_crypted = malloc (length_password); memset (password_clear, 0, length_password); memset (password_crypted, 0, length_password); memcpy (password_clear, sasl_password, strlen (sasl_password)); /* crypt password using blowfish */ if (gcry_cipher_open (&gcrypt_handle, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB, 0) != 0) goto end; if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0) goto end; if (gcry_cipher_encrypt (gcrypt_handle, password_crypted, length_password, password_clear, length_password) != 0) goto end; /* * build answer for server, it is concatenation of: * 1. key length (2 bytes) * 2. public key ('length_key' bytes) * 3. sasl_username ('length_username'+1 bytes) * 4. encrypted password ('length_password' bytes) */ length_username = strlen (sasl_username); length_answer = 2 + length_key + length_username + 1 + length_password; answer = malloc (length_answer); ptr_answer = answer; *((unsigned int *)ptr_answer) = htons(length_key); ptr_answer += 2; memcpy (ptr_answer, public_bin, length_key); ptr_answer += length_key; memcpy (ptr_answer, sasl_username, length_username + 1); ptr_answer += length_username + 1; memcpy (ptr_answer, password_crypted, length_password); /* encode answer to base64 */ answer_base64 = malloc (length_answer * 4); if (answer_base64) weechat_string_encode_base64 (answer, length_answer, answer_base64); end: if (data) free (data); if (secret_bin) free (secret_bin); if (public_bin) free (public_bin); if (password_clear) free (password_clear); if (password_crypted) free (password_crypted); if (answer) free (answer); if (data_prime_number) gcry_mpi_release (data_prime_number); if (data_generator_number) gcry_mpi_release (data_generator_number); if (data_server_pub_key) gcry_mpi_release (data_server_pub_key); if (pub_key) gcry_mpi_release (pub_key); if (priv_key) gcry_mpi_release (priv_key); if (secret_mpi) gcry_mpi_release (secret_mpi); return answer_base64; }
/* Check that left shifting works correctly. */ static void test_lshift (int pass) { static int size_list[] = {1, 31, 32, 63, 64, 65, 70, 0}; int size_idx; gcry_mpi_t a, b; char *tmpstr, *result, *result2; int i; wherestr = "test_lshift"; show ("checking that lshift works as expected (pass %d)\n", pass); for (size_idx=0; size_list[size_idx]; size_idx++) { a = gcry_mpi_new (0); b = gcry_mpi_new (0); /* gcry_mpi_randomize rounds up to full bytes, thus we need to use gcry_mpi_clear_highbit to fix that. */ gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); gcry_mpi_clear_highbit (a, size_list[size_idx]); for (i=0; i < 75; i++) { gcry_mpi_lshift (b, a, i); result = mpi2bitstr_nlz (b); tmpstr = mpi2bitstr_nlz (a); result2 = lshiftbitstring (tmpstr, i); xfree (tmpstr); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("lshift by %d failed\n", i); } xfree (result); xfree (result2); } /* Again. This time using in-place operation. */ gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); gcry_mpi_clear_highbit (a, size_list[size_idx]); for (i=0; i < 75; i++) { gcry_mpi_release (b); b = gcry_mpi_copy (a); gcry_mpi_lshift (b, b, i); result = mpi2bitstr_nlz (b); tmpstr = mpi2bitstr_nlz (a); result2 = lshiftbitstring (tmpstr, i); xfree (tmpstr); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("in-place lshift by %d failed\n", i); } xfree (result2); xfree (result); } gcry_mpi_release (b); gcry_mpi_release (a); } }
static void rsa_bench (int iterations, int print_header, int no_blinding) { gpg_error_t err; int p_sizes[] = { 1024, 2048, 3072, 4096 }; int testno; if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; printf ("RSA %3d bit ", p_sizes[testno]); fflush (stdout); err = gcry_sexp_build (&key_spec, NULL, gcry_fips_mode_active () ? "(genkey (RSA (nbits %d)))" : "(genkey (RSA (nbits %d)(transient-key)))", p_sizes[testno]); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit RSA key failed: %s\n", p_sizes[testno], gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed (%d): %s\n", count, gpg_strerror (err)); } } stop_timer (); printf (" %s", elapsed_time ()); if (no_blinding) { fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags no-blinding) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); } putchar ('\n'); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } }
static void dsa_bench (int iterations, int print_header) { gpg_error_t err; gcry_sexp_t pub_key[3], sec_key[3]; int p_sizes[3] = { 1024, 2048, 3072 }; int q_sizes[3] = { 160, 224, 256 }; gcry_sexp_t data; gcry_sexp_t sig = NULL; int i, j; err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024, strlen (sample_public_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024, strlen (sample_private_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048, strlen (sample_public_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048, strlen (sample_private_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072, strlen (sample_public_dsa_key_3072)); if (!err) err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072, strlen (sample_private_dsa_key_3072)); if (err) { fprintf (stderr, PGM ": converting sample keys failed: %s\n", gcry_strerror (err)); exit (1); } if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (i=0; i < DIM (q_sizes); i++) { gcry_mpi_t x; x = gcry_mpi_new (q_sizes[i]); gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) { fprintf (stderr, PGM ": converting data failed: %s\n", gcry_strerror (err)); exit (1); } printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { err = gcry_pk_verify (sig, data, pub_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": verify failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s\n", elapsed_time ()); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); sig = NULL; } for (i=0; i < DIM (q_sizes); i++) { gcry_sexp_release (sec_key[i]); gcry_sexp_release (pub_key[i]); } }
/* * Generate a random number less than p * FIXME: takes ages ... */ void gen_rand(gcry_mpi_t r, gcry_mpi_t p) { do { gcry_mpi_randomize(r, gcry_mpi_get_nbits(p), GCRY_STRONG_RANDOM); gcry_mpi_clear_highbit(r, gcry_mpi_get_nbits(p) + 1); } while (gcry_mpi_cmp(p, r) < 0); }
int irc_sasl_dh (const char *data_base64, unsigned char **public_bin, unsigned char **secret_bin, int *length_key) { char *data; unsigned char *ptr_data; int length_data, size, num_bits_prime_number, rc; size_t num_written; gcry_mpi_t data_prime_number, data_generator_number, data_server_pub_key; gcry_mpi_t pub_key, priv_key, secret_mpi; rc = 0; data = NULL; data_prime_number = NULL; data_generator_number = NULL; data_server_pub_key = NULL; pub_key = NULL; priv_key = NULL; secret_mpi = NULL; /* decode data */ data = malloc (strlen (data_base64) + 1); length_data = weechat_string_decode_base64 (data_base64, data); ptr_data = (unsigned char *)data; /* extract prime number */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto dhend; data_prime_number = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_prime_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); num_bits_prime_number = gcry_mpi_get_nbits (data_prime_number); ptr_data += size; length_data -= size; /* extract generator number */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto dhend; data_generator_number = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_generator_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); ptr_data += size; length_data -= size; /* extract server-generated public key */ size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); ptr_data += 2; length_data -= 2; if (size > length_data) goto dhend; data_server_pub_key = gcry_mpi_new (size * 8); gcry_mpi_scan (&data_server_pub_key, GCRYMPI_FMT_USG, ptr_data, size, NULL); /* generate keys */ pub_key = gcry_mpi_new (num_bits_prime_number); priv_key = gcry_mpi_new (num_bits_prime_number); gcry_mpi_randomize (priv_key, num_bits_prime_number, GCRY_STRONG_RANDOM); /* pub_key = (g ^ priv_key) % p */ gcry_mpi_powm (pub_key, data_generator_number, priv_key, data_prime_number); /* compute secret_bin */ *length_key = num_bits_prime_number / 8; *secret_bin = malloc (*length_key); secret_mpi = gcry_mpi_new (num_bits_prime_number); /* secret_mpi = (y ^ priv_key) % p */ gcry_mpi_powm (secret_mpi, data_server_pub_key, priv_key, data_prime_number); gcry_mpi_print (GCRYMPI_FMT_USG, *secret_bin, *length_key, &num_written, secret_mpi); /* create public_bin */ *public_bin = malloc (*length_key); gcry_mpi_print (GCRYMPI_FMT_USG, *public_bin, *length_key, &num_written, pub_key); rc = 1; dhend: if (data) free (data); if (data_prime_number) gcry_mpi_release (data_prime_number); if (data_generator_number) gcry_mpi_release (data_generator_number); if (data_server_pub_key) gcry_mpi_release (data_server_pub_key); if (pub_key) gcry_mpi_release (pub_key); if (priv_key) gcry_mpi_release (priv_key); if (secret_mpi) gcry_mpi_release (secret_mpi); return rc; }
static void ecc_bench (int iterations, int print_header) { #if USE_ECC gpg_error_t err; int p_sizes[] = { 192, 224, 256, 384, 521 }; int testno; if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; printf ("ECDSA %3d bit ", p_sizes[testno]); fflush (stdout); err = gcry_sexp_build (&key_spec, NULL, "(genkey (ECDSA (nbits %d)))", p_sizes[testno]); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit ECC key failed: %s\n", p_sizes[testno], gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno], GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed: %s\n", gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed: %s\n", gpg_strerror (err)); } } stop_timer (); printf (" %s\n", elapsed_time ()); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } #endif /*USE_ECC*/ }