00001 #include "pch.h"
00002 #include "gost.h"
00003 #include "misc.h"
00004
00005 NAMESPACE_BEGIN(CryptoPP)
00006
00007
00008 const byte GOST::Base::sBox[8][16]={
00009 {4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
00010 {14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},
00011 {5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},
00012 {7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3},
00013 {6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},
00014 {4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},
00015 {13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},
00016 {1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}};
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 volatile bool GOST::Base::sTableCalculated = false;
00031 word32 GOST::Base::sTable[4][256];
00032
00033 void GOST::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
00034 {
00035 AssertValidKeyLength(length);
00036
00037 PrecalculateSTable();
00038
00039 GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), 8, userKey, KEYLENGTH);
00040 }
00041
00042 void GOST::Base::PrecalculateSTable()
00043 {
00044 if (!sTableCalculated)
00045 {
00046 for (unsigned i = 0; i < 4; i++)
00047 for (unsigned j = 0; j < 256; j++)
00048 {
00049 word32 temp = sBox[2*i][j%16] | (sBox[2*i+1][j/16] << 4);
00050 sTable[i][j] = rotlMod(temp, 11+8*i);
00051 }
00052
00053 sTableCalculated=true;
00054 }
00055 }
00056
00057 #define f(x) ( t=x, \
00058 sTable[3][GETBYTE(t, 3)] ^ sTable[2][GETBYTE(t, 2)] \
00059 ^ sTable[1][GETBYTE(t, 1)] ^ sTable[0][GETBYTE(t, 0)] )
00060
00061 typedef BlockGetAndPut<word32, LittleEndian> Block;
00062
00063 void GOST::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00064 {
00065 word32 n1, n2, t;
00066
00067 Block::Get(inBlock)(n1)(n2);
00068
00069 for (unsigned int i=0; i<3; i++)
00070 {
00071 n2 ^= f(n1+key[0]);
00072 n1 ^= f(n2+key[1]);
00073 n2 ^= f(n1+key[2]);
00074 n1 ^= f(n2+key[3]);
00075 n2 ^= f(n1+key[4]);
00076 n1 ^= f(n2+key[5]);
00077 n2 ^= f(n1+key[6]);
00078 n1 ^= f(n2+key[7]);
00079 }
00080
00081 n2 ^= f(n1+key[7]);
00082 n1 ^= f(n2+key[6]);
00083 n2 ^= f(n1+key[5]);
00084 n1 ^= f(n2+key[4]);
00085 n2 ^= f(n1+key[3]);
00086 n1 ^= f(n2+key[2]);
00087 n2 ^= f(n1+key[1]);
00088 n1 ^= f(n2+key[0]);
00089
00090 Block::Put(xorBlock, outBlock)(n2)(n1);
00091 }
00092
00093 void GOST::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00094 {
00095 word32 n1, n2, t;
00096
00097 Block::Get(inBlock)(n1)(n2);
00098
00099 n2 ^= f(n1+key[0]);
00100 n1 ^= f(n2+key[1]);
00101 n2 ^= f(n1+key[2]);
00102 n1 ^= f(n2+key[3]);
00103 n2 ^= f(n1+key[4]);
00104 n1 ^= f(n2+key[5]);
00105 n2 ^= f(n1+key[6]);
00106 n1 ^= f(n2+key[7]);
00107
00108 for (unsigned int i=0; i<3; i++)
00109 {
00110 n2 ^= f(n1+key[7]);
00111 n1 ^= f(n2+key[6]);
00112 n2 ^= f(n1+key[5]);
00113 n1 ^= f(n2+key[4]);
00114 n2 ^= f(n1+key[3]);
00115 n1 ^= f(n2+key[2]);
00116 n2 ^= f(n1+key[1]);
00117 n1 ^= f(n2+key[0]);
00118 }
00119
00120 Block::Put(xorBlock, outBlock)(n2)(n1);
00121 }
00122
00123 NAMESPACE_END