Ejemplo n.º 1
0
static void ecdsa_sign(ssh_key *key, ptrlen data,
                       unsigned flags, BinarySink *bs)
{
    struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;
    assert(ek->privateKey);

    mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data);

    /* Generate k between 1 and curve->n, using the same deterministic
     * k generation system we use for conventional DSA. */
    mp_int *k;
    {
        unsigned char digest[20];
        hash_simple(&ssh_sha1, data, digest);
        k = dss_gen_k(
            "ECDSA deterministic k generator", ek->curve->w.G_order,
            ek->privateKey, digest, sizeof(digest));
    }

    WeierstrassPoint *kG = ecc_weierstrass_multiply(ek->curve->w.G, k);
    mp_int *x;
    ecc_weierstrass_get_affine(kG, &x, NULL);
    ecc_weierstrass_point_free(kG);

    /* r = kG.x mod order(G) */
    mp_int *r = mp_mod(x, ek->curve->w.G_order);
    mp_free(x);

    /* s = (z + r * priv)/k mod n */
    mp_int *rPriv = mp_modmul(r, ek->privateKey, ek->curve->w.G_order);
    mp_int *numerator = mp_modadd(z, rPriv, ek->curve->w.G_order);
    mp_free(z);
    mp_free(rPriv);
    mp_int *kInv = mp_invert(k, ek->curve->w.G_order);
    mp_free(k);
    mp_int *s = mp_modmul(numerator, kInv, ek->curve->w.G_order);
    mp_free(numerator);
    mp_free(kInv);

    /* Format the output */
    put_stringz(bs, ek->sshk.vt->ssh_id);

    strbuf *substr = strbuf_new();
    put_mp_ssh2(substr, r);
    put_mp_ssh2(substr, s);
    put_stringsb(bs, substr);

    mp_free(r);
    mp_free(s);
}
Ejemplo n.º 2
0
/*
 * Verify that the public data in an RSA key matches the private
 * data. We also check the private data itself: we ensure that p >
 * q and that iqmp really is the inverse of q mod p.
 */
bool rsa_verify(RSAKey *key)
{
    mp_int *n, *ed, *pm1, *qm1;
    unsigned ok = 1;

    /* Preliminary checks: p,q must actually be nonzero. */
    if (mp_eq_integer(key->p, 0) | mp_eq_integer(key->q, 0))
        return false;

    /* n must equal pq. */
    n = mp_mul(key->p, key->q);
    ok &= mp_cmp_eq(n, key->modulus);
    mp_free(n);

    /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */
    pm1 = mp_copy(key->p);
    mp_sub_integer_into(pm1, pm1, 1);
    ed = mp_modmul(key->exponent, key->private_exponent, pm1);
    mp_free(pm1);
    ok &= mp_eq_integer(ed, 1);
    mp_free(ed);

    qm1 = mp_copy(key->q);
    mp_sub_integer_into(qm1, qm1, 1);
    ed = mp_modmul(key->exponent, key->private_exponent, qm1);
    mp_free(qm1);
    ok &= mp_eq_integer(ed, 1);
    mp_free(ed);

    /*
     * Ensure p > q.
     *
     * I have seen key blobs in the wild which were generated with
     * p < q, so instead of rejecting the key in this case we
     * should instead flip them round into the canonical order of
     * p > q. This also involves regenerating iqmp.
     */
    mp_int *p_new = mp_max(key->p, key->q);
    mp_int *q_new = mp_min(key->p, key->q);
    mp_free(key->p);
    mp_free(key->q);
    mp_free(key->iqmp);
    key->p = p_new;
    key->q = q_new;
    key->iqmp = mp_invert(key->q, key->p);

    return ok;
}
Ejemplo n.º 3
0
/*-------------------------------------------------------------------*/
static void convert_to_integer(gmp_poly_t *alg_sqrt, mp_t *n,
				mp_t *c, signed_mp_t *m1, 
				signed_mp_t *m0, mp_t *res) {

	/* given the completed square root, apply the homomorphism
	   to convert the polynomial to an integer. We do this
	   by evaluating alg_sqrt at c*m0/m1, with all calculations
	   performed mod n */

	uint32 i;
	mpz_t gmp_n;
	mp_t m1_pow;
	mp_t m1_tmp;
	mp_t m0_tmp;
	mp_t next_coeff;

	mpz_init(gmp_n); 
	mp2gmp(n, gmp_n);
	gmp_poly_mod_q(alg_sqrt, gmp_n, alg_sqrt);
	mpz_clear(gmp_n);

	mp_copy(&m1->num, &m1_tmp);
	if (m1->sign == NEGATIVE)
		mp_sub(n, &m1_tmp, &m1_tmp);
	mp_copy(&m1_tmp, &m1_pow);

	mp_modmul(&m0->num, c, n, &m0_tmp);
	if (m0->sign == POSITIVE)
		mp_sub(n, &m0_tmp, &m0_tmp);

	i = alg_sqrt->degree;
	gmp2mp(alg_sqrt->coeff[i], res);

	for (i--; (int32)i >= 0; i--) {
		mp_modmul(res, &m0_tmp, n, res);
		gmp2mp(alg_sqrt->coeff[i], &next_coeff);
		mp_modmul(&next_coeff, &m1_pow, n, &next_coeff);
		mp_add(res, &next_coeff, res);
		if (i > 0)
			mp_modmul(&m1_pow, &m1_tmp, n, &m1_pow);
	}
	if (mp_cmp(res, n) > 0)
		mp_sub(res, n, res);
}
Ejemplo n.º 4
0
static bool ecdsa_verify(ssh_key *key, ptrlen sig, ptrlen data)
{
    struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;

    BinarySource src[1];
    BinarySource_BARE_INIT_PL(src, sig);

    /* Check the signature starts with the algorithm name */
    if (!ptrlen_eq_string(get_string(src), ek->sshk.vt->ssh_id))
        return false;

    /* Everything else is nested inside a sub-string. Descend into that. */
    ptrlen sigstr = get_string(src);
    if (get_err(src))
        return false;
    BinarySource_BARE_INIT_PL(src, sigstr);

    /* Extract the signature integers r,s */
    mp_int *r = get_mp_ssh2(src);
    mp_int *s = get_mp_ssh2(src);
    if (get_err(src)) {
        mp_free(r);
        mp_free(s);
        return false;
    }

    /* Basic sanity checks: 0 < r,s < order(G) */
    unsigned invalid = 0;
    invalid |= mp_eq_integer(r, 0);
    invalid |= mp_eq_integer(s, 0);
    invalid |= mp_cmp_hs(r, ek->curve->w.G_order);
    invalid |= mp_cmp_hs(s, ek->curve->w.G_order);

    /* Get the hash of the signed data, converted to an integer */
    mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data);

    /* Verify the signature integers against the hash */
    mp_int *w = mp_invert(s, ek->curve->w.G_order);
    mp_int *u1 = mp_modmul(z, w, ek->curve->w.G_order);
    mp_free(z);
    mp_int *u2 = mp_modmul(r, w, ek->curve->w.G_order);
    mp_free(w);
    WeierstrassPoint *u1G = ecc_weierstrass_multiply(ek->curve->w.G, u1);
    mp_free(u1);
    WeierstrassPoint *u2P = ecc_weierstrass_multiply(ek->publicKey, u2);
    mp_free(u2);
    WeierstrassPoint *sum = ecc_weierstrass_add_general(u1G, u2P);
    ecc_weierstrass_point_free(u1G);
    ecc_weierstrass_point_free(u2P);

    mp_int *x;
    ecc_weierstrass_get_affine(sum, &x, NULL);
    ecc_weierstrass_point_free(sum);

    mp_divmod_into(x, ek->curve->w.G_order, NULL, x);
    invalid |= (1 ^ mp_cmp_eq(r, x));
    mp_free(x);

    mp_free(r);
    mp_free(s);

    return !invalid;
}
Ejemplo n.º 5
0
static void eddsa_sign(ssh_key *key, ptrlen data,
                       unsigned flags, BinarySink *bs)
{
    struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;
    assert(ek->privateKey);

    /*
     * EdDSA prescribes a specific method of generating the random
     * nonce integer for the signature. (A verifier can't tell
     * whether you followed that method, but it's important to
     * follow it anyway, because test vectors will want a specific
     * signature for a given message, and because this preserves
     * determinism of signatures even if the same signature were
     * made twice by different software.)
     */

    /*
     * First, we hash the private key integer (bare, little-endian)
     * into a hash generating 2*fieldBytes of output.
     */
    unsigned char hash[MAX_HASH_LEN];
    ssh_hash *h = ssh_hash_new(extra->hash);
    for (size_t i = 0; i < ek->curve->fieldBytes; ++i)
        put_byte(h, mp_get_byte(ek->privateKey, i));
    ssh_hash_final(h, hash);

    /*
     * The first half of the output hash is converted into an
     * integer a, by the standard EdDSA transformation.
     */
    mp_int *a = eddsa_exponent_from_hash(
        make_ptrlen(hash, ek->curve->fieldBytes), ek->curve);

    /*
     * The second half of the hash of the private key is hashed again
     * with the message to be signed, and used as an exponent to
     * generate the signature point r.
     */
    h = ssh_hash_new(extra->hash);
    put_data(h, hash + ek->curve->fieldBytes,
             extra->hash->hlen - ek->curve->fieldBytes);
    put_datapl(h, data);
    ssh_hash_final(h, hash);
    mp_int *log_r_unreduced = mp_from_bytes_le(
        make_ptrlen(hash, extra->hash->hlen));
    mp_int *log_r = mp_mod(log_r_unreduced, ek->curve->e.G_order);
    mp_free(log_r_unreduced);
    EdwardsPoint *r = ecc_edwards_multiply(ek->curve->e.G, log_r);

    /*
     * Encode r now, because we'll need its encoding for the next
     * hashing step as well as to write into the actual signature.
     */
    strbuf *r_enc = strbuf_new();
    put_epoint(r_enc, r, ek->curve, true); /* omit string header */
    ecc_edwards_point_free(r);

    /*
     * Compute the hash of (r || public key || message) just as
     * eddsa_verify does.
     */
    mp_int *H = eddsa_signing_exponent_from_data(
        ek, extra, ptrlen_from_strbuf(r_enc), data);

    /* And then s = (log(r) + H*a) mod order(G). */
    mp_int *Ha = mp_modmul(H, a, ek->curve->e.G_order);
    mp_int *s = mp_modadd(log_r, Ha, ek->curve->e.G_order);
    mp_free(H);
    mp_free(a);
    mp_free(Ha);
    mp_free(log_r);

    /* Format the output */
    put_stringz(bs, ek->sshk.vt->ssh_id);
    put_uint32(bs, r_enc->len + ek->curve->fieldBytes);
    put_data(bs, r_enc->u, r_enc->len);
    strbuf_free(r_enc);
    for (size_t i = 0; i < ek->curve->fieldBytes; ++i)
        put_byte(bs, mp_get_byte(s, i));
    mp_free(s);
}