aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/dh.h1
-rw-r--r--src/dh-gex.c14
-rw-r--r--src/dh.c27
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,
diff --git a/src/dh.c b/src/dh.c
index e6c2cfd9..10830441 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -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)
{