Implementation of the ARIA cipher as described in RFC 5794.
[openssl.git] / crypto / aria / aria.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* ====================================================================
11  * Copyright (c) 2017 Oracle and/or its affiliates.  All rights reserved.
12  */
13
14 #include <assert.h>
15 #include <openssl/e_os2.h>
16 #include <string.h>
17 #include "internal/aria.h"
18
19 static const unsigned char sb1[256] = {
20     0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
21     0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
22     0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
23     0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
24     0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
25     0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
26     0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
27     0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
28     0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
29     0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
30     0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
31     0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
32     0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
33     0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
34     0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
35     0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
36     0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
37     0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
38     0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
39     0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
40     0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
41     0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
42     0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
43     0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
44     0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
45     0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
46     0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
47     0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
48     0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
49     0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
50     0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
51     0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
52 };
53
54 static const unsigned char sb2[256] = {
55     0xe2, 0x4e, 0x54, 0xfc, 0x94, 0xc2, 0x4a, 0xcc,
56     0x62, 0x0d, 0x6a, 0x46, 0x3c, 0x4d, 0x8b, 0xd1,
57     0x5e, 0xfa, 0x64, 0xcb, 0xb4, 0x97, 0xbe, 0x2b,
58     0xbc, 0x77, 0x2e, 0x03, 0xd3, 0x19, 0x59, 0xc1,
59     0x1d, 0x06, 0x41, 0x6b, 0x55, 0xf0, 0x99, 0x69,
60     0xea, 0x9c, 0x18, 0xae, 0x63, 0xdf, 0xe7, 0xbb,
61     0x00, 0x73, 0x66, 0xfb, 0x96, 0x4c, 0x85, 0xe4,
62     0x3a, 0x09, 0x45, 0xaa, 0x0f, 0xee, 0x10, 0xeb,
63     0x2d, 0x7f, 0xf4, 0x29, 0xac, 0xcf, 0xad, 0x91,
64     0x8d, 0x78, 0xc8, 0x95, 0xf9, 0x2f, 0xce, 0xcd,
65     0x08, 0x7a, 0x88, 0x38, 0x5c, 0x83, 0x2a, 0x28,
66     0x47, 0xdb, 0xb8, 0xc7, 0x93, 0xa4, 0x12, 0x53,
67     0xff, 0x87, 0x0e, 0x31, 0x36, 0x21, 0x58, 0x48,
68     0x01, 0x8e, 0x37, 0x74, 0x32, 0xca, 0xe9, 0xb1,
69     0xb7, 0xab, 0x0c, 0xd7, 0xc4, 0x56, 0x42, 0x26,
70     0x07, 0x98, 0x60, 0xd9, 0xb6, 0xb9, 0x11, 0x40,
71     0xec, 0x20, 0x8c, 0xbd, 0xa0, 0xc9, 0x84, 0x04,
72     0x49, 0x23, 0xf1, 0x4f, 0x50, 0x1f, 0x13, 0xdc,
73     0xd8, 0xc0, 0x9e, 0x57, 0xe3, 0xc3, 0x7b, 0x65,
74     0x3b, 0x02, 0x8f, 0x3e, 0xe8, 0x25, 0x92, 0xe5,
75     0x15, 0xdd, 0xfd, 0x17, 0xa9, 0xbf, 0xd4, 0x9a,
76     0x7e, 0xc5, 0x39, 0x67, 0xfe, 0x76, 0x9d, 0x43,
77     0xa7, 0xe1, 0xd0, 0xf5, 0x68, 0xf2, 0x1b, 0x34,
78     0x70, 0x05, 0xa3, 0x8a, 0xd5, 0x79, 0x86, 0xa8,
79     0x30, 0xc6, 0x51, 0x4b, 0x1e, 0xa6, 0x27, 0xf6,
80     0x35, 0xd2, 0x6e, 0x24, 0x16, 0x82, 0x5f, 0xda,
81     0xe6, 0x75, 0xa2, 0xef, 0x2c, 0xb2, 0x1c, 0x9f,
82     0x5d, 0x6f, 0x80, 0x0a, 0x72, 0x44, 0x9b, 0x6c,
83     0x90, 0x0b, 0x5b, 0x33, 0x7d, 0x5a, 0x52, 0xf3,
84     0x61, 0xa1, 0xf7, 0xb0, 0xd6, 0x3f, 0x7c, 0x6d,
85     0xed, 0x14, 0xe0, 0xa5, 0x3d, 0x22, 0xb3, 0xf8,
86     0x89, 0xde, 0x71, 0x1a, 0xaf, 0xba, 0xb5, 0x81
87 };
88
89 static const unsigned char sb3[256] = {
90     0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
91     0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
92     0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
93     0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
94     0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
95     0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
96     0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
97     0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
98     0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
99     0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
100     0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
101     0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
102     0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
103     0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
104     0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
105     0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
106     0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
107     0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
108     0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
109     0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
110     0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
111     0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
112     0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
113     0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
114     0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
115     0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
116     0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
117     0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
118     0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
119     0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
120     0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
121     0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
122 };
123
124 static const unsigned char sb4[256] = {
125     0x30, 0x68, 0x99, 0x1b, 0x87, 0xb9, 0x21, 0x78,
126     0x50, 0x39, 0xdb, 0xe1, 0x72, 0x09, 0x62, 0x3c,
127     0x3e, 0x7e, 0x5e, 0x8e, 0xf1, 0xa0, 0xcc, 0xa3,
128     0x2a, 0x1d, 0xfb, 0xb6, 0xd6, 0x20, 0xc4, 0x8d,
129     0x81, 0x65, 0xf5, 0x89, 0xcb, 0x9d, 0x77, 0xc6,
130     0x57, 0x43, 0x56, 0x17, 0xd4, 0x40, 0x1a, 0x4d,
131     0xc0, 0x63, 0x6c, 0xe3, 0xb7, 0xc8, 0x64, 0x6a,
132     0x53, 0xaa, 0x38, 0x98, 0x0c, 0xf4, 0x9b, 0xed,
133     0x7f, 0x22, 0x76, 0xaf, 0xdd, 0x3a, 0x0b, 0x58,
134     0x67, 0x88, 0x06, 0xc3, 0x35, 0x0d, 0x01, 0x8b,
135     0x8c, 0xc2, 0xe6, 0x5f, 0x02, 0x24, 0x75, 0x93,
136     0x66, 0x1e, 0xe5, 0xe2, 0x54, 0xd8, 0x10, 0xce,
137     0x7a, 0xe8, 0x08, 0x2c, 0x12, 0x97, 0x32, 0xab,
138     0xb4, 0x27, 0x0a, 0x23, 0xdf, 0xef, 0xca, 0xd9,
139     0xb8, 0xfa, 0xdc, 0x31, 0x6b, 0xd1, 0xad, 0x19,
140     0x49, 0xbd, 0x51, 0x96, 0xee, 0xe4, 0xa8, 0x41,
141     0xda, 0xff, 0xcd, 0x55, 0x86, 0x36, 0xbe, 0x61,
142     0x52, 0xf8, 0xbb, 0x0e, 0x82, 0x48, 0x69, 0x9a,
143     0xe0, 0x47, 0x9e, 0x5c, 0x04, 0x4b, 0x34, 0x15,
144     0x79, 0x26, 0xa7, 0xde, 0x29, 0xae, 0x92, 0xd7,
145     0x84, 0xe9, 0xd2, 0xba, 0x5d, 0xf3, 0xc5, 0xb0,
146     0xbf, 0xa4, 0x3b, 0x71, 0x44, 0x46, 0x2b, 0xfc,
147     0xeb, 0x6f, 0xd5, 0xf6, 0x14, 0xfe, 0x7c, 0x70,
148     0x5a, 0x7d, 0xfd, 0x2f, 0x18, 0x83, 0x16, 0xa5,
149     0x91, 0x1f, 0x05, 0x95, 0x74, 0xa9, 0xc1, 0x5b,
150     0x4a, 0x85, 0x6d, 0x13, 0x07, 0x4f, 0x4e, 0x45,
151     0xb2, 0x0f, 0xc9, 0x1c, 0xa6, 0xbc, 0xec, 0x73,
152     0x90, 0x7b, 0xcf, 0x59, 0x8f, 0xa1, 0xf9, 0x2d,
153     0xf2, 0xb1, 0x00, 0x94, 0x37, 0x9f, 0xd0, 0x2e,
154     0x9c, 0x6e, 0x28, 0x3f, 0x80, 0xf0, 0x3d, 0xd3,
155     0x25, 0x8a, 0xb5, 0xe7, 0x42, 0xb3, 0xc7, 0xea,
156     0xf7, 0x4c, 0x11, 0x33, 0x03, 0xa2, 0xac, 0x60
157 };
158
159 static const ARIA_u128 c1 = {
160     0x51, 0x7c, 0xc1, 0xb7, 0x27, 0x22, 0x0a, 0x94,
161     0xfe, 0x13, 0xab, 0xe8, 0xfa, 0x9a, 0x6e, 0xe0
162 };
163
164 static const ARIA_u128 c2 = {
165     0x6d, 0xb1, 0x4a, 0xcc, 0x9e, 0x21, 0xc8, 0x20,
166     0xff, 0x28, 0xb1, 0xd5, 0xef, 0x5d, 0xe2, 0xb0
167 };
168
169 static const ARIA_u128 c3 = {
170     0xdb, 0x92, 0x37, 0x1d, 0x21, 0x26, 0xe9, 0x70,
171     0x03, 0x24, 0x97, 0x75, 0x04, 0xe8, 0xc9, 0x0e
172 };
173
174 /*
175  * Exclusive or two 128 bit values into the result.
176  * It is safe for the result to be the same as the either input.
177  */
178 static void xor128(ARIA_u128 o, const ARIA_u128 x, const ARIA_u128 y)
179 {
180     int i;
181
182     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
183         o[i] = x[i] ^ y[i];
184 }
185
186 /*
187  * Generalised circular rotate right and exclusive or function.
188  * It is safe for the output to overlap either input.
189  */
190 static ossl_inline void rotnr(unsigned int n, ARIA_u128 o, const ARIA_u128 xor,
191                               const ARIA_u128 z)
192 {
193     const unsigned int bytes = n / 8, bits = n % 8;
194     unsigned int i;
195     ARIA_u128 t;
196
197     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
198         t[(i + bytes) % ARIA_BLOCK_SIZE] = z[i];
199     for (i = 0; i < ARIA_BLOCK_SIZE; i++)
200         o[i] = ((t[i] >> bits) |
201                 (t[i ? i - 1 : ARIA_BLOCK_SIZE - 1] << (8 - bits))) ^ xor[i];
202 }
203
204 /*
205  * Circular rotate 19 bits right and xor.
206  * It is safe for the output to overlap either input.
207  */
208 static void rot19r(ARIA_u128 o, const ARIA_u128 xor, const ARIA_u128 z)
209 {
210     rotnr(19, o, xor, z);
211 }
212
213 /*
214  * Circular rotate 31 bits right and xor.
215  * It is safe for the output to overlap either input.
216  */
217 static void rot31r(ARIA_u128 o, const ARIA_u128 xor, const ARIA_u128 z)
218 {
219     rotnr(31, o, xor, z);
220 }
221
222 /*
223  * Circular rotate 61 bits left and xor.
224  * It is safe for the output to overlap either input.
225  */
226 static void rot61l(ARIA_u128 o, const ARIA_u128 xor, const ARIA_u128 z)
227 {
228     rotnr(8 * ARIA_BLOCK_SIZE - 61, o, xor, z);
229 }
230
231 /*
232  * Circular rotate 31 bits left and xor.
233  * It is safe for the output to overlap either input.
234  */
235 static void rot31l(ARIA_u128 o, const ARIA_u128 xor, const ARIA_u128 z)
236 {
237     rotnr(8 * ARIA_BLOCK_SIZE - 31, o, xor, z);
238 }
239
240 /*
241  * Circular rotate 19 bits left and xor.
242  * It is safe for the output to overlap either input.
243  */
244 static void rot19l(ARIA_u128 o, const ARIA_u128 xor, const ARIA_u128 z)
245 {
246     rotnr(8 * ARIA_BLOCK_SIZE - 19, o, xor, z);
247 }
248
249 /*
250  * First substitution and xor layer, used for odd steps.
251  * It is safe for the input and output to be the same.
252  */
253 static void sl1(ARIA_u128 o, const ARIA_u128 x, const ARIA_u128 y)
254 {
255     unsigned int i;
256     for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
257         o[i    ] = sb1[x[i    ] ^ y[i    ]];
258         o[i + 1] = sb2[x[i + 1] ^ y[i + 1]];
259         o[i + 2] = sb3[x[i + 2] ^ y[i + 2]];
260         o[i + 3] = sb4[x[i + 3] ^ y[i + 3]];
261     }
262 }
263
264 /*
265  * Second substitution and xor layer, used for even steps.
266  * It is safe for the input and output to be the same.
267  */
268 static void sl2(ARIA_u128 o, const ARIA_u128 x, const ARIA_u128 y)
269 {
270     unsigned int i;
271     for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
272         o[i    ] = sb3[x[i    ] ^ y[i    ]];
273         o[i + 1] = sb4[x[i + 1] ^ y[i + 1]];
274         o[i + 2] = sb1[x[i + 2] ^ y[i + 2]];
275         o[i + 3] = sb2[x[i + 3] ^ y[i + 3]];
276     }
277 }
278
279 /*
280  * Diffusion layer step
281  * It is NOT safe for the input and output to overlap.
282  */
283 static void a(ARIA_u128 y, const ARIA_u128 x)
284 {
285     y[ 0] = x[3] ^ x[4] ^ x[6] ^ x[ 8] ^ x[ 9] ^ x[13] ^ x[14];
286     y[ 1] = x[2] ^ x[5] ^ x[7] ^ x[ 8] ^ x[ 9] ^ x[12] ^ x[15];
287     y[ 2] = x[1] ^ x[4] ^ x[6] ^ x[10] ^ x[11] ^ x[12] ^ x[15];
288     y[ 3] = x[0] ^ x[5] ^ x[7] ^ x[10] ^ x[11] ^ x[13] ^ x[14];
289     y[ 4] = x[0] ^ x[2] ^ x[5] ^ x[ 8] ^ x[11] ^ x[14] ^ x[15];
290     y[ 5] = x[1] ^ x[3] ^ x[4] ^ x[ 9] ^ x[10] ^ x[14] ^ x[15];
291     y[ 6] = x[0] ^ x[2] ^ x[7] ^ x[ 9] ^ x[10] ^ x[12] ^ x[13];
292     y[ 7] = x[1] ^ x[3] ^ x[6] ^ x[ 8] ^ x[11] ^ x[12] ^ x[13];
293     y[ 8] = x[0] ^ x[1] ^ x[4] ^ x[ 7] ^ x[10] ^ x[13] ^ x[15];
294     y[ 9] = x[0] ^ x[1] ^ x[5] ^ x[ 6] ^ x[11] ^ x[12] ^ x[14];
295     y[10] = x[2] ^ x[3] ^ x[5] ^ x[ 6] ^ x[ 8] ^ x[13] ^ x[15];
296     y[11] = x[2] ^ x[3] ^ x[4] ^ x[ 7] ^ x[ 9] ^ x[12] ^ x[14];
297     y[12] = x[1] ^ x[2] ^ x[6] ^ x[ 7] ^ x[ 9] ^ x[11] ^ x[12];
298     y[13] = x[0] ^ x[3] ^ x[6] ^ x[ 7] ^ x[ 8] ^ x[10] ^ x[13];
299     y[14] = x[0] ^ x[3] ^ x[4] ^ x[ 5] ^ x[ 9] ^ x[11] ^ x[14];
300     y[15] = x[1] ^ x[2] ^ x[4] ^ x[ 5] ^ x[ 8] ^ x[10] ^ x[15];
301 }
302
303 /*
304  * Odd round function
305  * Apply the first substitution layer and then a diffusion step.
306  * It is safe for the input and output to overlap.
307  */
308 static ossl_inline void FO(ARIA_u128 o, const ARIA_u128 d, const ARIA_u128 rk)
309 {
310         ARIA_u128 y;
311
312         sl1(y, d, rk);
313         a(o, y);
314 }
315
316 /*
317  * Even round function
318  * Apply the second substitution layer and then a diffusion step.
319  * It is safe for the input and output to overlap.
320  */
321 static ossl_inline void FE(ARIA_u128 o, const ARIA_u128 d, const ARIA_u128 rk)
322 {
323         ARIA_u128 y;
324
325         sl2(y, d, rk);
326         a(o, y);
327 }
328
329 /*
330  * Encrypt or decrypt a single block
331  * in and out can overlap
332  */
333 static void do_encrypt(ARIA_u128 o, const ARIA_u128 pin, unsigned int rounds,
334                        const ARIA_u128 *keys)
335 {
336     ARIA_u128 p;
337     unsigned int i;
338
339     memcpy(p, pin, sizeof(p));
340     for (i = 0; i < rounds - 2; i += 2) {
341         FO(p, p, keys[i]);
342         FE(p, p, keys[i + 1]);
343     }
344     FO(p, p, keys[rounds - 2]);
345     sl2(o, p, keys[rounds - 1]);
346     xor128(o, o, keys[rounds]);
347 }
348
349 /*
350  * Encrypt a single block
351  * in and out can overlap
352  */
353 void aria_encrypt(const unsigned char *in, unsigned char *out,
354                   const ARIA_KEY *key)
355 {
356     assert(in != NULL && out != NULL && key != NULL);
357     do_encrypt(out, in, key->rounds, key->rd_key);
358 }
359
360
361 /*
362  * Expand the cipher key into the encryption key schedule.
363  * We short circuit execution of the last two
364  * or four rotations based on the key size.
365  */
366 int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
367                          ARIA_KEY *key)
368 {
369     const unsigned char *ck1, *ck2, *ck3;
370     ARIA_u128 kr, w0, w1, w2, w3;
371
372     if (!userKey || !key)
373         return -1;
374     memcpy(w0, userKey, sizeof(w0));
375     switch (bits) {
376     default:
377         return -2;
378     case 128:
379         key->rounds = 12;
380         ck1 = c1;
381         ck2 = c2;
382         ck3 = c3;
383         memset(kr, 0, sizeof(kr));
384         break;
385
386     case 192:
387         key->rounds = 14;
388         ck1 = c2;
389         ck2 = c3;
390         ck3 = c1;
391         memcpy(kr, userKey + ARIA_BLOCK_SIZE, sizeof(kr) / 2);
392         memset(kr + ARIA_BLOCK_SIZE / 2, 0, sizeof(kr) / 2);
393         break;
394
395     case 256:
396         key->rounds = 16;
397         ck1 = c3;
398         ck2 = c1;
399         ck3 = c2;
400         memcpy(kr, userKey + ARIA_BLOCK_SIZE, sizeof(kr));
401         break;
402     }
403
404     FO(w3, w0, ck1);    xor128(w1, w3, kr);
405     FE(w3, w1, ck2);    xor128(w2, w3, w0);
406     FO(kr, w2, ck3);    xor128(w3, kr, w1);
407
408     rot19r(key->rd_key[ 0], w0, w1);
409     rot19r(key->rd_key[ 1], w1, w2);
410     rot19r(key->rd_key[ 2], w2, w3);
411     rot19r(key->rd_key[ 3], w3, w0);
412
413     rot31r(key->rd_key[ 4], w0, w1);
414     rot31r(key->rd_key[ 5], w1, w2);
415     rot31r(key->rd_key[ 6], w2, w3);
416     rot31r(key->rd_key[ 7], w3, w0);
417
418     rot61l(key->rd_key[ 8], w0, w1);
419     rot61l(key->rd_key[ 9], w1, w2);
420     rot61l(key->rd_key[10], w2, w3);
421     rot61l(key->rd_key[11], w3, w0);
422
423     rot31l(key->rd_key[12], w0, w1);
424     if (key->rounds > 12) {
425         rot31l(key->rd_key[13], w1, w2);
426         rot31l(key->rd_key[14], w2, w3);
427
428         if (key->rounds > 14) {
429             rot31l(key->rd_key[15], w3, w0);
430             rot19l(key->rd_key[16], w0, w1);
431         }
432     }
433     return 0;
434 }
435
436 /*
437  * Expand the cipher key into the decryption key schedule.
438  */
439 int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
440                          ARIA_KEY *key)
441 {
442     ARIA_KEY ek;
443     const int r = aria_set_encrypt_key(userKey, bits, &ek);
444     unsigned int i, rounds = ek.rounds;
445
446     if (r == 0) {
447         key->rounds = rounds;
448         memcpy(key->rd_key[0], ek.rd_key[rounds], sizeof(key->rd_key[0]));
449         for (i = 1; i < rounds; i++)
450             a(key->rd_key[i], ek.rd_key[rounds - i]);
451         memcpy(key->rd_key[rounds], ek.rd_key[0], sizeof(key->rd_key[rounds]));
452     }
453     return r;
454 }