aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--gost_lcl.h5
-rw-r--r--gost_prov.c3
-rw-r--r--gost_prov_digest.c200
-rw-r--r--test/01-digest.t371
5 files changed, 471 insertions, 109 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 05645c3..c95e5ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,6 +200,7 @@ set(GOST_ENGINE_SOURCE_FILES
set(GOST_PROV_SOURCE_FILES
gost_prov.c
gost_prov_cipher.c
+ gost_prov_digest.c
)
set(TEST_ENVIRONMENT_COMMON
diff --git a/gost_lcl.h b/gost_lcl.h
index edfabcf..0e544ee 100644
--- a/gost_lcl.h
+++ b/gost_lcl.h
@@ -381,6 +381,7 @@ typedef struct gost_digest_st GOST_digest;
EVP_MD *GOST_init_digest(GOST_digest *d);
void GOST_deinit_digest(GOST_digest *d);
+/* ENGINE implementation data */
extern GOST_digest GostR3411_94_digest;
extern GOST_digest Gost28147_89_MAC_digest;
extern GOST_digest Gost28147_89_mac_12_digest;
@@ -390,5 +391,9 @@ extern GOST_digest magma_mac_digest;
extern GOST_digest grasshopper_mac_digest;
extern GOST_digest kuznyechik_ctracpkm_omac_digest;
+/* Provider implementation data */
+extern const OSSL_ALGORITHM GOST_prov_digests[];
+void GOST_prov_deinit_digests(void);
+
#endif
/* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */
diff --git a/gost_prov.c b/gost_prov.c
index 04f4f3d..ba7120b 100644
--- a/gost_prov.c
+++ b/gost_prov.c
@@ -89,6 +89,8 @@ static const OSSL_ALGORITHM *gost_operation(void *vprovctx,
switch (operation_id) {
case OSSL_OP_CIPHER:
return GOST_prov_ciphers;
+ case OSSL_OP_DIGEST:
+ return GOST_prov_digests;
}
return NULL;
}
@@ -110,6 +112,7 @@ static const OSSL_ITEM *gost_get_reason_strings(void *provctx)
static void gost_teardown(void *vprovctx)
{
GOST_prov_deinit_ciphers();
+ GOST_prov_deinit_digests();
provider_ctx_free(vprovctx);
}
diff --git a/gost_prov_digest.c b/gost_prov_digest.c
new file mode 100644
index 0000000..9acd005
--- /dev/null
+++ b/gost_prov_digest.c
@@ -0,0 +1,200 @@
+/**********************************************************************
+ * gost_prov_digest.c - Initialize all digests *
+ * *
+ * Copyright (c) 2021 Richard Levitte <richard@levitte.org> *
+ * This file is distributed under the same license as OpenSSL *
+ * *
+ * OpenSSL provider interface to GOST digest 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 OSSL_DISPATCH functions, to make sure they
+ * are correctly defined further down.
+ */
+static OSSL_FUNC_digest_dupctx_fn digest_dupctx;
+static OSSL_FUNC_digest_freectx_fn digest_freectx;
+static OSSL_FUNC_digest_init_fn digest_init;
+static OSSL_FUNC_digest_update_fn digest_update;
+static OSSL_FUNC_digest_final_fn digest_final;
+
+
+struct gost_prov_crypt_ctx_st {
+ /* Provider context */
+ PROV_CTX *provctx;
+ /* OSSL_PARAM descriptors */
+ const OSSL_PARAM *known_params;
+ /* GOST_digest descriptor */
+ GOST_digest *descriptor;
+
+ /*
+ * Since existing functionality is designed for ENGINEs, the functions
+ * in this file are accomodated and are simply wrappers that use a local
+ * EVP_MD and EVP_MD_CTX.
+ * Future development should take a more direct approach and have the
+ * appropriate digest functions and digest data directly in this context.
+ */
+
+ /* The EVP_MD created from |descriptor| */
+ EVP_MD *digest;
+ /* The context for the EVP_MD functions */
+ EVP_MD_CTX *dctx;
+};
+typedef struct gost_prov_crypt_ctx_st GOST_CTX;
+
+static void digest_freectx(void *vgctx)
+{
+ GOST_CTX *gctx = vgctx;
+
+ /*
+ * We don't free gctx->digest here.
+ * That will be done by the provider teardown, via
+ * GOST_prov_deinit_digests() (defined at the bottom of this file).
+ */
+ EVP_MD_CTX_free(gctx->dctx);
+ OPENSSL_free(gctx);
+}
+
+static GOST_CTX *digest_newctx(void *provctx, GOST_digest *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->digest = GOST_init_digest(descriptor);
+ gctx->dctx = EVP_MD_CTX_new();
+
+ if (gctx->digest == NULL || gctx->dctx == NULL) {
+ digest_freectx(gctx);
+ gctx = NULL;
+ }
+ }
+ return gctx;
+}
+
+static void *digest_dupctx(void *vsrc)
+{
+ GOST_CTX *src = vsrc;
+ GOST_CTX *dst =
+ digest_newctx(src->provctx, src->descriptor, src->known_params);
+
+ if (dst != NULL)
+ EVP_MD_CTX_copy(dst->dctx, src->dctx);
+ return dst;
+}
+
+static int digest_get_params(EVP_MD *d, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL
+ && !OSSL_PARAM_set_size_t(p, EVP_MD_block_size(d)))
+ || ((p = OSSL_PARAM_locate(params, "size")) != NULL
+ && !OSSL_PARAM_set_size_t(p, EVP_MD_size(d)))
+ || ((p = OSSL_PARAM_locate(params, "xof")) != NULL
+ && !OSSL_PARAM_set_size_t(p, EVP_MD_flags(d) & EVP_MD_FLAG_XOF)))
+ return 0;
+ return 1;
+}
+
+static int digest_init(void *vgctx, const OSSL_PARAM unused_params[])
+{
+ GOST_CTX *gctx = vgctx;
+
+ return EVP_DigestInit_ex(gctx->dctx, gctx->digest, gctx->provctx->e) > 0;
+}
+
+static int digest_update(void *vgctx, const unsigned char *in, size_t inl)
+{
+ GOST_CTX *gctx = vgctx;
+
+ return EVP_DigestUpdate(gctx->dctx, in, (int)inl) > 0;
+}
+
+static int digest_final(void *vgctx,
+ unsigned char *out, size_t *outl, size_t outsize)
+{
+ GOST_CTX *gctx = vgctx;
+ unsigned int int_outl = outl != NULL ? *outl : 0;
+ int res = EVP_DigestFinal(gctx->dctx, out, &int_outl);
+
+ if (res > 0 && outl != NULL)
+ *outl = (size_t)int_outl;
+ return res > 0;
+}
+
+static const OSSL_PARAM known_GostR3411_94_digest_params[] = {};
+static const OSSL_PARAM known_GostR3411_2012_256_digest_params[] = {};
+static const OSSL_PARAM known_GostR3411_2012_512_digest_params[] = {};
+
+/*
+ * These are named like the EVP_MD templates in gost_md.c etc, 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_digest_get_params_fn name##_get_params; \
+ static int name##_get_params(OSSL_PARAM *params) \
+ { \
+ return digest_get_params(GOST_init_digest(&name), params); \
+ } \
+ static OSSL_FUNC_digest_newctx_fn name##_newctx; \
+ static void *name##_newctx(void *provctx) \
+ { \
+ return digest_newctx(provctx, &name, known_##name##_params); \
+ } \
+ static const OSSL_DISPATCH name##_functions[] = { \
+ { OSSL_FUNC_DIGEST_GET_PARAMS, (fptr_t)name##_get_params }, \
+ { OSSL_FUNC_DIGEST_NEWCTX, (fptr_t)name##_newctx }, \
+ { OSSL_FUNC_DIGEST_DUPCTX, (fptr_t)digest_dupctx }, \
+ { OSSL_FUNC_DIGEST_FREECTX, (fptr_t)digest_freectx }, \
+ { OSSL_FUNC_DIGEST_INIT, (fptr_t)digest_init }, \
+ { OSSL_FUNC_DIGEST_UPDATE, (fptr_t)digest_update }, \
+ { OSSL_FUNC_DIGEST_FINAL, (fptr_t)digest_final }, \
+ }
+
+MAKE_FUNCTIONS(GostR3411_94_digest);
+MAKE_FUNCTIONS(GostR3411_2012_256_digest);
+MAKE_FUNCTIONS(GostR3411_2012_512_digest);
+
+/* The OSSL_ALGORITHM for the provider's operation query function */
+const OSSL_ALGORITHM GOST_prov_digests[] = {
+ /*
+ * Described in RFC 6986, first name from
+ * https://www.ietf.org/archive/id/draft-deremin-rfc4491-bis-06.txt
+ * (is there not an RFC namming these?)
+ */
+ { "id-tc26-gost3411-12-256:md_gost12_256:1.2.643.7.1.1.2.2", NULL,
+ GostR3411_2012_256_digest_functions,
+ "GOST R 34.11-2012 with 256 bit hash" },
+ { "id-tc26-gost3411-12-512:md_gost12_512:1.2.643.7.1.1.2.3", NULL,
+ GostR3411_2012_512_digest_functions,
+ "GOST R 34.11-2012 with 512 bit hash" },
+
+ /* Described in RFC 5831, first name from RFC 4357, section 10.4 */
+ { "id-GostR3411-94:md_gost94:1.2.643.2.2.9", NULL,
+ GostR3411_94_digest_functions, "GOST R 34.11-94" },
+ { NULL , NULL, NULL }
+};
+
+void GOST_prov_deinit_digests(void) {
+ static GOST_digest *list[] = {
+ &GostR3411_94_digest,
+ &GostR3411_2012_256_digest,
+ &GostR3411_2012_512_digest,
+ };
+ size_t i;
+#define elems(l) (sizeof(l) / sizeof(l[0]))
+
+ for (i = 0; i < elems(list); i++)
+ GOST_deinit_digest(list[i]);
+}
diff --git a/test/01-digest.t b/test/01-digest.t
index 8d537b6..e116f7b 100644
--- a/test/01-digest.t
+++ b/test/01-digest.t
@@ -1,114 +1,267 @@
#!/usr/bin/perl
use Test2::V0;
-skip_all('TODO: add digest support in provider')
- unless $ARGV[0] eq 'engine';
-plan(16);
-
-# Set engine name from environment to allow testing of different engines
-my $engine=$ENV{'ENGINE_NAME'}||"gost";
-# Reopen STDERR to eliminate extra output
-open STDERR, ">>","tests.err";
-
-# prepare data for
-my $F;
-
-open $F,">","testm1.dat";
-print $F "012345678901234567890123456789012345678901234567890123456789012";
-close $F;
-is(`openssl dgst -engine ${engine} -md_gost12_256 testm1.dat`,
-"md_gost12_256(testm1.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\n",
-"GOST R 34.11-2012 256bit example 1 from standard");
-
-is(`openssl dgst -engine ${engine} -md_gost12_512 testm1.dat`,
-"md_gost12_512(testm1.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\n",
-"GOST R 34.11-2012 512bit example 1 from standard");
-
-unlink("testm1.dat");
-
-open $F,">","testm2.dat";
-print $F pack("H*","d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb");
-close $F;
-is(`openssl dgst -engine ${engine} -md_gost12_256 testm2.dat`,
-"md_gost12_256(testm2.dat)= 9dd2fe4e90409e5da87f53976d7405b0c0cac628fc669a741d50063c557e8f50\n",
-"GOST R 34.11-2012 256bit example 2 from standard");
-
-is(`openssl dgst -engine ${engine} -md_gost12_512 testm2.dat`,
-"md_gost12_512(testm2.dat)= 1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28\n",
-"GOST R 34.11-2012 512bit example 2 from standard");
-
-unlink("testm2.dat");
-
-
-open $F,">","testdata.dat";
-binmode $F;
-print $F "12345670" x 128;
-close $F;
-is(`openssl dgst -engine ${engine} -md_gost94 testdata.dat`,
-"md_gost94(testdata.dat)= f7fc6d16a6a5c12ac4f7d320e0fd0d8354908699125e09727a4ef929122b1cae\n",
-"GOST R 34.11-94 1K ascii");
-
-is(`openssl dgst -engine ${engine} -md_gost12_256 testdata.dat`,
-"md_gost12_256(testdata.dat)= 1906512b86a1283c68cec8419e57113efc562a1d0e95d8f4809542900c416fe4\n",
-"GOST R 34.11-2012 256bit 1K ascii");
-
-is(`openssl dgst -engine ${engine} -md_gost12_512 testdata.dat`,
-"md_gost12_512(testdata.dat)= 283587e434864d0d4bea97c0fb10e2dd421572fc859304bdf6a94673d652c59049212bad7802b4fcf5eecc1f8fab569d60f2c20dbd789a7fe4efbd79d8137ee7\n",
-"GOST R 34.11-2012 512bit 1K ascii");
-
-unlink("testdata.dat");
-
-open $F,">","testdata2.dat";
-binmode $F;
-print $F "\x00\x01\x02\x15\x84\x67\x45\x31" x 128;
-close $F;
-
-is(`openssl dgst -engine ${engine} -md_gost94 testdata2.dat`,
-"md_gost94(testdata2.dat)= 69f529aa82d9344ab0fa550cdf4a70ecfd92a38b5520b1906329763e09105196\n",
-"GOST R 34.11-94 1K binary");
-
-is(`openssl dgst -engine ${engine} -md_gost12_256 testdata2.dat`,
-"md_gost12_256(testdata2.dat)= 2eb1306be3e490f18ff0e2571a077b3831c815c46c7d4fdf9e0e26de4032b3f3\n",
-"GOST R 34.11-2012 256bit 1K binary");
-
-is(`openssl dgst -engine ${engine} -md_gost12_512 testdata2.dat`,
-"md_gost12_512(testdata2.dat)= 55656e5bcf795b499031a7833cd7dc18fe10d4a47e15be545c6ab3f304a4fe411c4c39de5b1fc6844880111441e0b92bf1ec2fb7840453fe39a2b70ced461968\n",
-"GOST R 34.11-2012 512bit 1K binary");
-
-unlink("testdata2.dat");
-
-open $F, ">","testdata3.dat";
-binmode $F;
-print $F substr("12345670" x 128,0,539);
-close $F;
-
-is(`openssl dgst -engine ${engine} -md_gost94 testdata3.dat`,
-"md_gost94(testdata3.dat)= bd5f1e4b539c7b00f0866afdbc8ed452503a18436061747a343f43efe888aac9\n",
-"GOST R 34.11-94 539 bytes");
-
-is(`openssl dgst -engine ${engine} -md_gost12_256 testdata3.dat`,
-"md_gost12_256(testdata3.dat)= c98a17f9fadff78d08521e4179a7b2e6275f3b1da88339a3cb961a3514e5332e\n",
-"GOST R 34.11-2012 256bit 539 bytes");
-
-is(`openssl dgst -engine ${engine} -md_gost12_512 testdata3.dat`,
-"md_gost12_512(testdata3.dat)= d5ad93fbc9ed7abc1cf28d00827a052b40bea74b04c4fd753102c1bcf9f9dad5142887f8a4cceaa0d64a0a8291592413d6adb956b99138a0023e127ff37bdf08\n",
-"GOST R 34.11-2012 512bit 539 bytes");
-
-unlink "testdata3.dat";
-open $F , ">","bigdata.dat";
-binmode $F;
-print $F ("121345678" x 7 . "1234567\n") x 4096,"12345\n";
-close $F;
-
-is(`openssl dgst -engine ${engine} -md_gost94 bigdata.dat`,
-"md_gost94(bigdata.dat)= e5d3ac4ea3f67896c51ff919cedb9405ad771e39f0f2eab103624f9a758e506f\n",
-"GOST R 34.11-94 128K");
-is(`openssl dgst -engine ${engine} -md_gost12_256 bigdata.dat`,
-"md_gost12_256(bigdata.dat)= 50e935d725d9359e5991b6b7eba8b3539fca03584d26adf4c827c982ffd49367\n",
-"GOST R 34.11-2012 256bit 128K");
+my $engine_name = $ENV{ENGINE_NAME} || 'gost';
+my $provider_name = $ENV{PROVIDER_NAME} || 'gostprov';
-is(`openssl dgst -engine ${engine} -md_gost12_512 bigdata.dat`,
-"md_gost12_512(bigdata.dat)= 1d93645ebfbb477660f98b7d1598e37fbf3bfc8234ead26e2246e1b979e590ac46138158a692f9a0c9ac2550758b4d0d4c9fb8af5e595a16d3760c6516443f82\n",
-"GOST R 34.11-2012 512bit 128K");
+# Supported test types:
+#
+# 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' )
+ : () ) );
-unlink "bigdata.dat";
+plan(16 * scalar @test_types);
+
+# prepare data for
+
+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_name}=${engine_name}_conf
+[${engine_name}_conf]
+default_algorithms = ALL
+EOCFG
+ },
+ 'standalone-provider-conf' => {
+ 'openssl-conf' => <<EOCFG,
+openssl_conf = openssl_def
+[openssl_def]
+providers = providers
+[providers]
+${provider_name}=${provider_name}_conf
+[${provider_name}_conf]
+EOCFG
+ },
+);
+
+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 $F;
+ my $cmd;
+ my $name_re;
+
+ open $F,">","testm1.dat";
+ print $F "012345678901234567890123456789012345678901234567890123456789012";
+ close $F;
+ $cmd = "openssl dgst${module_args} -md_gost12_256 testm1.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testm1.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\E\n$/ms,
+ "GOST R 34.11-2012 256bit example 1 from standard")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 testm1.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testm1.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\E\n$/ms,
+ "GOST R 34.11-2012 512bit example 1 from standard")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink("testm1.dat");
+
+
+ open $F,">","testm2.dat";
+ print $F pack("H*","d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb");
+ close $F;
+ $cmd = "openssl dgst${module_args} -md_gost12_256 testm2.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testm2.dat)= 9dd2fe4e90409e5da87f53976d7405b0c0cac628fc669a741d50063c557e8f50\E\n$/ms,
+ "GOST R 34.11-2012 256bit example 2 from standard")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 testm2.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testm2.dat)= 1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28\E\n$/ms,
+ "GOST R 34.11-2012 512bit example 2 from standard")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink("testm2.dat");
+
+
+ open $F,">","testdata.dat";
+ binmode $F;
+ print $F "12345670" x 128;
+ close $F;
+ $cmd = "openssl dgst${module_args} -md_gost94 testdata.dat";
+ $name_re = qr/id-GostR3411-94|md_gost94/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata.dat)= f7fc6d16a6a5c12ac4f7d320e0fd0d8354908699125e09727a4ef929122b1cae\E\n$/ms,
+ "GOST R 34.11-94 1K ascii")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_256 testdata.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata.dat)= 1906512b86a1283c68cec8419e57113efc562a1d0e95d8f4809542900c416fe4\E\n$/ms,
+ "GOST R 34.11-2012 256bit 1K ascii")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 testdata.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata.dat)= 283587e434864d0d4bea97c0fb10e2dd421572fc859304bdf6a94673d652c59049212bad7802b4fcf5eecc1f8fab569d60f2c20dbd789a7fe4efbd79d8137ee7\E\n$/ms,
+ "GOST R 34.11-2012 512bit 1K ascii")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink("testdata.dat");
+
+
+ open $F,">","testdata2.dat";
+ binmode $F;
+ print $F "\x00\x01\x02\x15\x84\x67\x45\x31" x 128;
+ close $F;
+
+ $cmd = "openssl dgst${module_args} -md_gost94 testdata2.dat";
+ $name_re = qr/id-GostR3411-94|md_gost94/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata2.dat)= 69f529aa82d9344ab0fa550cdf4a70ecfd92a38b5520b1906329763e09105196\E\n$/ms,
+ "GOST R 34.11-94 1K binary")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_256 testdata2.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata2.dat)= 2eb1306be3e490f18ff0e2571a077b3831c815c46c7d4fdf9e0e26de4032b3f3\E\n$/ms,
+ "GOST R 34.11-2012 256bit 1K binary")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 testdata2.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata2.dat)= 55656e5bcf795b499031a7833cd7dc18fe10d4a47e15be545c6ab3f304a4fe411c4c39de5b1fc6844880111441e0b92bf1ec2fb7840453fe39a2b70ced461968\E\n$/ms,
+ "GOST R 34.11-2012 512bit 1K binary")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink("testdata2.dat");
+
+ open $F, ">","testdata3.dat";
+ binmode $F;
+ print $F substr("12345670" x 128,0,539);
+ close $F;
+
+ $cmd = "openssl dgst${module_args} -md_gost94 testdata3.dat";
+ $name_re = qr/id-GostR3411-94|md_gost94/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata3.dat)= bd5f1e4b539c7b00f0866afdbc8ed452503a18436061747a343f43efe888aac9\E\n$/ms,
+ "GOST R 34.11-94 539 bytes")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_256 testdata3.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata3.dat)= c98a17f9fadff78d08521e4179a7b2e6275f3b1da88339a3cb961a3514e5332e\E\n$/ms,
+ "GOST R 34.11-2012 256bit 539 bytes")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 testdata3.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(testdata3.dat)= d5ad93fbc9ed7abc1cf28d00827a052b40bea74b04c4fd753102c1bcf9f9dad5142887f8a4cceaa0d64a0a8291592413d6adb956b99138a0023e127ff37bdf08\E\n$/ms,
+ "GOST R 34.11-2012 512bit 539 bytes")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink "testdata3.dat";
+ open $F , ">","bigdata.dat";
+ binmode $F;
+ print $F ("121345678" x 7 . "1234567\n") x 4096,"12345\n";
+ close $F;
+
+ $cmd = "openssl dgst${module_args} -md_gost94 bigdata.dat";
+ $name_re = qr/id-GostR3411-94|md_gost94/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(bigdata.dat)= e5d3ac4ea3f67896c51ff919cedb9405ad771e39f0f2eab103624f9a758e506f\E\n$/ms,
+ "GOST R 34.11-94 128K")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_256 bigdata.dat";
+ $name_re = qr/id-tc26-gost3411-12-256|md_gost12_256/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(bigdata.dat)= 50e935d725d9359e5991b6b7eba8b3539fca03584d26adf4c827c982ffd49367\E\n$/ms,
+ "GOST R 34.11-2012 256bit 128K")) {
+ diag("Command was: $cmd");
+ }
+
+ $cmd = "openssl dgst${module_args} -md_gost12_512 bigdata.dat";
+ $name_re = qr/id-tc26-gost3411-12-512|md_gost12_512/;
+ unless (like(`$cmd`,
+ qr/^${name_re}\Q(bigdata.dat)= 1d93645ebfbb477660f98b7d1598e37fbf3bfc8234ead26e2246e1b979e590ac46138158a692f9a0c9ac2550758b4d0d4c9fb8af5e595a16d3760c6516443f82\E\n$/ms,
+ "GOST R 34.11-2012 512bit 128K")) {
+ diag("Command was: $cmd");
+ }
+
+ unlink "bigdata.dat";
+}