void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(msk + 0); p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); n = gcry_mpi_new(0); gcry_mpi_mul(n, p, q); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ store_secpar(state + 0, secpar); mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n); mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); gcry_mpi_release(p); gcry_mpi_release(q); gcry_mpi_release(n); gcry_mpi_release(x); gcry_mpi_release(xp); gcry_mpi_release(xq); gcry_mpi_release(kp); gcry_mpi_release(kq); gcry_mpi_release(xm); }
void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN]; gcry_mpi_t n, p, q; uint16_t secpar; VALIDATE_SECPAR(_secpar); secpar = _secpar; initialize_libgcrypt(); if (!seed) { gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); seed = iseed; seedlen = FSPRG_RECOMMENDED_SEEDLEN; } p = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_P); q = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_Q); if (msk) { store_secpar(msk + 0, secpar); mpi_export(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8, p); mpi_export(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8, q); } if (mpk) { n = gcry_mpi_new(0); gcry_mpi_mul(n, p, q); assert(gcry_mpi_get_nbits(n) == secpar); store_secpar(mpk + 0, secpar); mpi_export(mpk + 2, secpar / 8, n); gcry_mpi_release(n); } gcry_mpi_release(p); gcry_mpi_release(q); }
static int test_mul (void) { gcry_mpi_t two; gcry_mpi_t three; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); gcry_mpi_scan(&three, GCRYMPI_FMT_USG, threes, sizeof(threes), NULL); result = gcry_mpi_new(0); gcry_mpi_mul(result, two, three); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of two mul three:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(two); gcry_mpi_release(three); gcry_mpi_release(result); return 1; }
/** * 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); }
/* Compute and print missing RSA parameters. */ static void compute_missing (gcry_mpi_t rsa_p, gcry_mpi_t rsa_q, gcry_mpi_t rsa_e) { gcry_mpi_t rsa_n, rsa_d, rsa_pm1, rsa_qm1, rsa_u; gcry_mpi_t phi, tmp_g, tmp_f; rsa_n = gcry_mpi_new (0); rsa_d = gcry_mpi_new (0); rsa_pm1 = gcry_mpi_new (0); rsa_qm1 = gcry_mpi_new (0); rsa_u = gcry_mpi_new (0); phi = gcry_mpi_new (0); tmp_f = gcry_mpi_new (0); tmp_g = gcry_mpi_new (0); /* Check that p < q; if not swap p and q. */ if (openpgp_mode && gcry_mpi_cmp (rsa_p, rsa_q) > 0) { fprintf (stderr, PGM ": swapping p and q\n"); gcry_mpi_swap (rsa_p, rsa_q); } gcry_mpi_mul (rsa_n, rsa_p, rsa_q); /* Compute the Euler totient: phi = (p-1)(q-1) */ gcry_mpi_sub_ui (rsa_pm1, rsa_p, 1); gcry_mpi_sub_ui (rsa_qm1, rsa_q, 1); gcry_mpi_mul (phi, rsa_pm1, rsa_qm1); if (!gcry_mpi_gcd (tmp_g, rsa_e, phi)) die ("parameter 'e' does match 'p' and 'q'\n"); /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */ gcry_mpi_gcd (tmp_g, rsa_pm1, rsa_qm1); gcry_mpi_div (tmp_f, NULL, phi, tmp_g, -1); /* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */ gcry_mpi_invm (rsa_d, rsa_e, tmp_f); /* Compute the CRT helpers: d mod (p-1), d mod (q-1) */ gcry_mpi_mod (rsa_pm1, rsa_d, rsa_pm1); gcry_mpi_mod (rsa_qm1, rsa_d, rsa_qm1); /* Compute the CRT value: OpenPGP: u = p^{-1} mod q Standard: iqmp = q^{-1} mod p */ if (openpgp_mode) gcry_mpi_invm (rsa_u, rsa_p, rsa_q); else gcry_mpi_invm (rsa_u, rsa_q, rsa_p); gcry_mpi_release (phi); gcry_mpi_release (tmp_f); gcry_mpi_release (tmp_g); /* Print everything. */ print_mpi_line ("n", rsa_n); print_mpi_line ("e", rsa_e); if (openpgp_mode) print_mpi_line ("d", rsa_d); print_mpi_line ("p", rsa_p); print_mpi_line ("q", rsa_q); if (openpgp_mode) print_mpi_line ("u", rsa_u); else { print_mpi_line ("dmp1", rsa_pm1); print_mpi_line ("dmq1", rsa_qm1); print_mpi_line ("iqmp", rsa_u); } gcry_mpi_release (rsa_n); gcry_mpi_release (rsa_d); gcry_mpi_release (rsa_pm1); gcry_mpi_release (rsa_qm1); gcry_mpi_release (rsa_u); }
void gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) { gcry_mpi_mul (w, u, v); _gcry_mpi_tdiv_r (w, w, m); }
/* Check that the RSA secret key SKEY is valid. Swap parameters to the libgcrypt standard. */ static gpg_error_t rsa_key_check (struct rsa_secret_key_s *skey) { int err = 0; gcry_mpi_t t = gcry_mpi_snew (0); gcry_mpi_t t1 = gcry_mpi_snew (0); gcry_mpi_t t2 = gcry_mpi_snew (0); gcry_mpi_t phi = gcry_mpi_snew (0); /* Check that n == p * q. */ gcry_mpi_mul (t, skey->p, skey->q); if (gcry_mpi_cmp( t, skey->n) ) { log_error ("RSA oops: n != p * q\n"); err++; } /* Check that p is less than q. */ if (gcry_mpi_cmp (skey->p, skey->q) > 0) { gcry_mpi_t tmp; log_info ("swapping secret primes\n"); tmp = gcry_mpi_copy (skey->p); gcry_mpi_set (skey->p, skey->q); gcry_mpi_set (skey->q, tmp); gcry_mpi_release (tmp); /* Recompute u. */ gcry_mpi_invm (skey->u, skey->p, skey->q); } /* Check that e divides neither p-1 nor q-1. */ gcry_mpi_sub_ui (t, skey->p, 1 ); gcry_mpi_div (NULL, t, t, skey->e, 0); if (!gcry_mpi_cmp_ui( t, 0) ) { log_error ("RSA oops: e divides p-1\n"); err++; } gcry_mpi_sub_ui (t, skey->q, 1); gcry_mpi_div (NULL, t, t, skey->e, 0); if (!gcry_mpi_cmp_ui( t, 0)) { log_info ("RSA oops: e divides q-1\n" ); err++; } /* Check that d is correct. */ gcry_mpi_sub_ui (t1, skey->p, 1); gcry_mpi_sub_ui (t2, skey->q, 1); gcry_mpi_mul (phi, t1, t2); gcry_mpi_invm (t, skey->e, phi); if (gcry_mpi_cmp (t, skey->d)) { /* No: try universal exponent. */ gcry_mpi_gcd (t, t1, t2); gcry_mpi_div (t, NULL, phi, t, 0); gcry_mpi_invm (t, skey->e, t); if (gcry_mpi_cmp (t, skey->d)) { log_error ("RSA oops: bad secret exponent\n"); err++; } } /* Check for correctness of u. */ gcry_mpi_invm (t, skey->p, skey->q); if (gcry_mpi_cmp (t, skey->u)) { log_info ("RSA oops: bad u parameter\n"); err++; } if (err) log_info ("RSA secret key check failed\n"); gcry_mpi_release (t); gcry_mpi_release (t1); gcry_mpi_release (t2); gcry_mpi_release (phi); return err? gpg_error (GPG_ERR_BAD_SECKEY):0; }