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

# 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(CipherDir dir, const byte *key, unsigned int keyLen, unsigned int rounds)
    00036 {
    00037         AssertValidKeyLength(keyLen);
    00038         AssertValidRounds(rounds);
    00039
    00040         m_rounds = rounds;
    00041         m_roundKeys.New(m_rounds+1);
    00042
    00043         // concatenate key enought times to fill a
    00044         for (unsigned int i=0; i<(m_rounds+1)*8; i++)
    00045                 ((byte *)m_roundKeys.begin())[i] = key[i%keyLen];
    00046
    00047         SHARK::Encryption e;
    00048         e.InitForKeySetup();
    00049         byte IV[8] = {0,0,0,0,0,0,0,0};
    00050         CFB_Mode_ExternalCipher::Encryption cfb(e, IV);
    00051
    00052         cfb.ProcessString((byte *)m_roundKeys.begin(), (m_rounds+1)*8);
    00053
    00054         ConditionalByteReverse(BIG_ENDIAN_ORDER, m_roundKeys.begin(), m_roundKeys.begin(), (m_rounds+1)*8);
    00055
    00056         m_roundKeys[m_rounds] = SHARKTransform(m_roundKeys[m_rounds]);
    00057
    00058         if (dir == DECRYPTION)
    00059         {
    00060                 unsigned int i;
    00061
    00062                 // transform encryption round keys into decryption round keys
    00063                 for (i=0; i<m_rounds/2; i++)
    00064                         std::swap(m_roundKeys[i], m_roundKeys[m_rounds-i]);
    00065
    00066                 for (i=1; i<m_rounds; i++)
    00067                         m_roundKeys[i] = SHARKTransform(m_roundKeys[i]);
    00068         }
    00069
    00070 #ifdef IS_LITTLE_ENDIAN
    00071         m_roundKeys[0] = ByteReverse(m_roundKeys[0]);
    00072         m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]);
    00073 #endif
    00074 }
    00075
    00076 // construct an SHARK_Enc object with fixed round keys, to be used to initialize actual round keys
    00077 void SHARK::Enc::InitForKeySetup()
    00078 {
    00079         m_rounds = DEFAULT_ROUNDS;
    00080         m_roundKeys.New(DEFAULT_ROUNDS+1);
    00081
    00082         for (unsigned int i=0; i<DEFAULT_ROUNDS; i++)
    00083                 m_roundKeys[i] = cbox[0][i];
    00084
    00085         m_roundKeys[DEFAULT_ROUNDS] = SHARKTransform(cbox[0][DEFAULT_ROUNDS]);
    00086
    00087 #ifdef IS_LITTLE_ENDIAN
    00088         m_roundKeys[0] = ByteReverse(m_roundKeys[0]);
    00089         m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]);
    00090 #endif
    00091 }
    00092
    00093 typedef word64 ArrayOf256Word64s[256];
    00094
    00095 template <const byte *sbox, const ArrayOf256Word64s *cbox>
    00096 struct SharkProcessAndXorBlock{         // VC60 workaround: problem with template functions
    00097 inline SharkProcessAndXorBlock(const word64 *roundKeys, unsigned int rounds, const byte *inBlock, const byte *xorBlock, byte *outBlock)
    00098 {
    00099         word64 tmp = *(word64 *)inBlock ^ roundKeys[0];
    00100
    00101         ByteOrder order = GetNativeByteOrder();
    00102         tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)]
    00103                 ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)]
    00104                 ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)]
    00105                 ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)]
    00106                 ^ roundKeys[1];
    00107
    00108         for(unsigned int i=2; i<rounds; i++)
    00109         {
    00110                 tmp = cbox[0][GETBYTE(tmp, 7)] ^ cbox[1][GETBYTE(tmp, 6)]
    00111                         ^ cbox[2][GETBYTE(tmp, 5)] ^ cbox[3][GETBYTE(tmp, 4)]
    00112                         ^ cbox[4][GETBYTE(tmp, 3)] ^ cbox[5][GETBYTE(tmp, 2)]
    00113                         ^ cbox[6][GETBYTE(tmp, 1)] ^ cbox[7][GETBYTE(tmp, 0)]
    00114                         ^ roundKeys[i];
    00115         }
    00116
    00117         PutBlock<byte, BigEndian>(xorBlock, outBlock)
    00118                 (sbox[GETBYTE(tmp, 7)])
    00119                 (sbox[GETBYTE(tmp, 6)])
    00120                 (sbox[GETBYTE(tmp, 5)])
    00121                 (sbox[GETBYTE(tmp, 4)])
    00122                 (sbox[GETBYTE(tmp, 3)])
    00123                 (sbox[GETBYTE(tmp, 2)])
    00124                 (sbox[GETBYTE(tmp, 1)])
    00125                 (sbox[GETBYTE(tmp, 0)]);
    00126
    00127         *(word64 *)outBlock ^= roundKeys[rounds];
    00128 }};
    00129
    00130 void SHARK::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
    00131 {
    00132         SharkProcessAndXorBlock<sbox, cbox>(m_roundKeys, m_rounds, inBlock, xorBlock, outBlock);
    00133 }
    00134
    00135 void SHARK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
    00136 {
    00137         SharkProcessAndXorBlock<sbox, cbox>(m_roundKeys, m_rounds, inBlock, xorBlock, outBlock);
    00138 }
    00139
    00140 NAMESPACE_END
    00141
    00142 #endif // WORD64_AVAILABLE