Windows: Add Magma cipher (GOST-89)

This commit is contained in:
Mounir IDRASSI 2016-08-09 09:54:00 +02:00
parent 460f552a41
commit 0b2c8b09c6
No known key found for this signature in database
GPG Key ID: DD0C382D5FCFB8FC
11 changed files with 889 additions and 8 deletions

View File

@ -23,6 +23,7 @@
#include "Volumes.h" #include "Volumes.h"
#include "cpu.h" #include "cpu.h"
#pragma warning (disable:4706) // assignment within conditional expression
/* Update the following when adding a new cipher or EA: /* Update the following when adding a new cipher or EA:
Crypto.h: Crypto.h:
@ -54,6 +55,9 @@ static Cipher Ciphers[] =
{ SERPENT, L"Serpent", 16, 32, 140*4 }, { SERPENT, L"Serpent", 16, 32, 140*4 },
{ TWOFISH, L"Twofish", 16, 32, TWOFISH_KS }, { TWOFISH, L"Twofish", 16, 32, TWOFISH_KS },
{ CAMELLIA, L"Camellia", 16, 32, CAMELLIA_KS }, { CAMELLIA, L"Camellia", 16, 32, CAMELLIA_KS },
#if defined(CIPHER_GOST89)
{ GOST89, L"GOST89", 16, 32, GOST_KS },
#endif // defined(CIPHER_GOST89)
#endif #endif
{ 0, 0, 0, 0, 0 } { 0, 0, 0, 0, 0 }
}; };
@ -71,6 +75,9 @@ static EncryptionAlgorithm EncryptionAlgorithms[] =
{ { SERPENT, 0 }, { XTS, 0 }, 1 }, { { SERPENT, 0 }, { XTS, 0 }, 1 },
{ { TWOFISH, 0 }, { XTS, 0 }, 1 }, { { TWOFISH, 0 }, { XTS, 0 }, 1 },
{ { CAMELLIA, 0 }, { XTS, 0 }, 1 }, { { CAMELLIA, 0 }, { XTS, 0 }, 1 },
#if defined(CIPHER_GOST89)
{ { GOST89, 0 }, { XTS, 0 }, 1 },
#endif // defined(CIPHER_GOST89)
{ { TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, { { TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
{ { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, { { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
{ { AES, SERPENT, 0 }, { XTS, 0 }, 1 }, { { AES, SERPENT, 0 }, { XTS, 0 }, 1 },
@ -143,6 +150,14 @@ int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks)
break; break;
#endif #endif
#if !defined(TC_WINDOWS_BOOT)
#if defined(CIPHER_GOST89)
case GOST89:
gost_set_key(key, (gost_kds*)ks);
break;
#endif // && defined(CIPHER_GOST89)
#endif // !defined(TC_WINDOWS_BOOT)
default: default:
// Unknown/wrong cipher ID // Unknown/wrong cipher ID
return ERR_CIPHER_INIT_FAILURE; return ERR_CIPHER_INIT_FAILURE;
@ -170,6 +185,11 @@ void EncipherBlock(int cipher, void *data, void *ks)
#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA) #if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA)
case CAMELLIA: camellia_encrypt (data, data, ks); break; case CAMELLIA: camellia_encrypt (data, data, ks); break;
#endif #endif
#if !defined(TC_WINDOWS_BOOT)
#if defined(CIPHER_GOST89)
case GOST89: gost_encrypt(data, data, ks, 1); break;
#endif // defined(CIPHER_GOST89)
#endif // !defined(TC_WINDOWS_BOOT)
default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID
} }
} }
@ -203,6 +223,9 @@ void EncipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
KeRestoreFloatingPointState (&floatingPointState); KeRestoreFloatingPointState (&floatingPointState);
#endif #endif
} }
else if (cipher == GOST89) {
gost_encrypt(data, data, ks, (int)blockCount);
}
else else
{ {
size_t blockSize = CipherGetBlockSize (cipher); size_t blockSize = CipherGetBlockSize (cipher);
@ -225,6 +248,13 @@ void DecipherBlock(int cipher, void *data, void *ks)
#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA) #if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA)
case CAMELLIA: camellia_decrypt (data, data, ks); break; case CAMELLIA: camellia_decrypt (data, data, ks); break;
#endif #endif
#if !defined(TC_WINDOWS_BOOT)
#if defined(CIPHER_GOST89)
case GOST89: gost_decrypt(data, data, ks, 1); break;
#endif // defined(CIPHER_GOST89)
#endif // !defined(TC_WINDOWS_BOOT)
#ifndef TC_WINDOWS_BOOT #ifndef TC_WINDOWS_BOOT
case AES: case AES:
@ -272,6 +302,9 @@ void DecipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
KeRestoreFloatingPointState (&floatingPointState); KeRestoreFloatingPointState (&floatingPointState);
#endif #endif
} }
else if (cipher == GOST89) {
gost_decrypt(data, data, ks, (int)blockCount);
}
else else
{ {
size_t blockSize = CipherGetBlockSize (cipher); size_t blockSize = CipherGetBlockSize (cipher);
@ -340,7 +373,8 @@ int CipherGetKeyScheduleSize (int cipherId)
BOOL CipherSupportsIntraDataUnitParallelization (int cipher) BOOL CipherSupportsIntraDataUnitParallelization (int cipher)
{ {
return cipher == AES && IsAesHwCpuSupported(); return cipher == AES && IsAesHwCpuSupported() ||
cipher == GOST89;
} }
#endif #endif

View File

@ -107,7 +107,8 @@ enum
AES, AES,
SERPENT, SERPENT,
TWOFISH, TWOFISH,
CAMELLIA CAMELLIA,
GOST89
}; };
typedef struct typedef struct
@ -189,9 +190,10 @@ typedef struct
#ifndef TC_WINDOWS_BOOT #ifndef TC_WINDOWS_BOOT
# include "Sha2.h" # include "Sha2.h"
# include "Whirlpool.h" # include "Whirlpool.h"
# include "Camellia.h" # include "GostCipher.h"
# include "Camellia.h"
#else #else
# include "CamelliaSmall.h" # include "CamelliaSmall.h"
#endif #endif
#include "GfMul.h" #include "GfMul.h"

View File

@ -497,7 +497,11 @@ void CipherInit2(int cipher, void* key, void* ks, int key_len)
case CAMELLIA: case CAMELLIA:
CipherInit(cipher,key,ks); CipherInit(cipher,key,ks);
break; break;
#if defined(CIPHER_GOST89)
case GOST89:
CipherInit(cipher,key,ks);
break;
#endif // defined(CIPHER_GOST89)
default: default:
/* Unknown/wrong ID */ /* Unknown/wrong ID */
TC_THROW_FATAL_EXCEPTION; TC_THROW_FATAL_EXCEPTION;
@ -925,8 +929,11 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci)
nTestsPerformed++; nTestsPerformed++;
} }
#if defined(CIPHER_GOST89)
return (nTestsPerformed == 90); return (nTestsPerformed == 100);
#else
return (nTestsPerformed == 95);
#endif
} }
static BOOL DoAutoTestAlgorithms (void) static BOOL DoAutoTestAlgorithms (void)

View File

@ -199,6 +199,16 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox --prefix _ -o "$(TargetDir)\%(Filename).obj" -l "$(TargetDir)\%(Filename).lst" "%(FullPath)" <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox --prefix _ -o "$(TargetDir)\%(Filename).obj" -l "$(TargetDir)\%(Filename).lst" "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Include="Gost89_x64.asm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -o "$(TargetDir)\%(Filename).obj" -l "$(TargetDir)\%(Filename).lst" "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -o "$(TargetDir)\%(Filename).obj" -l "$(TargetDir)\%(Filename).lst" "%(FullPath)"
</Command> </Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
</CustomBuild> </CustomBuild>
@ -208,6 +218,7 @@
<ClCompile Include="Aestab.c" /> <ClCompile Include="Aestab.c" />
<ClCompile Include="Camellia.c" /> <ClCompile Include="Camellia.c" />
<ClCompile Include="cpu.c" /> <ClCompile Include="cpu.c" />
<ClCompile Include="GostCipher.c" />
<ClCompile Include="Rmd160.c" /> <ClCompile Include="Rmd160.c" />
<ClCompile Include="Serpent.c" /> <ClCompile Include="Serpent.c" />
<ClCompile Include="Sha2.c" /> <ClCompile Include="Sha2.c" />
@ -222,6 +233,7 @@
<ClInclude Include="Camellia.h" /> <ClInclude Include="Camellia.h" />
<ClInclude Include="config.h" /> <ClInclude Include="config.h" />
<ClInclude Include="cpu.h" /> <ClInclude Include="cpu.h" />
<ClInclude Include="GostCipher.h" />
<ClInclude Include="misc.h" /> <ClInclude Include="misc.h" />
<ClInclude Include="Rmd160.h" /> <ClInclude Include="Rmd160.h" />
<ClInclude Include="Serpent.h" /> <ClInclude Include="Serpent.h" />

View File

@ -42,6 +42,9 @@
<ClCompile Include="Whirlpool.c"> <ClCompile Include="Whirlpool.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="GostCipher.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Aes.h"> <ClInclude Include="Aes.h">
@ -83,6 +86,9 @@
<ClInclude Include="Whirlpool.h"> <ClInclude Include="Whirlpool.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="GostCipher.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="Aes_hw_cpu.asm"> <CustomBuild Include="Aes_hw_cpu.asm">
@ -94,5 +100,8 @@
<CustomBuild Include="Aes_x86.asm"> <CustomBuild Include="Aes_x86.asm">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="Gost89_x64.asm">
<Filter>Source Files</Filter>
</CustomBuild>
</ItemGroup> </ItemGroup>
</Project> </Project>

269
src/Crypto/GostCipher.c Normal file
View File

@ -0,0 +1,269 @@
/** @file
GOST89 implementation
Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the Apache License, Version 2.0. The full text of the license may be found at
https://opensource.org/licenses/Apache-2.0
Dynamic SBOX idea is from GostCrypt project. Copyright (c) 2008-2011 TrueCrypt Developers Association
**/
#include "GostCipher.h"
#include "Streebog.h"
#include "common\Tcdefs.h"
#include "cpu.h"
#if defined(CIPHER_GOST89)
// Crypto Pro
byte S_CryptoPro[8][16] = {
{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
{0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
{0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
};
// TC26
byte S_TC26[8][16] =
{
{ 0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1 },
{ 0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf },
{ 0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0 },
{ 0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb },
{ 0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc },
{ 0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0 },
{ 0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7 },
{ 0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2 },
};
void gost_prepare_kds(gost_kds* kds) {
uint32 i;
// Build substitution tables.
for (i = 0; i < 256; ++i) {
uint32 p;
p = kds->sbox[7][i >> 4] << 4 | kds->sbox[6][i & 15];
p = p << 24; p = p << 11 | p >> 21;
kds->sbox_cvt[i] = p; // S87
p = kds->sbox[5][i >> 4] << 4 | kds->sbox[4][i & 15];
p = p << 16; p = p << 11 | p >> 21;
kds->sbox_cvt[256 + i] = p; // S65
p = kds->sbox[3][i >> 4] << 4 | kds->sbox[2][i & 15];
p = p << 8; p = p << 11 | p >> 21;
kds->sbox_cvt[256 * 2 + i] = p; // S43
p = kds->sbox[1][i >> 4] << 4 | kds->sbox[0][i & 15];
p = p << 11 | p >> 21;
kds->sbox_cvt[256 * 3 + i] = p; // S21
}
}
#ifdef GOST_DYNAMIC_SBOXES
static void xor_s_box(byte s_box[8][16], byte *seed)
{
int i;
for (i = 0; i < 16; i++)
{
s_box[1][i] ^= (seed[ (i * 4) + 0 ] ) & 0xF;
s_box[2][i] ^= (seed[ (i * 4) + 0 ]>>4) & 0xF;
s_box[3][i] ^= (seed[ (i * 4) + 1 ] ) & 0xF;
s_box[4][i] ^= (seed[ (i * 4) + 1 ]>>4) & 0xF;
s_box[5][i] ^= (seed[ (i * 4) + 2 ] ) & 0xF;
s_box[6][i] ^= (seed[ (i * 4) + 2 ]>>4) & 0xF;
s_box[7][i] ^= (seed[ (i * 4) + 3 ] ) & 0xF;
s_box[8][i] ^= (seed[ (i * 4) + 3 ]>>4) & 0xF;
}
}
#endif
void gost_set_key(byte *key, gost_kds *ks)
{
#ifdef GOST_DYNAMIC_SBOXES
STREEBOG_CTX sctx;
byte sbox_seed[64];
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
KFLOATING_SAVE floatingPointState;
NTSTATUS saveStatus = STATUS_SUCCESS;
if (HasSSE2() || HasSSE41())
saveStatus = KeSaveFloatingPointState (&floatingPointState);
#endif
#endif
memcpy(ks->key, key, GOST_KEYSIZE);
memcpy(ks->sbox, S_TC26, sizeof(ks->sbox));
#ifdef GOST_DYNAMIC_SBOXES
//Generate pseudorandom data based on the key
STREEBOG_init(&sctx);
STREEBOG_add(&sctx, key, 32);
STREEBOG_finalize(&sctx, sbox_seed);
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
if (NT_SUCCESS (saveStatus) && (HasSSE2() || HasSSE41()))
KeRestoreFloatingPointState (&floatingPointState);
#endif
xor_s_box(ks->sbox, sbox_seed);
#endif
gost_prepare_kds(ks);
}
static uint32 f(uint32 v, uint32* sbox){
byte* x =(byte*) &v;
/* Do substitutions */
return sbox[x[3]] | sbox[256 + x[2]] | sbox[256*2 + x[1]] | sbox[256*3 + x[0]];
}
void gost_encrypt_block(uint64 in_, uint64* out_, gost_kds* kds) {
uint32* in = (uint32*)&in_;
uint32* out = (uint32*)out_;
uint32* key = (uint32*)kds->key;
uint32* sbox = kds->sbox_cvt;
// As named in the GOST
uint32 n1 = in[0];
uint32 n2 = in[1];
n2 ^= f(n1+key[0], sbox);
n1 ^= f(n2+key[1], sbox);
n2 ^= f(n1+key[2], sbox);
n1 ^= f(n2+key[3], sbox);
n2 ^= f(n1+key[4], sbox);
n1 ^= f(n2+key[5], sbox);
n2 ^= f(n1+key[6], sbox);
n1 ^= f(n2+key[7], sbox);
n2 ^= f(n1+key[0], sbox);
n1 ^= f(n2+key[1], sbox);
n2 ^= f(n1+key[2], sbox);
n1 ^= f(n2+key[3], sbox);
n2 ^= f(n1+key[4], sbox);
n1 ^= f(n2+key[5], sbox);
n2 ^= f(n1+key[6], sbox);
n1 ^= f(n2+key[7], sbox);
n2 ^= f(n1+key[0], sbox);
n1 ^= f(n2+key[1], sbox);
n2 ^= f(n1+key[2], sbox);
n1 ^= f(n2+key[3], sbox);
n2 ^= f(n1+key[4], sbox);
n1 ^= f(n2+key[5], sbox);
n2 ^= f(n1+key[6], sbox);
n1 ^= f(n2+key[7], sbox);
n2 ^= f(n1+key[7], sbox);
n1 ^= f(n2+key[6], sbox);
n2 ^= f(n1+key[5], sbox);
n1 ^= f(n2+key[4], sbox);
n2 ^= f(n1+key[3], sbox);
n1 ^= f(n2+key[2], sbox);
n2 ^= f(n1+key[1], sbox);
n1 ^= f(n2+key[0], sbox);
// There is no swap after the last round
out[0] = n2;
out[1] = n1;
}
void gost_decrypt_block(uint64 in_, uint64* out_, gost_kds* kds) {
uint32* in = (uint32*)&in_;
uint32* out = (uint32*)out_;
uint32* key = (uint32*)kds->key;
uint32* sbox = kds->sbox_cvt;
// As named in the GOST
uint32 n1 = in[0];
uint32 n2 = in[1];
n2 ^= f(n1+key[0], sbox);
n1 ^= f(n2+key[1], sbox);
n2 ^= f(n1+key[2], sbox);
n1 ^= f(n2+key[3], sbox);
n2 ^= f(n1+key[4], sbox);
n1 ^= f(n2+key[5], sbox);
n2 ^= f(n1+key[6], sbox);
n1 ^= f(n2+key[7], sbox);
n2 ^= f(n1+key[7], sbox);
n1 ^= f(n2+key[6], sbox);
n2 ^= f(n1+key[5], sbox);
n1 ^= f(n2+key[4], sbox);
n2 ^= f(n1+key[3], sbox);
n1 ^= f(n2+key[2], sbox);
n2 ^= f(n1+key[1], sbox);
n1 ^= f(n2+key[0], sbox);
n2 ^= f(n1+key[7], sbox);
n1 ^= f(n2+key[6], sbox);
n2 ^= f(n1+key[5], sbox);
n1 ^= f(n2+key[4], sbox);
n2 ^= f(n1+key[3], sbox);
n1 ^= f(n2+key[2], sbox);
n2 ^= f(n1+key[1], sbox);
n1 ^= f(n2+key[0], sbox);
n2 ^= f(n1+key[7], sbox);
n1 ^= f(n2+key[6], sbox);
n2 ^= f(n1+key[5], sbox);
n1 ^= f(n2+key[4], sbox);
n2 ^= f(n1+key[3], sbox);
n1 ^= f(n2+key[2], sbox);
n2 ^= f(n1+key[1], sbox);
n1 ^= f(n2+key[0], sbox);
out[0] = n2;
out[1] = n1;
}
#if defined(_M_AMD64)
void gost_encrypt_128_CBC_asm(byte *in, byte *out, gost_kds *ks, uint64 count);
void gost_decrypt_128_CBC_asm(byte *in, byte *out, gost_kds *ks, uint64 count);
#endif
void gost_encrypt(byte *in, byte *out, gost_kds *ks, int count) {
#if defined(_M_AMD64)
gost_encrypt_128_CBC_asm(in, out, ks, (uint64)count);
#else
while (count > 0) {
// encrypt two blocks in CBC mode
gost_encrypt_block(*((uint64*)in), (uint64*)out, ks);
*((gst_udword*)(out + 8)) = *((gst_udword*)(in + 8)) ^ *((gst_udword*)(out));
*((gst_udword*)(out + 12)) = *((gst_udword*)(in + 12)) ^ *((gst_udword*)(out + 4));
gost_encrypt_block(*((uint64*)(out + 8)), (uint64*)(out + 8), ks);
count--;
in += 16;
out += 16;
}
#endif
}
void gost_decrypt(byte *in, byte *out, gost_kds *ks, int count) {
#if defined(_M_AMD64)
gost_decrypt_128_CBC_asm(in, out, ks, (uint64)count);
#else
while (count > 0) {
// decrypt two blocks in CBC mode
gost_decrypt_block(*((uint64*)(in + 8)), (uint64*)(out + 8), ks);
*((gst_udword*)(out + 8)) ^= *((gst_udword*)(in));;
*((gst_udword*)(out + 12)) ^= *((gst_udword*)(in + 4));;
gost_decrypt_block(*((uint64*)(in)), (uint64*)(out), ks);
count--;
in += 16;
out += 16;
}
#endif
}
#endif

61
src/Crypto/GostCipher.h Normal file
View File

@ -0,0 +1,61 @@
/*
Copyright (c) 2008-2011 TrueCrypt Developers Association. All rights reserved.
Governed by the TrueCrypt License 3.0 the full text of which is contained in
the file License.txt included in TrueCrypt binary and source code distribution
packages.
*/
#ifndef GOST_CIPHER_H
#define GOST_CIPHER_H
//In unsigned chars
#define GOST_KEYSIZE 32
#define GOST_BLOCKSIZE 8
#define GOST_SBOX_SIZE 16
//Production setting, but can be turned off to compare the algorithm with other implementations
#define CIPHER_GOST89
#define GOST_DYNAMIC_SBOXES
#if defined(CIPHER_GOST89)
#ifndef rotl32
#define rotl32(b, shift) ((b << shift) | (b >> (32 - shift)))
#endif
typedef unsigned char byte;
#ifdef GST_WINDOWS_BOOT
typedef int gst_word;
typedef long gst_dword;
typedef unsigned int gst_uword;
typedef unsigned long gst_udword;
#else
typedef short gst_word;
typedef int gst_dword;
typedef unsigned short gst_uword;
typedef unsigned int gst_udword;
#endif
typedef struct gost_kds
{
byte key[32];
gst_udword sbox_cvt[256 * 4];
byte sbox[8][16];
} gost_kds;
#define GOST_KS (sizeof(gost_kds))
void gost_encrypt(byte *in, byte *out, gost_kds *ks, int count);
void gost_decrypt(byte *in, byte *out, gost_kds *ks, int count);
void gost_set_key(byte *key, gost_kds *ks);
#else
#define GOST_KS (0)
#endif
#endif

View File

@ -8,6 +8,9 @@ TC_ASFLAGS = $(TC_ASFLAGS) -f win64
TC_ASM_ERR_LOG = ..\Driver\build_errors_asm.log TC_ASM_ERR_LOG = ..\Driver\build_errors_asm.log
"$(OBJ_PATH)\$(O)\gost89_$(TC_ARCH).obj": gost89_$(TC_ARCH).asm
nasm.exe $(TC_ASFLAGS) -o "$@" -l "$(OBJ_PATH)\$(O)\gost89_$(TC_ARCH).lst" gost89_$(TC_ARCH).asm 2>$(TC_ASM_ERR_LOG)
"$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj": Aes_$(TC_ARCH).asm "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj": Aes_$(TC_ARCH).asm
nasm.exe $(TC_ASFLAGS) -o "$@" -l "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).lst" Aes_$(TC_ARCH).asm 2>$(TC_ASM_ERR_LOG) nasm.exe $(TC_ASFLAGS) -o "$@" -l "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).lst" Aes_$(TC_ARCH).asm 2>$(TC_ASM_ERR_LOG)

View File

@ -5,10 +5,12 @@ INCLUDES = ..
NTTARGETFILES = \ NTTARGETFILES = \
"$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj" \ "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj" \
"$(OBJ_PATH)\$(O)\Aes_hw_cpu.obj" "$(OBJ_PATH)\$(O)\Aes_hw_cpu.obj" \
"$(OBJ_PATH)\$(O)\gost89_$(TC_ARCH).obj"
SOURCES = \ SOURCES = \
Aes_$(TC_ARCH).asm \ Aes_$(TC_ARCH).asm \
gost89_$(TC_ARCH).asm \
Aes_hw_cpu.asm \ Aes_hw_cpu.asm \
Aeskey.c \ Aeskey.c \
Aestab.c \ Aestab.c \
@ -17,5 +19,6 @@ SOURCES = \
Serpent.c \ Serpent.c \
Sha2.c \ Sha2.c \
Twofish.c \ Twofish.c \
GostCipher.c \
Whirlpool.c \ Whirlpool.c \
Camellia.c Camellia.c

481
src/Crypto/gost89_x64.asm Normal file
View File

@ -0,0 +1,481 @@
;
; GOST89 implementation x64
;
; Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
;
; This program and the accompanying materials
; are licensed and made available under the terms and conditions
; of the Apache License, Version 2.0. The full text of the license may be found at
; https://opensource.org/licenses/Apache-2.0
;
; Some ideas from article https://xakep.ru/2013/10/19/shifrovanie-gost-28147-89/
;
[section .bss align=16]
;///////////////////////////////////////////////////////////////////
;// Win64 registers to save
;///////////////////////////////////////////////////////////////////
%macro SaveRegs 0
sub rsp,8*8+10*16
mov [rsp], rbx
mov [rsp+8], rbp
mov [rsp+8*2], rdi
mov [rsp+8*3], rsi
mov [rsp+8*4], r12
mov [rsp+8*5], r13
mov [rsp+8*6], r14
mov [rsp+8*7], r15
%endmacro
%macro RestoreRegs 0
mov rbx, [rsp]
mov rbp, [rsp+8]
mov rdi, [rsp+8*2]
mov rsi, [rsp+8*3]
mov r12, [rsp+8*4]
mov r13, [rsp+8*5]
mov r14, [rsp+8*6]
mov r15, [rsp+8*7]
add rsp,8*8+10*16
%endmacro
[section .text align=16]
;///////////////////////////////////////////////////////////////////
;// Crypting 2 blocks
;///////////////////////////////////////////////////////////////////
%macro gost_round2 2 ; 1 - pos1, 2 - pos2
; 1st
; 1-2 byte
add ecx, r13d ; add key
movzx edi, cl
movzx esi, ch
xor r14d, dword [r8 + 32 + 256*3*4 + rdi*4]
xor r14d, dword [r8 + 32 + 256*2*4 + rsi*4]
shr ecx, 16
; 3-4 áàéò
movzx edi, cl
xor r14d, dword [r8 + 32 + 256*4 + rdi*4]
movzx esi, ch
xor r14d, dword [r8 + 32 + rsi*4]
mov edx, [r8 + %1*4] ; read key for second step
; 2nd
; 1-2 byte
add eax, r10d ; read key
movzx r15d, al
movzx ebp, ah
xor r11d, dword [r8 + 32 + 256*3*4 + r15*4]
xor r11d, dword [r8 + 32 + 256*2*4 + rbp*4]
shr eax, 16
; 3-4 áàéò
movzx r15d, al
xor r11d, dword [r8 + 32 + 256*4 + r15*4]
movzx ebp, ah
xor r11d, dword [r8 + 32 + rbp*4]
mov ebx, [r8 + %1*4] ; read key for second step
; second step
; 1st
; 1-2 byte
add edx, r14d ; add key
movzx edi, dl
movzx esi, dh
xor r13d, dword [r8 + 32 + 256*3*4 + rdi*4]
xor r13d, dword [r8 + 32 + 256*2*4 + rsi*4]
shr edx, 16
; 3-4 áàéò
movzx edi, dl
xor r13d, dword [r8 + 32 + 256*4 + rdi*4]
movzx esi, dh
xor r13d, dword [r8 + 32 + rsi*4]
mov ecx, [r8 + %2*4] ; read key
; 2nd
; 1-2 byte
add ebx, r11d; ; add key
movzx r15d, bl;
movzx ebp, bh;
xor r10d, dword [r8 + 32 + 256*3*4 + r15*4]
xor r10d, dword [r8 + 32 + 256*2*4 + rbp*4]
shr ebx, 16
; 3-4 áàéò
movzx r15d, bl
xor r10d, dword [r8 + 32 + 256*4 + r15*4]
movzx ebp, bh
xor r10d, dword [r8 + 32 + rbp*4]
mov eax, [r8 + %2*4] ; read key
%endmacro
; input: r8 - &key, rdx - &IN
; returns: (r13) & (r10)
GostEncrypt2x64:
; 1st
mov r13d, [rdx]
mov r14, [rdx]
shr r14, 32
; 2nd
mov r10d, [rdx + 16]
mov r11, [rdx + 16]
shr r11, 32
mov ecx, [r8]
mov eax, ecx
gost_round2 1, 2
gost_round2 3, 4
gost_round2 5, 6
gost_round2 7, 0
gost_round2 1, 2
gost_round2 3, 4
gost_round2 5, 6
gost_round2 7, 0
gost_round2 1, 2
gost_round2 3, 4
gost_round2 5, 6
gost_round2 7, 7
gost_round2 6, 5
gost_round2 4, 3
gost_round2 2, 1
gost_round2 0, 0
shl r13, 32 ; combine
or r13, r14
shl r10, 32 ; combine
or r10, r11
ret
; input: r8 - &key, rdx - &IN
; returns: (r13) & (r10)
GostDecrypt2x64:
; 1st
mov r13d, [rdx]
mov r14, [rdx]
shr r14, 32
; 2nd
mov r10d, [rdx + 16]
mov r11, [rdx + 16]
shr r11, 32
mov ecx, [r8]
mov eax, ecx
gost_round2 1, 2
gost_round2 3, 4
gost_round2 5, 6
gost_round2 7, 7
gost_round2 6, 5
gost_round2 4, 3
gost_round2 2, 1
gost_round2 0, 7
gost_round2 6, 5
gost_round2 4, 3
gost_round2 2, 1
gost_round2 0, 7
gost_round2 6, 5
gost_round2 4, 3
gost_round2 2, 1
gost_round2 0, 0
shl r13, 32 ; combine
or r13, r14
shl r10, 32 ; combine
or r10, r11
ret
;///////////////////////////////////////////////////////////////////
;// Crypting 1 block
;///////////////////////////////////////////////////////////////////
%macro gost_round1 2 ; 1 - pos1, 2 - pos2
; 1-2 byte
add ecx, r13d ; add key
movzx edi, cl
movzx esi, ch
xor r14d, dword [r8 + 32 + 256*3*4 + rdi*4]
xor r14d, dword [r8 + 32 + 256*2*4 + rsi*4]
shr ecx, 16
; 3-4 áàéò
movzx edi, cl
xor r14d, dword [r8 + 32 + 256*4 + rdi*4]
movzx esi, ch
xor r14d, dword [r8 + 32 + rsi*4]
mov edx, [r8 + %1*4] ; read key for second step
; second step
; 1-2 byte
add edx, r14d ; add key
movzx edi, dl
movzx esi, dh
xor r13d, dword [r8 + 32 + 256*3*4 + rdi*4]
xor r13d, dword [r8 + 32 + 256*2*4 + rsi*4]
shr edx, 16
; 3-4 áàéò
movzx edi, dl
xor r13d, dword [r8 + 32 + 256*4 + rdi*4]
movzx esi, dh
xor r13d, dword [r8 + 32 + rsi*4]
mov ecx, [r8 + %2*4] ; read key
%endmacro
; input: r8 - &gost_kds rdx - &IN
; returns: r13
GostEncrypt1x64:
mov r13d, [rdx]
mov r14, [rdx]
shr r14, 32
mov ecx, [r8]
gost_round1 1, 2
gost_round1 3, 4
gost_round1 5, 6
gost_round1 7, 0
gost_round1 1, 2
gost_round1 3, 4
gost_round1 5, 6
gost_round1 7, 0
gost_round1 1, 2
gost_round1 3, 4
gost_round1 5, 6
gost_round1 7, 7
gost_round1 6, 5
gost_round1 4, 3
gost_round1 2, 1
gost_round1 0, 0
shl r13, 32 ; combine
or r13, r14
ret
; input: r8 - &gost_kds rdx - IN
; returns: r13
GostDecrypt1x64:
mov r13d, [rdx]
mov r14, [rdx]
shr r14, 32
mov ecx, [r8]
gost_round1 1, 2
gost_round1 3, 4
gost_round1 5, 6
gost_round1 7, 7
gost_round1 6, 5
gost_round1 4, 3
gost_round1 2, 1
gost_round1 0, 7
gost_round1 6, 5
gost_round1 4, 3
gost_round1 2, 1
gost_round1 0, 7
gost_round1 6, 5
gost_round1 4, 3
gost_round1 2, 1
gost_round1 0, 0
shl r13, 32 ; combine
or r13, r14
ret
global gost_encrypt_128_CBC_asm ; gost_encrypt_128_CBC_asm(uint64* out, uint64* in, gost_kds* kds, uint64 count);
; rcx - &out
; rdx - &in
; r8 - &gost_kds
; r9 - count
gost_encrypt_128_CBC_asm:
SaveRegs ; Saving
sub rsp, 32
mov [rsp], rcx ; Save out addr
mov [rsp + 8], rdx ; Save in addr
mov [rsp + 16], r8 ; key addr
.do:
mov [rsp + 24], r9 ; Save count
cmp r9, 2
jge .blk2
cmp r9, 1
jge .blk1
jmp .end
; One 128 block encryption
.blk1:
mov rdx, [rsp + 8] ; set in addr
call GostEncrypt1x64
mov rcx, [rsp] ; Restore out
mov rdx, [rsp + 8] ; restore in
mov [rcx], r13
mov rax, [rdx + 8]
xor rax, r13 ; CBC
add rcx, 8 ;next 8 bytes
mov [rcx], rax
mov rdx, rcx
call GostEncrypt1x64
mov rcx, [rsp] ; Restore out addr
mov rdx, [rsp+8] ; Restore in addr
mov [rcx + 8], r13
add rcx,16
mov [rsp], rcx
add rdx, 16
mov [rsp+8], rdx
mov r9, [rsp + 24]
dec r9
jmp .do
.blk2:
mov rdx, [rsp + 8] ; set in addr
call GostEncrypt2x64
mov rcx, [rsp] ; Restore out
mov rdx, [rsp + 8] ; restore in
mov [rcx], r13
mov rax, [rdx + 8]
xor rax, r13 ; CBC
mov [rcx + 16], r10
mov rbx, [rdx + 24]
xor rbx, r10 ; CBC
mov [rcx + 8], rax
mov [rcx + 24], rbx
add rcx, 8 ;next 8 bytes
mov rdx, rcx
call GostEncrypt2x64
mov rcx, [rsp] ; Restore out addr
mov rdx, [rsp+8] ; Restore in addr
mov [rcx + 8], r13
mov [rcx + 24], r10
add rcx,32
mov [rsp], rcx
add rdx, 32
mov [rsp+8], rdx
mov r9, [rsp + 24]
sub r9, 2
jmp .do
.end:
add rsp, 32 ; Load out addr
RestoreRegs ; Load
ret
global gost_decrypt_128_CBC_asm ; gost_decrypt_128_CBC_asm(uint64* out, uint64* in, const gost_kds* kds, uint64 count);
; rcx - &out
; rdx - &in
; r8 - &gost_kds
; r9 - count
gost_decrypt_128_CBC_asm:
SaveRegs ; Saving
sub rsp, 32
mov [rsp], rdx ; Save out addr
mov [rsp+8], rcx ; Save in addr
mov [rsp+16], r8 ; key addr
.do:
mov [rsp + 24], r9 ; Save count
cmp r9, 2
jge .blk2
cmp r9, 1
jge .blk1
jmp .end
; One 128 block decryption
.blk1:
add rdx, 8
call GostDecrypt1x64
mov rcx, [rsp] ; Restore out
mov rdx, [rsp + 8] ; Restore in
mov rax, [rdx]
xor rax, r13 ; CBC
mov [rcx + 8], rax
call GostDecrypt1x64
mov rcx, [rsp] ; Restore out addr
mov rdx, [rsp+8] ; Restore in addr
mov [rcx], r13
add rcx,16
mov [rsp], rcx
add rdx, 16
mov [rsp+8], rdx
mov r9, [rsp + 24]
dec r9
jmp .do
.blk2:
add rdx, 8
call GostDecrypt2x64
mov rcx, [rsp] ; Restore out
mov rdx, [rsp + 8] ; Restore in
mov rax, [rdx]
xor rax, r13 ; CBC
mov [rcx + 8], rax
mov rbx, [rdx+16]
xor rbx, r10 ; CBC
mov [rcx + 24], rbx
call GostDecrypt2x64
mov rcx, [rsp] ; Restore out addr
mov rdx, [rsp+8] ; Restore in addr
mov [rcx], r13
mov [rcx+16], r10
add rcx,32
mov [rsp], rcx
add rdx,32
mov [rsp+8], rdx
mov r9, [rsp + 24]
sub r9, 2
jmp .do
.end:
add rsp, 32 ; Load out addr
RestoreRegs ; Load
ret

View File