1#include "pch.h" 2#include "gost.h" 3#include "misc.h" 4 5NAMESPACE_BEGIN(CryptoPP) 6 7// these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333 8const byte GOST::Base::sBox[8][16]={ 9 {4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3}, 10 {14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9}, 11 {5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11}, 12 {7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3}, 13 {6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2}, 14 {4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14}, 15 {13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12}, 16 {1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}}; 17 18/* // these are the S-boxes given in the GOST source code listing in Applied 19 // Cryptography 2nd Ed., p. 644. they appear to be from the DES S-boxes 20 {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, 21 { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, 22 {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, 23 { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, 24 { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, 25 {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, 26 {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, 27 {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }}; 28*/ 29 30bool GOST::Base::sTableCalculated = false; 31word32 GOST::Base::sTable[4][256]; 32 33void GOST::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) 34{ 35 AssertValidKeyLength(length); 36 37 PrecalculateSTable(); 38 39 GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), 8, userKey, KEYLENGTH); 40} 41 42void GOST::Base::PrecalculateSTable() 43{ 44 if (!sTableCalculated) 45 { 46 for (unsigned i = 0; i < 4; i++) 47 for (unsigned j = 0; j < 256; j++) 48 { 49 word32 temp = sBox[2*i][j%16] | (sBox[2*i+1][j/16] << 4); 50 sTable[i][j] = rotlMod(temp, 11+8*i); 51 } 52 53 sTableCalculated=true; 54 } 55} 56 57#define f(x) ( t=x, \ 58 sTable[3][GETBYTE(t, 3)] ^ sTable[2][GETBYTE(t, 2)] \ 59 ^ sTable[1][GETBYTE(t, 1)] ^ sTable[0][GETBYTE(t, 0)] ) 60 61typedef BlockGetAndPut<word32, LittleEndian> Block; 62 63void GOST::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 64{ 65 word32 n1, n2, t; 66 67 Block::Get(inBlock)(n1)(n2); 68 69 for (unsigned int i=0; i<3; i++) 70 { 71 n2 ^= f(n1+key[0]); 72 n1 ^= f(n2+key[1]); 73 n2 ^= f(n1+key[2]); 74 n1 ^= f(n2+key[3]); 75 n2 ^= f(n1+key[4]); 76 n1 ^= f(n2+key[5]); 77 n2 ^= f(n1+key[6]); 78 n1 ^= f(n2+key[7]); 79 } 80 81 n2 ^= f(n1+key[7]); 82 n1 ^= f(n2+key[6]); 83 n2 ^= f(n1+key[5]); 84 n1 ^= f(n2+key[4]); 85 n2 ^= f(n1+key[3]); 86 n1 ^= f(n2+key[2]); 87 n2 ^= f(n1+key[1]); 88 n1 ^= f(n2+key[0]); 89 90 Block::Put(xorBlock, outBlock)(n2)(n1); 91} 92 93void GOST::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 94{ 95 word32 n1, n2, t; 96 97 Block::Get(inBlock)(n1)(n2); 98 99 n2 ^= f(n1+key[0]); 100 n1 ^= f(n2+key[1]); 101 n2 ^= f(n1+key[2]); 102 n1 ^= f(n2+key[3]); 103 n2 ^= f(n1+key[4]); 104 n1 ^= f(n2+key[5]); 105 n2 ^= f(n1+key[6]); 106 n1 ^= f(n2+key[7]); 107 108 for (unsigned int i=0; i<3; i++) 109 { 110 n2 ^= f(n1+key[7]); 111 n1 ^= f(n2+key[6]); 112 n2 ^= f(n1+key[5]); 113 n1 ^= f(n2+key[4]); 114 n2 ^= f(n1+key[3]); 115 n1 ^= f(n2+key[2]); 116 n2 ^= f(n1+key[1]); 117 n1 ^= f(n2+key[0]); 118 } 119 120 Block::Put(xorBlock, outBlock)(n2)(n1); 121} 122 123NAMESPACE_END 124