--- /dev/null
+sudo: required
+dist: trusty
+
+os: linux
+
+language: c
+
+env:
+ global:
+ - PREFIX=${HOME}/opt
+ - LD_LIBRARY_PATH=${PREFIX}/lib
+ - PATH=${PREFIX}/bin:${PATH}
+ - OPENSSL_ENGINES=${TRAVIS_BUILD_DIR}/bin
+
+matrix:
+ include:
+ - env: OPENSSL_BRANCH=master
+ os: linux
+ compiler: gcc
+ - env: OPENSSL_BRANCH=OpenSSL_1_1_0-stable
+ os: linux
+ compiler: gcc
+
+before_script:
+ - git clone -b ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git
+ - cd openssl
+ - ./config shared --prefix=${PREFIX} --openssldir=${PREFIX} && make all install_sw > build.log 2>&1 || (cat build.log && exit 1)
+ - cd ..
+
+script:
+ - cmake -DOPENSSL_ROOT_DIR=${PREFIX} -DOPENSSL_LIBRARIES=${PREFIX}/lib && make VERBOSE=1
+ - make test ARGS='--verbose'
cmake_minimum_required(VERSION 2.8)
project(ccgost C)
+find_package(OpenSSL 1.1 REQUIRED)
+include_directories(${OPENSSL_INCLUDE_DIR})
+
+enable_testing()
+
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
message(STATUS "Using Clang and adding -Qunused-arguments flag")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments")
gost_md2012.c
gost_pmeth.c)
+add_test(NAME engine
+ COMMAND perl run_tests
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test)
+
+add_executable(test_grasshopper test_grasshopper.c)
+target_link_libraries(test_grasshopper gost_engine gost ${OPENSSL_CRYPTO_LIBRARY})
+add_test(NAME grasshopper
+ COMMAND test_grasshopper)
+
add_library(gost STATIC ${GOST_LIB_SOURCE_FILES})
set_target_properties(gost PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_library(gost_engine MODULE ${GOST_ENGINE_SOURCE_FILES})
set_target_properties(gost_engine PROPERTIES PREFIX "" OUTPUT_NAME "gost")
-target_link_libraries(gost_engine crypto gost)
+target_link_libraries(gost_engine ${OPENSSL_CRYPTO_LIBRARY} gost)
set(GOST_12_SUM_SOURCE_FILES
gost12sum.c
--- /dev/null
+#!/usr/bin/perl
+use Test::More tests => 7;
+use Cwd 'abs_path';
+
+# prepare data for
+
+open F,">","testdata.dat";
+print F "12345670" x 128;
+close F;
+
+# Set OPENSSL_ENGINES environment variable to just built engine
+if(!defined $ENV{'OPENSSL_ENGINES'}){
+ $ENV{'OPENSSL_ENGINES'} = abs_path("../.libs");
+}
+
+$key='0123456789abcdef' x 2;
+
+#
+# You can redefine engine to use using ENGINE_NAME environment variable
+#
+$engine=$ENV{'ENGINE_NAME'}||"gost";
+
+# Reopen STDERR to eliminate extra output
+open STDERR, ">>","tests.err";
+
+if (exists $ENV{'OPENSSL_CONF'}) {
+ delete $ENV{'OPENSSL_CONF'}
+}
+#
+# This test needs output of openssl engine -c command.
+# Default one is hardcoded below, but you can place file
+# ${ENGINE_NAME}.info into this directory if you use this test suite
+# to test other engine implementing GOST cryptography.
+#
+if ( -f $engine . ".info") {
+ diag("Reading $engine.info");
+ open F, "<", $engine . ".info";
+ read F,$engine_info,1024;
+} else {
+
+$engine_info= <<EOINF;
+(gost) Reference implementation of GOST engine
+ [gost89, gost89-cnt, gost89-cnt-12, gost89-cbc, grasshopper-ecb, grasshopper-cbc, grasshopper-cfb, grasshopper-ofb, grasshopper-ctr, md_gost94, gost-mac, md_gost12_256, md_gost12_512, gost-mac-12, gost2001, gost-mac, gost2012_256, gost2012_512, gost-mac-12]
+EOINF
+}
+
+$ENV{'OPENSSL_CONF'}=abs_path("no_such_file.cfg");
+is(`openssl engine -c $engine`,
+$engine_info,
+"load engine without any config");
+
+is(`openssl dgst -engine $engine -md_gost94 testdata.dat`,
+"md_gost94(testdata.dat)= f7fc6d16a6a5c12ac4f7d320e0fd0d8354908699125e09727a4ef929122b1cae\n",
+"compute digest without config");
+
+
+open F,">","test.cnf";
+print F <<EOCFG;
+openssl_conf = openssl_def
+[openssl_def]
+engines = engines
+[engines]
+${engine}=gost_conf
+[gost_conf]
+default_algorithms = ALL
+
+EOCFG
+close F;
+$ENV{'OPENSSL_CONF'}=abs_path('test.cnf');
+
+is(`openssl engine -c $engine`,
+$engine_info,
+"load engine with config");
+
+is(`openssl dgst -md_gost94 testdata.dat`,
+"md_gost94(testdata.dat)= f7fc6d16a6a5c12ac4f7d320e0fd0d8354908699125e09727a4ef929122b1cae\n",
+"compute digest with config without explicit engine param");
+
+is(`openssl dgst -engine $engine -md_gost94 testdata.dat`,
+"md_gost94(testdata.dat)= f7fc6d16a6a5c12ac4f7d320e0fd0d8354908699125e09727a4ef929122b1cae\n",
+"compute digest with both config and explicit engine param");
+
+like(`openssl ciphers`, qr|GOST2001-GOST89-GOST89|, 'display GOST2001-GOST89-GOST89 cipher');
+
+like(`openssl ciphers`, qr|GOST2012-GOST8912-GOST8912|, 'display GOST2012-GOST8912-GOST8912 cipher');
+
+unlink('testdata.dat');
+unlink('test.cnf');
--- /dev/null
+#!/usr/bin/perl
+use Test::More tests => 16;
+use Cwd 'abs_path';
+
+# Set OPENSSL_ENGINES environment variable to just built engine
+if(!defined $ENV{'OPENSSL_ENGINES'}){
+ $ENV{'OPENSSL_ENGINES'} = abs_path("../.libs");
+}
+# Set engine name from environment to allow testing of different engines
+$engine=$ENV{'ENGINE_NAME'}||"gost";
+# Reopen STDERR to eliminate extra output
+open STDERR, ">>","tests.err";
+
+# prepare data for
+
+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");
+
+is(`openssl dgst -engine ${engine} -md_gost12_512 bigdata.dat`,
+"md_gost12_512(bigdata.dat)= 1d93645ebfbb477660f98b7d1598e37fbf3bfc8234ead26e2246e1b979e590ac46138158a692f9a0c9ac2550758b4d0d4c9fb8af5e595a16d3760c6516443f82\n",
+"GOST R 34.11-2012 512bit 128K");
+
+unlink "bigdata.dat";
--- /dev/null
+#!/usr/bin/perl
+use Test::More tests => 19;
+use Cwd 'abs_path';
+
+# prepare data for
+
+open F,">","testdata.dat";
+print F "12345670" x 128;
+close F;
+
+open F,">","testbig.dat";
+print F ("12345670" x 8 . "\n") x 4096;
+close F;
+# Set OPENSSL_ENGINES environment variable to just built engine
+if(!defined $ENV{'OPENSSL_ENGINES'}){
+ $ENV{'OPENSSL_ENGINES'} = abs_path("../.libs");
+}
+
+$key='0123456789abcdef' x 2;
+
+$engine=$ENV{'ENGINE_NAME'}||"gost";
+
+# Reopen STDERR to eliminate extra output
+open STDERR, ">>","tests.err";
+
+is(`openssl dgst -engine ${engine} -mac gost-mac -macopt key:${key} testdata.dat`,
+"GOST-MAC-gost-mac(testdata.dat)= 2ee8d13d\n",
+"GOST MAC - default size");
+
+for ($i=1;$i<=8; $i++) {
+ is(`openssl dgst -engine ${engine} -mac gost-mac -macopt key:${key} -sigopt size:$i testdata.dat`,
+"GOST-MAC-gost-mac(testdata.dat)= ".substr("2ee8d13dff7f037d",0,$i*2)."\n",
+"GOST MAC - size $i bytes");
+}
+
+
+
+is(`openssl dgst -engine ${engine} -mac gost-mac -macopt key:${key} testbig.dat`,
+"GOST-MAC-gost-mac(testbig.dat)= 5efab81f\n",
+"GOST MAC - big data");
+
+is(`openssl dgst -engine ${engine} -mac gost-mac-12 -macopt key:${key} testdata.dat`,
+"GOST-MAC-12-gost-mac-12(testdata.dat)= be4453ec\n",
+"GOST MAC - parameters 2012");
+
+
+for ($i=1;$i<=8; $i++) {
+ is(`openssl dgst -engine ${engine} -mac gost-mac-12 -macopt key:${key} -sigopt size:$i testdata.dat`,
+"GOST-MAC-12-gost-mac-12(testdata.dat)= ".substr("be4453ec1ec327be",0,$i*2)."\n",
+"GOST MAC parameters 2012 - size $i bytes");
+}
+unlink('testdata.dat');
+unlink('testbig.dat');
--- /dev/null
+#!/usr/bin/perl
+use Test::More tests => 48;
+use Cwd 'abs_path';
+
+#
+# If this variable is set, engine would be loaded via configuration
+# file. Otherwise - via command line
+#
+$use_config = 1;
+
+# prepare data for
+
+
+# Set OPENSSL_ENGINES environment variable to just built engine
+if(!defined $ENV{'OPENSSL_ENGINES'}){
+ $ENV{'OPENSSL_ENGINES'} = abs_path("../.libs");
+}
+
+$key='0123456789abcdef' x 2;
+
+#
+# You can redefine engine to use using ENGINE_NAME environment variable
+#
+$engine=$ENV{'ENGINE_NAME'}||"gost";
+
+# Reopen STDERR to eliminate extra output
+open STDERR, ">>","tests.err";
+
+our $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)
+#
+
+open F,">","test.cnf";
+if (defined($use_config) && $use_config) {
+ $eng_param = "";
+ open F,">","test.cnf";
+ print F <<EOCFG;
+openssl_conf = openssl_def
+[openssl_def]
+engines = engines
+[engines]
+${engine}=gost_conf
+[gost_conf]
+default_algorithms = ALL
+
+EOCFG
+} else {
+ $eng_param = "-engine $engine"
+}
+close F;
+$ENV{'OPENSSL_CONF'}=abs_path('test.cnf');
+
+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 my $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'};
+}
+
+$key = '0123456789ABCDEF' x 4;
+$iv = '0000000000000000';
+$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";
--- /dev/null
+#!/usr/bin/perl
+use Test::More tests => 15;
+use Cwd 'abs_path';
+
+#
+# If this variable is set, engine would be loaded via configuration
+# file. Otherwise - via command line
+#
+$use_config = 1;
+
+# prepare data for
+
+
+# Set OPENSSL_ENGINES environment variable to just built engine
+if(!defined $ENV{'OPENSSL_ENGINES'}){
+ $ENV{'OPENSSL_ENGINES'} = abs_path("../.libs");
+}
+
+$engine=$ENV{'ENGINE_NAME'}||"gost";
+
+# Reopen STDERR to eliminate extra output
+open STDERR, ">>","tests.err";
+
+
+open F,">","test.cnf";
+if (defined($use_config) && $use_config) {
+ $eng_param = "";
+ open F,">","test.cnf";
+ print F <<EOCFG;
+openssl_conf = openssl_def
+[openssl_def]
+engines = engines
+[engines]
+${engine}=gost_conf
+[gost_conf]
+default_algorithms = ALL
+
+EOCFG
+} else {
+ $eng_param = "-engine $engine"
+}
+close F;
+$ENV{'OPENSSL_CONF'}=abs_path('test.cnf');
+
+
+@keys=(['gost2001','A',"-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgIgRhUDJ1WQASIf
+nx+aUM2eagzV9dCt6mQ5wdtenr2ZS/Y=
+-----END PRIVATE KEY-----
+","Private key: 46150327559001221F9F1F9A50CD9E6A0CD5F5D0ADEA6439C1DB5E9EBD994BF6
+","Public key:
+ X:789094AF6386A43AF191210FFED0AEA5D1D9750D8FF8BCD1B584BFAA966850E4
+ Y:25ED63EE42624403D08FC60E5F8130F121ECDC5E297D9E3C7B106C906E0855E9
+Parameter set: id-GostR3410-2001-CryptoPro-A-ParamSet
+","-----BEGIN PUBLIC KEY-----
+MGMwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEDQwAEQORQaJaqv4S10bz4
+jw112dGlrtD+DyGR8TqkhmOvlJB46VUIbpBsEHs8nn0pXtzsIfEwgV8Oxo/QA0Ri
+Qu5j7SU=
+-----END PUBLIC KEY-----
+"],
+['gost2001','B'=>'-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwICHgEEIgIgImwnCcqcfuXK
+MVYg+UWQhiXYKz1yQ8kDSB7Ly515XH4=
+-----END PRIVATE KEY-----
+','Private key: 226C2709CA9C7EE5CA315620F945908625D82B3D7243C903481ECBCB9D795C7E
+','Public key:
+ X:59C15439385CBE790274D6537D318A35B27413D265FFDC5FBE5354DF8C7AC591
+ Y:11B771AC016AA817542184D05F2C7DDD0F9A5A5C9F840A79B5B7A73658F3048A
+Parameter set: id-GostR3410-2001-CryptoPro-B-ParamSet
+','-----BEGIN PUBLIC KEY-----
+MGMwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwICHgEDQwAEQJHFeozfVFO+X9z/
+ZdITdLI1ijF9U9Z0Anm+XDg5VMFZigTzWDant7V5CoSfXFqaD919LF/QhCFUF6hq
+AaxxtxE=
+-----END PUBLIC KEY-----
+'],
+['gost2001','C'=>'-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwMGByqFAwICHgEEIgIgKKUJVY2xlp24
+mky1F9inWeq3mm0J/uza6HsDvspgSzY=
+-----END PRIVATE KEY-----
+','Private key: 28A509558DB1969DB89A4CB517D8A759EAB79A6D09FEECDAE87B03BECA604B36
+','Public key:
+ X:58154320380CCFD2A101D2B7844516984023CF5A38610C4F98220E017270B2D4
+ Y:14C6977A6E9C0412DF5B53E69CD48DAF2B5805F55F6ACBEB4E01BA7B2BF84FC8
+Parameter set: id-GostR3410-2001-CryptoPro-C-ParamSet
+','-----BEGIN PUBLIC KEY-----
+MGMwHAYGKoUDAgITMBIGByqFAwICIwMGByqFAwICHgEDQwAEQNSycHIBDiKYTwxh
+OFrPI0CYFkWEt9IBodLPDDggQxVYyE/4K3u6AU7ry2pf9QVYK6+N1JzmU1vfEgSc
+bnqXxhQ=
+-----END PUBLIC KEY-----
+'],
+['gost2001','XA'=>,'-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIgIgOFuMMveKUx/C
+BOSjl9XCepDCHWHv/1bcjdKexKGJkZw=
+-----END PRIVATE KEY-----
+','Private key: 385B8C32F78A531FC204E4A397D5C27A90C21D61EFFF56DC8DD29EC4A189919C
+','Public key:
+ X:FA969CB29310E897978A1C9245107B46499D5C14A3975BF8E10EF5F613BE4EC6
+ Y:17FCFACCB0F838AE730E8B4021E880937824214DFF5365A61576AC5E72F92E35
+Parameter set: id-GostR3410-2001-CryptoPro-XchA-ParamSet
+','-----BEGIN PUBLIC KEY-----
+MGMwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEDQwAEQMZOvhP29Q7h+FuX
+oxRcnUlGexBFkhyKl5foEJOynJb6NS75cl6sdhWmZVP/TSEkeJOA6CFAiw5zrjj4
+sMz6/Bc=
+-----END PUBLIC KEY-----
+'],
+['gost2001','XB'=>,'-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwICHgEEIgIgE7WWqiYWoKLs
+7ezZ8L8Q9JcT73Jf5NYfFnlnoKRIQGg=
+-----END PRIVATE KEY-----
+','Private key: 13B596AA2616A0A2ECEDECD9F0BF10F49713EF725FE4D61F167967A0A4484068
+','Public key:
+ X:1D33A01774E501EFADD6C7A936728AF644749E98FEF5AE77A25E185955ED2E14
+ Y:FAD2D8101A99EDE8FBDF118B70A9894F4E6DE962B68D27E39B057624A51727
+Parameter set: id-GostR3410-2001-CryptoPro-XchB-ParamSet
+','-----BEGIN PUBLIC KEY-----
+MGMwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwICHgEDQwAEQBQu7VVZGF6id671
+/piedET2inI2qcfWre8B5XQXoDMdJxelJHYFm+MnjbZi6W1OT4mpcIsR3/vo7Zka
+ENjS+gA=
+-----END PUBLIC KEY-----
+']
+);
+for $keyinfo (@keys) {
+ my ($alg,$paramset,$seckey,$sectext,$pubtext,$pubkey) = @$keyinfo;
+ open F,">",'tmp.pem';
+ print F $seckey;
+ close F;
+ #1. Прочитать секретный ключ и напечатать публичный и секретный ключи
+ is(`openssl pkey -noout -text -in tmp.pem`,$sectext . $pubtext,
+ "Print key pair $alg:$paramset");
+ #2. Прочитать секретный ключ и вывести публичный (все алгоритмы)
+ is(`openssl pkey -pubout -in tmp.pem`,$pubkey,
+ "Compute public key $alg:$paramset");
+ open F,">","tmp.pem";
+ print F $pubkey;
+ close F;
+ #3. Прочитать публичный и напечать его в виде текста
+ is(`openssl pkey -pubin -noout -in tmp.pem -text`,$pubtext,
+ "Read and print public key $alg:paramset");
+
+}
+unlink "tmp.pem";
+#4. Сгенерировать ключ два раза (для всех алгоритов и параметров).
+# Проверить что получились числа требуемой длины и они не совпадают
+
+
+#5. Проверить эталонную подпись
+
+#6. Выработать подпись и проверить её
+
+#7. Выработать подпись, поменять в ней один бит и убедиться что она
+# перестала проверяться
+
+# 8. Выработать подпись, поменять 1 бит в подписываемых данных и
+# убедитсья, что подпись перестала быть корректной.
+
+# 9. Выработать shared ключ по vko
+
+# 10. Разобрать стандартый encrypted key
+
+# 11. Сгенерирвоать encrypted key и его разобрать.
+
+unlink "test.cnf";
+
--- /dev/null
+PERL=@PERL@
+
+test:
+ $(PERL) ./run_tests
--- /dev/null
+#!/usr/bin/perl
+use TAP::Harness;
+
+my $harness = TAP::Harness->new();
+exit ($harness->runtests(glob("*.t"))->all_passed() ? 0 : 1);
--- /dev/null
+/*
+ * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved.
+ *
+ * Contents licensed under the terms of the OpenSSL license
+ * See https://www.openssl.org/source/license.html for details
+ */
+
+#include "gost_grasshopper_cipher.h"
+#include "gost_grasshopper_defines.h"
+#include "gost_grasshopper_math.h"
+#include "gost_grasshopper_core.h"
+#include "e_gost_err.h"
+#include "gost_lcl.h"
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/asn1.h>
+#include <string.h>
+
+#define T(e) if (!(e)) {\
+ ERR_print_errors_fp(stderr);\
+ OpenSSLDie(__FILE__, __LINE__, #e);\
+ }
+
+#define cRED "\033[1;31m"
+#define cDRED "\033[0;31m"
+#define cGREEN "\033[1;32m"
+#define cDGREEN "\033[0;32m"
+#define cNORM "\033[m"
+#define TEST_ASSERT(e) {if ((test = (e))) \
+ printf(cRED "Test FAILED\n" cNORM); \
+ else \
+ printf(cGREEN "Test passed\n" cNORM);}
+
+/* Test key from both GOST R 34.12-2015 and GOST R 34.13-2015. */
+static const unsigned char K[] = {
+ 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
+ 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+};
+
+/* Plaintext from GOST R 34.13-2015 A.1.
+ * First 16 bytes is vector (a) from GOST R 34.12-2015 A.1. */
+static const unsigned char P[] = {
+ 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88,
+ 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xee,0xff,0x0a,
+ 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xee,0xff,0x0a,0x00,
+ 0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xee,0xff,0x0a,0x00,0x11,
+};
+static const unsigned char E_ecb[] = {
+ /* ECB test vectors from GOST R 34.13-2015 A.1.1 */
+ /* first 16 bytes is vector (b) from GOST R 34.12-2015 A.1 */
+ 0x7f,0x67,0x9d,0x90,0xbe,0xbc,0x24,0x30,0x5a,0x46,0x8d,0x42,0xb9,0xd4,0xed,0xcd,
+ 0xb4,0x29,0x91,0x2c,0x6e,0x00,0x32,0xf9,0x28,0x54,0x52,0xd7,0x67,0x18,0xd0,0x8b,
+ 0xf0,0xca,0x33,0x54,0x9d,0x24,0x7c,0xee,0xf3,0xf5,0xa5,0x31,0x3b,0xd4,0xb1,0x57,
+ 0xd0,0xb0,0x9c,0xcd,0xe8,0x30,0xb9,0xeb,0x3a,0x02,0xc4,0xc5,0xaa,0x8a,0xda,0x98,
+};
+static const unsigned char E_ctr[] = {
+ /* CTR test vectors from GOST R 34.13-2015 A.1.2 */
+ 0xf1,0x95,0xd8,0xbe,0xc1,0x0e,0xd1,0xdb,0xd5,0x7b,0x5f,0xa2,0x40,0xbd,0xa1,0xb8,
+ 0x85,0xee,0xe7,0x33,0xf6,0xa1,0x3e,0x5d,0xf3,0x3c,0xe4,0xb3,0x3c,0x45,0xde,0xe4,
+ 0xa5,0xea,0xe8,0x8b,0xe6,0x35,0x6e,0xd3,0xd5,0xe8,0x77,0xf1,0x35,0x64,0xa3,0xa5,
+ 0xcb,0x91,0xfa,0xb1,0xf2,0x0c,0xba,0xb6,0xd1,0xc6,0xd1,0x58,0x20,0xbd,0xba,0x73,
+};
+/*
+ * Other modes (ofb, cbc, cfb) is impossible to test to match GOST R
+ * 34.13-2015 test vectors exactly, due to these vectors having exceeding
+ * IV length value (m) = 256 bits, while openssl have hard-coded limit
+ * of maximum IV length of 128 bits (EVP_MAX_IV_LENGTH).
+ * Also, current grasshopper code having fixed IV length of 128 bits.
+ *
+ * Thus, new test vectors are generated with truncated 128-bit IV using
+ * canonical GOST implementation from TC26.
+ */
+static const unsigned char E_ofb[] = {
+ /* OFB test vector generated from canonical implementation */
+ 0x81,0x80,0x0a,0x59,0xb1,0x84,0x2b,0x24,0xff,0x1f,0x79,0x5e,0x89,0x7a,0xbd,0x95,
+ 0x77,0x91,0x46,0xdb,0x2d,0x93,0xa9,0x4e,0xd9,0x3c,0xf6,0x8b,0x32,0x39,0x7f,0x19,
+ 0xe9,0x3c,0x9e,0x57,0x44,0x1d,0x87,0x05,0x45,0xf2,0x40,0x36,0xa5,0x8c,0xee,0xa3,
+ 0xcf,0x3f,0x00,0x61,0xd5,0x64,0x23,0x54,0x5b,0x96,0x0d,0x86,0x4c,0xc8,0x68,0xda,
+};
+static const unsigned char E_cbc[] = {
+ /* CBC test vector generated from canonical implementation */
+ 0x68,0x99,0x72,0xd4,0xa0,0x85,0xfa,0x4d,0x90,0xe5,0x2e,0x3d,0x6d,0x7d,0xcc,0x27,
+ 0xab,0xf1,0x70,0xb2,0xb2,0x26,0xc3,0x01,0x0c,0xcf,0xa1,0x36,0xd6,0x59,0xcd,0xaa,
+ 0xca,0x71,0x92,0x72,0xab,0x1d,0x43,0x8e,0x15,0x50,0x7d,0x52,0x1e,0xcd,0x55,0x22,
+ 0xe0,0x11,0x08,0xff,0x8d,0x9d,0x3a,0x6d,0x8c,0xa2,0xa5,0x33,0xfa,0x61,0x4e,0x71,
+};
+static const unsigned char E_cfb[] = {
+ /* CFB test vector generated from canonical implementation */
+ 0x81,0x80,0x0a,0x59,0xb1,0x84,0x2b,0x24,0xff,0x1f,0x79,0x5e,0x89,0x7a,0xbd,0x95,
+ 0x68,0xc1,0xb9,0x9c,0x4d,0xf5,0x9c,0xc7,0x95,0x1e,0x37,0x39,0xb5,0xb3,0xcd,0xbf,
+ 0x07,0x3f,0x4d,0xd2,0xd6,0xde,0xb3,0xcf,0xb0,0x26,0x54,0x5f,0x7a,0xf1,0xd8,0xe8,
+ 0xe1,0xc8,0x52,0xe9,0xa8,0x56,0x71,0x62,0xdb,0xb5,0xda,0x7f,0x66,0xde,0xa9,0x26,
+};
+
+static const unsigned char iv_ctr[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xce,0xf0, 0,0,0,0,0,0,0,0 };
+/* truncated to 128-bits IV */
+static const unsigned char iv_128bit[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xce,0xf0,
+ 0xa1,0xb2,0xc3,0xd4,0xe5,0xf0,0x01,0x12 };
+struct testcase {
+ const char *name;
+ const EVP_CIPHER *(*type)(void);
+ int stream;
+ const unsigned char *plaintext;
+ const unsigned char *expected;
+ size_t size;
+ const unsigned char *iv;
+ size_t iv_size;
+ int acpkm;
+};
+static struct testcase testcases[] = {
+ { "ecb", cipher_gost_grasshopper_ecb, 0, P, E_ecb, sizeof(P), NULL, 0, 0 },
+ { "ctr", cipher_gost_grasshopper_ctr, 1, P, E_ctr, sizeof(P), iv_ctr, sizeof(iv_ctr), 0 },
+ { "ofb", cipher_gost_grasshopper_ofb, 1, P, E_ofb, sizeof(P), iv_128bit, sizeof(iv_128bit), 0 },
+ { "cbc", cipher_gost_grasshopper_cbc, 0, P, E_cbc, sizeof(P), iv_128bit, sizeof(iv_128bit), 0 },
+ { "cfb", cipher_gost_grasshopper_cfb, 0, P, E_cfb, sizeof(P), iv_128bit, sizeof(iv_128bit), 0 },
+ NULL
+};
+
+static void hexdump(const void *ptr, size_t len)
+{
+ const unsigned char *p = ptr;
+ size_t i, j;
+
+ for (i = 0; i < len; i += j) {
+ for (j = 0; j < 16 && i + j < len; j++)
+ printf("%s%02x", j? "" : " ", p[i + j]);
+ }
+ printf("\n");
+}
+
+static int test_block(const EVP_CIPHER *type, const char *name,
+ const unsigned char *pt, const unsigned char *exp, size_t size,
+ const unsigned char *iv, size_t iv_size, int acpkm)
+{
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ unsigned char c[size];
+ int outlen, tmplen;
+ int ret = 0, test;
+
+ OPENSSL_assert(ctx);
+ printf("Encryption test from GOST R 34.13-2015 [%s] \n", name);
+ /* test with single big chunk */
+ EVP_CIPHER_CTX_init(ctx);
+ T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, 1));
+ T(EVP_CIPHER_CTX_set_padding(ctx, 0));
+ memset(c, 0, sizeof(c));
+ if (acpkm)
+ T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, 256 / 8, NULL));
+ T(EVP_CipherUpdate(ctx, c, &outlen, pt, size));
+ T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
+ EVP_CIPHER_CTX_cleanup(ctx);
+ printf(" c[%d] = ", outlen);
+ hexdump(c, outlen);
+
+ TEST_ASSERT(outlen != size || memcmp(c, exp, size));
+ ret |= test;
+
+ /* test with small chunks of block size */
+ printf("Chunked encryption test from GOST R 34.13-2015 [%s] \n", name);
+ int blocks = size / GRASSHOPPER_BLOCK_SIZE;
+ int z;
+ EVP_CIPHER_CTX_init(ctx);
+ T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, 1));
+ T(EVP_CIPHER_CTX_set_padding(ctx, 0));
+ memset(c, 0, sizeof(c));
+ if (acpkm)
+ T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, 256 / 8, NULL));
+ for (z = 0; z < blocks; z++) {
+ int offset = z * GRASSHOPPER_BLOCK_SIZE;
+ int sz = GRASSHOPPER_BLOCK_SIZE;
+
+ T(EVP_CipherUpdate(ctx, c + offset, &outlen, pt + offset, sz));
+ }
+ outlen = z * GRASSHOPPER_BLOCK_SIZE;
+ T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
+ EVP_CIPHER_CTX_cleanup(ctx);
+ printf(" c[%d] = ", outlen);
+ hexdump(c, outlen);
+
+ TEST_ASSERT(outlen != size || memcmp(c, exp, size));
+ ret |= test;
+
+ /* test with single big chunk */
+ printf("Decryption test from GOST R 34.13-2015 [%s] \n", name);
+ EVP_CIPHER_CTX_init(ctx);
+ T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, 0));
+ T(EVP_CIPHER_CTX_set_padding(ctx, 0));
+ memset(c, 0, sizeof(c));
+ if (acpkm)
+ T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, 256 / 8, NULL));
+ T(EVP_CipherUpdate(ctx, c, &outlen, exp, size));
+ T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
+ EVP_CIPHER_CTX_cleanup(ctx);
+ EVP_CIPHER_CTX_free(ctx);
+ printf(" d[%d] = ", outlen);
+ hexdump(c, outlen);
+
+ TEST_ASSERT(outlen != size || memcmp(c, pt, size));
+ ret |= test;
+
+ return ret;
+}
+
+static int test_stream(const EVP_CIPHER *type, const char *name,
+ const unsigned char *pt, const unsigned char *exp, size_t size,
+ const unsigned char *iv, size_t iv_size, int acpkm)
+{
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ int ret = 0, test;
+ int z;
+
+ OPENSSL_assert(ctx);
+ /* Cycle through all lengths from 1 upto maximum size */
+ printf("Stream encryption test from GOST R 34.13-2015 [%s] \n", name);
+ for (z = 1; z <= size; z++) {
+ unsigned char c[size];
+ int outlen, tmplen;
+ int sz = 0;
+ int i;
+
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_CipherInit_ex(ctx, type, NULL, K, iv, 1);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ memset(c, 0xff, sizeof(c));
+ if (acpkm)
+ T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, 256 / 8, NULL));
+ for (i = 0; i < size; i += z) {
+ if (i + z > size)
+ sz = size - i;
+ else
+ sz = z;
+ EVP_CipherUpdate(ctx, c + i, &outlen, pt + i, sz);
+ OPENSSL_assert(outlen == sz);
+ }
+ outlen = i - z + sz;
+ EVP_CipherFinal_ex(ctx, c + outlen, &tmplen);
+ EVP_CIPHER_CTX_cleanup(ctx);
+
+ test = outlen != size || memcmp(c, exp, size);
+ printf("%c", test ? 'E' : '+');
+ ret |= test;
+ }
+ printf("\n");
+ TEST_ASSERT(ret);
+ EVP_CIPHER_CTX_free(ctx);
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+ const struct testcase *t;
+
+ for (t = testcases; t->name; t++) {
+ ret |= test_block(t->type(), t->name,
+ t->plaintext, t->expected, t->size,
+ t->iv, t->iv_size, t->acpkm);
+ if (t->stream)
+ ret |= test_stream(t->type(), t->name,
+ t->plaintext, t->expected, t->size,
+ t->iv, t->iv_size, t->acpkm);
+ }
+
+ if (ret)
+ printf(cDRED "= Some tests FAILED!\n" cNORM);
+ else
+ printf(cDGREEN "= All tests passed!\n" cNORM);
+ return ret;
+}