Crypto++  8.8
Free C++ class library of cryptographic schemes
tea.cpp
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 
7 // http://github.com/weidai11/cryptopp/issues/503
8 #if defined(__xlC__) || defined(__SUNPRO_CC)
9 # define MAYBE_VOLATILE(x) (*const_cast<volatile word32*>(&x))
10 #else
11 # define MAYBE_VOLATILE(x) (x)
12 #endif
13 
14 NAMESPACE_BEGIN(CryptoPP)
15 
16 static const word32 DELTA = 0x9e3779b9;
18 
19 #define UINT32_CAST(x) ((word32*)(void*)(x))
20 #define CONST_UINT32_CAST(x) ((const word32*)(const void*)(x))
21 
22 void TEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
23 {
24  AssertValidKeyLength(length);
25 
26  GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
27  m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
28 }
29 
30 void TEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
31 {
32  word32 y, z, sum = 0;
33  Block::Get(inBlock)(y)(z);
34 
35  // http://github.com/weidai11/cryptopp/issues/503
36  while (MAYBE_VOLATILE(sum) != m_limit)
37  {
38  sum += DELTA;
39  y += ((z << 4) + m_k[0]) ^ (z + sum) ^ ((z >> 5) + m_k[1]);
40  z += ((y << 4) + m_k[2]) ^ (y + sum) ^ ((y >> 5) + m_k[3]);
41  }
42 
43  Block::Put(xorBlock, outBlock)(y)(z);
44 }
45 
46 void TEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
47 {
48  word32 y, z, sum = m_limit;
49  Block::Get(inBlock)(y)(z);
50 
51  // http://github.com/weidai11/cryptopp/issues/503
52  while (MAYBE_VOLATILE(sum) != 0)
53  {
54  z -= ((y << 4) + m_k[2]) ^ (y + sum) ^ ((y >> 5) + m_k[3]);
55  y -= ((z << 4) + m_k[0]) ^ (z + sum) ^ ((z >> 5) + m_k[1]);
56  sum -= DELTA;
57  }
58 
59  Block::Put(xorBlock, outBlock)(y)(z);
60 }
61 
62 void XTEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
63 {
64  AssertValidKeyLength(length);
65 
66  GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
67  m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
68 }
69 
70 void XTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
71 {
72  word32 y, z, sum = 0;
73  Block::Get(inBlock)(y)(z);
74 
75  // http://github.com/weidai11/cryptopp/issues/503
76  while (MAYBE_VOLATILE(sum) != m_limit)
77  {
78  y += ((z<<4 ^ z>>5) + z) ^ (sum + m_k[sum&3]);
79  sum += DELTA;
80  z += ((y<<4 ^ y>>5) + y) ^ (sum + m_k[sum>>11 & 3]);
81  }
82 
83  Block::Put(xorBlock, outBlock)(y)(z);
84 }
85 
86 void XTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
87 {
88  word32 y, z, sum = m_limit;
89  Block::Get(inBlock)(y)(z);
90 
91  // http://github.com/weidai11/cryptopp/issues/503
92  while (MAYBE_VOLATILE(sum) != 0)
93  {
94  z -= ((y<<4 ^ y>>5) + y) ^ (sum + m_k[sum>>11 & 3]);
95  sum -= DELTA;
96  y -= ((z<<4 ^ z>>5) + z) ^ (sum + m_k[sum&3]);
97  }
98 
99  Block::Put(xorBlock, outBlock)(y)(z);
100 }
101 
102 #define MX ((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(m_k[(p&3)^e]^z))
103 
104 void BTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
105 {
106  CRYPTOPP_UNUSED(xorBlock);
107  CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf<word32>()));
108  CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf<word32>()));
109 
110  unsigned int n = m_blockSize / 4;
111  word32 *v = UINT32_CAST(outBlock);
112  ConditionalByteReverse(BIG_ENDIAN_ORDER, v, CONST_UINT32_CAST(inBlock), m_blockSize);
113 
114  word32 y, z = v[n-1], e;
115  word32 p, q = 6+52/n;
116  word32 sum = 0;
117 
118  while (q-- > 0)
119  {
120  sum += DELTA;
121  e = sum>>2 & 3;
122  for (p = 0; p < n-1; p++)
123  {
124  y = v[p+1];
125  z = v[p] += MX;
126  }
127  y = v[0];
128  z = v[n-1] += MX;
129  }
130 
131  ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
132 }
133 
134 void BTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
135 {
136  CRYPTOPP_UNUSED(xorBlock);
137  CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf<word32>()));
138  CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf<word32>()));
139 
140  unsigned int n = m_blockSize / 4;
141  word32 *v = UINT32_CAST(outBlock);
142  ConditionalByteReverse(BIG_ENDIAN_ORDER, v, CONST_UINT32_CAST(inBlock), m_blockSize);
143 
144  word32 y = v[0], z, e;
145  word32 p, q = 6+52/n;
146  word32 sum = q * DELTA;
147 
148  while (sum != 0)
149  {
150  e = sum>>2 & 3;
151  for (p = n-1; p > 0; p--)
152  {
153  z = v[p-1];
154  y = v[p] -= MX;
155  }
156 
157  z = v[n-1];
158  y = v[0] -= MX;
159  sum -= DELTA;
160  }
161 
162  ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
163 }
164 
165 NAMESPACE_END
Interface for retrieving values given their names.
Definition: cryptlib.h:327
Access a block of memory.
Definition: misc.h:3016
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:152
Utility functions for the Crypto++ library.
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1436
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2417
void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
Copy bytes in a buffer to an array of elements in big-endian order.
Definition: misc.h:2500
Crypto++ library namespace.
Precompiled header file.
Access a block of memory.
Definition: misc.h:3053
Classes for the TEA, BTEA and XTEA block ciphers.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68