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