Crypto++ 8.7
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
14NAMESPACE_BEGIN(CryptoPP)
15
16static 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
22void 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
30void 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
46void 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
62void 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
70void 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
86void 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
104void 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
134void 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
165NAMESPACE_END
Interface for retrieving values given their names.
Definition: cryptlib.h:322
Access a block of memory.
Definition: misc.h:2807
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:147
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:1227
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2208
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:2291
Crypto++ library namespace.
Precompiled header file.
Access a block of memory.
Definition: misc.h:2844
Classes for the TEA, BTEA and XTEA block ciphers.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68