aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--gost_lcl.h5
-rw-r--r--gost_prov.c5
-rw-r--r--gost_prov_cipher.c352
-rw-r--r--test/03-encrypt.t350
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
diff --git a/gost_lcl.h b/gost_lcl.h
index 4801e17..edfabcf 100644
--- a/gost_lcl.h
+++ b/gost_lcl.h
@@ -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";
+ }
+}