diff --git a/include/libssh/pki.h b/include/libssh/pki.h index 621378ad..b682f273 100644 --- a/include/libssh/pki.h +++ b/include/libssh/pki.h @@ -99,6 +99,7 @@ void ssh_key_clean (ssh_key key); const char * ssh_key_get_signature_algorithm(ssh_session session, enum ssh_keytypes_e type); +enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name); /* SSH Signature Functions */ ssh_signature ssh_signature_new(void); diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h index 623ca5a1..fe7e92a8 100644 --- a/include/libssh/pki_priv.h +++ b/include/libssh/pki_priv.h @@ -104,9 +104,12 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type); -ssh_signature pki_do_sign_sessionid(const ssh_key key, - const unsigned char *hash, - size_t hlen); +#define pki_do_sign_sessionid(key, hash, hlen) \ + pki_do_sign_sessionid_hash(key, hash, hlen, SSH_DIGEST_AUTO) +ssh_signature pki_do_sign_sessionid_hash(const ssh_key key, + const unsigned char *hash, + size_t hlen, + enum ssh_digest_e hash_type); int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig, const unsigned char *hash, size_t hlen); int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig, diff --git a/src/pki.c b/src/pki.c index 9e1bfc43..2531fbed 100644 --- a/src/pki.c +++ b/src/pki.c @@ -357,7 +357,7 @@ ssh_key_get_signature_algorithm(ssh_session session, * * @return The enum ssh key algorithm type. */ -static enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) { +enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) { if (name == NULL) { return SSH_KEYTYPE_UNKNOWN; } @@ -2033,21 +2033,36 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, sig = NULL; } } else { - unsigned char hash[SHA_DIGEST_LEN] = {0}; - SHACTX ctx; + unsigned char hash[SHA512_DIGEST_LEN] = {0}; + uint32_t hlen = 0; + enum ssh_digest_e hash_type; - ctx = sha1_init(); - if (ctx == NULL) { + hash_type = ssh_key_type_to_hash(session, privkey->type); + switch (hash_type) { + case SSH_DIGEST_SHA256: + sha256(crypto->secret_hash, crypto->digest_len, hash); + hlen = SHA256_DIGEST_LEN; + break; + case SSH_DIGEST_SHA512: + sha512(crypto->secret_hash, crypto->digest_len, hash); + hlen = SHA512_DIGEST_LEN; + break; + case SSH_DIGEST_SHA1: + case SSH_DIGEST_AUTO: + sha1(crypto->secret_hash, crypto->digest_len, hash); + hlen = SHA_DIGEST_LEN; + break; + default: + SSH_LOG(SSH_LOG_TRACE, "Unknown sig->type: %d", sig->type); return NULL; } - sha1_update(ctx, crypto->secret_hash, crypto->digest_len); - sha1_final(hash, ctx); + #ifdef DEBUG_CRYPTO - ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN); + ssh_print_hexa("Hash being signed", hash, hlen); #endif - sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN); + sig = pki_do_sign_sessionid_hash(privkey, hash, hlen, hash_type); if (sig == NULL) { return NULL; } diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 524cc0ff..8e1e16ad 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -1236,26 +1236,6 @@ static ssh_string _RSA_do_sign_hash(const unsigned char *digest, return sig_blob; } -/** - * @internal - * - * @brief Compute a digital signature. - * - * @param[in] digest The message digest. - * - * @param[in] dlen The length of the digest. - * - * @param[in] privkey The private rsa key to use for signing. - * - * @return A newly allocated rsa sig blob or NULL on error. - */ -static ssh_string _RSA_do_sign(const unsigned char *digest, - int dlen, - RSA *privkey) -{ - return _RSA_do_sign_hash(digest, dlen, privkey, SSH_DIGEST_AUTO); -} - static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) { char buffer[40] = { 0 }; @@ -1813,16 +1793,24 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, } #ifdef WITH_SERVER -ssh_signature pki_do_sign_sessionid(const ssh_key key, - const unsigned char *hash, - size_t hlen) +ssh_signature pki_do_sign_sessionid_hash(const ssh_key key, + const unsigned char *hash, + size_t hlen, + enum ssh_digest_e hash_type) { ssh_signature sig; + /* Only RSA supports different signature algorithm types now */ + if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) { + SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed"); + return NULL; + } + sig = ssh_signature_new(); if (sig == NULL) { return NULL; } + sig->type = key->type; sig->type_c = key->type_c; @@ -1836,7 +1824,8 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key, break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: - sig->rsa_sig = _RSA_do_sign(hash, hlen, key->rsa); + sig->type_c = ssh_key_signature_to_char(key->type, hash_type); + sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, key->rsa, hash_type); if (sig->rsa_sig == NULL) { ssh_signature_free(sig); return NULL; diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c index c0395e9d..a988d805 100644 --- a/src/pki_gcrypt.c +++ b/src/pki_gcrypt.c @@ -2199,19 +2199,28 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, } #ifdef WITH_SERVER -ssh_signature pki_do_sign_sessionid(const ssh_key key, - const unsigned char *hash, - size_t hlen) +ssh_signature pki_do_sign_sessionid_hash(const ssh_key key, + const unsigned char *hash, + size_t hlen, + enum ssh_digest_e hash_type) { unsigned char ghash[hlen + 1]; + const char *hash_c = NULL; ssh_signature sig; gcry_sexp_t sexp; gcry_error_t err; + /* Only RSA supports different signature algorithm types now */ + if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) { + SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed"); + return NULL; + } + sig = ssh_signature_new(); if (sig == NULL) { return NULL; } + sig->type = key->type; sig->type_c = key->type_c; @@ -2238,9 +2247,25 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key, } break; case SSH_KEYTYPE_RSA: + sig->type_c = ssh_key_signature_to_char(key->type, hash_type); + switch (hash_type) { + case SSH_DIGEST_SHA1: + hash_c = "sha1"; + break; + case SSH_DIGEST_SHA256: + hash_c = "sha256"; + break; + case SSH_DIGEST_SHA512: + hash_c = "sha512"; + break; + default: + SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm"); + return NULL; + } err = gcry_sexp_build(&sexp, NULL, - "(data(flags pkcs1)(hash sha1 %b))", + "(data(flags pkcs1)(hash %s %b))", + hash_c, hlen, hash); if (err) { diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c index 68a80b42..fceacd80 100644 --- a/src/pki_mbedcrypto.c +++ b/src/pki_mbedcrypto.c @@ -1127,22 +1127,32 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, } #ifdef WITH_SERVER -ssh_signature pki_do_sign_sessionid(const ssh_key key, const unsigned char - *hash, size_t hlen) +ssh_signature pki_do_sign_sessionid_hash(const ssh_key key, + const unsigned char *hash, + size_t hlen, + enum ssh_digest_e hash_type) { ssh_signature sig = NULL; int rc; + /* Only RSA supports different signature algorithm types now */ + if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) { + SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed"); + return NULL; + } + sig = ssh_signature_new(); if (sig == NULL) { return NULL; } + sig->type = key->type; sig->type_c = key->type_c; switch (key->type) { case SSH_KEYTYPE_RSA: - sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, SSH_DIGEST_AUTO); + sig->type_c = ssh_key_signature_to_char(key->type, hash_type); + sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, hash_type); if (sig->rsa_sig == NULL) { ssh_signature_free(sig); return NULL; diff --git a/src/wrapper.c b/src/wrapper.c index 48749489..68707989 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -509,7 +509,7 @@ int crypt_set_algorithms_server(ssh_session session){ } method = session->next_crypto->kex_methods[SSH_HOSTKEYS]; - session->srv.hostkey = ssh_key_type_from_name(method); + session->srv.hostkey = ssh_key_type_from_signature_name(method); return SSH_OK; } diff --git a/tests/pkd/pkd_client.h b/tests/pkd/pkd_client.h index da40a7c5..4d01a607 100644 --- a/tests/pkd/pkd_client.h +++ b/tests/pkd/pkd_client.h @@ -15,8 +15,8 @@ #define OPENSSH_BINARY "ssh" #define OPENSSH_KEYGEN "ssh-keygen" -#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,ssh-rsa" -#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,ssh-rsa" +#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa" +#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa" #if HAVE_ECC #define OPENSSH_HOSTKEY_ALGOS_ECDSA ",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"