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