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