• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

shark.cpp

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

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