Crypto++
|
00001 // mars.cpp - written and placed in the public domain by Wei Dai 00002 00003 // includes IBM's key setup "tweak" proposed in August 1999 (http://www.research.ibm.com/security/key-setup.txt) 00004 00005 #include "pch.h" 00006 #include "mars.h" 00007 #include "misc.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 void MARS::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) 00012 { 00013 AssertValidKeyLength(length); 00014 00015 // Initialize T[] with the key data 00016 FixedSizeSecBlock<word32, 15> T; 00017 GetUserKey(LITTLE_ENDIAN_ORDER, T.begin(), 15, userKey, length); 00018 T[length/4] = length/4; 00019 00020 for (unsigned int j=0; j<4; j++) // compute 10 words of K[] in each iteration 00021 { 00022 unsigned int i; 00023 // Do linear transformation 00024 for (i=0; i<15; i++) 00025 T[i] = T[i] ^ rotlFixed(T[(i+8)%15] ^ T[(i+13)%15], 3) ^ (4*i+j); 00026 00027 // Do four rounds of stirring 00028 for (unsigned int k=0; k<4; k++) 00029 for (i=0; i<15; i++) 00030 T[i] = rotlFixed(T[i] + Sbox[T[(i+14)%15]%512], 9); 00031 00032 // Store next 10 key words into K[] 00033 for (i=0; i<10; i++) 00034 m_k[10*j+i] = T[4*i%15]; 00035 } 00036 00037 // Modify multiplication key-words 00038 for(unsigned int i = 5; i < 37; i += 2) 00039 { 00040 word32 m, w = m_k[i] | 3; 00041 m = (~w ^ (w<<1)) & (~w ^ (w>>1)) & 0x7ffffffe; 00042 m &= m>>1; m &= m>>2; m &= m>>4; 00043 m |= m<<1; m |= m<<2; m |= m<<4; 00044 m &= 0x7ffffffc; 00045 w ^= rotlMod(Sbox[265 + (m_k[i] & 3)], m_k[i-1]) & m; 00046 m_k[i] = w; 00047 } 00048 } 00049 00050 #define S(a) Sbox[(a)&0x1ff] 00051 #define S0(a) Sbox[(a)&0xff] 00052 #define S1(a) Sbox[((a)&0xff) + 256] 00053 00054 typedef BlockGetAndPut<word32, LittleEndian> Block; 00055 00056 void MARS::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00057 { 00058 unsigned int i; 00059 word32 a, b, c, d, l, m, r, t; 00060 const word32 *k = m_k; 00061 00062 Block::Get(inBlock)(a)(b)(c)(d); 00063 00064 a += k[0]; b += k[1]; c += k[2]; d += k[3]; 00065 00066 for (i=0; i<8; i++) 00067 { 00068 b = (b ^ S0(a)) + S1(a>>8); 00069 c += S0(a>>16); 00070 a = rotrFixed(a, 24); 00071 d ^= S1(a); 00072 a += (i%4==0) ? d : 0; 00073 a += (i%4==1) ? b : 0; 00074 t = a; a = b; b = c; c = d; d = t; 00075 } 00076 00077 for (i=0; i<16; i++) 00078 { 00079 t = rotlFixed(a, 13); 00080 r = rotlFixed(t * k[2*i+5], 10); 00081 m = a + k[2*i+4]; 00082 l = rotlMod((S(m) ^ rotrFixed(r, 5) ^ r), r); 00083 c += rotlMod(m, rotrFixed(r, 5)); 00084 (i<8 ? b : d) += l; 00085 (i<8 ? d : b) ^= r; 00086 a = b; b = c; c = d; d = t; 00087 } 00088 00089 for (i=0; i<8; i++) 00090 { 00091 a -= (i%4==2) ? d : 0; 00092 a -= (i%4==3) ? b : 0; 00093 b ^= S1(a); 00094 c -= S0(a>>24); 00095 t = rotlFixed(a, 24); 00096 d = (d - S1(a>>16)) ^ S0(t); 00097 a = b; b = c; c = d; d = t; 00098 } 00099 00100 a -= k[36]; b -= k[37]; c -= k[38]; d -= k[39]; 00101 00102 Block::Put(xorBlock, outBlock)(a)(b)(c)(d); 00103 } 00104 00105 void MARS::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00106 { 00107 unsigned int i; 00108 word32 a, b, c, d, l, m, r, t; 00109 const word32 *k = m_k; 00110 00111 Block::Get(inBlock)(d)(c)(b)(a); 00112 00113 d += k[36]; c += k[37]; b += k[38]; a += k[39]; 00114 00115 for (i=0; i<8; i++) 00116 { 00117 b = (b ^ S0(a)) + S1(a>>8); 00118 c += S0(a>>16); 00119 a = rotrFixed(a, 24); 00120 d ^= S1(a); 00121 a += (i%4==0) ? d : 0; 00122 a += (i%4==1) ? b : 0; 00123 t = a; a = b; b = c; c = d; d = t; 00124 } 00125 00126 for (i=0; i<16; i++) 00127 { 00128 t = rotrFixed(a, 13); 00129 r = rotlFixed(a * k[35-2*i], 10); 00130 m = t + k[34-2*i]; 00131 l = rotlMod((S(m) ^ rotrFixed(r, 5) ^ r), r); 00132 c -= rotlMod(m, rotrFixed(r, 5)); 00133 (i<8 ? b : d) -= l; 00134 (i<8 ? d : b) ^= r; 00135 a = b; b = c; c = d; d = t; 00136 } 00137 00138 for (i=0; i<8; i++) 00139 { 00140 a -= (i%4==2) ? d : 0; 00141 a -= (i%4==3) ? b : 0; 00142 b ^= S1(a); 00143 c -= S0(a>>24); 00144 t = rotlFixed(a, 24); 00145 d = (d - S1(a>>16)) ^ S0(t); 00146 a = b; b = c; c = d; d = t; 00147 } 00148 00149 d -= k[0]; c -= k[1]; b -= k[2]; a -= k[3]; 00150 00151 Block::Put(xorBlock, outBlock)(d)(c)(b)(a); 00152 } 00153 00154 NAMESPACE_END