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