/* Blinds the c, by computing c *= r^e (mod n), for a random r. Also returns the inverse (ri), for use by rsa_unblind. */ void _rsa_blind (const struct rsa_public_key *pub, void *random_ctx, nettle_random_func *random, mpz_t c, mpz_t ri) { mpz_t r; mpz_init(r); /* c = c*(r^e) * ri = r^(-1) */ do { nettle_mpz_random(r, random_ctx, random, pub->n); /* invert r */ } while (!mpz_invert (ri, r, pub->n)); /* c = c*(r^e) mod n */ mpz_powm_sec(r, r, pub->e, pub->n); mpz_mul(c, c, r); mpz_fdiv_r(c, c, pub->n); mpz_clear(r); }
int _dsa_sign(const struct dsa_public_key *pub, const struct dsa_private_key *key, void *random_ctx, nettle_random_func *random, unsigned digest_size, const uint8_t *digest, struct dsa_signature *signature) { mpz_t k; mpz_t h; mpz_t tmp; /* Require precise match of bitsize of q and hash size. The general description of DSA in FIPS186-3 allows both larger and smaller q; in the the latter case, the hash must be truncated to the right number of bits. */ if (mpz_sizeinbase(pub->q, 2) != 8 * digest_size) return 0; /* Select k, 0<k<q, randomly */ mpz_init_set(tmp, pub->q); mpz_sub_ui(tmp, tmp, 1); mpz_init(k); nettle_mpz_random(k, random_ctx, random, tmp); mpz_add_ui(k, k, 1); /* Compute r = (g^k (mod p)) (mod q) */ mpz_powm(tmp, pub->g, k, pub->p); mpz_fdiv_r(signature->r, tmp, pub->q); /* Compute hash */ mpz_init(h); nettle_mpz_set_str_256_u(h, digest_size, digest); /* Compute k^-1 (mod q) */ if (!mpz_invert(k, k, pub->q)) /* What do we do now? The key is invalid. */ return 0; /* Compute signature s = k^-1 (h + xr) (mod q) */ mpz_mul(tmp, signature->r, key->x); mpz_fdiv_r(tmp, tmp, pub->q); mpz_add(tmp, tmp, h); mpz_mul(tmp, tmp, k); mpz_fdiv_r(signature->s, tmp, pub->q); mpz_clear(k); mpz_clear(h); mpz_clear(tmp); return 1; }
static void dsa_find_generator(mpz_t g, void *random_ctx, nettle_random_func random, void *progress_ctx, nettle_progress_func progress, const mpz_t p, const mpz_t q) { mpz_t e; mpz_t n; /* e = (p-1)/q */ mpz_init_set(e, p); mpz_sub_ui(e, e, 1); mpz_divexact(e, e, q); /* n = p-2 = |2, 3, ... p-1| */ mpz_init_set(n, p); mpz_sub_ui(n, n, 2); for (;;) { nettle_mpz_random(g, random_ctx, random, n); mpz_add_ui(g, g, 2); if (progress) progress(progress_ctx, 'g'); mpz_powm(g, g, e, p); if (mpz_cmp_ui(g, 1)) { /* g != 1. Finished. */ if (progress) progress(progress_ctx, '\n'); mpz_clear(e); mpz_clear(n); return; } } }
int dsa_generate_keypair(struct dsa_public_key *pub, struct dsa_private_key *key, void *random_ctx, nettle_random_func random, void *progress_ctx, nettle_progress_func progress, /* Size of key, in bits. * Use size = 512 + 64 * l for the official * NIS key sizes. */ unsigned bits) { mpz_t t; if (bits < DSA_MIN_P_BITS) return 0; dsa_nist_gen(pub->p, pub->q, random_ctx, random, progress_ctx, progress, bits); dsa_find_generator(pub->g, random_ctx, random, progress_ctx, progress, pub->p, pub->q); mpz_init_set(t, pub->q); mpz_sub_ui(t, t, 2); nettle_mpz_random(key->x, random_ctx, random, t); mpz_add_ui(key->x, key->x, 1); mpz_powm(pub->y, pub->g, key->x, pub->p); mpz_clear(t); return 1; }
/* To generate a DH key either q must be set in the params or * level should be set to the number of required bits. */ static int wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i; switch (algo) { case GNUTLS_PK_DSA: #ifdef ENABLE_FIPS140 { struct dsa_public_key pub; struct dsa_private_key priv; if (params->params[DSA_Q] == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); dsa_private_key_init(&priv); mpz_init(pub.y); ret = dsa_generate_dss_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dsa_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), pub.y); mpz_set(TOMPZ(params->params[DSA_X]), priv.x); params->params_nr += 2; dsa_fail: dsa_private_key_clear(&priv); mpz_clear(pub.y); if (ret < 0) goto fail; break; } #endif case GNUTLS_PK_DH: { struct dsa_public_key pub; mpz_t r; mpz_t x, y; int max_tries; unsigned have_q = 0; if (algo != params->algo) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); if (params->params[DSA_Q] != NULL) have_q = 1; /* This check is for the case !ENABLE_FIPS140 */ if (algo == GNUTLS_PK_DSA && have_q == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); mpz_init(r); mpz_init(x); mpz_init(y); max_tries = 3; do { if (have_q) { mpz_set(r, pub.q); mpz_sub_ui(r, r, 2); nettle_mpz_random(x, NULL, rnd_func, r); mpz_add_ui(x, x, 1); } else { unsigned size = mpz_sizeinbase(pub.p, 2); if (level == 0) level = MIN(size, DH_EXPONENT_SIZE(size)); nettle_mpz_random_size(x, NULL, rnd_func, level); if (level >= size) mpz_mod(x, x, pub.p); } mpz_powm(y, pub.g, x, pub.p); max_tries--; if (max_tries <= 0) { gnutls_assert(); ret = GNUTLS_E_RANDOM_FAILED; goto dh_fail; } } while(mpz_cmp_ui(y, 1) == 0); ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dh_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), y); mpz_set(TOMPZ(params->params[DSA_X]), x); params->params_nr += 2; ret = 0; dh_fail: mpz_clear(r); mpz_clear(x); mpz_clear(y); if (ret < 0) goto fail; break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; struct rsa_private_key priv; rsa_public_key_init(&pub); rsa_private_key_init(&priv); mpz_set_ui(pub.e, 65537); #ifdef ENABLE_FIPS140 ret = rsa_generate_fips186_4_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level); #else ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); #endif if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { ret = _gnutls_mpi_init(¶ms->params[i]); if (ret < 0) { gnutls_assert(); goto rsa_fail; } params->params_nr++; } mpz_set(TOMPZ(params->params[0]), pub.n); mpz_set(TOMPZ(params->params[1]), pub.e); mpz_set(TOMPZ(params->params[2]), priv.d); mpz_set(TOMPZ(params->params[3]), priv.p); mpz_set(TOMPZ(params->params[4]), priv.q); mpz_set(TOMPZ(params->params[5]), priv.c); mpz_set(TOMPZ(params->params[6]), priv.a); mpz_set(TOMPZ(params->params[7]), priv.b); ret = 0; rsa_fail: rsa_private_key_clear(&priv); rsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { struct ecc_scalar key; struct ecc_point pub; const struct ecc_curve *curve; curve = get_supported_curve(level); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); ret = _gnutls_mpi_init_multi(¶ms->params[ECC_X], ¶ms->params[ECC_Y], ¶ms->params[ECC_K], NULL); if (ret < 0) { gnutls_assert(); goto ecc_fail; } params->flags = level; params->params_nr = ECC_PRIVATE_PARAMS; ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ret = 0; ecc_fail: ecc_point_clear(&pub); ecc_scalar_clear(&key); if (ret < 0) goto fail; break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } FAIL_IF_LIB_ERROR; return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release(¶ms->params[i]); } params->params_nr = 0; FAIL_IF_LIB_ERROR; return ret; }
/* Valid sizes, according to FIPS 186-3 are (1024, 160), (2048. 224), (2048, 256), (3072, 256). Currenty, we use only q_bits of 160 or 256. */ int dsa_generate_keypair(struct dsa_public_key *pub, struct dsa_private_key *key, void *random_ctx, nettle_random_func *random, void *progress_ctx, nettle_progress_func *progress, unsigned p_bits, unsigned q_bits) { mpz_t p0, p0q, r; unsigned p0_bits; unsigned a; switch (q_bits) { case 160: if (p_bits < DSA_SHA1_MIN_P_BITS) return 0; break; case 256: if (p_bits < DSA_SHA256_MIN_P_BITS) return 0; break; default: return 0; } mpz_init (p0); mpz_init (p0q); mpz_init (r); nettle_random_prime (pub->q, q_bits, 0, random_ctx, random, progress_ctx, progress); p0_bits = (p_bits + 3)/2; nettle_random_prime (p0, p0_bits, 0, random_ctx, random, progress_ctx, progress); if (progress) progress (progress_ctx, 'q'); /* Generate p = 2 r q p0 + 1, such that 2^{n-1} < p < 2^n. * * We select r in the range i + 1 < r <= 2i, with i = floor (2^{n-2} / (p0 q). */ mpz_mul (p0q, p0, pub->q); _nettle_generate_pocklington_prime (pub->p, r, p_bits, 0, random_ctx, random, p0, pub->q, p0q); if (progress) progress (progress_ctx, 'p'); mpz_mul (r, r, p0); for (a = 2; ; a++) { mpz_set_ui (pub->g, a); mpz_powm (pub->g, pub->g, r, pub->p); if (mpz_cmp_ui (pub->g, 1) != 0) break; } if (progress) progress (progress_ctx, 'g'); mpz_set(r, pub->q); mpz_sub_ui(r, r, 2); nettle_mpz_random(key->x, random_ctx, random, r); mpz_add_ui(key->x, key->x, 1); mpz_powm(pub->y, pub->g, key->x, pub->p); if (progress) progress (progress_ctx, '\n'); mpz_clear (p0); mpz_clear (p0q); mpz_clear (r); return 1; }