diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | gost_lcl.h | 5 | ||||
-rw-r--r-- | gost_prov.c | 5 | ||||
-rw-r--r-- | gost_prov_cipher.c | 352 | ||||
-rw-r--r-- | test/03-encrypt.t | 350 |
5 files changed, 570 insertions, 143 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 499fc7e..05645c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,6 +199,7 @@ set(GOST_ENGINE_SOURCE_FILES set(GOST_PROV_SOURCE_FILES gost_prov.c + gost_prov_cipher.c ) set(TEST_ENVIRONMENT_COMMON @@ -337,6 +337,7 @@ 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; extern GOST_cipher Gost28147_89_cnt_cipher; @@ -355,6 +356,10 @@ extern GOST_cipher grasshopper_ctr_acpkm_omac_cipher; extern GOST_cipher magma_kexp15_cipher; extern GOST_cipher kuznyechik_kexp15_cipher; +/* Provider implementation data */ +extern const OSSL_ALGORITHM GOST_prov_ciphers[]; +void GOST_prov_deinit_ciphers(void); + struct gost_digest_st { struct gost_digest_st *template; int nid; diff --git a/gost_prov.c b/gost_prov.c index fe65c4d..04f4f3d 100644 --- a/gost_prov.c +++ b/gost_prov.c @@ -86,6 +86,10 @@ static const OSSL_ALGORITHM *gost_operation(void *vprovctx, int operation_id, const int *no_cache) { + switch (operation_id) { + case OSSL_OP_CIPHER: + return GOST_prov_ciphers; + } return NULL; } @@ -105,6 +109,7 @@ 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(); provider_ctx_free(vprovctx); } diff --git a/gost_prov_cipher.c b/gost_prov_cipher.c new file mode 100644 index 0000000..d64b0ff --- /dev/null +++ b/gost_prov_cipher.c @@ -0,0 +1,352 @@ +/********************************************************************** + * gost_prov_crypt.c - Initialize all ciphers * + * * + * Copyright (c) 2021 Richard Levitte <richard@levitte.org> * + * This file is distributed under the same license as OpenSSL * + * * + * OpenSSL provider interface to GOST cipher functions * + * Requires OpenSSL 3.0 for compilation * + **********************************************************************/ + +#include <openssl/core.h> +#include <openssl/core_dispatch.h> +#include "gost_prov.h" +#include "gost_lcl.h" + +/* + * Forward declarations of all generic OSSL_DISPATCH functions, to make sure + * they are correctly defined further down. For the algorithm specific ones + * MAKE_FUNCTIONS() does it for us. + */ +static OSSL_FUNC_cipher_dupctx_fn cipher_dupctx; +static OSSL_FUNC_cipher_freectx_fn cipher_freectx; +static OSSL_FUNC_cipher_get_ctx_params_fn cipher_get_ctx_params; +static OSSL_FUNC_cipher_set_ctx_params_fn cipher_set_ctx_params; +static OSSL_FUNC_cipher_encrypt_init_fn cipher_encrypt_init; +static OSSL_FUNC_cipher_decrypt_init_fn cipher_decrypt_init; +static OSSL_FUNC_cipher_update_fn cipher_update; +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; +}; +typedef struct gost_prov_crypt_ctx_st GOST_CTX; + +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); + OPENSSL_free(gctx); +} + +static GOST_CTX *cipher_newctx(void *provctx, GOST_cipher *descriptor, + const OSSL_PARAM *known_params) +{ + 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) { + cipher_freectx(gctx); + gctx = NULL; + } + } + return gctx; +} + +static void *cipher_dupctx(void *vsrc) +{ + GOST_CTX *src = vsrc; + GOST_CTX *dst = + cipher_newctx(src->provctx, src->descriptor, src->known_params); + + if (dst != NULL) + EVP_CIPHER_CTX_copy(dst->cctx, src->cctx); + return dst; +} + +static int cipher_get_params(EVP_CIPHER *c, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL + && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_block_size(c))) + || ((p = OSSL_PARAM_locate(params, "ivlen")) != NULL + && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_iv_length(c))) + || ((p = OSSL_PARAM_locate(params, "keylen")) != NULL + && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_key_length(c))) + || ((p = OSSL_PARAM_locate(params, "mode")) != NULL + && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_flags(c)))) + return 0; + return 1; +} + +static int cipher_get_ctx_params(void *vgctx, OSSL_PARAM params[]) +{ + GOST_CTX *gctx = vgctx; + OSSL_PARAM *p; + + if (!cipher_get_params(gctx->cipher, params)) + return 0; + if ((p = OSSL_PARAM_locate(params, "alg_id_param")) != NULL) { + ASN1_TYPE *algidparam = NULL; + unsigned char *der = NULL; + int derlen = 0; + int ret; + + ret = (algidparam = ASN1_TYPE_new()) != NULL + && EVP_CIPHER_param_to_asn1(gctx->cctx, algidparam) > 0 + && (derlen = i2d_ASN1_TYPE(algidparam, &der)) >= 0 + && 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); + + if (!OSSL_PARAM_set_octet_ptr(p, iv, ivlen) + && !OSSL_PARAM_set_octet_string(p, iv, ivlen)) + return 0; + } + return 1; +} + +static int cipher_set_ctx_params(void *vgctx, const OSSL_PARAM params[]) +{ + GOST_CTX *gctx = vgctx; + const OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate_const(params, "alg_id_param")) != NULL) { + ASN1_TYPE *algidparam = NULL; + const unsigned char *der = NULL; + size_t derlen = 0; + int ret; + + 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; + + 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) + 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) + return 0; + } + return 1; +} + +static int cipher_encrypt_init(void *vgctx, + const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + 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)) + return 0; + return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e, + key, iv, 1); +} + +static int cipher_decrypt_init(void *vgctx, + const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + 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)) + return 0; + return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e, + key, iv, 0) > 0; +} + +static int cipher_update(void *vgctx, + unsigned char *out, size_t *outl, size_t outsize, + 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); + + if (res > 0 && outl != NULL) + *outl = (size_t)int_outl; + return res > 0; +} + +static int cipher_final(void *vgctx, + unsigned char *out, size_t *outl, size_t outsize) +{ + GOST_CTX *gctx = vgctx; + int int_outl = outl != NULL ? *outl : 0; + int res = EVP_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_grasshopper_ctr_acpkm_cipher_params[] = {}; +static const OSSL_PARAM known_grasshopper_ctr_acpkm_omac_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 + * actual implementation. + */ +typedef void (*fptr_t)(void); +#define MAKE_FUNCTIONS(name) \ + 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); \ + } \ + static OSSL_FUNC_cipher_newctx_fn name##_newctx; \ + static void *name##_newctx(void *provctx) \ + { \ + return cipher_newctx(provctx, &name, known_##name##_params); \ + } \ + static const OSSL_DISPATCH name##_functions[] = { \ + { OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)name##_get_params }, \ + { OSSL_FUNC_CIPHER_NEWCTX, (fptr_t)name##_newctx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (fptr_t)cipher_dupctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (fptr_t)cipher_freectx }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (fptr_t)cipher_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (fptr_t)cipher_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (fptr_t)cipher_encrypt_init }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (fptr_t)cipher_decrypt_init }, \ + { OSSL_FUNC_CIPHER_UPDATE, (fptr_t)cipher_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (fptr_t)cipher_final }, \ + } + +MAKE_FUNCTIONS(Gost28147_89_cipher); +MAKE_FUNCTIONS(Gost28147_89_cnt_cipher); +MAKE_FUNCTIONS(Gost28147_89_cnt_12_cipher); +MAKE_FUNCTIONS(Gost28147_89_cbc_cipher); +MAKE_FUNCTIONS(grasshopper_ecb_cipher); +MAKE_FUNCTIONS(grasshopper_cbc_cipher); +MAKE_FUNCTIONS(grasshopper_cfb_cipher); +MAKE_FUNCTIONS(grasshopper_ofb_cipher); +MAKE_FUNCTIONS(grasshopper_ctr_cipher); +MAKE_FUNCTIONS(magma_cbc_cipher); +MAKE_FUNCTIONS(magma_ctr_cipher); +MAKE_FUNCTIONS(magma_ctr_acpkm_cipher); +MAKE_FUNCTIONS(magma_ctr_acpkm_omac_cipher); +MAKE_FUNCTIONS(grasshopper_ctr_acpkm_cipher); +MAKE_FUNCTIONS(grasshopper_ctr_acpkm_omac_cipher); + +/* The OSSL_ALGORITHM for the provider's operation query function */ +const OSSL_ALGORITHM GOST_prov_ciphers[] = { + { SN_id_Gost28147_89 ":gost89:GOST 28147-89:1.2.643.2.2.21", NULL, + Gost28147_89_cipher_functions }, + { SN_gost89_cnt, NULL, Gost28147_89_cnt_cipher_functions }, + { SN_gost89_cnt_12, NULL, Gost28147_89_cnt_12_cipher_functions }, + { SN_gost89_cbc, NULL, Gost28147_89_cbc_cipher_functions }, + { SN_grasshopper_ecb, NULL, grasshopper_ecb_cipher_functions }, + { SN_grasshopper_cbc, NULL, grasshopper_cbc_cipher_functions }, + { SN_grasshopper_cfb, NULL, grasshopper_cfb_cipher_functions }, + { SN_grasshopper_ofb, NULL, grasshopper_ofb_cipher_functions }, + { SN_grasshopper_ctr, NULL, grasshopper_ctr_cipher_functions }, + { SN_magma_cbc, NULL, magma_cbc_cipher_functions }, + { SN_magma_ctr, NULL, magma_ctr_cipher_functions }, + { SN_magma_ctr_acpkm ":1.2.643.7.1.1.5.1.1", NULL, + magma_ctr_acpkm_cipher_functions }, + { SN_magma_ctr_acpkm_omac ":1.2.643.7.1.1.5.1.2", NULL, + magma_ctr_acpkm_omac_cipher_functions }, + { SN_kuznyechik_ctr_acpkm ":1.2.643.7.1.1.5.2.1", NULL, + grasshopper_ctr_acpkm_cipher_functions }, + { SN_kuznyechik_ctr_acpkm_omac ":1.2.643.7.1.1.5.2.2", NULL, + grasshopper_ctr_acpkm_omac_cipher_functions }, +#if 0 /* Not yet implemented */ + { SN_magma_kexp15 ":1.2.643.7.1.1.7.1.1", NULL, + magma_kexp15_cipher_functions }, + { SN_kuznyechik_kexp15 ":1.2.643.7.1.1.7.2.1", NULL, + kuznyechik_kexp15_cipher_functions }, +#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, + &grasshopper_ctr_acpkm_cipher, + &grasshopper_ctr_acpkm_omac_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/test/03-encrypt.t b/test/03-encrypt.t index 5b25f30..91e8876 100644 --- a/test/03-encrypt.t +++ b/test/03-encrypt.t @@ -1,160 +1,224 @@ #!/usr/bin/perl use Test2::V0; -skip_all('TODO: add symmetric cipher support in provider') - unless $ARGV[0] eq 'engine'; -plan(48); use Cwd 'abs_path'; -# -# If this variable is set, engine would be loaded via configuration -# file. Otherwise - via command line -# -my $use_config = 1; - -# prepare data for - -my $key='0123456789abcdef' x 2; +my $engine_name = $ENV{ENGINE_NAME} || 'gost'; +my $provider_name = $ENV{PROVIDER_NAME} || 'gostprov'; +# Supported test types: # -# You can redefine engine to use using ENGINE_NAME environment variable -# -my $engine=$ENV{'ENGINE_NAME'}||"gost"; +# conf Only if there's a command line argument. +# For this test type, we rely entirely on the +# caller to define the environment variable +# OPENSSL_CONF appropriately. +# standalone-engine-conf Tests the engine through a generated config +# file. +# This is done when there are no command line +# arguments or when the environment variable +# ENGINE_NAME is defined. +# standalone-engine-args Tests the engine through openssl command args. +# This is done when there are no command line +# arguments or when the environment variable +# ENGINE_NAME is defined. +# standalone-provider-conf Tests the provider through a generated config +# file. +# This is done when there are no command line +# arguments or when the environment variable +# PROVIDER_NAME is defined. +# standalone-provider-args Tests the provider through openssl command args. +# This is done when there are no command line +# arguments or when the environment variable +# PROVIDER_NAME is defined. +my @test_types = ( $ARGV[0] ? 'conf' : (), + ( !$ARGV[0] || $ENV{ENGINE_NAME} + ? ( 'standalone-engine-conf', 'standalone-engine-args' ) + : () ), + ( !$ARGV[0] || $ENV{PROVIDER_NAME} + ? ( 'standalone-provider-conf', 'standalone-provider-args' ) + : () ) ); + +plan(48 * scalar @test_types); + +# prepare data for -# Reopen STDERR to eliminate extra output -open STDERR, ">>","tests.err"; - -our $count=0; +my $key='0123456789abcdef' x 2; -# -# parameters -paramset = oid of the parameters -# -cleartext - data to encrypt -# -ciphertext - expected ciphertext (hex-encoded) -# -key - key (hex-encoded) -# -iv - IV (hex-encoded) -# -my $F; -my $eng_param; - -open $F,">","test.cnf"; -if (defined($use_config) && $use_config) { - $eng_param = ""; - open $F,">","test.cnf"; - print $F <<EOCFG +my %configurations = ( + 'standalone-engine-args' => { + 'openssl-args' => "-engine $engine_name", + }, + 'standalone-provider-args' => { + 'openssl-args' => "-provider $provider_name -provider default", + }, + 'standalone-engine-conf' => { + 'openssl-conf' => <<EOCFG, openssl_conf = openssl_def [openssl_def] engines = engines [engines] -${engine}=gost_conf -[gost_conf] +${engine_name}=${engine_name}_conf +[${engine_name}_conf] default_algorithms = ALL - EOCFG -} else { - $eng_param = "-engine $engine" -} -close $F; -$ENV{'OPENSSL_CONF'}=abs_path('test.cnf'); - + }, + 'standalone-provider-conf' => { + 'openssl-conf' => <<EOCFG, +openssl_conf = openssl_def +[openssl_def] +providers = providers +[providers] +${provider_name}=${provider_name}_conf +[${provider_name}_conf] +EOCFG + }, +); + sub crypt_test { - my %p = @_; - our $count++; - open my $f, ">", "test$count.clear"; - print $f $p{-cleartext}; - close $f; - - $ENV{'CRYPT_PARAMS'} = $p{-paramset} if exists $p{-paramset}; - my $ctext = `openssl enc ${eng_param} -e -$p{-alg} -K $p{-key} -iv $p{-iv} -in test$count.clear`; - is($?,0,"$p{-name} - encrypt successful"); - is(unpack("H*",$ctext),$p{-ciphertext},"$p{-name} - ciphertext expected"); - open $f, ">", "test$count.enc"; - print $f $ctext; - close $f; - my $otext = `openssl enc ${eng_param} -d -$p{-alg} -K $p{-key} -iv $p{-iv} -in test$count.enc`; - is($?,0,"$p{-name} - decrypt successful"); - is($otext,$p{-cleartext},"$p{-name} - decrypted correctly"); - unlink "test$count.enc"; - unlink "test$count.clear"; - delete $ENV{'CRYPT_PARAMS'}; + my %p = @_; + my $test_type = $p{-testtype}; + my $args = $p{-args}; + my $count = ++${$p{-count}}; + my $result_name = "$test_type$count"; + open my $f, ">", "$result_name.clear"; + print $f $p{-cleartext}; + close $f; + + $ENV{'CRYPT_PARAMS'} = $p{-paramset} if exists $p{-paramset}; + my $ccmd = "openssl enc${args} -e -$p{-alg} -K $p{-key} -iv $p{-iv} -in $result_name.clear"; + my $ctext = `$ccmd`; + unless (is($?,0,"$p{-name} - Trying to encrypt")) { + diag("Command was: $ccmd"); + } + is(unpack("H*",$ctext),$p{-ciphertext},"$p{-name} - Checking that it encrypted correctly"); + open $f, ">", "$result_name.enc"; + print $f $ctext; + close $f; + my $ocmd = "openssl enc${args} -d -$p{-alg} -K $p{-key} -iv $p{-iv} -in $result_name.enc"; + my $otext = `$ocmd`; + unless(is($?,0,"$p{-name} - Trying to decrypt")) { + diag("Command was: $ocmd"); + } + is($otext,$p{-cleartext},"$p{-name} - Checking that it decrypted correctly"); + unlink "$result_name.enc"; + unlink "$result_name.clear"; + delete $ENV{'CRYPT_PARAMS'}; } -$key = '0123456789ABCDEF' x 4; -my $iv = '0000000000000000'; -my $clear1 = "The quick brown fox jumps over the lazy dog\n"; - -crypt_test(-paramset=> "1.2.643.2.2.31.1", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => '07f4102c6185c4a09e676e269bfa4bc9c5df6575916b879bd13a893a2285ee6690107cdeef7a315d2eb54bfa', - -alg => 'gost89', - -name=> 'CFB short text, paramset A'); - -crypt_test(-paramset=> "1.2.643.2.2.31.2", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => '11465c1c9708033e784fbb5536f2719c38353cb488b01f195c20d4c027022e8300d98bb66c138afbe878c88b', - -alg => 'gost89', - -name=> 'CFB short text, paramset B'); - -crypt_test(-paramset=> "1.2.643.2.2.31.3", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => '2f213b390c9b6ceb18de479686d23f4f03c76644a0aab8894b50b71a3bbb3c027ec4c2d569ba0e6a873bd46e', - -alg => 'gost89', - -name=> 'CFB short text, paramset C'); - -crypt_test(-paramset=> "1.2.643.2.2.31.4", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'e835f59a7fdfd84764efe1e987660327f5d0de187afea72f9cd040983a5e5bbeb4fe1aa5ff85d623ebc4d435', - -alg => 'gost89', - -name=> 'CFB short text, paramset D'); - - -crypt_test(-paramset=> "1.2.643.2.2.31.1", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'bcb821452e459f10f92019171e7c3b27b87f24b174306667f67704812c07b70b5e7420f74a9d54feb4897df8', - -alg => 'gost89-cnt', - -name=> 'CNT short text'); - -crypt_test(-paramset=> "1.2.643.2.2.31.2", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'bcb821452e459f10f92019171e7c3b27b87f24b174306667f67704812c07b70b5e7420f74a9d54feb4897df8', - -alg => 'gost89-cnt', - -name=> 'CNT short text, paramset param doesnt affect cnt'); - - -crypt_test(-paramset=> "1.2.643.2.2.31.1", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'cf3f5f713b3d10abd0c6f7bafb6aaffe13dfc12ef5c844f84873aeaaf6eb443a9747c9311b86f97ba3cdb5c4', - -alg => 'gost89-cnt-12', - -name=> 'CNT-12 short text'); - -crypt_test(-paramset=> "1.2.643.2.2.31.2", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'cf3f5f713b3d10abd0c6f7bafb6aaffe13dfc12ef5c844f84873aeaaf6eb443a9747c9311b86f97ba3cdb5c4', - -alg => 'gost89-cnt-12', - -name=> 'CNT-12 short text, paramset param doesnt affect cnt'); - - -crypt_test(-paramset=> "1.2.643.2.2.31.1", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => '3a3293e75089376572da44966cd1759c29d2f1e5e1c3fa9674909a63026da3dc51a4266bff37fb74a3a07155c9ca8fcf', - -alg => 'gost89-cbc', - -name=> 'CBC short text, paramset A'); - - -crypt_test(-paramset=> "1.2.643.2.2.31.2", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'af2a2167b75852378af176ac9950e3c4bffc94d3d4355191707adbb16d6c8e3f3a07868c4702babef18393edfac60a6d', - -alg => 'gost89-cbc', - -name=> 'CBC short text, paramset B'); - -crypt_test(-paramset=> "1.2.643.2.2.31.3", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => '987c0fb3d84530467a1973791e0a25e33c5d14591976f8c1573bdb9d056eb7b353f66fef3ffe2e3524583b3997123c8a', - -alg => 'gost89-cbc', - -name=> 'CBC short text, paramset C'); - -crypt_test(-paramset=> "1.2.643.2.2.31.4", -key => $key, -iv => $iv, - -cleartext => $clear1, - -ciphertext => 'e076b09822d4786a2863125d16594d765d8acd0f360e52df42e9d52c8e6c0e6595b5f6bbecb04a22c8ae5f4f87c1523b', - -alg => 'gost89-cbc', - -name=> 'CBC short text, paramset D'); - -unlink "test.cnf"; +foreach my $test_type (@test_types) { + my $configuration = $configurations{$test_type}; + my $module_args = $configuration->{'openssl-args'} // ''; + my $module_conf = $configuration->{'openssl-conf'}; + # This is a trick to make a locally modifiable environment variable and + # retain it's current value as a default. + local $ENV{OPENSSL_CONF} = $ENV{OPENSSL_CONF}; + + note("Running tests for test type $test_type"); + + if ($module_args) { + $module_args = ' ' . $module_args; + } + if (defined $module_conf) { + my $confname = "$test_type.cnf"; + open my $F, '>', $confname; + print $F $module_conf; + close $F; + $ENV{OPENSSL_CONF} = abs_path($confname); + } + + # Reopen STDERR to eliminate extra output + #open STDERR, ">>","tests.err"; + + my $count=0; + + # + # parameters -paramset = oid of the parameters + # -cleartext - data to encrypt + # -ciphertext - expected ciphertext (hex-encoded) + # -key - key (hex-encoded) + # -iv - IV (hex-encoded) + # + $key = '0123456789ABCDEF' x 4; + my $iv = '0000000000000000'; + my $clear1 = "The quick brown fox jumps over the lazy dog\n"; + my @common_args = ( -count => \$count, + -args => $module_args, + -key => $key, + -iv => $iv, + -cleartext => $clear1 ); + + crypt_test(-paramset => "1.2.643.2.2.31.1", + -ciphertext => '07f4102c6185c4a09e676e269bfa4bc9c5df6575916b879bd13a893a2285ee6690107cdeef7a315d2eb54bfa', + -alg => 'gost89', + -name => 'CFB short text, paramset A', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.2", + -ciphertext => '11465c1c9708033e784fbb5536f2719c38353cb488b01f195c20d4c027022e8300d98bb66c138afbe878c88b', + -alg => 'gost89', + -name => 'CFB short text, paramset B', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.3", + -ciphertext => '2f213b390c9b6ceb18de479686d23f4f03c76644a0aab8894b50b71a3bbb3c027ec4c2d569ba0e6a873bd46e', + -alg => 'gost89', + -name => 'CFB short text, paramset C', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.4", + -ciphertext => 'e835f59a7fdfd84764efe1e987660327f5d0de187afea72f9cd040983a5e5bbeb4fe1aa5ff85d623ebc4d435', + -alg => 'gost89', + -name => 'CFB short text, paramset D', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.1", + -ciphertext => 'bcb821452e459f10f92019171e7c3b27b87f24b174306667f67704812c07b70b5e7420f74a9d54feb4897df8', + -alg => 'gost89-cnt', + -name => 'CNT short text', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.2", + -ciphertext => 'bcb821452e459f10f92019171e7c3b27b87f24b174306667f67704812c07b70b5e7420f74a9d54feb4897df8', + -alg => 'gost89-cnt', + -name => 'CNT short text, paramset param doesnt affect cnt', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.1", + -ciphertext => 'cf3f5f713b3d10abd0c6f7bafb6aaffe13dfc12ef5c844f84873aeaaf6eb443a9747c9311b86f97ba3cdb5c4', + -alg => 'gost89-cnt-12', + -name => 'CNT-12 short text', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.2", + -ciphertext => 'cf3f5f713b3d10abd0c6f7bafb6aaffe13dfc12ef5c844f84873aeaaf6eb443a9747c9311b86f97ba3cdb5c4', + -alg => 'gost89-cnt-12', + -name => 'CNT-12 short text, paramset param doesnt affect cnt', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.1", + -ciphertext => '3a3293e75089376572da44966cd1759c29d2f1e5e1c3fa9674909a63026da3dc51a4266bff37fb74a3a07155c9ca8fcf', + -alg => 'gost89-cbc', + -name => 'CBC short text, paramset A', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.2", + -ciphertext => 'af2a2167b75852378af176ac9950e3c4bffc94d3d4355191707adbb16d6c8e3f3a07868c4702babef18393edfac60a6d', + -alg => 'gost89-cbc', + -name => 'CBC short text, paramset B', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.3", + -ciphertext => '987c0fb3d84530467a1973791e0a25e33c5d14591976f8c1573bdb9d056eb7b353f66fef3ffe2e3524583b3997123c8a', + -alg => 'gost89-cbc', + -name => 'CBC short text, paramset C', + @common_args); + + crypt_test(-paramset => "1.2.643.2.2.31.4", + -ciphertext => 'e076b09822d4786a2863125d16594d765d8acd0f360e52df42e9d52c8e6c0e6595b5f6bbecb04a22c8ae5f4f87c1523b', + -alg => 'gost89-cbc', + -name => 'CBC short text, paramset D', + @common_args); + + if (defined $module_conf) { + unlink "$test_type.cnf"; + } +} |