You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.1 KiB
177 lines
5.1 KiB
// square.cpp - written and placed in the public domain by Wei Dai |
|
// Based on Paulo S.L.M. Barreto's public domain implementation |
|
|
|
#include "pch.h" |
|
#include "square.h" |
|
#include "misc.h" |
|
#include "gf256.h" |
|
|
|
NAMESPACE_BEGIN(CryptoPP) |
|
|
|
// apply theta to a roundkey |
|
static void SquareTransform (word32 in[4], word32 out[4]) |
|
{ |
|
static const byte G[4][4] = |
|
{ |
|
0x02U, 0x01U, 0x01U, 0x03U, |
|
0x03U, 0x02U, 0x01U, 0x01U, |
|
0x01U, 0x03U, 0x02U, 0x01U, |
|
0x01U, 0x01U, 0x03U, 0x02U |
|
}; |
|
|
|
GF256 gf256(0xf5); |
|
|
|
for (int i = 0; i < 4; i++) |
|
{ |
|
word32 temp = 0; |
|
for (int j = 0; j < 4; j++) |
|
for (int k = 0; k < 4; k++) |
|
temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8); |
|
out[i] = temp; |
|
} |
|
} |
|
|
|
#define roundkeys(i, j) m_roundkeys[(i)*4+(j)] |
|
#define roundkeys4(i) (m_roundkeys+(i)*4) |
|
|
|
void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) |
|
{ |
|
AssertValidKeyLength(length); |
|
|
|
static const word32 offset[ROUNDS] = { |
|
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, |
|
0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, |
|
}; |
|
|
|
GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH); |
|
|
|
/* apply the key evolution function */ |
|
for (int i = 1; i < ROUNDS+1; i++) |
|
{ |
|
roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlFixed(roundkeys(i-1, 3), 8U) ^ offset[i-1]; |
|
roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0); |
|
roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1); |
|
roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2); |
|
} |
|
|
|
/* produce the round keys */ |
|
if (IsForwardTransformation()) |
|
{ |
|
for (int i = 0; i < ROUNDS; i++) |
|
SquareTransform (roundkeys4(i), roundkeys4(i)); |
|
} |
|
else |
|
{ |
|
for (int i = 0; i < ROUNDS/2; i++) |
|
for (int j = 0; j < 4; j++) |
|
std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j)); |
|
SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS)); |
|
} |
|
} |
|
|
|
#define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */ |
|
#define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */ |
|
#define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */ |
|
#define LSB(x) (((x) ) & 0xffU) /* least significant byte */ |
|
|
|
#define squareRound(text, temp, T0, T1, T2, T3, roundkey) \ |
|
{ \ |
|
temp[0] = T0[MSB (text[0])] \ |
|
^ T1[MSB (text[1])] \ |
|
^ T2[MSB (text[2])] \ |
|
^ T3[MSB (text[3])] \ |
|
^ roundkey[0]; \ |
|
temp[1] = T0[SSB (text[0])] \ |
|
^ T1[SSB (text[1])] \ |
|
^ T2[SSB (text[2])] \ |
|
^ T3[SSB (text[3])] \ |
|
^ roundkey[1]; \ |
|
temp[2] = T0[TSB (text[0])] \ |
|
^ T1[TSB (text[1])] \ |
|
^ T2[TSB (text[2])] \ |
|
^ T3[TSB (text[3])] \ |
|
^ roundkey[2]; \ |
|
temp[3] = T0[LSB (text[0])] \ |
|
^ T1[LSB (text[1])] \ |
|
^ T2[LSB (text[2])] \ |
|
^ T3[LSB (text[3])] \ |
|
^ roundkey[3]; \ |
|
} /* squareRound */ |
|
|
|
#define squareFinal(text, temp, S, roundkey) \ |
|
{ \ |
|
text[0] = ((word32) (S[MSB (temp[0])]) << 24) \ |
|
^ ((word32) (S[MSB (temp[1])]) << 16) \ |
|
^ ((word32) (S[MSB (temp[2])]) << 8) \ |
|
^ (word32) (S[MSB (temp[3])]) \ |
|
^ roundkey[0]; \ |
|
text[1] = ((word32) (S[SSB (temp[0])]) << 24) \ |
|
^ ((word32) (S[SSB (temp[1])]) << 16) \ |
|
^ ((word32) (S[SSB (temp[2])]) << 8) \ |
|
^ (word32) (S[SSB (temp[3])]) \ |
|
^ roundkey[1]; \ |
|
text[2] = ((word32) (S[TSB (temp[0])]) << 24) \ |
|
^ ((word32) (S[TSB (temp[1])]) << 16) \ |
|
^ ((word32) (S[TSB (temp[2])]) << 8) \ |
|
^ (word32) (S[TSB (temp[3])]) \ |
|
^ roundkey[2]; \ |
|
text[3] = ((word32) (S[LSB (temp[0])]) << 24) \ |
|
^ ((word32) (S[LSB (temp[1])]) << 16) \ |
|
^ ((word32) (S[LSB (temp[2])]) << 8) \ |
|
^ (word32) (S[LSB (temp[3])]) \ |
|
^ roundkey[3]; \ |
|
} /* squareFinal */ |
|
|
|
typedef BlockGetAndPut<word32, BigEndian> Block; |
|
|
|
void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
|
{ |
|
word32 text[4], temp[4]; |
|
Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); |
|
|
|
/* initial key addition */ |
|
text[0] ^= roundkeys(0, 0); |
|
text[1] ^= roundkeys(0, 1); |
|
text[2] ^= roundkeys(0, 2); |
|
text[3] ^= roundkeys(0, 3); |
|
|
|
/* ROUNDS - 1 full rounds */ |
|
for (int i=1; i+1<ROUNDS; i+=2) |
|
{ |
|
squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i)); |
|
squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1)); |
|
} |
|
squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1)); |
|
|
|
/* last round (diffusion becomes only transposition) */ |
|
squareFinal (text, temp, Se, roundkeys4(ROUNDS)); |
|
|
|
Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); |
|
} |
|
|
|
void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
|
{ |
|
word32 text[4], temp[4]; |
|
Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]); |
|
|
|
/* initial key addition */ |
|
text[0] ^= roundkeys(0, 0); |
|
text[1] ^= roundkeys(0, 1); |
|
text[2] ^= roundkeys(0, 2); |
|
text[3] ^= roundkeys(0, 3); |
|
|
|
/* ROUNDS - 1 full rounds */ |
|
for (int i=1; i+1<ROUNDS; i+=2) |
|
{ |
|
squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i)); |
|
squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1)); |
|
} |
|
squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1)); |
|
|
|
/* last round (diffusion becomes only transposition) */ |
|
squareFinal (text, temp, Sd, roundkeys4(ROUNDS)); |
|
|
|
Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]); |
|
} |
|
|
|
NAMESPACE_END
|
|
|