From 265d89dcbce7fce4fa2b560b70597132fd8eb3b2 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sat, 13 Feb 2021 14:50:49 +0100 Subject: [PATCH] Making a gost provider - Add the provider foundation This adds the source to get a minimal provider that provides... nothing. --- .cirrus.yml | 2 + .github/workflows/ci.yml | 16 +++ .github/workflows/codeql-analysis.yml | 2 + .gitmodules | 3 + CMakeLists.txt | 32 +++++- e_gost_err.c | 2 + gost_lcl.h | 1 + gost_prov.c | 144 ++++++++++++++++++++++++++ gost_prov.h | 27 +++++ libprov | 1 + 10 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 100644 gost_prov.c create mode 100644 gost_prov.h create mode 160000 libprov diff --git a/.cirrus.yml b/.cirrus.yml index 7a0c3c9..d205855 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -8,6 +8,8 @@ FreeBSD_task: install_script: - pkg install -y git cmake p5-App-cpanminus gdb pkgconf - sudo cpanm --notest Test2::V0 + update_git_script: + - git submodule update --recursive --init script: - git clone --depth 1 -b ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git - cd openssl diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14718dc..8baf3ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -19,6 +21,8 @@ jobs: CC: clang steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -28,6 +32,8 @@ jobs: USE_RPATH: steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -37,6 +43,8 @@ jobs: OPENSSL_BRANCH: master steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -47,6 +55,8 @@ jobs: USE_RPATH: steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -57,6 +67,8 @@ jobs: ASAN: -DASAN=1 steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -68,6 +80,8 @@ jobs: USE_RPATH: steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh @@ -80,6 +94,8 @@ jobs: APT_INSTALL: gcc-multilib steps: - uses: actions/checkout@v2 + with: + submodules: true - run: .github/before_script.sh - run: .github/script.sh diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ec6665d..194a08d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,6 +27,8 @@ jobs: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 + # gost-engine has submodules + submodules: true # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f40e730 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libprov"] + path = libprov + url = https://github.com/provider-corner/libprov.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ff1a71d..b6476e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,10 @@ set(GOST_ENGINE_SOURCE_FILES gost_eng.c ) +set(GOST_PROV_SOURCE_FILES + gost_prov.c + ) + set(TEST_ENVIRONMENT CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} PERL5LIB=${CMAKE_CURRENT_SOURCE_DIR}/test @@ -205,6 +209,7 @@ set(TEST_ENVIRONMENT OPENSSL_CRYPTO_LIBRARY=${OPENSSL_CRYPTO_LIBRARY} OPENSSL_CONF=${CMAKE_CURRENT_SOURCE_DIR}/test/engine.cnf ) + add_executable(test_digest test_digest.c) target_link_libraries(test_digest OpenSSL::Crypto) add_test(NAME digest COMMAND test_digest) @@ -307,8 +312,31 @@ 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 PRIVATE gost_core) - +target_link_libraries(lib_gost_engine PRIVATE gost_core gost_err) + + +# The GOST provider uses this +add_subdirectory(libprov) + +# The GOST provider in module form +add_library(gost_prov MODULE + ${GOST_PROV_SOURCE_FILES} ${GOST_ENGINE_SOURCE_FILES} + ) +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) + +# The GOST provider in library form +add_library(lib_gost_prov SHARED + ${GOST_PROV_SOURCE_FILES} ${GOST_ENGINE_SOURCE_FILES} + ) +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) set(GOST_SUM_SOURCE_FILES gostsum.c diff --git a/e_gost_err.c b/e_gost_err.c index c71272e..51599ca 100644 --- a/e_gost_err.c +++ b/e_gost_err.c @@ -176,6 +176,7 @@ static ERR_STRING_DATA GOST_str_reasons[] = { #endif +#ifndef GOST_PROV static int lib_code = 0; static int error_loaded = 0; @@ -220,3 +221,4 @@ void ERR_GOST_error(int function, int reason, char *file, int line) ERR_set_debug(file, line, NULL); #endif } +#endif diff --git a/gost_lcl.h b/gost_lcl.h index c518ed0..4801e17 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -10,6 +10,7 @@ * OpenSSL 0.9.9 libraries required to compile and use * * this code * **********************************************************************/ +# include # include # include # include diff --git a/gost_prov.c b/gost_prov.c new file mode 100644 index 0000000..fe65c4d --- /dev/null +++ b/gost_prov.c @@ -0,0 +1,144 @@ +/********************************************************************** + * gost_prov.c - The provider itself * + * * + * Copyright (c) 2021 Richard Levitte * + * This file is distributed under the same license as OpenSSL * + * * + * Requires OpenSSL 3.0 for compilation * + **********************************************************************/ + +#include +#include "gost_prov.h" +#include "gost_lcl.h" +#include "prov/err.h" /* libprov err functions */ + +/********************************************************************* + * + * Errors + * + *****/ + +/* + * Ugly hack, to get the errors generated by mkerr.pl. This should ideally + * be replaced with a local OSSL_ITEM list of < number, string > pairs as + * reason strings, but for now, we will simply use GOST_str_reasons. + * Fortunately, the ERR_STRING_DATA structure is compatible with OSSL_ITEM, + * so we can return it directly. + */ +static struct proverr_functions_st *err_handle; +#define GOST_PROV +#include "e_gost_err.c" +void ERR_GOST_error(int function, int reason, char *file, int line) +{ + proverr_new_error(err_handle); + proverr_set_error_debug(err_handle, file, line, NULL); + proverr_set_error(err_handle, reason, NULL); +} + +/********************************************************************* + * + * Provider context + * + *****/ + +static void provider_ctx_free(PROV_CTX *ctx) +{ + if (ctx != NULL) { + ENGINE_free(ctx->e); + proverr_free_handle(ctx->proverr_handle); + OSSL_LIB_CTX_free(ctx->libctx); + } + free(ctx); +} + +extern int populate_gost_engine(ENGINE *e); +static PROV_CTX *provider_ctx_new(const OSSL_CORE_HANDLE *core, + const OSSL_DISPATCH *in) +{ + PROV_CTX *ctx; + + if ((ctx = malloc(sizeof(*ctx))) != NULL + && (ctx->proverr_handle = proverr_new_handle(core, in)) != NULL + && (ctx->libctx = OSSL_LIB_CTX_new()) != NULL + && (ctx->e = ENGINE_new()) != NULL + && populate_gost_engine(ctx->e)) { + ctx->core_handle = core; + + /* Ugly hack */ + err_handle = ctx->proverr_handle; + } else { + provider_ctx_free(ctx); + ctx = NULL; + } + return ctx; +} + +/********************************************************************* + * + * Setup + * + *****/ + +typedef void (*fptr_t)(void); + +/* The function that returns the appropriate algorithm table per operation */ +static const OSSL_ALGORITHM *gost_operation(void *vprovctx, + int operation_id, + const int *no_cache) +{ + return NULL; +} + +static int gost_get_params(void *provctx, OSSL_PARAM *params) +{ + return 1; +} + +static const OSSL_ITEM *gost_get_reason_strings(void *provctx) +{ +#if 0 + return reason_strings; +#endif + return (OSSL_ITEM *)GOST_str_reasons; +} + +/* The function that tears down this provider */ +static void gost_teardown(void *vprovctx) +{ + provider_ctx_free(vprovctx); +} + +/* The base dispatch table */ +static const OSSL_DISPATCH provider_functions[] = { + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (fptr_t)gost_operation }, + { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (fptr_t)gost_get_reason_strings }, + { OSSL_FUNC_PROVIDER_GET_PARAMS, (fptr_t)gost_get_params }, + { OSSL_FUNC_PROVIDER_TEARDOWN, (fptr_t)gost_teardown }, + { 0, NULL } +}; + +struct prov_ctx_st { + void *core_handle; + struct proverr_functions_st *err_handle; +}; + +#ifdef BUILDING_PROVIDER_AS_LIBRARY +/* + * This allows the provider to be built in library form. In this case, the + * application must add it explicitly like this: + * + * OSSL_PROVIDER_add_builtin(NULL, "gost", GOST_provider_init); + */ +# define OSSL_provider_init GOST_provider_init +#endif + +int OSSL_provider_init(const OSSL_CORE_HANDLE *core, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, + void **vprovctx) +{ + if ((*vprovctx = provider_ctx_new(core, in)) == NULL) + return 0; + *out = provider_functions; + return 1; +} diff --git a/gost_prov.h b/gost_prov.h new file mode 100644 index 0000000..c7f6e66 --- /dev/null +++ b/gost_prov.h @@ -0,0 +1,27 @@ +/********************************************************************** + * gost_prov.h - The provider itself * + * * + * Copyright (c) 2021 Richard Levitte * + * This file is distributed under the same license as OpenSSL * + * * + * Requires OpenSSL 3.0 for compilation * + **********************************************************************/ + +#include +#include + +struct provider_ctx_st { + OSSL_LIB_CTX *libctx; + const OSSL_CORE_HANDLE *core_handle; + struct proverr_functions_st *proverr_handle; + + /* + * "internal" GOST engine, which is the implementation that all the + * provider functions will use to access the crypto functionality. + * This is pure hackery, but allows us to quickly wrap all the ENGINE + * function with provider wrappers. There is no other supported way + * to do this. + */ + ENGINE *e; +}; +typedef struct provider_ctx_st PROV_CTX; diff --git a/libprov b/libprov new file mode 160000 index 0000000..0f87843 --- /dev/null +++ b/libprov @@ -0,0 +1 @@ +Subproject commit 0f87843c0b85f325bdac7e0341946fc97d5d9d2d -- 2.39.2