From 0557d6c62b7d1f46f6f51e0dca87ad9409236164 Mon Sep 17 00:00:00 2001 From: slontis Date: Mon, 1 Jul 2024 11:11:16 +1000 Subject: [PATCH] Add FIPS indicator callback. Add a FIPS indicator callback that can be set via OSSL_INDICATOR_set_callback(). This callback is intended to be run whenever a non approved algorithm check has occurred and strict checking has been disabled.The callback may be used to log non approved algorithms. The callback is passed a type and description string as well as the cbarg specified in OSSL_INDICATOR_set_callback. The return value can be either 0 or 1. A value of 0 can be used for testing purposes to force an error to occur from the algorithm that called the callback. Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/24623) --- crypto/build.info | 2 +- crypto/context.c | 11 ++++ crypto/indicator_core.c | 55 ++++++++++++++++ crypto/provider_core.c | 9 +++ doc/build.info | 6 ++ doc/man3/OSSL_INDICATOR_set_callback.pod | 81 ++++++++++++++++++++++++ include/crypto/context.h | 2 + include/internal/cryptlib.h | 3 +- include/openssl/core_dispatch.h | 5 ++ include/openssl/indicator.h | 31 +++++++++ providers/fips/fipsprov.c | 22 ++++++- 11 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 crypto/indicator_core.c create mode 100644 doc/man3/OSSL_INDICATOR_set_callback.pod create mode 100644 include/openssl/indicator.h diff --git a/crypto/build.info b/crypto/build.info index 881007f8ac..2642d30754 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -91,7 +91,7 @@ DEFINE[../providers/libdefault.a]=$CPUIDDEF $CORE_COMMON=provider_core.c provider_predefined.c \ core_fetch.c core_algorithm.c core_namemap.c self_test_core.c -SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c +SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c indicator_core.c SOURCE[../providers/libfips.a]=$CORE_COMMON # Central utilities diff --git a/crypto/context.c b/crypto/context.c index 1059a43b2c..f3d9f384fc 100644 --- a/crypto/context.c +++ b/crypto/context.c @@ -40,6 +40,7 @@ struct ossl_lib_ctx_st { OSSL_METHOD_STORE *encoder_store; OSSL_METHOD_STORE *store_loader_store; void *self_test_cb; + void *indicator_cb; #endif #if defined(OPENSSL_THREADS) void *threads; @@ -177,6 +178,9 @@ static int context_init(OSSL_LIB_CTX *ctx) ctx->self_test_cb = ossl_self_test_set_callback_new(ctx); if (ctx->self_test_cb == NULL) goto err; + ctx->indicator_cb = ossl_indicator_set_callback_new(ctx); + if (ctx->indicator_cb == NULL) + goto err; #endif #ifdef FIPS_MODULE @@ -313,6 +317,11 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx) } #ifndef FIPS_MODULE + if (ctx->indicator_cb != NULL) { + ossl_indicator_set_callback_free(ctx->indicator_cb); + ctx->indicator_cb = NULL; + } + if (ctx->self_test_cb != NULL) { ossl_self_test_set_callback_free(ctx->self_test_cb); ctx->self_test_cb = NULL; @@ -604,6 +613,8 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index) return ctx->store_loader_store; case OSSL_LIB_CTX_SELF_TEST_CB_INDEX: return ctx->self_test_cb; + case OSSL_LIB_CTX_INDICATOR_CB_INDEX: + return ctx->indicator_cb; #endif #ifndef OPENSSL_NO_THREAD_POOL case OSSL_LIB_CTX_THREAD_INDEX: diff --git a/crypto/indicator_core.c b/crypto/indicator_core.c new file mode 100644 index 0000000000..4b3c122717 --- /dev/null +++ b/crypto/indicator_core.c @@ -0,0 +1,55 @@ +/* + * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include "crypto/context.h" + +typedef struct indicator_cb_st +{ + OSSL_INDICATOR_CALLBACK *cb; +} INDICATOR_CB; + +void *ossl_indicator_set_callback_new(OSSL_LIB_CTX *ctx) +{ + INDICATOR_CB *cb; + + cb = OPENSSL_zalloc(sizeof(*cb)); + return cb; +} + +void ossl_indicator_set_callback_free(void *cb) +{ + OPENSSL_free(cb); +} + +static INDICATOR_CB *get_indicator_callback(OSSL_LIB_CTX *libctx) +{ + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_INDICATOR_CB_INDEX); +} + +void OSSL_INDICATOR_set_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK *cb) +{ + INDICATOR_CB *icb = get_indicator_callback(libctx); + + if (icb != NULL) + icb->cb = cb; +} + +void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb) +{ + INDICATOR_CB *icb = get_indicator_callback(libctx); + + if (cb != NULL) + *cb = (icb != NULL ? icb->cb : NULL); +} diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 693e2913d5..266423dda9 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -32,6 +32,7 @@ #include "crypto/context.h" #ifndef FIPS_MODULE # include +# include #endif /* @@ -1934,6 +1935,7 @@ OSSL_FUNC_BIO_up_ref_fn ossl_core_bio_up_ref; OSSL_FUNC_BIO_free_fn ossl_core_bio_free; OSSL_FUNC_BIO_vprintf_fn ossl_core_bio_vprintf; OSSL_FUNC_BIO_vsnprintf_fn BIO_vsnprintf; +static OSSL_FUNC_indicator_cb_fn core_indicator_get_callback; static OSSL_FUNC_self_test_cb_fn core_self_test_get_callback; static OSSL_FUNC_get_entropy_fn rand_get_entropy; static OSSL_FUNC_get_user_entropy_fn rand_get_user_entropy; @@ -2097,6 +2099,12 @@ static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle) return ERR_pop_to_mark(); } +static void core_indicator_get_callback(OPENSSL_CORE_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb) +{ + OSSL_INDICATOR_get_callback((OSSL_LIB_CTX *)libctx, cb); +} + static void core_self_test_get_callback(OPENSSL_CORE_CTX *libctx, OSSL_CALLBACK **cb, void **cbarg) { @@ -2258,6 +2266,7 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))ossl_core_bio_vprintf }, { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf }, { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))core_self_test_get_callback }, + { OSSL_FUNC_INDICATOR_CB, (void (*)(void))core_indicator_get_callback }, { OSSL_FUNC_GET_ENTROPY, (void (*)(void))rand_get_entropy }, { OSSL_FUNC_GET_USER_ENTROPY, (void (*)(void))rand_get_user_entropy }, { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))rand_cleanup_entropy }, diff --git a/doc/build.info b/doc/build.info index b2689b7ace..5c24273b63 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1747,6 +1747,10 @@ DEPEND[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_pr GENERATE[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod DEPEND[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod GENERATE[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +DEPEND[html/man3/OSSL_INDICATOR_set_callback.html]=man3/OSSL_INDICATOR_set_callback.pod +GENERATE[html/man3/OSSL_INDICATOR_set_callback.html]=man3/OSSL_INDICATOR_set_callback.pod +DEPEND[man/man3/OSSL_INDICATOR_set_callback.3]=man3/OSSL_INDICATOR_set_callback.pod +GENERATE[man/man3/OSSL_INDICATOR_set_callback.3]=man3/OSSL_INDICATOR_set_callback.pod DEPEND[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod GENERATE[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod DEPEND[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod @@ -3424,6 +3428,7 @@ html/man3/OSSL_HTTP_parse_url.html \ html/man3/OSSL_HTTP_transfer.html \ html/man3/OSSL_IETF_ATTR_SYNTAX.html \ html/man3/OSSL_IETF_ATTR_SYNTAX_print.html \ +html/man3/OSSL_INDICATOR_set_callback.html \ html/man3/OSSL_ITEM.html \ html/man3/OSSL_LIB_CTX.html \ html/man3/OSSL_LIB_CTX_set_conf_diagnostics.html \ @@ -4083,6 +4088,7 @@ man/man3/OSSL_HTTP_parse_url.3 \ man/man3/OSSL_HTTP_transfer.3 \ man/man3/OSSL_IETF_ATTR_SYNTAX.3 \ man/man3/OSSL_IETF_ATTR_SYNTAX_print.3 \ +man/man3/OSSL_INDICATOR_set_callback.3 \ man/man3/OSSL_ITEM.3 \ man/man3/OSSL_LIB_CTX.3 \ man/man3/OSSL_LIB_CTX_set_conf_diagnostics.3 \ diff --git a/doc/man3/OSSL_INDICATOR_set_callback.pod b/doc/man3/OSSL_INDICATOR_set_callback.pod new file mode 100644 index 0000000000..34ead2bd3f --- /dev/null +++ b/doc/man3/OSSL_INDICATOR_set_callback.pod @@ -0,0 +1,81 @@ +=pod + +=head1 NAME + +OSSL_INDICATOR_set_callback, +OSSL_INDICATOR_get_callback - specify a callback for FIPS indicators + +=head1 SYNOPSIS + + #include + +typedef int (OSSL_INDICATOR_CALLBACK)(const char *type, const char *desc, + const OSSL_PARAM params[]); + + void OSSL_INDICATOR_set_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK *cb); + void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb); + +=head1 DESCRIPTION + +OSSL_INDICATOR_set_callback() sets a user callback I associated with a +I that will be called when a non approved FIPS operation is detected. + +The user's callback may be triggered multiple times during an algorithm operation +to indicate different approved mode checks have failed. + +Non approved operations may only occur if the user has deliberately chosen to do +so (either by setting a global FIPS configuration option or via an option in an +algorithm's operation context). + +The user's callback B I and I +contain the algorithm type and operation that is not approved. +I is not currently used. + +If the user callback returns 0, an error will occur in the caller. This can be +used for testing purposes. + +=head1 RETURN VALUES + +OSSL_INDICATOR_get_callback() returns the callback that has been set via +OSSL_INDICATOR_set_callback() for the given library context I, or NULL +if no callback is currently set. + +=head1 EXAMPLES + +A simple indicator callback to log non approved FIPS operations + + static int indicator_cb(const char *type, const char *desc, + const OSSL_PARAM params[]) + { + if (type != NULL && desc != NULL) + fprintf(stdout, "%s %s is not approved\n", type, desc); +end: + /* For Testing purposes you could return 0 here to cause an error */ + return 1; + } + + OSSL_INDICATOR_set_callback(libctx, indicator_cb); + + +=head1 SEE ALSO + +L, +L +L + +=head1 HISTORY + +The functions described here were added in OpenSSL 3.4. + +=head1 COPYRIGHT + +Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/include/crypto/context.h b/include/crypto/context.h index 7369a730fb..8831fcb2a5 100644 --- a/include/crypto/context.h +++ b/include/crypto/context.h @@ -20,6 +20,7 @@ void *ossl_bio_core_globals_new(OSSL_LIB_CTX *); void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *); void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *); void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *); +void *ossl_indicator_set_callback_new(OSSL_LIB_CTX *); void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *); int ossl_thread_register_fips(OSSL_LIB_CTX *); void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *); @@ -38,6 +39,7 @@ void ossl_prov_conf_ctx_free(void *); void ossl_bio_core_globals_free(void *); void ossl_child_prov_ctx_free(void *); void ossl_prov_drbg_nonce_ctx_free(void *); +void ossl_indicator_set_callback_free(void *cb); void ossl_self_test_set_callback_free(void *); void ossl_rand_crng_ctx_free(void *); void ossl_thread_event_ctx_free(void *); diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index 1635830500..32caabad7e 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -117,7 +117,8 @@ typedef struct ossl_ex_data_global_st { # define OSSL_LIB_CTX_THREAD_INDEX 19 # define OSSL_LIB_CTX_DECODER_CACHE_INDEX 20 # define OSSL_LIB_CTX_COMP_METHODS 21 -# define OSSL_LIB_CTX_MAX_INDEXES 21 +# define OSSL_LIB_CTX_INDICATOR_CB_INDEX 22 +# define OSSL_LIB_CTX_MAX_INDEXES 22 OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx); int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx); diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index a5bc2cf75d..fa4de4954c 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -13,6 +13,7 @@ # include # include +# include # ifdef __cplusplus extern "C" { @@ -182,6 +183,9 @@ OSSL_CORE_MAKE_FUNC(int, BIO_ctrl, (OSSL_CORE_BIO *bio, #define OSSL_FUNC_GET_USER_ENTROPY 98 #define OSSL_FUNC_GET_USER_NONCE 99 +#define OSSL_FUNC_INDICATOR_CB 95 +OSSL_CORE_MAKE_FUNC(void, indicator_cb, (OPENSSL_CORE_CTX *ctx, + OSSL_INDICATOR_CALLBACK **cb)) #define OSSL_FUNC_SELF_TEST_CB 100 OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg)) @@ -588,6 +592,7 @@ OSSL_CORE_MAKE_FUNC(void *, keymgmt_new, (void *provctx)) # define OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS 5 # define OSSL_FUNC_KEYMGMT_GEN 6 # define OSSL_FUNC_KEYMGMT_GEN_CLEANUP 7 + OSSL_CORE_MAKE_FUNC(void *, keymgmt_gen_init, (void *provctx, int selection, const OSSL_PARAM params[])) OSSL_CORE_MAKE_FUNC(int, keymgmt_gen_set_template, diff --git a/include/openssl/indicator.h b/include/openssl/indicator.h new file mode 100644 index 0000000000..3ea0122188 --- /dev/null +++ b/include/openssl/indicator.h @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OPENSSL_INDICATOR_H +# define OPENSSL_INDICATOR_H +# pragma once + +# ifdef __cplusplus +extern "C" { +# endif + +#include + +typedef int (OSSL_INDICATOR_CALLBACK)(const char *type, const char *desc, + const OSSL_PARAM params[]); + +void OSSL_INDICATOR_set_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK *cb); +void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb); + +# ifdef __cplusplus +} +# endif +#endif /* OPENSSL_INDICATOR_H */ diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 0174c6b33b..bae56a8bba 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,6 +14,7 @@ #include #include /* RAND_get0_public() */ #include +#include #include "internal/cryptlib.h" #include "prov/implementations.h" #include "prov/names.h" @@ -76,6 +77,7 @@ static OSSL_FUNC_CRYPTO_secure_clear_free_fn *c_CRYPTO_secure_clear_free; static OSSL_FUNC_CRYPTO_secure_allocated_fn *c_CRYPTO_secure_allocated; static OSSL_FUNC_BIO_vsnprintf_fn *c_BIO_vsnprintf; static OSSL_FUNC_self_test_cb_fn *c_stcbfn = NULL; +static OSSL_FUNC_indicator_cb_fn *c_indcbfn = NULL; static OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; typedef struct { @@ -689,6 +691,9 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, case OSSL_FUNC_SELF_TEST_CB: set_func(c_stcbfn, OSSL_FUNC_self_test_cb(in)); break; + case OSSL_FUNC_INDICATOR_CB: + set_func(c_indcbfn, OSSL_FUNC_indicator_cb(in)); + break; default: /* Just ignore anything we don't understand */ break; @@ -954,6 +959,7 @@ 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, @@ -971,3 +977,17 @@ void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb, *cbarg = NULL; } } + +void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb) +{ + assert(libctx != NULL); + + if (c_indcbfn != NULL && c_get_libctx != NULL) { + /* Get the parent libctx */ + c_indcbfn(c_get_libctx(FIPS_get_core_handle(libctx)), cb); + } else { + if (cb != NULL) + *cb = NULL; + } +}