jonathancammack / rpms / openssh

Forked from rpms/openssh 8 months ago
Clone
07d1ba
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
07d1ba
index 36b9d2f5..6b517db4 100644
07d1ba
--- a/auth2-hostbased.c
07d1ba
+++ b/auth2-hostbased.c
07d1ba
@@ -119,6 +119,11 @@ userauth_hostbased(struct ssh *ssh, const char *method)
07d1ba
 		    "(null)" : key->cert->signature_type);
07d1ba
 		goto done;
07d1ba
 	}
07d1ba
+	if ((r = sshkey_check_rsa_length(key,
07d1ba
+	    options.required_rsa_size)) != 0) {
07d1ba
+		logit_r(r, "refusing %s key", sshkey_type(key));
07d1ba
+		goto done;
07d1ba
+	}
07d1ba
 
07d1ba
 	if (!authctxt->valid || authctxt->user == NULL) {
07d1ba
 		debug2_f("disabled because of invalid user");
07d1ba
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
07d1ba
index 962fd342..5d59febc 100644
07d1ba
--- a/auth2-pubkey.c
07d1ba
+++ b/auth2-pubkey.c
07d1ba
@@ -175,6 +175,11 @@ userauth_pubkey(struct ssh *ssh, const char *method)
07d1ba
 		    "(null)" : key->cert->signature_type);
07d1ba
 		goto done;
07d1ba
 	}
07d1ba
+	if ((r = sshkey_check_rsa_length(key,
07d1ba
+	    options.required_rsa_size)) != 0) {
07d1ba
+		logit_r(r, "refusing %s key", sshkey_type(key));
07d1ba
+		goto done;
07d1ba
+	}
07d1ba
 	key_s = format_key(key);
07d1ba
 	if (sshkey_is_cert(key))
07d1ba
 		ca_s = format_key(key->cert->signature_key);
07d1ba
diff --git a/readconf.c b/readconf.c
07d1ba
index 7f26c680..42be690b 100644
07d1ba
--- a/readconf.c
07d1ba
+++ b/readconf.c
07d1ba
@@ -174,7 +174,7 @@ typedef enum {
07d1ba
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
07d1ba
 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
07d1ba
 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
07d1ba
-	oSecurityKeyProvider, oKnownHostsCommand,
07d1ba
+	oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
07d1ba
 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
07d1ba
 } OpCodes;
07d1ba
 
07d1ba
@@ -320,6 +320,8 @@ static struct {
07d1ba
 	{ "proxyjump", oProxyJump },
07d1ba
 	{ "securitykeyprovider", oSecurityKeyProvider },
07d1ba
 	{ "knownhostscommand", oKnownHostsCommand },
07d1ba
+	{ "requiredrsasize", oRequiredRSASize },
07d1ba
+	{ "rsaminsize", oRequiredRSASize }, /* alias */
07d1ba
 
07d1ba
 	{ NULL, oBadOption }
07d1ba
 };
07d1ba
@@ -2176,6 +2177,10 @@ parse_pubkey_algos:
07d1ba
 			*charptr = xstrdup(arg);
07d1ba
 		break;
07d1ba
 
07d1ba
+	case oRequiredRSASize:
07d1ba
+		intptr = &options->required_rsa_size;
07d1ba
+		goto parse_int;
07d1ba
+
07d1ba
 	case oDeprecated:
07d1ba
 		debug("%s line %d: Deprecated option \"%s\"",
07d1ba
 		    filename, linenum, keyword);
07d1ba
@@ -2423,6 +2428,7 @@ initialize_options(Options * options)
07d1ba
 	options->hostbased_accepted_algos = NULL;
07d1ba
 	options->pubkey_accepted_algos = NULL;
07d1ba
 	options->known_hosts_command = NULL;
07d1ba
+	options->required_rsa_size = -1;
07d1ba
 }
07d1ba
 
07d1ba
 /*
07d1ba
@@ -2619,6 +2625,8 @@ fill_default_options(Options * options)
07d1ba
 	if (options->sk_provider == NULL)
07d1ba
 		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
07d1ba
 #endif
07d1ba
+	if (options->required_rsa_size == -1)
07d1ba
+		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
07d1ba
 
07d1ba
 	/* Expand KEX name lists */
07d1ba
 	all_cipher = cipher_alg_list(',', 0);
07d1ba
@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host)
07d1ba
 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
07d1ba
 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
07d1ba
 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
07d1ba
+	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
07d1ba
 
07d1ba
 	/* String options */
07d1ba
 	dump_cfg_string(oBindAddress, o->bind_address);
07d1ba
diff --git a/readconf.h b/readconf.h
07d1ba
index f647bd42..ffb5ec4f 100644
07d1ba
--- a/readconf.h
07d1ba
+++ b/readconf.h
07d1ba
@@ -176,6 +176,8 @@ typedef struct {
07d1ba
 
07d1ba
 	char   *known_hosts_command;
07d1ba
 
07d1ba
+	int	required_rsa_size;	/* minimum size of RSA keys */
07d1ba
+
07d1ba
 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
07d1ba
 }       Options;
07d1ba
 
07d1ba
diff --git a/servconf.c b/servconf.c
07d1ba
index 29df0463..423772b1 100644
07d1ba
--- a/servconf.c
07d1ba
+++ b/servconf.c
07d1ba
@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options)
07d1ba
 	options->fingerprint_hash = -1;
07d1ba
 	options->disable_forwarding = -1;
07d1ba
 	options->expose_userauth_info = -1;
07d1ba
+	options->required_rsa_size = -1;
07d1ba
 }
07d1ba
 
07d1ba
 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
07d1ba
@@ -441,6 +442,8 @@ fill_default_server_options(ServerOptions *options)
07d1ba
 		options->expose_userauth_info = 0;
07d1ba
 	if (options->sk_provider == NULL)
07d1ba
 		options->sk_provider = xstrdup("internal");
07d1ba
+	if (options->required_rsa_size == -1)
07d1ba
+		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
07d1ba
 
07d1ba
 	assemble_algorithms(options);
07d1ba
 
07d1ba
@@ -517,6 +520,7 @@ typedef enum {
07d1ba
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
07d1ba
 	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
07d1ba
 	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
07d1ba
+	sRequiredRSASize,
07d1ba
 	sDeprecated, sIgnore, sUnsupported
07d1ba
 } ServerOpCodes;
07d1ba
 
07d1ba
@@ -676,6 +680,8 @@ static struct {
07d1ba
 	{ "rdomain", sRDomain, SSHCFG_ALL },
07d1ba
 	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
07d1ba
 	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
07d1ba
+	{ "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
07d1ba
+	{ "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
07d1ba
 	{ NULL, sBadOption, 0 }
07d1ba
 };
07d1ba
 
07d1ba
@@ -2438,6 +2443,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
07d1ba
 			*charptr = xstrdup(arg);
07d1ba
 		break;
07d1ba
 
07d1ba
+	case sRequiredRSASize:
07d1ba
+		intptr = &options->required_rsa_size;
07d1ba
+		goto parse_int;
07d1ba
+
07d1ba
 	case sDeprecated:
07d1ba
 	case sIgnore:
07d1ba
 	case sUnsupported:
07d1ba
@@ -2610,6 +2619,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
07d1ba
 	M_CP_INTOPT(rekey_limit);
07d1ba
 	M_CP_INTOPT(rekey_interval);
07d1ba
 	M_CP_INTOPT(log_level);
07d1ba
+	M_CP_INTOPT(required_rsa_size);
07d1ba
 
07d1ba
 	/*
07d1ba
 	 * The bind_mask is a mode_t that may be unsigned, so we can't use
07d1ba
@@ -2874,6 +2884,7 @@ dump_config(ServerOptions *o)
07d1ba
 	dump_cfg_int(sMaxSessions, o->max_sessions);
07d1ba
 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
07d1ba
 	dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
07d1ba
+	dump_cfg_int(sRequiredRSASize, o->required_rsa_size);
07d1ba
 	dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
07d1ba
 
07d1ba
 	/* formatted integer arguments */
07d1ba
diff --git a/servconf.h b/servconf.h
07d1ba
index 8a04463e..9346155c 100644
07d1ba
--- a/servconf.h
07d1ba
+++ b/servconf.h
07d1ba
@@ -229,6 +229,7 @@ typedef struct {
07d1ba
 	int	expose_userauth_info;
07d1ba
 	u_int64_t timing_secret;
07d1ba
 	char   *sk_provider;
07d1ba
+	int	required_rsa_size;	/* minimum size of RSA keys */
07d1ba
 }       ServerOptions;
07d1ba
 
07d1ba
 /* Information about the incoming connection as used by Match */
07d1ba
diff --git a/ssh.c b/ssh.c
07d1ba
index 559bf2af..25be53d5 100644
07d1ba
--- a/ssh.c
07d1ba
+++ b/ssh.c
07d1ba
@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port)
07d1ba
 }
07d1ba
 
07d1ba
 /*
07d1ba
- * Check the result of hostkey loading, ignoring some errors and
07d1ba
- * fatal()ing for others.
07d1ba
+ * Check the result of hostkey loading, ignoring some errors and either
07d1ba
+ * discarding the key or fatal()ing for others.
07d1ba
  */
07d1ba
 static void
07d1ba
-check_load(int r, const char *path, const char *message)
07d1ba
+check_load(int r, struct sshkey **k, const char *path, const char *message)
07d1ba
 {
07d1ba
 	switch (r) {
07d1ba
 	case 0:
07d1ba
+		/* Check RSA keys size and discard if undersized */
07d1ba
+		if (k != NULL && *k != NULL &&
07d1ba
+		    (r = sshkey_check_rsa_length(*k,
07d1ba
+		    options.required_rsa_size)) != 0) {
07d1ba
+			error_r(r, "load %s \"%s\"", message, path);
07d1ba
+			free(*k);
07d1ba
+			*k = NULL;
07d1ba
+		}
07d1ba
 		break;
07d1ba
 	case SSH_ERR_INTERNAL_ERROR:
07d1ba
 	case SSH_ERR_ALLOC_FAIL:
07d1ba
@@ -1578,7 +1586,7 @@ main(int ac, char **av)
07d1ba
 	if ((o) >= sensitive_data.nkeys) \
07d1ba
 		fatal_f("pubkey out of array bounds"); \
07d1ba
 	check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
07d1ba
-	    p, "pubkey"); \
07d1ba
+	    &(sensitive_data.keys[o]), p, "pubkey"); \
07d1ba
 } while (0)
07d1ba
 #define L_CERT(p,o) do { \
07d1ba
 	if ((o) >= sensitive_data.nkeys) \
07d1ba
@@ -1586,7 +1594,8 @@ main(int ac, char **av)
07d1ba
 #define L_CERT(p,o) do { \
07d1ba
 	if ((o) >= sensitive_data.nkeys) \
07d1ba
 		fatal_f("cert out of array bounds"); \
07d1ba
-	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
07d1ba
+	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \
07d1ba
+	    &(sensitive_data.keys[o]), p, "cert"); \
07d1ba
 } while (0)
07d1ba
 
07d1ba
 		if (options.hostbased_authentication == 1) {
07d1ba
@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
07d1ba
 		filename = default_client_percent_dollar_expand(cp, cinfo);
07d1ba
 		free(cp);
07d1ba
 		check_load(sshkey_load_public(filename, &public, NULL),
07d1ba
-		    filename, "pubkey");
07d1ba
+		    &public, filename, "pubkey");
07d1ba
 		debug("identity file %s type %d", filename,
07d1ba
 		    public ? public->type : -1);
07d1ba
 		free(options.identity_files[i]);
07d1ba
@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
07d1ba
 			continue;
07d1ba
 		xasprintf(&cp, "%s-cert", filename);
07d1ba
 		check_load(sshkey_load_public(cp, &public, NULL),
07d1ba
-		    filename, "pubkey");
07d1ba
+		    &public, filename, "pubkey");
07d1ba
 		debug("identity file %s type %d", cp,
07d1ba
 		    public ? public->type : -1);
07d1ba
 		if (public == NULL) {
07d1ba
@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
07d1ba
 		free(cp);
07d1ba
 
07d1ba
 		check_load(sshkey_load_public(filename, &public, NULL),
07d1ba
-		    filename, "certificate");
07d1ba
+		    &public, filename, "certificate");
07d1ba
 		debug("certificate file %s type %d", filename,
07d1ba
 		    public ? public->type : -1);
07d1ba
 		free(options.certificate_files[i]);
07d1ba
diff --git a/sshconnect2.c b/sshconnect2.c
07d1ba
index f9bd19ea..58fe98db 100644
07d1ba
--- a/sshconnect2.c
07d1ba
+++ b/sshconnect2.c
07d1ba
@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info;
07d1ba
 static int
07d1ba
 verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
07d1ba
 {
07d1ba
+	int r;
07d1ba
+
07d1ba
+	if ((r = sshkey_check_rsa_length(hostkey,
07d1ba
+	    options.required_rsa_size)) != 0)
07d1ba
+		fatal_r(r, "Bad server host key");
07d1ba
 	if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
07d1ba
 	    xxx_conn_info) == -1)
07d1ba
 		fatal("Host key verification failed.");
07d1ba
@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id)
07d1ba
 			private = NULL;
07d1ba
 			quit = 1;
07d1ba
 		}
07d1ba
+		if (!quit && (r = sshkey_check_rsa_length(private,
07d1ba
+		    options.required_rsa_size)) != 0) {
07d1ba
+			debug_fr(r, "Skipping key %s", id->filename);
07d1ba
+			sshkey_free(private);
07d1ba
+			private = NULL;
07d1ba
+			quit = 1;
07d1ba
+		}
07d1ba
 		if (!quit && private != NULL && id->agent_fd == -1 &&
07d1ba
 		    !(id->key && id->isprivate))
07d1ba
 			maybe_add_key_to_agent(id->filename, private, comment,
07d1ba
@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
07d1ba
		close(agent_fd);
07d1ba
	} else {
07d1ba
 		for (j = 0; j < idlist->nkeys; j++) {
07d1ba
+			if ((r = sshkey_check_rsa_length(idlist->keys[j],
07d1ba
+			    options.required_rsa_size)) != 0) {
07d1ba
+				debug_fr(r, "ignoring %s agent key",
07d1ba
+				    sshkey_ssh_name(idlist->keys[j]));
07d1ba
+				continue;
07d1ba
+			}
07d1ba
 			found = 0;
07d1ba
 			TAILQ_FOREACH(id, &files, next) {
07d1ba
 				/*
07d1ba
diff --git a/sshd.c b/sshd.c
07d1ba
index 17eee9d8..395ef493 100644
07d1ba
--- a/sshd.c
07d1ba
+++ b/sshd.c
07d1ba
@@ -1870,6 +1870,13 @@ main(int ac, char **av)
07d1ba
 				fatal_r(r, "Could not demote key: \"%s\"",
07d1ba
 				    options.host_key_files[i]);
07d1ba
 		}
07d1ba
+		if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey,
07d1ba
+		    options.required_rsa_size)) != 0) {
07d1ba
+			error_fr(r, "Host key %s", options.host_key_files[i]);
07d1ba
+			sshkey_free(pubkey);
07d1ba
+			sshkey_free(key);
07d1ba
+			continue;
07d1ba
+		}
07d1ba
 		sensitive_data.host_keys[i] = key;
07d1ba
 		sensitive_data.host_pubkeys[i] = pubkey;
07d1ba
 
07d1ba
diff --git a/sshkey.c b/sshkey.c
07d1ba
index ed2b5dff..77093235 100644
07d1ba
--- a/sshkey.c
07d1ba
+++ b/sshkey.c
07d1ba
@@ -2365,18 +2365,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
07d1ba
 	return ret;
07d1ba
 }
07d1ba
 
07d1ba
-#ifdef WITH_OPENSSL
07d1ba
-static int
07d1ba
-check_rsa_length(const RSA *rsa)
07d1ba
+int
07d1ba
+sshkey_check_rsa_length(const struct sshkey *k, int min_size)
07d1ba
 {
07d1ba
+#ifdef WITH_OPENSSL
07d1ba
 	const BIGNUM *rsa_n;
07d1ba
+	int nbits;
07d1ba
 
07d1ba
-	RSA_get0_key(rsa, &rsa_n, NULL, NULL);
07d1ba
-	if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
07d1ba
+	if (k == NULL || k->rsa == NULL ||
07d1ba
+	    (k->type != KEY_RSA && k->type != KEY_RSA_CERT))
07d1ba
+		return 0;
07d1ba
+	RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
07d1ba
+	nbits = BN_num_bits(rsa_n);
07d1ba
+	if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
07d1ba
+	    (min_size > 0 && nbits < min_size))
07d1ba
 		return SSH_ERR_KEY_LENGTH;
07d1ba
+#endif /* WITH_OPENSSL */
07d1ba
 	return 0;
07d1ba
 }
07d1ba
-#endif
07d1ba
 
07d1ba
 static int
07d1ba
 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
07d1ba
@@ -2439,7 +2445,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
07d1ba
 			goto out;
07d1ba
 		}
07d1ba
 		rsa_n = rsa_e = NULL; /* transferred */
07d1ba
-		if ((ret = check_rsa_length(key->rsa)) != 0)
07d1ba
+		if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
07d1ba
 			goto out;
07d1ba
 #ifdef DEBUG_PK
07d1ba
 		RSA_print_fp(stderr, key->rsa, 8);
07d1ba
@@ -3642,7 +3648,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
07d1ba
 			goto out;
07d1ba
 		}
07d1ba
 		rsa_p = rsa_q = NULL; /* transferred */
07d1ba
-		if ((r = check_rsa_length(k->rsa)) != 0)
07d1ba
+		if ((r = sshkey_check_rsa_length(k, 0)) != 0)
07d1ba
 			goto out;
07d1ba
 		if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
07d1ba
 			goto out;
07d1ba
@@ -4644,7 +4650,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
07d1ba
 			r = SSH_ERR_LIBCRYPTO_ERROR;
07d1ba
 			goto out;
07d1ba
 		}
07d1ba
-		if ((r = check_rsa_length(prv->rsa)) != 0)
07d1ba
+		if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
07d1ba
 			goto out;
07d1ba
 	} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
07d1ba
 	    (type == KEY_UNSPEC || type == KEY_DSA)) {
07d1ba
diff --git a/sshkey.h b/sshkey.h
07d1ba
index 094815e0..be254e6b 100644
07d1ba
--- a/sshkey.h
07d1ba
+++ b/sshkey.h
07d1ba
@@ -273,6 +273,7 @@ int	sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
07d1ba
 int	sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
07d1ba
     int type, struct sshkey **pubkeyp);
07d1ba
 
07d1ba
+int sshkey_check_rsa_length(const struct sshkey *, int);
07d1ba
 /* XXX should be internal, but used by ssh-keygen */
07d1ba
 int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
07d1ba
 
07d1ba
diff --git a/ssh.1 b/ssh.1
07d1ba
index b4956aec..e255b9b9 100644
07d1ba
--- a/ssh.1
07d1ba
+++ b/ssh.1
07d1ba
@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see
07d1ba
 .It RemoteCommand
07d1ba
 .It RemoteForward
07d1ba
 .It RequestTTY
07d1ba
+.It RequiredRSASize
07d1ba
 .It SendEnv
07d1ba
 .It ServerAliveInterval
07d1ba
 .It ServerAliveCountMax
07d1ba
diff --git a/ssh_config.5 b/ssh_config.5
07d1ba
index 24a46460..d1ede18e 100644
07d1ba
--- a/ssh_config.5
07d1ba
+++ b/ssh_config.5
07d1ba
@@ -1634,6 +1634,17 @@ and
07d1ba
 .Fl T
07d1ba
 flags for
07d1ba
 .Xr ssh 1 .
07d1ba
+.It Cm RequiredRSASize
07d1ba
+Specifies the minimum RSA key size (in bits) that
07d1ba
+.Xr ssh 1
07d1ba
+will accept.
07d1ba
+User authentication keys smaller than this limit will be ignored.
07d1ba
+Servers that present host keys smaller than this limit will cause the
07d1ba
+connection to be terminated.
07d1ba
+The default is
07d1ba
+.Cm 1024
07d1ba
+bits.
07d1ba
+Note that this limit may only be raised from the default.
07d1ba
 .It Cm RevokedHostKeys
07d1ba
 Specifies revoked host public keys.
07d1ba
 Keys listed in this file will be refused for host authentication.
07d1ba
diff --git a/sshd_config.5 b/sshd_config.5
07d1ba
index 867a747d..f5a06637 100644
07d1ba
--- a/sshd_config.5
07d1ba
+++ b/sshd_config.5
07d1ba
@@ -1596,6 +1596,16 @@ is
07d1ba
 .Cm default none ,
07d1ba
 which means that rekeying is performed after the cipher's default amount
07d1ba
 of data has been sent or received and no time based rekeying is done.
07d1ba
+.It Cm RequiredRSASize
07d1ba
+Specifies the minimum RSA key size (in bits) that
07d1ba
+.Xr sshd 8
07d1ba
+will accept.
07d1ba
+User and host-based authentication keys smaller than this limit will be
07d1ba
+refused.
07d1ba
+The default is
07d1ba
+.Cm 1024
07d1ba
+bits.
07d1ba
+Note that this limit may only be raised from the default.
07d1ba
 .It Cm RevokedKeys
07d1ba
 Specifies revoked public keys file, or
07d1ba
 .Cm none