00001
00002
00003
00004 #include "pch.h"
00005 #include "square.h"
00006 #include "misc.h"
00007 #include "gf256.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011
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
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
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)
00073 #define SSB(x) (((x) >> 16) & 0xffU)
00074 #define TSB(x) (((x) >> 8) & 0xffU)
00075 #define LSB(x) (((x) ) & 0xffU)
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 }
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 }
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
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
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
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
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
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
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