diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cc84b8e..fd80d4bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ set(GOST_ERR_SOURCE_FILES e_gost_err.h ) -set(GOST_CORE_SOURCE_FILES +set(GOST_LEGACY_CORE_SOURCE_FILES gost_ameth.c gost_pmeth.c gost_ctl.c @@ -174,6 +174,13 @@ set(GOST_CORE_SOURCE_FILES gost_keyexpimp.c ) +set(GOST_NEW_CORE_DIGEST_SOURCE_FILES + gost_digest_3411_2012.c + gost_digest_3411_94.c + gost_digest_base.c + gost_digest.c +) + set(GOST_EC_SOURCE_FILES gost_ec_keyx.c gost_ec_sign.c @@ -193,7 +200,7 @@ set (GOST_OMAC_SOURCE_FILES ) set(GOST_LIB_SOURCE_FILES - ${GOST_CORE_SOURCE_FILES} + ${GOST_LEGACY_CORE_SOURCE_FILES} ${GOST_GRASSHOPPER_SOURCE_FILES} ${GOST_EC_SOURCE_FILES} ${GOST_OMAC_SOURCE_FILES} @@ -384,7 +391,7 @@ target_link_libraries(gost89 PRIVATE OpenSSL::Crypto) add_library(gosthash STATIC ${GOST_HASH_SOURCE_FILES}) set_target_properties(gosthash PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_link_libraries(gosthash PRIVATE OpenSSL::Crypto) +target_link_libraries(gosthash PRIVATE OpenSSL::Crypto gost89) add_library(gosthash2012 STATIC ${GOST_HASH_2012_SOURCE_FILES}) set_target_properties(gosthash2012 PROPERTIES POSITION_INDEPENDENT_CODE ON) @@ -398,6 +405,10 @@ add_library(gost_err STATIC ${GOST_ERR_SOURCE_FILES}) set_target_properties(gost_err PROPERTIES POSITION_INDEPENDENT_CODE ON) target_link_libraries(gost_err PRIVATE OpenSSL::Crypto) +add_library(gost_new_core_digest STATIC ${GOST_NEW_CORE_DIGEST_SOURCE_FILES}) +set_target_properties(gost_new_core_digest PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(gost_new_core_digest PRIVATE OpenSSL::Crypto gosthash gosthash2012) + # The GOST engine in module form add_library(gost_engine MODULE ${GOST_ENGINE_SOURCE_FILES}) # Set the suffix explicitly to adapt to OpenSSL's idea of what a @@ -427,7 +438,7 @@ set_target_properties(gost_prov PROPERTIES PREFIX "" OUTPUT_NAME "gostprov" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} COMPILE_DEFINITIONS "BUILDING_GOST_PROVIDER;OPENSSL_NO_DYNAMIC_ENGINE" ) -target_link_libraries(gost_prov PRIVATE gost_core libprov) +target_link_libraries(gost_prov PRIVATE gost_core gost_new_core_digest libprov) if (NOT MSVC) # The GOST provider in library form @@ -438,7 +449,7 @@ set_target_properties(lib_gost_prov PROPERTIES OUTPUT_NAME "gostprov" COMPILE_DEFINITIONS "BUILDING_GOST_PROVIDER;BUILDING_PROVIDER_AS_LIBRARY;OPENSSL_NO_DYNAMIC_ENGINE" ) -target_link_libraries(lib_gost_prov PRIVATE gost_core libprov) +target_link_libraries(lib_gost_prov PRIVATE gost_core gost_new_core_digest libprov) endif() set(GOST_SUM_SOURCE_FILES diff --git a/gost_digest.c b/gost_digest.c new file mode 100644 index 00000000..761cbd36 --- /dev/null +++ b/gost_digest.c @@ -0,0 +1,5 @@ +#include "gost_digest.h" + +void* GOST_digest_ctx_data(const GOST_digest_ctx* ctx) { + return ctx->algctx; +} diff --git a/gost_digest.h b/gost_digest.h new file mode 100644 index 00000000..25bba20a --- /dev/null +++ b/gost_digest.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +#include "utils_one_level_inheritance.h" + +struct gost_digest_st; +typedef struct gost_digest_st GOST_digest; + +struct gost_digest_ctx_st; +typedef struct gost_digest_ctx_st GOST_digest_ctx; + +typedef GOST_digest_ctx* (gost_digest_st_new_fn)(const GOST_digest *); +typedef void (gost_digest_st_free_fn)(GOST_digest_ctx *); + +typedef int (gost_digest_st_init_fn)(GOST_digest_ctx *ctx); +typedef int (gost_digest_st_update_fn)(GOST_digest_ctx *ctx, const void *data, size_t count); +typedef int (gost_digest_st_final_fn)(GOST_digest_ctx *ctx, unsigned char *md); +typedef int (gost_digest_st_copy_fn)(GOST_digest_ctx *to, const GOST_digest_ctx *from); +typedef int (gost_digest_st_cleanup_fn)(GOST_digest_ctx *ctx); +typedef int (gost_digest_st_ctrl_fn)(GOST_digest_ctx *ctx, int cmd, int p1, void *p2); + +typedef void (gost_digest_st_static_init_fn)(const GOST_digest *); +typedef void (gost_digest_st_static_deinit_fn)(const GOST_digest *); + +struct gost_digest_st { + DECL_BASE(const struct gost_digest_st); + + DECL_MEMBER(int, nid); + DECL_MEMBER(const char *, alias); + DECL_MEMBER(int, result_size); + DECL_MEMBER(int, input_blocksize); + DECL_MEMBER(int, flags); + DECL_MEMBER(const char *, micalg); + DECL_MEMBER(size_t, algctx_size); + + DECL_MEMBER(gost_digest_st_new_fn *, new); + DECL_MEMBER(gost_digest_st_free_fn *, free); + DECL_MEMBER(gost_digest_st_init_fn *, init); + DECL_MEMBER(gost_digest_st_update_fn *, update); + DECL_MEMBER(gost_digest_st_final_fn *, final); + DECL_MEMBER(gost_digest_st_copy_fn *, copy); + DECL_MEMBER(gost_digest_st_cleanup_fn *, cleanup); + DECL_MEMBER(gost_digest_st_ctrl_fn *, ctrl); + + DECL_MEMBER(gost_digest_st_static_init_fn *, static_init); + DECL_MEMBER(gost_digest_st_static_deinit_fn *, static_deinit); +}; + +struct gost_digest_ctx_st { + const GOST_digest* cls; + void* algctx; +}; + +void* GOST_digest_ctx_data(const GOST_digest_ctx* ctx); diff --git a/gost_digest_3411_2012.c b/gost_digest_3411_2012.c new file mode 100644 index 00000000..1e8af172 --- /dev/null +++ b/gost_digest_3411_2012.c @@ -0,0 +1,78 @@ +#include +#include +#include "gosthash2012.h" +#include "gost_digest_3411_2012.h" +#include "gost_digest_base.h" + +static int gost_digest_init(GOST_digest_ctx *ctx); +static int gost_digest_update(GOST_digest_ctx *ctx, const void *data, + size_t count); +static int gost_digest_final(GOST_digest_ctx *ctx, unsigned char *md); +static int gost_digest_copy(GOST_digest_ctx *to, const GOST_digest_ctx *from); +static int gost_digest_cleanup(GOST_digest_ctx *ctx); + +#define INIT_COMMON_MEMBERS() \ + INIT_MEMBER(base, &GostR3411_digest_base), \ + \ + INIT_MEMBER(input_blocksize, 64), \ + INIT_MEMBER(algctx_size, sizeof(gost2012_hash_ctx)), \ + \ + INIT_MEMBER(init, gost_digest_init), \ + INIT_MEMBER(update, gost_digest_update), \ + INIT_MEMBER(final, gost_digest_final), \ + INIT_MEMBER(copy, gost_digest_copy), \ + INIT_MEMBER(cleanup, gost_digest_cleanup) + +const GOST_digest GostR3411_2012_256_digest = { + INIT_MEMBER(nid, NID_id_GostR3411_2012_256), + INIT_MEMBER(alias, "streebog256"), + INIT_MEMBER(micalg, "gostr3411-2012-256"), + INIT_MEMBER(result_size, 32), + + INIT_COMMON_MEMBERS(), +}; + +const GOST_digest GostR3411_2012_512_digest = { + INIT_MEMBER(nid, NID_id_GostR3411_2012_512), + INIT_MEMBER(alias, "streebog512"), + INIT_MEMBER(micalg, "gostr3411-2012-512"), + INIT_MEMBER(result_size, 64), + + INIT_COMMON_MEMBERS(), +}; + +static inline gost2012_hash_ctx* impl_digest_ctx_data(const GOST_digest_ctx *ctx) { + return (gost2012_hash_ctx*)GOST_digest_ctx_data(ctx); +} + +static int gost_digest_init(GOST_digest_ctx *ctx) +{ + init_gost2012_hash_ctx(impl_digest_ctx_data(ctx), 8 * GET_MEMBER(ctx->cls, result_size)); + return 1; +} + +static int gost_digest_update(GOST_digest_ctx *ctx, const void *data, size_t count) +{ + gost2012_hash_block(impl_digest_ctx_data(ctx), data, count); + return 1; +} + +static int gost_digest_final(GOST_digest_ctx *ctx, unsigned char *md) +{ + gost2012_finish_hash(impl_digest_ctx_data(ctx), md); + return 1; +} + +static int gost_digest_copy(GOST_digest_ctx *to, const GOST_digest_ctx *from) +{ + memcpy(impl_digest_ctx_data(to), impl_digest_ctx_data(from), sizeof(gost2012_hash_ctx)); + + return 1; +} + +static int gost_digest_cleanup(GOST_digest_ctx *ctx) +{ + OPENSSL_cleanse(impl_digest_ctx_data(ctx), sizeof(gost2012_hash_ctx)); + + return 1; +} diff --git a/gost_digest_3411_2012.h b/gost_digest_3411_2012.h new file mode 100644 index 00000000..d1d39795 --- /dev/null +++ b/gost_digest_3411_2012.h @@ -0,0 +1,6 @@ +#pragma once + +#include "gost_digest.h" + +extern const GOST_digest GostR3411_2012_256_digest; +extern const GOST_digest GostR3411_2012_512_digest; diff --git a/gost_digest_3411_94.c b/gost_digest_3411_94.c new file mode 100644 index 00000000..dccf61d2 --- /dev/null +++ b/gost_digest_3411_94.c @@ -0,0 +1,76 @@ +#include + +#include + +#include "gost_digest_3411_94.h" +#include "gost_digest_base.h" +#include "gosthash.h" +#include "gost89.h" + +static int gost_digest_init(GOST_digest_ctx *ctx); +static int gost_digest_update(GOST_digest_ctx *ctx, const void *data, + size_t count); +static int gost_digest_final(GOST_digest_ctx *ctx, unsigned char *md); +static int gost_digest_copy(GOST_digest_ctx *to, const GOST_digest_ctx *from); +static int gost_digest_cleanup(GOST_digest_ctx *ctx); + +struct ossl_gost_digest_ctx { + gost_hash_ctx dctx; + gost_ctx cctx; +}; + +static inline struct ossl_gost_digest_ctx* impl_digest_ctx_data(const GOST_digest_ctx *ctx) { + return (struct ossl_gost_digest_ctx*)GOST_digest_ctx_data(ctx); +} + +const GOST_digest GostR3411_94_digest = { + INIT_MEMBER(nid, NID_id_GostR3411_94), + INIT_MEMBER(result_size, 32), + INIT_MEMBER(input_blocksize, 32), + INIT_MEMBER(algctx_size, sizeof(struct ossl_gost_digest_ctx)), + + INIT_MEMBER(base, &GostR3411_digest_base), + + INIT_MEMBER(init, gost_digest_init), + INIT_MEMBER(update, gost_digest_update), + INIT_MEMBER(final, gost_digest_final), + INIT_MEMBER(copy, gost_digest_copy), + INIT_MEMBER(cleanup, gost_digest_cleanup), +}; + +static int gost_digest_init(GOST_digest_ctx *ctx) +{ + struct ossl_gost_digest_ctx *c = impl_digest_ctx_data(ctx); + memset(&(c->dctx), 0, sizeof(gost_hash_ctx)); + gost_init(&(c->cctx), &GostR3411_94_CryptoProParamSet); + c->dctx.cipher_ctx = &(c->cctx); + return 1; +} + +static int gost_digest_update(GOST_digest_ctx *ctx, const void *data, size_t count) +{ + return hash_block(&(impl_digest_ctx_data(ctx)->dctx), data, count); +} + +static int gost_digest_final(GOST_digest_ctx *ctx, unsigned char *md) +{ + return finish_hash(&(impl_digest_ctx_data(ctx)->dctx), md); +} + +static int gost_digest_copy(GOST_digest_ctx *to, const GOST_digest_ctx *from) +{ + struct ossl_gost_digest_ctx *md_ctx = impl_digest_ctx_data(to); + if (impl_digest_ctx_data(to) && impl_digest_ctx_data(from)) { + memcpy(impl_digest_ctx_data(to), impl_digest_ctx_data(from), + sizeof(struct ossl_gost_digest_ctx)); + md_ctx->dctx.cipher_ctx = &(md_ctx->cctx); + } + return 1; +} + +static int gost_digest_cleanup(GOST_digest_ctx *ctx) +{ + if (impl_digest_ctx_data(ctx)) + OPENSSL_cleanse(impl_digest_ctx_data(ctx), sizeof(struct ossl_gost_digest_ctx)); + return 1; +} diff --git a/gost_digest_3411_94.h b/gost_digest_3411_94.h new file mode 100644 index 00000000..494c8e05 --- /dev/null +++ b/gost_digest_3411_94.h @@ -0,0 +1,5 @@ +#pragma once + +#include "gost_digest.h" + +extern const GOST_digest GostR3411_94_digest; diff --git a/gost_digest_base.c b/gost_digest_base.c new file mode 100644 index 00000000..fa4a8824 --- /dev/null +++ b/gost_digest_base.c @@ -0,0 +1,51 @@ +#include + +#include "gost_digest_base.h" + +static void gost_digest_static_init(const GOST_digest* d); +static void gost_digest_static_deinit(const GOST_digest* d); + +static GOST_digest_ctx* gost_digest_new(const GOST_digest* d); +static void gost_digest_free(GOST_digest_ctx* vctx); + +const GOST_digest GostR3411_digest_base = { + INIT_MEMBER(static_init, gost_digest_static_init), + INIT_MEMBER(static_deinit, gost_digest_static_deinit), + INIT_MEMBER(new, gost_digest_new), + INIT_MEMBER(free, gost_digest_free), +}; + +static GOST_digest_ctx* gost_digest_new(const GOST_digest *d) +{ + GOST_digest_ctx *ctx = (GOST_digest_ctx*)OPENSSL_zalloc(sizeof(GOST_digest_ctx)); + if (!ctx) + return ctx; + + ctx->cls = d; + ctx->algctx = OPENSSL_zalloc(GET_MEMBER(d, algctx_size)); + if (!ctx->algctx) { + OPENSSL_free(ctx); + ctx = NULL; + } + + return ctx; +} + +void gost_digest_free(GOST_digest_ctx *ctx) +{ + if (!ctx) + return; + + OPENSSL_free(ctx->algctx); + OPENSSL_free(ctx); +} + +static void gost_digest_static_init(const GOST_digest* d) { + if (GET_MEMBER(d, alias)) + EVP_add_digest_alias(OBJ_nid2sn(GET_MEMBER(d, nid)), GET_MEMBER(d, alias)); +} + +static void gost_digest_static_deinit(const GOST_digest* d) { + if (GET_MEMBER(d, alias)) + EVP_delete_digest_alias(GET_MEMBER(d, alias)); +} diff --git a/gost_digest_base.h b/gost_digest_base.h new file mode 100644 index 00000000..0e2dce2a --- /dev/null +++ b/gost_digest_base.h @@ -0,0 +1,5 @@ +#pragma once + +#include "gost_digest.h" + +extern const GOST_digest GostR3411_digest_base; diff --git a/gost_eng.c b/gost_eng.c index e1a036c0..e02995fb 100644 --- a/gost_eng.c +++ b/gost_eng.c @@ -73,10 +73,10 @@ static EVP_PKEY_ASN1_METHOD* ameth_GostR3410_2001 = NULL, * ameth_magma_mac_acpkm = NULL, * ameth_grasshopper_mac_acpkm = NULL; GOST_digest *gost_digest_array[] = { - &GostR3411_94_digest, + &GostR3411_94_digest_legacy, &Gost28147_89_MAC_digest, - &GostR3411_2012_256_digest, - &GostR3411_2012_512_digest, + &GostR3411_2012_256_digest_legacy, + &GostR3411_2012_512_digest_legacy, &Gost28147_89_mac_12_digest, &magma_mac_digest, &grasshopper_mac_digest, diff --git a/gost_lcl.h b/gost_lcl.h index e11f4437..faaf8f89 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -439,11 +439,11 @@ int internal_print_gost_ec_pub(BIO *out, const EC_KEY *ec, int indent, int pkey_ int internal_print_gost_ec_param(BIO *out, const EC_KEY *ec, int indent); /* ENGINE implementation data */ -extern GOST_digest GostR3411_94_digest; +extern GOST_digest GostR3411_94_digest_legacy; extern GOST_digest Gost28147_89_MAC_digest; extern GOST_digest Gost28147_89_mac_12_digest; -extern GOST_digest GostR3411_2012_256_digest; -extern GOST_digest GostR3411_2012_512_digest; +extern GOST_digest GostR3411_2012_256_digest_legacy; +extern GOST_digest GostR3411_2012_512_digest_legacy; extern GOST_digest magma_mac_digest; extern GOST_digest grasshopper_mac_digest; extern GOST_digest kuznyechik_ctracpkm_omac_digest; diff --git a/gost_md.c b/gost_md.c index b8824eb4..e6690133 100644 --- a/gost_md.c +++ b/gost_md.c @@ -20,7 +20,7 @@ static int gost_digest_final(EVP_MD_CTX *ctx, unsigned char *md); static int gost_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); static int gost_digest_cleanup(EVP_MD_CTX *ctx); -GOST_digest GostR3411_94_digest = { +GOST_digest GostR3411_94_digest_legacy = { .nid = NID_id_GostR3411_94, .result_size = 32, .input_blocksize = 32, diff --git a/gost_md2012.c b/gost_md2012.c index 3ea1e364..3d7a52a0 100644 --- a/gost_md2012.c +++ b/gost_md2012.c @@ -38,7 +38,7 @@ GOST_digest GostR3411_2012_template_digest = { .cleanup = gost_digest_cleanup, }; -GOST_digest GostR3411_2012_256_digest = { +GOST_digest GostR3411_2012_256_digest_legacy = { .nid = NID_id_GostR3411_2012_256, .alias = "streebog256", .template = &GostR3411_2012_template_digest, @@ -47,7 +47,7 @@ GOST_digest GostR3411_2012_256_digest = { .ctrl = gost_digest_ctrl_256, }; -GOST_digest GostR3411_2012_512_digest = { +GOST_digest GostR3411_2012_512_digest_legacy = { .nid = NID_id_GostR3411_2012_512, .alias = "streebog512", .template = &GostR3411_2012_template_digest, diff --git a/gost_prov.c b/gost_prov.c index 4ae77a18..3c86b197 100644 --- a/gost_prov.c +++ b/gost_prov.c @@ -11,6 +11,7 @@ #include #include "gost_prov.h" #include "gost_prov_tls.h" +#include "gost_prov_digest.h" #include "gost_lcl.h" #include "prov/err.h" /* libprov err functions */ @@ -183,6 +184,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *core, { if ((*vprovctx = provider_ctx_new(core, in)) == NULL) return 0; + + GOST_prov_init_digests(); + *out = provider_functions; return 1; } diff --git a/gost_prov.h b/gost_prov.h index b86c509a..38193176 100644 --- a/gost_prov.h +++ b/gost_prov.h @@ -78,11 +78,9 @@ int gost_get_max_signature_size(const GOST_KEY_DATA *); void GOST_prov_deinit_mac_digests(void); void GOST_prov_deinit_ciphers(void); -void GOST_prov_deinit_digests(void); extern const OSSL_ALGORITHM GOST_prov_macs[]; extern const OSSL_ALGORITHM GOST_prov_ciphers[]; -extern const OSSL_ALGORITHM GOST_prov_digests[]; extern const OSSL_ALGORITHM GOST_prov_keymgmt[]; extern const OSSL_ALGORITHM GOST_prov_encoder[]; extern const OSSL_ALGORITHM GOST_prov_signature[]; diff --git a/gost_prov_digest.c b/gost_prov_digest.c index a79c09fc..db40b772 100644 --- a/gost_prov_digest.c +++ b/gost_prov_digest.c @@ -11,7 +11,9 @@ #include #include #include "gost_prov.h" -#include "gost_lcl.h" +#include "gost_prov_digest.h" +#include "gost_digest_3411_94.h" +#include "gost_digest_3411_2012.h" /* * Forward declarations of all OSSL_DISPATCH functions, to make sure they @@ -25,54 +27,33 @@ static OSSL_FUNC_digest_final_fn digest_final; struct gost_prov_crypt_ctx_st { - /* Provider context */ PROV_CTX *provctx; - /* OSSL_PARAM descriptors */ - const OSSL_PARAM *known_params; - /* GOST_digest descriptor */ - GOST_digest *descriptor; + const GOST_digest *descriptor; - /* - * Since existing functionality is designed for ENGINEs, the functions - * in this file are accomodated and are simply wrappers that use a local - * EVP_MD and EVP_MD_CTX. - * Future development should take a more direct approach and have the - * appropriate digest functions and digest data directly in this context. - */ - - /* The EVP_MD created from |descriptor| */ - EVP_MD *digest; - /* The context for the EVP_MD functions */ - EVP_MD_CTX *dctx; + GOST_digest_ctx *dctx; }; typedef struct gost_prov_crypt_ctx_st GOST_CTX; static void digest_freectx(void *vgctx) { GOST_CTX *gctx = vgctx; + if (!gctx) + return; - /* - * We don't free gctx->digest here. - * That will be done by the provider teardown, via - * GOST_prov_deinit_digests() (defined at the bottom of this file). - */ - EVP_MD_CTX_free(gctx->dctx); + GET_MEMBER(gctx->descriptor, free)(gctx->dctx); OPENSSL_free(gctx); } -static GOST_CTX *digest_newctx(void *provctx, GOST_digest *descriptor, - const OSSL_PARAM *known_params) +static GOST_CTX *digest_newctx(void *provctx, const GOST_digest *descriptor) { GOST_CTX *gctx = NULL; if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) { gctx->provctx = provctx; - gctx->known_params = known_params; gctx->descriptor = descriptor; - gctx->digest = GOST_init_digest(descriptor); - gctx->dctx = EVP_MD_CTX_new(); - - if (gctx->digest == NULL || gctx->dctx == NULL) { + + gctx->dctx = GET_MEMBER(gctx->descriptor, new)(gctx->descriptor); + if (gctx->dctx == NULL) { digest_freectx(gctx); gctx = NULL; } @@ -83,24 +64,24 @@ static GOST_CTX *digest_newctx(void *provctx, GOST_digest *descriptor, static void *digest_dupctx(void *vsrc) { GOST_CTX *src = vsrc; - GOST_CTX *dst = - digest_newctx(src->provctx, src->descriptor, src->known_params); + GOST_CTX *dst = digest_newctx(src->provctx, src->descriptor); if (dst != NULL) - EVP_MD_CTX_copy(dst->dctx, src->dctx); + GET_MEMBER(src->descriptor, copy)(dst->dctx, src->dctx); + return dst; } -static int digest_get_params(EVP_MD *d, OSSL_PARAM params[]) +static int digest_get_params(const GOST_digest *descriptor, OSSL_PARAM params[]) { OSSL_PARAM *p; if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_MD_block_size(d))) + && !OSSL_PARAM_set_size_t(p, GET_MEMBER(descriptor, input_blocksize))) || ((p = OSSL_PARAM_locate(params, "size")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_MD_size(d))) + && !OSSL_PARAM_set_size_t(p, GET_MEMBER(descriptor, result_size))) || ((p = OSSL_PARAM_locate(params, "xof")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_MD_flags(d) & EVP_MD_FLAG_XOF))) + && !OSSL_PARAM_set_size_t(p, GET_MEMBER(descriptor, flags) & EVP_MD_FLAG_XOF))) return 0; return 1; } @@ -109,32 +90,34 @@ static int digest_init(void *vgctx, const OSSL_PARAM unused_params[]) { GOST_CTX *gctx = vgctx; - return EVP_DigestInit_ex(gctx->dctx, gctx->digest, gctx->provctx->e) > 0; + return GET_MEMBER(gctx->descriptor, init)(gctx->dctx) > 0; } static int digest_update(void *vgctx, const unsigned char *in, size_t inl) { GOST_CTX *gctx = vgctx; - return EVP_DigestUpdate(gctx->dctx, in, (int)inl) > 0; + return GET_MEMBER(gctx->descriptor, update)(gctx->dctx, in, inl) > 0; } static int digest_final(void *vgctx, unsigned char *out, size_t *outl, size_t outsize) { GOST_CTX *gctx = vgctx; - unsigned int int_outl = outl != NULL ? *outl : 0; - int res = EVP_DigestFinal(gctx->dctx, out, &int_outl); + + if (outsize < GET_MEMBER(gctx->descriptor, result_size)) + return 0; + + int res = GET_MEMBER(gctx->descriptor, final)(gctx->dctx, out); + + GET_MEMBER(gctx->descriptor, cleanup)(gctx->dctx); if (res > 0 && outl != NULL) - *outl = (size_t)int_outl; + *outl = GET_MEMBER(gctx->descriptor, result_size); + return res > 0; } -static const OSSL_PARAM *known_GostR3411_94_digest_params; -static const OSSL_PARAM *known_GostR3411_2012_256_digest_params; -static const OSSL_PARAM *known_GostR3411_2012_512_digest_params; - /* * These are named like the EVP_MD templates in gost_md.c etc, with the * added suffix "_functions". Hopefully, that makes it easy to find the @@ -145,12 +128,12 @@ typedef void (*fptr_t)(void); static OSSL_FUNC_digest_get_params_fn name##_get_params; \ static int name##_get_params(OSSL_PARAM *params) \ { \ - return digest_get_params(GOST_init_digest(&name), params); \ + return digest_get_params(&name, params); \ } \ static OSSL_FUNC_digest_newctx_fn name##_newctx; \ static void *name##_newctx(void *provctx) \ { \ - return digest_newctx(provctx, &name, known_##name##_params); \ + return digest_newctx(provctx, &name); \ } \ static const OSSL_DISPATCH name##_functions[] = { \ { OSSL_FUNC_DIGEST_GET_PARAMS, (fptr_t)name##_get_params }, \ @@ -186,15 +169,22 @@ const OSSL_ALGORITHM GOST_prov_digests[] = { { NULL , NULL, NULL } }; -void GOST_prov_deinit_digests(void) { - static GOST_digest *list[] = { - &GostR3411_94_digest, - &GostR3411_2012_256_digest, - &GostR3411_2012_512_digest, - }; +static const GOST_digest *digests[] = { + &GostR3411_94_digest, + &GostR3411_2012_256_digest, + &GostR3411_2012_512_digest, +}; + +#define arraysize(l) (sizeof(l) / sizeof(l[0])) + +void GOST_prov_init_digests(void) { size_t i; -#define elems(l) (sizeof(l) / sizeof(l[0])) + for (i = 0; i < arraysize(digests); i++) + GET_MEMBER(digests[i], static_init)(digests[i]); +} - for (i = 0; i < elems(list); i++) - GOST_deinit_digest(list[i]); +void GOST_prov_deinit_digests(void) { + size_t i; + for (i = 0; i < arraysize(digests); i++) + GET_MEMBER(digests[i], static_deinit)(digests[i]); } diff --git a/gost_prov_digest.h b/gost_prov_digest.h new file mode 100644 index 00000000..e733f947 --- /dev/null +++ b/gost_prov_digest.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +void GOST_prov_init_digests(void); +void GOST_prov_deinit_digests(void); + +extern const OSSL_ALGORITHM GOST_prov_digests[]; diff --git a/test_digest.c b/test_digest.c index 38cc2ebd..e86156ab 100644 --- a/test_digest.c +++ b/test_digest.c @@ -535,6 +535,34 @@ static const struct hash_testvec testvecs[] = { { 0 } }; +int engine_is_available(const char *name); + +int warn_md_impl_is_expected(EVP_MD* md) { + if (OSSL_PROVIDER_available(NULL, "gostprov") && !EVP_MD_get0_provider(md)) { + printf(cRED "Non-provided md during provider test" cNORM "\n"); + return 1; + } + if (engine_is_available("gost") && EVP_MD_get0_provider(md)) { + printf(cRED "Provided md during engine test" cNORM "\n"); + return 1; + } + + return 0; +} + +int warn_mac_impl_is_expected(EVP_MAC* md) { + if (OSSL_PROVIDER_available(NULL, "gostprov") && !EVP_MAC_get0_provider(md)) { + printf(cRED "Non-provided mac during provider test" cNORM "\n"); + return 1; + } + if (engine_is_available("gost") && EVP_MAC_get0_provider(md)) { + printf(cRED "Provided mac during engine test" cNORM "\n"); + return 1; + } + + return 0; +} + static void hexdump(const void *ptr, size_t len) { const unsigned char *p = ptr; @@ -798,13 +826,16 @@ static int do_test(const struct hash_testvec *tv) EVP_MAC *mac = NULL; ERR_set_mark(); - T((md = (EVP_MD *)EVP_get_digestbyname(tv->algname)) - || (md = EVP_MD_fetch(NULL, tv->algname, NULL)) - || (mac = EVP_MAC_fetch(NULL, tv->algname, NULL))); + T((md = EVP_MD_fetch(NULL, tv->algname, NULL)) + || (mac = EVP_MAC_fetch(NULL, tv->algname, NULL)) + || (md = (EVP_MD *)EVP_get_digestbyname(tv->algname))); ERR_pop_to_mark(); printf(cBLUE "Test %s: %s: " cNORM, tv->algname, tv->name); + ret |= md && warn_md_impl_is_expected(md); + ret |= mac && warn_mac_impl_is_expected(mac); + /* Test alignment problems. */ int shifts = 32; int i; @@ -858,8 +889,13 @@ static int do_synthetic_once(const struct hash_testvec *tv, unsigned int shifts) ibuf[shifts + len] = len & 0xff; EVP_MD *dgst; - T((dgst = (EVP_MD *)EVP_get_digestbyname(tv->algname)) - || (dgst = EVP_MD_fetch(NULL, tv->algname, NULL))); + T((dgst = EVP_MD_fetch(NULL, tv->algname, NULL)) + || (dgst = (EVP_MD *)EVP_get_digestbyname(tv->algname))); + if (dgst && warn_md_impl_is_expected(dgst)) { + EVP_MD_free(dgst); + return 1; + } + OPENSSL_assert(EVP_MD_is_a(dgst, tv->algname)); EVP_MD_CTX *ctx, *ctx2; T(ctx = EVP_MD_CTX_new()); diff --git a/utils_one_level_inheritance.h b/utils_one_level_inheritance.h new file mode 100644 index 00000000..a8be4708 --- /dev/null +++ b/utils_one_level_inheritance.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#define MEMBER_SUFFIX _private +#define MEMBER_SUFFIX_ISSET _private_isset + +#define DETAILS_BASE_NAME base + +#define DETAILS_MAKE_NAME_IMPL(prefix, suffix) prefix##suffix +#define DETAILS_MAKE_NAME(prefix, suffix) DETAILS_MAKE_NAME_IMPL(prefix, suffix) + +#define DETAILS_MEMBER_NAME(name) DETAILS_MAKE_NAME(name, MEMBER_SUFFIX) +#define DETAILS_MEMBER_NAME_ISSET(name) DETAILS_MAKE_NAME(name, MEMBER_SUFFIX_ISSET) + +#define DETAILS_GET_BASE_MEMBER(object, name) ( \ + ((object)->DETAILS_MEMBER_NAME(DETAILS_BASE_NAME)) ? \ + ((object)->DETAILS_MEMBER_NAME(DETAILS_BASE_NAME)->DETAILS_MEMBER_NAME(name)) : \ + 0 \ +) + +#define DETAILS_GET_MEMBER(object, name) ( \ + ((object)->DETAILS_MEMBER_NAME_ISSET(name)) ? \ + ((object)->DETAILS_MEMBER_NAME(name)) : \ + DETAILS_GET_BASE_MEMBER(object, name) \ +) + +#define DECL_MEMBER(type, name) \ + type DETAILS_MEMBER_NAME(name); \ + bool DETAILS_MEMBER_NAME_ISSET(name) + +#define DECL_BASE(type) DECL_MEMBER(type*, DETAILS_BASE_NAME) + +#define INIT_MEMBER(name, val) \ + .DETAILS_MEMBER_NAME(name) = (val), \ + .DETAILS_MEMBER_NAME_ISSET(name) = true + +#define GET_MEMBER(object, name) DETAILS_GET_MEMBER(object, name)