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