From dd645e71d12ec790dc6c2e1c44163e2683ae4c6a Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sat, 13 Feb 2021 14:56:17 +0100 Subject: [PATCH] Making a gost provider - Add the digests We add the digests for the provider as wrappers around the routines designed for ENGINEs. This is not the most elegant, but it does the job. When an algorithm has an OID, it's included in the OSSL_ALGORITHM name as an aliase. This is the way to avoid having to register the OIDs in OpenSSL proper. test/01-digest.t is modified to test the provider as well. --- CMakeLists.txt | 1 + gost_lcl.h | 5 + gost_prov.c | 3 + gost_prov_digest.c | 200 ++++++++++++++++++++++++ test/01-digest.t | 371 ++++++++++++++++++++++++++++++++------------- 5 files changed, 471 insertions(+), 109 deletions(-) create mode 100644 gost_prov_digest.c 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 * + * This file is distributed under the same license as OpenSSL * + * * + * OpenSSL provider interface to GOST digest functions * + * Requires OpenSSL 3.0 for compilation * + **********************************************************************/ + +#include +#include +#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' => < { + 'openssl-conf' => <{'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"; +} -- 2.39.2