1 // mars.cpp - originally written and placed in the public domain by Wei Dai
2 
3 // includes IBM's key setup "tweak" proposed in August 1999 (http://www.research.ibm.com/security/key-setup.txt)
4 
5 #include "pch.h"
6 #include "mars.h"
7 #include "misc.h"
8 
NAMESPACE_BEGIN(CryptoPP)9 NAMESPACE_BEGIN(CryptoPP)
10 
11 void MARS::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
12 {
13 	AssertValidKeyLength(length);
14 
15 	// Initialize T[] with the key data
16 	FixedSizeSecBlock<word32, 15> T;
17 	GetUserKey(LITTLE_ENDIAN_ORDER, T.begin(), 15, userKey, length);
18 	T[length/4] = length/4;
19 
20 	for (unsigned int j=0; j<4; j++)	// compute 10 words of K[] in each iteration
21 	{
22 		unsigned int i;
23 		// Do linear transformation
24 		for (i=0; i<15; i++)
25 			T[i] = T[i] ^ rotlConstant<3>(T[(i + 8) % 15] ^ T[(i + 13) % 15]) ^ (4 * i + j);
26 
27 		// Do four rounds of stirring
28 		for (unsigned int k=0; k<4; k++)
29 			for (i=0; i<15; i++)
30 				T[i] = rotlConstant<9>(T[i] + Sbox[T[(i + 14) % 15] % 512]);
31 
32 		// Store next 10 key words into K[]
33 		for (i=0; i<10; i++)
34 			m_k[10*j+i] = T[4*i%15];
35 	}
36 
37 	// Modify multiplication key-words
38 	for(unsigned int i = 5; i < 37; i += 2)
39 	{
40 		word32 m, w = m_k[i] | 3;
41 		m = (~w ^ (w<<1)) & (~w ^ (w>>1)) & 0x7ffffffe;
42 		m &= m>>1; m &= m>>2; m &= m>>4;
43 		m |= m<<1; m |= m<<2; m |= m<<4;
44 		m &= 0x7ffffffc;
45 		w ^= rotlMod(Sbox[265 + (m_k[i] & 3)], m_k[i-1]) & m;
46 		m_k[i] = w;
47 	}
48 }
49 
50 #define S(a)	Sbox[(a)&0x1ff]
51 #define S0(a)	Sbox[(a)&0xff]
52 #define S1(a)	Sbox[((a)&0xff) + 256]
53 
54 typedef BlockGetAndPut<word32, LittleEndian> Block;
55 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const56 void MARS::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
57 {
58 	unsigned int i;
59 	word32 a, b, c, d, l, m, r, t;
60 	const word32 *k = m_k;
61 
62 	Block::Get(inBlock)(a)(b)(c)(d);
63 
64 	a += k[0];	b += k[1];	c += k[2];	d += k[3];
65 
66 	for (i=0; i<8; i++)
67 	{
68 		b = (b ^ S0(a)) + S1(a>>8);
69 		c += S0(a>>16);
70 		a = rotrConstant<24>(a);
71 		d ^= S1(a);
72 		a += (i%4==0) ? d : 0;
73 		a += (i%4==1) ? b : 0;
74 		t = a;	a = b;	b = c;	c = d;	d = t;
75 	}
76 
77 	for (i=0; i<16; i++)
78 	{
79 		t = rotlConstant<13>(a);
80 		r = rotlConstant<10>(t * k[2 * i + 5]);
81 		m = a + k[2*i+4];
82 		l = rotlMod((S(m) ^ rotrConstant<5>(r) ^ r), r);
83 		c += rotlMod(m, rotrConstant<5>(r));
84 		(i<8 ? b : d) += l;
85 		(i<8 ? d : b) ^= r;
86 		a = b;	b = c;	c = d;	d = t;
87 	}
88 
89 	for (i=0; i<8; i++)
90 	{
91 		a -= (i%4==2) ? d : 0;
92 		a -= (i%4==3) ? b : 0;
93 		b ^= S1(a);
94 		c -= S0(a>>24);
95 		t = rotlConstant<24>(a);
96 		d = (d - S1(a>>16)) ^ S0(t);
97 		a = b;	b = c;	c = d;	d = t;
98 	}
99 
100 	a -= k[36];	b -= k[37];	c -= k[38];	d -= k[39];
101 
102 	Block::Put(xorBlock, outBlock)(a)(b)(c)(d);
103 }
104 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const105 void MARS::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
106 {
107 	unsigned int i;
108 	word32 a, b, c, d, l, m, r, t;
109 	const word32 *k = m_k;
110 
111 	Block::Get(inBlock)(d)(c)(b)(a);
112 
113 	d += k[36];	c += k[37];	b += k[38];	a += k[39];
114 
115 	for (i=0; i<8; i++)
116 	{
117 		b = (b ^ S0(a)) + S1(a>>8);
118 		c += S0(a>>16);
119 		a = rotrConstant<24>(a);
120 		d ^= S1(a);
121 		a += (i%4==0) ? d : 0;
122 		a += (i%4==1) ? b : 0;
123 		t = a;	a = b;	b = c;	c = d;	d = t;
124 	}
125 
126 	for (i=0; i<16; i++)
127 	{
128 		t = rotrConstant<13>(a);
129 		r = rotlConstant<10>(a * k[35 - 2 * i]);
130 		m = t + k[34-2*i];
131 		l = rotlMod((S(m) ^ rotrConstant<5>(r) ^ r), r);
132 		c -= rotlMod(m, rotrConstant<5>(r));
133 		(i<8 ? b : d) -= l;
134 		(i<8 ? d : b) ^= r;
135 		a = b;	b = c;	c = d;	d = t;
136 	}
137 
138 	for (i=0; i<8; i++)
139 	{
140 		a -= (i%4==2) ? d : 0;
141 		a -= (i%4==3) ? b : 0;
142 		b ^= S1(a);
143 		c -= S0(a>>24);
144 		t = rotlConstant<24>(a);
145 		d = (d - S1(a>>16)) ^ S0(t);
146 		a = b;	b = c;	c = d;	d = t;
147 	}
148 
149 	d -= k[0];	c -= k[1];	b -= k[2];	a -= k[3];
150 
151 	Block::Put(xorBlock, outBlock)(d)(c)(b)(a);
152 }
153 
154 NAMESPACE_END
155