- Main Page
- Namespaces
- Classes
- Files

# 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