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; }
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; }
static int generate_key_or_iv(unsigned int id, tvbuff_t *salt_tvb, unsigned int iter, const char *pw, unsigned int req_keylen, char * keybuf) { int rc; unsigned int i, j; gcry_md_hd_t md; gcry_mpi_t num_b1 = NULL; size_t pwlen; char hash[20], buf_b[64], buf_i[128], *p; char *salt_p; int salt_size; size_t cur_keylen; size_t n; gcry_error_t err; cur_keylen = 0; salt_size = tvb_captured_length(salt_tvb); salt_p = (char *)tvb_memdup(wmem_packet_scope(), salt_tvb, 0, salt_size); if (pw == NULL) pwlen = 0; else pwlen = strlen(pw); if (pwlen > 63 / 2) { return FALSE; } /* Store salt and password in BUF_I */ p = buf_i; for (i = 0; i < 64; i++) *p++ = salt_p[i % salt_size]; if (pw) { for (i = j = 0; i < 64; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing zero */ j = 0; } } else memset (p, 0, 64); for (;;) { err = gcry_md_open(&md, GCRY_MD_SHA1, 0); if (gcry_err_code(err)) { return FALSE; } for (i = 0; i < 64; i++) { unsigned char lid = id & 0xFF; gcry_md_write (md, &lid, 1); } gcry_md_write(md, buf_i, pw ? 128 : 64); gcry_md_final (md); memcpy (hash, gcry_md_read (md, 0), 20); gcry_md_close (md); for (i = 1; i < iter; i++) gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20); for (i = 0; i < 20 && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { gcry_mpi_release (num_b1); return TRUE; /* ready */ } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % 20]; n = 64; rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, n, &n); if (rc != 0) { return FALSE; } gcry_mpi_add_ui (num_b1, num_b1, 1); for (i = 0; i < 128; i += 64) { gcry_mpi_t num_ij; n = 64; rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, n, &n); if (rc != 0) { return FALSE; } gcry_mpi_add (num_ij, num_ij, num_b1); gcry_mpi_clear_highbit (num_ij, 64 * 8); n = 64; rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, n, &n, num_ij); if (rc != 0) { return FALSE; } gcry_mpi_release (num_ij); } } }
/* 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); } }
/* * 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); }