From: Richard Levitte Date: Wed, 17 Feb 2021 18:01:19 +0000 (+0100) Subject: Also build gost-engine in library form X-Git-Tag: v3.0.0~36 X-Git-Url: http://www.wagner.pp.ru/gitweb/?p=openssl-gost%2Fengine.git;a=commitdiff_plain;h=d9a2b2973a1174baa4cecbffc6809764b63de2eb Also build gost-engine in library form In this form, the GOST engine isn't loadable through OpenSSL's dynamic ENGINE loader, but directly as its own function, ENGINE_load_gost(). After making that call, the engine functionality can be used as usual. This includes a public header file called gost-engine.h, which declares that functions. This also rearranges the code in gost_eng.c, as the binding functionality was spread around in the file. Now, it's all nicely tucked at the end. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c32b90f..ed2d44f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,7 @@ set_property(TARGET ${BINARY_TESTS_TARGETS} APPEND PROPERTY COMPILE_DEFINITIONS add_library(gost_core STATIC ${GOST_LIB_SOURCE_FILES}) set_target_properties(gost_core PROPERTIES POSITION_INDEPENDENT_CODE ON) +# 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 # module suffix should be @@ -282,6 +283,15 @@ set_target_properties(gost_engine PROPERTIES PREFIX "" OUTPUT_NAME "gost" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) target_link_libraries(gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) +# The GOST engine in library form +add_library(lib_gost_engine SHARED ${GOST_ENGINE_SOURCE_FILES}) +set_target_properties(lib_gost_engine PROPERTIES + COMPILE_DEFINITIONS "BUILDING_ENGINE_AS_LIBRARY" + PUBLIC_HEADER gost-engine.h + OUTPUT_NAME "gost") +target_link_libraries(lib_gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) + + set(GOST_SUM_SOURCE_FILES gostsum.c ) diff --git a/gost-engine.h b/gost-engine.h new file mode 100644 index 0000000..da292c3 --- /dev/null +++ b/gost-engine.h @@ -0,0 +1,14 @@ +/********************************************************************** + * gost-engine.h * + * GOST engine in library form * + * * + * Copyright (c) 2021 Richard Levitte * + * This file is distributed under the same license as OpenSSL * + * * + **********************************************************************/ +#ifndef GOST_ENGINE_H +# define GOST_ENGINE_H + +void ENGINE_load_gost(void); + +#endif diff --git a/gost_eng.c b/gost_eng.c index f930faa..d2371d2 100644 --- a/gost_eng.c +++ b/gost_eng.c @@ -16,6 +16,7 @@ #include #include "e_gost_err.h" #include "gost_lcl.h" +#include "gost-engine.h" #include "gost_grasshopper_cipher.h" @@ -190,6 +191,101 @@ static int known_cipher_nids[OSSL_NELEM(gost_cipher_array)]; /* `- 1' because of terminating zero element */ static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1]; +/* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */ +static int gost_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + int i; + + if (!digest) { + int *n = known_digest_nids; + + *nids = n; + for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) + *n++ = gost_digest_array[i]->nid; + return i; + } + + for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) + if (nid == gost_digest_array[i]->nid) { + *digest = GOST_init_digest(gost_digest_array[i]); + return 1; + } + *digest = NULL; + return 0; +} + +/* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */ +static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + int i; + + if (!cipher) { + int *n = known_cipher_nids; + + *nids = n; + for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) + *n++ = gost_cipher_array[i]->nid; + return i; + } + + for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) + if (nid == gost_cipher_array[i]->nid) { + *cipher = GOST_init_cipher(gost_cipher_array[i]); + return 1; + } + *cipher = NULL; + return 0; +} + +static int gost_meth_nids(const int **nids) +{ + struct gost_meth_minfo *info = gost_meth_array; + int *n = known_meths_nids; + + *nids = n; + for (; info->nid; info++) + *n++ = info->nid; + return OSSL_NELEM(known_meths_nids); +} + +/* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */ +static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid) +{ + struct gost_meth_minfo *info; + + if (!pmeth) + return gost_meth_nids(nids); + + for (info = gost_meth_array; info->nid; info++) + if (nid == info->nid) { + *pmeth = *info->pmeth; + return 1; + } + *pmeth = NULL; + return 0; +} + +/* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */ +static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, + const int **nids, int nid) +{ + struct gost_meth_minfo *info; + + if (!ameth) + return gost_meth_nids(nids); + + for (info = gost_meth_array; info->nid; info++) + if (nid == info->nid) { + *ameth = *info->ameth; + return 1; + } + *ameth = NULL; + return 0; +} + static int gost_engine_init(ENGINE* e) { return 1; } @@ -219,14 +315,16 @@ static int gost_engine_destroy(ENGINE* e) { return 1; } -static int bind_gost(ENGINE* e, const char* id) { +/* + * Following is the glue that populates the ENGINE structure and that + * binds it to OpenSSL libraries + */ + +static int populate_gost_engine(ENGINE* e) { int ret = 0; - if (id != NULL && strcmp(id, engine_gost_id) != 0) - return 0; - if (ameth_GostR3410_2001) { - printf("GOST engine already loaded\n"); + + if (e == NULL) goto end; - } if (!ENGINE_set_id(e, engine_gost_id)) { printf("ENGINE_set_id failed\n"); goto end; @@ -266,6 +364,12 @@ static int bind_gost(ENGINE* e, const char* id) { goto end; } + /* + * "register" in "register_ameth_gost" and "register_pmeth_gost" is + * not registering in an ENGINE sense, where things are hooked into + * OpenSSL's library. "register_ameth_gost" and "register_pmeth_gost" + * merely allocate and populate the method structures of this engine. + */ struct gost_meth_minfo *minfo = gost_meth_array; for (; minfo->nid; minfo++) { @@ -280,6 +384,14 @@ static int bind_gost(ENGINE* e, const char* id) { goto end; } + ret = 1; + end: + return ret; +} + +static int bind_gost_engine(ENGINE* e) { + int ret = 0; + if (!ENGINE_register_ciphers(e) || !ENGINE_register_digests(e) || !ENGINE_register_pkey_meths(e)) @@ -300,133 +412,57 @@ static int bind_gost(ENGINE* e, const char* id) { ERR_load_GOST_strings(); ret = 1; - end: + end: return ret; } -#ifndef OPENSSL_NO_DYNAMIC_ENGINE -IMPLEMENT_DYNAMIC_BIND_FN(bind_gost) - IMPLEMENT_DYNAMIC_CHECK_FN() -#endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */ - -/* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */ -static int gost_digests(ENGINE *e, const EVP_MD **digest, - const int **nids, int nid) +static int check_gost_engine(ENGINE* e, const char* id) { - int i; - - if (!digest) { - int *n = known_digest_nids; - - *nids = n; - for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) - *n++ = gost_digest_array[i]->nid; - return i; - } - - for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) - if (nid == gost_digest_array[i]->nid) { - *digest = GOST_init_digest(gost_digest_array[i]); - return 1; - } - *digest = NULL; - return 0; -} - -/* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */ -static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, - const int **nids, int nid) -{ - int i; - - if (!cipher) { - int *n = known_cipher_nids; - - *nids = n; - for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) - *n++ = gost_cipher_array[i]->nid; - return i; + if (id != NULL && strcmp(id, engine_gost_id) != 0) + return 0; + if (ameth_GostR3410_2001) { + printf("GOST engine already loaded\n"); + return 0; } - - for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) - if (nid == gost_cipher_array[i]->nid) { - *cipher = GOST_init_cipher(gost_cipher_array[i]); - return 1; - } - *cipher = NULL; - return 0; + return 1; } -static int gost_meth_nids(const int **nids) +static int make_gost_engine(ENGINE* e, const char* id) { - struct gost_meth_minfo *info = gost_meth_array; - int *n = known_meths_nids; - - *nids = n; - for (; info->nid; info++) - *n++ = info->nid; - return OSSL_NELEM(known_meths_nids); + return check_gost_engine(e, id) + && populate_gost_engine(e) + && bind_gost_engine(e); } -/* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */ -static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, - const int **nids, int nid) -{ - struct gost_meth_minfo *info; +#ifndef BUILDING_ENGINE_AS_LIBRARY - if (!pmeth) - return gost_meth_nids(nids); +/* + * When building gost-engine as a dynamically loadable module, these two + * lines do everything that's needed, and OpenSSL's libcrypto will be able + * to call its entry points, v_check and bind_engine. + */ - for (info = gost_meth_array; info->nid; info++) - if (nid == info->nid) { - *pmeth = *info->pmeth; - return 1; - } - *pmeth = NULL; - return 0; -} +IMPLEMENT_DYNAMIC_BIND_FN(make_gost_engine) +IMPLEMENT_DYNAMIC_CHECK_FN() -/* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */ -static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, - const int **nids, int nid) -{ - struct gost_meth_minfo *info; +#else - if (!ameth) - return gost_meth_nids(nids); - - for (info = gost_meth_array; info->nid; info++) - if (nid == info->nid) { - *ameth = *info->ameth; - return 1; - } - *ameth = NULL; - return 0; -} - -#ifdef OPENSSL_NO_DYNAMIC_ENGINE - -static ENGINE* engine_gost(void) { - ENGINE* ret = ENGINE_new(); - if (!ret) - return NULL; - if (!bind_gost(ret, engine_gost_id)) { - ENGINE_free(ret); - return NULL; - } - return ret; -} +/* + * When building gost-engine as a shared library, the application that uses + * it must manually call ENGINE_load_gost() for it to bind itself into the + * libcrypto libraries. + */ void ENGINE_load_gost(void) { ENGINE* toadd; - if (pmeth_GostR3410_2001) - return; - toadd = engine_gost(); - if (!toadd) - return; - ENGINE_add(toadd); + int ret = 0; + + if ((toadd = ENGINE_new()) != NULL + && (ret = make_gost_engine(toadd, engine_gost_id)) > 0) + ENGINE_add(toadd); ENGINE_free(toadd); - ERR_clear_error(); + if (ret > 0) + ERR_clear_error(); } #endif