Optimize and cleanup 32-bit and 64-bit endianess transforms
[libgcrypt.git] / cipher / seed.c
1 /* SEED for libgcrypt
2  *      Copyright (C) 2006 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  * This implementation was provided for libgcrypt in public domain
22  * by Hye-Shik Chang <perky@FreeBSD.org>, July 2006.
23  */
24 \f
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "types.h"  /* for byte and u32 typedefs */
30 #include "g10lib.h"
31 #include "cipher.h"
32 #include "bufhelp.h"
33
34 #define NUMKC   16
35
36 #define GETU32(pt) buf_get_be32(pt)
37 #define PUTU32(ct, st) buf_put_be32(ct, st)
38
39 union wordbuf
40 {
41   u32 w;
42   byte b[4];
43 };
44
45 #ifdef WORDS_BIGENDIAN
46 #define b0  b[3]
47 #define b1  b[2]
48 #define b2  b[1]
49 #define b3  b[0]
50 #else
51 #define b0  b[0]
52 #define b1  b[1]
53 #define b2  b[2]
54 #define b3  b[3]
55 #endif
56
57 static const char *selftest(void);
58
59 typedef struct
60 {
61   u32 keyschedule[32];
62 } SEED_context;
63
64 static const u32 SS0[256] = {
65     0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c,
66     0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c,
67     0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044,
68     0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
69     0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310,
70     0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8,
71     0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194,
72     0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
73     0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc,
74     0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380,
75     0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050,
76     0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
77     0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210,
78     0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140,
79     0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198,
80     0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
81     0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388,
82     0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c,
83     0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec,
84     0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
85     0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120,
86     0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288,
87     0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344,
88     0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
89     0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114,
90     0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c,
91     0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8,
92     0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
93     0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158,
94     0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364,
95     0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c,
96     0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
97     0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c,
98     0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0,
99     0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc,
100     0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
101     0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328,
102     0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c,
103     0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8,
104     0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
105     0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128,
106     0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178,
107     0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298,
108 };
109
110 static const u32 SS1[256] = {
111     0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2,
112     0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3,
113     0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262,
114     0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
115     0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0,
116     0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0,
117     0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541,
118     0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
119     0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1,
120     0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72,
121     0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0,
122     0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
123     0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20,
124     0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1,
125     0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2,
126     0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
127     0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82,
128     0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202,
129     0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3,
130     0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
131     0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3,
132     0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12,
133     0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73,
134     0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
135     0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22,
136     0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292,
137     0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3,
138     0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
139     0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0,
140     0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040,
141     0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101,
142     0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
143     0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1,
144     0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282,
145     0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450,
146     0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
147     0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2,
148     0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30,
149     0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050,
150     0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
151     0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353,
152     0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83,
153     0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3,
154 };
155
156 static const u32 SS2[256] = {
157     0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d,
158     0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e,
159     0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444,
160     0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
161     0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303,
162     0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888,
163     0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585,
164     0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
165     0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc,
166     0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383,
167     0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040,
168     0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
169     0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202,
170     0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141,
171     0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989,
172     0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
173     0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b,
174     0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d,
175     0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf,
176     0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
177     0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101,
178     0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a,
179     0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747,
180     0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
181     0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505,
182     0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c,
183     0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb,
184     0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
185     0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949,
186     0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747,
187     0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e,
188     0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
189     0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d,
190     0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1,
191     0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc,
192     0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
193     0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b,
194     0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f,
195     0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca,
196     0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
197     0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909,
198     0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949,
199     0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a,
200 };
201
202 static const u32 SS3[256] = {
203     0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e,
204     0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407,
205     0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022,
206     0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
207     0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c,
208     0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828,
209     0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405,
210     0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
211     0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839,
212     0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a,
213     0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414,
214     0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
215     0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c,
216     0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829,
217     0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e,
218     0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
219     0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a,
220     0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002,
221     0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b,
222     0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
223     0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023,
224     0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a,
225     0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b,
226     0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
227     0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e,
228     0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012,
229     0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b,
230     0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
231     0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434,
232     0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000,
233     0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001,
234     0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
235     0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425,
236     0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002,
237     0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414,
238     0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
239     0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a,
240     0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c,
241     0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010,
242     0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
243     0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013,
244     0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f,
245     0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437,
246 };
247
248 static const u32 KC[NUMKC] = {
249     0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc,
250     0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
251     0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1,
252     0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b,
253 };
254 \f
255
256
257 /* Perform the key setup.
258  */
259 static gcry_err_code_t
260 do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen)
261 {
262   static int initialized = 0;
263   static const char *selftest_failed=0;
264   u32 x1, x2, x3, x4;
265   union wordbuf t0, t1;
266   u32 *keyout = ctx->keyschedule;
267   int i;
268
269   if (!initialized)
270     {
271       initialized = 1;
272       selftest_failed = selftest ();
273       if( selftest_failed )
274         log_error ("%s\n", selftest_failed );
275     }
276   if (selftest_failed)
277     return GPG_ERR_SELFTEST_FAILED;
278
279   if (keylen != 16)
280     return GPG_ERR_INV_KEYLEN;
281
282   x1 = GETU32 (key);
283   x2 = GETU32 (key+4);
284   x3 = GETU32 (key+8);
285   x4 = GETU32 (key+12);
286
287   for (i = 0; i < NUMKC; i++)
288     {
289       t0.w = x1 + x3 - KC[i];
290       t1.w = x2 + KC[i] - x4;
291       *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3];
292       *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3];
293
294       if (i % 2 == 0)
295         {
296           t0.w = x1;
297           x1 = (x1>>8) ^ (x2<<24);
298           x2 = (x2>>8) ^ (t0.w<<24);
299         }
300       else
301         {
302           t0.w = x3;
303           x3 = (x3<<8) ^ (x4>>24);
304           x4 = (x4<<8) ^ (t0.w>>24);
305         }
306     }
307
308   return 0;
309 }
310
311 static gcry_err_code_t
312 seed_setkey (void *context, const byte *key, const unsigned keylen)
313 {
314   SEED_context *ctx = context;
315
316   int rc = do_setkey (ctx, key, keylen);
317   _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2);
318   return rc;
319 }
320
321
322 \f
323 #define OP(X1, X2, X3, X4, rbase)                               \
324     t0.w = X3 ^ ctx->keyschedule[rbase];                        \
325     t1.w = X4 ^ ctx->keyschedule[rbase+1];                      \
326     t1.w ^= t0.w;                                               \
327     t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3];   \
328     t0.w += t1.w;                                               \
329     t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3];   \
330     t1.w += t0.w;                                               \
331     t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3];   \
332     t0.w += t1.w;                                               \
333     X1 ^= t0.w;                                                 \
334     X2 ^= t1.w;
335
336 /* Encrypt one block.  inbuf and outbuf may be the same. */
337 static void
338 do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf)
339 {
340   u32 x1, x2, x3, x4;
341   union wordbuf t0, t1;
342
343   x1 = GETU32 (inbuf);
344   x2 = GETU32 (inbuf+4);
345   x3 = GETU32 (inbuf+8);
346   x4 = GETU32 (inbuf+12);
347
348   OP (x1, x2, x3, x4, 0);
349   OP (x3, x4, x1, x2, 2);
350   OP (x1, x2, x3, x4, 4);
351   OP (x3, x4, x1, x2, 6);
352   OP (x1, x2, x3, x4, 8);
353   OP (x3, x4, x1, x2, 10);
354   OP (x1, x2, x3, x4, 12);
355   OP (x3, x4, x1, x2, 14);
356   OP (x1, x2, x3, x4, 16);
357   OP (x3, x4, x1, x2, 18);
358   OP (x1, x2, x3, x4, 20);
359   OP (x3, x4, x1, x2, 22);
360   OP (x1, x2, x3, x4, 24);
361   OP (x3, x4, x1, x2, 26);
362   OP (x1, x2, x3, x4, 28);
363   OP (x3, x4, x1, x2, 30);
364
365   PUTU32 (outbuf, x3);
366   PUTU32 (outbuf+4, x4);
367   PUTU32 (outbuf+8, x1);
368   PUTU32 (outbuf+12, x2);
369 }
370
371 static unsigned int
372 seed_encrypt (void *context, byte *outbuf, const byte *inbuf)
373 {
374   SEED_context *ctx = context;
375
376   do_encrypt (ctx, outbuf, inbuf);
377   return /*burn_stack*/ (4*6);
378 }
379
380
381 \f
382 /* Decrypt one block.  inbuf and outbuf may be the same. */
383 static void
384 do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf)
385 {
386   u32 x1, x2, x3, x4;
387   union wordbuf t0, t1;
388
389   x1 = GETU32 (inbuf);
390   x2 = GETU32 (inbuf+4);
391   x3 = GETU32 (inbuf+8);
392   x4 = GETU32 (inbuf+12);
393
394   OP (x1, x2, x3, x4, 30);
395   OP (x3, x4, x1, x2, 28);
396   OP (x1, x2, x3, x4, 26);
397   OP (x3, x4, x1, x2, 24);
398   OP (x1, x2, x3, x4, 22);
399   OP (x3, x4, x1, x2, 20);
400   OP (x1, x2, x3, x4, 18);
401   OP (x3, x4, x1, x2, 16);
402   OP (x1, x2, x3, x4, 14);
403   OP (x3, x4, x1, x2, 12);
404   OP (x1, x2, x3, x4, 10);
405   OP (x3, x4, x1, x2, 8);
406   OP (x1, x2, x3, x4, 6);
407   OP (x3, x4, x1, x2, 4);
408   OP (x1, x2, x3, x4, 2);
409   OP (x3, x4, x1, x2, 0);
410
411   PUTU32 (outbuf, x3);
412   PUTU32 (outbuf+4, x4);
413   PUTU32 (outbuf+8, x1);
414   PUTU32 (outbuf+12, x2);
415 }
416
417 static unsigned int
418 seed_decrypt (void *context, byte *outbuf, const byte *inbuf)
419 {
420   SEED_context *ctx = context;
421
422   do_decrypt (ctx, outbuf, inbuf);
423   return /*burn_stack*/ (4*6);
424 }
425
426 \f
427 /* Test a single encryption and decryption with each key size. */
428 static const char*
429 selftest (void)
430 {
431   SEED_context ctx;
432   byte scratch[16];
433
434   /* The test vector is taken from the appendix section B.3 of RFC4269.
435    */
436   static const byte plaintext[16] = {
437     0x83, 0xA2, 0xF8, 0xA2, 0x88, 0x64, 0x1F, 0xB9,
438     0xA4, 0xE9, 0xA5, 0xCC, 0x2F, 0x13, 0x1C, 0x7D
439   };
440   static const byte key[16] = {
441     0x47, 0x06, 0x48, 0x08, 0x51, 0xE6, 0x1B, 0xE8,
442     0x5D, 0x74, 0xBF, 0xB3, 0xFD, 0x95, 0x61, 0x85
443   };
444   static const byte ciphertext[16] = {
445     0xEE, 0x54, 0xD1, 0x3E, 0xBC, 0xAE, 0x70, 0x6D,
446     0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A,
447   };
448
449   seed_setkey (&ctx, key, sizeof(key));
450   seed_encrypt (&ctx, scratch, plaintext);
451   if (memcmp (scratch, ciphertext, sizeof (ciphertext)))
452     return "SEED test encryption failed.";
453   seed_decrypt (&ctx, scratch, scratch);
454   if (memcmp (scratch, plaintext, sizeof (plaintext)))
455     return "SEED test decryption failed.";
456
457   return NULL;
458 }
459
460 \f
461
462 static gcry_cipher_oid_spec_t seed_oids[] =
463   {
464     { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB },
465     { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC },
466     { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB },
467     { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB },
468     { NULL }
469   };
470
471 gcry_cipher_spec_t _gcry_cipher_spec_seed =
472   {
473     "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context),
474     seed_setkey, seed_encrypt, seed_decrypt,
475   };