diff --git a/CMakeLists.txt b/CMakeLists.txt index 60552abf0..9cc84b8e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,9 +194,6 @@ set (GOST_OMAC_SOURCE_FILES set(GOST_LIB_SOURCE_FILES ${GOST_CORE_SOURCE_FILES} - ${GOST_89_SOURCE_FILES} - ${GOST_HASH_SOURCE_FILES} - ${GOST_HASH_2012_SOURCE_FILES} ${GOST_GRASSHOPPER_SOURCE_FILES} ${GOST_EC_SOURCE_FILES} ${GOST_OMAC_SOURCE_FILES} @@ -313,9 +310,17 @@ add_test(NAME keyexpimp COMMAND test_keyexpimp) # test_gost89 is an internals testing program, it doesn't need a test env add_executable(test_gost89 test_gost89.c) -target_link_libraries(test_gost89 gost_core gost_err) +target_link_libraries(test_gost89 gost89) add_test(NAME gost89 COMMAND test_gost89) +add_executable(test_gosthash test_gosthash.c) +target_link_libraries(test_gosthash gosthash gost89) +add_test(NAME gosthash COMMAND test_gosthash) + +add_executable(test_gosthash2012 test_gosthash2012.c) +target_link_libraries(test_gosthash2012 gosthash2012) +add_test(NAME gosthash2012 COMMAND test_gosthash2012) + if(TLS13_PATCHED_OPENSSL) add_executable(test_mgm test_mgm.c) target_link_libraries(test_mgm OpenSSL::Crypto) @@ -368,12 +373,27 @@ set(BINARY_TESTS_TARGETS test_keyexpimp test_gost89 test_tls + test_gosthash + test_gosthash2012 ) set_property(TARGET ${BINARY_TESTS_TARGETS} APPEND PROPERTY COMPILE_DEFINITIONS ENGINE_DIR="${OUTPUT_DIRECTORY}") +add_library(gost89 STATIC ${GOST_89_SOURCE_FILES}) +set_target_properties(gost89 PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(gost89 PRIVATE OpenSSL::Crypto) + +add_library(gosthash STATIC ${GOST_HASH_SOURCE_FILES}) +set_target_properties(gosthash PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(gosthash PRIVATE OpenSSL::Crypto) + +add_library(gosthash2012 STATIC ${GOST_HASH_2012_SOURCE_FILES}) +set_target_properties(gosthash2012 PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(gosthash2012 PRIVATE OpenSSL::Crypto) + add_library(gost_core STATIC ${GOST_LIB_SOURCE_FILES}) set_target_properties(gost_core PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_link_libraries(gost_core PRIVATE OpenSSL::Crypto) +target_link_libraries(gost_core PRIVATE OpenSSL::Crypto gost89 gosthash gosthash2012) + add_library(gost_err STATIC ${GOST_ERR_SOURCE_FILES}) set_target_properties(gost_err PROPERTIES POSITION_INDEPENDENT_CODE ON) target_link_libraries(gost_err PRIVATE OpenSSL::Crypto) @@ -426,14 +446,14 @@ set(GOST_SUM_SOURCE_FILES ) add_executable(gostsum ${GOST_SUM_SOURCE_FILES}) -target_link_libraries(gostsum gost_core gost_err) +target_link_libraries(gostsum gost89 gosthash) set(GOST_12_SUM_SOURCE_FILES gost12sum.c ) add_executable(gost12sum ${GOST_12_SUM_SOURCE_FILES}) -target_link_libraries(gost12sum gost_core gost_err) +target_link_libraries(gost12sum gosthash2012) set_source_files_properties(tags PROPERTIES GENERATED true) add_custom_target(tags diff --git a/gosthash2012.h b/gosthash2012.h index 99c9e3d69..dd47d859e 100644 --- a/gosthash2012.h +++ b/gosthash2012.h @@ -53,11 +53,12 @@ # define ALIGN(x) __attribute__ ((__aligned__(x))) #endif -ALIGN(16) -typedef union uint512_u { +union ALIGN(16) uint512_u { unsigned long long QWORD[8]; unsigned char B[64]; -} uint512_u; +}; + +typedef union uint512_u uint512_u; #include "gosthash2012_const.h" #include "gosthash2012_precalc.h" diff --git a/test_gosthash.c b/test_gosthash.c new file mode 100644 index 000000000..bc94ba36a --- /dev/null +++ b/test_gosthash.c @@ -0,0 +1,135 @@ +/********************************************************************** + * No OpenSSL libraries required to compile and use * + * this code * + **********************************************************************/ +#include +#include + +#include "gost89.h" +#include "gosthash.h" + +static void hexdump(FILE *f, const char *title, const unsigned char *s, int l) +{ + int n = 0; + + fprintf(f, "%s", title); + for (; n < l; ++n) { + if ((n % 16) == 0) + fprintf(f, "\n%04x", n); + fprintf(f, " %02x", s[n]); + } + fprintf(f, "\n"); +} + +int test(const gost_subst_block* subst_block, const byte* data, size_t data_len, + const byte* expected_digest) { + int r = 0; + gost_hash_ctx ctx; + byte digest[32]; + + r = init_gost_hash_ctx(&ctx, subst_block); + if (r != 1) { + fprintf(stderr, "init_gost_hash_ctx failed"); + goto exit_return; + } + + r = start_hash(&ctx); + if (r != 1) { + fprintf(stderr, "start_hash failed"); + goto exit_done_gost_hash_ctx; + } + + r = hash_block(&ctx, data, data_len); + if (r != 1) { + fprintf(stderr, "hash_block failed"); + goto exit_done_gost_hash_ctx; + } + + r = finish_hash(&ctx, digest); + if (r != 1) { + fprintf(stderr, "finish_hash failed"); + goto exit_done_gost_hash_ctx; + } + + if (memcmp(digest, expected_digest, sizeof(digest))) { + hexdump(stdout, "Data to digest", data, data_len); + hexdump(stdout, "Calculated digest", digest, sizeof(digest)); + hexdump(stdout, "Expected digest", expected_digest, sizeof(digest)); + fprintf(stderr, "Digest does not match expected value\n"); + r = 0; + } + +exit_done_gost_hash_ctx: + done_gost_hash_ctx(&ctx); + +exit_return: + return r; +} + +void revert(byte* buffer, size_t len) { + size_t i = 0; + byte c; + for (; i < len/2; ++i) { + c = buffer[i]; + buffer[i] = buffer[len - i - 1]; + buffer[len - i - 1] = c; + } +} + +int main(void) +{ + int ret = 1; + int r = 0; + + // https://www.rfc-editor.org/rfc/rfc5831.html#section-7.3.1 + byte rfc5831_7_3_1_m[] = { + 0x73, 0x65, 0x74, 0x79, 0x62, 0x20, 0x32, 0x33, + 0x3D, 0x68, 0x74, 0x67, 0x6E, 0x65, 0x6C, 0x20, + 0x2C, 0x65, 0x67, 0x61, 0x73, 0x73, 0x65, 0x6D, + 0x20, 0x73, 0x69, 0x20, 0x73, 0x69, 0x68, 0x54 + }; + + byte rfc5831_7_3_1_h[] = { + 0xFA, 0xFF, 0x37, 0xA6, 0x15, 0xA8, 0x16, 0x69, + 0x1C, 0xFF, 0x3E, 0xF8, 0xB6, 0x8C, 0xA2, 0x47, + 0xE0, 0x95, 0x25, 0xF3, 0x9F, 0x81, 0x19, 0x83, + 0x2E, 0xB8, 0x19, 0x75, 0xD3, 0x66, 0xC4, 0xB1 + }; + + // https://www.rfc-editor.org/rfc/rfc5831.html#section-7.3.2 + byte rfc5831_7_3_2_m[] = { + 0x73, 0x65, 0x74, 0x79, 0x62, 0x20, 0x30, 0x35, + 0x20, 0x3D, 0x20, 0x68, 0x74, 0x67, 0x6E, 0x65, + 0x6C, 0x20, 0x73, 0x61, 0x68, 0x20, 0x65, 0x67, + 0x61, 0x73, 0x73, 0x65, 0x6D, 0x20, 0x6C, 0x61, + 0x6E, 0x69, 0x67, 0x69, 0x72, 0x6F, 0x20, 0x65, + 0x68, 0x74, 0x20, 0x65, 0x73, 0x6F, 0x70, 0x70, + 0x75, 0x53 + }; + + byte rfc5831_7_3_2_h[] = { + 0x08, 0x52, 0xF5, 0x62, 0x3B, 0x89, 0xDD, 0x57, + 0xAE, 0xB4, 0x78, 0x1F, 0xE5, 0x4D, 0xF1, 0x4E, + 0xEA, 0xFB, 0xC1, 0x35, 0x06, 0x13, 0x76, 0x3A, + 0x0D, 0x77, 0x0A, 0xA6, 0x57, 0xBA, 0x1A, 0x47 + }; + + revert(rfc5831_7_3_1_m, sizeof(rfc5831_7_3_1_m)); + revert(rfc5831_7_3_1_h, sizeof(rfc5831_7_3_1_h)); + r = test(&GostR3411_94_TestParamSet, rfc5831_7_3_1_m, sizeof(rfc5831_7_3_1_m), rfc5831_7_3_1_h); + if (r != 1) { + goto exit_return; + } + + revert(rfc5831_7_3_2_m, sizeof(rfc5831_7_3_2_m)); + revert(rfc5831_7_3_2_h, sizeof(rfc5831_7_3_2_h)); + r = test(&GostR3411_94_TestParamSet, rfc5831_7_3_2_m, sizeof(rfc5831_7_3_2_m), rfc5831_7_3_2_h); + if (r != 1) { + goto exit_return; + } + + ret = 0; + +exit_return: + return ret; +} diff --git a/test_gosthash2012.c b/test_gosthash2012.c new file mode 100644 index 000000000..0713854c1 --- /dev/null +++ b/test_gosthash2012.c @@ -0,0 +1,153 @@ +/********************************************************************** + * No OpenSSL libraries required to compile and use * + * this code * + **********************************************************************/ +#include +#include + +#include "gosthash2012.h" + +typedef unsigned char byte; + +static void hexdump(FILE *f, const char *title, const unsigned char *s, int l) +{ + int n = 0; + + fprintf(f, "%s", title); + for (; n < l; ++n) { + if ((n % 16) == 0) + fprintf(f, "\n%04x", n); + fprintf(f, " %02x", s[n]); + } + fprintf(f, "\n"); +} + +int test(unsigned int digest_size_bytes, const byte* data, size_t data_len, + const byte* expected_digest) { + gost2012_hash_ctx ctx; + byte digest[64]; + + init_gost2012_hash_ctx(&ctx, digest_size_bytes * 8); + gost2012_hash_block(&ctx, data, data_len); + gost2012_finish_hash(&ctx, digest); + + if (memcmp(digest, expected_digest, digest_size_bytes)) { + hexdump(stdout, "Data to digest", data, data_len); + hexdump(stdout, "Calculated digest", digest, digest_size_bytes); + hexdump(stdout, "Expected digest", expected_digest, digest_size_bytes); + fprintf(stderr, "Digest does not match expected value\n"); + return 0; + } + + return 1; +} + +void revert(byte* buffer, size_t len) { + size_t i = 0; + byte c; + for (; i < len/2; ++i) { + c = buffer[i]; + buffer[i] = buffer[len - i - 1]; + buffer[len - i - 1] = c; + } +} + +int main(void) +{ + int ret = 1; + int r = 0; + + // https://datatracker.ietf.org/doc/html/rfc6986#section-10.1 + byte rfc6986_10_1_m[] = { + 0x32, 0x31, 0x30, 0x39, 0x38, 0x37, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, 0x30, 0x39, 0x38, 0x37, + 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x39, + 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, + 0x30, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, + 0x32, 0x31, 0x30, 0x39, 0x38, 0x37, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, 0x30, 0x39, 0x38, 0x37, + 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30 + }; + + byte rfc6986_10_1_1_h[] = { + 0x48, 0x6f, 0x64, 0xc1, 0x91, 0x78, 0x79, 0x41, + 0x7f, 0xef, 0x08, 0x2b, 0x33, 0x81, 0xa4, 0xe2, + 0x11, 0xc3, 0x24, 0xf0, 0x74, 0x65, 0x4c, 0x38, + 0x82, 0x3a, 0x7b, 0x76, 0xf8, 0x30, 0xad, 0x00, + 0xfa, 0x1f, 0xba, 0xe4, 0x2b, 0x12, 0x85, 0xc0, + 0x35, 0x2f, 0x22, 0x75, 0x24, 0xbc, 0x9a, 0xb1, + 0x62, 0x54, 0x28, 0x8d, 0xd6, 0x86, 0x3d, 0xcc, + 0xd5, 0xb9, 0xf5, 0x4a, 0x1a, 0xd0, 0x54, 0x1b + }; + + byte rfc6986_10_1_2_h[] = { + 0x00, 0x55, 0x7b, 0xe5, 0xe5, 0x84, 0xfd, 0x52, + 0xa4, 0x49, 0xb1, 0x6b, 0x02, 0x51, 0xd0, 0x5d, + 0x27, 0xf9, 0x4a, 0xb7, 0x6c, 0xba, 0xa6, 0xda, + 0x89, 0x0b, 0x59, 0xd8, 0xef, 0x1e, 0x15, 0x9d + }; + + // https://datatracker.ietf.org/doc/html/rfc6986#section-10.2 + byte rfc6986_10_2_m[] = { + 0xfb, 0xe2, 0xe5, 0xf0, 0xee, 0xe3, 0xc8, 0x20, + 0xfb, 0xea, 0xfa, 0xeb, 0xef, 0x20, 0xff, 0xfb, + 0xf0, 0xe1, 0xe0, 0xf0, 0xf5, 0x20, 0xe0, 0xed, + 0x20, 0xe8, 0xec, 0xe0, 0xeb, 0xe5, 0xf0, 0xf2, + 0xf1, 0x20, 0xff, 0xf0, 0xee, 0xec, 0x20, 0xf1, + 0x20, 0xfa, 0xf2, 0xfe, 0xe5, 0xe2, 0x20, 0x2c, + 0xe8, 0xf6, 0xf3, 0xed, 0xe2, 0x20, 0xe8, 0xe6, + 0xee, 0xe1, 0xe8, 0xf0, 0xf2, 0xd1, 0x20, 0x2c, + 0xe8, 0xf0, 0xf2, 0xe5, 0xe2, 0x20, 0xe5, 0xd1 + }; + + byte rfc6986_10_2_1_h[] = { + 0x28, 0xfb, 0xc9, 0xba, 0xda, 0x03, 0x3b, 0x14, + 0x60, 0x64, 0x2b, 0xdc, 0xdd, 0xb9, 0x0c, 0x3f, + 0xb3, 0xe5, 0x6c, 0x49, 0x7c, 0xcd, 0x0f, 0x62, + 0xb8, 0xa2, 0xad, 0x49, 0x35, 0xe8, 0x5f, 0x03, + 0x76, 0x13, 0x96, 0x6d, 0xe4, 0xee, 0x00, 0x53, + 0x1a, 0xe6, 0x0f, 0x3b, 0x5a, 0x47, 0xf8, 0xda, + 0xe0, 0x69, 0x15, 0xd5, 0xf2, 0xf1, 0x94, 0x99, + 0x6f, 0xca, 0xbf, 0x26, 0x22, 0xe6, 0x88, 0x1e + }; + + byte rfc6986_10_2_2_h[] = { + 0x50, 0x8f, 0x7e, 0x55, 0x3c, 0x06, 0x50, 0x1d, + 0x74, 0x9a, 0x66, 0xfc, 0x28, 0xc6, 0xca, 0xc0, + 0xb0, 0x05, 0x74, 0x6d, 0x97, 0x53, 0x7f, 0xa8, + 0x5d, 0x9e, 0x40, 0x90, 0x4e, 0xfe, 0xd2, 0x9d + }; + + revert(rfc6986_10_1_m, sizeof(rfc6986_10_1_m)); + + revert(rfc6986_10_1_1_h, sizeof(rfc6986_10_1_1_h)); + r = test(sizeof(rfc6986_10_1_1_h), rfc6986_10_1_m, sizeof(rfc6986_10_1_m), rfc6986_10_1_1_h); + if (r != 1) { + goto exit_return; + } + + revert(rfc6986_10_1_2_h, sizeof(rfc6986_10_1_2_h)); + r = test(sizeof(rfc6986_10_1_2_h), rfc6986_10_1_m, sizeof(rfc6986_10_1_m), rfc6986_10_1_2_h); + if (r != 1) { + goto exit_return; + } + + revert(rfc6986_10_2_m, sizeof(rfc6986_10_2_m)); + + revert(rfc6986_10_2_1_h, sizeof(rfc6986_10_2_1_h)); + r = test(sizeof(rfc6986_10_2_1_h), rfc6986_10_2_m, sizeof(rfc6986_10_2_m), rfc6986_10_2_1_h); + if (r != 1) { + goto exit_return; + } + + revert(rfc6986_10_2_2_h, sizeof(rfc6986_10_2_2_h)); + r = test(sizeof(rfc6986_10_2_2_h), rfc6986_10_2_m, sizeof(rfc6986_10_2_m), rfc6986_10_2_2_h); + if (r != 1) { + goto exit_return; + } + + ret = 0; + +exit_return: + return ret; +}