From 85caa417e0915aaae9fa6f87ccfa6c4c79b41dbb Mon Sep 17 00:00:00 2001 From: slontis Date: Thu, 4 Jul 2024 11:59:43 +1000 Subject: [PATCH] Disable DSA signing in the FIPS provider. This is a FIPS 140-3 requirement. This uses a FIP indicator if either the FIPS configurable "dsa_sign_disabled" is set to 0, OR OSSL_SIGNATURE_PARAM_FIPS_SIGN_CHECK is set to 0 in the dsa signing context. Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/24799) --- apps/fipsinstall.c | 25 +++++++--- doc/man1/openssl-fipsinstall.pod.in | 6 +++ doc/man7/EVP_SIGNATURE-DSA.pod | 2 + doc/man7/provider-signature.pod | 11 ++++- include/openssl/fips_names.h | 7 +++ providers/common/include/prov/fipscommon.h | 1 + providers/common/include/prov/securitycheck.h | 4 ++ providers/fips/fipsprov.c | 12 ++++- providers/fips/self_test_data.inc | 5 ++ providers/fips/self_test_kats.c | 20 +++++--- providers/implementations/signature/dsa_sig.c | 28 ++++++++++- test/acvp_test.c | 18 ++++--- test/evp_test.c | 3 +- test/recipes/20-test_cli_fips.t | 5 +- test/recipes/30-test_evp_data/evppkey_dsa.txt | 49 +++++++++++++++++-- test/recipes/80-test_cms.t | 8 ++- test/recipes/80-test_ssl_new.t | 8 +++ test/recipes/80-test_ssl_old.t | 15 +++++- util/mk-fipsmodule-cnf.pl | 4 ++ util/perl/OpenSSL/paramnames.pm | 2 + 20 files changed, 201 insertions(+), 32 deletions(-) diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c index 171d6166170..d725839787b 100644 --- a/apps/fipsinstall.c +++ b/apps/fipsinstall.c @@ -46,6 +46,7 @@ typedef enum OPTION_choice { OPT_SSHKDF_DIGEST_CHECK, OPT_SSKDF_DIGEST_CHECK, OPT_X963KDF_DIGEST_CHECK, + OPT_DISALLOW_DSA_SIGN, OPT_SELF_TEST_ONLOAD, OPT_SELF_TEST_ONINSTALL } OPTION_CHOICE; @@ -54,7 +55,7 @@ const OPTIONS fipsinstall_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"pedantic", OPT_PEDANTIC, '-', "Set options for strict FIPS compliance"}, {"verify", OPT_VERIFY, '-', - "Verify a config file instead of generating one"}, + "Verify a config file instead of generating one"}, {"module", OPT_MODULE, '<', "File name of the provider module"}, {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"}, {"section_name", OPT_SECTION_NAME, 's', @@ -84,6 +85,8 @@ const OPTIONS fipsinstall_options[] = { "Enable digest check for SSKDF"}, {"x963kdf_digest_check", OPT_X963KDF_DIGEST_CHECK, '-', "Enable digest check for X963KDF"}, + {"dsa_sign_disabled", OPT_DISALLOW_DSA_SIGN, '-', + "Disallow DSA signing"}, OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input config file, used when verifying"}, @@ -112,6 +115,7 @@ typedef struct { unsigned int sshkdf_digest_check : 1; unsigned int sskdf_digest_check : 1; unsigned int x963kdf_digest_check : 1; + unsigned int dsa_sign_disabled : 1; } FIPS_OPTS; /* Pedantic FIPS compliance */ @@ -127,6 +131,7 @@ static const FIPS_OPTS pedantic_opts = { 1, /* sshkdf_digest_check */ 1, /* sskdf_digest_check */ 1, /* x963kdf_digest_check */ + 1, /* dsa_sign_disabled */ }; /* Default FIPS settings for backward compatibility */ @@ -142,6 +147,7 @@ static FIPS_OPTS fips_opts = { 0, /* sshkdf_digest_check */ 0, /* sskdf_digest_check */ 0, /* x963kdf_digest_check */ + 0, /* dsa_sign_disabled */ }; static int check_non_pedantic_fips(int pedantic, const char *name) @@ -281,6 +287,8 @@ static int write_config_fips_section(BIO *out, const char *section, || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_X963KDF_DIGEST_CHECK, opts->x963kdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_DSA_SIGN_DISABLED, + opts->dsa_sign_disabled ? "1" : "0") <= 0 || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, module_mac_len)) goto end; @@ -290,7 +298,7 @@ static int write_config_fips_section(BIO *out, const char *section, install_mac_len) || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS, INSTALL_STATUS_VAL) <= 0) - goto end; + goto end; } ret = 1; end: @@ -307,12 +315,12 @@ static CONF *generate_config_and_load(const char *prov_name, CONF *conf = NULL; mem_bio = BIO_new(BIO_s_mem()); - if (mem_bio == NULL) + if (mem_bio == NULL) return 0; if (!write_config_header(mem_bio, prov_name, section) - || !write_config_fips_section(mem_bio, section, - module_mac, module_mac_len, - opts, NULL, 0)) + || !write_config_fips_section(mem_bio, section, + module_mac, module_mac_len, + opts, NULL, 0)) goto end; conf = app_load_config_bio(mem_bio, NULL); @@ -434,7 +442,7 @@ int fipsinstall_main(int argc, char **argv) switch (o) { case OPT_EOF: case OPT_ERR: -opthelp: + opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto cleanup; case OPT_HELP: @@ -485,6 +493,9 @@ opthelp: case OPT_X963KDF_DIGEST_CHECK: fips_opts.x963kdf_digest_check = 1; break; + case OPT_DISALLOW_DSA_SIGN: + fips_opts.dsa_sign_disabled = 1; + break; case OPT_QUIET: quiet = 1; /* FALLTHROUGH */ diff --git a/doc/man1/openssl-fipsinstall.pod.in b/doc/man1/openssl-fipsinstall.pod.in index 5bffe97d790..cb985989041 100644 --- a/doc/man1/openssl-fipsinstall.pod.in +++ b/doc/man1/openssl-fipsinstall.pod.in @@ -30,6 +30,7 @@ B [B<-sshkdf_digest_check>] [B<-sskdf_digest_check>] [B<-x963kdf_digest_check>] +[B<-dsa_sign_disabled>] [B<-self_test_onload>] [B<-self_test_oninstall>] [B<-corrupt_desc> I] @@ -232,6 +233,11 @@ Configure the module to enable a run-time digest check when deriving a key by X963KDF. See NIST SP 800-131Ar2 for details. +=item B<-dsa_sign_disabled> + +Configure the module to not allow DSA signing (DSA signature verification is +still allowed). 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 diff --git a/doc/man7/EVP_SIGNATURE-DSA.pod b/doc/man7/EVP_SIGNATURE-DSA.pod index b0ae2ea33f5..ca33f5f7513 100644 --- a/doc/man7/EVP_SIGNATURE-DSA.pod +++ b/doc/man7/EVP_SIGNATURE-DSA.pod @@ -29,6 +29,8 @@ using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex(). =item "digest-check" (B) +=item "sign-check" (B) + The settable parameters are described in L. =back diff --git a/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod index 49466e2cbcc..01647d42a75 100644 --- a/doc/man7/provider-signature.pod +++ b/doc/man7/provider-signature.pod @@ -392,7 +392,7 @@ supply known values that either pass or fail. A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. This may be used after calling either the sign or verify final functions. It may -return 0 if either the "digest-check" or the "key-check" are set to 0. +return 0 if either the "digest-check", "key-check", or "sign-check" are set to 0. This option is used by the OpenSSL FIPS provider. =item "key-check" (B) @@ -414,6 +414,15 @@ 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. +=item "sign-check" (B) + +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. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + =back OSSL_FUNC_signature_gettable_ctx_params() and OSSL_FUNC_signature_settable_ctx_params() get a diff --git a/include/openssl/fips_names.h b/include/openssl/fips_names.h index dbf27166309..1c87c8f7e6b 100644 --- a/include/openssl/fips_names.h +++ b/include/openssl/fips_names.h @@ -118,6 +118,13 @@ extern "C" { */ # define OSSL_PROV_FIPS_PARAM_X963KDF_DIGEST_CHECK "x963kdf-digest-check" +/* + * A boolean that determines if DSA signing operations are allowed. + * This is disabled by default. + * Type: OSSL_PARAM_UTF8_STRING + */ +# define OSSL_PROV_FIPS_PARAM_DSA_SIGN_DISABLED "dsa-sign-disabled" + # ifdef __cplusplus } # endif diff --git a/providers/common/include/prov/fipscommon.h b/providers/common/include/prov/fipscommon.h index a38bb33ed9e..1e26f99e1d4 100644 --- a/providers/common/include/prov/fipscommon.h +++ b/providers/common/include/prov/fipscommon.h @@ -19,5 +19,6 @@ int FIPS_tls1_prf_digest_check(OSSL_LIB_CTX *libctx); int FIPS_sshkdf_digest_check(OSSL_LIB_CTX *libctx); 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); #endif diff --git a/providers/common/include/prov/securitycheck.h b/providers/common/include/prov/securitycheck.h index 70d22492ff2..860fcaeca45 100644 --- a/providers/common/include/prov/securitycheck.h +++ b/providers/common/include/prov/securitycheck.h @@ -10,6 +10,10 @@ #include "crypto/types.h" #include +#ifdef FIPS_MODULE +# include "fipscommon.h" +#endif + /* Functions that are common */ int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect); int ossl_rsa_check_key_size(const RSA *rsa, int protect); diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 71936e3ab0d..f686c786f0c 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -97,6 +97,7 @@ typedef struct fips_global_st { FIPS_OPTION fips_sshkdf_digest_check; FIPS_OPTION fips_sskdf_digest_check; FIPS_OPTION fips_x963kdf_digest_check; + FIPS_OPTION fips_dsa_sign_disallowed; } FIPS_GLOBAL; static void init_fips_option(FIPS_OPTION *opt, int enabled) @@ -120,6 +121,7 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) init_fips_option(&fgbl->fips_sshkdf_digest_check, 0); init_fips_option(&fgbl->fips_sskdf_digest_check, 0); init_fips_option(&fgbl->fips_x963kdf_digest_check, 0); + init_fips_option(&fgbl->fips_dsa_sign_disallowed, 0); return fgbl; } @@ -149,6 +151,8 @@ static const OSSL_PARAM fips_param_types[] = { NULL, 0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_X963KDF_DIGEST_CHECK, OSSL_PARAM_INTEGER, NULL, 0), + OSSL_PARAM_DEFN(OSSL_PROV_PARAM_DSA_SIGN_DISABLED, + OSSL_PARAM_INTEGER, NULL, 0), OSSL_PARAM_END }; @@ -162,7 +166,7 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl) * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS and * OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK are not self test parameters. */ - OSSL_PARAM core_params[16], *p = core_params; + OSSL_PARAM core_params[17], *p = core_params; *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_PARAM_CORE_MODULE_FILENAME, @@ -213,6 +217,8 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl) fips_sskdf_digest_check); FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_X963KDF_DIGEST_CHECK, fips_x963kdf_digest_check); + FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_DSA_SIGN_DISABLED, + fips_dsa_sign_disallowed); #undef FIPS_FEATURE_OPTION *p = OSSL_PARAM_construct_end(); @@ -272,6 +278,8 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[]) fips_sskdf_digest_check); FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_X963KDF_DIGEST_CHECK, fips_x963kdf_digest_check); + FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_DSA_SIGN_DISABLED, + fips_dsa_sign_disallowed); #undef FIPS_FEATURE_GET return 1; } @@ -812,6 +820,7 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, FIPS_SET_OPTION(fgbl, fips_sshkdf_digest_check); FIPS_SET_OPTION(fgbl, fips_sskdf_digest_check); FIPS_SET_OPTION(fgbl, fips_x963kdf_digest_check); + FIPS_SET_OPTION(fgbl, fips_dsa_sign_disallowed); #undef FIPS_SET_OPTION ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers); @@ -1019,6 +1028,7 @@ FIPS_FEATURE_CHECK(FIPS_tls1_prf_digest_check, fips_tls1_prf_digest_check) FIPS_FEATURE_CHECK(FIPS_sshkdf_digest_check, fips_sshkdf_digest_check) 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) #undef FIPS_FEATURE_CHECK diff --git a/providers/fips/self_test_data.inc b/providers/fips/self_test_data.inc index 9a612468045..4abb628c86e 100644 --- a/providers/fips/self_test_data.inc +++ b/providers/fips/self_test_data.inc @@ -44,6 +44,9 @@ typedef struct st_kat_st { #define CIPHER_MODE_DECRYPT 2 #define CIPHER_MODE_ALL (CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT) +/* FIPS 140-3 only allows DSA verification for legacy purposes */ +#define ST_PARAM_VERIFY_ONLY "verify_only" + typedef ST_KAT ST_KAT_DIGEST; typedef struct st_kat_cipher_st { ST_KAT base; @@ -1632,12 +1635,14 @@ static const unsigned char dsa_expected_sig[] = { 0x34, 0x8d, 0x9e, 0x88, 0x08, 0x06 }; +static int verify_only = 1; static const ST_KAT_PARAM dsa_key[] = { ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_P, dsa_p), ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_Q, dsa_q), ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_G, dsa_g), ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PUB_KEY, dsa_pub), ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, dsa_priv), + ST_KAT_PARAM_INT(ST_PARAM_VERIFY_ONLY, verify_only), ST_KAT_PARAM_END() }; #endif /* OPENSSL_NO_DSA */ diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c index 07f3e433ad1..9f2e58ff7c8 100644 --- a/providers/fips/self_test_kats.c +++ b/providers/fips/self_test_kats.c @@ -488,8 +488,7 @@ static int self_test_sign(const ST_KAT_SIGN *t, /* Create a EVP_PKEY_CTX to use for the signing operation */ sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL); - if (sctx == NULL - || EVP_PKEY_sign_init(sctx) <= 0) + if (sctx == NULL) goto err; /* set signature parameters */ @@ -498,11 +497,20 @@ static int self_test_sign(const ST_KAT_SIGN *t, strlen(t->mdalgorithm) + 1)) goto err; params_sig = OSSL_PARAM_BLD_to_param(bld); - if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) - goto err; - if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0 - || EVP_PKEY_verify_init(sctx) <= 0 + /* Skip the sign for legacy algorithms that only support the verify operation */ + if (OSSL_PARAM_locate(params, ST_PARAM_VERIFY_ONLY) == NULL) { + if (EVP_PKEY_sign_init(sctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) + goto err; + if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0) + goto err; + } else { + memcpy(sig, t->sig_expected, t->sig_expected_len); + siglen = t->sig_expected_len; + } + if (EVP_PKEY_verify_init(sctx) <= 0 || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) goto err; diff --git a/providers/implementations/signature/dsa_sig.c b/providers/implementations/signature/dsa_sig.c index 7df8adfdd5b..832fa2f10da 100644 --- a/providers/implementations/signature/dsa_sig.c +++ b/providers/implementations/signature/dsa_sig.c @@ -209,6 +209,19 @@ err: } #ifdef FIPS_MODULE + +static int dsa_sign_check_approved(PROV_DSA_CTX *ctx, int signing, + const char *desc) +{ + /* DSA Signing is not approved in FIPS 140-3 */ + if (signing + && !OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE2, + ctx->libctx, desc, "DSA", + FIPS_dsa_sign_check)) + return 0; + return 1; +} + static int dsa_check_key(PROV_DSA_CTX *ctx, int sign, const char *desc) { int approved = ossl_dsa_check_key(ctx->dsa, sign); @@ -253,6 +266,8 @@ static int dsa_signverify_init(void *vpdsactx, void *vdsa, if (!dsa_set_ctx_params(pdsactx, params)) return 0; #ifdef FIPS_MODULE + if (!dsa_sign_check_approved(pdsactx, operation == EVP_PKEY_OP_SIGN, desc)) + return 0; if (!dsa_check_key(pdsactx, operation == EVP_PKEY_OP_SIGN, desc)) return 0; #endif @@ -284,6 +299,11 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, if (!ossl_prov_is_running()) return 0; +#ifdef FIPS_MODULE + if (!dsa_sign_check_approved(pdsactx, 1, "Sign")) + return 0; +#endif + if (sig == NULL) { *siglen = dsasize; return 1; @@ -541,10 +561,13 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[]) if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdsactx, OSSL_FIPS_IND_SETTABLE0, params, OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)) - return 0; + return 0; if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdsactx, OSSL_FIPS_IND_SETTABLE1, params, OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)) - return 0; + return 0; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdsactx, OSSL_FIPS_IND_SETTABLE2, params, + OSSL_SIGNATURE_PARAM_FIPS_SIGN_CHECK)) + return 0; p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); if (p != NULL) { @@ -575,6 +598,7 @@ static const OSSL_PARAM settable_ctx_params[] = { OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), 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_CHECK) OSSL_PARAM_END }; diff --git a/test/acvp_test.c b/test/acvp_test.c index 45509095afd..82ecaf8b00e 100644 --- a/test/acvp_test.c +++ b/test/acvp_test.c @@ -46,6 +46,9 @@ static OSSL_PROVIDER *prov_null = NULL; static OSSL_LIB_CTX *libctx = NULL; static SELF_TEST_ARGS self_test_args = { 0 }; static OSSL_CALLBACK self_test_events; +#ifndef OPENSSL_NO_DSA +static int dsasign_allowed = 1; +#endif const OPTIONS *test_get_options(void) { @@ -597,12 +600,14 @@ static int dsa_siggen_test(int id) if (!TEST_ptr(pkey = dsa_keygen(tst->L, tst->N))) goto err; - if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len, - &sig, &sig_len)) - || !TEST_true(get_dsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen))) - goto err; - test_output_memory("r", r, rlen); - test_output_memory("s", s, slen); + if (dsasign_allowed) { + if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len, + &sig, &sig_len)) + || !TEST_true(get_dsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen))) + goto err; + test_output_memory("r", r, rlen); + test_output_memory("s", s, slen); + } ret = 1; err: OPENSSL_free(r); @@ -1479,6 +1484,7 @@ int setup_tests(void) #endif /* OPENSSL_NO_DH */ #ifndef OPENSSL_NO_DSA + dsasign_allowed = fips_provider_version_lt(libctx, 3, 4, 0); ADD_ALL_TESTS(dsa_keygen_test, OSSL_NELEM(dsa_keygen_data)); ADD_ALL_TESTS(dsa_paramgen_test, OSSL_NELEM(dsa_paramgen_data)); ADD_ALL_TESTS(dsa_pqver_test, OSSL_NELEM(dsa_pqver_data)); diff --git a/test/evp_test.c b/test/evp_test.c index c14cb196f4d..b44842bc917 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -189,6 +189,7 @@ static const OSSL_PARAM settable_ctx_params[] = { OSSL_PARAM_int("key-check", NULL), OSSL_PARAM_int("digest-check", NULL), OSSL_PARAM_int("ems_check", NULL), + OSSL_PARAM_int("sign-check", NULL), OSSL_PARAM_END }; @@ -4072,7 +4073,7 @@ static int check_deterministic_noncetype(EVP_TEST *t, static int signverify_init(EVP_TEST *t, DIGESTSIGN_DATA *data) { const char *name = data->md == NULL ? NULL : EVP_MD_get0_name(data->md); - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM params[5]; OSSL_PARAM *p = NULL; int i, ret = 0; size_t params_n = 0, params_allocated_n = 0; diff --git a/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t index d4b4d4ca51c..8f9c6c3941d 100644 --- a/test/recipes/20-test_cli_fips.t +++ b/test/recipes/20-test_cli_fips.t @@ -36,6 +36,9 @@ my $bogus_data = $fipsconf; $ENV{OPENSSL_CONF} = $fipsconf; +run(test(["fips_version_test", "-config", $fipsconf, "<3.4.0"]), + capture => 1, statusvar => \my $dsasignpass); + ok(run(app(['openssl', 'list', '-public-key-methods', '-verbose'])), "provider listing of public key methods"); ok(run(app(['openssl', 'list', '-public-key-algorithms', '-verbose'])), @@ -279,7 +282,7 @@ SKIP: { SKIP : { skip "FIPS DSA tests because of no dsa in this build", 1 - if disabled("dsa"); + if disabled("dsa") || $dsasignpass == '0'; subtest DSA => sub { my $testtext_prefix = 'DSA'; diff --git a/test/recipes/30-test_evp_data/evppkey_dsa.txt b/test/recipes/30-test_evp_data/evppkey_dsa.txt index 5cc5f015e68..1109abb4531 100644 --- a/test/recipes/30-test_evp_data/evppkey_dsa.txt +++ b/test/recipes/30-test_evp_data/evppkey_dsa.txt @@ -277,6 +277,7 @@ Output = 00 Result = DIGESTSIGNINIT_ERROR # Test sign with a 2048 bit key with N == 224 is allowed in fips mode +FIPSversion = <3.4.0 DigestSign = SHA256 Key = DSA-2048-224 Input = "Hello" @@ -284,18 +285,21 @@ Output = 00 Result = SIGNATURE_MISMATCH # Test sign with a 2048 bit key with N == 256 is allowed in fips mode +FIPSversion = <3.4.0 DigestSign = SHA256 Key = DSA-2048-256 Input = "Hello" Result = SIGNATURE_MISMATCH # Test sign with a 3072 bit key with N == 256 is allowed in fips mode +FIPSversion = <3.4.0 DigestSign = SHA256 Key = DSA-3072-256 Input = "Hello" Result = SIGNATURE_MISMATCH # Test sign with a 2048 bit SHA3 is allowed in fips mode +FIPSversion = <3.4.0 DigestSign = SHA3-224 Key = DSA-2048-256 Input = "Hello" @@ -354,45 +358,82 @@ Key = DSA-4096-256 Input = "Hello" Result = DIGESTSIGNINIT_ERROR +# Test sign is not allowed in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Key = DSA-2048-256 +Input = "Hello" +Result = DIGESTSIGNINIT_ERROR + Title = Fips Indicator Tests # Check that the indicator callback is triggered -# Test sign with a 1024 bit key in fips mode +# Test sign with a 1024 bit key is unapproved in fips mode if the sign and key +# checks are ignored. FIPSversion = >=3.4.0 DigestSign = SHA256 Securitycheck = 1 Unapproved = 1 +CtrlInit = sign-check:0 CtrlInit = key-check:0 Key = DSA-1024-FIPS186-2 Input = "Hello" Result = SIGNATURE_MISMATCH -# Test sign with a 3072 bit key with N == 224 is not allowed in fips mode +# Test sign with a 1024 bit key is unapproved and fails the key check in +# fips mode if the sign check is ignored +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = sign-check:0 +Key = DSA-1024-FIPS186-2 +Input = "Hello" +Result = DIGESTSIGNINIT_ERROR + +# Test sign with a 3072 bit key with N == 224 is unapproved in fips mode if the +# sign and key checks are ignored FIPSversion = >=3.4.0 DigestSign = SHA256 Securitycheck = 1 Unapproved = 1 +CtrlInit = sign-check:0 CtrlInit = key-check:0 Key = DSA-3072-224 Input = "Hello" Result = SIGNATURE_MISMATCH -# Test sign with a 4096 bit key is not allowed in fips mode +# Test sign with a 4096 bit key is unapproved in fips mode if the sign and key +# checks are ignored FIPSversion = >=3.4.0 DigestSign = SHA256 Securitycheck = 1 Unapproved = 1 +CtrlInit = sign-check:0 CtrlInit = key-check:0 Key = DSA-4096-256 Input = "Hello" Result = SIGNATURE_MISMATCH -# Test sign with SHA1 is not allowed in fips mode +# Test DSA sign with SHA1 is unapproved in fips mode if the sign and digest checks +# are ignored FIPSversion = >=3.4.0 DigestSign = SHA1 Securitycheck = 1 Unapproved = 1 +CtrlInit = sign-check:0 CtrlInit = digest-check:0 Key = DSA-2048-256 Input = "Hello" Result = SIGNATURE_MISMATCH + +# Test sign with SHA1 is unapproved in fips mode if DSA sign check is ignored +FIPSversion = >=3.4.0 +DigestSign = SHA1 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = sign-check:0 +Key = DSA-2048-256 +Input = "Hello" +Result = DIGESTSIGNINIT_ERROR diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index cff058f0a31..84e0fe2d879 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -40,6 +40,7 @@ my @defaultprov = ("-provider-path", $provpath, my @config = ( ); my $provname = 'default'; +my $dsaallow = '1'; my $datadir = srctop_dir("test", "recipes", "80-test_cms_data"); my $smdir = srctop_dir("test", "smime-certs"); @@ -55,8 +56,13 @@ plan tests => 25; ok(run(test(["pkcs7_test"])), "test pkcs7"); unless ($no_fips) { - @config = ( "-config", srctop_file("test", "fips-and-base.cnf") ); + my $provconf = srctop_file("test", "fips-and-base.cnf"); + @config = ( "-config", $provconf ); $provname = 'fips'; + + run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]), + capture => 1, statusvar => \$dsaallow); + $no_dsa = 1 if $dsaallow == '0'; } $ENV{OPENSSL_TEST_LIBCTX} = "1"; diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 195b85ea8cd..7684191fc1d 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -28,6 +28,7 @@ use lib srctop_dir('Configurations'); use lib bldtop_dir('.'); my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); +my $dsaallow = '1'; $ENV{TEST_CERTS_DIR} = srctop_dir("test", "certs"); @@ -48,6 +49,12 @@ map { s/;.*// } @conf_srcs if $^O eq "VMS"; my @conf_files = map { basename($_, ".in") } @conf_srcs; map { s/\^// } @conf_files if $^O eq "VMS"; +unless ($no_fips) { + my $provconf = srctop_file("test", "fips-and-base.cnf"); + run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]), + capture => 1, statusvar => \$dsaallow); +} + # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. my $is_default_tls = (disabled("ssl3") && !disabled("tls1") && @@ -177,6 +184,7 @@ sub test_conf { # Test 3. Run the test. skip "No tests available; skipping tests", 1 if $skip; skip "Stale sources; skipping tests", 1 if !$run_test; + skip "Dsa not allowed in FIPS 140-3 provider", 1 if ($provider eq "fips") && ($dsaallow eq '0'); my $msg = "running CTLOG_FILE=test/ct/log_list.cnf". # $ENV{CTLOG_FILE}. " TEST_CERTS_DIR=test/certs". # $ENV{TEST_CERTS_DIR}. diff --git a/test/recipes/80-test_ssl_old.t b/test/recipes/80-test_ssl_old.t index 50b74a1e295..b967dc14c56 100644 --- a/test/recipes/80-test_ssl_old.t +++ b/test/recipes/80-test_ssl_old.t @@ -38,6 +38,7 @@ my $no_anydtls = alldisabled(available_protocols("dtls")); plan skip_all => "No SSL/TLS/DTLS protocol is support by this OpenSSL build" if $no_anytls && $no_anydtls; +my $dsaallow = '1'; my $digest = "-sha1"; my @reqcmd = ("openssl", "req"); my @x509cmd = ("openssl", "x509", $digest); @@ -331,6 +332,12 @@ sub testssl { push @providerflags, "-provider", "legacy"; } + $dsaallow = '1'; + if ($provider eq "fips") { + run(test(["fips_version_test", "-config", $configfile, "<3.4.0"]), + capture => 1, statusvar => \$dsaallow); + } + my @ssltest = ("ssl_old_test", "-s_key", $key, "-s_cert", $cert, "-c_key", $key, "-c_cert", $cert, @@ -436,7 +443,7 @@ sub testssl { my @exkeys = (); my $ciphers = '-PSK:-SRP:@SECLEVEL=0'; - if (!$no_dsa) { + if (!$no_dsa && $dsaallow == '1') { push @exkeys, "-s_cert", "certD.ss", "-s_key", $Dkey; } @@ -494,7 +501,11 @@ sub testssl { my $flag = $protocol eq "-tls1_3" ? "" : $protocol; my $ciphersuites = ""; foreach my $cipher (@{$ciphersuites{$protocol}}) { - if ($protocol eq "-ssl3" && $cipher =~ /ECDH/ ) { + if ($dsaallow == '0' && index($cipher, "DSS") != -1) { + # DSA is not allowed in FIPS 140-3 + note "*****SKIPPING $protocol $cipher"; + ok(1); + } elsif ($protocol eq "-ssl3" && $cipher =~ /ECDH/ ) { note "*****SKIPPING $protocol $cipher"; ok(1); } else { diff --git a/util/mk-fipsmodule-cnf.pl b/util/mk-fipsmodule-cnf.pl index b6a49382bdb..54b774e0631 100644 --- a/util/mk-fipsmodule-cnf.pl +++ b/util/mk-fipsmodule-cnf.pl @@ -15,8 +15,10 @@ my $security_checks = 1; my $ems_check = 1; my $drgb_no_trunc_dgst = 1; my $kdf_digest_check = 1; +my $dsa_sign_disabled = 1; my $activate = 1; +my $version = 1; my $mac_key; my $module_name; my $section_name = "fips_sect"; @@ -44,10 +46,12 @@ my $module_mac = join(':', @module_mac); print <<_____; [$section_name] activate = $activate +install-version = $version conditional-errors = $conditional_errors security-checks = $security_checks tls1-prf-ems-check = $ems_check drbg-no-trunc-md = $drgb_no_trunc_dgst +dsa-sign-disabled = $dsa_sign_disabled module-mac = $module_mac hkdf-digest-check = $kdf_digest_check tls13-kdf-digest-check = $kdf_digest_check diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index a7087fb3a2a..3d1ef1c65ed 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -39,6 +39,7 @@ my %params = ( 'PROV_PARAM_SSHKDF_DIGEST_CHECK' => "sshkdf-digest-check", # uint 'PROV_PARAM_SSKDF_DIGEST_CHECK' => "sskdf-digest-check", # uint 'PROV_PARAM_X963KDF_DIGEST_CHECK' => "x963kdf-digest-check", # uint + 'PROV_PARAM_DSA_SIGN_DISABLED' => "dsa-sign-disabled", # uint # Self test callback parameters 'PROV_PARAM_SELF_TEST_PHASE' => "st-phase",# utf8_string @@ -407,6 +408,7 @@ my %params = ( 'SIGNATURE_PARAM_CONTEXT_STRING' => "context-string", 'SIGNATURE_PARAM_FIPS_DIGEST_CHECK' => '*PKEY_PARAM_FIPS_DIGEST_CHECK', 'SIGNATURE_PARAM_FIPS_KEY_CHECK' => '*PKEY_PARAM_FIPS_KEY_CHECK', + 'SIGNATURE_PARAM_FIPS_SIGN_CHECK' => "sign-check", 'SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Asym cipher parameters -- 2.47.2