Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

# square.cpp

    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 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         /* apply the key evolution function */
    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         /* produce the round keys */
    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)    /* most  significant byte */
    00070 #define SSB(x) (((x) >> 16) & 0xffU)    /* second in significance */
    00071 #define TSB(x) (((x) >>  8) & 0xffU)    /* third  in significance */
    00072 #define LSB(x) (((x)      ) & 0xffU)    /* least significant byte */
    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 } /* squareRound */
    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 } /* squareFinal */
    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         /* initial key addition */
    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         /* ROUNDS - 1 full rounds */
    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         /* last round (diffusion becomes only transposition) */
    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         /* initial key addition */
    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         /* ROUNDS - 1 full rounds */
    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         /* last round (diffusion becomes only transposition) */
    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