Crypto++ 8.5 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;
17 typedef BlockGetAndPut<word32, BigEndian> Block;
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
IsAlignedOn
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1206
BIG_ENDIAN_ORDER
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:147
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68
tea.h
Classes for the TEA, BTEA and XTEA block ciphers.
pch.h
Precompiled header file.
word32
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
misc.h
Utility functions for the Crypto++ library.
PutBlock
Access a block of memory.
Definition: misc.h:2549
BlockGetAndPut
Access a block of memory.
Definition: misc.h:2586
ConditionalByteReverse
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2167
CryptoPP
Crypto++ library namespace.
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:321