typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_3, OPT_F4, OPT_ENGINE,
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OPT_3,
+#endif
+ OPT_F4, OPT_ENGINE,
OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
#endif
OPT_SECTION("Input"),
- {"3", OPT_3, '-', "Use 3 for the E value"},
- {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
- {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"3", OPT_3, '-', "(deprecated) Use 3 for the E value"},
+#endif
+ {"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
+ {"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output the key to specified file"},
ret = 0;
opt_help(genrsa_options);
goto end;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
case OPT_3:
f4 = RSA_3;
break;
+#endif
case OPT_F4:
f4 = RSA_F4;
break;
return rsa_keygen(NULL, rsa, bits, primes, e_value, cb, 0);
}
-static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
- BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
+#ifndef FIPS_MODULE
+static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb)
{
- int ok = -1;
-#ifdef FIPS_MODULE
- if (primes != 2)
- return 0;
- ok = rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
- pairwise_test = 1; /* FIPS MODE needs to always run the pairwise test */
-#else
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
int n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
BN_CTX *ctx = NULL;
BN_ULONG bitst = 0;
unsigned long error = 0;
+ int ok = -1;
if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */
goto err;
}
+ /* A bad value for e can cause infinite loops */
+ if (e_value != NULL && !rsa_check_public_exponent(e_value)) {
+ RSAerr(0, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
+ return 0;
+ }
+
if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */
RSAerr(0, RSA_R_KEY_PRIME_NUM_INVALID);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
+ return ok;
+}
#endif /* FIPS_MODULE */
+static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
+{
+ int ok = 0;
+
+ /*
+ * Only multi-prime keys or insecure keys with a small key length will use
+ * the older rsa_multiprime_keygen().
+ */
+ if (primes == 2 && bits >= 2048)
+ ok = rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+#ifndef FIPS_MODULE
+ else
+ ok = rsa_multiprime_keygen(rsa, bits, primes, e_value, cb);
+#endif /* FIPS_MODULE */
+
+#ifdef FIPS_MODULE
+ pairwise_test = 1; /* FIPS MODE needs to always run the pairwise test */
+#endif
if (pairwise_test && ok > 0) {
OSSL_CALLBACK *stcb = NULL;
void *stcbarg = NULL;
return ret;
}
+#ifndef FIPS_MODULE
+static int bn_is_three(const BIGNUM *bn)
+{
+ BIGNUM *num = BN_dup(bn);
+ int ret = (num != NULL && BN_sub_word(num, 3) && BN_is_zero(num));
+
+ BN_free(num);
+ return ret;
+}
+#endif /* FIPS_MODULE */
+
/* Check exponent is odd, and has a bitlen ranging from [17..256] */
int rsa_check_public_exponent(const BIGNUM *e)
{
- int bitlen = BN_num_bits(e);
+ int bitlen;
+
+ /* For legacy purposes RSA_3 is allowed in non fips mode */
+#ifndef FIPS_MODULE
+ if (bn_is_three(e))
+ return 1;
+#endif /* FIPS_MODULE */
- return (BN_is_odd(e) && bitlen > 16 && bitlen < 257);
+ bitlen = BN_num_bits(e);
+ return (BN_is_odd(e) && bitlen > 16 && bitlen < 257);
}
/*
* Signature Generation and Key Agree/Transport.
*/
if (nbits < RSA_FIPS1864_MIN_KEYGEN_KEYSIZE) {
- RSAerr(RSA_F_RSA_FIPS186_4_GEN_PROB_PRIMES, RSA_R_INVALID_KEY_LENGTH);
+ RSAerr(RSA_F_RSA_FIPS186_4_GEN_PROB_PRIMES, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
int rsa_sp800_56b_validate_strength(int nbits, int strength)
{
int s = (int)ifc_ffc_compute_security_bits(nbits);
-
+#ifdef FIPS_MODULE
if (s < RSA_FIPS1864_MIN_KEYGEN_STRENGTH
|| s > RSA_FIPS1864_MAX_KEYGEN_STRENGTH) {
RSAerr(RSA_F_RSA_SP800_56B_VALIDATE_STRENGTH, RSA_R_INVALID_MODULUS);
return 0;
}
+#endif
if (strength != -1 && s != strength) {
RSAerr(RSA_F_RSA_SP800_56B_VALIDATE_STRENGTH, RSA_R_INVALID_STRENGTH);
return 0;
{- $OpenSSL::safe::opt_provider_synopsis -}
[B<numbits>]
-=for openssl ifdef engine
+=for openssl ifdef engine 3
=head1 DESCRIPTION
=item B<-F4>, B<-f4>, B<-3>
The public exponent to use, either 65537 or 3. The default is 65537.
+The B<-3> option has been deprecated.
=item B<-primes> I<num>
being generated so the maximum number could be less.
Some providers may only support a value of 2.
+=item "e" (B<OSSL_PKEY_PARAM_RSA_E>) <unsigned integer>
+
+The RSA "e" value. The value may be any odd number greater than or equal to
+65537. The default value is 65537.
+For legacy reasons a value of 3 is currently accepted but is deprecated.
+
=back
=head1 CONFORMING TO
# ifndef OPENSSL_NO_DEPRECATED_3_0
/* The types RSA and RSA_METHOD are defined in ossl_typ.h */
-# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
+# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 2048
# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
setup("test_genrsa");
-plan tests => 9;
+plan tests => 12;
# We want to know that an absurdly small number of bits isn't support
if (disabled("deprecated-3.0")) {
my $bits = 2 ** $checked;
if (disabled("deprecated-3.0")) {
$fin = run(app([ 'openssl', 'genpkey', '-out', 'genrsatest.pem',
- '-algorithm', 'RSA', '-pkeyopt', 'rsa_keygen_pubexp:3',
+ '-algorithm', 'RSA', '-pkeyopt', 'rsa_keygen_pubexp:65537',
'-pkeyopt', "rsa_keygen_bits:$bits",
], stderr => undef));
} else {
note "Found lowest allowed amount of bits to be $good";
ok(run(app([ 'openssl', 'genpkey', '-algorithm', 'RSA',
- '-pkeyopt', 'rsa_keygen_pubexp:3',
+ '-pkeyopt', 'rsa_keygen_pubexp:65537',
'-pkeyopt', "rsa_keygen_bits:$good",
'-out', 'genrsatest.pem' ])),
"genpkey -3 $good");
'-pkeyopt', "rsa_keygen_bits:$good",
'-out', 'genrsatest.pem' ])),
"genpkey -f4 $good");
-ok(run(app([ 'openssl', 'pkey', '-check', '-in', 'genrsatest.pem', '-noout' ])),
+
+ok(run(app([ 'openssl', 'genpkey', '-algorithm', 'RSA',
+ '-pkeyopt', 'rsa_keygen_bits:2048',
+ '-out', 'genrsatest2048.pem' ])),
+ "genpkey 2048 bits");
+ok(run(app([ 'openssl', 'pkey', '-check', '-in', 'genrsatest2048.pem', '-noout' ])),
"pkey -check");
+ok(!run(app([ 'openssl', 'genpkey', '-algorithm', 'RSA',
+ '-pkeyopt', 'hexe:02',
+ '-out', 'genrsatest.pem' ])),
+ "genpkey with a bad public exponent should fail");
+ok(!run(app([ 'openssl', 'genpkey', '-algorithm', 'RSA',
+ '-pkeyopt', 'e:65538',
+ '-out', 'genrsatest.pem' ])),
+ "genpkey with a even public exponent should fail");
+
+
SKIP: {
skip "Skipping rsa command line test", 4 if disabled("deprecated-3.0");