jonathancammack / rpms / openssh

Forked from rpms/openssh a year ago
Clone
4b21ae
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
4b21ae
index 2ab222ed6..4e9437912 100644
4b21ae
--- a/auth2-hostbased.c
4b21ae
+++ b/auth2-hostbased.c
4b21ae
@@ -118,6 +118,10 @@ userauth_hostbased(struct ssh *ssh, const char *method)
4b21ae
 		    "(null)" : key->cert->signature_type);
4b21ae
 		goto done;
4b21ae
 	}
4b21ae
+	if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
4b21ae
+		logit("refusing %s key", sshkey_type(key));
4b21ae
+		goto done;
4b21ae
+	}
4b21ae
 
4b21ae
 	if (!authctxt->valid || authctxt->user == NULL) {
4b21ae
 		debug2_f("disabled because of invalid user");
4b21ae
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
4b21ae
index daa756a01..68e7dea1f 100644
4b21ae
--- a/auth2-pubkey.c
4b21ae
+++ b/auth2-pubkey.c
4b21ae
@@ -172,6 +172,10 @@ userauth_pubkey(struct ssh *ssh, const char *method)
4b21ae
 		    "(null)" : key->cert->signature_type);
4b21ae
 		goto done;
4b21ae
 	}
4b21ae
+	if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
4b21ae
+		logit("refusing %s key", sshkey_type(key));
4b21ae
+		goto done;
4b21ae
+	}
4b21ae
 	key_s = format_key(key);
4b21ae
 	if (sshkey_is_cert(key))
4b21ae
 		ca_s = format_key(key->cert->signature_key);
4b21ae
diff --git a/readconf.c b/readconf.c
4b21ae
index 5b5afa8e3..5e17abd41 100644
4b21ae
--- a/readconf.c
4b21ae
+++ b/readconf.c
4b21ae
@@ -160,7 +160,7 @@ typedef enum {
4b21ae
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
4b21ae
 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
4b21ae
 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
4b21ae
-	oSecurityKeyProvider, oKnownHostsCommand,
4b21ae
+	oSecurityKeyProvider, oKnownHostsCommand, oRSAMinSize,
4b21ae
 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
4b21ae
 } OpCodes;
4b21ae
 
4b21ae
@@ -306,6 +306,7 @@ static struct {
4b21ae
 	{ "proxyjump", oProxyJump },
4b21ae
 	{ "securitykeyprovider", oSecurityKeyProvider },
4b21ae
 	{ "knownhostscommand", oKnownHostsCommand },
4b21ae
+	{ "rsaminsize", oRSAMinSize },
4b21ae
 
4b21ae
 	{ NULL, oBadOption }
4b21ae
 };
4b21ae
@@ -2162,6 +2163,10 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
4b21ae
 			*charptr = xstrdup(arg);
4b21ae
 		break;
4b21ae
 
4b21ae
+	case oRSAMinSize:
4b21ae
+		intptr = &options->rsa_min_size;
4b21ae
+		goto parse_int;
4b21ae
+
4b21ae
 	case oDeprecated:
4b21ae
 		debug("%s line %d: Deprecated option \"%s\"",
4b21ae
 		    filename, linenum, keyword);
4b21ae
@@ -2409,6 +2414,7 @@ initialize_options(Options * options)
4b21ae
 	options->hostbased_accepted_algos = NULL;
4b21ae
 	options->pubkey_accepted_algos = NULL;
4b21ae
 	options->known_hosts_command = NULL;
4b21ae
+	options->rsa_min_size = -1;
4b21ae
 }
4b21ae
 
4b21ae
 /*
4b21ae
@@ -2598,6 +2604,8 @@ fill_default_options(Options * options)
4b21ae
 	if (options->sk_provider == NULL)
4b21ae
 		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
4b21ae
 #endif
4b21ae
+	if (options->rsa_min_size == -1)
4b21ae
+		options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
4b21ae
 
4b21ae
 	/* Expand KEX name lists */
4b21ae
 	all_cipher = cipher_alg_list(',', 0);
4b21ae
@@ -3287,6 +3295,7 @@ dump_client_config(Options *o, const char *host)
4b21ae
 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
4b21ae
 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
4b21ae
 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
4b21ae
+	dump_cfg_int(oRSAMinSize, o->rsa_min_size);
4b21ae
 
4b21ae
 	/* String options */
4b21ae
 	dump_cfg_string(oBindAddress, o->bind_address);
4b21ae
diff --git a/readconf.h b/readconf.h
4b21ae
index f647bd42a..29db353ab 100644
4b21ae
--- a/readconf.h
4b21ae
+++ b/readconf.h
4b21ae
@@ -176,6 +176,8 @@ typedef struct {
4b21ae
 
4b21ae
 	char   *known_hosts_command;
4b21ae
 
4b21ae
+	int	rsa_min_size;	/* minimum size of RSA keys */
4b21ae
+
4b21ae
 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
4b21ae
 }       Options;
4b21ae
 
4b21ae
diff --git a/servconf.c b/servconf.c
4b21ae
index f7317a5cb..362ff5b67 100644
4b21ae
--- a/servconf.c
4b21ae
+++ b/servconf.c
4b21ae
@@ -177,6 +177,7 @@ initialize_server_options(ServerOptions *options)
4b21ae
 	options->fingerprint_hash = -1;
4b21ae
 	options->disable_forwarding = -1;
4b21ae
 	options->expose_userauth_info = -1;
4b21ae
+	options->rsa_min_size = -1;
4b21ae
 }
4b21ae
 
4b21ae
 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
4b21ae
@@ -416,6 +417,8 @@ fill_default_server_options(ServerOptions *options)
4b21ae
 		options->expose_userauth_info = 0;
4b21ae
 	if (options->sk_provider == NULL)
4b21ae
 		options->sk_provider = xstrdup("internal");
4b21ae
+	if (options->rsa_min_size == -1)
4b21ae
+		options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
4b21ae
 
4b21ae
 	assemble_algorithms(options);
4b21ae
 
4b21ae
@@ -489,6 +492,7 @@ typedef enum {
4b21ae
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
4b21ae
 	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
4b21ae
 	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
4b21ae
+	sRSAMinSize,
4b21ae
 	sDeprecated, sIgnore, sUnsupported
4b21ae
 } ServerOpCodes;
4b21ae
 
4b21ae
@@ -632,6 +636,7 @@ static struct {
4b21ae
 	{ "rdomain", sRDomain, SSHCFG_ALL },
4b21ae
 	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
4b21ae
 	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
4b21ae
+	{ "rsaminsize", sRSAMinSize, SSHCFG_ALL },
4b21ae
 	{ NULL, sBadOption, 0 }
4b21ae
 };
4b21ae
 
4b21ae
@@ -2377,6 +2382,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
4b21ae
 			*charptr = xstrdup(arg);
4b21ae
 		break;
4b21ae
 
4b21ae
+	case sRSAMinSize:
4b21ae
+		intptr = &options->rsa_min_size;
4b21ae
+		goto parse_int;
4b21ae
+
4b21ae
 	case sDeprecated:
4b21ae
 	case sIgnore:
4b21ae
 	case sUnsupported:
4b21ae
@@ -2549,6 +2558,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
4b21ae
 	M_CP_INTOPT(rekey_limit);
4b21ae
 	M_CP_INTOPT(rekey_interval);
4b21ae
 	M_CP_INTOPT(log_level);
4b21ae
+	M_CP_INTOPT(rsa_min_size);
4b21ae
 
4b21ae
 	/*
4b21ae
 	 * The bind_mask is a mode_t that may be unsigned, so we can't use
4b21ae
@@ -2810,6 +2820,7 @@ dump_config(ServerOptions *o)
4b21ae
 	dump_cfg_int(sMaxSessions, o->max_sessions);
4b21ae
 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
4b21ae
 	dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
4b21ae
+	dump_cfg_int(sRSAMinSize, o->rsa_min_size);
4b21ae
 	dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
4b21ae
 
4b21ae
 	/* formatted integer arguments */
4b21ae
diff --git a/servconf.h b/servconf.h
4b21ae
index 115db1e79..2e3486906 100644
4b21ae
--- a/servconf.h
4b21ae
+++ b/servconf.h
4b21ae
@@ -227,6 +227,7 @@ typedef struct {
4b21ae
 	int	expose_userauth_info;
4b21ae
 	u_int64_t timing_secret;
4b21ae
 	char   *sk_provider;
4b21ae
+	int	rsa_min_size;	/* minimum size of RSA keys */
4b21ae
 }       ServerOptions;
4b21ae
 
4b21ae
 /* Information about the incoming connection as used by Match */
4b21ae
diff --git a/ssh.c b/ssh.c
4b21ae
index a926cc007..cd13fb879 100644
4b21ae
--- a/ssh.c
4b21ae
+++ b/ssh.c
4b21ae
@@ -500,14 +500,22 @@ resolve_canonicalize(char **hostp, int port)
4b21ae
 }
4b21ae
 
4b21ae
 /*
4b21ae
- * Check the result of hostkey loading, ignoring some errors and
4b21ae
- * fatal()ing for others.
4b21ae
+ * Check the result of hostkey loading, ignoring some errors and either
4b21ae
+ * discarding the key or fatal()ing for others.
4b21ae
  */
4b21ae
 static void
4b21ae
-check_load(int r, const char *path, const char *message)
4b21ae
+check_load(int r, struct sshkey **k, const char *path, const char *message)
4b21ae
 {
4b21ae
 	switch (r) {
4b21ae
 	case 0:
4b21ae
+		/* Check RSA keys size and discard if undersized */
4b21ae
+		if (k != NULL && *k != NULL &&
4b21ae
+		    (r = sshkey_check_rsa_length(*k,
4b21ae
+		    options.rsa_min_size)) != 0) {
4b21ae
+			error_r(r, "load %s \"%s\"", message, path);
4b21ae
+			free(*k);
4b21ae
+			*k = NULL;
4b21ae
+		}
4b21ae
 		break;
4b21ae
 	case SSH_ERR_INTERNAL_ERROR:
4b21ae
 	case SSH_ERR_ALLOC_FAIL:
4b21ae
@@ -1557,12 +1565,13 @@ main(int ac, char **av)
4b21ae
 	if ((o) >= sensitive_data.nkeys) \
4b21ae
 		fatal_f("pubkey out of array bounds"); \
4b21ae
 	check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
4b21ae
-	    p, "pubkey"); \
4b21ae
+	    &(sensitive_data.keys[o]), p, "pubkey"); \
4b21ae
 } while (0)
4b21ae
 #define L_CERT(p,o) do { \
4b21ae
 	if ((o) >= sensitive_data.nkeys) \
4b21ae
 		fatal_f("cert out of array bounds"); \
4b21ae
-	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
4b21ae
+	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \
4b21ae
+	    &(sensitive_data.keys[o]), p, "cert"); \
4b21ae
 } while (0)
4b21ae
 
4b21ae
 		if (options.hostbased_authentication == 1) {
4b21ae
@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
4b21ae
 		filename = default_client_percent_dollar_expand(cp, cinfo);
4b21ae
 		free(cp);
4b21ae
 		check_load(sshkey_load_public(filename, &public, NULL),
4b21ae
-		    filename, "pubkey");
4b21ae
+		    &public, filename, "pubkey");
4b21ae
 		debug("identity file %s type %d", filename,
4b21ae
 		    public ? public->type : -1);
4b21ae
 		free(options.identity_files[i]);
4b21ae
@@ -2263,7 +2272,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
4b21ae
 			continue;
4b21ae
 		xasprintf(&cp, "%s-cert", filename);
4b21ae
 		check_load(sshkey_load_public(cp, &public, NULL),
4b21ae
-		    filename, "pubkey");
4b21ae
+		    &public, filename, "pubkey");
4b21ae
 		debug("identity file %s type %d", cp,
4b21ae
 		    public ? public->type : -1);
4b21ae
 		if (public == NULL) {
4b21ae
@@ -2294,7 +2303,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
4b21ae
 		free(cp);
4b21ae
 
4b21ae
 		check_load(sshkey_load_public(filename, &public, NULL),
4b21ae
-		    filename, "certificate");
4b21ae
+		    &public, filename, "certificate");
4b21ae
 		debug("certificate file %s type %d", filename,
4b21ae
 		    public ? public->type : -1);
4b21ae
 		free(options.certificate_files[i]);
4b21ae
diff --git a/sshconnect2.c b/sshconnect2.c
4b21ae
index 67f8e0309..d050c1656 100644
4b21ae
--- a/sshconnect2.c
4b21ae
+++ b/sshconnect2.c
4b21ae
@@ -91,6 +91,10 @@ static const struct ssh_conn_info *xxx_conn_info;
4b21ae
 static int
4b21ae
 verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
4b21ae
 {
4b21ae
+	int r;
4b21ae
+
4b21ae
+	if ((r = sshkey_check_rsa_length(hostkey, options.rsa_min_size)) != 0)
4b21ae
+		fatal_r(r, "Bad server host key");
4b21ae
 	if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
4b21ae
 	    xxx_conn_info) == -1)
4b21ae
 		fatal("Host key verification failed.");
4b21ae
@@ -1747,6 +1751,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
4b21ae
		close(agent_fd);
4b21ae
	} else {
4b21ae
 		for (j = 0; j < idlist->nkeys; j++) {
4b21ae
+			if ((r = sshkey_check_rsa_length(idlist->keys[j],
4b21ae
+			    options.rsa_min_size)) != 0) {
4b21ae
+				debug_fr(r, "ignoring %s agent key",
4b21ae
+				    sshkey_ssh_name(idlist->keys[j]));
4b21ae
+				continue;
4b21ae
+			}
4b21ae
 			found = 0;
4b21ae
 			TAILQ_FOREACH(id, &files, next) {
4b21ae
 				/*
4b21ae
diff --git a/sshd.c b/sshd.c
4b21ae
index d26eb86ae..5f36905a1 100644
4b21ae
--- a/sshd.c
4b21ae
+++ b/sshd.c
4b21ae
@@ -1746,6 +1746,13 @@ main(int ac, char **av)
4b21ae
 				fatal_r(r, "Could not demote key: \"%s\"",
4b21ae
 				    options.host_key_files[i]);
4b21ae
 		}
4b21ae
+		if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey,
4b21ae
+		    options.rsa_min_size)) != 0) {
4b21ae
+			error_fr(r, "Host key %s", options.host_key_files[i]);
4b21ae
+			sshkey_free(pubkey);
4b21ae
+			sshkey_free(key);
4b21ae
+			continue;
4b21ae
+		}
4b21ae
 		sensitive_data.host_keys[i] = key;
4b21ae
 		sensitive_data.host_pubkeys[i] = pubkey;
4b21ae
 
4b21ae
diff --git a/sshkey.c b/sshkey.c
4b21ae
index 47864e6d8..8bad6bd99 100644
4b21ae
--- a/sshkey.c
4b21ae
+++ b/sshkey.c
4b21ae
@@ -2319,18 +2319,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
4b21ae
 	return ret;
4b21ae
 }
4b21ae
 
4b21ae
-#ifdef WITH_OPENSSL
4b21ae
-static int
4b21ae
-check_rsa_length(const RSA *rsa)
4b21ae
+int
4b21ae
+sshkey_check_rsa_length(const struct sshkey *k, int min_size)
4b21ae
 {
4b21ae
+#ifdef WITH_OPENSSL
4b21ae
 	const BIGNUM *rsa_n;
4b21ae
+	int nbits;
4b21ae
 
4b21ae
-	RSA_get0_key(rsa, &rsa_n, NULL, NULL);
4b21ae
-	if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
4b21ae
+	if (k == NULL || k->rsa == NULL ||
4b21ae
+	    (k->type != KEY_RSA && k->type != KEY_RSA_CERT))
4b21ae
+		return 0;
4b21ae
+	RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
4b21ae
+	nbits = BN_num_bits(rsa_n);
4b21ae
+	if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
4b21ae
+	    (min_size > 0 && nbits < min_size))
4b21ae
 		return SSH_ERR_KEY_LENGTH;
4b21ae
+#endif /* WITH_OPENSSL */
4b21ae
 	return 0;
4b21ae
 }
4b21ae
-#endif
4b21ae
 
4b21ae
 static int
4b21ae
 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
4b21ae
@@ -2391,7 +2397,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
4b21ae
 			goto out;
4b21ae
 		}
4b21ae
 		rsa_n = rsa_e = NULL; /* transferred */
4b21ae
-		if ((ret = check_rsa_length(key->rsa)) != 0)
4b21ae
+		if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
4b21ae
 			goto out;
4b21ae
 #ifdef DEBUG_PK
4b21ae
 		RSA_print_fp(stderr, key->rsa, 8);
4b21ae
@@ -3580,7 +3586,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
4b21ae
 			goto out;
4b21ae
 		}
4b21ae
 		rsa_p = rsa_q = NULL; /* transferred */
4b21ae
-		if ((r = check_rsa_length(k->rsa)) != 0)
4b21ae
+		if ((r = sshkey_check_rsa_length(k, 0)) != 0)
4b21ae
 			goto out;
4b21ae
 		if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
4b21ae
 			goto out;
4b21ae
@@ -4566,7 +4572,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
4b21ae
 			r = SSH_ERR_LIBCRYPTO_ERROR;
4b21ae
 			goto out;
4b21ae
 		}
4b21ae
-		if ((r = check_rsa_length(prv->rsa)) != 0)
4b21ae
+		if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
4b21ae
 			goto out;
4b21ae
 	} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
4b21ae
 	    (type == KEY_UNSPEC || type == KEY_DSA)) {
4b21ae
diff --git a/sshkey.h b/sshkey.h
4b21ae
index 125cadb64..52e879456 100644
4b21ae
--- a/sshkey.h
4b21ae
+++ b/sshkey.h
4b21ae
@@ -267,6 +267,7 @@ int	sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4b21ae
 int	sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
4b21ae
     int type, struct sshkey **pubkeyp);
4b21ae
 
4b21ae
+int sshkey_check_rsa_length(const struct sshkey *, int);
4b21ae
 /* XXX should be internal, but used by ssh-keygen */
4b21ae
 int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
4b21ae
 
4b21ae
diff --git a/ssh.1 b/ssh.1
4b21ae
index b4956aec..b1a40ebd 100644
4b21ae
--- a/ssh.1
4b21ae
+++ b/ssh.1
4b21ae
@@ -554,6 +554,7 @@ For full details of the options listed below, and their possible values, see
4b21ae
 .It LogLevel
4b21ae
 .It MACs
4b21ae
 .It Match
4b21ae
+.It RSAMinSize
4b21ae
 .It NoHostAuthenticationForLocalhost
4b21ae
 .It NumberOfPasswordPrompts
4b21ae
 .It PasswordAuthentication
4b21ae
diff --git a/ssh_config.5 b/ssh_config.5
4b21ae
index 24a46460..68771e4b 100644
4b21ae
--- a/ssh_config.5
4b21ae
+++ b/ssh_config.5
4b21ae
@@ -1322,6 +1322,10 @@ The argument to this keyword must be
4b21ae
 or
4b21ae
 .Cm no
4b21ae
 (the default).
4b21ae
+.It Cm RSAMinSize
4b21ae
+Provides a minimal bits requirement for RSA keys when used for signature and
4b21ae
+verification but not for the key generation. The default value is 1024 and
4b21ae
+can't be reduced.
4b21ae
 .It Cm NumberOfPasswordPrompts
4b21ae
 Specifies the number of password prompts before giving up.
4b21ae
 The argument to this keyword must be an integer.
4b21ae
diff --git a/sshd_config.5 b/sshd_config.5
4b21ae
index 867a747d..e08811ca 100644
4b21ae
--- a/sshd_config.5
4b21ae
+++ b/sshd_config.5
4b21ae
@@ -1266,6 +1266,10 @@ will refuse connection attempts with a probability of rate/100 (30%)
4b21ae
 if there are currently start (10) unauthenticated connections.
4b21ae
 The probability increases linearly and all connection attempts
4b21ae
 are refused if the number of unauthenticated connections reaches full (60).
4b21ae
+.It Cm RSAMinSize
4b21ae
+Provides a minimal bits requirement for RSA keys when used for signature and
4b21ae
+verification but not for the key generation. The default value is 1024 and
4b21ae
+can't be reduced.
4b21ae
 .It Cm ModuliFile
4b21ae
 Specifies the
4b21ae
 .Xr moduli 5
4b21ae
diff --git a/sshkey.h b/sshkey.h
4b21ae
index 094815e0..2bb8cb90 100644
4b21ae
--- a/sshkey.h
4b21ae
+++ b/sshkey.h
4b21ae
@@ -286,6 +286,8 @@ int	 sshkey_private_serialize_maxsign(struct sshkey *key,
4b21ae
 
4b21ae
 void	 sshkey_sig_details_free(struct sshkey_sig_details *);
4b21ae
 
4b21ae
+int ssh_set_rsa_min_bits(int minbits);
4b21ae
+
4b21ae
 #ifdef SSHKEY_INTERNAL
4b21ae
 int ssh_rsa_sign(const struct sshkey *key,
4b21ae
     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,