00001
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 ¶ms)
00033 {
00034 AssertValidKeyLength(keyLen);
00035
00036 m_rounds = GetRoundsAndThrowIfInvalid(params, this);
00037 m_roundKeys.New(m_rounds+1);
00038
00039
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
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
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{
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