diff options
-rw-r--r-- | include/libssh/dh.h | 1 | ||||
-rw-r--r-- | src/dh-gex.c | 14 | ||||
-rw-r--r-- | src/dh.c | 27 |
3 files changed, 42 insertions, 0 deletions
diff --git a/include/libssh/dh.h b/include/libssh/dh.h index 02c99760..48d8c46a 100644 --- a/include/libssh/dh.h +++ b/include/libssh/dh.h @@ -68,5 +68,6 @@ void ssh_server_dh_init(ssh_session session); #endif /* WITH_SERVER */ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet); int ssh_fallback_group(uint32_t pmax, bignum *p, bignum *g); +bool ssh_dh_is_known_group(bignum modulus, bignum generator); #endif /* DH_H_ */ diff --git a/src/dh-gex.c b/src/dh-gex.c index 1a4c3395..26c4f9d8 100644 --- a/src/dh-gex.c +++ b/src/dh-gex.c @@ -139,6 +139,13 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group) goto error; } /* basic checks */ + if (ssh_fips_mode() && + !ssh_dh_is_known_group(modulus, generator)) { + ssh_set_error(session, + SSH_FATAL, + "The received DH group is not FIPS approved"); + goto error; + } rc = bignum_set_word(one, 1); if (rc != 1) { goto error; @@ -474,6 +481,13 @@ static int ssh_retrieve_dhgroup(uint32_t pmin, char *modulus = NULL; int rc; + /* In FIPS mode, we can not negotiate arbitrary primes, + * but just the approved ones */ + if (ssh_fips_mode()) { + SSH_LOG(SSH_LOG_TRACE, "In FIPS mode, using built-in primes"); + return ssh_fallback_group(pmax, p, g); + } + moduli = fopen(MODULI_FILE, "r"); if (moduli == NULL) { SSH_LOG(SSH_LOG_WARNING, @@ -590,6 +590,33 @@ int ssh_fallback_group(uint32_t pmax, * @{ */ +bool ssh_dh_is_known_group(bignum modulus, bignum generator) +{ + int cmp, bits; + bignum m = NULL; + + bits = bignum_num_bits(modulus); + if (bits < 3072) { + m = ssh_dh_group14; + } else if (bits < 6144) { + m = ssh_dh_group16; + } else { + m = ssh_dh_group18; + } + + cmp = bignum_cmp(m, modulus); + if (cmp != 0) { + return false; + } + + cmp = bignum_cmp(ssh_dh_generator, generator); + if (cmp != 0) { + return false; + } + + SSH_LOG(SSH_LOG_TRACE, "The received primes in FIPS are known"); + return true; +} ssh_key ssh_dh_get_current_server_publickey(ssh_session session) { |