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