server: Use really the negotiated signature type

Generally, when the extension negotiation is enabled and client supports
SHA2 algorithms for RSA, they are supposed to be prioritized against the
old SHA1. If it is not (ssh-rsa is listed in front of rsa-sha2-* hostkey
algorithms during negotiation), the server wrongly tries to provide the
new typo of signature, ignoring the negotiated algirithm

This commit propagates the digest algorithm from negotiation to the actual
signature functions, which were previously responsible for decision
about the hash algorithm based just on the negotiated extensions.

Fixes T191

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2019-10-31 13:03:21 +01:00
committed by Andreas Schneider
parent fbc2912dde
commit 1ebf506913
12 changed files with 41 additions and 29 deletions

View File

@@ -388,6 +388,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
/* SSH host keys (rsa,dsa,ecdsa) */
ssh_key privkey;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
int rc;
(void)type;
@@ -435,7 +436,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
}
/* privkey is not allocated */
rc = ssh_get_key_params(session, &privkey);
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc == SSH_ERROR) {
goto error;
}
@@ -478,7 +479,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
goto error;
}
/* add signature blob */
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
goto error;

View File

@@ -431,6 +431,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
{
struct ssh_crypto_struct *crypto = session->next_crypto;
ssh_key privkey = NULL;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
ssh_string pubkey_blob = NULL;
bignum client_pubkey;
@@ -456,7 +457,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
goto error;
}
rc = ssh_get_key_params(session, &privkey);
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc != SSH_OK) {
goto error;
}
@@ -473,7 +474,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
goto error;
}
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
goto error;

View File

@@ -206,6 +206,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
bignum_CTX ctx;
/* SSH host keys (rsa,dsa,ecdsa) */
ssh_key privkey;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
ssh_string pubkey_blob = NULL;
int curve;
@@ -277,7 +278,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
}
/* privkey is not allocated */
rc = ssh_get_key_params(session, &privkey);
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc == SSH_ERROR) {
goto error;
}
@@ -288,7 +289,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
goto error;
}
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
goto error;

View File

@@ -273,6 +273,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
gcry_sexp_t key = NULL;
/* SSH host keys (rsa,dsa,ecdsa) */
ssh_key privkey;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
ssh_string pubkey_blob = NULL;
int rc = SSH_ERROR;
@@ -325,7 +326,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
}
/* privkey is not allocated */
rc = ssh_get_key_params(session, &privkey);
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc != SSH_OK) {
goto out;
}
@@ -336,7 +337,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
goto out;
}
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
rc = SSH_ERROR;

View File

@@ -188,6 +188,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
ssh_string q_s_string = NULL;
mbedtls_ecp_group grp;
ssh_key privkey = NULL;
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL;
ssh_string pubkey_blob = NULL;
int rc;
@@ -250,7 +251,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
}
/* privkey is not allocated */
rc = ssh_get_key_params(session, &privkey);
rc = ssh_get_key_params(session, &privkey, &digest);
if (rc == SSH_ERROR) {
rc = SSH_ERROR;
goto out;
@@ -263,7 +264,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
goto out;
}
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
if (sig_blob == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
rc = SSH_ERROR;

View File

@@ -305,7 +305,7 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
return NULL;
}
static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
enum ssh_digest_e ssh_key_hash_from_name(const char *name)
{
if (name == NULL) {
/* TODO we should rather fail */
@@ -2423,7 +2423,8 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
#ifdef WITH_SERVER
ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
const ssh_key privkey)
const ssh_key privkey,
const enum ssh_digest_e digest)
{
struct ssh_crypto_struct *crypto = NULL;
@@ -2432,8 +2433,6 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
ssh_buffer sign_input = NULL;
enum ssh_digest_e hash_type;
int rc;
if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
@@ -2448,9 +2447,6 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
return NULL;
}
/* Get the hash type from the key type */
hash_type = ssh_key_type_to_hash(session, privkey->type);
/* Fill the input */
sign_input = ssh_buffer_new();
if (sign_input == NULL) {
@@ -2470,7 +2466,7 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
sig = pki_do_sign(privkey,
ssh_buffer_get(sign_input),
ssh_buffer_get_len(sign_input),
hash_type);
digest);
if (sig == NULL) {
goto end;
}

View File

@@ -264,7 +264,11 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
return SSH_PACKET_NOT_USED;
}
int ssh_get_key_params(ssh_session session, ssh_key *privkey){
int
ssh_get_key_params(ssh_session session,
ssh_key *privkey,
enum ssh_digest_e *digest)
{
ssh_key pubkey;
ssh_string pubkey_blob;
int rc;
@@ -290,6 +294,7 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
*privkey = NULL;
}
*digest = session->srv.hostkey_digest;
rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL,

View File

@@ -539,6 +539,7 @@ int crypt_set_algorithms_server(ssh_session session){
method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
session->srv.hostkey = ssh_key_type_from_signature_name(method);
session->srv.hostkey_digest = ssh_key_hash_from_name(method);
/* setup DH key exchange type */
switch (session->next_crypto->kex_type) {