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; }
/* * Compute (base ^ exp) % mod, provided mod == p * q, with p,q * distinct primes, and iqmp is the multiplicative inverse of q mod p. * Uses Chinese Remainder Theorem to speed computation up over the * obvious implementation of a single big modpow. */ mp_int *crt_modpow(mp_int *base, mp_int *exp, mp_int *mod, mp_int *p, mp_int *q, mp_int *iqmp) { mp_int *pm1, *qm1, *pexp, *qexp, *presult, *qresult; mp_int *diff, *multiplier, *ret0, *ret; /* * Reduce the exponent mod phi(p) and phi(q), to save time when * exponentiating mod p and mod q respectively. Of course, since p * and q are prime, phi(p) == p-1 and similarly for q. */ pm1 = mp_copy(p); mp_sub_integer_into(pm1, pm1, 1); qm1 = mp_copy(q); mp_sub_integer_into(qm1, qm1, 1); pexp = mp_mod(exp, pm1); qexp = mp_mod(exp, qm1); /* * Do the two modpows. */ mp_int *base_mod_p = mp_mod(base, p); presult = mp_modpow(base_mod_p, pexp, p); mp_free(base_mod_p); mp_int *base_mod_q = mp_mod(base, q); qresult = mp_modpow(base_mod_q, qexp, q); mp_free(base_mod_q); /* * Recombine the results. We want a value which is congruent to * qresult mod q, and to presult mod p. * * We know that iqmp * q is congruent to 1 * mod p (by definition * of iqmp) and to 0 mod q (obviously). So we start with qresult * (which is congruent to qresult mod both primes), and add on * (presult-qresult) * (iqmp * q) which adjusts it to be congruent * to presult mod p without affecting its value mod q. * * (If presult-qresult < 0, we add p to it to keep it positive.) */ unsigned presult_too_small = mp_cmp_hs(qresult, presult); mp_cond_add_into(presult, presult, p, presult_too_small); diff = mp_sub(presult, qresult); multiplier = mp_mul(iqmp, q); ret0 = mp_mul(multiplier, diff); mp_add_into(ret0, ret0, qresult); /* * Finally, reduce the result mod n. */ ret = mp_mod(ret0, mod); /* * Free all the intermediate results before returning. */ mp_free(pm1); mp_free(qm1); mp_free(pexp); mp_free(qexp); mp_free(presult); mp_free(qresult); mp_free(diff); mp_free(multiplier); mp_free(ret0); return ret; }