diff --git a/ssh.h b/ssh.h index 40641342..56bd4339 100644 --- a/ssh.h +++ b/ssh.h @@ -997,6 +997,8 @@ extern const ssh_kex ssh_ec_kex_nistp521; extern const ssh_kexes ssh_ecdh_kex; extern const ssh_keyalg ssh_dss; extern const ssh_keyalg ssh_rsa; +extern const ssh_keyalg ssh_rsa_sha256; +extern const ssh_keyalg ssh_rsa_sha512; extern const ssh_keyalg ssh_ecdsa_ed25519; extern const ssh_keyalg ssh_ecdsa_ed448; extern const ssh_keyalg ssh_ecdsa_nistp256; diff --git a/ssh2transport.h b/ssh2transport.h index 10d660ab..9f34f11b 100644 --- a/ssh2transport.h +++ b/ssh2transport.h @@ -52,6 +52,8 @@ struct kexinit_algorithm { X(HK_ECDSA, ssh_ecdsa_nistp384) \ X(HK_ECDSA, ssh_ecdsa_nistp521) \ X(HK_DSA, ssh_dss) \ + X(HK_RSA, ssh_rsa_sha512) \ + X(HK_RSA, ssh_rsa_sha256) \ X(HK_RSA, ssh_rsa) \ /* end of list */ #define COUNT_HOSTKEY_ALGORITHM(type, alg) +1 diff --git a/sshrsa.c b/sshrsa.c index 8ff05afb..f58ca375 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -456,9 +456,13 @@ void freersakey(RSAKey *key) } /* ---------------------------------------------------------------------- - * Implementation of the ssh-rsa signing key type. + * Implementation of the ssh-rsa signing key type family. */ +struct ssh2_rsa_extra { + unsigned signflags; +}; + static void rsa2_freekey(ssh_key *key); /* forward reference */ static ssh_key *rsa2_new_pub(const ssh_keyalg *self, ptrlen data) @@ -471,7 +475,7 @@ static ssh_key *rsa2_new_pub(const ssh_keyalg *self, ptrlen data) return NULL; rsa = snew(RSAKey); - rsa->sshk.vt = &ssh_rsa; + rsa->sshk.vt = self; rsa->exponent = get_mp_ssh2(src); rsa->modulus = get_mp_ssh2(src); rsa->private_exponent = NULL; @@ -729,8 +733,10 @@ static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data) ptrlen type, in_pl; mp_int *in, *out; - /* If we need to support variable flags on verify, this is where they go */ - const ssh_hashalg *halg = rsa2_hash_alg_for_flags(0, NULL); + const struct ssh2_rsa_extra *extra = + (const struct ssh2_rsa_extra *)key->vt->extra; + + const ssh_hashalg *halg = rsa2_hash_alg_for_flags(extra->signflags, NULL); /* Start by making sure the key is even long enough to encode a * signature. If not, everything fails to verify. */ @@ -751,7 +757,7 @@ static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data) * mp_from_bytes_be, which will tolerate anything. */ in_pl = get_string(src); - if (get_err(src) || !ptrlen_eq_string(type, "ssh-rsa")) + if (get_err(src) || !ptrlen_eq_string(type, key->vt->ssh_id)) return false; in = mp_from_bytes_be(in_pl); @@ -780,6 +786,10 @@ static void rsa2_sign(ssh_key *key, ptrlen data, const ssh_hashalg *halg; const char *sign_alg_name; + const struct ssh2_rsa_extra *extra = + (const struct ssh2_rsa_extra *)key->vt->extra; + flags |= extra->signflags; + halg = rsa2_hash_alg_for_flags(flags, &sign_alg_name); nbytes = (mp_get_nbits(rsa->modulus) + 7) / 8; @@ -816,23 +826,46 @@ static char *rsa2_invalid(ssh_key *key, unsigned flags) return NULL; } +static const struct ssh2_rsa_extra + rsa_extra = { 0 }, + rsa_sha256_extra = { SSH_AGENT_RSA_SHA2_256 }, + rsa_sha512_extra = { SSH_AGENT_RSA_SHA2_512 }; + +#define COMMON_KEYALG_FIELDS \ + .new_pub = rsa2_new_pub, \ + .new_priv = rsa2_new_priv, \ + .new_priv_openssh = rsa2_new_priv_openssh, \ + .freekey = rsa2_freekey, \ + .invalid = rsa2_invalid, \ + .sign = rsa2_sign, \ + .verify = rsa2_verify, \ + .public_blob = rsa2_public_blob, \ + .private_blob = rsa2_private_blob, \ + .openssh_blob = rsa2_openssh_blob, \ + .cache_str = rsa2_cache_str, \ + .components = rsa2_components, \ + .pubkey_bits = rsa2_pubkey_bits, \ + .cache_id = "rsa2" + const ssh_keyalg ssh_rsa = { - .new_pub = rsa2_new_pub, - .new_priv = rsa2_new_priv, - .new_priv_openssh = rsa2_new_priv_openssh, - .freekey = rsa2_freekey, - .invalid = rsa2_invalid, - .sign = rsa2_sign, - .verify = rsa2_verify, - .public_blob = rsa2_public_blob, - .private_blob = rsa2_private_blob, - .openssh_blob = rsa2_openssh_blob, - .cache_str = rsa2_cache_str, - .components = rsa2_components, - .pubkey_bits = rsa2_pubkey_bits, + COMMON_KEYALG_FIELDS, .ssh_id = "ssh-rsa", - .cache_id = "rsa2", .supported_flags = SSH_AGENT_RSA_SHA2_256 | SSH_AGENT_RSA_SHA2_512, + .extra = &rsa_extra, +}; + +const ssh_keyalg ssh_rsa_sha256 = { + COMMON_KEYALG_FIELDS, + .ssh_id = "rsa-sha2-256", + .supported_flags = 0, + .extra = &rsa_sha256_extra, +}; + +const ssh_keyalg ssh_rsa_sha512 = { + COMMON_KEYALG_FIELDS, + .ssh_id = "rsa-sha2-512", + .supported_flags = 0, + .extra = &rsa_sha512_extra, }; RSAKey *ssh_rsakex_newkey(ptrlen data)