Crypto++
|
00001 // serpent.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 #include "serpent.h" 00005 #include "misc.h" 00006 00007 #include "serpentp.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen) 00012 { 00013 FixedSizeSecBlock<word32, 8> k0; 00014 GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen); 00015 if (keylen < 32) 00016 k0[keylen/4] |= word32(1) << ((keylen%4)*8); 00017 00018 word32 t = k0[7]; 00019 unsigned int i; 00020 for (i = 0; i < 8; ++i) 00021 k[i] = k0[i] = t = rotlFixed(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); 00022 for (i = 8; i < 4*(rounds+1); ++i) 00023 k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); 00024 k -= 20; 00025 00026 word32 a,b,c,d,e; 00027 for (i=0; i<rounds/8; i++) 00028 { 00029 afterS2(LK); afterS2(S3); afterS3(SK); 00030 afterS1(LK); afterS1(S2); afterS2(SK); 00031 afterS0(LK); afterS0(S1); afterS1(SK); 00032 beforeS0(LK); beforeS0(S0); afterS0(SK); 00033 k += 8*4; 00034 afterS6(LK); afterS6(S7); afterS7(SK); 00035 afterS5(LK); afterS5(S6); afterS6(SK); 00036 afterS4(LK); afterS4(S5); afterS5(SK); 00037 afterS3(LK); afterS3(S4); afterS4(SK); 00038 } 00039 afterS2(LK); afterS2(S3); afterS3(SK); 00040 } 00041 00042 void Serpent::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &) 00043 { 00044 AssertValidKeyLength(keylen); 00045 Serpent_KeySchedule(m_key, 32, userKey, keylen); 00046 } 00047 00048 typedef BlockGetAndPut<word32, LittleEndian> Block; 00049 00050 void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00051 { 00052 word32 a, b, c, d, e; 00053 00054 Block::Get(inBlock)(a)(b)(c)(d); 00055 00056 const word32 *k = m_key; 00057 unsigned int i=1; 00058 00059 do 00060 { 00061 beforeS0(KX); beforeS0(S0); afterS0(LT); 00062 afterS0(KX); afterS0(S1); afterS1(LT); 00063 afterS1(KX); afterS1(S2); afterS2(LT); 00064 afterS2(KX); afterS2(S3); afterS3(LT); 00065 afterS3(KX); afterS3(S4); afterS4(LT); 00066 afterS4(KX); afterS4(S5); afterS5(LT); 00067 afterS5(KX); afterS5(S6); afterS6(LT); 00068 afterS6(KX); afterS6(S7); 00069 00070 if (i == 4) 00071 break; 00072 00073 ++i; 00074 c = b; 00075 b = e; 00076 e = d; 00077 d = a; 00078 a = e; 00079 k += 32; 00080 beforeS0(LT); 00081 } 00082 while (true); 00083 00084 afterS7(KX); 00085 00086 Block::Put(xorBlock, outBlock)(d)(e)(b)(a); 00087 } 00088 00089 void Serpent::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00090 { 00091 word32 a, b, c, d, e; 00092 00093 Block::Get(inBlock)(a)(b)(c)(d); 00094 00095 const word32 *k = m_key + 96; 00096 unsigned int i=4; 00097 00098 beforeI7(KX); 00099 goto start; 00100 00101 do 00102 { 00103 c = b; 00104 b = d; 00105 d = e; 00106 k -= 32; 00107 beforeI7(ILT); 00108 start: 00109 beforeI7(I7); afterI7(KX); 00110 afterI7(ILT); afterI7(I6); afterI6(KX); 00111 afterI6(ILT); afterI6(I5); afterI5(KX); 00112 afterI5(ILT); afterI5(I4); afterI4(KX); 00113 afterI4(ILT); afterI4(I3); afterI3(KX); 00114 afterI3(ILT); afterI3(I2); afterI2(KX); 00115 afterI2(ILT); afterI2(I1); afterI1(KX); 00116 afterI1(ILT); afterI1(I0); afterI0(KX); 00117 } 00118 while (--i != 0); 00119 00120 Block::Put(xorBlock, outBlock)(a)(d)(b)(e); 00121 } 00122 00123 NAMESPACE_END