#include "prov/providercommon.h"
#include "prov/provider_util.h"
#include "prov/seeding.h"
+#include "prov/fipscommon.h"
+#include "internal/nelem.h"
#include "self_test.h"
#include "crypto/context.h"
#include "internal/core.h"
static OSSL_FUNC_provider_get_params_fn fips_get_params;
static OSSL_FUNC_provider_query_operation_fn fips_query;
-/* Locale object accessor functions */
-#ifdef OPENSSL_SYS_MACOSX
-# include <xlocale.h>
-#else
-# include <locale.h>
-#endif
-
-#if defined OPENSSL_SYS_WINDOWS
-# define locale_t _locale_t
-# define freelocale _free_locale
-#endif
-static locale_t loc;
-
-static int fips_init_casecmp(void);
-static void fips_deinit_casecmp(void);
-
-#define ALGC(NAMES, FUNC, CHECK) { { NAMES, FIPS_DEFAULT_PROPERTIES, FUNC }, CHECK }
+#define ALGC(NAMES, FUNC, CHECK) \
+ { { NAMES, FIPS_DEFAULT_PROPERTIES, FUNC }, CHECK }
+#define UNAPPROVED_ALGC(NAMES, FUNC, CHECK) \
+ { { NAMES, FIPS_UNAPPROVED_PROPERTIES, FUNC }, CHECK }
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
+#define UNAPPROVED_ALG(NAMES, FUNC) UNAPPROVED_ALGC(NAMES, FUNC, NULL)
extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
-int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
/*
* Should these function pointers be stored in the provider side provctx? Could
static OSSL_FUNC_self_test_cb_fn *c_stcbfn = NULL;
static OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+typedef struct {
+ const char *option;
+ unsigned char enabled;
+} FIPS_OPTION;
+
typedef struct fips_global_st {
const OSSL_CORE_HANDLE *handle;
SELF_TEST_POST_PARAMS selftest_params;
- int fips_security_checks;
- const char *fips_security_check_option;
+ FIPS_OPTION fips_security_checks;
+ FIPS_OPTION fips_tls1_prf_ems_check;
+ FIPS_OPTION fips_restricted_drgb_digests;
} FIPS_GLOBAL;
+static void init_fips_option(FIPS_OPTION *opt, int enabled)
+{
+ opt->enabled = enabled;
+ opt->option = enabled ? "1" : "0";
+}
+
void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
{
FIPS_GLOBAL *fgbl = OPENSSL_zalloc(sizeof(*fgbl));
if (fgbl == NULL)
return NULL;
- fgbl->fips_security_checks = 1;
- fgbl->fips_security_check_option = "1";
-
+ init_fips_option(&fgbl->fips_security_checks, 1);
+ init_fips_option(&fgbl->fips_tls1_prf_ems_check, 0); /* Disabled by default */
+ init_fips_option(&fgbl->fips_restricted_drgb_digests, 0);
return fgbl;
}
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_SECURITY_CHECKS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST, OSSL_PARAM_INTEGER, NULL, 0),
OSSL_PARAM_END
};
* NOTE: inside core_get_params() these will be loaded from config items
* stored inside prov->parameters (except for
* OSSL_PROV_PARAM_CORE_MODULE_FILENAME).
- * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS is not a self test parameter.
+ * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS and
+ * OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK are not self test parameters.
*/
- OSSL_PARAM core_params[8], *p = core_params;
+ OSSL_PARAM core_params[10], *p = core_params;
*p++ = OSSL_PARAM_construct_utf8_ptr(
OSSL_PROV_PARAM_CORE_MODULE_FILENAME,
OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
(char **)&fgbl->selftest_params.conditional_error_check,
sizeof(fgbl->selftest_params.conditional_error_check));
- *p++ = OSSL_PARAM_construct_utf8_ptr(
- OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
- (char **)&fgbl->fips_security_check_option,
- sizeof(fgbl->fips_security_check_option));
+
+/* FIPS features can be enabled or disabled independently */
+#define FIPS_FEATURE_OPTION(fgbl, pname, field) \
+ *p++ = OSSL_PARAM_construct_utf8_ptr( \
+ pname, (char **)&fgbl->field.option, \
+ sizeof(fgbl->field.option))
+
+ FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+ fips_security_checks);
+ FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK,
+ fips_tls1_prf_ems_check);
+ FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_DRBG_TRUNC_DIGEST,
+ fips_restricted_drgb_digests);
+#undef FIPS_FEATURE_OPTION
+
*p = OSSL_PARAM_construct_end();
if (!c_get_params(fgbl->handle, core_params)) {
p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
return 0;
- p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_SECURITY_CHECKS);
- if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_security_checks))
- return 0;
+
+#define FIPS_FEATURE_GET(fgbl, pname, field) \
+ p = OSSL_PARAM_locate(params, pname); \
+ if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->field.enabled)) \
+ return 0
+
+ FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_SECURITY_CHECKS,
+ fips_security_checks);
+ FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK,
+ fips_tls1_prf_ems_check);
+ FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST,
+ fips_restricted_drgb_digests);
+#undef FIPS_FEATURE_GET
return 1;
}
ALGC(PROV_NAMES_AES_256_CBC_HMAC_SHA256, ossl_aes256cbc_hmac_sha256_functions,
ossl_cipher_capable_aes_cbc_hmac_sha256),
#ifndef OPENSSL_NO_DES
- ALG(PROV_NAMES_DES_EDE3_ECB, ossl_tdes_ede3_ecb_functions),
- ALG(PROV_NAMES_DES_EDE3_CBC, ossl_tdes_ede3_cbc_functions),
+ UNAPPROVED_ALG(PROV_NAMES_DES_EDE3_ECB, ossl_tdes_ede3_ecb_functions),
+ UNAPPROVED_ALG(PROV_NAMES_DES_EDE3_CBC, ossl_tdes_ede3_cbc_functions),
#endif /* OPENSSL_NO_DES */
{ { NULL, NULL, NULL }, NULL }
};
#endif
{ PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_signature_functions },
#ifndef OPENSSL_NO_EC
- { PROV_NAMES_ED25519, FIPS_DEFAULT_PROPERTIES, ossl_ed25519_signature_functions },
- { PROV_NAMES_ED448, FIPS_DEFAULT_PROPERTIES, ossl_ed448_signature_functions },
+ { PROV_NAMES_ED25519, FIPS_UNAPPROVED_PROPERTIES,
+ ossl_ed25519_signature_functions },
+ { PROV_NAMES_ED448, FIPS_UNAPPROVED_PROPERTIES, ossl_ed448_signature_functions },
{ PROV_NAMES_ECDSA, FIPS_DEFAULT_PROPERTIES, ossl_ecdsa_signature_functions },
#endif
{ PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES,
PROV_DESCS_X25519 },
{ PROV_NAMES_X448, FIPS_DEFAULT_PROPERTIES, ossl_x448_keymgmt_functions,
PROV_DESCS_X448 },
- { PROV_NAMES_ED25519, FIPS_DEFAULT_PROPERTIES, ossl_ed25519_keymgmt_functions,
+ { PROV_NAMES_ED25519, FIPS_UNAPPROVED_PROPERTIES, ossl_ed25519_keymgmt_functions,
PROV_DESCS_ED25519 },
- { PROV_NAMES_ED448, FIPS_DEFAULT_PROPERTIES, ossl_ed448_keymgmt_functions,
+ { PROV_NAMES_ED448, FIPS_UNAPPROVED_PROPERTIES, ossl_ed448_keymgmt_functions,
PROV_DESCS_ED448 },
#endif
{ PROV_NAMES_TLS1_PRF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions,
return NULL;
}
-void *ossl_c_locale() {
- return (void *)loc;
-}
-
-static int fips_init_casecmp(void) {
-# ifdef OPENSSL_SYS_WINDOWS
- loc = _create_locale(LC_COLLATE, "C");
-# else
- loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
-# endif
- return (loc == (locale_t) 0) ? 0 : 1;
-}
-
-static void fips_deinit_casecmp(void) {
- freelocale(loc);
-}
-
static void fips_teardown(void *provctx)
{
OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
* We know that the library context is the same as for the outer provider,
* so no need to destroy it here.
*/
- fips_deinit_casecmp();
ossl_prov_ctx_free(provctx);
}
{ OSSL_FUNC_PROVIDER_GET_CAPABILITIES,
(void (*)(void))ossl_prov_get_capabilities },
{ OSSL_FUNC_PROVIDER_SELF_TEST, (void (*)(void))fips_self_test },
- { 0, NULL }
+ OSSL_DISPATCH_END
};
/* Functions we provide to ourself */
static const OSSL_DISPATCH intern_dispatch_table[] = {
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))fips_intern_teardown },
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
- { 0, NULL }
+ OSSL_DISPATCH_END
};
/*
memset(&selftest_params, 0, sizeof(selftest_params));
- if (!fips_init_casecmp())
- return 0;
if (!ossl_prov_seeding_from_dispatch(in))
- return 0;
+ goto err;
for (; in->function_id != 0; in++) {
/*
* We do not support the scenario of an application linked against
&& strcmp(fgbl->selftest_params.conditional_error_check, "0") == 0)
SELF_TEST_disable_conditional_error_state();
- /* Disable the security check if it's disabled in the fips config file. */
- if (fgbl->fips_security_check_option != NULL
- && strcmp(fgbl->fips_security_check_option, "0") == 0)
- fgbl->fips_security_checks = 0;
+ /* Enable or disable FIPS provider options */
+#define FIPS_SET_OPTION(fgbl, field) \
+ if (fgbl->field.option != NULL) { \
+ if (strcmp(fgbl->field.option, "1") == 0) \
+ fgbl->field.enabled = 1; \
+ else if (strcmp(fgbl->field.option, "0") == 0) \
+ fgbl->field.enabled = 0; \
+ else \
+ goto err; \
+ }
+
+ FIPS_SET_OPTION(fgbl, fips_security_checks);
+ FIPS_SET_OPTION(fgbl, fips_tls1_prf_ems_check);
+ FIPS_SET_OPTION(fgbl, fips_restricted_drgb_digests);
+#undef FIPS_SET_OPTION
ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
return ret;
}
-int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx)
-{
- FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
- OSSL_LIB_CTX_FIPS_PROV_INDEX);
+#define FIPS_FEATURE_CHECK(fname, field) \
+ int fname(OSSL_LIB_CTX *libctx) \
+ { \
+ FIPS_GLOBAL *fgbl = \
+ ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX); \
+ return fgbl->field.enabled; \
+ }
- return fgbl->fips_security_checks;
-}
+FIPS_FEATURE_CHECK(FIPS_security_check_enabled, fips_security_checks)
+FIPS_FEATURE_CHECK(FIPS_tls_prf_ems_check, fips_tls1_prf_ems_check)
+FIPS_FEATURE_CHECK(FIPS_restricted_drbg_digests_enabled,
+ fips_restricted_drgb_digests)
+#undef FIPS_FEATURE_CHECK
void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg)