Optimize sha/asm/keccak1600-avx2.pl.
[openssl.git] / crypto / aria / aria.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the OpenSSL license (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 /*
12  * Copyright (C) 2017 National Security Research Institute. All Rights Reserved.
13  *
14  * Information for ARIA
15  *     http://210.104.33.10/ARIA/index-e.html (English)
16  *     http://seed.kisa.or.kr/ (Korean)
17  *
18  * Public domain version is distributed above.
19  */
20
21 #include <openssl/e_os2.h>
22 #include "internal/aria.h"
23
24 #include <assert.h>
25 #include <string.h>
26
27 #ifndef OPENSSL_SMALL_FOOTPRINT
28
29 /* Begin macro */
30
31 /* rotation */
32 #define rotl32(v, r) (((uint32_t)(v) << (r)) | ((uint32_t)(v) >> (32 - r)))
33 #define rotr32(v, r) (((uint32_t)(v) >> (r)) | ((uint32_t)(v) << (32 - r)))
34
35 #define bswap32(v)                                          \
36     (((v) << 24) ^ ((v) >> 24) ^                            \
37     (((v) & 0x0000ff00) << 8) ^ (((v) & 0x00ff0000) >> 8))
38
39 #define GET_U8_BE(X, Y) ((uint8_t)((X) >> ((3 - Y) * 8)))
40 #define GET_U32_BE(X, Y) (                                  \
41     ((uint32_t)((const uint8_t *)(X))[Y * 4    ] << 24) ^   \
42     ((uint32_t)((const uint8_t *)(X))[Y * 4 + 1] << 16) ^   \
43     ((uint32_t)((const uint8_t *)(X))[Y * 4 + 2] <<  8) ^   \
44     ((uint32_t)((const uint8_t *)(X))[Y * 4 + 3]      )     )
45
46 #define PUT_U32_BE(DEST, IDX, VAL)                              \
47     do {                                                        \
48         ((uint8_t *)(DEST))[IDX * 4    ] = GET_U8_BE(VAL, 0);   \
49         ((uint8_t *)(DEST))[IDX * 4 + 1] = GET_U8_BE(VAL, 1);   \
50         ((uint8_t *)(DEST))[IDX * 4 + 2] = GET_U8_BE(VAL, 2);   \
51         ((uint8_t *)(DEST))[IDX * 4 + 3] = GET_U8_BE(VAL, 3);   \
52     } while(0)
53
54 #define MAKE_U32(V0, V1, V2, V3) (      \
55     ((uint32_t)((uint8_t)(V0)) << 24) | \
56     ((uint32_t)((uint8_t)(V1)) << 16) | \
57     ((uint32_t)((uint8_t)(V2)) <<  8) | \
58     ((uint32_t)((uint8_t)(V3))      )   )
59
60 /* End Macro*/
61
62 /* Key Constant
63  * 128bit : 0, 1,    2
64  * 192bit : 1, 2,    3(0)
65  * 256bit : 2, 3(0), 4(1)
66  */
67 static const uint32_t Key_RC[5][4] = {
68     { 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0 },
69     { 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0 },
70     { 0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e },
71     { 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0 },
72     { 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0 }
73 };
74
75 /* 32bit expanded s-box */
76 static const uint32_t S1[256] = {
77     0x00636363, 0x007c7c7c, 0x00777777, 0x007b7b7b,
78     0x00f2f2f2, 0x006b6b6b, 0x006f6f6f, 0x00c5c5c5,
79     0x00303030, 0x00010101, 0x00676767, 0x002b2b2b,
80     0x00fefefe, 0x00d7d7d7, 0x00ababab, 0x00767676,
81     0x00cacaca, 0x00828282, 0x00c9c9c9, 0x007d7d7d,
82     0x00fafafa, 0x00595959, 0x00474747, 0x00f0f0f0,
83     0x00adadad, 0x00d4d4d4, 0x00a2a2a2, 0x00afafaf,
84     0x009c9c9c, 0x00a4a4a4, 0x00727272, 0x00c0c0c0,
85     0x00b7b7b7, 0x00fdfdfd, 0x00939393, 0x00262626,
86     0x00363636, 0x003f3f3f, 0x00f7f7f7, 0x00cccccc,
87     0x00343434, 0x00a5a5a5, 0x00e5e5e5, 0x00f1f1f1,
88     0x00717171, 0x00d8d8d8, 0x00313131, 0x00151515,
89     0x00040404, 0x00c7c7c7, 0x00232323, 0x00c3c3c3,
90     0x00181818, 0x00969696, 0x00050505, 0x009a9a9a,
91     0x00070707, 0x00121212, 0x00808080, 0x00e2e2e2,
92     0x00ebebeb, 0x00272727, 0x00b2b2b2, 0x00757575,
93     0x00090909, 0x00838383, 0x002c2c2c, 0x001a1a1a,
94     0x001b1b1b, 0x006e6e6e, 0x005a5a5a, 0x00a0a0a0,
95     0x00525252, 0x003b3b3b, 0x00d6d6d6, 0x00b3b3b3,
96     0x00292929, 0x00e3e3e3, 0x002f2f2f, 0x00848484,
97     0x00535353, 0x00d1d1d1, 0x00000000, 0x00ededed,
98     0x00202020, 0x00fcfcfc, 0x00b1b1b1, 0x005b5b5b,
99     0x006a6a6a, 0x00cbcbcb, 0x00bebebe, 0x00393939,
100     0x004a4a4a, 0x004c4c4c, 0x00585858, 0x00cfcfcf,
101     0x00d0d0d0, 0x00efefef, 0x00aaaaaa, 0x00fbfbfb,
102     0x00434343, 0x004d4d4d, 0x00333333, 0x00858585,
103     0x00454545, 0x00f9f9f9, 0x00020202, 0x007f7f7f,
104     0x00505050, 0x003c3c3c, 0x009f9f9f, 0x00a8a8a8,
105     0x00515151, 0x00a3a3a3, 0x00404040, 0x008f8f8f,
106     0x00929292, 0x009d9d9d, 0x00383838, 0x00f5f5f5,
107     0x00bcbcbc, 0x00b6b6b6, 0x00dadada, 0x00212121,
108     0x00101010, 0x00ffffff, 0x00f3f3f3, 0x00d2d2d2,
109     0x00cdcdcd, 0x000c0c0c, 0x00131313, 0x00ececec,
110     0x005f5f5f, 0x00979797, 0x00444444, 0x00171717,
111     0x00c4c4c4, 0x00a7a7a7, 0x007e7e7e, 0x003d3d3d,
112     0x00646464, 0x005d5d5d, 0x00191919, 0x00737373,
113     0x00606060, 0x00818181, 0x004f4f4f, 0x00dcdcdc,
114     0x00222222, 0x002a2a2a, 0x00909090, 0x00888888,
115     0x00464646, 0x00eeeeee, 0x00b8b8b8, 0x00141414,
116     0x00dedede, 0x005e5e5e, 0x000b0b0b, 0x00dbdbdb,
117     0x00e0e0e0, 0x00323232, 0x003a3a3a, 0x000a0a0a,
118     0x00494949, 0x00060606, 0x00242424, 0x005c5c5c,
119     0x00c2c2c2, 0x00d3d3d3, 0x00acacac, 0x00626262,
120     0x00919191, 0x00959595, 0x00e4e4e4, 0x00797979,
121     0x00e7e7e7, 0x00c8c8c8, 0x00373737, 0x006d6d6d,
122     0x008d8d8d, 0x00d5d5d5, 0x004e4e4e, 0x00a9a9a9,
123     0x006c6c6c, 0x00565656, 0x00f4f4f4, 0x00eaeaea,
124     0x00656565, 0x007a7a7a, 0x00aeaeae, 0x00080808,
125     0x00bababa, 0x00787878, 0x00252525, 0x002e2e2e,
126     0x001c1c1c, 0x00a6a6a6, 0x00b4b4b4, 0x00c6c6c6,
127     0x00e8e8e8, 0x00dddddd, 0x00747474, 0x001f1f1f,
128     0x004b4b4b, 0x00bdbdbd, 0x008b8b8b, 0x008a8a8a,
129     0x00707070, 0x003e3e3e, 0x00b5b5b5, 0x00666666,
130     0x00484848, 0x00030303, 0x00f6f6f6, 0x000e0e0e,
131     0x00616161, 0x00353535, 0x00575757, 0x00b9b9b9,
132     0x00868686, 0x00c1c1c1, 0x001d1d1d, 0x009e9e9e,
133     0x00e1e1e1, 0x00f8f8f8, 0x00989898, 0x00111111,
134     0x00696969, 0x00d9d9d9, 0x008e8e8e, 0x00949494,
135     0x009b9b9b, 0x001e1e1e, 0x00878787, 0x00e9e9e9,
136     0x00cecece, 0x00555555, 0x00282828, 0x00dfdfdf,
137     0x008c8c8c, 0x00a1a1a1, 0x00898989, 0x000d0d0d,
138     0x00bfbfbf, 0x00e6e6e6, 0x00424242, 0x00686868,
139     0x00414141, 0x00999999, 0x002d2d2d, 0x000f0f0f,
140     0x00b0b0b0, 0x00545454, 0x00bbbbbb, 0x00161616
141 };
142
143 static const uint32_t S2[256] = {
144     0xe200e2e2, 0x4e004e4e, 0x54005454, 0xfc00fcfc,
145     0x94009494, 0xc200c2c2, 0x4a004a4a, 0xcc00cccc,
146     0x62006262, 0x0d000d0d, 0x6a006a6a, 0x46004646,
147     0x3c003c3c, 0x4d004d4d, 0x8b008b8b, 0xd100d1d1,
148     0x5e005e5e, 0xfa00fafa, 0x64006464, 0xcb00cbcb,
149     0xb400b4b4, 0x97009797, 0xbe00bebe, 0x2b002b2b,
150     0xbc00bcbc, 0x77007777, 0x2e002e2e, 0x03000303,
151     0xd300d3d3, 0x19001919, 0x59005959, 0xc100c1c1,
152     0x1d001d1d, 0x06000606, 0x41004141, 0x6b006b6b,
153     0x55005555, 0xf000f0f0, 0x99009999, 0x69006969,
154     0xea00eaea, 0x9c009c9c, 0x18001818, 0xae00aeae,
155     0x63006363, 0xdf00dfdf, 0xe700e7e7, 0xbb00bbbb,
156     0x00000000, 0x73007373, 0x66006666, 0xfb00fbfb,
157     0x96009696, 0x4c004c4c, 0x85008585, 0xe400e4e4,
158     0x3a003a3a, 0x09000909, 0x45004545, 0xaa00aaaa,
159     0x0f000f0f, 0xee00eeee, 0x10001010, 0xeb00ebeb,
160     0x2d002d2d, 0x7f007f7f, 0xf400f4f4, 0x29002929,
161     0xac00acac, 0xcf00cfcf, 0xad00adad, 0x91009191,
162     0x8d008d8d, 0x78007878, 0xc800c8c8, 0x95009595,
163     0xf900f9f9, 0x2f002f2f, 0xce00cece, 0xcd00cdcd,
164     0x08000808, 0x7a007a7a, 0x88008888, 0x38003838,
165     0x5c005c5c, 0x83008383, 0x2a002a2a, 0x28002828,
166     0x47004747, 0xdb00dbdb, 0xb800b8b8, 0xc700c7c7,
167     0x93009393, 0xa400a4a4, 0x12001212, 0x53005353,
168     0xff00ffff, 0x87008787, 0x0e000e0e, 0x31003131,
169     0x36003636, 0x21002121, 0x58005858, 0x48004848,
170     0x01000101, 0x8e008e8e, 0x37003737, 0x74007474,
171     0x32003232, 0xca00caca, 0xe900e9e9, 0xb100b1b1,
172     0xb700b7b7, 0xab00abab, 0x0c000c0c, 0xd700d7d7,
173     0xc400c4c4, 0x56005656, 0x42004242, 0x26002626,
174     0x07000707, 0x98009898, 0x60006060, 0xd900d9d9,
175     0xb600b6b6, 0xb900b9b9, 0x11001111, 0x40004040,
176     0xec00ecec, 0x20002020, 0x8c008c8c, 0xbd00bdbd,
177     0xa000a0a0, 0xc900c9c9, 0x84008484, 0x04000404,
178     0x49004949, 0x23002323, 0xf100f1f1, 0x4f004f4f,
179     0x50005050, 0x1f001f1f, 0x13001313, 0xdc00dcdc,
180     0xd800d8d8, 0xc000c0c0, 0x9e009e9e, 0x57005757,
181     0xe300e3e3, 0xc300c3c3, 0x7b007b7b, 0x65006565,
182     0x3b003b3b, 0x02000202, 0x8f008f8f, 0x3e003e3e,
183     0xe800e8e8, 0x25002525, 0x92009292, 0xe500e5e5,
184     0x15001515, 0xdd00dddd, 0xfd00fdfd, 0x17001717,
185     0xa900a9a9, 0xbf00bfbf, 0xd400d4d4, 0x9a009a9a,
186     0x7e007e7e, 0xc500c5c5, 0x39003939, 0x67006767,
187     0xfe00fefe, 0x76007676, 0x9d009d9d, 0x43004343,
188     0xa700a7a7, 0xe100e1e1, 0xd000d0d0, 0xf500f5f5,
189     0x68006868, 0xf200f2f2, 0x1b001b1b, 0x34003434,
190     0x70007070, 0x05000505, 0xa300a3a3, 0x8a008a8a,
191     0xd500d5d5, 0x79007979, 0x86008686, 0xa800a8a8,
192     0x30003030, 0xc600c6c6, 0x51005151, 0x4b004b4b,
193     0x1e001e1e, 0xa600a6a6, 0x27002727, 0xf600f6f6,
194     0x35003535, 0xd200d2d2, 0x6e006e6e, 0x24002424,
195     0x16001616, 0x82008282, 0x5f005f5f, 0xda00dada,
196     0xe600e6e6, 0x75007575, 0xa200a2a2, 0xef00efef,
197     0x2c002c2c, 0xb200b2b2, 0x1c001c1c, 0x9f009f9f,
198     0x5d005d5d, 0x6f006f6f, 0x80008080, 0x0a000a0a,
199     0x72007272, 0x44004444, 0x9b009b9b, 0x6c006c6c,
200     0x90009090, 0x0b000b0b, 0x5b005b5b, 0x33003333,
201     0x7d007d7d, 0x5a005a5a, 0x52005252, 0xf300f3f3,
202     0x61006161, 0xa100a1a1, 0xf700f7f7, 0xb000b0b0,
203     0xd600d6d6, 0x3f003f3f, 0x7c007c7c, 0x6d006d6d,
204     0xed00eded, 0x14001414, 0xe000e0e0, 0xa500a5a5,
205     0x3d003d3d, 0x22002222, 0xb300b3b3, 0xf800f8f8,
206     0x89008989, 0xde00dede, 0x71007171, 0x1a001a1a,
207     0xaf00afaf, 0xba00baba, 0xb500b5b5, 0x81008181
208 };
209
210 static const uint32_t X1[256] = {
211     0x52520052, 0x09090009, 0x6a6a006a, 0xd5d500d5,
212     0x30300030, 0x36360036, 0xa5a500a5, 0x38380038,
213     0xbfbf00bf, 0x40400040, 0xa3a300a3, 0x9e9e009e,
214     0x81810081, 0xf3f300f3, 0xd7d700d7, 0xfbfb00fb,
215     0x7c7c007c, 0xe3e300e3, 0x39390039, 0x82820082,
216     0x9b9b009b, 0x2f2f002f, 0xffff00ff, 0x87870087,
217     0x34340034, 0x8e8e008e, 0x43430043, 0x44440044,
218     0xc4c400c4, 0xdede00de, 0xe9e900e9, 0xcbcb00cb,
219     0x54540054, 0x7b7b007b, 0x94940094, 0x32320032,
220     0xa6a600a6, 0xc2c200c2, 0x23230023, 0x3d3d003d,
221     0xeeee00ee, 0x4c4c004c, 0x95950095, 0x0b0b000b,
222     0x42420042, 0xfafa00fa, 0xc3c300c3, 0x4e4e004e,
223     0x08080008, 0x2e2e002e, 0xa1a100a1, 0x66660066,
224     0x28280028, 0xd9d900d9, 0x24240024, 0xb2b200b2,
225     0x76760076, 0x5b5b005b, 0xa2a200a2, 0x49490049,
226     0x6d6d006d, 0x8b8b008b, 0xd1d100d1, 0x25250025,
227     0x72720072, 0xf8f800f8, 0xf6f600f6, 0x64640064,
228     0x86860086, 0x68680068, 0x98980098, 0x16160016,
229     0xd4d400d4, 0xa4a400a4, 0x5c5c005c, 0xcccc00cc,
230     0x5d5d005d, 0x65650065, 0xb6b600b6, 0x92920092,
231     0x6c6c006c, 0x70700070, 0x48480048, 0x50500050,
232     0xfdfd00fd, 0xeded00ed, 0xb9b900b9, 0xdada00da,
233     0x5e5e005e, 0x15150015, 0x46460046, 0x57570057,
234     0xa7a700a7, 0x8d8d008d, 0x9d9d009d, 0x84840084,
235     0x90900090, 0xd8d800d8, 0xabab00ab, 0x00000000,
236     0x8c8c008c, 0xbcbc00bc, 0xd3d300d3, 0x0a0a000a,
237     0xf7f700f7, 0xe4e400e4, 0x58580058, 0x05050005,
238     0xb8b800b8, 0xb3b300b3, 0x45450045, 0x06060006,
239     0xd0d000d0, 0x2c2c002c, 0x1e1e001e, 0x8f8f008f,
240     0xcaca00ca, 0x3f3f003f, 0x0f0f000f, 0x02020002,
241     0xc1c100c1, 0xafaf00af, 0xbdbd00bd, 0x03030003,
242     0x01010001, 0x13130013, 0x8a8a008a, 0x6b6b006b,
243     0x3a3a003a, 0x91910091, 0x11110011, 0x41410041,
244     0x4f4f004f, 0x67670067, 0xdcdc00dc, 0xeaea00ea,
245     0x97970097, 0xf2f200f2, 0xcfcf00cf, 0xcece00ce,
246     0xf0f000f0, 0xb4b400b4, 0xe6e600e6, 0x73730073,
247     0x96960096, 0xacac00ac, 0x74740074, 0x22220022,
248     0xe7e700e7, 0xadad00ad, 0x35350035, 0x85850085,
249     0xe2e200e2, 0xf9f900f9, 0x37370037, 0xe8e800e8,
250     0x1c1c001c, 0x75750075, 0xdfdf00df, 0x6e6e006e,
251     0x47470047, 0xf1f100f1, 0x1a1a001a, 0x71710071,
252     0x1d1d001d, 0x29290029, 0xc5c500c5, 0x89890089,
253     0x6f6f006f, 0xb7b700b7, 0x62620062, 0x0e0e000e,
254     0xaaaa00aa, 0x18180018, 0xbebe00be, 0x1b1b001b,
255     0xfcfc00fc, 0x56560056, 0x3e3e003e, 0x4b4b004b,
256     0xc6c600c6, 0xd2d200d2, 0x79790079, 0x20200020,
257     0x9a9a009a, 0xdbdb00db, 0xc0c000c0, 0xfefe00fe,
258     0x78780078, 0xcdcd00cd, 0x5a5a005a, 0xf4f400f4,
259     0x1f1f001f, 0xdddd00dd, 0xa8a800a8, 0x33330033,
260     0x88880088, 0x07070007, 0xc7c700c7, 0x31310031,
261     0xb1b100b1, 0x12120012, 0x10100010, 0x59590059,
262     0x27270027, 0x80800080, 0xecec00ec, 0x5f5f005f,
263     0x60600060, 0x51510051, 0x7f7f007f, 0xa9a900a9,
264     0x19190019, 0xb5b500b5, 0x4a4a004a, 0x0d0d000d,
265     0x2d2d002d, 0xe5e500e5, 0x7a7a007a, 0x9f9f009f,
266     0x93930093, 0xc9c900c9, 0x9c9c009c, 0xefef00ef,
267     0xa0a000a0, 0xe0e000e0, 0x3b3b003b, 0x4d4d004d,
268     0xaeae00ae, 0x2a2a002a, 0xf5f500f5, 0xb0b000b0,
269     0xc8c800c8, 0xebeb00eb, 0xbbbb00bb, 0x3c3c003c,
270     0x83830083, 0x53530053, 0x99990099, 0x61610061,
271     0x17170017, 0x2b2b002b, 0x04040004, 0x7e7e007e,
272     0xbaba00ba, 0x77770077, 0xd6d600d6, 0x26260026,
273     0xe1e100e1, 0x69690069, 0x14140014, 0x63630063,
274     0x55550055, 0x21210021, 0x0c0c000c, 0x7d7d007d
275 };
276
277 static const uint32_t X2[256] = {
278     0x30303000, 0x68686800, 0x99999900, 0x1b1b1b00,
279     0x87878700, 0xb9b9b900, 0x21212100, 0x78787800,
280     0x50505000, 0x39393900, 0xdbdbdb00, 0xe1e1e100,
281     0x72727200, 0x09090900, 0x62626200, 0x3c3c3c00,
282     0x3e3e3e00, 0x7e7e7e00, 0x5e5e5e00, 0x8e8e8e00,
283     0xf1f1f100, 0xa0a0a000, 0xcccccc00, 0xa3a3a300,
284     0x2a2a2a00, 0x1d1d1d00, 0xfbfbfb00, 0xb6b6b600,
285     0xd6d6d600, 0x20202000, 0xc4c4c400, 0x8d8d8d00,
286     0x81818100, 0x65656500, 0xf5f5f500, 0x89898900,
287     0xcbcbcb00, 0x9d9d9d00, 0x77777700, 0xc6c6c600,
288     0x57575700, 0x43434300, 0x56565600, 0x17171700,
289     0xd4d4d400, 0x40404000, 0x1a1a1a00, 0x4d4d4d00,
290     0xc0c0c000, 0x63636300, 0x6c6c6c00, 0xe3e3e300,
291     0xb7b7b700, 0xc8c8c800, 0x64646400, 0x6a6a6a00,
292     0x53535300, 0xaaaaaa00, 0x38383800, 0x98989800,
293     0x0c0c0c00, 0xf4f4f400, 0x9b9b9b00, 0xededed00,
294     0x7f7f7f00, 0x22222200, 0x76767600, 0xafafaf00,
295     0xdddddd00, 0x3a3a3a00, 0x0b0b0b00, 0x58585800,
296     0x67676700, 0x88888800, 0x06060600, 0xc3c3c300,
297     0x35353500, 0x0d0d0d00, 0x01010100, 0x8b8b8b00,
298     0x8c8c8c00, 0xc2c2c200, 0xe6e6e600, 0x5f5f5f00,
299     0x02020200, 0x24242400, 0x75757500, 0x93939300,
300     0x66666600, 0x1e1e1e00, 0xe5e5e500, 0xe2e2e200,
301     0x54545400, 0xd8d8d800, 0x10101000, 0xcecece00,
302     0x7a7a7a00, 0xe8e8e800, 0x08080800, 0x2c2c2c00,
303     0x12121200, 0x97979700, 0x32323200, 0xababab00,
304     0xb4b4b400, 0x27272700, 0x0a0a0a00, 0x23232300,
305     0xdfdfdf00, 0xefefef00, 0xcacaca00, 0xd9d9d900,
306     0xb8b8b800, 0xfafafa00, 0xdcdcdc00, 0x31313100,
307     0x6b6b6b00, 0xd1d1d100, 0xadadad00, 0x19191900,
308     0x49494900, 0xbdbdbd00, 0x51515100, 0x96969600,
309     0xeeeeee00, 0xe4e4e400, 0xa8a8a800, 0x41414100,
310     0xdadada00, 0xffffff00, 0xcdcdcd00, 0x55555500,
311     0x86868600, 0x36363600, 0xbebebe00, 0x61616100,
312     0x52525200, 0xf8f8f800, 0xbbbbbb00, 0x0e0e0e00,
313     0x82828200, 0x48484800, 0x69696900, 0x9a9a9a00,
314     0xe0e0e000, 0x47474700, 0x9e9e9e00, 0x5c5c5c00,
315     0x04040400, 0x4b4b4b00, 0x34343400, 0x15151500,
316     0x79797900, 0x26262600, 0xa7a7a700, 0xdedede00,
317     0x29292900, 0xaeaeae00, 0x92929200, 0xd7d7d700,
318     0x84848400, 0xe9e9e900, 0xd2d2d200, 0xbababa00,
319     0x5d5d5d00, 0xf3f3f300, 0xc5c5c500, 0xb0b0b000,
320     0xbfbfbf00, 0xa4a4a400, 0x3b3b3b00, 0x71717100,
321     0x44444400, 0x46464600, 0x2b2b2b00, 0xfcfcfc00,
322     0xebebeb00, 0x6f6f6f00, 0xd5d5d500, 0xf6f6f600,
323     0x14141400, 0xfefefe00, 0x7c7c7c00, 0x70707000,
324     0x5a5a5a00, 0x7d7d7d00, 0xfdfdfd00, 0x2f2f2f00,
325     0x18181800, 0x83838300, 0x16161600, 0xa5a5a500,
326     0x91919100, 0x1f1f1f00, 0x05050500, 0x95959500,
327     0x74747400, 0xa9a9a900, 0xc1c1c100, 0x5b5b5b00,
328     0x4a4a4a00, 0x85858500, 0x6d6d6d00, 0x13131300,
329     0x07070700, 0x4f4f4f00, 0x4e4e4e00, 0x45454500,
330     0xb2b2b200, 0x0f0f0f00, 0xc9c9c900, 0x1c1c1c00,
331     0xa6a6a600, 0xbcbcbc00, 0xececec00, 0x73737300,
332     0x90909000, 0x7b7b7b00, 0xcfcfcf00, 0x59595900,
333     0x8f8f8f00, 0xa1a1a100, 0xf9f9f900, 0x2d2d2d00,
334     0xf2f2f200, 0xb1b1b100, 0x00000000, 0x94949400,
335     0x37373700, 0x9f9f9f00, 0xd0d0d000, 0x2e2e2e00,
336     0x9c9c9c00, 0x6e6e6e00, 0x28282800, 0x3f3f3f00,
337     0x80808000, 0xf0f0f000, 0x3d3d3d00, 0xd3d3d300,
338     0x25252500, 0x8a8a8a00, 0xb5b5b500, 0xe7e7e700,
339     0x42424200, 0xb3b3b300, 0xc7c7c700, 0xeaeaea00,
340     0xf7f7f700, 0x4c4c4c00, 0x11111100, 0x33333300,
341     0x03030300, 0xa2a2a200, 0xacacac00, 0x60606000
342 };
343
344 /* Key XOR Layer */
345 #define ARIA_ADD_ROUND_KEY(RK, T0, T1, T2, T3)  \
346     do {                                        \
347         (T0) ^= (RK)->u[0];                     \
348         (T1) ^= (RK)->u[1];                     \
349         (T2) ^= (RK)->u[2];                     \
350         (T3) ^= (RK)->u[3];                     \
351     } while(0)
352
353 /* S-Box Layer 1 + M */
354 #define ARIA_SBOX_LAYER1_WITH_PRE_DIFF(T0, T1, T2, T3)  \
355     do {                                                \
356         (T0) =                                          \
357             S1[GET_U8_BE(T0, 0)] ^                      \
358             S2[GET_U8_BE(T0, 1)] ^                      \
359             X1[GET_U8_BE(T0, 2)] ^                      \
360             X2[GET_U8_BE(T0, 3)];                       \
361         (T1) =                                          \
362             S1[GET_U8_BE(T1, 0)] ^                      \
363             S2[GET_U8_BE(T1, 1)] ^                      \
364             X1[GET_U8_BE(T1, 2)] ^                      \
365             X2[GET_U8_BE(T1, 3)];                       \
366         (T2) =                                          \
367             S1[GET_U8_BE(T2, 0)] ^                      \
368             S2[GET_U8_BE(T2, 1)] ^                      \
369             X1[GET_U8_BE(T2, 2)] ^                      \
370             X2[GET_U8_BE(T2, 3)];                       \
371         (T3) =                                          \
372             S1[GET_U8_BE(T3, 0)] ^                      \
373             S2[GET_U8_BE(T3, 1)] ^                      \
374             X1[GET_U8_BE(T3, 2)] ^                      \
375             X2[GET_U8_BE(T3, 3)];                       \
376     } while(0)
377
378 /* S-Box Layer 2 + M */
379 #define ARIA_SBOX_LAYER2_WITH_PRE_DIFF(T0, T1, T2, T3)  \
380     do {                                                \
381         (T0) =                                          \
382             X1[GET_U8_BE(T0, 0)] ^                      \
383             X2[GET_U8_BE(T0, 1)] ^                      \
384             S1[GET_U8_BE(T0, 2)] ^                      \
385             S2[GET_U8_BE(T0, 3)];                       \
386         (T1) =                                          \
387             X1[GET_U8_BE(T1, 0)] ^                      \
388             X2[GET_U8_BE(T1, 1)] ^                      \
389             S1[GET_U8_BE(T1, 2)] ^                      \
390             S2[GET_U8_BE(T1, 3)];                       \
391         (T2) =                                          \
392             X1[GET_U8_BE(T2, 0)] ^                      \
393             X2[GET_U8_BE(T2, 1)] ^                      \
394             S1[GET_U8_BE(T2, 2)] ^                      \
395             S2[GET_U8_BE(T2, 3)];                       \
396         (T3) =                                          \
397             X1[GET_U8_BE(T3, 0)] ^                      \
398             X2[GET_U8_BE(T3, 1)] ^                      \
399             S1[GET_U8_BE(T3, 2)] ^                      \
400             S2[GET_U8_BE(T3, 3)];                       \
401     } while(0)
402
403 /* Word-level diffusion */
404 #define ARIA_DIFF_WORD(T0,T1,T2,T3) \
405     do {                            \
406         (T1) ^= (T2);               \
407         (T2) ^= (T3);               \
408         (T0) ^= (T1);               \
409                                     \
410         (T3) ^= (T1);               \
411         (T2) ^= (T0);               \
412         (T1) ^= (T2);               \
413     } while(0)
414
415 /* Byte-level diffusion */
416 #define ARIA_DIFF_BYTE(T0, T1, T2, T3)                                  \
417     do {                                                                \
418         (T1) = (((T1) << 8) & 0xff00ff00) ^ (((T1) >> 8) & 0x00ff00ff); \
419         (T2) = rotr32(T2, 16);                                          \
420         (T3) = bswap32(T3);                                             \
421     } while(0)
422
423 /* Odd round Substitution & Diffusion */
424 #define ARIA_SUBST_DIFF_ODD(T0, T1, T2, T3)             \
425     do {                                                \
426         ARIA_SBOX_LAYER1_WITH_PRE_DIFF(T0, T1, T2, T3); \
427         ARIA_DIFF_WORD(T0, T1, T2, T3);                 \
428         ARIA_DIFF_BYTE(T0, T1, T2, T3);                 \
429         ARIA_DIFF_WORD(T0, T1, T2, T3);                 \
430     } while(0)
431
432 /* Even round Substitution & Diffusion */
433 #define ARIA_SUBST_DIFF_EVEN(T0, T1, T2, T3)            \
434     do {                                                \
435         ARIA_SBOX_LAYER2_WITH_PRE_DIFF(T0, T1, T2, T3); \
436         ARIA_DIFF_WORD(T0, T1, T2, T3);                 \
437         ARIA_DIFF_BYTE(T2, T3, T0, T1);                 \
438         ARIA_DIFF_WORD(T0, T1, T2, T3);                 \
439     } while(0)
440
441 /* Q, R Macro expanded ARIA GSRK */
442 #define _ARIA_GSRK(RK, X, Y, Q, R)                  \
443     do {                                            \
444         (RK)->u[0] =                                \
445             ((X)[0]) ^                              \
446             (((Y)[((Q)    ) % 4]) >> (R)) ^         \
447             (((Y)[((Q) + 3) % 4]) << (32 - (R)));   \
448         (RK)->u[1] =                                \
449             ((X)[1]) ^                              \
450             (((Y)[((Q) + 1) % 4]) >> (R)) ^         \
451             (((Y)[((Q)    ) % 4]) << (32 - (R)));   \
452         (RK)->u[2] =                                \
453             ((X)[2]) ^                              \
454             (((Y)[((Q) + 2) % 4]) >> (R)) ^         \
455             (((Y)[((Q) + 1) % 4]) << (32 - (R)));   \
456         (RK)->u[3] =                                \
457             ((X)[3]) ^                              \
458             (((Y)[((Q) + 3) % 4]) >> (R)) ^         \
459             (((Y)[((Q) + 2) % 4]) << (32 - (R)));   \
460     } while(0)
461
462 #define ARIA_GSRK(RK, X, Y, N) _ARIA_GSRK(RK, X, Y, 4 - ((N) / 32), (N) % 32)
463
464 #define ARIA_DEC_DIFF_BYTE(X, Y, TMP, TMP2)         \
465     do {                                            \
466         (TMP) = (X);                                \
467         (TMP2) = rotr32((TMP), 8);                  \
468         (Y) = (TMP2) ^ rotr32((TMP) ^ (TMP2), 16);  \
469     } while(0)
470
471 void aria_encrypt(const unsigned char *in, unsigned char *out,
472                   const ARIA_KEY *key)
473 {
474     register uint32_t reg0, reg1, reg2, reg3;
475     int Nr;
476
477     const ARIA_u128 *rk = key->rd_key;
478
479     if (in == NULL || out == NULL || key == NULL) {
480         return;
481     }
482
483     Nr = key->rounds;
484
485     if (Nr != 12 && Nr != 14 && Nr != 16) {
486         return;
487     }
488
489     reg0 = GET_U32_BE(in, 0);
490     reg1 = GET_U32_BE(in, 1);
491     reg2 = GET_U32_BE(in, 2);
492     reg3 = GET_U32_BE(in, 3);
493
494     ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3);
495     rk++;
496
497     ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3);
498     ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3);
499     rk++;
500
501     while(Nr -= 2){
502         ARIA_SUBST_DIFF_EVEN(reg0, reg1, reg2, reg3);
503         ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3);
504         rk++;
505
506         ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3);
507         ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3);
508         rk++;
509     }
510
511     reg0 = rk->u[0] ^ MAKE_U32(
512         (uint8_t)(X1[GET_U8_BE(reg0, 0)]     ),
513         (uint8_t)(X2[GET_U8_BE(reg0, 1)] >> 8),
514         (uint8_t)(S1[GET_U8_BE(reg0, 2)]     ),
515         (uint8_t)(S2[GET_U8_BE(reg0, 3)]     ));
516     reg1 = rk->u[1] ^ MAKE_U32(
517         (uint8_t)(X1[GET_U8_BE(reg1, 0)]     ),
518         (uint8_t)(X2[GET_U8_BE(reg1, 1)] >> 8),
519         (uint8_t)(S1[GET_U8_BE(reg1, 2)]     ),
520         (uint8_t)(S2[GET_U8_BE(reg1, 3)]     ));
521     reg2 = rk->u[2] ^ MAKE_U32(
522         (uint8_t)(X1[GET_U8_BE(reg2, 0)]     ),
523         (uint8_t)(X2[GET_U8_BE(reg2, 1)] >> 8),
524         (uint8_t)(S1[GET_U8_BE(reg2, 2)]     ),
525         (uint8_t)(S2[GET_U8_BE(reg2, 3)]     ));
526     reg3 = rk->u[3] ^ MAKE_U32(
527         (uint8_t)(X1[GET_U8_BE(reg3, 0)]     ),
528         (uint8_t)(X2[GET_U8_BE(reg3, 1)] >> 8),
529         (uint8_t)(S1[GET_U8_BE(reg3, 2)]     ),
530         (uint8_t)(S2[GET_U8_BE(reg3, 3)]     ));
531
532     PUT_U32_BE(out, 0, reg0);
533     PUT_U32_BE(out, 1, reg1);
534     PUT_U32_BE(out, 2, reg2);
535     PUT_U32_BE(out, 3, reg3);
536 }
537
538 int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
539                          ARIA_KEY *key)
540 {
541     register uint32_t reg0, reg1, reg2, reg3;
542     uint32_t w0[4], w1[4], w2[4], w3[4];
543     const uint32_t *ck;
544
545     ARIA_u128 *rk = key->rd_key;
546     int Nr = (bits + 256) / 32;
547
548     if (userKey == NULL || key == NULL) {
549         return -1;
550     }
551     if (bits != 128 && bits != 192 && bits != 256) {
552         return -2;
553     }
554
555     key->rounds = Nr;
556     ck = &Key_RC[(bits - 128) / 64][0];
557
558     w0[0] = GET_U32_BE(userKey, 0);
559     w0[1] = GET_U32_BE(userKey, 1);
560     w0[2] = GET_U32_BE(userKey, 2);
561     w0[3] = GET_U32_BE(userKey, 3);
562
563     reg0 = w0[0] ^ ck[0];
564     reg1 = w0[1] ^ ck[1];
565     reg2 = w0[2] ^ ck[2];
566     reg3 = w0[3] ^ ck[3];
567
568     ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3);
569
570     if (bits > 128) {
571         w1[0] = GET_U32_BE(userKey, 4);
572         w1[1] = GET_U32_BE(userKey, 5);
573         if (bits > 192) {
574             w1[2] = GET_U32_BE(userKey, 6);
575             w1[3] = GET_U32_BE(userKey, 7);
576         }
577         else {
578             w1[2] = w1[3] = 0;
579         }
580     }
581     else {
582         w1[0] = w1[1] = w1[2] = w1[3] = 0;
583     }
584
585     w1[0] ^= reg0;
586     w1[1] ^= reg1;
587     w1[2] ^= reg2;
588     w1[3] ^= reg3;
589
590     reg0 = w1[0];
591     reg1 = w1[1];
592     reg2 = w1[2];
593     reg3 = w1[3];
594
595     reg0 ^= ck[4];
596     reg1 ^= ck[5];
597     reg2 ^= ck[6];
598     reg3 ^= ck[7];
599
600     ARIA_SUBST_DIFF_EVEN(reg0, reg1, reg2, reg3);
601
602     reg0 ^= w0[0];
603     reg1 ^= w0[1];
604     reg2 ^= w0[2];
605     reg3 ^= w0[3];
606
607     w2[0] = reg0;
608     w2[1] = reg1;
609     w2[2] = reg2;
610     w2[3] = reg3;
611
612     reg0 ^= ck[8];
613     reg1 ^= ck[9];
614     reg2 ^= ck[10];
615     reg3 ^= ck[11];
616
617     ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3);
618
619     w3[0] = reg0 ^ w1[0];
620     w3[1] = reg1 ^ w1[1];
621     w3[2] = reg2 ^ w1[2];
622     w3[3] = reg3 ^ w1[3];
623
624     ARIA_GSRK(rk, w0, w1, 19);
625     rk++;
626     ARIA_GSRK(rk, w1, w2, 19);
627     rk++;
628     ARIA_GSRK(rk, w2, w3, 19);
629     rk++;
630     ARIA_GSRK(rk, w3, w0, 19);
631
632     rk++;
633     ARIA_GSRK(rk, w0, w1, 31);
634     rk++;
635     ARIA_GSRK(rk, w1, w2, 31);
636     rk++;
637     ARIA_GSRK(rk, w2, w3, 31);
638     rk++;
639     ARIA_GSRK(rk, w3, w0, 31);
640
641     rk++;
642     ARIA_GSRK(rk, w0, w1, 67);
643     rk++;
644     ARIA_GSRK(rk, w1, w2, 67);
645     rk++;
646     ARIA_GSRK(rk, w2, w3, 67);
647     rk++;
648     ARIA_GSRK(rk, w3, w0, 67);
649
650     rk++;
651     ARIA_GSRK(rk, w0, w1, 97);
652     if (bits > 128) {
653         rk++;
654         ARIA_GSRK(rk, w1, w2, 97);
655         rk++;
656         ARIA_GSRK(rk, w2, w3, 97);
657     }
658     if (bits > 192) {
659         rk++;
660         ARIA_GSRK(rk, w3, w0, 97);
661
662         rk++;
663         ARIA_GSRK(rk, w0, w1, 109);
664     }
665
666     return 0;
667 }
668
669 int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
670                          ARIA_KEY *key)
671 {
672     ARIA_u128 *rk_head;
673     ARIA_u128 *rk_tail;
674     register uint32_t w1, w2;
675     register uint32_t reg0, reg1, reg2, reg3;
676     uint32_t s0, s1, s2, s3;
677
678     const int r = aria_set_encrypt_key(userKey, bits, key);
679
680     if (r != 0) {
681         return r;
682     }
683
684     rk_head = key->rd_key;
685     rk_tail = rk_head + key->rounds;
686
687     reg0 = rk_head->u[0];
688     reg1 = rk_head->u[1];
689     reg2 = rk_head->u[2];
690     reg3 = rk_head->u[3];
691
692     memcpy(rk_head, rk_tail, ARIA_BLOCK_SIZE);
693
694     rk_tail->u[0] = reg0;
695     rk_tail->u[1] = reg1;
696     rk_tail->u[2] = reg2;
697     rk_tail->u[3] = reg3;
698
699     rk_head++;
700     rk_tail--;
701
702     for (; rk_head < rk_tail; rk_head++, rk_tail--) {
703         ARIA_DEC_DIFF_BYTE(rk_head->u[0], reg0, w1, w2);
704         ARIA_DEC_DIFF_BYTE(rk_head->u[1], reg1, w1, w2);
705         ARIA_DEC_DIFF_BYTE(rk_head->u[2], reg2, w1, w2);
706         ARIA_DEC_DIFF_BYTE(rk_head->u[3], reg3, w1, w2);
707
708         ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
709         ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3);
710         ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
711
712         s0 = reg0;
713         s1 = reg1;
714         s2 = reg2;
715         s3 = reg3;
716
717         ARIA_DEC_DIFF_BYTE(rk_tail->u[0], reg0, w1, w2);
718         ARIA_DEC_DIFF_BYTE(rk_tail->u[1], reg1, w1, w2);
719         ARIA_DEC_DIFF_BYTE(rk_tail->u[2], reg2, w1, w2);
720         ARIA_DEC_DIFF_BYTE(rk_tail->u[3], reg3, w1, w2);
721
722         ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
723         ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3);
724         ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
725
726         rk_head->u[0] = reg0;
727         rk_head->u[1] = reg1;
728         rk_head->u[2] = reg2;
729         rk_head->u[3] = reg3;
730
731         rk_tail->u[0] = s0;
732         rk_tail->u[1] = s1;
733         rk_tail->u[2] = s2;
734         rk_tail->u[3] = s3;
735     }
736     ARIA_DEC_DIFF_BYTE(rk_head->u[0], reg0, w1, w2);
737     ARIA_DEC_DIFF_BYTE(rk_head->u[1], reg1, w1, w2);
738     ARIA_DEC_DIFF_BYTE(rk_head->u[2], reg2, w1, w2);
739     ARIA_DEC_DIFF_BYTE(rk_head->u[3], reg3, w1, w2);
740
741     ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
742     ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3);
743     ARIA_DIFF_WORD(reg0, reg1, reg2, reg3);
744
745     rk_tail->u[0] = reg0;
746     rk_tail->u[1] = reg1;
747     rk_tail->u[2] = reg2;
748     rk_tail->u[3] = reg3;
749
750     return 0;
751 }
752
753 #else
754
755 static const unsigned char sb1[256] = {
756     0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
757     0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
758     0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
759     0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
760     0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
761     0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
762     0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
763     0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
764     0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
765     0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
766     0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
767     0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
768     0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
769     0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
770     0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
771     0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
772     0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
773     0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
774     0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
775     0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
776     0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
777     0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
778     0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
779     0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
780     0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
781     0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
782     0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
783     0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
784     0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
785     0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
786     0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
787     0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
788 };
789
790 static const unsigned char sb2[256] = {
791     0xe2, 0x4e, 0x54, 0xfc, 0x94, 0xc2, 0x4a, 0xcc,
792     0x62, 0x0d, 0x6a, 0x46, 0x3c, 0x4d, 0x8b, 0xd1,
793     0x5e, 0xfa, 0x64, 0xcb, 0xb4, 0x97, 0xbe, 0x2b,
794     0xbc, 0x77, 0x2e, 0x03, 0xd3, 0x19, 0x59, 0xc1,
795     0x1d, 0x06, 0x41, 0x6b, 0x55, 0xf0, 0x99, 0x69,
796     0xea, 0x9c, 0x18, 0xae, 0x63, 0xdf, 0xe7, 0xbb,
797     0x00, 0x73, 0x66, 0xfb, 0x96, 0x4c, 0x85, 0xe4,
798     0x3a, 0x09, 0x45, 0xaa, 0x0f, 0xee, 0x10, 0xeb,
799     0x2d, 0x7f, 0xf4, 0x29, 0xac, 0xcf, 0xad, 0x91,
800     0x8d, 0x78, 0xc8, 0x95, 0xf9, 0x2f, 0xce, 0xcd,
801     0x08, 0x7a, 0x88, 0x38, 0x5c, 0x83, 0x2a, 0x28,
802     0x47, 0xdb, 0xb8, 0xc7, 0x93, 0xa4, 0x12, 0x53,
803     0xff, 0x87, 0x0e, 0x31, 0x36, 0x21, 0x58, 0x48,
804     0x01, 0x8e, 0x37, 0x74, 0x32, 0xca, 0xe9, 0xb1,
805     0xb7, 0xab, 0x0c, 0xd7, 0xc4, 0x56, 0x42, 0x26,
806     0x07, 0x98, 0x60, 0xd9, 0xb6, 0xb9, 0x11, 0x40,
807     0xec, 0x20, 0x8c, 0xbd, 0xa0, 0xc9, 0x84, 0x04,
808     0x49, 0x23, 0xf1, 0x4f, 0x50, 0x1f, 0x13, 0xdc,
809     0xd8, 0xc0, 0x9e, 0x57, 0xe3, 0xc3, 0x7b, 0x65,
810     0x3b, 0x02, 0x8f, 0x3e, 0xe8, 0x25, 0x92, 0xe5,
811     0x15, 0xdd, 0xfd, 0x17, 0xa9, 0xbf, 0xd4, 0x9a,
812     0x7e, 0xc5, 0x39, 0x67, 0xfe, 0x76, 0x9d, 0x43,
813     0xa7, 0xe1, 0xd0, 0xf5, 0x68, 0xf2, 0x1b, 0x34,
814     0x70, 0x05, 0xa3, 0x8a, 0xd5, 0x79, 0x86, 0xa8,
815     0x30, 0xc6, 0x51, 0x4b, 0x1e, 0xa6, 0x27, 0xf6,
816     0x35, 0xd2, 0x6e, 0x24, 0x16, 0x82, 0x5f, 0xda,
817     0xe6, 0x75, 0xa2, 0xef, 0x2c, 0xb2, 0x1c, 0x9f,
818     0x5d, 0x6f, 0x80, 0x0a, 0x72, 0x44, 0x9b, 0x6c,
819     0x90, 0x0b, 0x5b, 0x33, 0x7d, 0x5a, 0x52, 0xf3,
820     0x61, 0xa1, 0xf7, 0xb0, 0xd6, 0x3f, 0x7c, 0x6d,
821     0xed, 0x14, 0xe0, 0xa5, 0x3d, 0x22, 0xb3, 0xf8,
822     0x89, 0xde, 0x71, 0x1a, 0xaf, 0xba, 0xb5, 0x81
823 };
824
825 static const unsigned char sb3[256] = {
826     0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
827     0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
828     0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
829     0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
830     0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
831     0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
832     0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
833     0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
834     0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
835     0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
836     0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
837     0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
838     0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
839     0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
840     0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
841     0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
842     0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
843     0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
844     0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
845     0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
846     0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
847     0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
848     0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
849     0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
850     0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
851     0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
852     0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
853     0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
854     0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
855     0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
856     0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
857     0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
858 };
859
860 static const unsigned char sb4[256] = {
861     0x30, 0x68, 0x99, 0x1b, 0x87, 0xb9, 0x21, 0x78,
862     0x50, 0x39, 0xdb, 0xe1, 0x72, 0x09, 0x62, 0x3c,
863     0x3e, 0x7e, 0x5e, 0x8e, 0xf1, 0xa0, 0xcc, 0xa3,
864     0x2a, 0x1d, 0xfb, 0xb6, 0xd6, 0x20, 0xc4, 0x8d,
865     0x81, 0x65, 0xf5, 0x89, 0xcb, 0x9d, 0x77, 0xc6,
866     0x57, 0x43, 0x56, 0x17, 0xd4, 0x40, 0x1a, 0x4d,
867     0xc0, 0x63, 0x6c, 0xe3, 0xb7, 0xc8, 0x64, 0x6a,
868     0x53, 0xaa, 0x38, 0x98, 0x0c, 0xf4, 0x9b, 0xed,
869     0x7f, 0x22, 0x76, 0xaf, 0xdd, 0x3a, 0x0b, 0x58,
870     0x67, 0x88, 0x06, 0xc3, 0x35, 0x0d, 0x01, 0x8b,
871     0x8c, 0xc2, 0xe6, 0x5f, 0x02, 0x24, 0x75, 0x93,
872     0x66, 0x1e, 0xe5, 0xe2, 0x54, 0xd8, 0x10, 0xce,
873     0x7a, 0xe8, 0x08, 0x2c, 0x12, 0x97, 0x32, 0xab,
874     0xb4, 0x27, 0x0a, 0x23, 0xdf, 0xef, 0xca, 0xd9,
875     0xb8, 0xfa, 0xdc, 0x31, 0x6b, 0xd1, 0xad, 0x19,
876     0x49, 0xbd, 0x51, 0x96, 0xee, 0xe4, 0xa8, 0x41,
877     0xda, 0xff, 0xcd, 0x55, 0x86, 0x36, 0xbe, 0x61,
878     0x52, 0xf8, 0xbb, 0x0e, 0x82, 0x48, 0x69, 0x9a,
879     0xe0, 0x47, 0x9e, 0x5c, 0x04, 0x4b, 0x34, 0x15,
880     0x79, 0x26, 0xa7, 0xde, 0x29, 0xae, 0x92, 0xd7,
881     0x84, 0xe9, 0xd2, 0xba, 0x5d, 0xf3, 0xc5, 0xb0,
882     0xbf, 0xa4, 0x3b, 0x71, 0x44, 0x46, 0x2b, 0xfc,
883     0xeb, 0x6f, 0xd5, 0xf6, 0x14, 0xfe, 0x7c, 0x70,
884     0x5a, 0x7d, 0xfd, 0x2f, 0x18, 0x83, 0x16, 0xa5,
885     0x91, 0x1f, 0x05, 0x95, 0x74, 0xa9, 0xc1, 0x5b,
886     0x4a, 0x85, 0x6d, 0x13, 0x07, 0x4f, 0x4e, 0x45,
887     0xb2, 0x0f, 0xc9, 0x1c, 0xa6, 0xbc, 0xec, 0x73,
888     0x90, 0x7b, 0xcf, 0x59, 0x8f, 0xa1, 0xf9, 0x2d,
889     0xf2, 0xb1, 0x00, 0x94, 0x37, 0x9f, 0xd0, 0x2e,
890     0x9c, 0x6e, 0x28, 0x3f, 0x80, 0xf0, 0x3d, 0xd3,
891     0x25, 0x8a, 0xb5, 0xe7, 0x42, 0xb3, 0xc7, 0xea,
892     0xf7, 0x4c, 0x11, 0x33, 0x03, 0xa2, 0xac, 0x60
893 };
894
895 static const ARIA_u128 c1 = {{
896     0x51, 0x7c, 0xc1, 0xb7, 0x27, 0x22, 0x0a, 0x94,
897     0xfe, 0x13, 0xab, 0xe8, 0xfa, 0x9a, 0x6e, 0xe0
898 }};
899
900 static const ARIA_u128 c2 = {{
901     0x6d, 0xb1, 0x4a, 0xcc, 0x9e, 0x21, 0xc8, 0x20,
902     0xff, 0x28, 0xb1, 0xd5, 0xef, 0x5d, 0xe2, 0xb0
903 }};
904
905 static const ARIA_u128 c3 = {{
906     0xdb, 0x92, 0x37, 0x1d, 0x21, 0x26, 0xe9, 0x70,
907     0x03, 0x24, 0x97, 0x75, 0x04, 0xe8, 0xc9, 0x0e
908 }};
909
910 /*
911  * Exclusive or two 128 bit values into the result.
912  * It is safe for the result to be the same as the either input.
913  */
914 static void xor128(ARIA_c128 o, const ARIA_c128 x, const ARIA_u128 *y)
915 {
916     int i;
917
918     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
919         o[i] = x[i] ^ y->c[i];
920 }
921
922 /*
923  * Generalised circular rotate right and exclusive or function.
924  * It is safe for the output to overlap either input.
925  */
926 static ossl_inline void rotnr(unsigned int n, ARIA_u128 *o,
927                               const ARIA_u128 *xor, const ARIA_u128 *z)
928 {
929     const unsigned int bytes = n / 8, bits = n % 8;
930     unsigned int i;
931     ARIA_u128 t;
932
933     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
934         t.c[(i + bytes) % ARIA_BLOCK_SIZE] = z->c[i];
935     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
936         o->c[i] = ((t.c[i] >> bits) |
937                 (t.c[i ? i - 1 : ARIA_BLOCK_SIZE - 1] << (8 - bits))) ^
938                 xor->c[i];
939 }
940
941 /*
942  * Circular rotate 19 bits right and xor.
943  * It is safe for the output to overlap either input.
944  */
945 static void rot19r(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z)
946 {
947     rotnr(19, o, xor, z);
948 }
949
950 /*
951  * Circular rotate 31 bits right and xor.
952  * It is safe for the output to overlap either input.
953  */
954 static void rot31r(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z)
955 {
956     rotnr(31, o, xor, z);
957 }
958
959 /*
960  * Circular rotate 61 bits left and xor.
961  * It is safe for the output to overlap either input.
962  */
963 static void rot61l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z)
964 {
965     rotnr(8 * ARIA_BLOCK_SIZE - 61, o, xor, z);
966 }
967
968 /*
969  * Circular rotate 31 bits left and xor.
970  * It is safe for the output to overlap either input.
971  */
972 static void rot31l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z)
973 {
974     rotnr(8 * ARIA_BLOCK_SIZE - 31, o, xor, z);
975 }
976
977 /*
978  * Circular rotate 19 bits left and xor.
979  * It is safe for the output to overlap either input.
980  */
981 static void rot19l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z)
982 {
983     rotnr(8 * ARIA_BLOCK_SIZE - 19, o, xor, z);
984 }
985
986 /*
987  * First substitution and xor layer, used for odd steps.
988  * It is safe for the input and output to be the same.
989  */
990 static void sl1(ARIA_u128 *o, const ARIA_u128 *x, const ARIA_u128 *y)
991 {
992     unsigned int i;
993     for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
994         o->c[i    ] = sb1[x->c[i    ] ^ y->c[i    ]];
995         o->c[i + 1] = sb2[x->c[i + 1] ^ y->c[i + 1]];
996         o->c[i + 2] = sb3[x->c[i + 2] ^ y->c[i + 2]];
997         o->c[i + 3] = sb4[x->c[i + 3] ^ y->c[i + 3]];
998     }
999 }
1000
1001 /*
1002  * Second substitution and xor layer, used for even steps.
1003  * It is safe for the input and output to be the same.
1004  */
1005 static void sl2(ARIA_c128 o, const ARIA_u128 *x, const ARIA_u128 *y)
1006 {
1007     unsigned int i;
1008     for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
1009         o[i    ] = sb3[x->c[i    ] ^ y->c[i    ]];
1010         o[i + 1] = sb4[x->c[i + 1] ^ y->c[i + 1]];
1011         o[i + 2] = sb1[x->c[i + 2] ^ y->c[i + 2]];
1012         o[i + 3] = sb2[x->c[i + 3] ^ y->c[i + 3]];
1013     }
1014 }
1015
1016 /*
1017  * Diffusion layer step
1018  * It is NOT safe for the input and output to overlap.
1019  */
1020 static void a(ARIA_u128 *y, const ARIA_u128 *x)
1021 {
1022     y->c[ 0] = x->c[ 3] ^ x->c[ 4] ^ x->c[ 6] ^ x->c[ 8] ^
1023                x->c[ 9] ^ x->c[13] ^ x->c[14];
1024     y->c[ 1] = x->c[ 2] ^ x->c[ 5] ^ x->c[ 7] ^ x->c[ 8] ^
1025                x->c[ 9] ^ x->c[12] ^ x->c[15];
1026     y->c[ 2] = x->c[ 1] ^ x->c[ 4] ^ x->c[ 6] ^ x->c[10] ^
1027                x->c[11] ^ x->c[12] ^ x->c[15];
1028     y->c[ 3] = x->c[ 0] ^ x->c[ 5] ^ x->c[ 7] ^ x->c[10] ^
1029                x->c[11] ^ x->c[13] ^ x->c[14];
1030     y->c[ 4] = x->c[ 0] ^ x->c[ 2] ^ x->c[ 5] ^ x->c[ 8] ^
1031                x->c[11] ^ x->c[14] ^ x->c[15];
1032     y->c[ 5] = x->c[ 1] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 9] ^
1033                x->c[10] ^ x->c[14] ^ x->c[15];
1034     y->c[ 6] = x->c[ 0] ^ x->c[ 2] ^ x->c[ 7] ^ x->c[ 9] ^
1035                x->c[10] ^ x->c[12] ^ x->c[13];
1036     y->c[ 7] = x->c[ 1] ^ x->c[ 3] ^ x->c[ 6] ^ x->c[ 8] ^
1037                x->c[11] ^ x->c[12] ^ x->c[13];
1038     y->c[ 8] = x->c[ 0] ^ x->c[ 1] ^ x->c[ 4] ^ x->c[ 7] ^
1039                x->c[10] ^ x->c[13] ^ x->c[15];
1040     y->c[ 9] = x->c[ 0] ^ x->c[ 1] ^ x->c[ 5] ^ x->c[ 6] ^
1041                x->c[11] ^ x->c[12] ^ x->c[14];
1042     y->c[10] = x->c[ 2] ^ x->c[ 3] ^ x->c[ 5] ^ x->c[ 6] ^
1043                x->c[ 8] ^ x->c[13] ^ x->c[15];
1044     y->c[11] = x->c[ 2] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 7] ^
1045                x->c[ 9] ^ x->c[12] ^ x->c[14];
1046     y->c[12] = x->c[ 1] ^ x->c[ 2] ^ x->c[ 6] ^ x->c[ 7] ^
1047                x->c[ 9] ^ x->c[11] ^ x->c[12];
1048     y->c[13] = x->c[ 0] ^ x->c[ 3] ^ x->c[ 6] ^ x->c[ 7] ^
1049                x->c[ 8] ^ x->c[10] ^ x->c[13];
1050     y->c[14] = x->c[ 0] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 5] ^
1051                x->c[ 9] ^ x->c[11] ^ x->c[14];
1052     y->c[15] = x->c[ 1] ^ x->c[ 2] ^ x->c[ 4] ^ x->c[ 5] ^
1053                x->c[ 8] ^ x->c[10] ^ x->c[15];
1054 }
1055
1056 /*
1057  * Odd round function
1058  * Apply the first substitution layer and then a diffusion step.
1059  * It is safe for the input and output to overlap.
1060  */
1061 static ossl_inline void FO(ARIA_u128 *o, const ARIA_u128 *d,
1062                            const ARIA_u128 *rk)
1063 {
1064     ARIA_u128 y;
1065
1066     sl1(&y, d, rk);
1067     a(o, &y);
1068 }
1069
1070 /*
1071  * Even round function
1072  * Apply the second substitution layer and then a diffusion step.
1073  * It is safe for the input and output to overlap.
1074  */
1075 static ossl_inline void FE(ARIA_u128 *o, const ARIA_u128 *d,
1076                            const ARIA_u128 *rk)
1077 {
1078     ARIA_u128 y;
1079
1080     sl2(y.c, d, rk);
1081     a(o, &y);
1082 }
1083
1084 /*
1085  * Encrypt or decrypt a single block
1086  * in and out can overlap
1087  */
1088 static void do_encrypt(unsigned char *o, const unsigned char *pin,
1089                        unsigned int rounds, const ARIA_u128 *keys)
1090 {
1091     ARIA_u128 p;
1092     unsigned int i;
1093
1094     memcpy(&p, pin, sizeof(p));
1095     for (i = 0; i < rounds - 2; i += 2) {
1096         FO(&p, &p, &keys[i]);
1097         FE(&p, &p, &keys[i + 1]);
1098     }
1099     FO(&p, &p, &keys[rounds - 2]);
1100     sl2(o, &p, &keys[rounds - 1]);
1101     xor128(o, o, &keys[rounds]);
1102 }
1103
1104 /*
1105  * Encrypt a single block
1106  * in and out can overlap
1107  */
1108 void aria_encrypt(const unsigned char *in, unsigned char *out,
1109                   const ARIA_KEY *key)
1110 {
1111     assert(in != NULL && out != NULL && key != NULL);
1112     do_encrypt(out, in, key->rounds, key->rd_key);
1113 }
1114
1115
1116 /*
1117  * Expand the cipher key into the encryption key schedule.
1118  * We short circuit execution of the last two
1119  * or four rotations based on the key size.
1120  */
1121 int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
1122                          ARIA_KEY *key)
1123 {
1124     const ARIA_u128 *ck1, *ck2, *ck3;
1125     ARIA_u128 kr, w0, w1, w2, w3;
1126
1127     if (!userKey || !key)
1128         return -1;
1129     memcpy(w0.c, userKey, sizeof(w0));
1130     switch (bits) {
1131     default:
1132         return -2;
1133     case 128:
1134         key->rounds = 12;
1135         ck1 = &c1;
1136         ck2 = &c2;
1137         ck3 = &c3;
1138         memset(kr.c, 0, sizeof(kr));
1139         break;
1140
1141     case 192:
1142         key->rounds = 14;
1143         ck1 = &c2;
1144         ck2 = &c3;
1145         ck3 = &c1;
1146         memcpy(kr.c, userKey + ARIA_BLOCK_SIZE, sizeof(kr) / 2);
1147         memset(kr.c + ARIA_BLOCK_SIZE / 2, 0, sizeof(kr) / 2);
1148         break;
1149
1150     case 256:
1151         key->rounds = 16;
1152         ck1 = &c3;
1153         ck2 = &c1;
1154         ck3 = &c2;
1155         memcpy(kr.c, userKey + ARIA_BLOCK_SIZE, sizeof(kr));
1156         break;
1157     }
1158
1159     FO(&w3, &w0, ck1);    xor128(w1.c, w3.c, &kr);
1160     FE(&w3, &w1, ck2);    xor128(w2.c, w3.c, &w0);
1161     FO(&kr, &w2, ck3);    xor128(w3.c, kr.c, &w1);
1162
1163     rot19r(&key->rd_key[ 0], &w0, &w1);
1164     rot19r(&key->rd_key[ 1], &w1, &w2);
1165     rot19r(&key->rd_key[ 2], &w2, &w3);
1166     rot19r(&key->rd_key[ 3], &w3, &w0);
1167
1168     rot31r(&key->rd_key[ 4], &w0, &w1);
1169     rot31r(&key->rd_key[ 5], &w1, &w2);
1170     rot31r(&key->rd_key[ 6], &w2, &w3);
1171     rot31r(&key->rd_key[ 7], &w3, &w0);
1172
1173     rot61l(&key->rd_key[ 8], &w0, &w1);
1174     rot61l(&key->rd_key[ 9], &w1, &w2);
1175     rot61l(&key->rd_key[10], &w2, &w3);
1176     rot61l(&key->rd_key[11], &w3, &w0);
1177
1178     rot31l(&key->rd_key[12], &w0, &w1);
1179     if (key->rounds > 12) {
1180         rot31l(&key->rd_key[13], &w1, &w2);
1181         rot31l(&key->rd_key[14], &w2, &w3);
1182
1183         if (key->rounds > 14) {
1184             rot31l(&key->rd_key[15], &w3, &w0);
1185             rot19l(&key->rd_key[16], &w0, &w1);
1186         }
1187     }
1188     return 0;
1189 }
1190
1191 /*
1192  * Expand the cipher key into the decryption key schedule.
1193  */
1194 int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
1195                          ARIA_KEY *key)
1196 {
1197     ARIA_KEY ek;
1198     const int r = aria_set_encrypt_key(userKey, bits, &ek);
1199     unsigned int i, rounds = ek.rounds;
1200
1201     if (r == 0) {
1202         key->rounds = rounds;
1203         memcpy(&key->rd_key[0], &ek.rd_key[rounds], sizeof(key->rd_key[0]));
1204         for (i = 1; i < rounds; i++)
1205             a(&key->rd_key[i], &ek.rd_key[rounds - i]);
1206         memcpy(&key->rd_key[rounds], &ek.rd_key[0], sizeof(key->rd_key[rounds]));
1207     }
1208     return r;
1209 }
1210
1211 #endif