28147-89 - 3


18.5.


C++ ( Crypto++ 5.1)

#include "pch.h"

#include "gost.h"

#include "misc.h"

18.5

NAMESPACE_BEGIN(CryptoPP)

// S-

const byte GOST::Base::sBox[8][16]={

{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},

{14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},

{5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},

{7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3},

{6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},

{4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},

{13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},

{1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}};

bool GOST::Base::sTableCalculated = false;

word32 GOST::Base::sTable[4][256];

void GOST::Base::UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length)

{

AssertValidKeyLength(length);

PrecalculateSTable();

GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), 8, userKey,

KEYLENGTH);

}

void GOST::Base::PrecalculateSTable()

{

if (!sTableCalculated)

{

for (unsigned i = 0; i < 4; i++)

for (unsigned j = 0; j < 256; j++)

{

word32 temp = sBox[2*i][j%16] | (sBox[2*i+1][j/16] << 4);

sTable[i][j] = rotlMod(temp, 11+8*i);

}

sTableCalculated=true;

}

}

#define f(x) ( t=x, \

sTable[3][GETBYTE(t, 3)] ^ sTable[2][GETBYTE(t, 2)] \

18.5

^ sTable[1][GETBYTE(t, 1)] ^ sTable[0][GETBYTE(t, 0)] )

typedef BlockGetAndPut<word32, LittleEndian> Block;

void GOST::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const

{

word32 n1, n2, t;

Block::Get(inBlock)(n1)(n2);

for (unsigned int i=0; i<3; i++)

{

n2 ^= f(n1+key[0]);

n1 ^= f(n2+key[1]);

n2 ^= f(n1+key[2]);

n1 ^= f(n2+key[3]);

n2 ^= f(n1+key[4]);