1// tea.cpp - modified by Wei Dai from code in the original paper
2
3#include "pch.h"
4#include "tea.h"
5#include "misc.h"
6
7NAMESPACE_BEGIN(CryptoPP)
8
9static const word32 DELTA = 0x9e3779b9;
10typedef BlockGetAndPut<word32, BigEndian> Block;
11
12void TEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
13{
14	AssertValidKeyLength(length);
15
16	GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
17	m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
18}
19
20void TEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
21{
22	word32 y, z;
23	Block::Get(inBlock)(y)(z);
24
25	word32 sum = 0;
26	while (sum != m_limit)
27	{
28		sum += DELTA;
29		y += (z << 4) + m_k[0] ^ z + sum ^ (z >> 5) + m_k[1];
30		z += (y << 4) + m_k[2] ^ y + sum ^ (y >> 5) + m_k[3];
31	}
32
33	Block::Put(xorBlock, outBlock)(y)(z);
34}
35
36void TEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
37{
38	word32 y, z;
39	Block::Get(inBlock)(y)(z);
40
41	word32 sum = m_limit;
42	while (sum != 0)
43	{
44		z -= (y << 4) + m_k[2] ^ y + sum ^ (y >> 5) + m_k[3];
45		y -= (z << 4) + m_k[0] ^ z + sum ^ (z >> 5) + m_k[1];
46		sum -= DELTA;
47	}
48
49	Block::Put(xorBlock, outBlock)(y)(z);
50}
51
52void XTEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length,  const NameValuePairs &params)
53{
54	AssertValidKeyLength(length);
55
56	GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
57	m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
58}
59
60void XTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
61{
62	word32 y, z;
63	Block::Get(inBlock)(y)(z);
64
65	word32 sum = 0;
66	while (sum != m_limit)
67	{
68		y += (z<<4 ^ z>>5) + z ^ sum + m_k[sum&3];
69		sum += DELTA;
70		z += (y<<4 ^ y>>5) + y ^ sum + m_k[sum>>11 & 3];
71	}
72
73	Block::Put(xorBlock, outBlock)(y)(z);
74}
75
76void XTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
77{
78	word32 y, z;
79	Block::Get(inBlock)(y)(z);
80
81	word32 sum = m_limit;
82	while (sum != 0)
83	{
84		z -= (y<<4 ^ y>>5) + y ^ sum + m_k[sum>>11 & 3];
85		sum -= DELTA;
86		y -= (z<<4 ^ z>>5) + z ^ sum + m_k[sum&3];
87	}
88
89	Block::Put(xorBlock, outBlock)(y)(z);
90}
91
92#define MX (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(m_k[p&3^e]^z)
93
94void BTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
95{
96	unsigned int n = m_blockSize / 4;
97	word32 *v = (word32*)outBlock;
98	ConditionalByteReverse(BIG_ENDIAN_ORDER, v, (const word32*)inBlock, m_blockSize);
99
100	word32 y = v[0], z = v[n-1], e;
101	word32 p, q = 6+52/n;
102	word32 sum = 0;
103
104	while (q-- > 0)
105	{
106		sum += DELTA;
107		e = sum>>2 & 3;
108		for (p = 0; p < n-1; p++)
109		{
110			y = v[p+1];
111			z = v[p] += MX;
112		}
113		y = v[0];
114		z = v[n-1] += MX;
115	}
116
117	ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
118}
119
120void BTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
121{
122	unsigned int n = m_blockSize / 4;
123	word32 *v = (word32*)outBlock;
124	ConditionalByteReverse(BIG_ENDIAN_ORDER, v, (const word32*)inBlock, m_blockSize);
125
126	word32 y = v[0], z = v[n-1], e;
127	word32 p, q = 6+52/n;
128	word32 sum = q * DELTA;
129
130	while (sum != 0)
131	{
132		e = sum>>2 & 3;
133		for (p = n-1; p > 0; p--)
134		{
135			z = v[p-1];
136			y = v[p] -= MX;
137		}
138
139		z = v[n-1];
140		y = v[0] -= MX;
141		sum -= DELTA;
142	}
143
144	ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
145}
146
147NAMESPACE_END
148