diff --git a/.github/before_script.sh b/.github/before_script.sh index d77ba17f6..161b209b7 100755 --- a/.github/before_script.sh +++ b/.github/before_script.sh @@ -14,6 +14,8 @@ fi git clone --depth 1 -b $OPENSSL_BRANCH https://github.com/openssl/openssl.git if [ "${PATCH_OPENSSL}" == "1" ]; then git apply patches/openssl-tls1.3.patch + git apply patches/openssl-asn1_item_verify_ctx.patch + git apply patches/openssl-x509_sig_info_init.patch fi cd openssl git describe --always --long diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index f9de2657c..136ae0218 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -24,6 +24,8 @@ jobs: - name: Apply patches run: | git apply patches/openssl-tls1.3.patch + git apply patches/openssl-asn1_item_verify_ctx.patch + git apply patches/openssl-x509_sig_info_init.patch - uses: ilammy/msvc-dev-cmd@v1 - name: Build OpenSSL if: steps.cache.outputs.cache-hit != 'true' diff --git a/CMakeLists.txt b/CMakeLists.txt index e6903578d..b97e464e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,7 @@ set(GOST_CORE_SOURCE_FILES gost_keyexpimp.c gost_digest.c gost_digest_ctx.c + gost_cipher.c ) set(GOST_EC_SOURCE_FILES @@ -211,6 +212,8 @@ set(GOST_ENGINE_SOURCE_FILES gost_eng.c gost_eng_digest.c gost_eng_digest_define.c + gost_eng_cipher.c + gost_cipher_ctx_evp.c ) set(GOST_PROV_SOURCE_FILES @@ -226,6 +229,7 @@ set(GOST_PROV_SOURCE_FILES gost_prov_keyexch.c gost_prov_tls.c gost_prov_tls.h + gost_cipher_ctx.c ) set(TEST_ENVIRONMENT_COMMON @@ -270,13 +274,13 @@ set_tests_properties(ciphers-with-provider # test_curves is an internals testing program, it doesn't need a test env add_executable(test_ecdhe test_ecdhe.c) -target_link_libraries(test_ecdhe gost_core gost_err) +target_link_libraries(test_ecdhe gost_core gost_core_additional_for_unittests gost_err) add_test(NAME ecdhe COMMAND test_ecdhe) set_tests_properties(ecdhe PROPERTIES ENVIRONMENT "${TEST_ENVIRONMENT_ENGINE}") add_executable(test_curves test_curves.c) -target_link_libraries(test_curves gost_core gost_err) +target_link_libraries(test_curves gost_core gost_core_additional_for_unittests gost_err) add_test(NAME curves COMMAND test_curves) add_executable(test_params test_params.c) @@ -370,7 +374,7 @@ endif() if(NOT MSVC) add_executable(sign benchmark/sign.c) - target_link_libraries(sign gost_core gost_err ${CLOCK_GETTIME_LIB}) + target_link_libraries(sign gost_core gost_core_additional_for_unittests gost_err ${CLOCK_GETTIME_LIB}) endif() # All that may need to load just built engine will have path to it defined. @@ -411,6 +415,9 @@ add_library(gost_core STATIC ${GOST_LIB_SOURCE_FILES}) set_target_properties(gost_core PROPERTIES POSITION_INDEPENDENT_CODE ON) target_link_libraries(gost_core PRIVATE OpenSSL::Crypto gost89 gosthash gosthash2012 gosttls12additional) +add_library(gost_core_additional_for_unittests STATIC gost_cipher_ctx.c) +set_target_properties(gost_core_additional_for_unittests PROPERTIES POSITION_INDEPENDENT_CODE ON) + 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) @@ -438,7 +445,7 @@ add_subdirectory(libprov) # The GOST provider in module form add_library(gost_prov MODULE - ${GOST_PROV_SOURCE_FILES} ${GOST_ENGINE_SOURCE_FILES} + ${GOST_PROV_SOURCE_FILES} ) set_target_properties(gost_prov PROPERTIES PREFIX "" OUTPUT_NAME "gostprov" SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} @@ -449,7 +456,7 @@ target_link_libraries(gost_prov PRIVATE gost_core libprov) if (NOT MSVC) # The GOST provider in library form add_library(lib_gost_prov SHARED - ${GOST_PROV_SOURCE_FILES} ${GOST_ENGINE_SOURCE_FILES} + ${GOST_PROV_SOURCE_FILES} ) set_target_properties(lib_gost_prov PROPERTIES OUTPUT_NAME "gostprov" diff --git a/gost_cipher.c b/gost_cipher.c new file mode 100644 index 000000000..97db3863e --- /dev/null +++ b/gost_cipher.c @@ -0,0 +1,117 @@ +#include "gost_cipher_details.h" +#include "gost_cipher_ctx.h" + +#define TPL_VAL(st, field) (((st) != NULL && (st)->template != NULL) \ + ? (st)->template->field : 0) + +int GOST_cipher_type(const GOST_cipher *c) +{ + return c != NULL ? c->nid : NID_undef; +} + +int GOST_cipher_nid(const GOST_cipher *c) +{ + return GOST_cipher_type(c); +} + +int GOST_cipher_flags(const GOST_cipher *c) +{ + return c != NULL ? (c->flags | TPL_VAL(c, flags)) : 0; +} + +int GOST_cipher_key_length(const GOST_cipher *c) +{ + if (c == NULL) + return 0; + + return c->key_len != 0 ? c->key_len : TPL_VAL(c, key_len); +} + +int GOST_cipher_iv_length(const GOST_cipher *c) +{ + if (c == NULL) + return 0; + + return c->iv_len != 0 ? c->iv_len : TPL_VAL(c, iv_len); +} + +int GOST_cipher_block_size(const GOST_cipher *c) +{ + if (c == NULL) + return 0; + + return c->block_size != 0 ? c->block_size : TPL_VAL(c, block_size); +} + +int GOST_cipher_mode(const GOST_cipher *c) +{ + return c != NULL ? (c->flags & EVP_CIPH_MODE) : 0; +} + +int GOST_cipher_ctx_size(const GOST_cipher *c) +{ + if (c == NULL) + return 0; + + return c->ctx_size != 0 ? c->ctx_size : TPL_VAL(c, ctx_size); +} + +int (*GOST_cipher_init_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc) +{ + if (c == NULL) + return NULL; + + return c->init != NULL ? c->init : TPL_VAL(c, init); +} + +int (*GOST_cipher_set_asn1_parameters_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx, + ASN1_TYPE *params) +{ + if (c == NULL) + return NULL; + + return c->set_asn1_parameters != NULL + ? c->set_asn1_parameters : TPL_VAL(c, set_asn1_parameters); +} + +int (*GOST_cipher_get_asn1_parameters_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx, + ASN1_TYPE *params) +{ + if (c == NULL) + return NULL; + + return c->get_asn1_parameters != NULL + ? c->get_asn1_parameters : TPL_VAL(c, get_asn1_parameters); +} + +int (*GOST_cipher_do_cipher_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl) +{ + if (c == NULL) + return NULL; + + return c->do_cipher != NULL ? c->do_cipher : TPL_VAL(c, do_cipher); +} + +int (*GOST_cipher_cleanup_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx) +{ + if (c == NULL) + return NULL; + + return c->cleanup != NULL ? c->cleanup : TPL_VAL(c, cleanup); +} + +int (*GOST_cipher_ctrl_fn(const GOST_cipher *c))(GOST_cipher_ctx *ctx, + int type, int arg, + void *ptr) +{ + if (c == NULL) + return NULL; + + return c->ctrl != NULL ? c->ctrl : TPL_VAL(c, ctrl); +} diff --git a/gost_cipher.h b/gost_cipher.h new file mode 100644 index 000000000..090c2b27e --- /dev/null +++ b/gost_cipher.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +struct gost_cipher_ctx_st; +struct gost_cipher_st; +typedef struct gost_cipher_st GOST_cipher; + +int GOST_cipher_type(const GOST_cipher *c); +int GOST_cipher_nid(const GOST_cipher *c); +int GOST_cipher_flags(const GOST_cipher *c); +int GOST_cipher_key_length(const GOST_cipher *c); +int GOST_cipher_iv_length(const GOST_cipher *c); +int GOST_cipher_block_size(const GOST_cipher *c); +int GOST_cipher_mode(const GOST_cipher *c); +int GOST_cipher_ctx_size(const GOST_cipher *c); +int (*GOST_cipher_init_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +// Fill ASN1_TYPE *params struct based on ctx +int (*GOST_cipher_set_asn1_parameters_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx, + ASN1_TYPE *params); +// Modify ctx based on ASN1_TYPE *params struct +int (*GOST_cipher_get_asn1_parameters_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx, + ASN1_TYPE *params); +int (*GOST_cipher_do_cipher_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +int (*GOST_cipher_cleanup_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx); +int (*GOST_cipher_ctrl_fn(const GOST_cipher *c))(struct gost_cipher_ctx_st *ctx, + int type, int arg, + void *ptr); diff --git a/gost_cipher_ctx.c b/gost_cipher_ctx.c new file mode 100644 index 000000000..0081d4318 --- /dev/null +++ b/gost_cipher_ctx.c @@ -0,0 +1,895 @@ +#include "gost_cipher_ctx.h" + +#include +#include +#include + +#include +#include /* For ossl_inline */ + +/* + * Source: openssl/include/internal/safe_math.h + * openssl v3.6.0 7b371d80d959ec9ab4139d09d78e83c090de9779 + */ +# ifndef OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING +# ifdef __has_builtin +# define has(func) __has_builtin(func) +# elif defined(__GNUC__) +# if __GNUC__ > 5 +# define has(func) 1 +# endif +# endif +# endif /* OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING */ + +# ifndef has +# define has(func) 0 +# endif + +# if has(__builtin_add_overflow) +# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \ + static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \ + type b, \ + int *err) \ + { \ + type r; \ + \ + if (!__builtin_add_overflow(a, b, &r)) \ + return r; \ + *err |= 1; \ + return a < 0 ? min : max; \ + } + +# else /* has(__builtin_add_overflow) */ +# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \ + static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \ + type b, \ + int *err) \ + { \ + if ((a < 0) ^ (b < 0) \ + || (a > 0 && b <= max - a) \ + || (a < 0 && b >= min - a) \ + || a == 0) \ + return a + b; \ + *err |= 1; \ + return a < 0 ? min : max; \ + } + +# endif /* has(__builtin_add_overflow) */ + +# define OSSL_SAFE_MATH_MODS(type_name, type, min, max) \ + static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \ + type b, \ + int *err) \ + { \ + if (b == 0) { \ + *err |= 1; \ + return 0; \ + } \ + if (b == -1 && a == min) { \ + *err |= 1; \ + return max; \ + } \ + return a % b; \ + } + +/* + * Safe division helpers + */ +# define OSSL_SAFE_MATH_DIVS(type_name, type, min, max) \ + static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \ + type b, \ + int *err) \ + { \ + if (b == 0) { \ + *err |= 1; \ + return a < 0 ? min : max; \ + } \ + if (b == -1 && a == min) { \ + *err |= 1; \ + return max; \ + } \ + return a / b; \ + } + +/* + * Calculate a / b rounding up: + * i.e. a / b + (a % b != 0) + * Which is usually (less safely) converted to (a + b - 1) / b + * If you *know* that b != 0, then it's safe to ignore err. + */ +#define OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, max) \ + static ossl_inline ossl_unused type safe_div_round_up_ ## type_name \ + (type a, type b, int *errp) \ + { \ + type x; \ + int *err, err_local = 0; \ + \ + /* Allow errors to be ignored by callers */ \ + err = errp != NULL ? errp : &err_local; \ + /* Fast path, both positive */ \ + if (b > 0 && a > 0) { \ + /* Faster path: no overflow concerns */ \ + if (a < max - b) \ + return (a + b - 1) / b; \ + return a / b + (a % b != 0); \ + } \ + if (b == 0) { \ + *err |= 1; \ + return a == 0 ? 0 : max; \ + } \ + if (a == 0) \ + return 0; \ + /* Rather slow path because there are negatives involved */ \ + x = safe_mod_ ## type_name(a, b, err); \ + return safe_add_ ## type_name(safe_div_ ## type_name(a, b, err), \ + x != 0, err); \ + } + +/* + * End of source: openssl/include/internal/safe_math.h + * openssl v3.6.0 7b371d80d959ec9ab4139d09d78e83c090de9779 + */ + +OSSL_SAFE_MATH_ADDS(int, int, INT_MIN, INT_MAX) +OSSL_SAFE_MATH_MODS(int, int, INT_MIN, INT_MAX) +OSSL_SAFE_MATH_DIVS(int, int, INT_MIN, INT_MAX) +OSSL_SAFE_MATH_DIV_ROUND_UP(int, int, INT_MAX) + +/* + * Local adaptation for EVP_CIPHER_CTX interface + * + * Sources: + * * openssl/crypto/evp/evp_local.h + * * openssl/crypto/evp/evp_enc.c + * * openssl/crypto/evp/evp_lib.c + * + * openssl v3.6.0 7b371d80d959ec9ab4139d09d78e83c090de9779 + */ + +struct gost_cipher_ctx_st { + const GOST_cipher *cipher; + int encrypt; /* encrypt or decrypt */ + int buf_len; /* number we have left */ + unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ + unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ + unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */ + int num; /* used by cfb/ofb/ctr mode */ + /* FIXME: Should this even exist? It appears unused */ + void *app_data; /* application stuff */ + int key_len; /* May change for variable length cipher */ + int iv_len; /* IV length */ + unsigned long flags; /* Various flags */ + void *cipher_data; /* per EVP data */ + int final_used; + int block_mask; + unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ +} /* GOST_cipher_ctx */ ; + +static int GOST_cipher_ctx_reset(GOST_cipher_ctx *ctx) { + if (ctx == NULL) + return 1; + + if (ctx->cipher != NULL) { + if (GOST_cipher_cleanup_fn(ctx->cipher) && !GOST_cipher_cleanup_fn(ctx->cipher)(ctx)) + return 0; + /* Cleanse cipher context data */ + if (ctx->cipher_data && GOST_cipher_ctx_size(ctx->cipher)) + OPENSSL_cleanse(ctx->cipher_data, GOST_cipher_ctx_size(ctx->cipher)); + } + OPENSSL_free(ctx->cipher_data); + + memset(ctx, 0, sizeof(*ctx)); + ctx->iv_len = -1; + return 1; +} + +GOST_cipher_ctx *GOST_cipher_ctx_new(void) +{ + GOST_cipher_ctx *ctx; + + ctx = OPENSSL_zalloc(sizeof(GOST_cipher_ctx)); + if (ctx == NULL) + return NULL; + + ctx->iv_len = -1; + return ctx; +} + +void GOST_cipher_ctx_free(GOST_cipher_ctx *ctx) +{ + if (ctx == NULL) + return; + GOST_cipher_ctx_reset(ctx); + OPENSSL_free(ctx); +} + +int GOST_cipher_ctx_copy(GOST_cipher_ctx *out, const GOST_cipher_ctx *in) +{ + if ((in == NULL) || (in->cipher == NULL)) { + return 0; + } + + GOST_cipher_ctx_reset(out); + memcpy(out, in, sizeof(*out)); + + if (in->cipher_data && GOST_cipher_ctx_size(in->cipher)) { + out->cipher_data = OPENSSL_malloc(GOST_cipher_ctx_size(in->cipher)); + if (out->cipher_data == NULL) { + out->cipher = NULL; + return 0; + } + memcpy(out->cipher_data, in->cipher_data, GOST_cipher_ctx_size(in->cipher)); + } + + if (GOST_cipher_flags(in->cipher) & EVP_CIPH_CUSTOM_COPY) + if ((GOST_cipher_ctrl_fn(in->cipher) == NULL) + || !GOST_cipher_ctrl_fn(in->cipher)((GOST_cipher_ctx *)in, EVP_CTRL_COPY, 0, out)) { + out->cipher = NULL; + return 0; + } + return 1; +} + +unsigned char *GOST_cipher_ctx_buf_noconst(GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->buf : NULL; +} + +const GOST_cipher *GOST_cipher_ctx_cipher(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->cipher : NULL; +} + +int GOST_cipher_ctx_encrypting(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->encrypt : 0; +} + +int GOST_cipher_ctx_iv_length(const GOST_cipher_ctx *ctx) +{ + if (ctx == NULL) + return 0; + + if (ctx->cipher == NULL) + return 0; + + if (ctx->iv_len < 0) { + int rv, len = GOST_cipher_iv_length(ctx->cipher); + + if ((GOST_cipher_flags(ctx->cipher) + & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) { + rv = GOST_cipher_ctx_ctrl((GOST_cipher_ctx *)ctx, EVP_CTRL_GET_IVLEN, + 0, &len); + if (rv <= 0) + return -1; + } + + ((GOST_cipher_ctx *)ctx)->iv_len = len; + } + return ctx->iv_len; +} + +const unsigned char *GOST_cipher_ctx_iv(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->iv : NULL; +} + +unsigned char *GOST_cipher_ctx_iv_noconst(GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->iv : NULL; +} + +int GOST_cipher_ctx_key_length(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->key_len : 0; +} + +int GOST_cipher_ctx_mode(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cipher != NULL ? GOST_cipher_mode(ctx->cipher) : 0; +} + +int GOST_cipher_ctx_nid(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cipher != NULL ? GOST_cipher_nid(ctx->cipher) : NID_undef; +} + +int GOST_cipher_ctx_num(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->num : 0; +} + +const unsigned char *GOST_cipher_ctx_original_iv(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->oiv : NULL; +} + +void *GOST_cipher_ctx_get_app_data(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->app_data : NULL; +} + +void *GOST_cipher_ctx_get_cipher_data(GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->cipher_data : NULL; +} + +int GOST_cipher_ctx_set_num(GOST_cipher_ctx *ctx, int num) +{ + if (ctx == NULL) + return 0; + + ctx->num = num; + return 1; +} + +int GOST_cipher_ctx_set_padding(GOST_cipher_ctx *ctx, int pad) +{ + if (ctx == NULL) + return 0; + + if (pad) + ctx->flags &= ~EVP_CIPH_NO_PADDING; + else + ctx->flags |= EVP_CIPH_NO_PADDING; + + return 1; +} + +int GOST_cipher_ctx_set_flags(GOST_cipher_ctx *ctx, int flags) +{ + if (ctx == NULL) + return 0; + + ctx->flags |= flags; + return 1; +} + +void GOST_cipher_ctx_set_app_data(GOST_cipher_ctx *ctx, void *data) +{ + if (ctx != NULL) + ctx->app_data = data; +} + +int GOST_cipher_ctx_cleanup(GOST_cipher_ctx *ctx) +{ + return GOST_cipher_ctx_reset(ctx); +} + +int GOST_cipher_ctx_ctrl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) +{ + if (ctx == NULL || ctx->cipher == NULL) { + return 0; + } + + if (GOST_cipher_ctrl_fn(ctx->cipher) == NULL) { + return 0; + } + + return GOST_cipher_ctrl_fn(ctx->cipher)(ctx, type, arg, ptr); + +} + +static int GOST_cipher_ctx_test_flags(const GOST_cipher_ctx *ctx, int flags) +{ + return (ctx->flags & flags); +} + +static int gost_cipher_init_internal(GOST_cipher_ctx *ctx, + const GOST_cipher *cipher, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + int n; + + /* + * enc == 1 means we are encrypting. + * enc == 0 means we are decrypting. + * enc == -1 means, use the previously initialised value for encrypt/decrypt + */ + if (enc == -1) { + enc = ctx->encrypt; + } else { + if (enc) + enc = 1; + ctx->encrypt = enc; + } + + if (cipher == NULL && ctx->cipher == NULL) { + return 0; + } + + /* + * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so + * this context may already have an ENGINE! Try to avoid releasing the + * previous handle, re-querying for an ENGINE, and having a + * reinitialisation, when it may all be unnecessary. + */ + if (ctx->cipher + && (cipher == NULL || cipher == ctx->cipher)) + goto skip_to_init; + + if (cipher != NULL) { + /* + * Ensure a context left lying around from last time is cleared (we + * previously attempted to avoid this if the same ENGINE and + * EVP_CIPHER could be used). + */ + if (ctx->cipher) { + unsigned long flags = ctx->flags; + GOST_cipher_ctx_reset(ctx); + /* Restore encrypt and flags */ + ctx->encrypt = enc; + ctx->flags = flags; + } + + ctx->cipher = cipher; + if (GOST_cipher_ctx_size(ctx->cipher)) { + ctx->cipher_data = OPENSSL_zalloc(GOST_cipher_ctx_size(ctx->cipher)); + if (ctx->cipher_data == NULL) { + ctx->cipher = NULL; + return 0; + } + } else { + ctx->cipher_data = NULL; + } + ctx->key_len = GOST_cipher_key_length(cipher); + /* Preserve wrap enable flag, zero everything else */ + ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; + if (GOST_cipher_flags(ctx->cipher) & EVP_CIPH_CTRL_INIT) { + if (GOST_cipher_ctx_ctrl(ctx, EVP_CTRL_INIT, 0, NULL) <= 0) { + ctx->cipher = NULL; + return 0; + } + } + } + + skip_to_init: + if (ctx->cipher == NULL) + return 0; + + /* we assume block size is a power of 2 in *cryptUpdate */ + OPENSSL_assert(GOST_cipher_block_size(ctx->cipher) == 1 + || GOST_cipher_block_size(ctx->cipher) == 8 + || GOST_cipher_block_size(ctx->cipher) == 16); + + if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) + && GOST_cipher_mode(ctx->cipher) == EVP_CIPH_WRAP_MODE) { + return 0; + } + + if ((GOST_cipher_flags(ctx->cipher) + & EVP_CIPH_CUSTOM_IV) == 0) { + switch (GOST_cipher_mode(ctx->cipher)) { + + case EVP_CIPH_STREAM_CIPHER: + case EVP_CIPH_ECB_MODE: + break; + + case EVP_CIPH_CFB_MODE: + case EVP_CIPH_OFB_MODE: + + ctx->num = 0; + /* fall-through */ + + case EVP_CIPH_CBC_MODE: + n = GOST_cipher_ctx_iv_length(ctx); + if (n < 0 || n > (int)sizeof(ctx->iv)) { + return 0; + } + if (iv != NULL) + memcpy(ctx->oiv, iv, n); + memcpy(ctx->iv, ctx->oiv, n); + break; + + case EVP_CIPH_CTR_MODE: + ctx->num = 0; + /* Don't reuse IV for CTR mode */ + if (iv != NULL) { + n = GOST_cipher_ctx_iv_length(ctx); + if (n <= 0 || n > (int)sizeof(ctx->iv)) { + return 0; + } + memcpy(ctx->iv, iv, n); + } + break; + + default: + return 0; + } + } + + if (key != NULL || (GOST_cipher_flags(ctx->cipher) & EVP_CIPH_ALWAYS_CALL_INIT)) { + if (!GOST_cipher_init_fn(ctx->cipher)(ctx, key, iv, enc)) + return 0; + } + ctx->buf_len = 0; + ctx->final_used = 0; + ctx->block_mask = GOST_cipher_block_size(ctx->cipher) - 1; + + return 1; +} + + +int GOST_CipherInit_ex(GOST_cipher_ctx *ctx, const GOST_cipher *cipher, + const unsigned char *key, const unsigned char *iv, + int enc) +{ + return gost_cipher_init_internal(ctx, cipher, key, iv, enc); +} + +/* + * According to the letter of standard difference between pointers + * is specified to be valid only within same object. This makes + * it formally challenging to determine if input and output buffers + * are not partially overlapping with standard pointer arithmetic. + */ +#ifdef PTRDIFF_T +# undef PTRDIFF_T +#endif +#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE==64 +/* + * Then we have VMS that distinguishes itself by adhering to + * sizeof(size_t)==4 even in 64-bit builds, which means that + * difference between two pointers might be truncated to 32 bits. + * In the context one can even wonder how comparison for + * equality is implemented. To be on the safe side we adhere to + * PTRDIFF_T even for comparison for equality. + */ +# define PTRDIFF_T uint64_t +#else +# define PTRDIFF_T size_t +#endif + +static int gost_cipher_is_partially_overlapping(const void *ptr1, + const void *ptr2, + size_t len) +{ + PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2; + /* + * Check for partially overlapping buffers. [Binary logical + * operations are used instead of boolean to minimize number + * of conditional branches.] + */ + int overlapped = (len > 0) & (diff != 0) & ((diff < (PTRDIFF_T)len) | + (diff > (0 - (PTRDIFF_T)len))); + + return overlapped; +} + +static int gost_cipher_EncryptDecryptUpdate(GOST_cipher_ctx *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int i, j, bl, cmpl = inl; + + if (GOST_cipher_ctx_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) + cmpl = safe_div_round_up_int(cmpl, 8, NULL); + + bl = GOST_cipher_block_size(ctx->cipher); + + if ((GOST_cipher_flags(ctx->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) { + /* If block size > 1 then the cipher will have to do this check */ + if (bl == 1 && gost_cipher_is_partially_overlapping(out, in, cmpl)) { + return 0; + } + + i = GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, in, inl); + if (i < 0) + return 0; + else + *outl = i; + return 1; + } + + if (inl <= 0) { + *outl = 0; + return inl == 0; + } + if (gost_cipher_is_partially_overlapping(out + ctx->buf_len, in, cmpl)) { + return 0; + } + + if (ctx->buf_len == 0 && (inl & (ctx->block_mask)) == 0) { + if (GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, in, inl)) { + *outl = inl; + return 1; + } else { + *outl = 0; + return 0; + } + } + i = ctx->buf_len; + OPENSSL_assert(bl <= (int)sizeof(ctx->buf)); + if (i != 0) { + if (bl - i > inl) { + memcpy(&(ctx->buf[i]), in, inl); + ctx->buf_len += inl; + *outl = 0; + return 1; + } else { + j = bl - i; + + /* + * Once we've processed the first j bytes from in, the amount of + * data left that is a multiple of the block length is: + * (inl - j) & ~(bl - 1) + * We must ensure that this amount of data, plus the one block that + * we process from ctx->buf does not exceed INT_MAX + */ + if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) { + return 0; + } + memcpy(&(ctx->buf[i]), in, j); + inl -= j; + in += j; + if (!GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, ctx->buf, bl)) + return 0; + out += bl; + *outl = bl; + } + } else + *outl = 0; + i = inl & (bl - 1); + inl -= i; + if (inl > 0) { + if (!GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, in, inl)) + return 0; + *outl += inl; + } + + if (i != 0) + memcpy(ctx->buf, &(in[inl]), i); + ctx->buf_len = i; + return 1; +} + +static int GOST_EncryptUpdate(GOST_cipher_ctx *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + if (outl != NULL) { + *outl = 0; + } else { + return 0; + } + + if (!ctx->encrypt) { + return 0; + } + + if (ctx->cipher == NULL) { + return 0; + } + + return gost_cipher_EncryptDecryptUpdate(ctx, out, outl, in, inl); +} + +static int GOST_DecryptUpdate(GOST_cipher_ctx *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int fix_len, cmpl = inl; + unsigned int b; + + if (outl != NULL) { + *outl = 0; + } else { + return 0; + } + + if (ctx->encrypt) { + return 0; + } + + if (ctx->cipher == NULL) { + return 0; + } + + b = GOST_cipher_block_size(ctx->cipher); + + if (GOST_cipher_ctx_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) + cmpl = safe_div_round_up_int(cmpl, 8, NULL); + + if (GOST_cipher_flags(ctx->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + if (b == 1 && gost_cipher_is_partially_overlapping(out, in, cmpl)) { + return 0; + } + + fix_len = GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, in, inl); + if (fix_len < 0) { + *outl = 0; + return 0; + } else + *outl = fix_len; + return 1; + } + + if (inl <= 0) { + *outl = 0; + return inl == 0; + } + + if (ctx->flags & EVP_CIPH_NO_PADDING) + return gost_cipher_EncryptDecryptUpdate(ctx, out, outl, in, inl); + + OPENSSL_assert(b <= sizeof(ctx->final)); + + if (ctx->final_used) { + /* see comment about PTRDIFF_T comparison above */ + if (((PTRDIFF_T)out == (PTRDIFF_T)in) + || gost_cipher_is_partially_overlapping(out, in, b)) { + return 0; + } + /* + * final_used is only ever set if buf_len is 0. Therefore the maximum + * length output we will ever see from evp_EncryptDecryptUpdate is + * the maximum multiple of the block length that is <= inl, or just: + * inl & ~(b - 1) + * Since final_used has been set then the final output length is: + * (inl & ~(b - 1)) + b + * This must never exceed INT_MAX + */ + if ((inl & ~(b - 1)) > INT_MAX - b) { + return 0; + } + memcpy(out, ctx->final, b); + out += b; + fix_len = 1; + } else + fix_len = 0; + + if (!gost_cipher_EncryptDecryptUpdate(ctx, out, outl, in, inl)) + return 0; + + /* + * if we have 'decrypted' a multiple of block size, make sure we have a + * copy of this last block + */ + if (b > 1 && !ctx->buf_len) { + *outl -= b; + ctx->final_used = 1; + memcpy(ctx->final, &out[*outl], b); + } else + ctx->final_used = 0; + + if (fix_len) + *outl += b; + + return 1; +} + +int GOST_CipherUpdate(GOST_cipher_ctx *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + if (ctx->encrypt) + return GOST_EncryptUpdate(ctx, out, outl, in, inl); + else + return GOST_DecryptUpdate(ctx, out, outl, in, inl); +} + +static int GOST_EncryptFinal(GOST_cipher_ctx *ctx, unsigned char *out, int *outl) +{ + int n, ret; + unsigned int i, b, bl; + + if (outl != NULL) { + *outl = 0; + } else { + return 0; + } + + /* Prevent accidental use of decryption context when encrypting */ + if (!ctx->encrypt) { + return 0; + } + + if (ctx->cipher == NULL) { + return 0; + } + + if (GOST_cipher_flags(ctx->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + ret = GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, NULL, 0); + if (ret < 0) + return 0; + else + *outl = ret; + return 1; + } + + b = GOST_cipher_block_size(ctx->cipher); + OPENSSL_assert(b <= sizeof(ctx->buf)); + if (b == 1) { + *outl = 0; + return 1; + } + bl = ctx->buf_len; + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (bl) { + return 0; + } + *outl = 0; + return 1; + } + + n = b - bl; + for (i = bl; i < b; i++) + ctx->buf[i] = n; + ret = GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, ctx->buf, b); + + if (ret) + *outl = b; + + return ret; +} + +static int GOST_DecryptFinal(GOST_cipher_ctx *ctx, unsigned char *out, int *outl) +{ + int i, n; + unsigned int b; + + if (outl != NULL) { + *outl = 0; + } else { + return 0; + } + + /* Prevent accidental use of encryption context when decrypting */ + if (ctx->encrypt) { + return 0; + } + + if (ctx->cipher == NULL) { + return 0; + } + + *outl = 0; + if (GOST_cipher_flags(ctx->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + i = GOST_cipher_do_cipher_fn(ctx->cipher)(ctx, out, NULL, 0); + if (i < 0) + return 0; + else + *outl = i; + return 1; + } + + b = GOST_cipher_block_size(ctx->cipher); + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (ctx->buf_len) { + return 0; + } + *outl = 0; + return 1; + } + if (b > 1) { + if (ctx->buf_len || !ctx->final_used) { + return 0; + } + OPENSSL_assert(b <= sizeof(ctx->final)); + + /* + * The following assumes that the ciphertext has been authenticated. + * Otherwise it provides a padding oracle. + */ + n = ctx->final[b - 1]; + if (n == 0 || n > (int)b) { + return 0; + } + for (i = 0; i < n; i++) { + if (ctx->final[--b] != n) { + return 0; + } + } + n = GOST_cipher_block_size(ctx->cipher) - n; + for (i = 0; i < n; i++) + out[i] = ctx->final[i]; + *outl = n; + } + return 1; +} + +int GOST_CipherFinal(GOST_cipher_ctx *ctx, unsigned char *out, int *outl) +{ + if (ctx->encrypt) + return GOST_EncryptFinal(ctx, out, outl); + else + return GOST_DecryptFinal(ctx, out, outl); +} diff --git a/gost_cipher_ctx.h b/gost_cipher_ctx.h new file mode 100644 index 000000000..f050adf96 --- /dev/null +++ b/gost_cipher_ctx.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include + +#include "gost_cipher.h" + +struct gost_cipher_ctx_st; +typedef struct gost_cipher_ctx_st GOST_cipher_ctx; + +GOST_cipher_ctx *GOST_cipher_ctx_new(void); +void GOST_cipher_ctx_free(GOST_cipher_ctx *ctx); + +int GOST_CipherInit_ex(GOST_cipher_ctx *ctx, const GOST_cipher *cipher, + const unsigned char *key, const unsigned char *iv, + int enc); +int GOST_CipherUpdate(GOST_cipher_ctx *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int GOST_CipherFinal(GOST_cipher_ctx *ctx, unsigned char *out, int *outl); + +/* GOST_cipher_ctx accessor functions */ +unsigned char *GOST_cipher_ctx_buf_noconst(GOST_cipher_ctx *ctx); +const GOST_cipher *GOST_cipher_ctx_cipher(const GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_encrypting(const GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_iv_length(const GOST_cipher_ctx *ctx); +const unsigned char *GOST_cipher_ctx_iv(const GOST_cipher_ctx *ctx); +unsigned char *GOST_cipher_ctx_iv_noconst(GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_key_length(const GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_mode(const GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_nid(const GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_num(const GOST_cipher_ctx *ctx); +const unsigned char *GOST_cipher_ctx_original_iv(const GOST_cipher_ctx *ctx); +void *GOST_cipher_ctx_get_app_data(const GOST_cipher_ctx *ctx); +void *GOST_cipher_ctx_get_cipher_data(GOST_cipher_ctx *ctx); + +/* GOST_cipher_ctx mutator functions */ +int GOST_cipher_ctx_set_num(GOST_cipher_ctx *ctx, int num); +int GOST_cipher_ctx_set_padding(GOST_cipher_ctx *ctx, int pad); +int GOST_cipher_ctx_set_flags(GOST_cipher_ctx *ctx, int flags); +void GOST_cipher_ctx_set_app_data(GOST_cipher_ctx *ctx, void *data); + +/* GOST_cipher_ctx control, operation and instance management functions */ +int GOST_cipher_ctx_cleanup(GOST_cipher_ctx *ctx); +int GOST_cipher_ctx_ctrl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr); +int GOST_cipher_ctx_copy(GOST_cipher_ctx *out, const GOST_cipher_ctx *in); diff --git a/gost_cipher_ctx_evp.c b/gost_cipher_ctx_evp.c new file mode 100644 index 000000000..acbc9d7fc --- /dev/null +++ b/gost_cipher_ctx_evp.c @@ -0,0 +1,240 @@ +#include "gost_cipher_ctx.h" + +struct gost_cipher_ctx_st { + const GOST_cipher *cipher; + EVP_CIPHER_CTX *cctx; +}; + +static int gost_cipher_ctx_init_evp(GOST_cipher_ctx *ctx, + const GOST_cipher *cipher, + EVP_CIPHER_CTX *cctx) +{ + if (ctx == NULL || cipher == NULL || cctx == NULL) + return 0; + + ctx->cipher = cipher; + ctx->cctx = cctx; + return 1; +} + +int GOST_cipher_init_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + const unsigned char *key, const unsigned char *iv, + int enc) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (GOST_cipher_init_fn(cipher) == NULL) + return 1; + + return GOST_cipher_init_fn(cipher)(&gctx, key, iv, enc); +} + +int GOST_cipher_do_cipher_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + unsigned char *out, const unsigned char *in, + size_t inl) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (GOST_cipher_do_cipher_fn(cipher) == NULL) + return 1; + + return GOST_cipher_do_cipher_fn(cipher)(&gctx, out, in, inl); +} + +int GOST_cipher_cleanup_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (GOST_cipher_cleanup_fn(cipher) == NULL) + return 1; + + return GOST_cipher_cleanup_fn(cipher)(&gctx); +} + +int GOST_cipher_ctrl_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + int type, int arg, void *ptr) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (type == EVP_CTRL_COPY) { + GOST_cipher_ctx out_ctx; + EVP_CIPHER_CTX *out = ptr; + + if (out == NULL || !gost_cipher_ctx_init_evp(&out_ctx, cipher, out)) + return 0; + + return GOST_cipher_ctx_copy(&out_ctx, &gctx); + } + if (GOST_cipher_ctrl_fn(cipher) == NULL) + return -2; + + return GOST_cipher_ctrl_fn(cipher)(&gctx, type, arg, ptr); +} + +int GOST_cipher_set_asn1_parameters_evp(const GOST_cipher *cipher, + EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (GOST_cipher_set_asn1_parameters_fn(cipher) == NULL) + return 1; + + return GOST_cipher_set_asn1_parameters_fn(cipher)(&gctx, params); +} + +int GOST_cipher_get_asn1_parameters_evp(const GOST_cipher *cipher, + EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params) +{ + GOST_cipher_ctx gctx; + + if (!gost_cipher_ctx_init_evp(&gctx, cipher, ctx)) + return 0; + if (GOST_cipher_get_asn1_parameters_fn(cipher) == NULL) + return 1; + + return GOST_cipher_get_asn1_parameters_fn(cipher)(&gctx, params); +} + +int GOST_cipher_ctx_copy(GOST_cipher_ctx *out, const GOST_cipher_ctx *in) +{ + if (out == NULL || in == NULL || out->cctx == NULL || in->cctx == NULL) + return 0; + + out->cipher = in->cipher; + if (EVP_CIPHER_CTX_get_app_data(in->cctx) == EVP_CIPHER_CTX_get_cipher_data(in->cctx)) + EVP_CIPHER_CTX_set_app_data(out->cctx, EVP_CIPHER_CTX_get_cipher_data(out->cctx)); + + if (out == in) + return 1; + if (out->cipher != NULL + && (GOST_cipher_flags(out->cipher) & EVP_CIPH_CUSTOM_COPY) != 0 + && GOST_cipher_ctrl_fn(out->cipher) != NULL) + return GOST_cipher_ctrl_fn(out->cipher)((GOST_cipher_ctx *)in, + EVP_CTRL_COPY, 0, out) > 0; + + return 1; +} + +unsigned char *GOST_cipher_ctx_buf_noconst(GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_buf_noconst(ctx->cctx) : NULL; +} + +const GOST_cipher *GOST_cipher_ctx_cipher(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL ? ctx->cipher : NULL; +} + +int GOST_cipher_ctx_encrypting(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_encrypting(ctx->cctx) : 0; +} + +int GOST_cipher_ctx_iv_length(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_iv_length(ctx->cctx) : 0; +} + +const unsigned char *GOST_cipher_ctx_iv(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_iv(ctx->cctx) : NULL; +} + +unsigned char *GOST_cipher_ctx_iv_noconst(GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_iv_noconst(ctx->cctx) : NULL; +} + +int GOST_cipher_ctx_key_length(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_key_length(ctx->cctx) : 0; +} + +int GOST_cipher_ctx_mode(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_mode(ctx->cctx) : 0; +} + +int GOST_cipher_ctx_nid(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_nid(ctx->cctx) : NID_undef; +} + +int GOST_cipher_ctx_num(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_num(ctx->cctx) : 0; +} + +const unsigned char *GOST_cipher_ctx_original_iv(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_original_iv(ctx->cctx) : NULL; +} + +void *GOST_cipher_ctx_get_app_data(const GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_get_app_data(ctx->cctx) : NULL; +} + +void *GOST_cipher_ctx_get_cipher_data(GOST_cipher_ctx *ctx) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_get_cipher_data(ctx->cctx) : NULL; +} + +int GOST_cipher_ctx_set_num(GOST_cipher_ctx *ctx, int num) +{ + if (ctx == NULL) + return 0; + + EVP_CIPHER_CTX_set_num(ctx->cctx, num); + return 1; +} + +int GOST_cipher_ctx_set_padding(GOST_cipher_ctx *ctx, int pad) +{ + return ctx != NULL && ctx->cctx != NULL ? EVP_CIPHER_CTX_set_padding(ctx->cctx, pad) : 0; +} + +int GOST_cipher_ctx_set_flags(GOST_cipher_ctx *ctx, int flags) +{ + if (ctx == NULL) + return 0; + + EVP_CIPHER_CTX_set_flags(ctx->cctx, flags); + return 1; +} + +void GOST_cipher_ctx_set_app_data(GOST_cipher_ctx *ctx, void *data) +{ + if (ctx != NULL && ctx->cctx != NULL) + EVP_CIPHER_CTX_set_app_data(ctx->cctx, data); +} + +int GOST_cipher_ctx_cleanup(GOST_cipher_ctx *ctx) +{ + if (ctx == NULL || ctx->cipher == NULL) + return 0; + if (GOST_cipher_cleanup_fn(ctx->cipher) == NULL) + return 1; + + return GOST_cipher_cleanup_fn(ctx->cipher)(ctx); +} + +int GOST_cipher_ctx_ctrl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) +{ + if (ctx == NULL || ctx->cipher == NULL || GOST_cipher_ctrl_fn(ctx->cipher) == NULL) + return -2; + + return GOST_cipher_ctrl_fn(ctx->cipher)(ctx, type, arg, ptr); +} diff --git a/gost_cipher_details.h b/gost_cipher_details.h new file mode 100644 index 000000000..5004a8f95 --- /dev/null +++ b/gost_cipher_details.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "gost_cipher.h" + +/* Internal cipher descriptor layout. Public users must treat GOST_cipher as opaque. */ +struct gost_cipher_st { + struct gost_cipher_st *template; /* template struct */ + int nid; + int block_size; /* (bytes) */ + int key_len; /* (bytes) */ + int iv_len; + int flags; + int (*init) (struct gost_cipher_ctx_st *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + int (*do_cipher)(struct gost_cipher_ctx_st *ctx, unsigned char *out, + const unsigned char *in, size_t inl); + int (*cleanup)(struct gost_cipher_ctx_st *); + int ctx_size; + int (*set_asn1_parameters)(struct gost_cipher_ctx_st *, ASN1_TYPE *); + int (*get_asn1_parameters)(struct gost_cipher_ctx_st *, ASN1_TYPE *); + int (*ctrl)(struct gost_cipher_ctx_st *, int type, int arg, void *ptr); +}; diff --git a/gost_crypt.c b/gost_crypt.c index 5a5b90c3f..5ef875751 100644 --- a/gost_crypt.c +++ b/gost_crypt.c @@ -17,6 +17,8 @@ #include "gost_gost2015.h" #include "gost_tls12_additional.h" #include "gost_digest_details.h" +#include "gost_cipher_details.h" +#include "gost_cipher_ctx.h" #if !defined(CCGOST_DEBUG) && !defined(DEBUG) # ifndef NDEBUG @@ -25,121 +27,58 @@ #endif #include -static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); -static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_cipher_init_cbc(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); -static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_cipher_init_cpa(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); -static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx, +static int gost_cipher_init_cp_12(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); /* Handles block of data in CFB mode */ -static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cfb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); /* Handles block of data in CBC mode */ -static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cbc(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); /* Handles block of data in CNT mode */ -static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cnt(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); /* Cleanup function */ -static int gost_cipher_cleanup(EVP_CIPHER_CTX *); -static int gost_magma_mgm_cleanup(EVP_CIPHER_CTX *c); +static int gost_cipher_cleanup(GOST_cipher_ctx *); +static int gost_magma_mgm_cleanup(GOST_cipher_ctx *c); /* set/get cipher parameters */ -static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); -static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); +static int gost89_set_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params); +static int gost89_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params); /* Control function */ -static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +static int gost_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr); -static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int magma_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); -static int magma_cipher_init_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int magma_cipher_init_ctr_acpkm_omac(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); -static int gost_magma_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_magma_cipher_init_mgm(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc); /* Handles block of data in CBC mode */ -static int magma_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ecb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); -static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_cbc(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); -static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ctr(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); -static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ctr_acpkm_omac(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl); -static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_magma_cipher_do_mgm(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len); /* set/get cipher parameters */ -static int magma_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); -static int magma_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); +static int magma_set_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params); +static int magma_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params); /* Control function */ -static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); -static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); -static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); - -/* - * Single level template accessor. - * Note: that you cannot template 0 value. - */ -#define TPL(st,field) ( \ - ((st)->field) ? ((st)->field) : TPL_VAL(st,field) \ -) - -#define TPL_VAL(st,field) ( \ - ((st)->template ? (st)->template->field : 0) \ -) - -EVP_CIPHER *GOST_init_cipher(GOST_cipher *c) -{ - if (c->cipher) - return c->cipher; - - /* Some sanity checking. */ - int flags = c->flags | TPL_VAL(c, flags); - int block_size = TPL(c, block_size); - switch (flags & EVP_CIPH_MODE) { - case EVP_CIPH_CBC_MODE: - case EVP_CIPH_ECB_MODE: - case EVP_CIPH_WRAP_MODE: - OPENSSL_assert(block_size != 1); - OPENSSL_assert(!(flags & EVP_CIPH_NO_PADDING)); - break; - default: - OPENSSL_assert(block_size == 1); - OPENSSL_assert(flags & EVP_CIPH_NO_PADDING); - } - - if (TPL(c, iv_len)) - OPENSSL_assert(flags & EVP_CIPH_CUSTOM_IV); - else - OPENSSL_assert(!(flags & EVP_CIPH_CUSTOM_IV)); - - EVP_CIPHER *cipher; - if (!(cipher = EVP_CIPHER_meth_new(c->nid, block_size, TPL(c, key_len))) - || !EVP_CIPHER_meth_set_iv_length(cipher, TPL(c, iv_len)) - || !EVP_CIPHER_meth_set_flags(cipher, flags) - || !EVP_CIPHER_meth_set_init(cipher, TPL(c, init)) - || !EVP_CIPHER_meth_set_do_cipher(cipher, TPL(c, do_cipher)) - || !EVP_CIPHER_meth_set_cleanup(cipher, TPL(c, cleanup)) - || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, TPL(c, ctx_size)) - || !EVP_CIPHER_meth_set_set_asn1_params(cipher, TPL(c, set_asn1_parameters)) - || !EVP_CIPHER_meth_set_get_asn1_params(cipher, TPL(c, get_asn1_parameters)) - || !EVP_CIPHER_meth_set_ctrl(cipher, TPL(c, ctrl))) { - EVP_CIPHER_meth_free(cipher); - cipher = NULL; - } - c->cipher = cipher; - return c->cipher; -} - -void GOST_deinit_cipher(GOST_cipher *c) -{ - if (c->cipher) { - EVP_CIPHER_meth_free(c->cipher); - c->cipher = NULL; - } -} +static int magma_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr); +static int magma_cipher_ctl_acpkm_omac(GOST_cipher_ctx *ctx, int type, int arg, void *ptr); +static int gost_magma_mgm_ctrl(GOST_cipher_ctx *c, int type, int arg, void *ptr); static GOST_cipher gost_template_cipher = { .block_size = 8, @@ -411,88 +350,88 @@ static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid) return 1; } -/* Initializes EVP_CIPHER_CTX by paramset NID */ -static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, +/* Initializes cipher context by paramset NID */ +static int gost_cipher_init_param(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc, int paramNID, int mode) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) { + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + if (GOST_cipher_ctx_get_app_data(ctx) == NULL) { if (!gost_cipher_set_param(c, paramNID)) return 0; - EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx)); + GOST_cipher_ctx_set_app_data(ctx, GOST_cipher_ctx_get_cipher_data(ctx)); } if (key) gost_key(&(c->cctx), key); if (iv) { - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, - EVP_CIPHER_CTX_iv_length(ctx)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, + GOST_cipher_ctx_iv_length(ctx)); } - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), - EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), + GOST_cipher_ctx_original_iv(ctx), GOST_cipher_ctx_iv_length(ctx)); return 1; } -static int gost_cipher_init_cnt(EVP_CIPHER_CTX *ctx, +static int gost_cipher_init_cnt(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, gost_subst_block * block) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); gost_init(&(c->cctx), block); c->key_meshing = 1; c->count = 0; if (key) gost_key(&(c->cctx), key); if (iv) { - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, - EVP_CIPHER_CTX_iv_length(ctx)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, + GOST_cipher_ctx_iv_length(ctx)); } - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), - EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), + GOST_cipher_ctx_original_iv(ctx), GOST_cipher_ctx_iv_length(ctx)); return 1; } -static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_cipher_init_cpa(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_CryptoProParamSetA); } -static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx, +static int gost_cipher_init_cp_12(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_TC26ParamSetZ); } -/* Initializes EVP_CIPHER_CTX with default values */ -static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +/* Initializes cipher context with default values */ +static int gost_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { return gost_cipher_init_param(ctx, key, iv, enc, NID_undef, EVP_CIPH_CFB_MODE); } -/* Initializes EVP_CIPHER_CTX with default values */ -static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, +/* Initializes cipher context with default values */ +static int gost_cipher_init_cbc(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { return gost_cipher_init_param(ctx, key, iv, enc, NID_undef, EVP_CIPH_CBC_MODE); } -/* Initializes EVP_CIPHER_CTX with default values */ -static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +/* Initializes cipher context with default values */ +static int magma_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); /* FIXME this is just initializtion check */ - if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) { + if (GOST_cipher_ctx_get_app_data(ctx) == NULL) { if (!gost_cipher_set_param(c, NID_id_tc26_gost_28147_param_Z)) return 0; - EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx)); + GOST_cipher_ctx_set_app_data(ctx, GOST_cipher_ctx_get_cipher_data(ctx)); if (enc) { if (init_zero_kdf_seed(c->kdf_seed) == 0) @@ -505,14 +444,14 @@ static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, magma_master_key(&(c->cctx), key); } if (iv) { - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, - EVP_CIPHER_CTX_iv_length(ctx)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, + GOST_cipher_ctx_iv_length(ctx)); } - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), - EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), + GOST_cipher_ctx_original_iv(ctx), GOST_cipher_ctx_iv_length(ctx)); - if (EVP_CIPHER_CTX_nid(ctx) == NID_magma_ctr_acpkm - || EVP_CIPHER_CTX_nid(ctx) == NID_magma_ctr_acpkm_omac) { + if (GOST_cipher_ctx_nid(ctx) == NID_magma_ctr_acpkm + || GOST_cipher_ctx_nid(ctx) == NID_magma_ctr_acpkm_omac) { c->key_meshing = 1024; } else { c->key_meshing = 0; @@ -522,12 +461,12 @@ static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } -/* Initializes EVP_CIPHER_CTX with default values */ -static int magma_cipher_init_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, const unsigned char *key, +/* Initializes cipher context with default values */ +static int magma_cipher_init_ctr_acpkm_omac(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { if (key) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); unsigned char cipher_key[32]; int ret; c->omac_ctx = EVP_MD_CTX_new(); @@ -615,17 +554,17 @@ static void gf64_mul (uint64_t *result, uint64_t *arg1, uint64_t *arg2) #endif } -static int gost_magma_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int gost_magma_cipher_init_mgm(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(ctx); int bl; if (!iv && !key) return 1; if (key) { - bl = EVP_CIPHER_CTX_iv_length(ctx); + bl = GOST_cipher_ctx_iv_length(ctx); if (!gost_cipher_set_param(&mctx->ks.g_ks, NID_id_tc26_gost_28147_param_Z)) return 0; magma_key(&(mctx->ks.g_ks.cctx), key); @@ -707,16 +646,16 @@ static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf) } /* GOST encryption in CBC mode */ -static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cbc(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { unsigned char b[8]; const unsigned char *in_ptr = in; unsigned char *out_ptr = out; int i; - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - if (EVP_CIPHER_CTX_encrypting(ctx)) { + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + if (GOST_cipher_ctx_encrypting(ctx)) { while (inl > 0) { for (i = 0; i < 8; i++) { @@ -746,11 +685,11 @@ static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, } /* MAGMA encryption in ECB mode */ -static int magma_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ecb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - if (EVP_CIPHER_CTX_encrypting(ctx)) { + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + if (GOST_cipher_ctx_encrypting(ctx)) { while (inl > 0) { magmacrypt(&(c->cctx), in, out); out += 8; @@ -769,7 +708,7 @@ static int magma_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out, } /* MAGMA encryption in CBC mode */ -static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_cbc(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { unsigned char b[8]; @@ -777,9 +716,9 @@ static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in_ptr = in; unsigned char *out_ptr = out; int i; - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - if (EVP_CIPHER_CTX_encrypting(ctx)) { + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + if (GOST_cipher_ctx_encrypting(ctx)) { while (inl > 0) { for (i = 0; i < 8; i++) { @@ -825,16 +764,16 @@ static inline void apply_acpkm_magma(struct ossl_gost_cipher_ctx * } /* MAGMA encryption in CTR mode */ -static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ctr(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { const unsigned char *in_ptr = in; unsigned char *out_ptr = out; size_t j; - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - unsigned int num = EVP_CIPHER_CTX_num(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *buf = GOST_cipher_ctx_buf_noconst(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + unsigned int num = GOST_cipher_ctx_num(ctx); size_t blocks, i, lasted = inl; /* Process partial blocks */ while ((num & MAGMA_BLOCK_MASK) && lasted) { @@ -870,16 +809,16 @@ static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, c->count += 8; num += lasted; } - EVP_CIPHER_CTX_set_num(ctx, num); + GOST_cipher_ctx_set_num(ctx, num); return inl; } /* MAGMA encryption in CTR mode */ -static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_cipher_do_ctr_acpkm_omac(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); if (in == NULL && inl == 0) /* Final call */ return gost2015_final_call(ctx, c->omac_ctx, MAGMA_MAC_MAX_SIZE, c->tag, magma_cipher_do_ctr); @@ -888,25 +827,25 @@ static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *ou return -1; /* As in and out can be the same pointer, process unencrypted here */ - if (EVP_CIPHER_CTX_encrypting(ctx)) + if (GOST_cipher_ctx_encrypting(ctx)) EVP_DigestSignUpdate(c->omac_ctx, in, inl); if (magma_cipher_do_ctr(ctx, out, in, inl) != inl) return -1; /* As in and out can be the same pointer, process decrypted here */ - if (!EVP_CIPHER_CTX_encrypting(ctx)) + if (!GOST_cipher_ctx_encrypting(ctx)) EVP_DigestSignUpdate(c->omac_ctx, out, inl); return inl; } -static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_magma_cipher_do_mgm(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); - int enc = EVP_CIPHER_CTX_encrypting(ctx); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(ctx); + int enc = GOST_cipher_ctx_encrypting(ctx); /* If not set up, return error */ if (!mctx->key_set) { @@ -937,13 +876,13 @@ static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out, if (mctx->taglen < 0) return -1; if (gost_mgm128_finish(&mctx->mgm, - EVP_CIPHER_CTX_buf_noconst(ctx), + GOST_cipher_ctx_buf_noconst(ctx), mctx->taglen) != 0) return -1; mctx->iv_set = 0; return 0; } - gost_mgm128_tag(&mctx->mgm, EVP_CIPHER_CTX_buf_noconst(ctx), 8); + gost_mgm128_tag(&mctx->mgm, GOST_cipher_ctx_buf_noconst(ctx), 8); mctx->taglen = 8; /* Don't reuse the IV */ mctx->iv_set = 0; @@ -953,30 +892,30 @@ static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out, } /* GOST encryption in CFB mode */ -static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cfb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { const unsigned char *in_ptr = in; unsigned char *out_ptr = out; size_t i = 0; size_t j = 0; - unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + unsigned char *buf = GOST_cipher_ctx_buf_noconst(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); /* process partial block if any */ - if (EVP_CIPHER_CTX_num(ctx)) { - for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; + if (GOST_cipher_ctx_num(ctx)) { + for (j = GOST_cipher_ctx_num(ctx), i = 0; j < 8 && i < inl; j++, i++, in_ptr++, out_ptr++) { - if (!EVP_CIPHER_CTX_encrypting(ctx)) + if (!GOST_cipher_ctx_encrypting(ctx)) buf[j + 8] = *in_ptr; *out_ptr = buf[j] ^ (*in_ptr); - if (EVP_CIPHER_CTX_encrypting(ctx)) + if (GOST_cipher_ctx_encrypting(ctx)) buf[j + 8] = *out_ptr; } if (j == 8) { memcpy(iv, buf + 8, 8); - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } else { - EVP_CIPHER_CTX_set_num(ctx, j); + GOST_cipher_ctx_set_num(ctx, j); return 1; } } @@ -985,59 +924,59 @@ static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, /* * block cipher current iv */ - gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); + gost_crypt_mesh(GOST_cipher_ctx_get_cipher_data(ctx), iv, buf); /* * xor next block of input text with it and output it */ /* * output this block */ - if (!EVP_CIPHER_CTX_encrypting(ctx)) + if (!GOST_cipher_ctx_encrypting(ctx)) memcpy(iv, in_ptr, 8); for (j = 0; j < 8; j++) { out_ptr[j] = buf[j] ^ in_ptr[j]; } /* Encrypt */ /* Next iv is next block of cipher text */ - if (EVP_CIPHER_CTX_encrypting(ctx)) + if (GOST_cipher_ctx_encrypting(ctx)) memcpy(iv, out_ptr, 8); } /* Process rest of buffer */ if (i < inl) { - gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); - if (!EVP_CIPHER_CTX_encrypting(ctx)) + gost_crypt_mesh(GOST_cipher_ctx_get_cipher_data(ctx), iv, buf); + if (!GOST_cipher_ctx_encrypting(ctx)) memcpy(buf + 8, in_ptr, inl - i); for (j = 0; i < inl; j++, i++) { out_ptr[j] = buf[j] ^ in_ptr[j]; } - EVP_CIPHER_CTX_set_num(ctx, j); - if (EVP_CIPHER_CTX_encrypting(ctx)) + GOST_cipher_ctx_set_num(ctx, j); + if (GOST_cipher_ctx_encrypting(ctx)) memcpy(buf + 8, out_ptr, j); } else { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } return 1; } -static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_cipher_do_cnt(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { const unsigned char *in_ptr = in; unsigned char *out_ptr = out; size_t i = 0; size_t j; - unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + unsigned char *buf = GOST_cipher_ctx_buf_noconst(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); /* process partial block if any */ - if (EVP_CIPHER_CTX_num(ctx)) { - for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; + if (GOST_cipher_ctx_num(ctx)) { + for (j = GOST_cipher_ctx_num(ctx), i = 0; j < 8 && i < inl; j++, i++, in_ptr++, out_ptr++) { *out_ptr = buf[j] ^ (*in_ptr); } if (j == 8) { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } else { - EVP_CIPHER_CTX_set_num(ctx, j); + GOST_cipher_ctx_set_num(ctx, j); return 1; } } @@ -1047,7 +986,7 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, * block cipher current iv */ /* Encrypt */ - gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); + gost_cnt_next(GOST_cipher_ctx_get_cipher_data(ctx), iv, buf); /* * xor next block of input text with it and output it */ @@ -1060,50 +999,50 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, } /* Process rest of buffer */ if (i < inl) { - gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); + gost_cnt_next(GOST_cipher_ctx_get_cipher_data(ctx), iv, buf); for (j = 0; i < inl; j++, i++) { out_ptr[j] = buf[j] ^ in_ptr[j]; } - EVP_CIPHER_CTX_set_num(ctx, j); + GOST_cipher_ctx_set_num(ctx, j); } else { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } return 1; } -/* Cleaning up of EVP_CIPHER_CTX */ -static int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) +/* Cleaning up of cipher context */ +static int gost_cipher_cleanup(GOST_cipher_ctx *ctx) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); EVP_MD_CTX_free(c->omac_ctx); gost_destroy(&(c->cctx)); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); + GOST_cipher_ctx_set_app_data(ctx, NULL); return 1; } -static int gost_magma_mgm_cleanup(EVP_CIPHER_CTX *c) +static int gost_magma_mgm_cleanup(GOST_cipher_ctx *c) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(c); if (mctx == NULL) return 0; gost_destroy(&mctx->ks.g_ks.cctx); OPENSSL_cleanse(&mctx->mgm, sizeof(mctx->mgm)); - EVP_CIPHER_CTX_set_app_data(c, NULL); + GOST_cipher_ctx_set_app_data(c, NULL); return 1; } -static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +static int gost_magma_mgm_ctrl(GOST_cipher_ctx *c, int type, int arg, void *ptr) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(c); unsigned char *buf, *iv; int ivlen, enc; switch (type) { case EVP_CTRL_INIT: - ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(c)); - iv = EVP_CIPHER_CTX_iv_noconst(c); + ivlen = GOST_cipher_iv_length(GOST_cipher_ctx_cipher(c)); + iv = GOST_cipher_ctx_iv_noconst(c); mctx->key_set = 0; mctx->iv_set = 0; mctx->ivlen = ivlen; @@ -1127,8 +1066,8 @@ static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) return 1; case EVP_CTRL_AEAD_SET_TAG: - buf = EVP_CIPHER_CTX_buf_noconst(c); - enc = EVP_CIPHER_CTX_encrypting(c); + buf = GOST_cipher_ctx_buf_noconst(c); + enc = GOST_cipher_ctx_encrypting(c); if (arg <= 0 || arg != 8 || enc) { GOSTerr(GOST_F_GOST_MAGMA_MGM_CTRL, GOST_R_INVALID_TAG_LENGTH); @@ -1139,8 +1078,8 @@ static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) return 1; case EVP_CTRL_AEAD_GET_TAG: - buf = EVP_CIPHER_CTX_buf_noconst(c); - enc = EVP_CIPHER_CTX_encrypting(c); + buf = GOST_cipher_ctx_buf_noconst(c); + enc = GOST_cipher_ctx_encrypting(c); if (arg <= 0 || arg > 8 || !enc || mctx->taglen < 0) { GOSTerr(GOST_F_GOST_MAGMA_MGM_CTRL, GOST_R_INVALID_TAG_LENGTH); @@ -1179,13 +1118,13 @@ static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) } /* Control function for gost cipher */ -static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +static int gost_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) { switch (type) { case EVP_CTRL_RAND_KEY: { if (RAND_priv_bytes - ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) { + ((unsigned char *)ptr, GOST_cipher_ctx_key_length(ctx)) <= 0) { GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR); return -1; } @@ -1213,7 +1152,7 @@ static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) case EVP_CTRL_SET_SBOX: if (ptr) { struct ossl_gost_cipher_ctx *c = - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); int nid; int cur_meshing; int ret; @@ -1241,7 +1180,7 @@ static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) case EVP_CTRL_KEY_MESH: { struct ossl_gost_cipher_ctx *c = - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); if (c == NULL) { return -1; @@ -1283,12 +1222,12 @@ int decrement_sequence(unsigned char *seq, int decrement) { } /* Control function for gost cipher */ -static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +static int magma_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) { switch (type) { case EVP_CTRL_RAND_KEY: if (RAND_priv_bytes - ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) { + ((unsigned char *)ptr, GOST_cipher_ctx_key_length(ctx)) <= 0) { GOSTerr(GOST_F_MAGMA_CIPHER_CTL, GOST_R_RNG_ERROR); return -1; } @@ -1296,7 +1235,7 @@ static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) case EVP_CTRL_KEY_MESH: { struct ossl_gost_cipher_ctx *c = - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); if (c == NULL) { return -1; @@ -1308,7 +1247,7 @@ static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) case EVP_CTRL_TLSTREE: { unsigned char newkey[32]; - int mode = EVP_CIPHER_CTX_mode(ctx); + int mode = GOST_cipher_ctx_mode(ctx); struct ossl_gost_cipher_ctx *ctr_ctx = NULL; gost_ctx *c = NULL; @@ -1318,7 +1257,7 @@ static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) if (mode != EVP_CIPH_CTR_MODE) return -1; - ctr_ctx = (struct ossl_gost_cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + ctr_ctx = (struct ossl_gost_cipher_ctx *)GOST_cipher_ctx_get_cipher_data(ctx); c = &(ctr_ctx->cctx); /* @@ -1338,15 +1277,15 @@ static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) if (gost_tlstree_magma_cbc((const unsigned char *)c->master_key, newkey, (const unsigned char *)seq, TLSTREE_MODE_NONE) > 0) { memset(adjusted_iv, 0, 8); - memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 4); + memcpy(adjusted_iv, GOST_cipher_ctx_original_iv(ctx), 4); for (j = 3, carry = 0; j >= 0; j--) { int adj_byte = adjusted_iv[j] + seq[j+4] + carry; carry = (adj_byte > 255) ? 1 : 0; adjusted_iv[j] = adj_byte & 0xFF; } - EVP_CIPHER_CTX_set_num(ctx, 0); - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 8); + GOST_cipher_ctx_set_num(ctx, 0); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), adjusted_iv, 8); magma_key(c, newkey); OPENSSL_cleanse(newkey, sizeof(newkey)); @@ -1361,20 +1300,20 @@ static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) return 1; } -static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +static int magma_cipher_ctl_acpkm_omac(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) { switch (type) { case EVP_CTRL_PROCESS_UNPROTECTED: { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); STACK_OF(X509_ATTRIBUTE) *x = ptr; return gost2015_process_unprotected_attributes(x, arg, MAGMA_MAC_MAX_SIZE, c->tag); } case EVP_CTRL_COPY: { - EVP_CIPHER_CTX *out = ptr; - struct ossl_gost_cipher_ctx *in_cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); - struct ossl_gost_cipher_ctx *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out); + GOST_cipher_ctx *out = ptr; + struct ossl_gost_cipher_ctx *in_cctx = GOST_cipher_ctx_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *out_cctx = GOST_cipher_ctx_get_cipher_data(out); if (in_cctx->omac_ctx == out_cctx->omac_ctx) { out_cctx->omac_ctx = EVP_MD_CTX_new(); @@ -1392,12 +1331,12 @@ static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, v } /* Set cipher parameters from ASN1 structure */ -static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +static int gost89_set_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) { int len = 0; unsigned char *buf = NULL; unsigned char *p = NULL; - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); ASN1_OCTET_STRING *os = NULL; if (!gcp) { @@ -1405,7 +1344,7 @@ static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) return 0; } if (!ASN1_OCTET_STRING_set - (gcp->iv, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx))) { + (gcp->iv, GOST_cipher_ctx_iv(ctx), GOST_cipher_ctx_iv_length(ctx))) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE); return 0; @@ -1437,12 +1376,12 @@ static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) } /* Store parameters into ASN1 structure */ -static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +static int gost89_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) { int len; GOST_CIPHER_PARAMS *gcp = NULL; unsigned char *p; - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); int nid; if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) { @@ -1455,7 +1394,7 @@ static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) params->value.sequence->length); len = gcp->iv->length; - if (len != EVP_CIPHER_CTX_iv_length(ctx)) { + if (len != GOST_cipher_ctx_iv_length(ctx)) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH); return -1; @@ -1474,8 +1413,8 @@ static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) return -1; } /*XXX missing non-const accessor */ - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), gcp->iv->data, - EVP_CIPHER_CTX_iv_length(ctx)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), gcp->iv->data, + GOST_cipher_ctx_iv_length(ctx)); GOST_CIPHER_PARAMS_free(gcp); @@ -1483,27 +1422,27 @@ static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) } #define MAGMA_UKM_LEN 12 -static int magma_set_asn1_parameters (EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +static int magma_set_asn1_parameters (GOST_cipher_ctx *ctx, ASN1_TYPE *params) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->key_meshing = 8192; - return gost2015_set_asn1_params(params, EVP_CIPHER_CTX_original_iv(ctx), 4, + return gost2015_set_asn1_params(params, GOST_cipher_ctx_original_iv(ctx), 4, c->kdf_seed); } -static int magma_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +static int magma_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) { - struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); unsigned char iv[16]; c->key_meshing = 8192; - if (gost2015_get_asn1_params(params, MAGMA_UKM_LEN, iv, 4, c->kdf_seed) < 0) + if (gost2015_get_asn1_params(params, MAGMA_UKM_LEN, iv, 4, c->kdf_seed) == 0) return -1; - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, sizeof(iv)); - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, sizeof(iv)); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), iv, sizeof(iv)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, sizeof(iv)); /* Key meshing 8 kb*/ c->key_meshing = 8192; diff --git a/gost_eng.c b/gost_eng.c index df70f6b18..24e91727e 100644 --- a/gost_eng.c +++ b/gost_eng.c @@ -18,6 +18,7 @@ #include "gost_lcl.h" #include "gost-engine.h" #include "gost_eng_digest.h" +#include "gost_eng_cipher.h" #include #include "gost_grasshopper_cipher.h" @@ -85,27 +86,27 @@ GOST_eng_digest *gost_digest_array[] = { &ENG_DIGEST_NAME(magma_ctracpkm_mac), }; -GOST_cipher *gost_cipher_array[] = { - &Gost28147_89_cipher, - &Gost28147_89_cnt_cipher, - &Gost28147_89_cnt_12_cipher, - &Gost28147_89_cbc_cipher, - &grasshopper_ecb_cipher, - &grasshopper_cbc_cipher, - &grasshopper_cfb_cipher, - &grasshopper_ofb_cipher, - &grasshopper_ctr_cipher, - &magma_ecb_cipher, - &grasshopper_mgm_cipher, - &magma_cbc_cipher, - &magma_ctr_cipher, - &magma_ctr_acpkm_cipher, - &magma_ctr_acpkm_omac_cipher, - &magma_mgm_cipher, - &grasshopper_ctr_acpkm_cipher, - &grasshopper_ctr_acpkm_omac_cipher, - &magma_kexp15_cipher, - &kuznyechik_kexp15_cipher, +GOST_eng_cipher *gost_cipher_array[] = { + &ENG_CIPHER_NAME(Gost28147_89_cipher), + &ENG_CIPHER_NAME(Gost28147_89_cnt_cipher), + &ENG_CIPHER_NAME(Gost28147_89_cnt_12_cipher), + &ENG_CIPHER_NAME(Gost28147_89_cbc_cipher), + &ENG_CIPHER_NAME(grasshopper_ecb_cipher), + &ENG_CIPHER_NAME(grasshopper_cbc_cipher), + &ENG_CIPHER_NAME(grasshopper_cfb_cipher), + &ENG_CIPHER_NAME(grasshopper_ofb_cipher), + &ENG_CIPHER_NAME(grasshopper_ctr_cipher), + &ENG_CIPHER_NAME(magma_ecb_cipher), + &ENG_CIPHER_NAME(grasshopper_mgm_cipher), + &ENG_CIPHER_NAME(magma_cbc_cipher), + &ENG_CIPHER_NAME(magma_ctr_cipher), + &ENG_CIPHER_NAME(magma_ctr_acpkm_cipher), + &ENG_CIPHER_NAME(magma_ctr_acpkm_omac_cipher), + &ENG_CIPHER_NAME(magma_mgm_cipher), + &ENG_CIPHER_NAME(grasshopper_ctr_acpkm_cipher), + &ENG_CIPHER_NAME(grasshopper_ctr_acpkm_omac_cipher), + &ENG_CIPHER_NAME(magma_kexp15_cipher), + &ENG_CIPHER_NAME(kuznyechik_kexp15_cipher), }; static struct gost_meth_minfo { @@ -232,13 +233,13 @@ static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, *nids = n; for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) - *n++ = gost_cipher_array[i]->nid; + *n++ = GOST_eng_cipher_nid(gost_cipher_array[i]); 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]); + if (nid == GOST_eng_cipher_nid(gost_cipher_array[i])) { + *cipher = GOST_eng_cipher_init(gost_cipher_array[i]); return 1; } *cipher = NULL; @@ -308,7 +309,7 @@ static int gost_engine_destroy(ENGINE* e) { for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) GOST_eng_digest_deinit(gost_digest_array[i]); for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) - GOST_deinit_cipher(gost_cipher_array[i]); + GOST_eng_cipher_deinit(gost_cipher_array[i]); gost_param_free(); @@ -481,7 +482,7 @@ static int bind_gost_engine(ENGINE* e) { int i; for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) { - if (!EVP_add_cipher(GOST_init_cipher(gost_cipher_array[i]))) + if (!EVP_add_cipher(GOST_eng_cipher_init(gost_cipher_array[i]))) goto end; } diff --git a/gost_eng_cipher.c b/gost_eng_cipher.c new file mode 100644 index 000000000..4d79aa9ca --- /dev/null +++ b/gost_eng_cipher.c @@ -0,0 +1,233 @@ +#include + +#include +#include +#include +#include "gost_lcl.h" +#include "gost_eng_cipher.h" + +struct gost_eng_cipher_st { + GOST_cipher *cipher; + EVP_CIPHER *evp_cipher; +}; + +/* Engine backend helpers */ +int GOST_cipher_init_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + const unsigned char *key, const unsigned char *iv, + int enc); +int GOST_cipher_do_cipher_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + unsigned char *out, const unsigned char *in, + size_t inl); +int GOST_cipher_cleanup_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx); +int GOST_cipher_ctrl_evp(const GOST_cipher *cipher, EVP_CIPHER_CTX *ctx, + int type, int arg, void *ptr); +int GOST_cipher_set_asn1_parameters_evp(const GOST_cipher *cipher, + EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params); +int GOST_cipher_get_asn1_parameters_evp(const GOST_cipher *cipher, + EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params); + +int gost_engine_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +int gost_engine_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +int gost_engine_cipher_cleanup(EVP_CIPHER_CTX *ctx); +int gost_engine_cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int gost_engine_cipher_set_asn1_parameters(EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params); +int gost_engine_cipher_get_asn1_parameters(EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params); + +static EVP_CIPHER *GOST_init_cipher(GOST_cipher *c) +{ + /* Some sanity checking. */ + int flags = GOST_cipher_flags(c) | EVP_CIPH_CUSTOM_COPY; + int block_size = GOST_cipher_block_size(c); + + switch (flags & EVP_CIPH_MODE) { + case EVP_CIPH_CBC_MODE: + case EVP_CIPH_ECB_MODE: + case EVP_CIPH_WRAP_MODE: + OPENSSL_assert(block_size != 1); + OPENSSL_assert(!(flags & EVP_CIPH_NO_PADDING)); + break; + default: + OPENSSL_assert(block_size == 1); + OPENSSL_assert(flags & EVP_CIPH_NO_PADDING); + } + + if (GOST_cipher_iv_length(c) != 0) + OPENSSL_assert(flags & EVP_CIPH_CUSTOM_IV); + else + OPENSSL_assert(!(flags & EVP_CIPH_CUSTOM_IV)); + + EVP_CIPHER *cipher = NULL; + if (!(cipher = EVP_CIPHER_meth_new(GOST_cipher_nid(c), block_size, + GOST_cipher_key_length(c))) + || !EVP_CIPHER_meth_set_iv_length(cipher, GOST_cipher_iv_length(c)) + || !EVP_CIPHER_meth_set_flags(cipher, flags) + || !EVP_CIPHER_meth_set_init(cipher, gost_engine_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(cipher, gost_engine_cipher_do_cipher) + || !EVP_CIPHER_meth_set_cleanup(cipher, gost_engine_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, GOST_cipher_ctx_size(c)) + || !EVP_CIPHER_meth_set_set_asn1_params(cipher, gost_engine_cipher_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(cipher, gost_engine_cipher_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(cipher, gost_engine_cipher_ctrl)) { + EVP_CIPHER_meth_free(cipher); + cipher = NULL; + } + return cipher; +} + +/* Wrapper functions to expose GOST_cipher descriptors as EVP_CIPHER objects + * cached in GOST_eng_cipher structures. */ +EVP_CIPHER *GOST_eng_cipher_init(GOST_eng_cipher *c) +{ + if (c->evp_cipher) + return c->evp_cipher; + + EVP_CIPHER *m = GOST_init_cipher(c->cipher); + c->evp_cipher = m; + return m; +} + +void GOST_eng_cipher_deinit(GOST_eng_cipher *c) +{ + EVP_CIPHER_meth_free(c->evp_cipher); + c->evp_cipher = NULL; +} + +int GOST_eng_cipher_nid(const GOST_eng_cipher *c) +{ + return GOST_cipher_nid(c->cipher); +} + +static const GOST_cipher *gost_cipher_from_nid(int nid) +{ + GOST_cipher *list[] = { + &Gost28147_89_cipher, + &Gost28147_89_cbc_cipher, + &Gost28147_89_cnt_cipher, + &Gost28147_89_cnt_12_cipher, + &magma_ctr_cipher, + &magma_ctr_acpkm_cipher, + &magma_ctr_acpkm_omac_cipher, + &magma_ecb_cipher, + &magma_cbc_cipher, + &magma_mgm_cipher, + &grasshopper_ecb_cipher, + &grasshopper_cbc_cipher, + &grasshopper_cfb_cipher, + &grasshopper_ofb_cipher, + &grasshopper_ctr_cipher, + &grasshopper_mgm_cipher, + &grasshopper_ctr_acpkm_cipher, + &grasshopper_ctr_acpkm_omac_cipher, + &magma_kexp15_cipher, + &kuznyechik_kexp15_cipher + }; + size_t i; + + for (i = 0; i < sizeof(list) / sizeof(list[0]); i++) { + if (GOST_cipher_nid(list[i]) == nid) + return list[i]; + } + return NULL; +} + +static const GOST_cipher *gost_engine_cipher_desc(EVP_CIPHER_CTX *ctx) +{ + const EVP_CIPHER *cipher; + + if (ctx == NULL) + return NULL; + cipher = EVP_CIPHER_CTX_cipher(ctx); + if (cipher == NULL) + return NULL; + + return gost_cipher_from_nid(EVP_CIPHER_nid(cipher)); +} + +int gost_engine_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_init_evp(cipher, ctx, key, iv, enc); +} + +int gost_engine_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_do_cipher_evp(cipher, ctx, out, in, inl); +} + +int gost_engine_cipher_cleanup(EVP_CIPHER_CTX *ctx) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_cleanup_evp(cipher, ctx); +} + +int gost_engine_cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_ctrl_evp(cipher, ctx, type, arg, ptr); +} + +int gost_engine_cipher_set_asn1_parameters(EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_set_asn1_parameters_evp(cipher, ctx, params); +} + +int gost_engine_cipher_get_asn1_parameters(EVP_CIPHER_CTX *ctx, + ASN1_TYPE *params) +{ + const GOST_cipher *cipher = gost_engine_cipher_desc(ctx); + + if (cipher == NULL) + return 0; + return GOST_cipher_get_asn1_parameters_evp(cipher, ctx, params); +} + +/* Define engine-exposed instances for all GOST ciphers */ +#define DEF_CIPHER(name) \ + GOST_eng_cipher ENG_CIPHER_NAME(name) = { &name, NULL } + +DEF_CIPHER(Gost28147_89_cipher); +DEF_CIPHER(Gost28147_89_cbc_cipher); +DEF_CIPHER(Gost28147_89_cnt_cipher); +DEF_CIPHER(Gost28147_89_cnt_12_cipher); +DEF_CIPHER(magma_ctr_cipher); +DEF_CIPHER(magma_ctr_acpkm_cipher); +DEF_CIPHER(magma_ctr_acpkm_omac_cipher); +DEF_CIPHER(magma_ecb_cipher); +DEF_CIPHER(magma_cbc_cipher); +DEF_CIPHER(magma_mgm_cipher); +DEF_CIPHER(grasshopper_ecb_cipher); +DEF_CIPHER(grasshopper_cbc_cipher); +DEF_CIPHER(grasshopper_cfb_cipher); +DEF_CIPHER(grasshopper_ofb_cipher); +DEF_CIPHER(grasshopper_ctr_cipher); +DEF_CIPHER(grasshopper_mgm_cipher); +DEF_CIPHER(grasshopper_ctr_acpkm_cipher); +DEF_CIPHER(grasshopper_ctr_acpkm_omac_cipher); +DEF_CIPHER(magma_kexp15_cipher); +DEF_CIPHER(kuznyechik_kexp15_cipher); diff --git a/gost_eng_cipher.h b/gost_eng_cipher.h new file mode 100644 index 000000000..6fcea10da --- /dev/null +++ b/gost_eng_cipher.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include "gost_lcl.h" + +struct gost_eng_cipher_st; +typedef struct gost_eng_cipher_st GOST_eng_cipher; + +EVP_CIPHER *GOST_eng_cipher_init(GOST_eng_cipher *c); +void GOST_eng_cipher_deinit(GOST_eng_cipher *c); +int GOST_eng_cipher_nid(const GOST_eng_cipher *c); + +#define STRCAT_IMPL(prefix, suffix) prefix##suffix +#define STRCAT(prefix, suffix) STRCAT_IMPL(prefix, suffix) +#define ENG_CIPHER_NAME(GOST_CIPHER_NAME) STRCAT(GOST_CIPHER_NAME, _eng_cipher) + +extern GOST_eng_cipher ENG_CIPHER_NAME(Gost28147_89_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(Gost28147_89_cbc_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(Gost28147_89_cnt_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(Gost28147_89_cnt_12_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_ctr_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_ctr_acpkm_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_ctr_acpkm_omac_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_ecb_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_cbc_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_mgm_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_ecb_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_cbc_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_cfb_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_ofb_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_ctr_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_mgm_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_ctr_acpkm_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(grasshopper_ctr_acpkm_omac_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(magma_kexp15_cipher); +extern GOST_eng_cipher ENG_CIPHER_NAME(kuznyechik_kexp15_cipher); + diff --git a/gost_gost2015.c b/gost_gost2015.c index e51de3634..54b6589ea 100644 --- a/gost_gost2015.c +++ b/gost_gost2015.c @@ -13,9 +13,9 @@ #include #include -int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size, - unsigned char *encrypted_mac, - int (*do_cipher) (EVP_CIPHER_CTX *ctx, +int gost2015_final_call(GOST_cipher_ctx *ctx, EVP_MD_CTX *omac_ctx, + size_t mac_size, unsigned char *encrypted_mac, + int (*do_cipher) (GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl)) @@ -23,7 +23,7 @@ int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_si unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE]; memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE); - if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (GOST_cipher_ctx_encrypting(ctx)) { EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size); if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) { diff --git a/gost_gost2015.h b/gost_gost2015.h index 37b94d087..df443119c 100644 --- a/gost_gost2015.h +++ b/gost_gost2015.h @@ -59,12 +59,12 @@ typedef struct { int tlstree_mode; } gost_mgm_ctx; -int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size, - unsigned char *encrypted_mac, - int (*do_cipher) (EVP_CIPHER_CTX *ctx, - unsigned char *out, - const unsigned char *in, - size_t inl)); +int gost2015_final_call(GOST_cipher_ctx *ctx, EVP_MD_CTX *omac_ctx, + size_t mac_size, unsigned char *encrypted_mac, + int (*do_cipher) (GOST_cipher_ctx *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)); /* IV is expected to be 16 bytes*/ int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size, diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 34de45c78..147d4b6d2 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -18,6 +18,7 @@ #include "gost_lcl.h" #include "gost_tls12_additional.h" #include "e_gost_err.h" +#include "gost_cipher_details.h" enum GRASSHOPPER_CIPHER_TYPE { GRASSHOPPER_CIPHER_ECB = 0, @@ -234,16 +235,16 @@ gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c) grasshopper_zero128(&ctx->partial_buffer); } -static int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx, +static int gost_grasshopper_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); - if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) { - EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx)); + if (GOST_cipher_ctx_get_app_data(ctx) == NULL) { + GOST_cipher_ctx_set_app_data(ctx, GOST_cipher_ctx_get_cipher_data(ctx)); if (enc && c->type == GRASSHOPPER_CIPHER_CTRACPKM) { - gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *ctr = GOST_cipher_ctx_get_cipher_data(ctx); if (init_zero_kdf_seed(ctr->kdf_seed) == 0) return -1; } @@ -255,12 +256,12 @@ static int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx, } if (iv != NULL) { - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, - EVP_CIPHER_CTX_iv_length(ctx)); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, + GOST_cipher_ctx_iv_length(ctx)); } - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), - EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), + GOST_cipher_ctx_original_iv(ctx), GOST_cipher_ctx_iv_length(ctx)); grasshopper_zero128(&c->buffer); @@ -268,54 +269,54 @@ static int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx, } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX *ctx, const unsigned char +gost_grasshopper_cipher_init_ecb(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->type = GRASSHOPPER_CIPHER_ECB; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char +gost_grasshopper_cipher_init_cbc(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->type = GRASSHOPPER_CIPHER_CBC; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } static GRASSHOPPER_INLINE -int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX *ctx, const unsigned char +int gost_grasshopper_cipher_init_ofb(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->type = GRASSHOPPER_CIPHER_OFB; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX *ctx, const unsigned char +gost_grasshopper_cipher_init_cfb(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->type = GRASSHOPPER_CIPHER_CFB; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx, const unsigned char +gost_grasshopper_cipher_init_ctr(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); c->c.type = GRASSHOPPER_CIPHER_CTR; - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); grasshopper_zero128(&c->partial_buffer); @@ -323,32 +324,32 @@ gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx, const unsigned char } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX +gost_grasshopper_cipher_init_ctracpkm(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); /* NB: setting type makes EVP do_cipher callback useless */ c->c.type = GRASSHOPPER_CIPHER_CTRACPKM; - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); c->section_size = 4096; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_ctracpkm_omac(EVP_CIPHER_CTX +gost_grasshopper_cipher_init_ctracpkm_omac(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); /* NB: setting type makes EVP do_cipher callback useless */ c->c.type = GRASSHOPPER_CIPHER_CTRACPKMOMAC; - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); c->section_size = 4096; if (key) { @@ -474,17 +475,17 @@ static void gf128_mul_uint64 (uint64_t *result, uint64_t *arg1, uint64_t *arg2) } static GRASSHOPPER_INLINE int -gost_grasshopper_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key, +gost_grasshopper_cipher_init_mgm(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(ctx); int bl; if (!iv && !key) return 1; if (key) { - bl = EVP_CIPHER_CTX_iv_length(ctx); + bl = GOST_cipher_ctx_iv_length(ctx); gost_grasshopper_cipher_key(&mctx->ks.gh_ks, key); gost_grasshopper_master_key(&mctx->ks.gh_ks, key); gost_mgm128_init(&mctx->mgm, &mctx->ks, @@ -514,12 +515,12 @@ gost_grasshopper_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } -static int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_ecb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { gost_grasshopper_cipher_ctx *c = - (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); - bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx); + (gost_grasshopper_cipher_ctx *) GOST_cipher_ctx_get_cipher_data(ctx); + bool encrypting = (bool) GOST_cipher_ctx_encrypting(ctx); const unsigned char *current_in = in; unsigned char *current_out = out; size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE; @@ -544,13 +545,13 @@ static int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *ou return 1; } -static int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_cbc(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { gost_grasshopper_cipher_ctx *c = - (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx); + (gost_grasshopper_cipher_ctx *) GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + bool encrypting = (bool) GOST_cipher_ctx_encrypting(ctx); const unsigned char *current_in = in; unsigned char *current_out = out; size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE; @@ -605,17 +606,17 @@ static void ctr128_inc(unsigned char *counter) inc_counter(counter, 16); } -static int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_ctr(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { gost_grasshopper_cipher_ctx_ctr *c = (gost_grasshopper_cipher_ctx_ctr *) - EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); const unsigned char *current_in = in; unsigned char *current_out = out; grasshopper_w128_t *currentInputBlock; grasshopper_w128_t *currentOutputBlock; - unsigned int n = EVP_CIPHER_CTX_num(ctx); + unsigned int n = GOST_cipher_ctx_num(ctx); size_t lasted = inl; size_t i; size_t blocks; @@ -627,7 +628,7 @@ static int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *ou --lasted; n = (n + 1) % GRASSHOPPER_BLOCK_SIZE; } - EVP_CIPHER_CTX_set_num(ctx, n); + GOST_cipher_ctx_set_num(ctx, n); blocks = lasted / GRASSHOPPER_BLOCK_SIZE; iv_buffer = (grasshopper_w128_t *) iv; @@ -655,7 +656,7 @@ static int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *ou currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i]; } - EVP_CIPHER_CTX_set_num(ctx, i); + GOST_cipher_ctx_set_num(ctx, i); ctr128_inc(iv_buffer->b); } @@ -674,14 +675,14 @@ static inline void apply_acpkm_grasshopper(gost_grasshopper_cipher_ctx_ctr * /* If meshing is not configured via ctrl (setting section_size) * this function works exactly like plain ctr */ -static int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx, +static int gost_grasshopper_cipher_do_ctracpkm(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - unsigned int num = EVP_CIPHER_CTX_num(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + unsigned int num = GOST_cipher_ctx_num(ctx); size_t blocks, i, lasted = inl; grasshopper_w128_t tmp; @@ -720,20 +721,20 @@ static int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx, ctr128_inc(iv); num += lasted; } - EVP_CIPHER_CTX_set_num(ctx, num); + GOST_cipher_ctx_set_num(ctx, num); return inl; } -static int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx, +static int gost_grasshopper_cipher_do_ctracpkm_omac(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { int result; - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); /* As in and out can be the same pointer, process unencrypted here */ - if (EVP_CIPHER_CTX_encrypting(ctx)) + if (GOST_cipher_ctx_encrypting(ctx)) EVP_DigestSignUpdate(c->omac_ctx, in, inl); if (in == NULL && inl == 0) { /* Final call */ @@ -747,7 +748,7 @@ static int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx, result = gost_grasshopper_cipher_do_ctracpkm(ctx, out, in, inl); /* As in and out can be the same pointer, process decrypted here */ - if (!EVP_CIPHER_CTX_encrypting(ctx)) + if (!GOST_cipher_ctx_encrypting(ctx)) EVP_DigestSignUpdate(c->omac_ctx, out, inl); return result; @@ -755,12 +756,12 @@ static int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx, -static int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_mgm(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); - int enc = EVP_CIPHER_CTX_encrypting(ctx); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(ctx); + int enc = GOST_cipher_ctx_encrypting(ctx); /* If not set up, return error */ if (!mctx->key_set) { @@ -791,13 +792,13 @@ static int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *ou if (mctx->taglen < 0) return -1; if (gost_mgm128_finish(&mctx->mgm, - EVP_CIPHER_CTX_buf_noconst(ctx), + GOST_cipher_ctx_buf_noconst(ctx), mctx->taglen) != 0) return -1; mctx->iv_set = 0; return 0; } - gost_mgm128_tag(&mctx->mgm, EVP_CIPHER_CTX_buf_noconst(ctx), 16); + gost_mgm128_tag(&mctx->mgm, GOST_cipher_ctx_buf_noconst(ctx), 16); mctx->taglen = 16; /* Don't reuse the IV */ mctx->iv_set = 0; @@ -820,16 +821,16 @@ static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx * ctx, memcpy(iv, buf, 16); } -static int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_ofb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { gost_grasshopper_cipher_ctx *c = (gost_grasshopper_cipher_ctx *) - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); const unsigned char *in_ptr = in; unsigned char *out_ptr = out; - unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - int num = EVP_CIPHER_CTX_num(ctx); + unsigned char *buf = GOST_cipher_ctx_buf_noconst(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + int num = GOST_cipher_ctx_num(ctx); size_t i = 0; size_t j; @@ -840,9 +841,9 @@ static int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *ou *out_ptr = buf[j] ^ (*in_ptr); } if (j == GRASSHOPPER_BLOCK_SIZE) { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } else { - EVP_CIPHER_CTX_set_num(ctx, (int)j); + GOST_cipher_ctx_set_num(ctx, (int)j); return 1; } } @@ -876,25 +877,25 @@ static int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *ou for (j = 0; i < inl; j++, i++) { out_ptr[j] = buf[j] ^ in_ptr[j]; } - EVP_CIPHER_CTX_set_num(ctx, (int)j); + GOST_cipher_ctx_set_num(ctx, (int)j); } else { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } return 1; } -static int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int gost_grasshopper_cipher_do_cfb(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { gost_grasshopper_cipher_ctx *c = - (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); + (gost_grasshopper_cipher_ctx *) GOST_cipher_ctx_get_cipher_data(ctx); const unsigned char *in_ptr = in; unsigned char *out_ptr = out; - unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); - bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx); - int num = EVP_CIPHER_CTX_num(ctx); + unsigned char *buf = GOST_cipher_ctx_buf_noconst(ctx); + unsigned char *iv = GOST_cipher_ctx_iv_noconst(ctx); + bool encrypting = (bool) GOST_cipher_ctx_encrypting(ctx); + int num = GOST_cipher_ctx_num(ctx); size_t i = 0; size_t j = 0; @@ -912,9 +913,9 @@ static int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *ou } if (j == GRASSHOPPER_BLOCK_SIZE) { memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE); - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } else { - EVP_CIPHER_CTX_set_num(ctx, (int)j); + GOST_cipher_ctx_set_num(ctx, (int)j); return 1; } } @@ -959,52 +960,52 @@ static int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *ou for (j = 0; i < inl; j++, i++) { out_ptr[j] = buf[j] ^ in_ptr[j]; } - EVP_CIPHER_CTX_set_num(ctx, (int)j); + GOST_cipher_ctx_set_num(ctx, (int)j); if (encrypting) { memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j); } } else { - EVP_CIPHER_CTX_set_num(ctx, 0); + GOST_cipher_ctx_set_num(ctx, 0); } return 1; } -static int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX *ctx) +static int gost_grasshopper_cipher_cleanup(GOST_cipher_ctx *ctx) { gost_grasshopper_cipher_ctx *c = - (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); + (gost_grasshopper_cipher_ctx *) GOST_cipher_ctx_get_cipher_data(ctx); if (!c) return 1; - if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) + if (GOST_cipher_ctx_mode(ctx) == EVP_CIPH_CTR_MODE) gost_grasshopper_cipher_destroy_ctr(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); + GOST_cipher_ctx_set_app_data(ctx, NULL); return 1; } -static int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +static int gost_grasshopper_set_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) { - if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) { - gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx); + if (GOST_cipher_ctx_mode(ctx) == EVP_CIPH_CTR_MODE) { + gost_grasshopper_cipher_ctx_ctr *ctr = GOST_cipher_ctx_get_cipher_data(ctx); /* CMS implies 256kb section_size */ ctr->section_size = 256*1024; return gost2015_set_asn1_params(params, - EVP_CIPHER_CTX_original_iv(ctx), 8, ctr->kdf_seed); + GOST_cipher_ctx_original_iv(ctx), 8, ctr->kdf_seed); } return 0; } static GRASSHOPPER_INLINE int -gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) +gost_grasshopper_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) { - if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) { - gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx); + if (GOST_cipher_ctx_mode(ctx) == EVP_CIPH_CTR_MODE) { + gost_grasshopper_cipher_ctx_ctr *ctr = GOST_cipher_ctx_get_cipher_data(ctx); int iv_len = 16; unsigned char iv[16]; @@ -1013,8 +1014,8 @@ gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) return 0; } - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, iv_len); - memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, iv_len); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), iv, iv_len); + memcpy((unsigned char *)GOST_cipher_ctx_original_iv(ctx), iv, iv_len); /* CMS implies 256kb section_size */ ctr->section_size = 256*1024; @@ -1023,30 +1024,30 @@ gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) return 0; } -static int gost_grasshopper_mgm_cleanup(EVP_CIPHER_CTX *c) +static int gost_grasshopper_mgm_cleanup(GOST_cipher_ctx *c) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(c); if (mctx == NULL) return 0; gost_grasshopper_cipher_destroy(&mctx->ks.gh_ks); OPENSSL_cleanse(&mctx->mgm, sizeof(mctx->mgm)); - if (mctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) + if (mctx->iv != GOST_cipher_ctx_iv_noconst(c)) OPENSSL_free(mctx->iv); return 1; } -static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +static int gost_grasshopper_mgm_ctrl(GOST_cipher_ctx *c, int type, int arg, void *ptr) { gost_mgm_ctx *mctx = - (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c); + (gost_mgm_ctx *)GOST_cipher_ctx_get_cipher_data(c); unsigned char *buf, *iv; int ivlen, enc; switch (type) { case EVP_CTRL_INIT: - ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(c)); - iv = EVP_CIPHER_CTX_iv_noconst(c); + ivlen = GOST_cipher_iv_length(GOST_cipher_ctx_cipher(c)); + iv = GOST_cipher_ctx_iv_noconst(c); mctx->key_set = 0; mctx->iv_set = 0; mctx->ivlen = ivlen; @@ -1070,8 +1071,8 @@ static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void return 1; case EVP_CTRL_AEAD_SET_TAG: - buf = EVP_CIPHER_CTX_buf_noconst(c); - enc = EVP_CIPHER_CTX_encrypting(c); + buf = GOST_cipher_ctx_buf_noconst(c); + enc = GOST_cipher_ctx_encrypting(c); if (arg <= 0 || arg != 16 || enc) { GOSTerr(GOST_F_GOST_GRASSHOPPER_MGM_CTRL, GOST_R_INVALID_TAG_LENGTH); @@ -1082,8 +1083,8 @@ static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void return 1; case EVP_CTRL_AEAD_GET_TAG: - buf = EVP_CIPHER_CTX_buf_noconst(c); - enc = EVP_CIPHER_CTX_encrypting(c); + buf = GOST_cipher_ctx_buf_noconst(c); + enc = GOST_cipher_ctx_encrypting(c); if (arg <= 0 || arg > 16 || !enc || mctx->taglen < 0) { GOSTerr(GOST_F_GOST_GRASSHOPPER_MGM_CTRL, GOST_R_INVALID_TAG_LENGTH); @@ -1121,12 +1122,12 @@ static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void } } -static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +static int gost_grasshopper_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) { switch (type) { case EVP_CTRL_RAND_KEY:{ if (RAND_priv_bytes - ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) { + ((unsigned char *)ptr, GOST_cipher_ctx_key_length(ctx)) <= 0) { GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, GOST_R_RNG_ERROR); return -1; } @@ -1134,7 +1135,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v } case EVP_CTRL_KEY_MESH:{ gost_grasshopper_cipher_ctx_ctr *c = - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); if ((c->c.type != GRASSHOPPER_CIPHER_CTRACPKM && c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC) || (arg == 0) @@ -1146,7 +1147,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v case EVP_CTRL_TLSTREE: { unsigned char newkey[32]; - int mode = EVP_CIPHER_CTX_mode(ctx); + int mode = GOST_cipher_ctx_mode(ctx); gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL; gost_grasshopper_cipher_ctx *c = NULL; @@ -1157,7 +1158,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v return -1; ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *) - EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_cipher_ctx_get_cipher_data(ctx); c = &(ctr_ctx->c); /* @@ -1178,15 +1179,15 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v if (gost_tlstree_grasshopper_cbc(c->master_key.k.b, newkey, (const unsigned char *)seq, TLSTREE_MODE_NONE) > 0) { memset(adjusted_iv, 0, 16); - memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8); + memcpy(adjusted_iv, GOST_cipher_ctx_original_iv(ctx), 8); for(j=7,carry=0; j>=0; j--) { int adj_byte = adjusted_iv[j]+seq[j]+carry; carry = (adj_byte > 255) ? 1 : 0; adjusted_iv[j] = adj_byte & 0xFF; } - EVP_CIPHER_CTX_set_num(ctx, 0); - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 16); + GOST_cipher_ctx_set_num(ctx, 0); + memcpy(GOST_cipher_ctx_iv_noconst(ctx), adjusted_iv, 16); gost_grasshopper_cipher_key(c, newkey); OPENSSL_cleanse(newkey, sizeof(newkey)); @@ -1201,7 +1202,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v int taglen = arg; unsigned char *tag = ptr; - gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); if (c->c.type != GRASSHOPPER_CIPHER_MGM) return -1; @@ -1222,7 +1223,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v case EVP_CTRL_PROCESS_UNPROTECTED: { STACK_OF(X509_ATTRIBUTE) *x = ptr; - gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *c = GOST_cipher_ctx_get_cipher_data(ctx); if (c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC) return -1; @@ -1230,10 +1231,10 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v return gost2015_process_unprotected_attributes(x, arg, KUZNYECHIK_MAC_MAX_SIZE, c->tag); } case EVP_CTRL_COPY: { - EVP_CIPHER_CTX *out = ptr; + GOST_cipher_ctx *out = ptr; - gost_grasshopper_cipher_ctx_ctr *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out); - gost_grasshopper_cipher_ctx_ctr *in_cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); + gost_grasshopper_cipher_ctx_ctr *out_cctx = GOST_cipher_ctx_get_cipher_data(out); + gost_grasshopper_cipher_ctx_ctr *in_cctx = GOST_cipher_ctx_get_cipher_data(ctx); if (in_cctx->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC) return -1; diff --git a/gost_grasshopper_cipher.h b/gost_grasshopper_cipher.h index f6ca04836..6c47a0b96 100644 --- a/gost_grasshopper_cipher.h +++ b/gost_grasshopper_cipher.h @@ -13,6 +13,7 @@ extern "C" { #endif #include "gost_grasshopper_defines.h" +#include "gost_cipher_ctx.h" #include "gost_lcl.h" #include @@ -42,71 +43,71 @@ static void gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx* c, const ui static void gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx* c); -static int gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_ecb(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_cbc(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_ofb(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_cfb(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_ctr(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_ctracpkm(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_ctracpkm_omac(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_ctracpkm_omac(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init_mgm(EVP_CIPHER_CTX* ctx, +static int gost_grasshopper_cipher_init_mgm(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_init(EVP_CIPHER_CTX* ctx, const unsigned char* key, +static int gost_grasshopper_cipher_init(GOST_cipher_ctx* ctx, const unsigned char* key, const unsigned char* iv, int enc); -static int gost_grasshopper_cipher_do(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_ecb(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_cbc(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_ofb(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_cfb(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_ctr(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_ctracpkm(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_ctracpkm_omac(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX* ctx, unsigned char* out, +static int gost_grasshopper_cipher_do_mgm(GOST_cipher_ctx* ctx, unsigned char* out, const unsigned char* in, size_t inl); -static int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX* ctx); +static int gost_grasshopper_cipher_cleanup(GOST_cipher_ctx* ctx); -static int gost_grasshopper_mgm_cleanup(EVP_CIPHER_CTX *c); +static int gost_grasshopper_mgm_cleanup(GOST_cipher_ctx *c); -static int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params); +static int gost_grasshopper_set_asn1_parameters(GOST_cipher_ctx* ctx, ASN1_TYPE* params); -static int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params); +static int gost_grasshopper_get_asn1_parameters(GOST_cipher_ctx* ctx, ASN1_TYPE* params); -static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX* ctx, int type, int arg, void* ptr); +static int gost_grasshopper_cipher_ctl(GOST_cipher_ctx* ctx, int type, int arg, void* ptr); -static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +static int gost_grasshopper_mgm_ctrl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr); #if defined(__cplusplus) } diff --git a/gost_keyexpimp.c b/gost_keyexpimp.c index fee04bd88..056b1ec26 100644 --- a/gost_keyexpimp.c +++ b/gost_keyexpimp.c @@ -16,6 +16,7 @@ #include "gost_grasshopper_cipher.h" #include "gost_tls12_additional.h" #include "e_gost_err.h" +#include "gost_cipher_details.h" #define GOST_WRAP_FLAGS EVP_CIPH_CTRL_INIT | EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_FLAG_DEFAULT_ASN1 @@ -34,10 +35,10 @@ typedef struct { size_t wrap_count; } GOST_WRAP_CTX; -static int magma_wrap_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int magma_wrap_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - GOST_WRAP_CTX *cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_WRAP_CTX *cctx = GOST_cipher_ctx_get_cipher_data(ctx); memset(cctx->wrapped, 0, MAX_WRAPPED_KEY_LEN); cctx->wrap_count = 0; @@ -52,11 +53,11 @@ static int magma_wrap_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } -static int magma_wrap_do(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int magma_wrap_do(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - GOST_WRAP_CTX *cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); - int enc = EVP_CIPHER_CTX_encrypting(ctx) ? 1 : 0; + GOST_WRAP_CTX *cctx = GOST_cipher_ctx_get_cipher_data(ctx); + int enc = GOST_cipher_ctx_encrypting(ctx) ? 1 : 0; if (out == NULL) return GOSTKEYLEN; @@ -87,10 +88,10 @@ static int magma_wrap_do(EVP_CIPHER_CTX *ctx, unsigned char *out, } } -static int kuznyechik_wrap_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int kuznyechik_wrap_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - GOST_WRAP_CTX *cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); + GOST_WRAP_CTX *cctx = GOST_cipher_ctx_get_cipher_data(ctx); memset(cctx->wrapped, 0, KUZNYECHIK_WRAPPED_KEY_LEN); cctx->wrap_count = 0; @@ -105,11 +106,11 @@ static int kuznyechik_wrap_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } -static int kuznyechik_wrap_do(EVP_CIPHER_CTX *ctx, unsigned char *out, +static int kuznyechik_wrap_do(GOST_cipher_ctx *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - GOST_WRAP_CTX *cctx = EVP_CIPHER_CTX_get_cipher_data(ctx); - int enc = EVP_CIPHER_CTX_encrypting(ctx) ? 1 : 0; + GOST_WRAP_CTX *cctx = GOST_cipher_ctx_get_cipher_data(ctx); + int enc = GOST_cipher_ctx_encrypting(ctx) ? 1 : 0; if (out == NULL) return GOSTKEYLEN; @@ -140,12 +141,12 @@ static int kuznyechik_wrap_do(EVP_CIPHER_CTX *ctx, unsigned char *out, } } -static int wrap_ctrl (EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +static int wrap_ctrl (GOST_cipher_ctx *ctx, int type, int arg, void *ptr) { switch(type) { case EVP_CTRL_INIT: - EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + GOST_cipher_ctx_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); return 1; default: return -2; diff --git a/gost_lcl.h b/gost_lcl.h index f53982076..9a4e851e7 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -21,6 +21,7 @@ # include "gost89.h" # include "gosthash.h" # include "gost_digest.h" +# include "gost_cipher.h" /* * This definitions are added in the patch to OpenSSL 3.4.2 version to support @@ -311,30 +312,6 @@ BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey); /* Decrements 8-byte sequence */ int decrement_sequence(unsigned char *seq, int decrement); -/* Struct describing cipher and used for init/deinit.*/ -struct gost_cipher_st { - struct gost_cipher_st *template; /* template struct */ - int nid; - EVP_CIPHER *cipher; - int block_size; /* (bytes) */ - int key_len; /* (bytes) */ - int iv_len; - int flags; - int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); - int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl); - int (*cleanup)(EVP_CIPHER_CTX *); - int ctx_size; - int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); - int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); - int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); -}; -typedef struct gost_cipher_st GOST_cipher; - -EVP_CIPHER *GOST_init_cipher(GOST_cipher *c); -void GOST_deinit_cipher(GOST_cipher *c); - /* ENGINE implementation data */ extern GOST_cipher Gost28147_89_cipher; extern GOST_cipher Gost28147_89_cbc_cipher; @@ -418,3 +395,4 @@ extern GOST_NID_JOB kuznyechik_mgm_NID; #endif /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */ + diff --git a/gost_prov.c b/gost_prov.c index 2aa6076e2..2180deb48 100644 --- a/gost_prov.c +++ b/gost_prov.c @@ -48,14 +48,11 @@ void ERR_GOST_error(int function, int reason, char *file, int line) 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); } OPENSSL_free(ctx); } - -extern int populate_gost_engine(ENGINE *e); static PROV_CTX *provider_ctx_new(const OSSL_CORE_HANDLE *core, const OSSL_DISPATCH *in) { @@ -63,9 +60,7 @@ static PROV_CTX *provider_ctx_new(const OSSL_CORE_HANDLE *core, if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL && (ctx->proverr_handle = proverr_new_handle(core, in)) != NULL - && (ctx->libctx = OSSL_LIB_CTX_new_child(core, in)) != NULL - && (ctx->e = ENGINE_new()) != NULL - && populate_gost_engine(ctx->e)) { + && (ctx->libctx = OSSL_LIB_CTX_new_child(core, in)) != NULL) { ctx->core_handle = core; /* Ugly hack */ @@ -136,7 +131,6 @@ static const OSSL_ITEM *gost_get_reason_strings(void *provctx) /* The function that tears down this provider */ static void gost_teardown(void *vprovctx) { - GOST_prov_deinit_ciphers(); GOST_prov_deinit_digests(); GOST_prov_deinit_macs(); provider_ctx_free(vprovctx); diff --git a/gost_prov.h b/gost_prov.h index 81961794e..861eac753 100644 --- a/gost_prov.h +++ b/gost_prov.h @@ -10,7 +10,7 @@ **********************************************************************/ #include -#include +#include /* OID constants for GOST algorithms */ #define OID_id_GostR3410_2001 "1.2.643.2.2.19" @@ -54,15 +54,6 @@ 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; @@ -76,8 +67,6 @@ typedef struct gost_key_data_st int gost_get_max_keyexch_size(const GOST_KEY_DATA *); int gost_get_max_signature_size(const GOST_KEY_DATA *); -void GOST_prov_deinit_ciphers(void); - extern const OSSL_ALGORITHM GOST_prov_ciphers[]; extern const OSSL_ALGORITHM GOST_prov_keymgmt[]; extern const OSSL_ALGORITHM GOST_prov_encoder[]; diff --git a/gost_prov_cipher.c b/gost_prov_cipher.c index 9410e7a84..db149dad3 100644 --- a/gost_prov_cipher.c +++ b/gost_prov_cipher.c @@ -11,7 +11,9 @@ #include #include #include +#include #include "gost_prov.h" +#include "gost_cipher_ctx.h" #include "gost_lcl.h" /* @@ -60,52 +62,50 @@ static OSSL_FUNC_cipher_final_fn cipher_final; struct gost_prov_crypt_ctx_st { /* Provider context */ PROV_CTX *provctx; - /* OSSL_PARAM descriptors */ - const OSSL_PARAM *known_params; /* GOST_cipher descriptor */ - GOST_cipher *descriptor; - - /* - * Since existing functionality is designed for ENGINEs, the functions - * in this file are accomodated and are simply wrappers that use a local - * EVP_CIPHER and EVP_CIPHER_CTX. - * Future development should take a more direct approach and have the - * appropriate cipher functions and cipher data directly in this context. - */ - - /* The EVP_CIPHER created from |descriptor| */ - EVP_CIPHER *cipher; - /* The context for the EVP_CIPHER functions */ - EVP_CIPHER_CTX *cctx; + GOST_cipher *cipher; + /* The context for the GOST_cipher functions */ + GOST_cipher_ctx *cctx; }; typedef struct gost_prov_crypt_ctx_st GOST_CTX; +static int cipher_validate_init_inputs(const GOST_CTX *gctx, + const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + if (key != NULL && keylen != (size_t)GOST_cipher_key_length(gctx->cipher)) + return 0; + + if (iv != NULL) { + if ((GOST_cipher_flags(gctx->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { + if (ivlen == 0 || ivlen > EVP_MAX_IV_LENGTH) + return 0; + } else if (ivlen != (size_t)GOST_cipher_iv_length(gctx->cipher)) { + return 0; + } + } + + return 1; +} + static void cipher_freectx(void *vgctx) { GOST_CTX *gctx = vgctx; - /* - * We don't free gctx->cipher here. - * That will be done by the provider teardown, via - * GOST_prov_deinit_ciphers() (defined at the bottom of this file). - */ - EVP_CIPHER_CTX_free(gctx->cctx); + if (gctx == NULL) + return; + GOST_cipher_ctx_free(gctx->cctx); OPENSSL_free(gctx); } -static GOST_CTX *cipher_newctx(void *provctx, GOST_cipher *descriptor, - const OSSL_PARAM *known_params) +static GOST_CTX *cipher_newctx(void *provctx, GOST_cipher *cipher) { GOST_CTX *gctx = NULL; if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) { gctx->provctx = provctx; - gctx->known_params = known_params; - gctx->descriptor = descriptor; - gctx->cipher = GOST_init_cipher(descriptor); - gctx->cctx = EVP_CIPHER_CTX_new(); - - if (gctx->cipher == NULL || gctx->cctx == NULL) { + gctx->cipher = cipher; + if ((gctx->cctx = GOST_cipher_ctx_new()) == NULL) { cipher_freectx(gctx); gctx = NULL; } @@ -116,30 +116,32 @@ static GOST_CTX *cipher_newctx(void *provctx, GOST_cipher *descriptor, static void *cipher_dupctx(void *vsrc) { GOST_CTX *src = vsrc; - GOST_CTX *dst = - cipher_newctx(src->provctx, src->descriptor, src->known_params); + GOST_CTX *dst = cipher_newctx(src->provctx, src->cipher); - if (dst != NULL) - EVP_CIPHER_CTX_copy(dst->cctx, src->cctx); + if (dst != NULL && !GOST_cipher_ctx_copy(dst->cctx, src->cctx)) { + cipher_freectx(dst); + dst = NULL; + } return dst; } -static int cipher_get_params(EVP_CIPHER *c, OSSL_PARAM params[]) +static int cipher_get_params(const GOST_cipher *c, OSSL_PARAM params[]) { OSSL_PARAM *p; + if (c == NULL) + return 0; if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_block_size(c))) + && !OSSL_PARAM_set_size_t(p, (size_t)GOST_cipher_block_size(c))) || ((p = OSSL_PARAM_locate(params, "ivlen")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_iv_length(c))) + && !OSSL_PARAM_set_size_t(p, (size_t)GOST_cipher_iv_length(c))) || ((p = OSSL_PARAM_locate(params, "keylen")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_key_length(c))) + && !OSSL_PARAM_set_size_t(p, (size_t)GOST_cipher_key_length(c))) || ((p = OSSL_PARAM_locate(params, "mode")) != NULL - && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_flags(c))) + && !OSSL_PARAM_set_uint(p, (unsigned int)GOST_cipher_mode(c))) || ((p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD)) != NULL - && (strcmp(EVP_CIPHER_name(c), "magma-mgm") == 0 - || strcmp(EVP_CIPHER_name(c), "kuznyechik-mgm") == 0) - && !OSSL_PARAM_set_size_t(p, 1))) + && (c == &magma_mgm_cipher || c == &grasshopper_mgm_cipher) + && !OSSL_PARAM_set_int(p, 1))) return 0; return 1; } @@ -158,17 +160,19 @@ static int cipher_get_ctx_params(void *vgctx, OSSL_PARAM params[]) int ret; ret = (algidparam = ASN1_TYPE_new()) != NULL - && EVP_CIPHER_param_to_asn1(gctx->cctx, algidparam) > 0 + && (GOST_cipher_set_asn1_parameters_fn(gctx->cipher) == NULL + || GOST_cipher_set_asn1_parameters_fn(gctx->cipher)(gctx->cctx, + algidparam) > 0) && (derlen = i2d_ASN1_TYPE(algidparam, &der)) >= 0 - && OSSL_PARAM_set_octet_string(p, &der, (size_t)derlen); + && OSSL_PARAM_set_octet_string(p, der, (size_t)derlen); OPENSSL_free(der); ASN1_TYPE_free(algidparam); return ret; } if ((p = OSSL_PARAM_locate(params, "updated-iv")) != NULL) { - const void *iv = EVP_CIPHER_CTX_iv(gctx->cctx); - size_t ivlen = EVP_CIPHER_CTX_iv_length(gctx->cctx); + const void *iv = GOST_cipher_ctx_iv(gctx->cctx); + size_t ivlen = (size_t)GOST_cipher_ctx_iv_length(gctx->cctx); if (!OSSL_PARAM_set_octet_ptr(p, iv, ivlen) && !OSSL_PARAM_set_octet_string(p, iv, ivlen)) @@ -178,9 +182,9 @@ static int cipher_get_ctx_params(void *vgctx, OSSL_PARAM params[]) void *tag = NULL; size_t taglen = 0; - if (!OSSL_PARAM_get_octet_string_ptr(p, (const void**)&tag, &taglen) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_AEAD_GET_TAG, - taglen, tag) <= 0) + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&tag, &taglen) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_AEAD_GET_TAG, + (int)taglen, tag) <= 0) return 0; } return 1; @@ -199,60 +203,57 @@ static int cipher_set_ctx_params(void *vgctx, const OSSL_PARAM params[]) ret = OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &derlen) && (algidparam = d2i_ASN1_TYPE(NULL, &der, (long)derlen)) != NULL - && EVP_CIPHER_asn1_to_param(gctx->cctx, algidparam) > 0; + && (GOST_cipher_get_asn1_parameters_fn(gctx->cipher) == NULL + || GOST_cipher_get_asn1_parameters_fn(gctx->cipher)(gctx->cctx, + algidparam) > 0); ASN1_TYPE_free(algidparam); return ret; } if ((p = OSSL_PARAM_locate_const(params, "padding")) != NULL) { unsigned int pad = 0; - if (!OSSL_PARAM_get_uint(p, &pad) - || EVP_CIPHER_CTX_set_padding(gctx->cctx, pad) <= 0) + || !GOST_cipher_ctx_set_padding(gctx->cctx, (int)pad)) return 0; } if ((p = OSSL_PARAM_locate_const(params, "key-mesh")) != NULL) { size_t key_mesh = 0; - if (!OSSL_PARAM_get_size_t(p, &key_mesh) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_KEY_MESH, - key_mesh, NULL) <= 0) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_KEY_MESH, + (int)key_mesh, NULL) <= 0) return 0; } if ((p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN)) != NULL) { size_t ivlen = 0; - if (!OSSL_PARAM_get_size_t(p, &ivlen) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_AEAD_SET_IVLEN, - ivlen, NULL) <= 0) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_AEAD_SET_IVLEN, + (int)ivlen, NULL) <= 0) return 0; } if ((p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG)) != NULL) { char tag[1024]; - void *val = (void *) tag; + void *val = (void *)tag; size_t taglen = 0; - if (!OSSL_PARAM_get_octet_string(p, &val, 1024, &taglen) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_AEAD_SET_TAG, - taglen, &tag) <= 0) + if (!OSSL_PARAM_get_octet_string(p, &val, sizeof(tag), &taglen) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_AEAD_SET_TAG, + (int)taglen, tag) <= 0) return 0; } if ((p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLSTREE)) != NULL) { const void *val = NULL; size_t arg = 0; - if (!OSSL_PARAM_get_octet_string_ptr(p, &val, &arg) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_TLSTREE, - arg, (void *)val) <= 0) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_TLSTREE, + (int)arg, (void *)val) <= 0) return 0; } if ((p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLSTREE_MODE)) != NULL) { const void *val = NULL; size_t arg = 0; - if (!OSSL_PARAM_get_octet_string_ptr(p, &val, &arg) - || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_SET_TLSTREE_PARAMS, - arg, (void *)val) <= 0) + || GOST_cipher_ctx_ctrl(gctx->cctx, EVP_CTRL_SET_TLSTREE_PARAMS, + (int)arg, (void *)val) <= 0) return 0; } return 1; @@ -266,12 +267,10 @@ static int cipher_encrypt_init(void *vgctx, GOST_CTX *gctx = vgctx; if (!cipher_set_ctx_params(vgctx, params) - || keylen > EVP_CIPHER_key_length(gctx->cipher) - || ivlen > EVP_CIPHER_iv_length(gctx->cipher)) + || !cipher_validate_init_inputs(gctx, key, keylen, iv, ivlen)) return 0; - return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e, - key, iv, 1); + return GOST_CipherInit_ex(gctx->cctx, gctx->cipher, key, iv, 1); } static int cipher_decrypt_init(void *vgctx, @@ -282,11 +281,9 @@ static int cipher_decrypt_init(void *vgctx, GOST_CTX *gctx = vgctx; if (!cipher_set_ctx_params(vgctx, params) - || keylen > EVP_CIPHER_key_length(gctx->cipher) - || ivlen > EVP_CIPHER_iv_length(gctx->cipher)) + || !cipher_validate_init_inputs(gctx, key, keylen, iv, ivlen)) return 0; - return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e, - key, iv, 0) > 0; + return GOST_CipherInit_ex(gctx->cctx, gctx->cipher, key, iv, 0); } static int cipher_update(void *vgctx, @@ -294,8 +291,9 @@ static int cipher_update(void *vgctx, const unsigned char *in, size_t inl) { GOST_CTX *gctx = vgctx; + int int_outl = outl != NULL ? *outl : 0; - int res = EVP_CipherUpdate(gctx->cctx, out, &int_outl, in, (int)inl); + int res = GOST_CipherUpdate(gctx->cctx, out, &int_outl, in, (int)inl); if (res > 0 && outl != NULL) *outl = (size_t)int_outl; @@ -307,30 +305,13 @@ static int cipher_final(void *vgctx, { GOST_CTX *gctx = vgctx; int int_outl = outl != NULL ? *outl : 0; - int res = EVP_CipherFinal(gctx->cctx, out, &int_outl); + int res = GOST_CipherFinal(gctx->cctx, out, &int_outl); if (res > 0 && outl != NULL) *outl = (size_t)int_outl; return res > 0; } -static const OSSL_PARAM *known_Gost28147_89_cipher_params; -static const OSSL_PARAM *known_Gost28147_89_cbc_cipher_params; -static const OSSL_PARAM *known_Gost28147_89_cnt_cipher_params; -static const OSSL_PARAM *known_Gost28147_89_cnt_12_cipher_params; -static const OSSL_PARAM *known_grasshopper_ecb_cipher_params; -static const OSSL_PARAM *known_grasshopper_cbc_cipher_params; -static const OSSL_PARAM *known_grasshopper_cfb_cipher_params; -static const OSSL_PARAM *known_grasshopper_ofb_cipher_params; -static const OSSL_PARAM *known_grasshopper_ctr_cipher_params; -static const OSSL_PARAM *known_magma_ctr_cipher_params; -static const OSSL_PARAM *known_magma_ctr_acpkm_cipher_params; -static const OSSL_PARAM *known_magma_ctr_acpkm_omac_cipher_params; -static const OSSL_PARAM *known_magma_cbc_cipher_params; -static const OSSL_PARAM *known_magma_mgm_cipher_params; -static const OSSL_PARAM *known_grasshopper_ctr_acpkm_cipher_params; -static const OSSL_PARAM *known_grasshopper_ctr_acpkm_omac_cipher_params; -static const OSSL_PARAM *known_grasshopper_mgm_cipher_params; /* * These are named like the EVP_CIPHER templates in gost_crypt.c, with the * added suffix "_functions". Hopefully, that makes it easy to find the @@ -341,12 +322,12 @@ typedef void (*fptr_t)(void); static OSSL_FUNC_cipher_get_params_fn name##_get_params; \ static int name##_get_params(OSSL_PARAM *params) \ { \ - return cipher_get_params(GOST_init_cipher(&name), params); \ + return cipher_get_params(&name, params); \ } \ static OSSL_FUNC_cipher_newctx_fn name##_newctx; \ static void *name##_newctx(void *provctx) \ { \ - return cipher_newctx(provctx, &name, known_##name##_params); \ + return cipher_newctx(provctx, &name); \ } \ static const OSSL_DISPATCH name##_functions[] = { \ { OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)name##_get_params }, \ @@ -412,30 +393,3 @@ const OSSL_ALGORITHM GOST_prov_ciphers[] = { #endif { NULL , NULL, NULL } }; - -void GOST_prov_deinit_ciphers(void) { - static GOST_cipher *list[] = { - &Gost28147_89_cipher, - &Gost28147_89_cnt_cipher, - &Gost28147_89_cnt_12_cipher, - &Gost28147_89_cbc_cipher, - &grasshopper_ecb_cipher, - &grasshopper_cbc_cipher, - &grasshopper_cfb_cipher, - &grasshopper_ofb_cipher, - &grasshopper_ctr_cipher, - &magma_cbc_cipher, - &magma_ctr_cipher, - &magma_ctr_acpkm_cipher, - &magma_ctr_acpkm_omac_cipher, - &magma_mgm_cipher, - &grasshopper_ctr_acpkm_cipher, - &grasshopper_ctr_acpkm_omac_cipher, - &grasshopper_mgm_cipher, - }; - size_t i; -#define elems(l) (sizeof(l) / sizeof(l[0])) - - for (i = 0; i < elems(list); i++) - GOST_deinit_cipher(list[i]); -} diff --git a/patches/openssl-asn1_item_verify_ctx.patch b/patches/openssl-asn1_item_verify_ctx.patch new file mode 100644 index 000000000..10168b300 --- /dev/null +++ b/patches/openssl-asn1_item_verify_ctx.patch @@ -0,0 +1,34 @@ +diff --git a/openssl/crypto/asn1/a_verify.c b/openssl/crypto/asn1/a_verify.c +index f6cac80..4378625 100644 +--- a/openssl/crypto/asn1/a_verify.c ++++ b/openssl/crypto/asn1/a_verify.c +@@ -112,6 +112,7 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, + EVP_MD_CTX *ctx) + { + EVP_PKEY *pkey; ++ EVP_MD *fetched_type = NULL; + unsigned char *buf_in = NULL; + int ret = -1, inl = 0; + int mdnid, pknid; +@@ -180,6 +181,13 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, + + if (mdnid != NID_undef) { + type = EVP_get_digestbynid(mdnid); ++ if (type == NULL) { ++ const char *mdname = OBJ_nid2sn(mdnid); ++ ++ if (mdname != NULL) ++ fetched_type = EVP_MD_fetch(NULL, mdname, NULL); ++ type = fetched_type; ++ } + if (type == NULL) { + ERR_raise_data(ERR_LIB_ASN1, + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM, +@@ -220,6 +228,7 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, + } + ret = 1; + err: ++ EVP_MD_free(fetched_type); + OPENSSL_clear_free(buf_in, inll); + return ret; + } diff --git a/patches/openssl-x509_sig_info_init.patch b/patches/openssl-x509_sig_info_init.patch new file mode 100644 index 000000000..9db35679b --- /dev/null +++ b/patches/openssl-x509_sig_info_init.patch @@ -0,0 +1,43 @@ +diff --git a/openssl/crypto/x509/x509_set.c b/crypto/x509/x509_set.c +index 3fab2af..673f206 100644 +--- a/openssl/crypto/x509/x509_set.c ++++ b/openssl/crypto/x509/x509_set.c +@@ -218,6 +218,7 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig, const EVP_PKEY *pubkey) + { + int pknid, mdnid, md_size; ++ EVP_MD *fetched_md = NULL; + const EVP_MD *md; + const EVP_PKEY_ASN1_METHOD *ameth; + +@@ -280,14 +281,25 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + break; + default: + /* Security bits: half number of bits in digest */ +- if ((md = EVP_get_digestbynid(mdnid)) == NULL) { ++ md = EVP_get_digestbynid(mdnid); ++ if (md == NULL) { ++ const char *mdname = OBJ_nid2sn(mdnid); ++ ++ if (mdname != NULL) ++ fetched_md = EVP_MD_fetch(NULL, mdname, NULL); ++ md = fetched_md; ++ } ++ if (md == NULL) { + ERR_raise(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID); + return 0; + } + md_size = EVP_MD_get_size(md); +- if (md_size <= 0) ++ if (md_size <= 0) { ++ EVP_MD_free(fetched_md); + return 0; ++ } + siginf->secbits = md_size * 4; ++ EVP_MD_free(fetched_md); + break; + } + switch (mdnid) { +-- +2.43.0 + diff --git a/test_ciphers.c b/test_ciphers.c index 60384988e..99dd99ff4 100644 --- a/test_ciphers.c +++ b/test_ciphers.c @@ -12,6 +12,7 @@ #endif #include #include +#include #include #include #include @@ -505,6 +506,178 @@ static int test_stream(const EVP_CIPHER *type, const char *name, return ret; } +static unsigned int expected_mode_for_cipher(const char *name) +{ + if (strcmp(name, SN_id_Gost28147_89) == 0 + || strcmp(name, SN_grasshopper_cfb) == 0) + return EVP_CIPH_CFB_MODE; + if (strcmp(name, SN_gost89_cnt) == 0 + || strcmp(name, SN_gost89_cnt_12) == 0 + || strcmp(name, SN_grasshopper_ofb) == 0) + return EVP_CIPH_OFB_MODE; + if (strcmp(name, SN_grasshopper_ecb) == 0) + return EVP_CIPH_ECB_MODE; + if (strcmp(name, SN_gost89_cbc) == 0 + || strcmp(name, SN_grasshopper_cbc) == 0 + || strcmp(name, SN_magma_cbc) == 0) + return EVP_CIPH_CBC_MODE; + if (strcmp(name, SN_grasshopper_ctr) == 0 + || strcmp(name, SN_magma_ctr) == 0 + || strcmp(name, SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm) == 0) + return EVP_CIPH_CTR_MODE; + + return 0; +} + +static int test_provider_mode_param(const EVP_CIPHER *type, const char *name, + unsigned int expected_mode) +{ + OSSL_PARAM params[] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + unsigned int mode = 0; + int test = 0; + + if (EVP_CIPHER_get0_provider(type) == NULL) + return 0; + + params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_MODE, &mode); + printf("Provider mode param test [%s]: ", name); + T(EVP_CIPHER_get_params((EVP_CIPHER *)type, params)); + TEST_ASSERT(mode != expected_mode); + return mode != expected_mode; +} + +static int test_provider_alg_id_param(const EVP_CIPHER *type, const char *name, + const unsigned char *key, + const unsigned char *iv) +{ + EVP_CIPHER_CTX *ctx; + OSSL_PARAM params[] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + ASN1_TYPE *algid = NULL; + unsigned char der[256]; + const unsigned char *p = der; + int ret = 0, test; + + if (EVP_CIPHER_get0_provider(type) == NULL) + return 0; + + ctx = EVP_CIPHER_CTX_new(); + T(ctx != NULL); + printf("Provider alg_id_param test [%s]: ", name); + + params[0] = OSSL_PARAM_construct_octet_string("alg_id_param", der, sizeof(der)); + T(EVP_CipherInit_ex(ctx, type, NULL, key, iv, 1)); + T(EVP_CIPHER_CTX_get_params(ctx, params)); + T(params[0].return_size > 0 && params[0].return_size <= sizeof(der)); + T((algid = d2i_ASN1_TYPE(NULL, &p, (long)params[0].return_size)) != NULL); + + TEST_ASSERT(0); + EVP_CIPHER_CTX_free(ctx); + ASN1_TYPE_free(algid); + return ret | test; +} + +static int test_provider_padded_decrypt_case(const EVP_CIPHER *type, + const char *name, + const unsigned char *key, + const unsigned char *iv, + const unsigned char *pt, + size_t ptlen, + const size_t *chunks, + size_t chunk_count) +{ + EVP_CIPHER_CTX *enc; + EVP_CIPHER_CTX *dec; + unsigned char ct[128]; + unsigned char out[128]; + size_t offset; + int ctlen = 0, tmplen = 0; + int outlen = 0, part = 0, final = 0; + int ret = 0, test; + size_t i; + + enc = EVP_CIPHER_CTX_new(); + dec = EVP_CIPHER_CTX_new(); + T(enc != NULL && dec != NULL); + T(sizeof(ct) >= ptlen + (size_t)EVP_CIPHER_block_size(type)); + + T(EVP_CipherInit_ex(enc, type, NULL, key, iv, 1)); + T(EVP_CipherUpdate(enc, ct, &ctlen, pt, (int)ptlen)); + T(EVP_CipherFinal_ex(enc, ct + ctlen, &tmplen)); + ctlen += tmplen; + + memset(out, 0, sizeof(out)); + T(EVP_CipherInit_ex(dec, type, NULL, key, iv, 0)); + offset = 0; + outlen = 0; + for (i = 0; i < chunk_count; i++) { + T(offset + chunks[i] <= (size_t)ctlen); + T(EVP_CipherUpdate(dec, out + outlen, &part, ct + offset, (int)chunks[i])); + outlen += part; + offset += chunks[i]; + } + T(offset == (size_t)ctlen); + T(EVP_CipherFinal_ex(dec, out + outlen, &final)); + outlen += final; + + TEST_ASSERT((size_t)outlen != ptlen || memcmp(out, pt, ptlen)); + ret |= test; + + EVP_CIPHER_CTX_free(enc); + EVP_CIPHER_CTX_free(dec); + return ret; +} + +static int test_provider_padded_decrypt(const EVP_CIPHER *type, const char *name, + int block_size, + const unsigned char *key, + const unsigned char *iv) +{ + unsigned char pt_short[31]; + unsigned char pt_long[63]; + size_t short_chunks[2]; + size_t long_chunks[2]; + size_t mixed_chunks[3]; + size_t ctlen; + int ret = 0; + size_t i; + + if (EVP_CIPHER_get0_provider(type) == NULL || EVP_CIPHER_block_size(type) == 1) + return 0; + + for (i = 0; i < sizeof(pt_short); i++) + pt_short[i] = (unsigned char)(0x10 + i); + for (i = 0; i < sizeof(pt_long); i++) + pt_long[i] = (unsigned char)(0x80 + i); + + printf("Provider padded decrypt regressions [%s]\n", name); + + short_chunks[0] = (size_t)block_size - 1; + short_chunks[1] = 1; + ret |= test_provider_padded_decrypt_case(type, name, key, iv, + pt_short, (size_t)block_size - 3, + short_chunks, 2); + + ctlen = (size_t)(block_size * 2); + long_chunks[0] = ctlen - 1; + long_chunks[1] = 1; + ret |= test_provider_padded_decrypt_case(type, name, key, iv, + pt_long, (size_t)(block_size * 2 - 1), + long_chunks, 2); + + mixed_chunks[0] = 1; + mixed_chunks[1] = (size_t)block_size - 2; + mixed_chunks[2] = ctlen - mixed_chunks[0] - mixed_chunks[1]; + ret |= test_provider_padded_decrypt_case(type, name, key, iv, + pt_long, (size_t)(block_size * 2 - 1), + mixed_chunks, 3); + + return ret; +} + int engine_is_available(const char *name) { ENGINE *e = ENGINE_get_first(); @@ -594,6 +767,17 @@ int main(int argc, char **argv) ret |= test_stream(ciph, t->algname, t->plaintext, t->key, t->expected, t->size, t->iv, t->iv_size, t->acpkm); + if (EVP_CIPHER_get0_provider(ciph) != NULL) { + ret |= test_provider_mode_param(ciph, t->algname, + expected_mode_for_cipher(t->algname)); + if (strcmp(t->algname, SN_grasshopper_ctr) == 0 + || strcmp(t->algname, + SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm) == 0) { + ret |= test_provider_alg_id_param(ciph, t->algname, t->key, t->iv); + } + ret |= test_provider_padded_decrypt(ciph, t->algname, t->block, + t->key, t->iv); + } EVP_CIPHER_free(ciph); }