static void context_alloc (void) { gpg_error_t err; gcry_ctx_t ctx; gcry_mpi_t p, a; wherestr = "context_alloc"; show ("checking context functions\n"); p = gcry_mpi_set_ui (NULL, 1); a = gcry_mpi_set_ui (NULL, 1); err = ec_p_new (&ctx, p, a); if (err) die ("ec_p_new returned an error: %s\n", gpg_strerror (err)); gcry_mpi_release (p); gcry_mpi_release (a); gcry_ctx_release (ctx); p = NULL; a = gcry_mpi_set_ui (NULL, 0); err = ec_p_new (&ctx, p, a); if (!err || gpg_err_code (err) != GPG_ERR_EINVAL) fail ("ec_p_new: bad parameter detection failed (1)\n"); gcry_mpi_release (a); a = NULL; err = ec_p_new (&ctx, p, a); if (!err || gpg_err_code (err) != GPG_ERR_EINVAL) fail ("ec_p_new: bad parameter detection failed (2)\n"); }
/** * Multiply the generator g of the elliptic curve by @a val * to obtain the point on the curve representing @a val. * Afterwards, point addition will correspond to integer * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to * convert a point back to an integer (as long as the * integer is smaller than the MAX of the @a edc context). * * @param edc calculation context for ECC operations * @param val value to encode into a point * @return representation of the value as an ECC point, * must be freed using #GNUNET_CRYPTO_ecc_free() */ gcry_mpi_point_t GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, int val) { gcry_mpi_t fact; gcry_mpi_t n; gcry_mpi_point_t g; gcry_mpi_point_t r; g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); if (val < 0) { n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_set_ui (fact, - val); gcry_mpi_sub (fact, n, fact); gcry_mpi_release (n); } else { gcry_mpi_set_ui (fact, val); } r = gcry_mpi_point_new (0); gcry_mpi_ec_mul (r, fact, g, edc->ctx); gcry_mpi_release (fact); gcry_mpi_point_release (g); return r; }
/** * Do pre-calculation for ECC discrete logarithm for small factors. * * @param max maximum value the factor can be * @param mem memory to use (should be smaller than @a max), must not be zero. * @return @a max if dlog failed, otherwise the factor */ struct GNUNET_CRYPTO_EccDlogContext * GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem) { struct GNUNET_CRYPTO_EccDlogContext *edc; unsigned int K = ((max + (mem-1)) / mem); gcry_mpi_point_t g; struct GNUNET_PeerIdentity key; gcry_mpi_point_t gKi; gcry_mpi_t fact; gcry_mpi_t n; unsigned int i; GNUNET_assert (max < INT32_MAX); edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); edc->max = max; edc->mem = mem; edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, GNUNET_NO); GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); gKi = gcry_mpi_point_new (0); for (i=0;i<=mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) i + max, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } /* negative values */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); for (i=1;i<mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_sub (fact, n, fact); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) max - i, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (gKi); gcry_mpi_point_release (g); return edc; }
/** * Do some DLOG operations for testing. * * @param edc context for ECC operations * @param do_dlog #GNUNET_YES if we want to actually do the bencharked operation */ static void test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, int do_dlog) { gcry_mpi_t fact; gcry_mpi_t n; gcry_ctx_t ctx; gcry_mpi_point_t q; gcry_mpi_point_t g; unsigned int i; int x; int iret; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", ctx, 0); GNUNET_assert (NULL != g); n = gcry_mpi_ec_get_mpi ("n", ctx, 0); q = gcry_mpi_point_new (0); fact = gcry_mpi_new (0); for (i=0;i<TEST_ITER;i++) { fprintf (stderr, "."); x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, MAX_FACT); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) { gcry_mpi_set_ui (fact, x); gcry_mpi_sub (fact, n, fact); x = - x; } else { gcry_mpi_set_ui (fact, x); } gcry_mpi_ec_mul (q, fact, g, ctx); if ( (GNUNET_YES == do_dlog) && (x != (iret = GNUNET_CRYPTO_ecc_dlog (edc, q))) ) { fprintf (stderr, "DLOG failed for value %d (%d)\n", x, iret); GNUNET_assert (0); } } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (g); gcry_mpi_point_release (q); gcry_ctx_release (ctx); fprintf (stderr, "\n"); }
void jacobian_load_affine(struct jacobian_point *p1, const struct affine_point *p2) { if (! point_is_zero(p2)) { gcry_mpi_set(p1->x, p2->x); gcry_mpi_set(p1->y, p2->y); gcry_mpi_set_ui(p1->z, 1); } else gcry_mpi_set_ui(p1->z, 0); }
/* Verify a signature on data using a public key. The data must be * small enough to be signed (i.e. already hashed, if necessary). */ gcry_error_t otrl_privkey_verify(const unsigned char *sigbuf, size_t siglen, unsigned short pubkey_type, gcry_sexp_t pubs, const unsigned char *data, size_t len) { gcry_error_t err; gcry_mpi_t datampi,r,s; gcry_sexp_t datas, sigs; if (pubkey_type != OTRL_PUBKEY_TYPE_DSA || siglen != 40) return gcry_error(GPG_ERR_INV_VALUE); if (len) { gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL); } else { datampi = gcry_mpi_set_ui(NULL, 0); } gcry_sexp_build(&datas, NULL, "(%m)", datampi); gcry_mpi_release(datampi); gcry_mpi_scan(&r, GCRYMPI_FMT_USG, sigbuf, 20, NULL); gcry_mpi_scan(&s, GCRYMPI_FMT_USG, sigbuf+20, 20, NULL); gcry_sexp_build(&sigs, NULL, "(sig-val (dsa (r %m)(s %m)))", r, s); gcry_mpi_release(r); gcry_mpi_release(s); err = gcry_pk_verify(sigs, datas, pubs); gcry_sexp_release(datas); gcry_sexp_release(sigs); return err; }
/* 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); }
void jacobian_double(struct jacobian_point *p, const struct domain_params *dp) { if (gcry_mpi_cmp_ui(p->z, 0)) { if (gcry_mpi_cmp_ui(p->y, 0)) { gcry_mpi_t t1, t2; t1 = gcry_mpi_snew(0); t2 = gcry_mpi_snew(0); gcry_mpi_mulm(t1, p->x, p->x, dp->m); gcry_mpi_addm(t2, t1, t1, dp->m); gcry_mpi_addm(t2, t2, t1, dp->m); gcry_mpi_mulm(t1, p->z, p->z, dp->m); gcry_mpi_mulm(t1, t1, t1, dp->m); gcry_mpi_mulm(t1, t1, dp->a, dp->m); gcry_mpi_addm(t1, t1, t2, dp->m); gcry_mpi_mulm(p->z, p->z, p->y, dp->m); gcry_mpi_addm(p->z, p->z, p->z, dp->m); gcry_mpi_mulm(p->y, p->y, p->y, dp->m); gcry_mpi_addm(p->y, p->y, p->y, dp->m); gcry_mpi_mulm(t2, p->x, p->y, dp->m); gcry_mpi_addm(t2, t2, t2, dp->m); gcry_mpi_mulm(p->x, t1, t1, dp->m); gcry_mpi_subm(p->x, p->x, t2, dp->m); gcry_mpi_subm(p->x, p->x, t2, dp->m); gcry_mpi_subm(t2, t2, p->x, dp->m); gcry_mpi_mulm(t1, t1, t2, dp->m); gcry_mpi_mulm(t2, p->y, p->y, dp->m); gcry_mpi_addm(t2, t2, t2, dp->m); gcry_mpi_subm(p->y, t1, t2, dp->m); gcry_mpi_release(t1); gcry_mpi_release(t2); } else gcry_mpi_set_ui(p->z, 0); } }
/* 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; }
gsti_error_t _gsti_kex_send_gex_group (gsti_ctx_t ctx) { gsti_error_t err; MSG_gexdh_group gex; const byte *mod; size_t n; memset (&gex, 0, sizeof gex); gex.g = gcry_mpi_set_ui (NULL, 2); mod = select_dh_modulus (ctx->gex.n, &n); err = gcry_mpi_scan (&gex.p, GCRYMPI_FMT_USG, mod, n, NULL); if (!err) err = build_gex_group (&gex, &ctx->pkt); if (!err) err = _gsti_packet_write (ctx, &ctx->pkt); if (!err) err = _gsti_packet_flush (ctx); /*free_gex_group (&gex); We store the DH group exchange values for later use */ ctx->kex.p = gex.p; ctx->kex.g = gex.g; return err; }
/* compute 2^m (mod phi(p)), for a prime p */ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { gcry_mpi_t phi, r; int n; phi = gcry_mpi_new(0); gcry_mpi_sub_ui(phi, p, 1); /* count number of used bits in m */ for (n = 0; ((uint64_t)1 << n) <= m; n++) ; r = gcry_mpi_new(0); gcry_mpi_set_ui(r, 1); while (n) { /* square and multiply algorithm for fast exponentiation */ n--; gcry_mpi_mulm(r, r, r, phi); if (m & ((uint64_t)1 << n)) { gcry_mpi_add(r, r, r); if (gcry_mpi_cmp(r, phi) >= 0) gcry_mpi_sub(r, r, phi); } } gcry_mpi_release(phi); return r; }
void gotr_ecbd_gen_flake_key(gcry_mpi_point_t *ret, gcry_mpi_point_t y0, gcry_mpi_t r1, gcry_mpi_point_t R1, gcry_mpi_point_t R0, gcry_mpi_point_t V1) { gcry_mpi_point_t tmp = gcry_mpi_point_new(0); gcry_mpi_t n = gcry_mpi_new(0); gcry_mpi_point_release(*ret); *ret = gcry_mpi_point_new(0); gcry_mpi_mul_ui(n, r1, 4); gcry_mpi_ec_mul(*ret, n, y0, edctx); gcry_mpi_set_ui(n, 3); gcry_mpi_ec_mul(tmp, n, R1, edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); gcry_mpi_ec_dup(tmp, R0, edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); gcry_mpi_ec_add(*ret, *ret, V1, edctx); gcry_mpi_point_release(tmp); gcry_mpi_release(n); }
static void set_get_point (void) { gcry_mpi_point_t point; gcry_mpi_t x, y, z; wherestr = "set_get_point"; show ("checking point setting functions\n"); point = gcry_mpi_point_new (0); x = gcry_mpi_set_ui (NULL, 17); y = gcry_mpi_set_ui (NULL, 42); z = gcry_mpi_set_ui (NULL, 11371); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0)) fail ("new point not initialized to (0,0,0)\n"); gcry_mpi_point_snatch_get (x, y, z, point); point = NULL; if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0)) fail ("snatch_get failed\n"); gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (z); point = gcry_mpi_point_new (0); x = gcry_mpi_set_ui (NULL, 17); y = gcry_mpi_set_ui (NULL, 42); z = gcry_mpi_set_ui (NULL, 11371); gcry_mpi_point_set (point, x, y, z); gcry_mpi_set_ui (x, 23); gcry_mpi_set_ui (y, 24); gcry_mpi_set_ui (z, 25); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 17) || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371)) fail ("point_set/point_get failed\n"); gcry_mpi_point_snatch_set (point, x, y, z); x = gcry_mpi_new (0); y = gcry_mpi_new (0); z = gcry_mpi_new (0); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 17) || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371)) fail ("point_snatch_set/point_get failed\n"); gcry_mpi_point_release (point); gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (z); }
int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute start; struct GNUNET_CRYPTO_PaillierPublicKey public_key; struct GNUNET_CRYPTO_PaillierPrivateKey private_key; struct GNUNET_CRYPTO_PaillierCiphertext c1; gcry_mpi_t m1; unsigned int i; start = GNUNET_TIME_absolute_get (); for (i=0;i<10;i++) GNUNET_CRYPTO_paillier_create (&public_key, &private_key); printf ("10x key generation took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Paillier key generation", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "keys/ms"); m1 = gcry_mpi_new (0); m1 = gcry_mpi_set_ui (m1, 1); /* m1 = m1 * 2 ^ (GCPB - 3) */ gcry_mpi_mul_2exp (m1, m1, GNUNET_CRYPTO_PAILLIER_BITS - 3); start = GNUNET_TIME_absolute_get (); for (i=0;i<10;i++) GNUNET_CRYPTO_paillier_encrypt (&public_key, m1, 2, &c1); printf ("10x encryption took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Paillier encryption", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "ops/ms"); start = GNUNET_TIME_absolute_get (); for (i=0;i<10;i++) GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key, &c1, m1); printf ("10x decryption took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Paillier decryption", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "ops/ms"); return 0; }
int crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n) { gcry_mpi_t mpi_basepoint_x = gcry_mpi_set_ui(NULL, 9); int r = x25519_mpi(q, n, mpi_basepoint_x); gcry_mpi_release(mpi_basepoint_x); return r; }
static void mpz_tdiv_q_2exp (gcry_mpi_t q, gcry_mpi_t n, unsigned int b) { gcry_mpi_t u, d; u = gcry_mpi_set_ui (NULL, 1); d = gcry_mpi_new (0); gcry_mpi_mul_2exp (d, u, b); gcry_mpi_div (q, NULL, n, d, 0); }
void* mod_exp(void* mod_exp_operands) { struct mod_exp_operands* op = (struct mod_exp_operands*) mod_exp_operands; unsigned long int g = op->g; unsigned long int e = op->e; unsigned long int n = op->n; unsigned long int ans; gcry_mpi_t ans_mpi = gcry_mpi_new(10); gcry_mpi_t g_mpi = gcry_mpi_new(10); gcry_mpi_t e_mpi = gcry_mpi_new(10); gcry_mpi_t n_mpi = gcry_mpi_new(10); printf("Value of g: %lu\n",g); g_mpi = gcry_mpi_set_ui(g_mpi, g); printf("Value of e: %lu\n",e); e_mpi = gcry_mpi_set_ui(e_mpi, e); printf("Value of n: %lu\n",n); n_mpi = gcry_mpi_set_ui(n_mpi, n); gcry_mpi_powm(ans_mpi, g_mpi,e_mpi,n_mpi); }
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); // } }
int ssh_gcry_dec2bn(bignum *bn, const char *data) { int count; *bn = bignum_new(); if (*bn == NULL) { return 0; } gcry_mpi_set_ui(*bn, 0); for (count = 0; data[count]; count++) { gcry_mpi_mul_ui(*bn, *bn, 10); gcry_mpi_add_ui(*bn, *bn, data[count] - '0'); } return count; }
/* Sign data using a private key. The data must be small enough to be * signed (i.e. already hashed, if necessary). The signature will be * returned in *sigp, which the caller must free(). Its length will be * returned in *siglenp. */ gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp, OtrlPrivKey *privkey, const unsigned char *data, size_t len) { gcry_mpi_t r,s, datampi; gcry_sexp_t dsas, rs, ss, sigs, datas; size_t nr, ns; const enum gcry_mpi_format format = GCRYMPI_FMT_USG; if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA) return gcry_error(GPG_ERR_INV_VALUE); *sigp = malloc(40); if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM); *siglenp = 40; if (len) { gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL); } else { datampi = gcry_mpi_set_ui(NULL, 0); } gcry_sexp_build(&datas, NULL, "(%m)", datampi); gcry_mpi_release(datampi); gcry_pk_sign(&sigs, datas, privkey->privkey); gcry_sexp_release(datas); dsas = gcry_sexp_find_token(sigs, "dsa", 0); gcry_sexp_release(sigs); rs = gcry_sexp_find_token(dsas, "r", 0); ss = gcry_sexp_find_token(dsas, "s", 0); gcry_sexp_release(dsas); r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG); gcry_sexp_release(rs); s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG); gcry_sexp_release(ss); gcry_mpi_print(format, NULL, 0, &nr, r); gcry_mpi_print(format, NULL, 0, &ns, s); memset(*sigp, 0, 40); gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r); gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s); gcry_mpi_release(r); gcry_mpi_release(s); return gcry_error(GPG_ERR_NO_ERROR); }
void gotr_ecbd_gen_circle_key(gcry_mpi_point_t *ret, gcry_mpi_point_t *X, gcry_mpi_point_t Z, gcry_mpi_t r) { gcry_mpi_point_t tmp = gcry_mpi_point_new(0); gcry_mpi_t n = gcry_mpi_new(0); unsigned int i; gcry_mpi_point_release(*ret); *ret = gcry_mpi_point_set(NULL, NULL, GCRYMPI_CONST_ONE, GCRYMPI_CONST_ONE); for (i = 0; X[i]; i++) { gcry_mpi_set_ui(n, i+1); gcry_mpi_ec_mul(tmp, n, X[i], edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); } gcry_mpi_mul_ui(n, r, i+1); gcry_mpi_ec_mul(tmp, n, Z, edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); gcry_mpi_release(n); gcry_mpi_point_release(tmp); }
void serialize_mpi(char *outbuf, int outlen, enum disp_format df, const gcry_mpi_t x) { switch(df) { case DF_BIN: do { int len = (gcry_mpi_get_nbits(x) + 7) / 8; assert(len <= outlen); memset(outbuf, 0, outlen - len); gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*)outbuf + (outlen - len), len, NULL, x); } while (0); break; case DF_COMPACT: case DF_BASE36: do { const char *digits = get_digits(df); unsigned int digit_count = get_digit_count(df); gcry_mpi_t base, Q, R; int i; base = gcry_mpi_set_ui(NULL, digit_count); Q = gcry_mpi_copy(x); R = gcry_mpi_snew(0); for(i = outlen - 1; i >= 0; i--) { unsigned char digit = 0; gcry_mpi_div(Q, R, Q, base, 0); gcry_mpi_print(GCRYMPI_FMT_USG, &digit, 1, NULL, R); assert(digit < digit_count); outbuf[i] = digits[digit]; } assert(! gcry_mpi_cmp_ui(Q, 0)); gcry_mpi_release(base); gcry_mpi_release(Q); gcry_mpi_release(R); } while(0); break; default: assert(0); } }
static void mpz_randomize (gcry_mpi_t n, unsigned int nbits, struct GNUNET_HashCode * rnd) { struct GNUNET_HashCode hc; struct GNUNET_HashCode tmp; int bits_per_hc = sizeof (struct GNUNET_HashCode) * 8; int cnt; int i; GNUNET_assert (nbits > 0); cnt = (nbits + bits_per_hc - 1) / bits_per_hc; gcry_mpi_set_ui (n, 0); tmp = *rnd; for (i = 0; i < cnt; i++) { int j; if (i > 0) GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), &tmp); for (j = 0; j < sizeof (struct GNUNET_HashCode) / sizeof (uint32_t); j++) { #if HAVE_GCRY_MPI_LSHIFT gcry_mpi_lshift (n, n, sizeof (uint32_t) * 8); #else gcry_mpi_mul_ui (n, n, 1 << (sizeof (uint32_t) * 4)); gcry_mpi_mul_ui (n, n, 1 << (sizeof (uint32_t) * 4)); #endif gcry_mpi_add_ui (n, n, ntohl (((uint32_t *) & tmp)[j])); } hc = tmp; } GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), rnd); i = gcry_mpi_get_nbits (n); while (i > nbits) gcry_mpi_clear_bit (n, --i); }
int get_serialization_len(const gcry_mpi_t x, enum disp_format df) { int res; switch(df) { case DF_BIN: res = (gcry_mpi_get_nbits(x) + 7) / 8; break; case DF_BASE36: case DF_COMPACT: do { gcry_mpi_t base, Q; base = gcry_mpi_set_ui(NULL, get_digit_count(df)); Q = gcry_mpi_copy(x); for(res = 0; gcry_mpi_cmp_ui(Q, 0); res++) gcry_mpi_div(Q, NULL, Q, base, 0); gcry_mpi_release(base); gcry_mpi_release(Q); } while (0); break; default: assert(0); } return res; }
nuts_mpi_t nuts_mpi_new_ul(const unsigned long ul) { gcry_check(); return nuts_mpi_alloc(gcry_mpi_set_ui(NULL, ul)); }
/* fixme: we need better tests */ static void basic (void) { int pass; gcry_sexp_t sexp; int idx; char *secure_buffer; size_t secure_buffer_len; const char *string; static struct { const char *token; const char *parm; } values[] = { { "public-key", NULL }, { "dsa", NULL }, { "dsa", "p" }, { "dsa", "y" }, { "dsa", "q" }, { "dsa", "g" }, { NULL } }; info ("doing some pretty pointless tests\n"); secure_buffer_len = 99; secure_buffer = gcry_xmalloc_secure (secure_buffer_len); memset (secure_buffer, 'G', secure_buffer_len); for (pass=0;;pass++) { gcry_mpi_t m; switch (pass) { case 0: string = ("(public-key (dsa (p #41424344#) (y this_is_y) " "(q #61626364656667#) (g %m)))"); m = gcry_mpi_set_ui (NULL, 42); if ( gcry_sexp_build (&sexp, NULL, string, m ) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); break; case 1: string = ("(public-key (dsa (p #41424344#) (y this_is_y) " "(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 42); if ( gcry_sexp_build (&sexp, NULL, string, 15, "foo\0\x01\0x02789012345", m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); break; case 2: string = ("(public-key (dsa (p #41424344#) (y silly_y_value) " "(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 17); if ( gcry_sexp_build (&sexp, NULL, string, secure_buffer_len, secure_buffer, m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); if (!gcry_is_secure (sexp)) fail ("gcry_sexp_build did not switch to secure memory\n"); break; case 3: { gcry_sexp_t help_sexp; if (gcry_sexp_new (&help_sexp, "(foobar-parms (xp #1234#)(xq #03#))", 0, 1)) { fail (" scanning fixed string failed\n"); return; } string = ("(public-key (dsa (p #41424344#) (parm %S) " "(y dummy)(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 17); if ( gcry_sexp_build (&sexp, NULL, string, help_sexp, secure_buffer_len, secure_buffer, m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); gcry_sexp_release (help_sexp); } break; default: return; /* Ready. */ } /* now find something */ for (idx=0; values[idx].token; idx++) { const char *token = values[idx].token; const char *parm = values[idx].parm; gcry_sexp_t s1, s2; gcry_mpi_t a; const char *p; size_t n; s1 = gcry_sexp_find_token (sexp, token, strlen(token) ); if (!s1) { fail ("didn't found `%s'\n", token); continue; } p = gcry_sexp_nth_data (s1, 0, &n); if (!p) { gcry_sexp_release (s1); fail ("no car for `%s'\n", token); continue; } info ("car=`%.*s'\n", (int)n, p); s2 = gcry_sexp_cdr (s1); if (!s2) { gcry_sexp_release (s1); fail ("no cdr for `%s'\n", token); continue; } p = gcry_sexp_nth_data (s2, 0, &n); gcry_sexp_release (s2); if (p) { gcry_sexp_release (s1); fail ("data at car of `%s'\n", token); continue; } if (parm) { s2 = gcry_sexp_find_token (s1, parm, strlen (parm)); gcry_sexp_release (s1); if (!s2) { fail ("didn't found `%s'\n", parm); continue; } p = gcry_sexp_nth_data (s2, 0, &n); if (!p) { gcry_sexp_release (s2); fail("no car for `%s'\n", parm ); continue; } info ("car=`%.*s'\n", (int)n, p); p = gcry_sexp_nth_data (s2, 1, &n); if (!p) { gcry_sexp_release (s2); fail("no cdr for `%s'\n", parm ); continue; } info ("cdr=`%.*s'\n", (int)n, p); a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG); gcry_sexp_release (s2); if (!a) { fail("failed to cdr the mpi for `%s'\n", parm); continue; } gcry_mpi_release (a); } else gcry_sexp_release (s1); } gcry_sexp_release (sexp); sexp = NULL; } gcry_free (secure_buffer); }
void attack(int i, unsigned char *digest, int hash_len){ void* dsa_buf; gcry_sexp_t new_dsa_key_pair; gcry_sexp_t ciphertext , plaintext, ptx2, ctx2; gcry_sexp_t r_param, r_tilda_param; gcry_sexp_t s_param, s_tilda_param; gcry_sexp_t g_param; gcry_sexp_t p_param; gcry_sexp_t q_param; gcry_sexp_t m_param; gcry_sexp_t y_param; gcry_sexp_t x_param; gcry_sexp_t misc_param; gcry_error_t err; gcry_mpi_t msg_digest, m; gcry_mpi_t r , r_tilda; gcry_mpi_t s , s_tilda; gcry_mpi_t g; gcry_mpi_t p; gcry_mpi_t q; gcry_mpi_t y; gcry_mpi_t x; retrieve_key_pair(files[i]); //*************** CORRECT SIGNATURE ********************// //20 is the mdlen of sha1 as specified in https://lists.gnupg.org/pipermail/gnupg-devel/2013-September/027916.html //a well formatted number for the immaediate has an even number of digits err = gcry_sexp_build(&plaintext, NULL, "(data (flags rfc6979) (hash %s %b))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ciphertext, plaintext, dsa_key_pair); //now let's convert the s-expression representing r into an MPI in order //to use it in the equation of the attack //--------- CIPHERTEXT -------------- //intercepted during some sniffing... r_param = gcry_sexp_find_token(ciphertext, "r", 0); r = gcry_sexp_nth_mpi ( r_param , 1, GCRYMPI_FMT_USG); s_param = gcry_sexp_find_token(ciphertext, "s", 0); s = gcry_sexp_nth_mpi ( s_param , 1, GCRYMPI_FMT_USG); //--------- PUB KEY -------------- g_param = gcry_sexp_find_token(dsa_key_pair, "g", 0); g = gcry_sexp_nth_mpi ( g_param , 1, GCRYMPI_FMT_USG); p_param = gcry_sexp_find_token(dsa_key_pair, "p", 0); p = gcry_sexp_nth_mpi ( p_param , 1, GCRYMPI_FMT_USG); q_param = gcry_sexp_find_token(dsa_key_pair, "q", 0); q = gcry_sexp_nth_mpi ( q_param , 1, GCRYMPI_FMT_USG); y_param = gcry_sexp_find_token(dsa_key_pair, "y", 0); y = gcry_sexp_nth_mpi ( y_param , 1, GCRYMPI_FMT_USG); x_param = gcry_sexp_find_token(dsa_key_pair, "x", 0); x = gcry_sexp_nth_mpi ( x_param , 1, GCRYMPI_FMT_USG); misc_param = gcry_sexp_find_token(dsa_key_pair, "misc-key-info", 0); //*************** FAULTY SIGNATURE ********************// err = gcry_sexp_build(&ptx2, NULL, "(data (flags rfc6979) (hash %s %b) (attack2_byte))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ctx2, ptx2, dsa_key_pair); s_tilda_param = gcry_sexp_find_token(ctx2, "s", 0); s_tilda = gcry_sexp_nth_mpi ( s_tilda_param , 1, GCRYMPI_FMT_USG); r_tilda_param = gcry_sexp_find_token(ctx2, "r", 0); r_tilda = gcry_sexp_nth_mpi ( r_tilda_param , 1, GCRYMPI_FMT_USG); m_param = gcry_sexp_find_token(ptx2, "hash", 0); m = gcry_sexp_nth_mpi ( m_param , 2, GCRYMPI_FMT_USG); //NOW LET'S START THE ATTACK unsigned long e = 0; unsigned int qbits = mpi_get_nbits(q); unsigned int pbits = mpi_get_nbits(p); int hash_len_bits = hash_len*8; gcry_mpi_t one = gcry_mpi_set_ui(NULL, 1); gcry_mpi_t tmp = gcry_mpi_new(qbits); gcry_mpi_t result = gcry_mpi_new(mpi_get_nbits(s)); gcry_mpi_invm(r,r,q); // r^-1 unsigned int j; for(e = 0; e < qbits ; e++){ gcry_mpi_t empi = gcry_mpi_set_ui(NULL,e); gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(empi, one, e); // twoi = 2^e for( j=0; j< 256 ; j++){ gcry_mpi_t jmpi = gcry_mpi_set_ui(NULL,j); gcry_mpi_mulm(twoi,jmpi,empi,q); //retrieve k gcry_mpi_mulm(tmp, s_tilda, twoi, q); // s_tilda*(2^e) modq q gcry_mpi_subm(result, s_tilda, s, q); // s_tilda - s mod q gcry_mpi_invm(result, result, q); // (s_tilda - s mod q)^-1 gcry_mpi_mulm(result,result, tmp, q); // s_tilda*(2^3) mod q)*(s_tilda - s mod q)^-1 === k //retrieve x gcry_mpi_mulm(result, s, result,q); // s*k mod q gcry_mpi_subm(result, result, m, q); // s*k - m mod q gcry_mpi_mulm(result, result,r,q); //(s*k -m)*r^-1 mod q err = gcry_sexp_build(&new_dsa_key_pair,NULL, "(key-data" " (public-key" " (dsa(p%m)(q%m)(g%m)(y%m)))" " (private-key" " (dsa(p%m)(q%m)(g%m)(y%m)(x%m))))", p,q,g,y,p,q,g,y,result); err = gcry_pk_sign(&ctx2, plaintext, new_dsa_key_pair); err = gcry_pk_verify(ctx2, plaintext, dsa_key_pair); if (err) { //puts("gcrypt: verify failed"); continue; } else{ printf("\n[!!!]PRIVATE KEY %d %d BITS CRACKED!!\n" , pbits,qbits ); printf("[DBG] BYTE : %d * 2^%d FAULT: k-j*2^%d\n" , j , (int)e,(int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } } for(e = 0; e < qbits; e++){ gcry_mpi_t empi = gcry_mpi_set_ui(NULL,e); gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(empi, one, e); // twoi = 2^e for( j=0; j< 256 ; j++){ gcry_mpi_t jmpi = gcry_mpi_set_ui(NULL,j); gcry_mpi_mulm(twoi,jmpi,empi,q); //retrieve k gcry_mpi_mulm(tmp, s_tilda, twoi, q); // s_tilda*(2^e) modq q gcry_mpi_subm(result, s, s_tilda, q); // s_tilda - s mod q gcry_mpi_invm(result, result, q); // (s_tilda - s mod q)^-1 gcry_mpi_mulm(result,result, tmp, q); // s_tilda*(2^3) mod q)*(s_tilda - s mod q)^-1 === k //retrieve x gcry_mpi_mulm(result, s, result,q); // s*k mod q gcry_mpi_subm(result, result, m, q); // s*k - m mod q gcry_mpi_mulm(result, result,r,q); //(s*k -m)*r^-1 mod q err = gcry_sexp_build(&new_dsa_key_pair,NULL, "(key-data" " (public-key" " (dsa(p%m)(q%m)(g%m)(y%m)))" " (private-key" " (dsa(p%m)(q%m)(g%m)(y%m)(x%m))))", p,q,g,y,p,q,g,y,result); err = gcry_pk_sign(&ctx2, plaintext, new_dsa_key_pair); err = gcry_pk_verify(ctx2, plaintext, dsa_key_pair); if (err) { continue; } else{ printf("\n[!!!]PRIVATE KEY %d %d BITS CRACKED!!\n" , pbits,qbits ); printf("[DBG] BYTE : %d * 2^%d FAULT: k+j*2^%d\n" , j , (int)e,(int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } } }
/* Find a generator for PRIME where the factorization of (prime-1) is in the NULL terminated array FACTORS. Return the generator as a newly allocated MPI in R_G. If START_G is not NULL, use this as s atart for the search. Returns 0 on success.*/ gcry_error_t gcry_prime_group_generator (gcry_mpi_t *r_g, gcry_mpi_t prime, gcry_mpi_t *factors, gcry_mpi_t start_g) { gcry_mpi_t tmp = gcry_mpi_new (0); gcry_mpi_t b = gcry_mpi_new (0); gcry_mpi_t pmin1 = gcry_mpi_new (0); gcry_mpi_t g = start_g? gcry_mpi_copy (start_g) : gcry_mpi_set_ui (NULL, 3); int first = 1; int i, n; if (!factors || !r_g || !prime) return gpg_error (GPG_ERR_INV_ARG); *r_g = NULL; for (n=0; factors[n]; n++) ; if (n < 2) return gpg_error (GPG_ERR_INV_ARG); /* Extra sanity check - usually disabled. */ /* mpi_set (tmp, factors[0]); */ /* for(i = 1; i < n; i++) */ /* mpi_mul (tmp, tmp, factors[i]); */ /* mpi_add_ui (tmp, tmp, 1); */ /* if (mpi_cmp (prime, tmp)) */ /* return gpg_error (GPG_ERR_INV_ARG); */ gcry_mpi_sub_ui (pmin1, prime, 1); do { if (first) first = 0; else gcry_mpi_add_ui (g, g, 1); if (DBG_CIPHER) { log_debug ("checking g:"); gcry_mpi_dump (g); log_debug ("\n"); } else progress('^'); for (i = 0; i < n; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); gcry_mpi_powm (b, g, tmp, prime); if (! mpi_cmp_ui (b, 1)) break; } if (DBG_CIPHER) progress('\n'); } while (i < n); gcry_mpi_release (tmp); gcry_mpi_release (b); gcry_mpi_release (pmin1); *r_g = g; return 0; }
/**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. With ALL_FACTORS set to true all afcors of * prime-1 are returned in FACTORS. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ static gcry_err_code_t prime_generate_internal (int mode, gcry_mpi_t *prime_generated, unsigned int pbits, unsigned int qbits, gcry_mpi_t g, gcry_mpi_t **ret_factors, gcry_random_level_t randomlevel, unsigned int flags, int all_factors, gcry_prime_check_func_t cb_func, void *cb_arg) { gcry_err_code_t err = 0; gcry_mpi_t *factors_new = NULL; /* Factors to return to the caller. */ gcry_mpi_t *factors = NULL; /* Current factors. */ gcry_mpi_t *pool = NULL; /* Pool of primes. */ unsigned char *perms = NULL; /* Permutations of POOL. */ gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */ unsigned int fbits = 0; /* Length of prime factors. */ unsigned int n = 0; /* Number of factors. */ unsigned int m = 0; /* Number of primes in pool. */ gcry_mpi_t q = NULL; /* First prime factor. */ gcry_mpi_t prime = NULL; /* Prime candidate. */ unsigned int nprime = 0; /* Bits of PRIME. */ unsigned int req_qbits; /* The original QBITS value. */ gcry_mpi_t val_2; /* For check_prime(). */ unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET); unsigned int count1 = 0, count2 = 0; unsigned int i = 0, j = 0; if (pbits < 48) return GPG_ERR_INV_ARG; /* If QBITS is not given, assume a reasonable value. */ if (!qbits) qbits = pbits / 3; req_qbits = qbits; /* Find number of needed prime factors. */ for (n = 1; (pbits - qbits - 1) / n >= qbits; n++) ; n--; val_2 = mpi_alloc_set_ui (2); if ((! n) || ((mode == 1) && (n < 2))) { err = GPG_ERR_INV_ARG; goto leave; } if (mode == 1) { n--; fbits = (pbits - 2 * req_qbits -1) / n; qbits = pbits - req_qbits - n * fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n * fbits; } if (DBG_CIPHER) log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n); prime = gcry_mpi_new (pbits); /* Generate first prime factor. */ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); if (mode == 1) q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); /* Allocate an array to hold the factors + 2 for later usage. */ factors = gcry_calloc (n + 2, sizeof (*factors)); if (!factors) { err = gpg_err_code_from_errno (errno); goto leave; } /* Make a pool of 3n+5 primes (this is an arbitrary value). */ m = n * 3 + 5; if (mode == 1) /* Need some more (for e.g. DSA). */ m += 5; if (m < 25) m = 25; pool = gcry_calloc (m , sizeof (*pool)); if (! pool) { err = gpg_err_code_from_errno (errno); goto leave; } /* Permutate over the pool of primes. */ do { next_try: if (! perms) { /* Allocate new primes. */ for(i = 0; i < m; i++) { mpi_free (pool[i]); pool[i] = NULL; } /* Init m_out_of_n(). */ perms = gcry_calloc (1, m); if (! perms) { err = gpg_err_code_from_errno (errno); goto leave; } for(i = 0; i < n; i++) { perms[i] = 1; pool[i] = gen_prime (fbits, is_secret, randomlevel, NULL, NULL); factors[i] = pool[i]; } } else { m_out_of_n ((char*)perms, n, m); for (i = j = 0; (i < m) && (j < n); i++) if (perms[i]) { if(! pool[i]) pool[i] = gen_prime (fbits, 0, 1, NULL, NULL); factors[j++] = pool[i]; } if (i == n) { gcry_free (perms); perms = NULL; progress ('!'); goto next_try; /* Allocate new primes. */ } } /* Generate next prime candidate: p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. */ mpi_set (prime, q); mpi_mul_ui (prime, prime, 2); if (mode == 1) mpi_mul (prime, prime, q_factor); for(i = 0; i < n; i++) mpi_mul (prime, prime, factors[i]); mpi_add_ui (prime, prime, 1); nprime = mpi_get_nbits (prime); if (nprime < pbits) { if (++count1 > 20) { count1 = 0; qbits++; progress('>'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count1 = 0; if (nprime > pbits) { if (++count2 > 20) { count2 = 0; qbits--; progress('<'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count2 = 0; } while (! ((nprime == pbits) && check_prime (prime, val_2, cb_func, cb_arg))); if (DBG_CIPHER) { progress ('\n'); log_mpidump ("prime : ", prime); log_mpidump ("factor q: ", q); if (mode == 1) log_mpidump ("factor q0: ", q_factor); for (i = 0; i < n; i++) log_mpidump ("factor pi: ", factors[i]); log_debug ("bit sizes: prime=%u, q=%u", mpi_get_nbits (prime), mpi_get_nbits (q)); if (mode == 1) log_debug (", q0=%u", mpi_get_nbits (q_factor)); for (i = 0; i < n; i++) log_debug (", p%d=%u", i, mpi_get_nbits (factors[i])); progress('\n'); } if (ret_factors) { /* Caller wants the factors. */ factors_new = gcry_calloc (n + 4, sizeof (*factors_new)); if (! factors_new) { err = gpg_err_code_from_errno (errno); goto leave; } if (all_factors) { i = 0; factors_new[i++] = gcry_mpi_set_ui (NULL, 2); factors_new[i++] = mpi_copy (q); if (mode == 1) factors_new[i++] = mpi_copy (q_factor); for(j=0; j < n; j++) factors_new[i++] = mpi_copy (factors[j]); } else { i = 0; if (mode == 1) { factors_new[i++] = mpi_copy (q_factor); for (; i <= n; i++) factors_new[i] = mpi_copy (factors[i]); } else for (; i < n; i++ ) factors_new[i] = mpi_copy (factors[i]); } } if (g) { /* Create a generator (start with 3). */ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); if (mode == 1) err = GPG_ERR_NOT_IMPLEMENTED; else { factors[n] = q; factors[n + 1] = mpi_alloc_set_ui (2); mpi_sub_ui (pmin1, prime, 1); mpi_set_ui (g, 2); do { mpi_add_ui (g, g, 1); if (DBG_CIPHER) { log_debug ("checking g:"); gcry_mpi_dump (g); log_printf ("\n"); } else progress('^'); for (i = 0; i < n + 2; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); /* No mpi_pow(), but it is okay to use this with mod prime. */ gcry_mpi_powm (b, g, tmp, prime); if (! mpi_cmp_ui (b, 1)) break; } if (DBG_CIPHER) progress('\n'); } while (i < n + 2); mpi_free (factors[n+1]); mpi_free (tmp); mpi_free (b); mpi_free (pmin1); } } if (! DBG_CIPHER) progress ('\n'); leave: if (pool) { for(i = 0; i < m; i++) mpi_free (pool[i]); gcry_free (pool); } if (factors) gcry_free (factors); /* Factors are shallow copies. */ if (perms) gcry_free (perms); mpi_free (val_2); mpi_free (q); mpi_free (q_factor); if (! err) { *prime_generated = prime; if (ret_factors) *ret_factors = factors_new; } else { if (factors_new) { for (i = 0; factors_new[i]; i++) mpi_free (factors_new[i]); gcry_free (factors_new); } mpi_free (prime); } return err; }
/** * Generate a key pair with a key of size NBITS. * @param sk where to store the key * @param nbits the number of bits to use * @param hc the HC to use for PRNG (modified!) */ static void generate_kblock_key (KBlock_secret_key *sk, unsigned int nbits, struct GNUNET_HashCode * hc) { gcry_mpi_t t1, t2; gcry_mpi_t phi; /* helper: (p-1)(q-1) */ gcry_mpi_t g; gcry_mpi_t f; /* make sure that nbits is even so that we generate p, q of equal size */ if ((nbits & 1)) nbits++; sk->e = gcry_mpi_set_ui (NULL, 257); sk->n = gcry_mpi_new (0); sk->p = gcry_mpi_new (0); sk->q = gcry_mpi_new (0); sk->d = gcry_mpi_new (0); sk->u = gcry_mpi_new (0); t1 = gcry_mpi_new (0); t2 = gcry_mpi_new (0); phi = gcry_mpi_new (0); g = gcry_mpi_new (0); f = gcry_mpi_new (0); do { do { gcry_mpi_release (sk->p); gcry_mpi_release (sk->q); gen_prime (&sk->p, nbits / 2, hc); gen_prime (&sk->q, nbits / 2, hc); if (gcry_mpi_cmp (sk->p, sk->q) > 0) /* p shall be smaller than q (for calc of u) */ gcry_mpi_swap (sk->p, sk->q); /* calculate the modulus */ gcry_mpi_mul (sk->n, sk->p, sk->q); } while (gcry_mpi_get_nbits (sk->n) != nbits); /* calculate Euler totient: phi = (p-1)(q-1) */ gcry_mpi_sub_ui (t1, sk->p, 1); gcry_mpi_sub_ui (t2, sk->q, 1); gcry_mpi_mul (phi, t1, t2); gcry_mpi_gcd (g, t1, t2); gcry_mpi_div (f, NULL, phi, g, 0); while (0 == gcry_mpi_gcd (t1, sk->e, phi)) { /* (while gcd is not 1) */ gcry_mpi_add_ui (sk->e, sk->e, 2); } /* calculate the secret key d = e^1 mod phi */ } while ((0 == gcry_mpi_invm (sk->d, sk->e, f)) || (0 == gcry_mpi_invm (sk->u, sk->p, sk->q))); gcry_mpi_release (t1); gcry_mpi_release (t2); gcry_mpi_release (phi); gcry_mpi_release (f); gcry_mpi_release (g); }