Crypto++
|
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 ¶ms) 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