Crypto++  8.8
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 
18 NAMESPACE_BEGIN(CryptoPP)
19 NAMESPACE_BEGIN(ARIATab)
20 
21 extern const word32 S1[256];
22 extern const word32 S2[256];
23 extern const word32 X1[256];
24 extern const word32 X2[256];
25 extern const word32 KRK[3][4];
26 
27 NAMESPACE_END
28 NAMESPACE_END
29 
30 NAMESPACE_BEGIN(CryptoPP)
31 
32 using CryptoPP::ARIATab::S1;
33 using CryptoPP::ARIATab::S2;
34 using CryptoPP::ARIATab::X1;
35 using CryptoPP::ARIATab::X2;
36 using CryptoPP::ARIATab::KRK;
37 
38 inline word32* UINT32_CAST(const byte* ptr) {
39  return reinterpret_cast<word32*>(const_cast<byte*>(ptr));
40 }
41 
42 inline 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.
47 inline 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
54 inline 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
62 inline 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 
69 inline 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 
76 inline void ARIA_M(word32& X, word32& Y) {
77  Y=X<<8 ^ X>>8 ^ X<<16 ^ X>>16 ^ X<<24 ^ X>>24;
78 }
79 
80 
81 inline 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 
86 inline 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 
93 inline 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)
101 extern void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen);
102 extern void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outblock, const byte *rk, word32 *t);
103 #endif
104 
105 #if (CRYPTOPP_SSSE3_AVAILABLE)
106 extern 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
110 template <unsigned int N>
111 inline 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 
122 void 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;
148  CRYPTOPP_ASSERT(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 
260 void 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 
357 NAMESPACE_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:2975
Interface for retrieving values given their names.
Definition: cryptlib.h:327
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:66
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
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:2231
#define COUNTOF(arr)
Counts elements in an array.
Definition: misc.h:193
Crypto++ library namespace.
Precompiled header file.
Access a block of memory.
Definition: misc.h:3053
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68