diff --git a/CMakeLists.txt b/CMakeLists.txt index 306ff5fa9d897c87af75919f5f92a489459821e3..e5cb645ee2df0d8096cd5aa3b86192ae7d318e3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ set( AKRYPT_SOURCES source/ak_blom.c source/ak_kdf.c source/ak_encrypt.c + source/ak_belt_hash.c ) # -------------------------------------------------------------------------------------------------- # @@ -353,6 +354,7 @@ set ( ARITHMETIC_TESTS_LIST hash02 kuznechik01 mac-offset + belt-hash ) if( AK_TESTS_GMP ) diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c new file mode 100644 index 0000000000000000000000000000000000000000..75fdc1dc5b9dd0097922f32d4e41b6909d223524 --- /dev/null +++ b/examples/tests/test-belt-hash.c @@ -0,0 +1,178 @@ +#include <libakrypt.h> +#include <string.h> + +//подстановка битов +#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\ + 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\ + 0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p + +int main() { + ak_uint8 X1[13] = { + 0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B, + 0x36, 0x6D, 0x00, 0x8E, 0x58 + }; + const ak_uint8 Y1[32] = { + H16(AB,EF,97,25,D4,C5,A8,35,97,A3,67,D1,44,94,CC,25), + H16(42,F2,0F,65,9D,DF,EC,C9,61,A3,EC,55,0C,BA,8C,75) + }; + ak_uint8 X2[32] = { + H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4), + H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D) + }; + const ak_uint8 Y2[32] = { + H16(74,9E,4C,36,53,AE,CE,5E,48,DB,47,61,22,77,42,EB), + H16(6D,BE,13,F4,A8,0F,7B,EF,F1,A9,CF,8D,10,EE,77,86) + }; + ak_uint8 X3[48] = { + H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4), + H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D), + H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B) + }; + const ak_uint8 Y3[32] = { + H16(9D,02,EE,44,6F,B6,A2,9F,E5,C9,82,D4,B1,3A,F9,D3), + H16(E9,08,61,BC,4C,EF,27,CF,30,6B,FB,0B,17,4A,15,4A) + }; + + ak_uint8 success = 0; + ak_uint8 A[32] = {0}; + struct hash ctx; + + if (ak_libakrypt_create(NULL) != ak_true) { + ak_libakrypt_destroy(); + return EXIT_FAILURE; + } + + printf("--------------------Testing belt-hash----------------------\n" + " -----------Test 1------------\n" + "Input:\n" + " > X1 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x\n" + "Expected output:\n" + " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + X1[0] , X1[1] , X1[2] , X1[3] , X1[4] , X1[5] , X1[6] , X1[7] , + X1[8] , X1[9] , X1[10], X1[11], X1[12], + Y1[0] , Y1[1] , Y1[2] , Y1[3] , Y1[4] , Y1[5] , Y1[6] , Y1[7] , + Y1[8] , Y1[9] , Y1[10], Y1[11], Y1[12], Y1[13], Y1[14], Y1[15], + Y1[16], Y1[17], Y1[18], Y1[19], Y1[20], Y1[21], Y1[22], Y1[23], + Y1[24], Y1[25], Y1[26], Y1[27], Y1[28], Y1[29], Y1[30], Y1[31]); + + ak_hash_create_belt_hash( &ctx ); + ak_hash_ptr( &ctx, X1, 13, A, 32 ); + ak_hash_destroy( &ctx ); + + printf("Output:\n" + " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] , + A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15], + A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23], + A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]); + + if(strncmp( (const char*)A, (const char*)Y1, 32) == 0) { + printf("Test 1 was successful\n\n"); + success += 1; + } + else { + printf("Test 1 failed\n\n"); + } + + printf(" -----------Test 2------------\n" + "Input:\n" + " > X2 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + "Expected output:\n" + " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + X2[0] , X2[1] , X2[2] , X2[3] , X2[4] , X2[5] , X2[6] , X2[7] , + X2[8] , X2[9] , X2[10], X2[11], X2[12], X2[13], X2[14], X2[15], + X2[16], X2[17], X2[18], X2[19], X2[20], X2[21], X2[22], X2[23], + X2[24], X2[25], X2[26], X2[27], X2[28], X2[29], X2[30], X2[31], + Y2[0] , Y2[1] , Y2[2] , Y2[3] , Y2[4] , Y2[5] , Y2[6] , Y2[7] , + Y2[8] , Y2[9] , Y2[10], Y2[11], Y2[12], Y2[13], Y2[14], Y2[15], + Y2[16], Y2[17], Y2[18], Y2[19], Y2[20], Y2[21], Y2[22], Y2[23], + Y2[24], Y2[25], Y2[26], Y2[27], Y2[28], Y2[29], Y2[30], Y2[31]); + + ak_hash_create_belt_hash( &ctx ); + ak_hash_ptr( &ctx, X2, 32, A, 32 ); + ak_hash_destroy( &ctx ); + + printf("Output:\n" + " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] , + A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15], + A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23], + A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]); + + if(strncmp((const char*)A, (const char*)Y2, 32) == 0) { + printf("Test 2 was successful\n\n"); + success += 2; + } + else { + printf("Test 2 failed\n\n"); + } + + printf(" -----------Test 3------------\n" + "Input:\n" + " > X3 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + "Expected output:\n" + " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + X3[0] , X3[1] , X3[2] , X3[3] , X3[4] , X3[5] , X3[6] , X3[7] , + X3[8] , X3[9] , X3[10], X3[11], X3[12], X3[13], X3[14], X3[15], + X3[16], X3[17], X3[18], X3[19], X3[20], X3[21], X3[22], X3[23], + X3[24], X3[25], X3[26], X3[27], X3[28], X3[29], X3[30], X3[31], + X3[32], X3[33], X3[34], X3[35], X3[36], X3[37], X3[38], X3[39], + X3[40], X3[41], X3[42], X3[43], X3[44], X3[45], X3[46], X3[47], + Y3[0] , Y3[1] , Y3[2] , Y3[3] , Y3[4] , Y3[5] , Y3[6] , Y3[7] , + Y3[8] , Y3[9] , Y3[10], Y3[11], Y3[12], Y3[13], Y3[14], Y3[15], + Y3[16], Y3[17], Y3[18], Y3[19], Y3[20], Y3[21], Y3[22], Y3[23], + Y3[24], Y3[25], Y3[26], Y3[27], Y3[28], Y3[29], Y3[30], Y3[31]); + + ak_hash_create_belt_hash( &ctx ); + ak_hash_ptr( &ctx, X3, 48, A, 32 ); + ak_hash_destroy( &ctx ); + + ak_libakrypt_destroy(); + + printf("Output:\n" + " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n" + " %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x\n", + A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] , + A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15], + A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23], + A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]); + + if(strncmp((const char*)A, (const char*)Y3, 32) == 0) { + printf("Test 3, was successful\n"); + success += 4; + } + else { + printf("Test 3 failed\n"); + } + + if(success == 7) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c new file mode 100644 index 0000000000000000000000000000000000000000..ab0b3d3552d99301761f2776ca2dae574aafa0a1 --- /dev/null +++ b/source/ak_belt_hash.c @@ -0,0 +1,417 @@ +/* ----------------------------------------------------------------------------------------------- */ +/* */ +/* Реализация хэширования сообщения */ +/* РёР· Белорусского стандарта РЎРўР‘ 34.101.31-2020 */ +/* */ +/* ----------------------------------------------------------------------------------------------- */ + +#include <libakrypt-internal.h> + +//--------------------------------------------------------- +//----------------------belt-block------------------------- +//--------------------------------------------------------- + +//подстановка битов +#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\ + 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\ + 0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p + +//базовая H +static const ak_uint8 H[256] = { + H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4), + H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D), + H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B), + H16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99), + H16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1), + H16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F), + H16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31), + H16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93), + H16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47), + H16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6), + H16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2), + H16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11), + H16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1), + H16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A), + H16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21), + H16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D), +}; + +const ak_uint8* beltH() +{ + return H; +} + +//rotl +#define ROTL32(a, r) \ + ((ak_uint32)0x##a << r | (ak_uint32)0x##a >> (32 - r)) + +#define ROTL32x16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, r)\ + ROTL32(a, r), ROTL32(b, r), ROTL32(c, r), ROTL32(d, r),\ + ROTL32(e, r), ROTL32(f, r), ROTL32(g, r), ROTL32(h, r),\ + ROTL32(i, r), ROTL32(j, r), ROTL32(k, r), ROTL32(l, r),\ + ROTL32(m, r), ROTL32(n, r), ROTL32(o, r), ROTL32(p, r) + +//rotl(h) +static const ak_uint32 H5[256] = { + ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 5), + ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 5), + ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 5), + ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 5), + ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 5), + ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 5), + ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 5), + ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 5), + ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 5), + ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 5), + ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 5), + ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 5), + ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 5), + ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 5), + ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 5), + ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 5), +}; + +static const ak_uint32 H13[256] = { + ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 13), + ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 13), + ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 13), + ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 13), + ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 13), + ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 13), + ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 13), + ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 13), + ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 13), + ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 13), + ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 13), + ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 13), + ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 13), + ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 13), + ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 13), + ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 13), +}; + +static const ak_uint32 H21[256] = { + ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 21), + ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 21), + ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 21), + ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 21), + ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 21), + ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 21), + ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 21), + ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 21), + ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 21), + ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 21), + ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 21), + ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 21), + ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 21), + ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 21), + ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 21), + ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 21), +}; + +static const ak_uint32 H29[256] = { + ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 29), + ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 29), + ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 29), + ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 29), + ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 29), + ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 29), + ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 29), + ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 29), + ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 29), + ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 29), + ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 29), + ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 29), + ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 29), + ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 29), + ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 29), + ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 29), +}; + +//gr(x) +#define G5(x)\ + H5[(x) & 255] ^ H13[(x) >> 8 & 255] ^ \ + H21[(x) >> 16 & 255] ^ H29[(x) >> 24] + +#define G13(x)\ + H13[(x) & 255] ^ H21[(x) >> 8 & 255] ^ \ + H29[(x) >> 16 & 255] ^ H5[(x) >> 24] + +#define G21(x)\ + H21[(x) & 255] ^ H29[(x) >> 8 & 255] ^ \ + H5[(x) >> 16 & 255] ^ H13[(x) >> 24] + +//1 раунд +#define R(a, b, c, d, K, i, subkey)\ + *b ^= G5(*a + subkey(K, i, 0));\ + *c ^= G21(*d + subkey(K, i, 1));\ + *a -= G13(*b + subkey(K, i, 2));\ + *c += *b;\ + *b += G21(*c + subkey(K, i, 3)) ^ i;\ + *c -= *b;\ + *d += G13(*c + subkey(K, i, 4));\ + *b ^= G21(*a + subkey(K, i, 5));\ + *c ^= G5(*d + subkey(K, i, 6));\ + +//ключевая развертка +#define subkey_e(K, i, j) K[(7 * (i) - 7 + (j)) % 8] + +//зашифрование СЃ перестановкой через аргументы +#define E(a, b, c, d, K)\ + R(a, b, c, d, K, 1, subkey_e);\ + R(b, d, a, c, K, 2, subkey_e);\ + R(d, c, b, a, K, 3, subkey_e);\ + R(c, a, d, b, K, 4, subkey_e);\ + R(a, b, c, d, K, 5, subkey_e);\ + R(b, d, a, c, K, 6, subkey_e);\ + R(d, c, b, a, K, 7, subkey_e);\ + R(c, a, d, b, K, 8, subkey_e);\ + *a ^= *b, *b ^= *a, *a ^= *b;\ + *c ^= *d, *d ^= *c, *c ^= *d;\ + *b ^= *c, *c ^= *b, *b ^= *c;\ + +/** + * \brief Алгоритм зашифрования belt-block. + * \param block [4*32 Р±РёС‚] Указатель РЅР° шифруемый блок данных. + * \param key [8*32 Р±РёС‚] Указатель РЅР° ключ шифрования. + */ +void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8]) { + E((block + 0), (block + 1), (block + 2), (block + 3), key); +} + +//--------------------------------------------------------- +//--------------------belt-compress------------------------ +//--------------------------------------------------------- + +#define beltBlockNeg(dest, src)\ + ((ak_uint32*)(dest))[0] = ~((const ak_uint32*)(src))[0],\ + ((ak_uint32*)(dest))[1] = ~((const ak_uint32*)(src))[1],\ + ((ak_uint32*)(dest))[2] = ~((const ak_uint32*)(src))[2],\ + ((ak_uint32*)(dest))[3] = ~((const ak_uint32*)(src))[3] + +#define beltBlockXor(dest, src1, src2)\ + ((ak_uint32*)(dest))[0] = \ + ((const ak_uint32*)(src1))[0] ^ ((const ak_uint32*)(src2))[0],\ + ((ak_uint32*)(dest))[1] = \ + ((const ak_uint32*)(src1))[1] ^ ((const ak_uint32*)(src2))[1],\ + ((ak_uint32*)(dest))[2] = \ + ((const ak_uint32*)(src1))[2] ^ ((const ak_uint32*)(src2))[2],\ + ((ak_uint32*)(dest))[3] = \ + ((const ak_uint32*)(src1))[3] ^ ((const ak_uint32*)(src2))[3] + +#define beltBlockXor2(dest, src)\ + ((ak_uint32*)(dest))[0] ^= ((const ak_uint32*)(src))[0],\ + ((ak_uint32*)(dest))[1] ^= ((const ak_uint32*)(src))[1],\ + ((ak_uint32*)(dest))[2] ^= ((const ak_uint32*)(src))[2],\ + ((ak_uint32*)(dest))[3] ^= ((const ak_uint32*)(src))[3] + +#define beltBlockCopy(dest, src)\ + ((ak_uint32*)(dest))[0] = ((const ak_uint32*)(src))[0],\ + ((ak_uint32*)(dest))[1] = ((const ak_uint32*)(src))[1],\ + ((ak_uint32*)(dest))[2] = ((const ak_uint32*)(src))[2],\ + ((ak_uint32*)(dest))[3] = ((const ak_uint32*)(src))[3] + +/** + * \brief Алгоритм сжатия belt-compress <b>без обработки S</b>. + * \param h [8*32 Р±РёС‚] Указатель РЅР° выходное значение Y <b>Рё второй половины РІС…РѕРґРЅРѕРіРѕ значения X</b>. + * \param X [8*32 Р±РёС‚] Указатель РЅР° РІС…РѕРґРЅРѕРµ значение первой половины данных X. + * \param stack [12*32 Р±РёС‚] Указатель РЅР° промежуточный буфер работы функции. + */ +void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack) { + // [12]buf = [4]buf0 || [4]buf1 || [4]buf2 + ak_uint32* buf = (ak_uint32*)stack; + // buf0, buf1 <- h0 + h1 + beltBlockXor(buf, h, h + 4); + beltBlockCopy(buf + 4, buf); + // buf0 <- beltBlock(buf0, X) + buf1 + beltBlockEncr2(buf, X); + beltBlockXor2(buf, buf + 4); + // buf2 <- h0 + beltBlockCopy(buf + 8, h); + // buf1 <- h1 [buf01 == K1] + beltBlockCopy(buf + 4, h + 4); + // h0 <- beltBlock(X0, buf01) + X0 + beltBlockCopy(h, X); + beltBlockEncr2(h, buf); + beltBlockXor2(h, X); + // buf1 <- ~buf0 [buf12 == K2] + beltBlockNeg(buf + 4, buf); + // h1 <- beltBlock(X1, buf12) + X1 + beltBlockCopy(h + 4, X + 4); + beltBlockEncr2(h + 4, buf + 4); + beltBlockXor2(h + 4, X + 4); +} + +/** + * \brief Алгоритм сжатия belt-compress. + * \param s [4*32 Р±РёС‚] Указатель РЅР° выходное значение данных S. + * \param h [8*32 Р±РёС‚] Указатель РЅР° выходное значение Y <b>Рё второй половины РІС…РѕРґРЅРѕРіРѕ значения X</b>. + * \param X [8*32 Р±РёС‚] Указатель РЅР° РІС…РѕРґРЅРѕРµ значение первой половины данных X. + * \param stack [12*32 Р±РёС‚] Указатель РЅР° промежуточный буфер работы функции. + */ +static inline void beltCompress2(ak_uint32 s[4], ak_uint32 h[8], + const ak_uint32 X[8], void* stack) { + // [12]buf = [4]buf0 || [4]buf1 || [4]buf2 + ak_uint32* buf = (ak_uint32*)stack; + // buf0, buf1 <- h0 + h1 + beltBlockXor(buf, h, h + 4); + beltBlockCopy(buf + 4, buf); + // buf0 <- beltBlock(buf0, X) + buf1 + beltBlockEncr2(buf, X); + beltBlockXor2(buf, buf + 4); + // s <- s ^ buf0 + beltBlockXor2(s, buf); + // buf2 <- h0 + beltBlockCopy(buf + 8, h); + // buf1 <- h1 [buf01 == K1] + beltBlockCopy(buf + 4, h + 4); + // h0 <- beltBlock(X0, buf01) + X0 + beltBlockCopy(h, X); + beltBlockEncr2(h, buf); + beltBlockXor2(h, X); + // buf1 <- ~buf0 [buf12 == K2] + beltBlockNeg(buf + 4, buf); + // h1 <- beltBlock(X1, buf12) + X1 + beltBlockCopy(h + 4, X + 4); + beltBlockEncr2(h + 4, buf + 4); + beltBlockXor2(h + 4, X + 4); +} + +//--------------------------------------------------------- +//----------------------belt-hash-------------------------- +//--------------------------------------------------------- + +#define beltBlockSetZero(block)\ + ((ak_uint32*)(block))[0] = 0,\ + ((ak_uint32*)(block))[1] = 0,\ + ((ak_uint32*)(block))[2] = 0,\ + ((ak_uint32*)(block))[3] = 0 + +ak_uint32 u32Rev(ak_uint32 w) { + return w << 24 | (w & 0xFF00) << 8 | (w >> 8 & 0xFF00) | w >> 24; +} + +#define beltBlockRevU32(block)\ + ((ak_uint32*)(block))[0] = u32Rev(((ak_uint32*)(block))[0]),\ + ((ak_uint32*)(block))[1] = u32Rev(((ak_uint32*)(block))[1]),\ + ((ak_uint32*)(block))[2] = u32Rev(((ak_uint32*)(block))[2]),\ + ((ak_uint32*)(block))[3] = u32Rev(((ak_uint32*)(block))[3]) + +static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) { + ak_belt_hash cx = ( ak_belt_hash ) bctx; + if( cx == NULL ) return ak_error_null_pointer; + + beltBlockSetZero(cx->ls); + beltBlockSetZero(cx->ls + 4); + memmove(cx->h, beltH(), 32); + + return ak_error_ok; +} + +static int ak_hash_context_belt_hash_update( + ak_pointer bctx, const ak_pointer in, const size_t size ) { + ak_belt_hash cx = ( ak_belt_hash ) bctx; + const ak_uint8* dt = (const ak_uint8*) in; + ak_uint64 count; + ak_uint64 count_for_r; + ak_uint32* carry; + + if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to internal streebog context" ); + if(( !size ) || ( in == NULL )) return ak_error_ok; + if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__, + "data length is not a multiple of the length of the block" ); + + // обновить длину + count = size; + count_for_r = count << 3; + carry = (ak_uint32*) &count_for_r; + + cx->ls[0] = carry[0]; + cx->ls[1] = carry[1]; + count_for_r = count >> 61; + cx->ls[2] = carry[0]; + cx->ls[3] = 0; + + + while (count >= 32) + { + beltBlockCopy(cx->block, dt); + beltBlockCopy(cx->block + 16, dt + 16); +#ifndef AK_LITTLE_ENDIAN + beltBlockRevU32(st->block); + beltBlockRevU32(st->block + 16); +#endif + beltCompress2(cx->ls + 4, cx->h, (ak_uint32*)cx->block, cx->stack); + dt += 32; + count -= 32; + } + + return ak_error_ok; +} + +static int ak_hash_context_belt_hash_finalize( ak_pointer bctx, + const ak_pointer in, const size_t size, ak_pointer out, + const size_t out_size ) +{ + ak_belt_hash cx = ( ak_belt_hash ) bctx; + struct belt_hash bx[1]; //здесь должна изменяться РєРѕРїРёСЏ контекста, Р° РЅРµ оригинал + ak_uint32 carry; + + if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to internal streebog context" ); + if( out == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to externl result buffer" ); + if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__, + "input length is too huge" ); + + memcpy( bx, cx, sizeof( struct belt_hash )); + + if(size) { + // обновить длину + carry = (ak_uint32) size << 3; + carry = (bx->ls[0] += carry) < carry; + carry = (bx->ls[1] += carry) < carry; + carry = (bx->ls[2] += carry) < carry; + bx->ls[3] += carry; + + //отработать последний блок + memset(bx->block, 0, 32); + if (in != NULL) { + memcpy(bx->block, in, size); + } +#ifndef AK_LITTLE_ENDIAN + beltBlockRevU32(bx->block); + beltBlockRevU32(bx->block + 16); +#endif + beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack); + } + beltCompress(bx->h, bx->ls, bx->stack); + + memcpy(out, bx->h, ak_min(32, out_size)); + + return ak_error_ok; +} + +/** + * \brief Рнициализация контекста функции бесключевого хеширования РЎРўР‘ 34.101.31-2020 (belt-hash). + * \param hctx Контекст функции хеширования, который будет заполнен + * \return Функция возвращает РєРѕРґ ошибки или \ref ak_error_ok (РІ случае успеха) + */ +int ak_hash_create_belt_hash( ak_hash hctx ) +{ + int error = ak_error_ok; + + if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to hash context" ); + if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL ) + return ak_error_message( ak_error_wrong_oid, __func__, + "incorrect internal search of belt-hash identifier" ); + if(( error = ak_mac_create( &hctx->mctx, 32, &hctx->data.bctx, + ak_hash_context_belt_hash_clean, + ak_hash_context_belt_hash_update, + ak_hash_context_belt_hash_finalize )) != ak_error_ok ) + return ak_error_message( error, __func__, "incorrect initialization of internal mac context" ); + + return ak_hash_context_belt_hash_clean( &hctx->data.bctx ); +} diff --git a/source/ak_hash.c b/source/ak_hash.c index efec30498afbf1a2368892719e5841614acb4bb6..4d0bf56f79f7386b225d0a045cc8d4cfa19f8f69 100644 --- a/source/ak_hash.c +++ b/source/ak_hash.c @@ -1512,7 +1512,7 @@ if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__, "destroying null pointer to hash context" ); hctx->oid = NULL; - memset( &hctx->data.sctx, 0, sizeof( struct streebog )); + memset( &hctx->data.sctx, 0, sizeof (&hctx->data) ); if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok ) ak_error_message( ak_error_get_value(), __func__, "incorrect cleaning of internal mac context" ); diff --git a/source/ak_oid.c b/source/ak_oid.c index 8cad564c4b4e365b37426fade4b27e59453c7cc2..3040f5e2d6f2d0502705bb205f5ea5e482da2f91 100644 --- a/source/ak_oid.c +++ b/source/ak_oid.c @@ -69,6 +69,8 @@ static const char *asn1_streebog256_i[] = { "1.2.643.7.1.1.2.2", NULL }; static const char *asn1_streebog512_n[] = { "streebog512", "md_gost12_512", NULL }; static const char *asn1_streebog512_i[] = { "1.2.643.7.1.1.2.3", NULL }; + static const char *asn1_belt_hash_n[] = { "belt-hash", NULL }; + static const char *asn1_belt_hash_i[] = { "1.2.112.0.2.0.34.101.31.81", NULL }; static const char *asn1_crc64_n[] = { "crc64", NULL }; static const char *asn1_crc64_i[] = { "1.2.643.2.52.1.2.2", NULL }; @@ -556,6 +558,10 @@ static struct oid libakrypt_oids[] = {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_streebog512, ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL }, ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }}, + { hash_function, algorithm, asn1_belt_hash_i, asn1_belt_hash_n, NULL, + {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_belt_hash, + ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL }, + ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }}, { hash_function, algorithm, asn1_crc64_i, asn1_crc64_n, NULL, {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_crc64, diff --git a/source/libakrypt.h b/source/libakrypt.h index c03e0c299b8c1a3b61d78fc5b0a583a4a07e3d54..415b12baff60b924e92fda43fdd8bbfd4eb0ed13 100644 --- a/source/libakrypt.h +++ b/source/libakrypt.h @@ -911,6 +911,20 @@ extern "C" { size_t hsize; } *ak_streebog; +/* ----------------------------------------------------------------------------------------------- */ +/*! \brief Структура для хранения внутренних данных функции хеширования семейства belt-hash */ +/* ----------------------------------------------------------------------------------------------- */ + typedef struct belt_hash { + /*! \brief Блок [4]len || [4]s */ + ak_uint32 ls[8]; + /*! \brief Временное значение С…СЌС€-СЃСѓРјРјС‹ */ + ak_uint32 h[8]; + /*! \brief Блок данных для шифрования */ + ak_uint8 block[32]; + /*! \brief Стек для работы beltCompr [12*4 байт] */ + ak_uint8 stack[12*4]; +} *ak_belt_hash; + /* ----------------------------------------------------------------------------------------------- */ /*! \brief Контекст бесключевой функции хеширования. */ /*! \details Класс предоставляет интерфейс для реализации бесключевых функций хеширования, построенных @@ -934,6 +948,8 @@ extern "C" { union { /*! \brief Структура алгоритмов семейства Стрибог. */ struct streebog sctx; + /*! \brief Структура алгоритма belt-hash. */ + struct belt_hash bctx; /*! \brief Вектор значений для алгоритмов семейства crc64 */ ak_uint64 b64; } data; @@ -944,6 +960,8 @@ extern "C" { dll_export int ak_hash_create_streebog256( ak_hash ); /*! \brief Рнициализация контекста функции бесключевого хеширования ГОСТ Р 34.11-2012 (Стрибог512). */ dll_export int ak_hash_create_streebog512( ak_hash ); +/*! \brief Рнициализация контекста функции бесключевого хеширования РЎРўР‘ 34.101.31-2020 (belt-hash). */ + dll_export int ak_hash_create_belt_hash( ak_hash ); /*! \brief Рнициализация контекста некриптографической функции хеширования crc64. */ dll_export int ak_hash_create_crc64( ak_hash ); /*! \brief Рнициализация контекста функции бесключевого хеширования РїРѕ заданному OID алгоритма. */