shark.cpp

00001 // shark.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 
00005 #ifdef WORD64_AVAILABLE
00006 
00007 #include "shark.h"
00008 #include "misc.h"
00009 #include "modes.h"
00010 #include "gf256.h"
00011 
00012 NAMESPACE_BEGIN(CryptoPP)
00013 
00014 static word64 SHARKTransform(word64 a)
00015 {
00016         static const byte iG[8][8] = {
00017                 0xe7, 0x30, 0x90, 0x85, 0xd0, 0x4b, 0x91, 0x41, 
00018                 0x53, 0x95, 0x9b, 0xa5, 0x96, 0xbc, 0xa1, 0x68, 
00019                 0x02, 0x45, 0xf7, 0x65, 0x5c, 0x1f, 0xb6, 0x52, 
00020                 0xa2, 0xca, 0x22, 0x94, 0x44, 0x63, 0x2a, 0xa2, 
00021                 0xfc, 0x67, 0x8e, 0x10, 0x29, 0x75, 0x85, 0x71, 
00022                 0x24, 0x45, 0xa2, 0xcf, 0x2f, 0x22, 0xc1, 0x0e, 
00023                 0xa1, 0xf1, 0x71, 0x40, 0x91, 0x27, 0x18, 0xa5, 
00024                 0x56, 0xf4, 0xaf, 0x32, 0xd2, 0xa4, 0xdc, 0x71, 
00025         };
00026 
00027         word64 result=0;
00028         GF256 gf256(0xf5);
00029         for (unsigned int i=0; i<8; i++)
00030                 for(unsigned int j=0; j<8; j++) 
00031                         result ^= word64(gf256.Multiply(iG[i][j], GF256::Element(a>>(56-8*j)))) << (56-8*i);
00032         return result;
00033 }
00034 
00035 void SHARK::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs &params)
00036 {
00037         AssertValidKeyLength(keyLen);
00038 
00039         m_rounds = GetRoundsAndThrowIfInvalid(params, this);
00040         m_roundKeys.New(m_rounds+1);
00041 
00042         // concatenate key enought times to fill a
00043         for (unsigned int i=0; i<(m_rounds+1)*8; i++)
00044                 ((byte *)m_roundKeys.begin())[i] = key[i%keyLen];
00045 
00046         SHARK::Encryption e;
00047         e.InitForKeySetup();
00048         byte IV[8] = {0,0,0,0,0,0,0,0};
00049         CFB_Mode_ExternalCipher::Encryption cfb(e, IV);
00050 
00051         cfb.ProcessString((byte *)m_roundKeys.begin(), (m_rounds+1)*8);
00052 
00053         ConditionalByteReverse(BIG_ENDIAN_ORDER, m_roundKeys.begin(), m_roundKeys.begin(), (m_rounds+1)*8);
00054 
00055         m_roundKeys[m_rounds] = SHARKTransform(m_roundKeys[m_rounds]);
00056 
00057         if (!IsForwardTransformation())
00058         {
00059                 unsigned int i;
00060 
00061                 // transform encryption round keys into decryption round keys
00062                 for (i=0; i<m_rounds/2; i++)
00063                         std::swap(m_roundKeys[i], m_roundKeys[m_rounds-i]);
00064 
00065                 for (i=1; i<m_rounds; i++)
00066                         m_roundKeys[i] = SHARKTransform(m_roundKeys[i]);
00067         }
00068 
00069 #ifdef IS_LITTLE_ENDIAN
00070         m_roundKeys[0] = ByteReverse(m_roundKeys[0]);
00071         m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]);
00072 #endif
00073 }
00074 
00075 // construct an SHARK_Enc object with fixed round keys, to be used to initialize actual round keys
00076 void SHARK::Enc::InitForKeySetup()
00077 {
00078         m_rounds = DEFAULT_ROUNDS;
00079         m_roundKeys.New(DEFAULT_ROUNDS+1);
00080 
00081         for (unsigned int i=0; i<DEFAULT_ROUNDS; i++)
00082                 m_roundKeys[i] = cbox[0][i];
00083 
00084         m_roundKeys[DEFAULT_ROUNDS] = SHARKTransform(cbox[0][DEFAULT_ROUNDS]);
00085 
00086 #ifdef IS_LITTLE_ENDIAN
00087         m_roundKeys[0] = ByteReverse(m_roundKeys[0]);
00088         m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]);
00089 #endif
00090 }
00091 
00092 typedef word64 ArrayOf256Word64s[256];
00093 
00094 template <const byte *sbox, const ArrayOf256Word64s *cbox>
00095 struct SharkProcessAndXorBlock{         // VC60 workaround: problem with template functions
00096 inline SharkProcessAndXorBlock(const word64 *roundKeys, unsigned int rounds, const byte *inBlock, const byte *xorBlock, byte *outBlock)
00097 {
00098         word64 tmp = *(word64 *)inBlock ^ roundKeys[0];
00099 
00100         ByteOrder order = GetNativeByteOrder();
00101         tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] 
00102                 ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] 
00103                 ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] 
00104                 ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)]
00105                 ^ roundKeys[1];
00106 
00107         for(unsigned int i=2; i<rounds; i++) 
00108         {
00109                 tmp = cbox[0][GETBYTE(tmp, 7)] ^ cbox[1][GETBYTE(tmp, 6)] 
00110                         ^ cbox[2][GETBYTE(tmp, 5)] ^ cbox[3][GETBYTE(tmp, 4)] 
00111                         ^ cbox[4][GETBYTE(tmp, 3)] ^ cbox[5][GETBYTE(tmp, 2)] 
00112                         ^ cbox[6][GETBYTE(tmp, 1)] ^ cbox[7][GETBYTE(tmp, 0)]
00113                         ^ roundKeys[i];
00114         }
00115 
00116         PutBlock<byte, BigEndian>(xorBlock, outBlock)
00117                 (sbox[GETBYTE(tmp, 7)])
00118                 (sbox[GETBYTE(tmp, 6)])
00119                 (sbox[GETBYTE(tmp, 5)])
00120                 (sbox[GETBYTE(tmp, 4)])
00121                 (sbox[GETBYTE(tmp, 3)])
00122                 (sbox[GETBYTE(tmp, 2)])
00123                 (sbox[GETBYTE(tmp, 1)])
00124                 (sbox[GETBYTE(tmp, 0)]);
00125 
00126         *(word64 *)outBlock ^= roundKeys[rounds];
00127 }};
00128 
00129 void SHARK::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00130 {
00131         SharkProcessAndXorBlock<sbox, cbox>(m_roundKeys, m_rounds, inBlock, xorBlock, outBlock);
00132 }
00133 
00134 void SHARK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00135 {
00136         SharkProcessAndXorBlock<sbox, cbox>(m_roundKeys, m_rounds, inBlock, xorBlock, outBlock);
00137 }
00138 
00139 NAMESPACE_END
00140 
00141 #endif // WORD64_AVAILABLE

Generated on Sat Dec 23 02:07:10 2006 for Crypto++ by  doxygen 1.5.1-p1