• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • 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 #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         /* apply the key evolution function */
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         /* produce the round keys */
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)    /* most  significant byte */
00073 #define SSB(x) (((x) >> 16) & 0xffU)    /* second in significance */
00074 #define TSB(x) (((x) >>  8) & 0xffU)    /* third  in significance */
00075 #define LSB(x) (((x)      ) & 0xffU)    /* least significant byte */
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 } /* squareRound */
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 } /* squareFinal */
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         /* initial key addition */
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         /* ROUNDS - 1 full rounds */
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         /* last round (diffusion becomes only transposition) */
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         /* initial key addition */
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         /* ROUNDS - 1 full rounds */
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         /* last round (diffusion becomes only transposition) */
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

Generated on Mon Aug 9 2010 15:56:38 for Crypto++ by  doxygen 1.7.1