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(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
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
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
00141
00142
#endif // WORD64_AVAILABLE