cast5: add ARMv6 assembly implementation
[libgcrypt.git] / cipher / cast5.c
1 /* cast5.c  -  CAST5 cipher (RFC2144)
2  *      Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /* Test vectors:
22  *
23  * 128-bit key         = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
24  *         plaintext   = 01 23 45 67 89 AB CD EF
25  *         ciphertext  = 23 8B 4F E5 84 7E 44 B2
26  *
27  * 80-bit  key         = 01 23 45 67 12 34 56 78 23 45
28  *                     = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
29  *         plaintext   = 01 23 45 67 89 AB CD EF
30  *         ciphertext  = EB 6A 71 1A 2C 02 27 1B
31  *
32  * 40-bit  key         = 01 23 45 67 12
33  *                     = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
34  *         plaintext   = 01 23 45 67 89 AB CD EF
35  *         ciphertext  = 7A C8 16 D1 6E 9B 30 2E
36  */
37
38 #include <config.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "g10lib.h"
43 #include "types.h"
44 #include "cipher.h"
45 #include "bufhelp.h"
46 #include "cipher-selftest.h"
47
48 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */
49 #undef USE_AMD64_ASM
50 #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)
51 # define USE_AMD64_ASM 1
52 #endif
53
54 /* USE_ARMV6_ASM indicates whether to use ARMv6 assembly code. */
55 #undef USE_ARMV6_ASM
56 #if defined(__arm__) && defined(__ARMEL__) && \
57          ((defined(__ARM_ARCH) && __ARM_ARCH >= 6) \
58         || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
59         || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
60         || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \
61         || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
62         || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
63         || defined(__ARM_ARCH_7EM__))
64 # ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
65 #  define USE_ARMV6_ASM 1
66 # endif
67 #endif
68
69 #define CAST5_BLOCKSIZE 8
70
71 typedef struct {
72     u32  Km[16];
73     byte Kr[16];
74 #ifdef USE_ARMV6_ASM
75     u32 Kr_arm_enc[16 / sizeof(u32)];
76     u32 Kr_arm_dec[16 / sizeof(u32)];
77 #endif
78 } CAST5_context;
79
80 static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen);
81 static void encrypt_block (void *c, byte *outbuf, const byte *inbuf);
82 static void decrypt_block (void *c, byte *outbuf, const byte *inbuf);
83
84
85
86 #define s1 _gcry_cast5_s1to4[0]
87 #define s2 _gcry_cast5_s1to4[1]
88 #define s3 _gcry_cast5_s1to4[2]
89 #define s4 _gcry_cast5_s1to4[3]
90
91 const u32 _gcry_cast5_s1to4[4][256] = { {
92 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
93 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
94 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
95 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
96 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
97 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
98 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
99 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
100 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
101 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
102 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
103 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
104 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
105 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
106 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
107 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
108 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
109 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
110 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
111 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
112 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
113 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
114 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
115 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
116 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
117 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
118 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
119 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
120 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
121 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
122 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
123 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
124 }, {
125 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
126 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
127 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
128 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
129 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
130 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
131 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
132 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
133 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
134 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
135 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
136 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
137 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
138 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
139 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
140 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
141 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
142 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
143 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
144 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
145 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
146 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
147 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
148 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
149 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
150 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
151 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
152 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
153 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
154 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
155 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
156 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
157 }, {
158 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
159 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
160 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
161 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
162 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
163 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
164 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
165 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
166 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
167 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
168 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
169 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
170 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
171 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
172 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
173 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
174 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
175 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
176 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
177 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
178 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
179 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
180 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
181 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
182 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
183 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
184 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
185 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
186 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
187 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
188 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
189 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
190 }, {
191 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
192 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
193 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
194 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
195 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
196 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
197 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
198 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
199 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
200 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
201 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
202 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
203 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
204 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
205 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
206 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
207 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
208 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
209 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
210 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
211 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
212 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
213 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
214 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
215 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
216 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
217 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
218 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
219 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
220 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
221 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
222 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
223 } };
224 static const u32 s5[256] = {
225 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
226 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
227 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
228 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
229 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
230 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
231 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
232 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
233 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
234 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
235 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
236 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
237 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
238 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
239 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
240 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
241 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
242 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
243 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
244 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
245 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
246 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
247 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
248 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
249 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
250 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
251 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
252 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
253 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
254 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
255 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
256 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
257 };
258 static const u32 s6[256] = {
259 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
260 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
261 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
262 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
263 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
264 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
265 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
266 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
267 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
268 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
269 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
270 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
271 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
272 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
273 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
274 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
275 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
276 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
277 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
278 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
279 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
280 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
281 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
282 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
283 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
284 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
285 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
286 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
287 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
288 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
289 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
290 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
291 };
292 static const u32 s7[256] = {
293 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
294 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
295 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
296 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
297 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
298 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
299 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
300 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
301 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
302 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
303 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
304 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
305 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
306 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
307 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
308 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
309 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
310 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
311 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
312 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
313 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
314 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
315 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
316 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
317 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
318 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
319 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
320 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
321 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
322 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
323 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
324 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
325 };
326 static const u32 s8[256] = {
327 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
328 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
329 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
330 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
331 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
332 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
333 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
334 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
335 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
336 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
337 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
338 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
339 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
340 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
341 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
342 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
343 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
344 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
345 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
346 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
347 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
348 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
349 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
350 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
351 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
352 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
353 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
354 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
355 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
356 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
357 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
358 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
359 };
360
361
362 #ifdef USE_AMD64_ASM
363
364 /* Assembly implementations of CAST5. */
365 extern void _gcry_cast5_amd64_encrypt_block(CAST5_context *c, byte *outbuf,
366                                             const byte *inbuf);
367
368 extern void _gcry_cast5_amd64_decrypt_block(CAST5_context *c, byte *outbuf,
369                                             const byte *inbuf);
370
371 /* These assembly implementations process four blocks in parallel. */
372 extern void _gcry_cast5_amd64_ctr_enc(CAST5_context *ctx, byte *out,
373                                       const byte *in, byte *ctr);
374
375 extern void _gcry_cast5_amd64_cbc_dec(CAST5_context *ctx, byte *out,
376                                       const byte *in, byte *iv);
377
378 extern void _gcry_cast5_amd64_cfb_dec(CAST5_context *ctx, byte *out,
379                                       const byte *in, byte *iv);
380
381 static void
382 do_encrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
383 {
384   _gcry_cast5_amd64_encrypt_block (context, outbuf, inbuf);
385 }
386
387 static void
388 do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
389 {
390   _gcry_cast5_amd64_decrypt_block (context, outbuf, inbuf);
391 }
392
393 static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
394 {
395   CAST5_context *c = (CAST5_context *) context;
396   do_encrypt_block (c, outbuf, inbuf);
397   _gcry_burn_stack (2*8);
398 }
399
400 static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
401 {
402   CAST5_context *c = (CAST5_context *) context;
403   _gcry_cast5_amd64_decrypt_block (c, outbuf, inbuf);
404   _gcry_burn_stack (2*8);
405 }
406
407 #elif defined(USE_ARMV6_ASM)
408
409 /* ARMv6 assembly implementations of CAST5. */
410 extern void _gcry_cast5_armv6_encrypt_block(CAST5_context *c, byte *outbuf,
411                                             const byte *inbuf);
412
413 extern void _gcry_cast5_armv6_decrypt_block(CAST5_context *c, byte *outbuf,
414                                             const byte *inbuf);
415
416 /* These assembly implementations process two blocks in parallel. */
417 extern void _gcry_cast5_armv6_ctr_enc(CAST5_context *ctx, byte *out,
418                                       const byte *in, byte *ctr);
419
420 extern void _gcry_cast5_armv6_cbc_dec(CAST5_context *ctx, byte *out,
421                                       const byte *in, byte *iv);
422
423 extern void _gcry_cast5_armv6_cfb_dec(CAST5_context *ctx, byte *out,
424                                       const byte *in, byte *iv);
425
426 static void
427 do_encrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
428 {
429   _gcry_cast5_armv6_encrypt_block (context, outbuf, inbuf);
430 }
431
432 static void
433 do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
434 {
435   _gcry_cast5_armv6_decrypt_block (context, outbuf, inbuf);
436 }
437
438 static void encrypt_block (void *context , byte *outbuf, const byte *inbuf)
439 {
440   CAST5_context *c = (CAST5_context *) context;
441   do_encrypt_block (c, outbuf, inbuf);
442   _gcry_burn_stack (10*4);
443 }
444
445 static void decrypt_block (void *context, byte *outbuf, const byte *inbuf)
446 {
447   CAST5_context *c = (CAST5_context *) context;
448   do_decrypt_block (c, outbuf, inbuf);
449   _gcry_burn_stack (10*4);
450 }
451
452 #else /*USE_ARMV6_ASM*/
453
454 #if defined(__GNUC__) && defined(__i386__)
455 static inline u32
456 rol(int n, u32 x)
457 {
458         __asm__("roll %%cl,%0"
459                 :"=r" (x)
460                 :"0" (x),"c" (n)
461                 :"cc");
462         return x;
463 }
464 #else
465 #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
466 #endif
467
468 #define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
469     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
470 #define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
471     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
472 #define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
473     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
474
475 static void
476 do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf )
477 {
478     u32 l, r, t;
479     u32 I;   /* used by the Fx macros */
480     u32 *Km;
481     byte *Kr;
482
483     Km = c->Km;
484     Kr = c->Kr;
485
486     /* (L0,R0) <-- (m1...m64).  (Split the plaintext into left and
487      * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
488      */
489     l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
490     r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
491
492     /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
493      *  Li = Ri-1;
494      *  Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
495      * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
496      * Rounds 2, 5, 8, 11, and 14 use f function Type 2.
497      * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
498      */
499
500     t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
501     t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
502     t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
503     t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
504     t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
505     t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
506     t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
507     t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
508     t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
509     t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
510     t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
511     t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
512     t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
513     t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
514     t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
515     t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
516
517     /* c1...c64 <-- (R16,L16).  (Exchange final blocks L16, R16 and
518      *  concatenate to form the ciphertext.) */
519     outbuf[0] = (r >> 24) & 0xff;
520     outbuf[1] = (r >> 16) & 0xff;
521     outbuf[2] = (r >>  8) & 0xff;
522     outbuf[3] =  r        & 0xff;
523     outbuf[4] = (l >> 24) & 0xff;
524     outbuf[5] = (l >> 16) & 0xff;
525     outbuf[6] = (l >>  8) & 0xff;
526     outbuf[7] =  l        & 0xff;
527 }
528
529 static void
530 encrypt_block (void *context , byte *outbuf, const byte *inbuf)
531 {
532   CAST5_context *c = (CAST5_context *) context;
533   do_encrypt_block (c, outbuf, inbuf);
534   _gcry_burn_stack (20+4*sizeof(void*));
535 }
536
537
538 static void
539 do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf )
540 {
541     u32 l, r, t;
542     u32 I;
543     u32 *Km;
544     byte *Kr;
545
546     Km = c->Km;
547     Kr = c->Kr;
548
549     l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
550     r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
551
552     t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
553     t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
554     t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
555     t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
556     t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
557     t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
558     t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
559     t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
560     t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
561     t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
562     t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
563     t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
564     t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
565     t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
566     t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
567     t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
568
569     outbuf[0] = (r >> 24) & 0xff;
570     outbuf[1] = (r >> 16) & 0xff;
571     outbuf[2] = (r >>  8) & 0xff;
572     outbuf[3] =  r        & 0xff;
573     outbuf[4] = (l >> 24) & 0xff;
574     outbuf[5] = (l >> 16) & 0xff;
575     outbuf[6] = (l >>  8) & 0xff;
576     outbuf[7] =  l        & 0xff;
577 }
578
579 static void
580 decrypt_block (void *context, byte *outbuf, const byte *inbuf)
581 {
582   CAST5_context *c = (CAST5_context *) context;
583   do_decrypt_block (c, outbuf, inbuf);
584   _gcry_burn_stack (20+4*sizeof(void*));
585 }
586
587 #endif /*!USE_ARMV6_ASM*/
588
589
590 /* Bulk encryption of complete blocks in CTR mode.  This function is only
591    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
592    of size CAST5_BLOCKSIZE. */
593 void
594 _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
595                     const void *inbuf_arg, unsigned int nblocks)
596 {
597   CAST5_context *ctx = context;
598   unsigned char *outbuf = outbuf_arg;
599   const unsigned char *inbuf = inbuf_arg;
600   unsigned char tmpbuf[CAST5_BLOCKSIZE];
601   int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
602
603   int i;
604
605 #ifdef USE_AMD64_ASM
606   {
607     if (nblocks >= 4)
608       burn_stack_depth += 8 * sizeof(void*);
609
610     /* Process data in 4 block chunks. */
611     while (nblocks >= 4)
612       {
613         _gcry_cast5_amd64_ctr_enc(ctx, outbuf, inbuf, ctr);
614
615         nblocks -= 4;
616         outbuf += 4 * CAST5_BLOCKSIZE;
617         inbuf  += 4 * CAST5_BLOCKSIZE;
618       }
619
620     /* Use generic code to handle smaller chunks... */
621     /* TODO: use caching instead? */
622   }
623 #elif defined(USE_ARMV6_ASM)
624   {
625     /* Process data in 2 block chunks. */
626     while (nblocks >= 2)
627       {
628         _gcry_cast5_armv6_ctr_enc(ctx, outbuf, inbuf, ctr);
629
630         nblocks -= 2;
631         outbuf += 2 * CAST5_BLOCKSIZE;
632         inbuf  += 2 * CAST5_BLOCKSIZE;
633       }
634
635     /* Use generic code to handle smaller chunks... */
636     /* TODO: use caching instead? */
637   }
638 #endif
639
640   for ( ;nblocks; nblocks-- )
641     {
642       /* Encrypt the counter. */
643       do_encrypt_block(ctx, tmpbuf, ctr);
644       /* XOR the input with the encrypted counter and store in output.  */
645       buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE);
646       outbuf += CAST5_BLOCKSIZE;
647       inbuf  += CAST5_BLOCKSIZE;
648       /* Increment the counter.  */
649       for (i = CAST5_BLOCKSIZE; i > 0; i--)
650         {
651           ctr[i-1]++;
652           if (ctr[i-1])
653             break;
654         }
655     }
656
657   wipememory(tmpbuf, sizeof(tmpbuf));
658   _gcry_burn_stack(burn_stack_depth);
659 }
660
661
662 /* Bulk decryption of complete blocks in CBC mode.  This function is only
663    intended for the bulk encryption feature of cipher.c. */
664 void
665 _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
666                     const void *inbuf_arg, unsigned int nblocks)
667 {
668   CAST5_context *ctx = context;
669   unsigned char *outbuf = outbuf_arg;
670   const unsigned char *inbuf = inbuf_arg;
671   unsigned char savebuf[CAST5_BLOCKSIZE];
672   int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
673
674 #ifdef USE_AMD64_ASM
675   {
676     if (nblocks >= 4)
677       burn_stack_depth += 8 * sizeof(void*);
678
679     /* Process data in 4 block chunks. */
680     while (nblocks >= 4)
681       {
682         _gcry_cast5_amd64_cbc_dec(ctx, outbuf, inbuf, iv);
683
684         nblocks -= 4;
685         outbuf += 4 * CAST5_BLOCKSIZE;
686         inbuf  += 4 * CAST5_BLOCKSIZE;
687       }
688
689     /* Use generic code to handle smaller chunks... */
690   }
691 #elif defined(USE_ARMV6_ASM)
692   {
693     /* Process data in 2 block chunks. */
694     while (nblocks >= 2)
695       {
696         _gcry_cast5_armv6_cbc_dec(ctx, outbuf, inbuf, iv);
697
698         nblocks -= 2;
699         outbuf += 2 * CAST5_BLOCKSIZE;
700         inbuf  += 2 * CAST5_BLOCKSIZE;
701       }
702
703     /* Use generic code to handle smaller chunks... */
704   }
705 #endif
706
707   for ( ;nblocks; nblocks-- )
708     {
709       /* We need to save INBUF away because it may be identical to
710          OUTBUF.  */
711       memcpy(savebuf, inbuf, CAST5_BLOCKSIZE);
712
713       do_decrypt_block (ctx, outbuf, inbuf);
714
715       buf_xor(outbuf, outbuf, iv, CAST5_BLOCKSIZE);
716       memcpy(iv, savebuf, CAST5_BLOCKSIZE);
717       inbuf += CAST5_BLOCKSIZE;
718       outbuf += CAST5_BLOCKSIZE;
719     }
720
721   wipememory(savebuf, sizeof(savebuf));
722   _gcry_burn_stack(burn_stack_depth);
723 }
724
725 /* Bulk decryption of complete blocks in CFB mode.  This function is only
726    intended for the bulk encryption feature of cipher.c. */
727 void
728 _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
729                     const void *inbuf_arg, unsigned int nblocks)
730 {
731   CAST5_context *ctx = context;
732   unsigned char *outbuf = outbuf_arg;
733   const unsigned char *inbuf = inbuf_arg;
734   int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
735
736 #ifdef USE_AMD64_ASM
737   {
738     if (nblocks >= 4)
739       burn_stack_depth += 8 * sizeof(void*);
740
741     /* Process data in 4 block chunks. */
742     while (nblocks >= 4)
743       {
744         _gcry_cast5_amd64_cfb_dec(ctx, outbuf, inbuf, iv);
745
746         nblocks -= 4;
747         outbuf += 4 * CAST5_BLOCKSIZE;
748         inbuf  += 4 * CAST5_BLOCKSIZE;
749       }
750
751     /* Use generic code to handle smaller chunks... */
752   }
753 #elif defined(USE_ARMV6_ASM)
754   {
755     /* Process data in 2 block chunks. */
756     while (nblocks >= 2)
757       {
758         _gcry_cast5_armv6_cfb_dec(ctx, outbuf, inbuf, iv);
759
760         nblocks -= 2;
761         outbuf += 2 * CAST5_BLOCKSIZE;
762         inbuf  += 2 * CAST5_BLOCKSIZE;
763       }
764
765     /* Use generic code to handle smaller chunks... */
766   }
767 #endif
768
769   for ( ;nblocks; nblocks-- )
770     {
771       do_encrypt_block(ctx, iv, iv);
772       buf_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE);
773       outbuf += CAST5_BLOCKSIZE;
774       inbuf  += CAST5_BLOCKSIZE;
775     }
776
777   _gcry_burn_stack(burn_stack_depth);
778 }
779
780
781 /* Run the self-tests for CAST5-CTR, tests IV increment of bulk CTR
782    encryption.  Returns NULL on success. */
783 static const char *
784 selftest_ctr (void)
785 {
786   const int nblocks = 4+1;
787   const int blocksize = CAST5_BLOCKSIZE;
788   const int context_size = sizeof(CAST5_context);
789
790   return _gcry_selftest_helper_ctr("CAST5", &cast_setkey,
791            &encrypt_block, &_gcry_cast5_ctr_enc, nblocks, blocksize,
792            context_size);
793 }
794
795
796 /* Run the self-tests for CAST5-CBC, tests bulk CBC decryption.
797    Returns NULL on success. */
798 static const char *
799 selftest_cbc (void)
800 {
801   const int nblocks = 4+2;
802   const int blocksize = CAST5_BLOCKSIZE;
803   const int context_size = sizeof(CAST5_context);
804
805   return _gcry_selftest_helper_cbc("CAST5", &cast_setkey,
806            &encrypt_block, &_gcry_cast5_cbc_dec, nblocks, blocksize,
807            context_size);
808 }
809
810
811 /* Run the self-tests for CAST5-CFB, tests bulk CBC decryption.
812    Returns NULL on success. */
813 static const char *
814 selftest_cfb (void)
815 {
816   const int nblocks = 4+2;
817   const int blocksize = CAST5_BLOCKSIZE;
818   const int context_size = sizeof(CAST5_context);
819
820   return _gcry_selftest_helper_cfb("CAST5", &cast_setkey,
821            &encrypt_block, &_gcry_cast5_cfb_dec, nblocks, blocksize,
822            context_size);
823 }
824
825
826 static const char*
827 selftest(void)
828 {
829     CAST5_context c;
830     byte key[16]  = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
831                       0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A  };
832     byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
833     byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 };
834     byte buffer[8];
835     const char *r;
836
837     cast_setkey( &c, key, 16 );
838     encrypt_block( &c, buffer, plain );
839     if( memcmp( buffer, cipher, 8 ) )
840         return "1";
841     decrypt_block( &c, buffer, buffer );
842     if( memcmp( buffer, plain, 8 ) )
843         return "2";
844
845 #if 0 /* full maintenance test */
846     {
847         int i;
848         byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
849                         0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
850         byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
851                         0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
852         byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6,
853                         0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 };
854         byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71,
855                         0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E };
856
857         for(i=0; i < 1000000; i++ ) {
858             cast_setkey( &c, b0, 16 );
859             encrypt_block( &c, a0, a0 );
860             encrypt_block( &c, a0+8, a0+8 );
861             cast_setkey( &c, a0, 16 );
862             encrypt_block( &c, b0, b0 );
863             encrypt_block( &c, b0+8, b0+8 );
864         }
865         if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) )
866             return "3";
867
868     }
869 #endif
870
871     if ( (r = selftest_cbc ()) )
872       return r;
873
874     if ( (r = selftest_cfb ()) )
875       return r;
876
877     if ( (r = selftest_ctr ()) )
878       return r;
879
880     return NULL;
881 }
882
883
884 static void
885 key_schedule( u32 *x, u32 *z, u32 *k )
886 {
887
888 #define xi(i)   ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
889 #define zi(i)   ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
890
891     z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
892     z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
893     z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
894     z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
895     k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)];
896     k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)];
897     k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)];
898     k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)];
899
900     x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
901     x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
902     x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
903     x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
904     k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)];
905     k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)];
906     k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)];
907     k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)];
908
909     z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
910     z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
911     z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
912     z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
913     k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)];
914     k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)];
915     k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)];
916     k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)];
917
918     x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
919     x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
920     x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
921     x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
922     k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)];
923     k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)];
924     k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)];
925     k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)];
926
927 #undef xi
928 #undef zi
929 }
930
931
932 static gcry_err_code_t
933 do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen )
934 {
935   static int initialized;
936   static const char* selftest_failed;
937   int i;
938   u32 x[4];
939   u32 z[4];
940   u32 k[16];
941
942   if( !initialized )
943     {
944       initialized = 1;
945       selftest_failed = selftest();
946       if( selftest_failed )
947         log_error ("CAST5 selftest failed (%s).\n", selftest_failed );
948     }
949   if( selftest_failed )
950     return GPG_ERR_SELFTEST_FAILED;
951
952   if( keylen != 16 )
953     return GPG_ERR_INV_KEYLEN;
954
955   x[0] = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];
956   x[1] = key[4]  << 24 | key[5]  << 16 | key[6]  << 8 | key[7];
957   x[2] = key[8]  << 24 | key[9]  << 16 | key[10] << 8 | key[11];
958   x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15];
959
960   key_schedule( x, z, k );
961   for(i=0; i < 16; i++ )
962     c->Km[i] = k[i];
963   key_schedule( x, z, k );
964   for(i=0; i < 16; i++ )
965     c->Kr[i] = k[i] & 0x1f;
966
967 #ifdef USE_ARMV6_ASM
968   for (i = 0; i < 4; i++)
969     {
970       byte Kr_arm[4];
971
972       /* Convert rotate left to rotate right and add shift left
973        * by 2.  */
974       Kr_arm[0] = ((32 - c->Kr[4 * i + 0]) - 2) & 0x1f;
975       Kr_arm[1] = ((32 - c->Kr[4 * i + 1]) - 2) & 0x1f;
976       Kr_arm[2] = ((32 - c->Kr[4 * i + 2]) - 2) & 0x1f;
977       Kr_arm[3] = ((32 - c->Kr[4 * i + 3]) - 2) & 0x1f;
978
979       /* Endian friendly store.  */
980       c->Kr_arm_enc[i] = Kr_arm[0] |
981                         (Kr_arm[1] << 8) |
982                         (Kr_arm[2] << 16) |
983                         (Kr_arm[3] << 24);
984       c->Kr_arm_dec[i] = Kr_arm[3] |
985                         (Kr_arm[2] << 8) |
986                         (Kr_arm[1] << 16) |
987                         (Kr_arm[0] << 24);
988
989       wipememory(Kr_arm, sizeof(Kr_arm));
990     }
991 #endif
992
993   memset(&x,0, sizeof x);
994   memset(&z,0, sizeof z);
995   memset(&k,0, sizeof k);
996
997 #undef xi
998 #undef zi
999   return GPG_ERR_NO_ERROR;
1000 }
1001
1002 static gcry_err_code_t
1003 cast_setkey (void *context, const byte *key, unsigned keylen )
1004 {
1005   CAST5_context *c = (CAST5_context *) context;
1006   gcry_err_code_t rc = do_cast_setkey (c, key, keylen);
1007   _gcry_burn_stack (96+7*sizeof(void*));
1008   return rc;
1009 }
1010
1011
1012 gcry_cipher_spec_t _gcry_cipher_spec_cast5 =
1013   {
1014     "CAST5", NULL, NULL, CAST5_BLOCKSIZE, 128, sizeof (CAST5_context),
1015     cast_setkey, encrypt_block, decrypt_block
1016   };