00001
00002
00003 #include "pch.h"
00004 #include "shark.h"
00005 #include "misc.h"
00006 #include "modes.h"
00007 #include "gf256.h"
00008
00009 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
00010 # pragma GCC diagnostic ignored "-Wmissing-braces"
00011 #endif
00012
00013 NAMESPACE_BEGIN(CryptoPP)
00014
00015 static word64 SHARKTransform(word64 a)
00016 {
00017 static const byte iG[8][8] = {
00018 0xe7, 0x30, 0x90, 0x85, 0xd0, 0x4b, 0x91, 0x41,
00019 0x53, 0x95, 0x9b, 0xa5, 0x96, 0xbc, 0xa1, 0x68,
00020 0x02, 0x45, 0xf7, 0x65, 0x5c, 0x1f, 0xb6, 0x52,
00021 0xa2, 0xca, 0x22, 0x94, 0x44, 0x63, 0x2a, 0xa2,
00022 0xfc, 0x67, 0x8e, 0x10, 0x29, 0x75, 0x85, 0x71,
00023 0x24, 0x45, 0xa2, 0xcf, 0x2f, 0x22, 0xc1, 0x0e,
00024 0xa1, 0xf1, 0x71, 0x40, 0x91, 0x27, 0x18, 0xa5,
00025 0x56, 0xf4, 0xaf, 0x32, 0xd2, 0xa4, 0xdc, 0x71,
00026 };
00027
00028 word64 result=0;
00029 GF256 gf256(0xf5);
00030 for (unsigned int i=0; i<8; i++)
00031 for(unsigned int j=0; j<8; j++)
00032 result ^= word64(gf256.Multiply(iG[i][j], GF256::Element(a>>(56-8*j)))) << (56-8*i);
00033 return result;
00034 }
00035
00036 void SHARK::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms)
00037 {
00038 AssertValidKeyLength(keyLen);
00039
00040 m_rounds = GetRoundsAndThrowIfInvalid(params, this);
00041 m_roundKeys.New(m_rounds+1);
00042
00043
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 (!IsForwardTransformation())
00059 {
00060 unsigned int i;
00061
00062
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
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{
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