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