summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2019-10-31 13:03:21 +0100
committerAndreas Schneider <asn@cryptomilk.org>2019-11-07 15:55:32 +0100
commit1ebf506913495a736322fc5a97ba336adff6e464 (patch)
treec5df3a393c157286e41c43219b7f7e8c08d9a37c
parentfbc2912ddeb22dfc901508467a23d6e9d41cd6a2 (diff)
downloadlibssh-1ebf506913495a736322fc5a97ba336adff6e464.tar.gz
libssh-1ebf506913495a736322fc5a97ba336adff6e464.tar.xz
libssh-1ebf506913495a736322fc5a97ba336adff6e464.zip
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>
-rw-r--r--include/libssh/pki.h4
-rw-r--r--include/libssh/priv.h12
-rw-r--r--include/libssh/session.h1
-rw-r--r--include/libssh/wrapper.h8
-rw-r--r--src/curve25519.c5
-rw-r--r--src/dh.c5
-rw-r--r--src/ecdh_crypto.c5
-rw-r--r--src/ecdh_gcrypt.c5
-rw-r--r--src/ecdh_mbedcrypto.c5
-rw-r--r--src/pki.c12
-rw-r--r--src/server.c7
-rw-r--r--src/wrapper.c1
12 files changed, 41 insertions, 29 deletions
diff --git a/include/libssh/pki.h b/include/libssh/pki.h
index 533d3e09..9b104349 100644
--- a/include/libssh/pki.h
+++ b/include/libssh/pki.h
@@ -111,6 +111,7 @@ enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
enum ssh_keytypes_e ssh_key_type_plain(enum ssh_keytypes_e type);
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
enum ssh_keytypes_e type);
+enum ssh_digest_e ssh_key_hash_from_name(const char *name);
#define is_ecdsa_key_type(t) \
((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521)
@@ -153,7 +154,8 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
struct ssh_buffer_struct *buf,
const ssh_key pubkey);
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);
/* Temporary functions, to be removed after migration to ssh_key */
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key);
diff --git a/include/libssh/priv.h b/include/libssh/priv.h
index ce74465a..90ef0dcf 100644
--- a/include/libssh/priv.h
+++ b/include/libssh/priv.h
@@ -221,7 +221,17 @@ int gettimeofday(struct timeval *__p, void *__t);
struct ssh_common_struct;
struct ssh_kex_struct;
-int ssh_get_key_params(ssh_session session, ssh_key *privkey);
+enum ssh_digest_e {
+ SSH_DIGEST_AUTO=0,
+ SSH_DIGEST_SHA1=1,
+ SSH_DIGEST_SHA256,
+ SSH_DIGEST_SHA384,
+ SSH_DIGEST_SHA512,
+};
+
+int ssh_get_key_params(ssh_session session,
+ ssh_key *privkey,
+ enum ssh_digest_e *digest);
/* LOGGING */
void ssh_log_function(int verbosity,
diff --git a/include/libssh/session.h b/include/libssh/session.h
index dfcb0cd6..6558da46 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -188,6 +188,7 @@ struct ssh_session_struct {
ssh_key ed25519_key;
/* The type of host key wanted by client */
enum ssh_keytypes_e hostkey;
+ enum ssh_digest_e hostkey_digest;
} srv;
/* auths accepted by server */
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 1c18f288..ba64939b 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -29,14 +29,6 @@
#include "libssh/libgcrypt.h"
#include "libssh/libmbedcrypto.h"
-enum ssh_digest_e {
- SSH_DIGEST_AUTO=0,
- SSH_DIGEST_SHA1=1,
- SSH_DIGEST_SHA256,
- SSH_DIGEST_SHA384,
- SSH_DIGEST_SHA512,
-};
-
enum ssh_kdf_digest {
SSH_KDF_SHA1=1,
SSH_KDF_SHA256,
diff --git a/src/curve25519.c b/src/curve25519.c
index cfbe6bd8..206cb130 100644
--- a/src/curve25519.c
+++ b/src/curve25519.c
@@ -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;
diff --git a/src/dh.c b/src/dh.c
index 2f63bafa..4869b37e 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -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;
diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c
index 9bdfe310..10c0bcd7 100644
--- a/src/ecdh_crypto.c
+++ b/src/ecdh_crypto.c
@@ -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;
diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c
index 3c3fe8f0..7bbad14e 100644
--- a/src/ecdh_gcrypt.c
+++ b/src/ecdh_gcrypt.c
@@ -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;
diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c
index 2c165aaa..3b10117b 100644
--- a/src/ecdh_mbedcrypto.c
+++ b/src/ecdh_mbedcrypto.c
@@ -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;
diff --git a/src/pki.c b/src/pki.c
index 488500cc..3bd7f272 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -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;
}
diff --git a/src/server.c b/src/server.c
index 9256c30a..14295fca 100644
--- a/src/server.c
+++ b/src/server.c
@@ -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,
diff --git a/src/wrapper.c b/src/wrapper.c
index 299d4f3f..fd3417f3 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -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) {