1
1

kex, pki, server, options: Filter algorithms in FIPS mode

When in FIPS mode, filter the algorithms to enable only the allowed
ones.  If any algorithm is explicitly set through options or
configuration file, they are kept.

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
Anderson Toshiyuki Sasaki 2019-05-22 18:33:14 +02:00 коммит произвёл Andreas Schneider
родитель 56041dc784
Коммит 54d76098ed
5 изменённых файлов: 137 добавлений и 14 удалений

Просмотреть файл

@ -39,11 +39,13 @@ int ssh_set_client_kex(ssh_session session);
int ssh_kex_select_methods(ssh_session session);
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list);
char **ssh_space_tokenize(const char *chain);
int ssh_get_kex1(ssh_session session);
char *ssh_find_matching(const char *in_d, const char *what_d);
const char *ssh_kex_get_supported_method(uint32_t algo);
const char *ssh_kex_get_default_methods(uint32_t algo);
const char *ssh_kex_get_fips_methods(uint32_t algo);
const char *ssh_kex_get_description(uint32_t algo);
char *ssh_client_select_hostkeys(ssh_session session);
int ssh_send_rekex(ssh_session session);

Просмотреть файл

@ -136,11 +136,55 @@
#define KEY_EXCHANGE_SUPPORTED \
GEX_SHA1 \
KEY_EXCHANGE
#define KEX_METHODS_SIZE 10
/* RFC 8308 */
#define KEX_EXTENSION_CLIENT "ext-info-c"
/* Allowed algorithms in FIPS mode */
#define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\
"aes256-ctr,"\
"aes256-cbc,"\
"aes128-gcm@openssh.com,"\
"aes128-ctr,"\
"aes128-cbc"
#define FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS "ecdsa-sha2-nistp521,"\
"ecdsa-sha2-nistp384,"\
"ecdsa-sha2-nistp256,"\
"rsa-sha2-512,"\
"rsa-sha2-256"
#define FIPS_ALLOWED_KEX "ecdh-sha2-nistp256,"\
"ecdh-sha2-nistp384,"\
"ecdh-sha2-nistp521,"\
"diffie-hellman-group-exchange-sha256,"\
"diffie-hellman-group16-sha512,"\
"diffie-hellman-group18-sha512"
#define FIPS_ALLOWED_MACS "hmac-sha2-256-etm@openssh.com,"\
"hmac-sha1-etm@openssh.com,"\
"hmac-sha2-512-etm@openssh.com,"\
"hmac-sha2-256,"\
"hmac-sha1,"\
"hmac-sha2-512"
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
static const char *fips_methods[] = {
FIPS_ALLOWED_KEX,
FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS,
FIPS_ALLOWED_CIPHERS,
FIPS_ALLOWED_CIPHERS,
FIPS_ALLOWED_MACS,
FIPS_ALLOWED_MACS,
ZLIB,
ZLIB,
"",
"",
NULL
};
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
static const char *default_methods[] = {
KEY_EXCHANGE,
@ -211,6 +255,14 @@ const char *ssh_kex_get_description(uint32_t algo) {
return ssh_kex_descriptions[algo];
}
const char *ssh_kex_get_fips_methods(uint32_t algo) {
if (algo >= KEX_METHODS_SIZE) {
return NULL;
}
return fips_methods[algo];
}
/**
* @internal
* @brief returns whether the first client key exchange algorithm or
@ -600,8 +652,13 @@ int ssh_set_client_kex(ssh_session session)
for (i = 0; i < KEX_METHODS_SIZE; i++) {
wanted = session->opts.wanted_methods[i];
if (wanted == NULL)
wanted = default_methods[i];
if (wanted == NULL) {
if (ssh_fips_mode()) {
wanted = fips_methods[i];
} else {
wanted = default_methods[i];
}
}
client->methods[i] = strdup(wanted);
if (client->methods[i] == NULL) {
ssh_set_error_oom(session);
@ -823,6 +880,27 @@ char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list)
return ssh_find_all_matching(supported_methods[algo], list);
}
/**
* @internal
*
* @brief Return a new allocated string containing only the FIPS allowed
* algorithms from the list.
*
* @param[in] algo The type of the methods to filter
* @param[in] list The list to be filtered
*
* @return A new allocated list containing only the FIPS allowed algorithms from
* the list; NULL in case of error.
*/
char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list)
{
if (algo > SSH_LANG_S_C) {
return NULL;
}
return ssh_find_all_matching(fips_methods[algo], list);
}
int ssh_make_sessionid(ssh_session session)
{
ssh_string num = NULL;

Просмотреть файл

@ -223,10 +223,15 @@ int ssh_options_set_algo(ssh_session session,
{
char *p = NULL;
p = ssh_keep_known_algos(algo, list);
if (ssh_fips_mode()) {
p = ssh_keep_fips_algos(algo, list);
} else {
p = ssh_keep_known_algos(algo, list);
}
if (p == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Setting method: no algorithm for method \"%s\" (%s)",
"Setting method: no allowed algorithm for method \"%s\" (%s)",
ssh_kex_get_description(algo), list);
return -1;
}
@ -796,7 +801,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
ssh_set_error_invalid(session);
return -1;
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
if (ssh_fips_mode()) {
p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
}
if (p == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Setting method: no known public key algorithm (%s)",
@ -1503,7 +1512,11 @@ static int ssh_bind_set_algo(ssh_bind sshbind,
{
char *p = NULL;
p = ssh_keep_known_algos(algo, list);
if (ssh_fips_mode()) {
p = ssh_keep_fips_algos(algo, list);
} else {
p = ssh_keep_known_algos(algo, list);
}
if (p == NULL) {
ssh_set_error(sshbind, SSH_REQUEST_DENIED,
"Setting method: no algorithm for method \"%s\" (%s)",
@ -1938,7 +1951,11 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
ssh_set_error_invalid(sshbind);
return -1;
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
if (ssh_fips_mode()) {
p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
}
if (p == NULL) {
ssh_set_error(sshbind, SSH_REQUEST_DENIED,
"Setting method: no known public key algorithm (%s)",

Просмотреть файл

@ -323,7 +323,11 @@ int ssh_key_algorithm_allowed(ssh_session session, const char *type)
if (session->client) {
allowed_list = session->opts.pubkey_accepted_types;
if (allowed_list == NULL) {
allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS);
if (ssh_fips_mode()) {
allowed_list = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
} else {
allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS);
}
}
}
#ifdef WITH_SERVER
@ -2111,13 +2115,26 @@ int pki_key_check_hash_compatible(ssh_key key,
case SSH_KEYTYPE_DSS_CERT01:
case SSH_KEYTYPE_DSS:
if (hash_type == SSH_DIGEST_SHA1) {
return SSH_OK;
if (ssh_fips_mode()) {
SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode");
return SSH_ERROR;
} else {
return SSH_OK;
}
}
break;
case SSH_KEYTYPE_RSA_CERT01:
case SSH_KEYTYPE_RSA:
if (hash_type == SSH_DIGEST_SHA1 ||
hash_type == SSH_DIGEST_SHA256 ||
if (hash_type == SSH_DIGEST_SHA1) {
if (ssh_fips_mode()) {
SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode");
return SSH_ERROR;
} else {
return SSH_OK;
}
}
if (hash_type == SSH_DIGEST_SHA256 ||
hash_type == SSH_DIGEST_SHA512)
{
return SSH_OK;

Просмотреть файл

@ -142,7 +142,11 @@ int server_set_kex(ssh_session session)
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
allowed = session->opts.wanted_methods[SSH_HOSTKEYS];
} else {
allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS);
if (ssh_fips_mode()) {
allowed = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
} else {
allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS);
}
}
/* It is expected for the list of allowed hostkeys to be ordered by
@ -163,8 +167,13 @@ int server_set_kex(ssh_session session)
}
for (i = 0; i < 10; i++) {
if ((wanted = session->opts.wanted_methods[i]) == NULL) {
wanted = ssh_kex_get_default_methods(i);
wanted = session->opts.wanted_methods[i];
if (wanted == NULL) {
if (ssh_fips_mode()) {
wanted = ssh_kex_get_fips_methods(i);
} else {
wanted = ssh_kex_get_default_methods(i);
}
}
server->methods[i] = strdup(wanted);
if (server->methods[i] == NULL) {