Crypto++
|
00001 // square.cpp - written and placed in the public domain by Wei Dai 00002 // Based on Paulo S.L.M. Barreto's public domain implementation 00003 00004 #include "pch.h" 00005 #include "square.h" 00006 #include "misc.h" 00007 #include "gf256.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 // apply theta to a roundkey 00012 static void SquareTransform (word32 in[4], word32 out[4]) 00013 { 00014 static const byte G[4][4] = 00015 { 00016 0x02U, 0x01U, 0x01U, 0x03U, 00017 0x03U, 0x02U, 0x01U, 0x01U, 00018 0x01U, 0x03U, 0x02U, 0x01U, 00019 0x01U, 0x01U, 0x03U, 0x02U 00020 }; 00021 00022 GF256 gf256(0xf5); 00023 00024 for (int i = 0; i < 4; i++) 00025 { 00026 word32 temp = 0; 00027 for (int j = 0; j < 4; j++) 00028 for (int k = 0; k < 4; k++) 00029 temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8); 00030 out[i] = temp; 00031 } 00032 } 00033 00034 #define roundkeys(i, j) m_roundkeys[(i)*4+(j)] 00035 #define roundkeys4(i) (m_roundkeys+(i)*4) 00036 00037 void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) 00038 { 00039 AssertValidKeyLength(length); 00040 00041 static const word32 offset[ROUNDS] = { 00042 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 00043 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 00044 }; 00045 00046 GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH); 00047 00048 /* apply the key evolution function */ 00049 for (int i = 1; i < ROUNDS+1; i++) 00050 { 00051 roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlFixed(roundkeys(i-1, 3), 8U) ^ offset[i-1]; 00052 roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0); 00053 roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1); 00054 roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2); 00055 } 00056 00057 /* produce the round keys */ 00058 if (IsForwardTransformation()) 00059 { 00060 for (int i = 0; i < ROUNDS; i++) 00061 SquareTransform (roundkeys4(i), roundkeys4(i)); 00062 } 00063 else 00064 { 00065 for (int i = 0; i < ROUNDS/2; i++) 00066 for (int j = 0; j < 4; j++) 00067 std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j)); 00068 SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS)); 00069 } 00070 } 00071 00072 #define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */ 00073 #define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */ 00074 #define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */ 00075 #define LSB(x) (((x) ) & 0xffU) /* least significant byte */ 00076 00077 #define squareRound(text, temp, T0, T1, T2, T3, roundkey) \ 00078 { \ 00079 temp[0] = T0[MSB (text[0])] \ 00080 ^ T1[MSB (text[1])] \ 00081 ^ T2[MSB (text[2])] \ 00082 ^ T3[MSB (text[3])] \ 00083 ^ roundkey[0]; \ 00084 temp[1] = T0[SSB (text[0])] \ 00085 ^ T1[SSB (text[1])] \ 00086 ^ T2[SSB (text[2])] \ 00087 ^ T3[SSB (text[3])] \ 00088 ^ roundkey[1]; \ 00089 temp[2] = T0[TSB (text[0])] \ 00090 ^ T1[TSB (text[1])] \ 00091 ^ T2[TSB (text[2])] \ 00092 ^ T3[TSB (text[3])] \ 00093 ^ roundkey[2]; \ 00094 temp[3] = T0[LSB (text[0])] \ 00095 ^ T1[LSB (text[1])] \ 00096 ^ T2[LSB (text[2])] \ 00097 ^ T3[LSB (text[3])] \ 00098 ^ roundkey[3]; \ 00099 } /* squareRound */ 00100 00101 #define squareFinal(text, temp, S, roundkey) \ 00102 { \ 00103 text[0] = ((word32) (S[MSB (temp[0])]) << 24) \ 00104 ^ ((word32) (S[MSB (temp[1])]) << 16) \ 00105 ^ ((word32) (S[MSB (temp[2])]) << 8) \ 00106 ^ (word32) (S[MSB (temp[3])]) \ 00107 ^ roundkey[0]; \ 00108 text[1] = ((word32) (S[SSB (temp[0])]) << 24) \ 00109 ^ ((word32) (S[SSB (temp[1])]) << 16) \ 00110 ^ ((word32) (S[SSB (temp[2])]) << 8) \ 00111 ^ (word32) (S[SSB (temp[3])]) \ 00112 ^ roundkey[1]; \ 00113 text[2] = ((word32) (S[TSB (temp[0])]) << 24) \ 00114 ^ ((word32) (S[TSB (temp[1])]) << 16) \ 00115 ^ ((word32) (S[TSB (temp[2])]) << 8) \ 00116 ^ (word32) (S[TSB (temp[3])]) \ 00117 ^ roundkey[2]; \ 00118 text[3] = ((word32) (S[LSB (temp[0])]) << 24) \ 00119 ^ ((word32) (S[LSB (temp[1])]) << 16) \ 00120 ^ ((word32) (S[LSB (temp[2])]) << 8) \ 00121 ^ (word32) (S[LSB (temp[3])]) \ 00122 ^ roundkey[3]; \ 00123 } /* squareFinal */ 00124 00125 typedef BlockGetAndPut<word32, BigEndian> Block; 00126 00127 void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00128 { 00129 word32 text[4], temp[4]; 00130 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); 00131 00132 /* initial key addition */ 00133 text[0] ^= roundkeys(0, 0); 00134 text[1] ^= roundkeys(0, 1); 00135 text[2] ^= roundkeys(0, 2); 00136 text[3] ^= roundkeys(0, 3); 00137 00138 /* ROUNDS - 1 full rounds */ 00139 for (int i=1; i+1<ROUNDS; i+=2) 00140 { 00141 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i)); 00142 squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1)); 00143 } 00144 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1)); 00145 00146 /* last round (diffusion becomes only transposition) */ 00147 squareFinal (text, temp, Se, roundkeys4(ROUNDS)); 00148 00149 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); 00150 } 00151 00152 void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00153 { 00154 word32 text[4], temp[4]; 00155 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); 00156 00157 /* initial key addition */ 00158 text[0] ^= roundkeys(0, 0); 00159 text[1] ^= roundkeys(0, 1); 00160 text[2] ^= roundkeys(0, 2); 00161 text[3] ^= roundkeys(0, 3); 00162 00163 /* ROUNDS - 1 full rounds */ 00164 for (int i=1; i+1<ROUNDS; i+=2) 00165 { 00166 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i)); 00167 squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1)); 00168 } 00169 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1)); 00170 00171 /* last round (diffusion becomes only transposition) */ 00172 squareFinal (text, temp, Sd, roundkeys4(ROUNDS)); 00173 00174 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); 00175 } 00176 00177 NAMESPACE_END