Skip to content

Commit

Permalink
Add RSA Signature restrictions for X9.31 padding in the FIPS provider.
Browse files Browse the repository at this point in the history
In FIPS 140-3, RSA Signing with X9.31 padding is not approved,
but verification is allowed for legacy purposes. An indicator has been added
for RSA signing with X9.31 padding.

A strict restriction on the size of the RSA modulus has been added
i.e. It must be 1024 + 256 * s (which is part of the ANSI X9.31 spec).

Added implementation comments to the X9.31 padding code

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl#24021)
  • Loading branch information
slontis committed Jul 29, 2024
1 parent 9c57eb7 commit 07e4d7f
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 5 deletions.
12 changes: 12 additions & 0 deletions apps/fipsinstall.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef enum OPTION_choice {
OPT_NO_CONDITIONAL_ERRORS,
OPT_NO_SECURITY_CHECKS,
OPT_TLS_PRF_EMS_CHECK, OPT_NO_SHORT_MAC,
OPT_DISALLOW_SIGNATURE_X931_PADDING,
OPT_DISALLOW_DRGB_TRUNC_DIGEST,
OPT_HKDF_DIGEST_CHECK,
OPT_TLS13_KDF_DIGEST_CHECK,
Expand Down Expand Up @@ -91,6 +92,8 @@ const OPTIONS fipsinstall_options[] = {
"Disallow DSA signing"},
{"tdes_encrypt_disabled", OPT_DISALLOW_TDES_ENCRYPT, '-',
"Disallow Triple-DES encryption"},
{"rsa_sign_x931_disabled", OPT_DISALLOW_SIGNATURE_X931_PADDING, '-',
"Disallow X931 Padding for RSA signing"},
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input config file, used when verifying"},

Expand Down Expand Up @@ -122,6 +125,7 @@ typedef struct {
unsigned int x963kdf_digest_check : 1;
unsigned int dsa_sign_disabled : 1;
unsigned int tdes_encrypt_disabled : 1;
unsigned int sign_x931_padding_disabled : 1;
} FIPS_OPTS;

/* Pedantic FIPS compliance */
Expand All @@ -140,6 +144,7 @@ static const FIPS_OPTS pedantic_opts = {
1, /* x963kdf_digest_check */
1, /* dsa_sign_disabled */
1, /* tdes_encrypt_disabled */
1, /* sign_x931_padding_disabled */
};

/* Default FIPS settings for backward compatibility */
Expand All @@ -158,6 +163,7 @@ static FIPS_OPTS fips_opts = {
0, /* x963kdf_digest_check */
0, /* dsa_sign_disabled */
0, /* tdes_encrypt_disabled */
0, /* sign_x931_padding_disabled */
};

static int check_non_pedantic_fips(int pedantic, const char *name)
Expand Down Expand Up @@ -303,6 +309,9 @@ static int write_config_fips_section(BIO *out, const char *section,
opts->dsa_sign_disabled ? "1" : "0") <= 0
|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED,
opts->tdes_encrypt_disabled ? "1" : "0") <= 0
|| BIO_printf(out, "%s = %s\n",
OSSL_PROV_FIPS_PARAM_RSA_SIGN_X931_PAD_DISABLED,
opts->sign_x931_padding_disabled ? "1" : "0") <= 0
|| !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
module_mac_len))
goto end;
Expand Down Expand Up @@ -516,6 +525,9 @@ int fipsinstall_main(int argc, char **argv)
case OPT_DISALLOW_TDES_ENCRYPT:
fips_opts.tdes_encrypt_disabled = 1;
break;
case OPT_DISALLOW_SIGNATURE_X931_PADDING:
fips_opts.sign_x931_padding_disabled = 1;
break;
case OPT_QUIET:
quiet = 1;
/* FALLTHROUGH */
Expand Down
1 change: 1 addition & 0 deletions crypto/rsa/rsa_ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
rsa->_method_mod_n))
goto err;

/* For X9.31: Assuming e is odd it does a 12 mod 16 test */
if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12))
if (!BN_sub(ret, rsa->n, ret))
goto err;
Expand Down
33 changes: 29 additions & 4 deletions crypto/rsa/rsa_x931.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,37 @@
#include <openssl/rsa.h>
#include <openssl/objects.h>

/*
* X9.31 Embeds the hash inside the following data structure
*
* header (4 bits = 0x6)
* padding (consisting of zero or more 4 bit values of a sequence of 0xB,
* ending with the terminator 0xA)
* hash(Msg) hash of a message (the output size is related to the hash function)
* trailer (consists of 2 bytes)
* The 1st byte is related to a part number for a hash algorithm
* (See RSA_X931_hash_id()), followed by the fixed value 0xCC
*
* The RSA modulus size n (which for X9.31 is 1024 + 256*s) is the size of the data
* structure, which determines the padding size.
* i.e. len(padding) = n - len(header) - len(hash) - len(trailer)
*
* Params:
* to The output buffer to write the data structure to.
* tolen The size of 'to' in bytes (it is the size of the n)
* from The input hash followed by the 1st byte of the trailer.
* flen The size of the input hash + 1 (trailer byte)
*/
int RSA_padding_add_X931(unsigned char *to, int tlen,
const unsigned char *from, int flen)
{
int j;
unsigned char *p;

/*
* Absolute minimum amount of padding is 1 header nibble, 1 padding
* nibble and 2 trailer bytes: but 1 hash if is already in 'from'.
* We need at least 1 byte for header + padding (0x6A)
* And 2 trailer bytes (but we subtract 1 since flen includes 1 trailer byte)
*/

j = tlen - flen - 2;

if (j < 0) {
Expand Down Expand Up @@ -101,7 +121,12 @@ int RSA_padding_check_X931(unsigned char *to, int tlen,
return j;
}

/* Translate between X931 hash ids and NIDs */
/*
* Translate between X9.31 hash ids and NIDs
* The returned values relate to ISO/IEC 10118 part numbers which consist of
* a hash algorithm and hash number. The returned values are used as the
* first byte of the 'trailer'.
*/

int RSA_X931_hash_id(int nid)
{
Expand Down
6 changes: 6 additions & 0 deletions doc/man1/openssl-fipsinstall.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ B<openssl fipsinstall>
[B<-dsa_sign_disabled>]
[B<-no_short_mac>]
[B<-tdes_encrypt_disabled>]
[B<-rsa_sign_x931_disabled>]
[B<-self_test_onload>]
[B<-self_test_oninstall>]
[B<-corrupt_desc> I<selftest_description>]
Expand Down Expand Up @@ -251,6 +252,11 @@ Configure the module to not allow Triple-DES encryption.
Triple-DES decryption is still allowed for legacy purposes.
See SP800-131Ar2 for details.

=item B<-rsa_sign_x931_disabled>

Configure the module to not allow X9.31 padding be used when signing with RSA.
See FIPS 140-3 IG C.K for details.

=item B<-self_test_onload>

Do not write the two fields related to the "test status indicator" and
Expand Down
6 changes: 6 additions & 0 deletions doc/man7/EVP_SIGNATURE-RSA.pod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex().

=item "digest-check" (B<OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK>) <integer>

=item "sign-x931-pad-check" (B<SIGNATURE_PARAM_FIPS_SIGN_X931_PAD_CHECK>) <int>

These common parameters are described in L<provider-signature(7)>.

=item "pad-mode" (B<OSSL_SIGNATURE_PARAM_PAD_MODE>) <UTF8 string>
Expand All @@ -41,6 +43,10 @@ The type of padding to be used. Its value can be one of the following:

=item "x931" (B<OSSL_PKEY_RSA_PAD_MODE_X931>)

This padding mode is no longer supported by the FIPS provider for signature
generation, but may be used for signature verification for legacy use cases.
(This is a FIPS 140-3 requirement)

=item "pss" (B<OSSL_PKEY_RSA_PAD_MODE_PSS>)

=back
Expand Down
4 changes: 4 additions & 0 deletions doc/man7/OSSL_PROVIDER-FIPS.pod
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ This is an unapproved algorithm.

=item RSA, see L<EVP_SIGNATURE-RSA(7)>

The B<X931> padding mode "OSSL_PKEY_RSA_PAD_MODE_X931" is no longer supported
for signature generation, but may be used for verification for legacy use cases.
(This is a FIPS 140-3 requirement)

=item DSA, see L<EVP_SIGNATURE-DSA(7)>

=item ED25519, see L<EVP_SIGNATURE-ED25519(7)>
Expand Down
7 changes: 7 additions & 0 deletions doc/man7/provider-signature.pod
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,13 @@ If required this parameter should be set early via an init function.
The default value of 1 causes an error when a signing algorithm is used. (This
is triggered by deprecated signing algorithms).
Setting this to 0 will ignore the error and set the approved "fips-indicator" to 0.

=item "sign-x931-pad-check" (B<SIGNATURE_PARAM_FIPS_SIGN_X931_PAD_CHECK>) <int>

If required this parameter should be set before the padding mode is set
The default value of 1 causes an error if the padding mode is set to X9.31 padding
for a RSA signing operation. Setting this to 0 will ignore the error and set the
approved "fips-indicator" to 0.
This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if
set to 0.

Expand Down
9 changes: 9 additions & 0 deletions include/openssl/fips_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ extern "C" {
*/
# define OSSL_PROV_FIPS_PARAM_TDES_ENCRYPT_DISABLED "tdes-encrypt-disabled"

/*
* A boolean that determines if X9.31 padding can be used for RSA signing.
* X9.31 RSA has been removed from FIPS 186-5, and is no longer approved for
* signing. it may still be used for verification for legacy purposes.
* This is disabled by default.
* Type: OSSL_PARAM_UTF8_STRING
*/
# define OSSL_PROV_FIPS_PARAM_RSA_SIGN_X931_PAD_DISABLED "rsa-sign-x931-pad-disabled"

# ifdef __cplusplus
}
# endif
Expand Down
1 change: 1 addition & 0 deletions providers/common/include/prov/fipscommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ int FIPS_sskdf_digest_check(OSSL_LIB_CTX *libctx);
int FIPS_x963kdf_digest_check(OSSL_LIB_CTX *libctx);
int FIPS_dsa_sign_check(OSSL_LIB_CTX *libctx);
int FIPS_tdes_encrypt_check(OSSL_LIB_CTX *libctx);
int FIPS_rsa_sign_x931_disallowed(OSSL_LIB_CTX *libctx);

#endif
11 changes: 11 additions & 0 deletions providers/fips/fipsprov.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct fips_global_st {
FIPS_OPTION fips_x963kdf_digest_check;
FIPS_OPTION fips_dsa_sign_disallowed;
FIPS_OPTION fips_tdes_encrypt_disallowed;
FIPS_OPTION fips_rsa_sign_x931_disallowed;
} FIPS_GLOBAL;

static void init_fips_option(FIPS_OPTION *opt, int enabled)
Expand All @@ -123,6 +124,7 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
init_fips_option(&fgbl->fips_x963kdf_digest_check, 0);
init_fips_option(&fgbl->fips_dsa_sign_disallowed, 0);
init_fips_option(&fgbl->fips_tdes_encrypt_disallowed, 0);
init_fips_option(&fgbl->fips_rsa_sign_x931_disallowed, 0);
return fgbl;
}

Expand Down Expand Up @@ -157,6 +159,8 @@ static const OSSL_PARAM fips_param_types[] = {
NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED, OSSL_PARAM_INTEGER,
NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_RSA_SIGN_X931_PAD_DISABLED,
OSSL_PARAM_INTEGER, NULL, 0),
OSSL_PARAM_END
};

Expand Down Expand Up @@ -227,6 +231,8 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
fips_dsa_sign_disallowed);
FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_TDES_ENCRYPT_DISABLED,
fips_tdes_encrypt_disallowed);
FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_RSA_SIGN_X931_PAD_DISABLED,
fips_rsa_sign_x931_disallowed);
#undef FIPS_FEATURE_OPTION

*p = OSSL_PARAM_construct_end();
Expand Down Expand Up @@ -292,6 +298,8 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[])
fips_dsa_sign_disallowed);
FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED,
fips_tdes_encrypt_disallowed);
FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_RSA_SIGN_X931_PAD_DISABLED,
fips_rsa_sign_x931_disallowed);
#undef FIPS_FEATURE_GET
return 1;
}
Expand Down Expand Up @@ -835,6 +843,7 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
FIPS_SET_OPTION(fgbl, fips_x963kdf_digest_check);
FIPS_SET_OPTION(fgbl, fips_dsa_sign_disallowed);
FIPS_SET_OPTION(fgbl, fips_tdes_encrypt_disallowed);
FIPS_SET_OPTION(fgbl, fips_rsa_sign_x931_disallowed);
#undef FIPS_SET_OPTION

ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
Expand Down Expand Up @@ -1045,6 +1054,8 @@ FIPS_FEATURE_CHECK(FIPS_sskdf_digest_check, fips_sskdf_digest_check)
FIPS_FEATURE_CHECK(FIPS_x963kdf_digest_check, fips_x963kdf_digest_check)
FIPS_FEATURE_CHECK(FIPS_dsa_sign_check, fips_dsa_sign_disallowed)
FIPS_FEATURE_CHECK(FIPS_tdes_encrypt_check, fips_tdes_encrypt_disallowed)
FIPS_FEATURE_CHECK(FIPS_rsa_sign_x931_disallowed,
fips_rsa_sign_x931_disallowed)

#undef FIPS_FEATURE_CHECK

Expand Down
36 changes: 35 additions & 1 deletion providers/implementations/signature/rsa_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,6 @@ static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
sig, prsactx->rsa, RSA_X931_PADDING);
clean_tbuf(prsactx);
break;

case RSA_PKCS1_PADDING:
{
unsigned int sltmp;
Expand Down Expand Up @@ -1196,6 +1195,25 @@ static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
return known_gettable_ctx_params;
}

#ifdef FIPS_MODULE
static int rsa_x931_padding_allowed(PROV_RSA_CTX *ctx)
{
int approved = ((ctx->operation & EVP_PKEY_OP_SIGN) == 0);

if (!approved) {
if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE2,
ctx->libctx,
"RSA Sign set ctx", "X931 Padding",
FIPS_rsa_sign_x931_disallowed)) {
ERR_raise(ERR_LIB_PROV,
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}
}
return 1;
}
#endif

static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
Expand All @@ -1220,6 +1238,10 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK))
return 0;

if (!OSSL_FIPS_IND_SET_CTX_PARAM(prsactx, OSSL_FIPS_IND_SETTABLE2, params,
OSSL_SIGNATURE_PARAM_FIPS_SIGN_X931_PAD_CHECK))
return 0;

pad_mode = prsactx->pad_mode;
saltlen = prsactx->saltlen;

Expand Down Expand Up @@ -1292,6 +1314,16 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
err_extra_text = "No padding not allowed with RSA-PSS";
goto cont;
case RSA_X931_PADDING:
#ifdef FIPS_MODULE
/* X9.31 only allows sizes of 1024 + 256 * s (bits) */
if ((RSA_bits(prsactx->rsa) & 0xFF) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
/* RSA Signing with X9.31 padding is not allowed in FIPS 140-3 */
if (!rsa_x931_padding_allowed(prsactx))
return 0;
#endif
err_extra_text = "X.931 padding not allowed with RSA-PSS";
cont:
if (RSA_test_flags(prsactx->rsa,
Expand Down Expand Up @@ -1438,6 +1470,7 @@ static const OSSL_PARAM settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_SIGN_X931_PAD_CHECK)
OSSL_PARAM_END
};

Expand All @@ -1448,6 +1481,7 @@ static const OSSL_PARAM settable_ctx_params_no_digest[] = {
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)
OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_SIGN_X931_PAD_CHECK)
OSSL_PARAM_END
};

Expand Down
1 change: 1 addition & 0 deletions test/evp_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ static const OSSL_PARAM settable_ctx_params[] = {
OSSL_PARAM_int("ems_check", NULL),
OSSL_PARAM_int("sign-check", NULL),
OSSL_PARAM_int("encrypt-check", NULL),
OSSL_PARAM_int("sign-x931-pad-check", NULL),
OSSL_PARAM_END
};

Expand Down
18 changes: 18 additions & 0 deletions test/recipes/30-test_evp_data/evppkey_rsa_common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,14 @@ Key = RSA-512
Input = "Hello"
Result = DIGESTVERIFYINIT_ERROR

# RSA Signing with X931 is not approved in FIPS 140-3
FIPSversion = >=3.4.0
Sign = RSA-2048
Ctrl = rsa_padding_mode:x931
Input = "0123456789ABCDEF123456789ABC"
Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
Result = PKEY_CTRL_ERROR

##################################################
# Check that the indicator callback is triggered

Expand Down Expand Up @@ -2008,3 +2016,13 @@ CtrlInit = key-check:0
Key = RSA-512
Input = "Hello"
Result = VERIFY_ERROR

# RSA Signing with X931 is not approved in FIPS 140-3
FIPSversion = >=3.4.0
Sign = RSA-2048
Unapproved = 1
CtrlInit = sign-x931-pad-check:0
Ctrl = digest:SHA256
Ctrl = rsa_padding_mode:x931
Input = "0123456789ABCDEF123456789ABCDEFG"
Output = 4b75f521e2e6eeda3f2dcb84ebdacbadeab8ffc1ecdf06c7c4e38727e082a8f5e71be66cdee6d14da1d3a0f18ff20914f71b5308363c81e7471688f4f201e82603ea6a7f31da89cd846b30e2893fd956e76b3d23d40f733e0358e3883526158c74577ba43cc664eaeb909818e75b89fc764cf4575517f87251f8d3cf29b1532f33e6183d454bddd6f255d0ca4415d957eb90dbc55d047f48a01c6e68d5ab46327a158ff7a3383b5b0446b8cd4a91b8859abd3285020a1613ef17d3f8562147828bb36be65505eeec77e968d04e172e2851ff1d7ef523b4022deb72d5fbf78db6738d170098586b904d1c369cedb5e3fe1b909a8dd8ac3beb521af2510d044580
Loading

0 comments on commit 07e4d7f

Please sign in to comment.