Source

Target

View open merge request
Commits (43)
Showing with 622 additions and 1 deletion
+622 -1
......@@ -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 )
......
#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;
}
/* ----------------------------------------------------------------------------------------------- */
/* */
/* Реализация хэширования сообщения */
/* из Белорусского стандарта СТБ 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 );
}
......@@ -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" );
......
......@@ -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,
......
......@@ -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 алгоритма. */
......