Crypto++ 8.7
Free C++ class library of cryptographic schemes
aria.cpp
1// aria.cpp - written and placed in the public domain by Jeffrey Walton
2
3#include "pch.h"
4#include "config.h"
5
6#include "aria.h"
7#include "misc.h"
8#include "cpu.h"
9
10#if CRYPTOPP_SSE2_INTRIN_AVAILABLE
11# define CRYPTOPP_ENABLE_ARIA_SSE2_INTRINSICS 1
12#endif
13
14#if CRYPTOPP_SSSE3_AVAILABLE
15# define CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS 1
16#endif
17
18NAMESPACE_BEGIN(CryptoPP)
19NAMESPACE_BEGIN(ARIATab)
20
21extern const word32 S1[256];
22extern const word32 S2[256];
23extern const word32 X1[256];
24extern const word32 X2[256];
25extern const word32 KRK[3][4];
26
27NAMESPACE_END
28NAMESPACE_END
29
30NAMESPACE_BEGIN(CryptoPP)
31
32using CryptoPP::ARIATab::S1;
33using CryptoPP::ARIATab::S2;
34using CryptoPP::ARIATab::X1;
35using CryptoPP::ARIATab::X2;
36using CryptoPP::ARIATab::KRK;
37
38inline word32* UINT32_CAST(const byte* ptr) {
39 return reinterpret_cast<word32*>(const_cast<byte*>(ptr));
40}
41
42inline byte ARIA_BRF(const word32 x, const int y) {
43 return static_cast<byte>(GETBYTE(x, y));
44}
45
46// Key XOR Layer. Bumps the round key pointer.
47inline const byte* ARIA_KXL(const byte rk[16], word32 t[4]) {
49 NativeBlock::Put(rk, t)(t[0])(t[1])(t[2])(t[3]);
50 return rk+16;
51}
52
53// S-Box Layer 1 + M
54inline void SBL1_M(word32& T0, word32& T1, word32& T2, word32& T3) {
55 T0=S1[ARIA_BRF(T0,3)]^S2[ARIA_BRF(T0,2)]^X1[ARIA_BRF(T0,1)]^X2[ARIA_BRF(T0,0)];
56 T1=S1[ARIA_BRF(T1,3)]^S2[ARIA_BRF(T1,2)]^X1[ARIA_BRF(T1,1)]^X2[ARIA_BRF(T1,0)];
57 T2=S1[ARIA_BRF(T2,3)]^S2[ARIA_BRF(T2,2)]^X1[ARIA_BRF(T2,1)]^X2[ARIA_BRF(T2,0)];
58 T3=S1[ARIA_BRF(T3,3)]^S2[ARIA_BRF(T3,2)]^X1[ARIA_BRF(T3,1)]^X2[ARIA_BRF(T3,0)];
59}
60
61// S-Box Layer 2 + M
62inline void SBL2_M(word32& T0, word32& T1, word32& T2, word32& T3) {
63 T0=X1[ARIA_BRF(T0,3)]^X2[ARIA_BRF(T0,2)]^S1[ARIA_BRF(T0,1)]^S2[ARIA_BRF(T0,0)];
64 T1=X1[ARIA_BRF(T1,3)]^X2[ARIA_BRF(T1,2)]^S1[ARIA_BRF(T1,1)]^S2[ARIA_BRF(T1,0)];
65 T2=X1[ARIA_BRF(T2,3)]^X2[ARIA_BRF(T2,2)]^S1[ARIA_BRF(T2,1)]^S2[ARIA_BRF(T2,0)];
66 T3=X1[ARIA_BRF(T3,3)]^X2[ARIA_BRF(T3,2)]^S1[ARIA_BRF(T3,1)]^S2[ARIA_BRF(T3,0)];
67 }
68
69inline void ARIA_P(word32& T0, word32& T1, word32& T2, word32& T3) {
70 CRYPTOPP_UNUSED(T0);
71 T1 = ((T1<< 8)&0xff00ff00) ^ ((T1>> 8)&0x00ff00ff);
72 T2 = rotrConstant<16>(T2);
73 T3 = ByteReverse((T3));
74}
75
76inline void ARIA_M(word32& X, word32& Y) {
77 Y=X<<8 ^ X>>8 ^ X<<16 ^ X>>16 ^ X<<24 ^ X>>24;
78}
79
80
81inline void ARIA_MM(word32& T0, word32& T1, word32& T2, word32& T3) {
82 T1^=T2; T2^=T3; T0^=T1;
83 T3^=T1; T2^=T0; T1^=T2;
84}
85
86inline void ARIA_FO(word32 t[4]) {
87 SBL1_M(t[0],t[1],t[2],t[3]);
88 ARIA_MM(t[0],t[1],t[2],t[3]);
89 ARIA_P(t[0],t[1],t[2],t[3]);
90 ARIA_MM(t[0],t[1],t[2],t[3]);
91}
92
93inline void ARIA_FE(word32 t[4]) {
94 SBL2_M(t[0],t[1],t[2],t[3]);
95 ARIA_MM(t[0],t[1],t[2],t[3]);
96 ARIA_P(t[2],t[3],t[0],t[1]);
97 ARIA_MM(t[0],t[1],t[2],t[3]);
98}
99
100#if (CRYPTOPP_ARM_NEON_AVAILABLE)
101extern void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen);
102extern void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outblock, const byte *rk, word32 *t);
103#endif
104
105#if (CRYPTOPP_SSSE3_AVAILABLE)
106extern void ARIA_ProcessAndXorBlock_SSSE3(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t);
107#endif
108
109// n-bit right shift of Y XORed to X
110template <unsigned int N>
111inline void ARIA_GSRK(const word32 X[4], const word32 Y[4], byte RK[16])
112{
113 // MSVC is not generating a "rotate immediate". Constify to help it along.
114 static const unsigned int Q = 4-(N/32);
115 static const unsigned int R = N % 32;
116 UINT32_CAST(RK)[0] = (X[0]) ^ ((Y[(Q )%4])>>R) ^ ((Y[(Q+3)%4])<<(32-R));
117 UINT32_CAST(RK)[1] = (X[1]) ^ ((Y[(Q+1)%4])>>R) ^ ((Y[(Q )%4])<<(32-R));
118 UINT32_CAST(RK)[2] = (X[2]) ^ ((Y[(Q+2)%4])>>R) ^ ((Y[(Q+1)%4])<<(32-R));
119 UINT32_CAST(RK)[3] = (X[3]) ^ ((Y[(Q+3)%4])>>R) ^ ((Y[(Q+2)%4])<<(32-R));
120}
121
122void ARIA::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params)
123{
124 CRYPTOPP_UNUSED(params);
125
126 m_rk.New(16*17); // round keys
127 m_w.New(4*7+4); // w0, w1, w2, w3, t and u
128
129 byte *rk = m_rk.data();
130 int Q, q, R, r;
131
132 switch (keylen)
133 {
134 case 16:
135 R = r = m_rounds = 12;
136 Q = q = 0;
137 break;
138 case 32:
139 R = r = m_rounds = 16;
140 Q = q = 2;
141 break;
142 case 24:
143 R = r = m_rounds = 14;
144 Q = q = 1;
145 break;
146 default:
147 Q = q = R = r = m_rounds = 0;
149 }
150
151 // w0 has room for 32 bytes. w1-w3 each has room for 16 bytes. t and u are 16 byte temp areas.
152 word32 *w0 = m_w.data(), *w1 = m_w.data()+8, *w2 = m_w.data()+12, *w3 = m_w.data()+16, *t = m_w.data()+20;
153
155 block(w0[0])(w0[1])(w0[2])(w0[3]);
156
157 t[0]=w0[0]^KRK[q][0]; t[1]=w0[1]^KRK[q][1];
158 t[2]=w0[2]^KRK[q][2]; t[3]=w0[3]^KRK[q][3];
159
160 ARIA_FO(t);
161
162 if (keylen == 32)
163 {
164 block(w1[0])(w1[1])(w1[2])(w1[3]);
165 }
166 else if (keylen == 24)
167 {
168 block(w1[0])(w1[1]); w1[2] = w1[3] = 0;
169 }
170 else
171 {
172 w1[0]=w1[1]=w1[2]=w1[3]=0;
173 }
174
175 w1[0]^=t[0]; w1[1]^=t[1]; w1[2]^=t[2]; w1[3]^=t[3];
176 std::memcpy(t, w1, 16);
177
178 q = (q==2) ? 0 : (q+1);
179 t[0]^=KRK[q][0]; t[1]^=KRK[q][1]; t[2]^=KRK[q][2]; t[3]^=KRK[q][3];
180
181 ARIA_FE(t);
182
183 t[0]^=w0[0]; t[1]^=w0[1]; t[2]^=w0[2]; t[3]^=w0[3];
184 std::memcpy(w2, t, 16);
185
186 q = (q==2) ? 0 : (q+1);
187 t[0]^=KRK[q][0]; t[1]^=KRK[q][1]; t[2]^=KRK[q][2]; t[3]^=KRK[q][3];
188
189 ARIA_FO(t);
190
191 w3[0]=t[0]^w1[0]; w3[1]=t[1]^w1[1]; w3[2]=t[2]^w1[2]; w3[3]=t[3]^w1[3];
192
193#if CRYPTOPP_ARM_NEON_AVAILABLE
194 if (HasNEON())
195 {
196 ARIA_UncheckedSetKey_Schedule_NEON(rk, m_w, keylen);
197 }
198 else
199#endif // CRYPTOPP_ARM_NEON_AVAILABLE
200 {
201 ARIA_GSRK<19>(w0, w1, rk + 0);
202 ARIA_GSRK<19>(w1, w2, rk + 16);
203 ARIA_GSRK<19>(w2, w3, rk + 32);
204 ARIA_GSRK<19>(w3, w0, rk + 48);
205 ARIA_GSRK<31>(w0, w1, rk + 64);
206 ARIA_GSRK<31>(w1, w2, rk + 80);
207 ARIA_GSRK<31>(w2, w3, rk + 96);
208 ARIA_GSRK<31>(w3, w0, rk + 112);
209 ARIA_GSRK<67>(w0, w1, rk + 128);
210 ARIA_GSRK<67>(w1, w2, rk + 144);
211 ARIA_GSRK<67>(w2, w3, rk + 160);
212 ARIA_GSRK<67>(w3, w0, rk + 176);
213 ARIA_GSRK<97>(w0, w1, rk + 192);
214
215 if (keylen > 16)
216 {
217 ARIA_GSRK<97>(w1, w2, rk + 208);
218 ARIA_GSRK<97>(w2, w3, rk + 224);
219
220 if (keylen > 24)
221 {
222 ARIA_GSRK< 97>(w3, w0, rk + 240);
223 ARIA_GSRK<109>(w0, w1, rk + 256);
224 }
225 }
226 }
227
228 // Decryption operation
229 if (!IsForwardTransformation())
230 {
231 word32 *a, *z, *s;
232 rk = m_rk.data();
233 r = R; q = Q;
234
235 a=UINT32_CAST(rk); s=m_w.data()+24; z=a+r*4;
236 std::memcpy(t, a, 16); std::memcpy(a, z, 16); std::memcpy(z, t, 16);
237
238 a+=4; z-=4;
239 for (; a<z; a+=4, z-=4)
240 {
241 ARIA_M(a[0],t[0]); ARIA_M(a[1],t[1]); ARIA_M(a[2],t[2]); ARIA_M(a[3],t[3]);
242 ARIA_MM(t[0],t[1],t[2],t[3]); ARIA_P(t[0],t[1],t[2],t[3]); ARIA_MM(t[0],t[1],t[2],t[3]);
243 std::memcpy(s, t, 16);
244
245 ARIA_M(z[0],t[0]); ARIA_M(z[1],t[1]); ARIA_M(z[2],t[2]); ARIA_M(z[3],t[3]);
246 ARIA_MM(t[0],t[1],t[2],t[3]); ARIA_P(t[0],t[1],t[2],t[3]); ARIA_MM(t[0],t[1],t[2],t[3]);
247 std::memcpy(a, t, 16); std::memcpy(z, s, 16);
248 }
249
250 ARIA_M(a[0],t[0]); ARIA_M(a[1],t[1]); ARIA_M(a[2],t[2]); ARIA_M(a[3],t[3]);
251 ARIA_MM(t[0],t[1],t[2],t[3]); ARIA_P(t[0],t[1],t[2],t[3]); ARIA_MM(t[0],t[1],t[2],t[3]);
252 std::memcpy(z, t, 16);
253 }
254
255 // Silence warnings
256 CRYPTOPP_UNUSED(Q); CRYPTOPP_UNUSED(R);
257 CRYPTOPP_UNUSED(q); CRYPTOPP_UNUSED(r);
258}
259
260void ARIA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
261{
262 const byte *rk = reinterpret_cast<const byte*>(m_rk.data());
263 word32 *t = const_cast<word32*>(m_w.data()+20);
264
265 // Timing attack countermeasure. See comments in Rijndael for more details.
266 // We used Yun's 32-bit implementation, so we use words rather than bytes.
267 const int cacheLineSize = GetCacheLineSize();
268 unsigned int i;
269 volatile word32 _u = 0;
270 word32 u = _u;
271
272 for (i=0; i<COUNTOF(S1); i+=cacheLineSize/(sizeof(S1[0])))
273 u |= *(S1+i);
274 t[0] |= u;
275
276 GetBlock<word32, BigEndian>block(inBlock);
277 block(t[0])(t[1])(t[2])(t[3]);
278
279 if (m_rounds > 12) {
280 rk = ARIA_KXL(rk, t); ARIA_FO(t);
281 rk = ARIA_KXL(rk, t); ARIA_FE(t);
282 }
283
284 if (m_rounds > 14) {
285 rk = ARIA_KXL(rk, t); ARIA_FO(t);
286 rk = ARIA_KXL(rk, t); ARIA_FE(t);
287 }
288
289 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t); ARIA_FE(t);
290 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t); ARIA_FE(t);
291 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t); ARIA_FE(t);
292 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t); ARIA_FE(t);
293 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t); ARIA_FE(t);
294 rk = ARIA_KXL(rk, t); ARIA_FO(t); rk = ARIA_KXL(rk, t);
295
296#if CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS
297 if (HasSSSE3())
298 {
299 ARIA_ProcessAndXorBlock_SSSE3(xorBlock, outBlock, rk, t);
300 return;
301 }
302 else
303#endif // CRYPTOPP_ENABLE_ARIA_SSSE3_INTRINSICS
304#if (CRYPTOPP_ARM_NEON_AVAILABLE)
305 if (HasNEON())
306 {
307 ARIA_ProcessAndXorBlock_NEON(xorBlock, outBlock, rk, t);
308 return;
309 }
310 else
311#endif // CRYPTOPP_ARM_NEON_AVAILABLE
312#if (CRYPTOPP_LITTLE_ENDIAN)
313 {
314 outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ) ^ rk[ 3];
315 outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8) ^ rk[ 2];
316 outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ) ^ rk[ 1];
317 outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ) ^ rk[ 0];
318 outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ) ^ rk[ 7];
319 outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8) ^ rk[ 6];
320 outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ) ^ rk[ 5];
321 outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ) ^ rk[ 4];
322 outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ) ^ rk[11];
323 outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8) ^ rk[10];
324 outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ) ^ rk[ 9];
325 outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ) ^ rk[ 8];
326 outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ) ^ rk[15];
327 outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8) ^ rk[14];
328 outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ) ^ rk[13];
329 outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ) ^ rk[12];
330 }
331#else
332 {
333 outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ) ^ rk[ 0];
334 outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8) ^ rk[ 1];
335 outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ) ^ rk[ 2];
336 outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ) ^ rk[ 3];
337 outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ) ^ rk[ 4];
338 outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8) ^ rk[ 5];
339 outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ) ^ rk[ 6];
340 outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ) ^ rk[ 7];
341 outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ) ^ rk[ 8];
342 outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8) ^ rk[ 9];
343 outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ) ^ rk[10];
344 outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ) ^ rk[11];
345 outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ) ^ rk[12];
346 outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8) ^ rk[13];
347 outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ) ^ rk[14];
348 outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ) ^ rk[15];
349 }
350#endif // CRYPTOPP_LITTLE_ENDIAN
351
352 if (xorBlock != NULLPTR)
353 for (unsigned int n=0; n<ARIA::BLOCKSIZE; ++n)
354 outBlock[n] ^= xorBlock[n];
355}
356
357NAMESPACE_END
Classes for the ARIA block cipher.
static const int BLOCKSIZE
The block size of the algorithm provided as a constant.
Definition: seckey.h:44
Access a block of memory.
Definition: misc.h:2766
Interface for retrieving values given their names.
Definition: cryptlib.h:322
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:857
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:1126
Library configuration file.
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:56
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
Functions for CPU features and intrinsics.
Utility functions for the Crypto++ library.
byte ByteReverse(byte value)
Reverses bytes in a 8-bit value.
Definition: misc.h:2022
#define COUNTOF(arr)
Counts elements in an array.
Definition: misc.h:191
Crypto++ library namespace.
Precompiled header file.
Access a block of memory.
Definition: misc.h:2844
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68