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
void Square::Base::UncheckedSetKey(CipherDir dir,
const byte *userKey,
unsigned int length)
00035 {
00036 AssertValidKeyLength(length);
00037
00038
static const word32 offset[ROUNDS] = {
00039 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
00040 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
00041 };
00042
00043 GetUserKey(BIG_ENDIAN_ORDER, roundkeys[0], KEYLENGTH/4, userKey, KEYLENGTH);
00044
00045
00046
for (
int i = 1; i < ROUNDS+1; i++)
00047 {
00048 roundkeys[i][0] = roundkeys[i-1][0] ^ rotlFixed(roundkeys[i-1][3], 8U) ^ offset[i-1];
00049 roundkeys[i][1] = roundkeys[i-1][1] ^ roundkeys[i][0];
00050 roundkeys[i][2] = roundkeys[i-1][2] ^ roundkeys[i][1];
00051 roundkeys[i][3] = roundkeys[i-1][3] ^ roundkeys[i][2];
00052 }
00053
00054
00055
if (dir == ENCRYPTION)
00056 {
00057
for (
int i = 0; i < ROUNDS; i++)
00058 SquareTransform (roundkeys[i], roundkeys[i]);
00059 }
00060
else
00061 {
00062
for (
int i = 0; i < ROUNDS/2; i++)
00063
for (
int j = 0; j < 4; j++)
00064 std::swap(roundkeys[i][j], roundkeys[ROUNDS-i][j]);
00065 SquareTransform (roundkeys[ROUNDS], roundkeys[ROUNDS]);
00066 }
00067 }
00068
00069
#define MSB(x) (((x) >> 24) & 0xffU)
00070
#define SSB(x) (((x) >> 16) & 0xffU)
00071
#define TSB(x) (((x) >> 8) & 0xffU)
00072
#define LSB(x) (((x) ) & 0xffU)
00073
00074
#define squareRound(text, temp, T0, T1, T2, T3, roundkey) \
00075
{ \
00076
temp[0] = T0[MSB (text[0])] \
00077
^ T1[MSB (text[1])] \
00078
^ T2[MSB (text[2])] \
00079
^ T3[MSB (text[3])] \
00080
^ roundkey[0]; \
00081
temp[1] = T0[SSB (text[0])] \
00082
^ T1[SSB (text[1])] \
00083
^ T2[SSB (text[2])] \
00084
^ T3[SSB (text[3])] \
00085
^ roundkey[1]; \
00086
temp[2] = T0[TSB (text[0])] \
00087
^ T1[TSB (text[1])] \
00088
^ T2[TSB (text[2])] \
00089
^ T3[TSB (text[3])] \
00090
^ roundkey[2]; \
00091
temp[3] = T0[LSB (text[0])] \
00092
^ T1[LSB (text[1])] \
00093
^ T2[LSB (text[2])] \
00094
^ T3[LSB (text[3])] \
00095
^ roundkey[3]; \
00096
}
00097
00098
#define squareFinal(text, temp, S, roundkey) \
00099
{ \
00100
text[0] = ((word32) (S[MSB (temp[0])]) << 24) \
00101
^ ((word32) (S[MSB (temp[1])]) << 16) \
00102
^ ((word32) (S[MSB (temp[2])]) << 8) \
00103
^ (word32) (S[MSB (temp[3])]) \
00104
^ roundkey[0]; \
00105
text[1] = ((word32) (S[SSB (temp[0])]) << 24) \
00106
^ ((word32) (S[SSB (temp[1])]) << 16) \
00107
^ ((word32) (S[SSB (temp[2])]) << 8) \
00108
^ (word32) (S[SSB (temp[3])]) \
00109
^ roundkey[1]; \
00110
text[2] = ((word32) (S[TSB (temp[0])]) << 24) \
00111
^ ((word32) (S[TSB (temp[1])]) << 16) \
00112
^ ((word32) (S[TSB (temp[2])]) << 8) \
00113
^ (word32) (S[TSB (temp[3])]) \
00114
^ roundkey[2]; \
00115
text[3] = ((word32) (S[LSB (temp[0])]) << 24) \
00116
^ ((word32) (S[LSB (temp[1])]) << 16) \
00117
^ ((word32) (S[LSB (temp[2])]) << 8) \
00118
^ (word32) (S[LSB (temp[3])]) \
00119
^ roundkey[3]; \
00120
}
00121
00122
typedef BlockGetAndPut<word32, BigEndian> Block;
00123
00124
void Square::Enc::ProcessAndXorBlock(
const byte *inBlock,
const byte *xorBlock, byte *outBlock)
const
00125
{
00126 word32 text[4], temp[4];
00127 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
00128
00129
00130 text[0] ^= roundkeys[0][0];
00131 text[1] ^= roundkeys[0][1];
00132 text[2] ^= roundkeys[0][2];
00133 text[3] ^= roundkeys[0][3];
00134
00135
00136
for (
int i=1; i+1<ROUNDS; i+=2)
00137 {
00138 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys[i]);
00139 squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys[i+1]);
00140 }
00141 squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys[ROUNDS-1]);
00142
00143
00144 squareFinal (text, temp, Se, roundkeys[ROUNDS]);
00145
00146 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
00147 }
00148
00149
void Square::Dec::ProcessAndXorBlock(
const byte *inBlock,
const byte *xorBlock, byte *outBlock)
const
00150
{
00151 word32 text[4], temp[4];
00152 Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
00153
00154
00155 text[0] ^= roundkeys[0][0];
00156 text[1] ^= roundkeys[0][1];
00157 text[2] ^= roundkeys[0][2];
00158 text[3] ^= roundkeys[0][3];
00159
00160
00161
for (
int i=1; i+1<ROUNDS; i+=2)
00162 {
00163 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys[i]);
00164 squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys[i+1]);
00165 }
00166 squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys[ROUNDS-1]);
00167
00168
00169 squareFinal (text, temp, Sd, roundkeys[ROUNDS]);
00170
00171 Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
00172 }
00173
00174 NAMESPACE_END