1/*
2 * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * The above Sun copyright is included due to changes made to this code
8 * for US export control.  No changes to the algorithm implementations have
9 * been made.
10 */
11
12/* $OpenBSD: blowfish.c,v 1.16 2002/02/19 19:39:36 millert Exp $ */
13/*
14 * Blowfish block cipher for OpenBSD
15 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
16 * All rights reserved.
17 *
18 * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 * 3. All advertising materials mentioning features or use of this software
29 *    must display the following acknowledgement:
30 *      This product includes software developed by Niels Provos.
31 * 4. The name of the author may not be used to endorse or promote products
32 *    derived from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45
46/*
47 * This code is derived from section 14.3 and the given source
48 * in section V of Applied Cryptography, second edition.
49 * Blowfish is an unpatented fast block cipher designed by
50 * Bruce Schneier.
51 */
52
53#if 0
54#include <stdio.h>		/* used for debugging */
55#include <string.h>
56#endif
57
58#include <sys/types.h>
59#include <blf.h>
60
61#undef inline
62#ifdef __GNUC__
63#define inline __inline
64#else				/* !__GNUC__ */
65#define inline
66#endif				/* !__GNUC__ */
67
68/* Function for Feistel Networks */
69
70#define F(s, x) ((((s)[        (((x)>>24)&0xFF)]  \
71		 + (s)[0x100 + (((x)>>16)&0xFF)]) \
72		 ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
73		 + (s)[0x300 + ( (x)     &0xFF)])
74
75#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
76
77void
78Blowfish_encipher(c, xl, xr)
79	blf_ctx *c;
80	uint32_t *xl;
81	uint32_t *xr;
82{
83	uint32_t Xl;
84	uint32_t Xr;
85	uint32_t *s = c->S[0];
86	uint32_t *p = c->P;
87
88	Xl = *xl;
89	Xr = *xr;
90
91	Xl ^= p[0];
92	BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
93	BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
94	BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
95	BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
96	BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
97	BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
98	BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
99	BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
100
101	*xl = Xr ^ p[17];
102	*xr = Xl;
103}
104
105void
106Blowfish_decipher(c, xl, xr)
107	blf_ctx *c;
108	uint32_t *xl;
109	uint32_t *xr;
110{
111	uint32_t Xl;
112	uint32_t Xr;
113	uint32_t *s = c->S[0];
114	uint32_t *p = c->P;
115
116	Xl = *xl;
117	Xr = *xr;
118
119	Xl ^= p[17];
120	BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
121	BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
122	BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
123	BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
124	BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
125	BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
126	BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
127	BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
128
129	*xl = Xr ^ p[0];
130	*xr = Xl;
131}
132
133void
134Blowfish_initstate(c)
135	blf_ctx *c;
136{
137/* P-box and S-box tables initialized with digits of Pi */
138
139	const blf_ctx initstate =
140
141	{ {
142		{
143			0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
144			0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
145			0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
146			0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
147			0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
148			0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
149			0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
150			0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
151			0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
152			0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
153			0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
154			0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
155			0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
156			0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
157			0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
158			0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
159			0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
160			0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
161			0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
162			0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
163			0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
164			0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
165			0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
166			0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
167			0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
168			0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
169			0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
170			0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
171			0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
172			0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
173			0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
174			0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
175			0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
176			0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
177			0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
178			0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
179			0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
180			0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
181			0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
182			0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
183			0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
184			0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
185			0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
186			0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
187			0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
188			0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
189			0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
190			0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
191			0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
192			0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
193			0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
194			0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
195			0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
196			0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
197			0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
198			0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
199			0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
200			0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
201			0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
202			0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
203			0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
204			0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
205			0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
206		0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
207		{
208			0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
209			0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
210			0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
211			0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
212			0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
213			0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
214			0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
215			0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
216			0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
217			0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
218			0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
219			0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
220			0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
221			0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
222			0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
223			0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
224			0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
225			0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
226			0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
227			0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
228			0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
229			0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
230			0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
231			0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
232			0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
233			0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
234			0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
235			0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
236			0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
237			0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
238			0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
239			0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
240			0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
241			0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
242			0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
243			0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
244			0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
245			0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
246			0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
247			0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
248			0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
249			0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
250			0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
251			0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
252			0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
253			0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
254			0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
255			0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
256			0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
257			0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
258			0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
259			0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
260			0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
261			0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
262			0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
263			0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
264			0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
265			0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
266			0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
267			0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
268			0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
269			0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
270			0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
271		0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
272		{
273			0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
274			0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
275			0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
276			0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
277			0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
278			0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
279			0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
280			0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
281			0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
282			0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
283			0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
284			0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
285			0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
286			0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
287			0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
288			0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
289			0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
290			0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
291			0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
292			0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
293			0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
294			0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
295			0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
296			0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
297			0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
298			0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
299			0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
300			0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
301			0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
302			0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
303			0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
304			0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
305			0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
306			0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
307			0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
308			0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
309			0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
310			0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
311			0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
312			0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
313			0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
314			0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
315			0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
316			0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
317			0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
318			0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
319			0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
320			0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
321			0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
322			0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
323			0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
324			0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
325			0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
326			0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
327			0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
328			0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
329			0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
330			0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
331			0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
332			0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
333			0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
334			0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
335			0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
336		0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
337		{
338			0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
339			0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
340			0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
341			0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
342			0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
343			0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
344			0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
345			0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
346			0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
347			0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
348			0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
349			0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
350			0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
351			0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
352			0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
353			0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
354			0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
355			0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
356			0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
357			0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
358			0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
359			0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
360			0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
361			0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
362			0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
363			0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
364			0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
365			0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
366			0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
367			0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
368			0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
369			0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
370			0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
371			0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
372			0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
373			0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
374			0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
375			0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
376			0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
377			0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
378			0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
379			0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
380			0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
381			0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
382			0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
383			0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
384			0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
385			0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
386			0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
387			0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
388			0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
389			0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
390			0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
391			0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
392			0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
393			0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
394			0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
395			0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
396			0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
397			0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
398			0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
399			0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
400			0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
401		0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
402	},
403	{
404		0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
405		0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
406		0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
407		0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
408		0x9216d5d9, 0x8979fb1b
409	} };
410
411	*c = initstate;
412}
413
414uint32_t
415Blowfish_stream2word(const uint8_t *data, uint16_t databytes, uint16_t *current)
416{
417	uint8_t i;
418	uint16_t j;
419	uint32_t temp;
420
421	temp = 0x00000000;
422	j = *current;
423
424	for (i = 0; i < 4; i++, j++) {
425		if (j >= databytes)
426			j = 0;
427		temp = (temp << 8) | data[j];
428	}
429
430	*current = j;
431	return temp;
432}
433
434void
435Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes)
436{
437	uint16_t i;
438	uint16_t j;
439	uint16_t k;
440	uint32_t temp;
441	uint32_t datal;
442	uint32_t datar;
443
444	j = 0;
445	for (i = 0; i < BLF_N + 2; i++) {
446		/* Extract 4 int8 to 1 int32 from keystream */
447		temp = Blowfish_stream2word(key, keybytes, &j);
448		c->P[i] = c->P[i] ^ temp;
449	}
450
451	j = 0;
452	datal = 0x00000000;
453	datar = 0x00000000;
454	for (i = 0; i < BLF_N + 2; i += 2) {
455		Blowfish_encipher(c, &datal, &datar);
456
457		c->P[i] = datal;
458		c->P[i + 1] = datar;
459	}
460
461	for (i = 0; i < 4; i++) {
462		for (k = 0; k < 256; k += 2) {
463			Blowfish_encipher(c, &datal, &datar);
464
465			c->S[i][k] = datal;
466			c->S[i][k + 1] = datar;
467		}
468	}
469}
470
471
472void
473Blowfish_expandstate(blf_ctx *c, const uint8_t *data, uint16_t databytes,
474		     const uint8_t *key, uint16_t keybytes)
475{
476	uint16_t i;
477	uint16_t j;
478	uint16_t k;
479	uint32_t temp;
480	uint32_t datal;
481	uint32_t datar;
482
483	j = 0;
484	for (i = 0; i < BLF_N + 2; i++) {
485		/* Extract 4 int8 to 1 int32 from keystream */
486		temp = Blowfish_stream2word(key, keybytes, &j);
487		c->P[i] = c->P[i] ^ temp;
488	}
489
490	j = 0;
491	datal = 0x00000000;
492	datar = 0x00000000;
493	for (i = 0; i < BLF_N + 2; i += 2) {
494		datal ^= Blowfish_stream2word(data, databytes, &j);
495		datar ^= Blowfish_stream2word(data, databytes, &j);
496		Blowfish_encipher(c, &datal, &datar);
497
498		c->P[i] = datal;
499		c->P[i + 1] = datar;
500	}
501
502	for (i = 0; i < 4; i++) {
503		for (k = 0; k < 256; k += 2) {
504			datal ^= Blowfish_stream2word(data, databytes, &j);
505			datar ^= Blowfish_stream2word(data, databytes, &j);
506			Blowfish_encipher(c, &datal, &datar);
507
508			c->S[i][k] = datal;
509			c->S[i][k + 1] = datar;
510		}
511	}
512}
513
514void
515blf_key(blf_ctx *c, const uint8_t *k, uint16_t len)
516{
517	/* Initialize S-boxes and subkeys with Pi */
518	Blowfish_initstate(c);
519
520	/* Transform S-boxes and subkeys with key */
521	Blowfish_expand0state(c, k, len);
522}
523
524void
525blf_enc(blf_ctx *c, uint32_t *data, uint16_t blocks)
526{
527	uint32_t *d;
528	uint16_t i;
529
530	d = data;
531	for (i = 0; i < blocks; i++) {
532		Blowfish_encipher(c, d, d + 1);
533		d += 2;
534	}
535}
536
537void
538blf_dec(blf_ctx *c, uint32_t *data, uint16_t blocks)
539{
540	uint32_t *d;
541	uint16_t i;
542
543	d = data;
544	for (i = 0; i < blocks; i++) {
545		Blowfish_decipher(c, d, d + 1);
546		d += 2;
547	}
548}
549
550void
551blf_ecb_encrypt(blf_ctx *c, uint8_t *data, uint32_t len)
552{
553	uint32_t l, r;
554	uint32_t i;
555
556	for (i = 0; i < len; i += 8) {
557		l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
558		r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
559		Blowfish_encipher(c, &l, &r);
560		data[0] = l >> 24 & 0xff;
561		data[1] = l >> 16 & 0xff;
562		data[2] = l >> 8 & 0xff;
563		data[3] = l & 0xff;
564		data[4] = r >> 24 & 0xff;
565		data[5] = r >> 16 & 0xff;
566		data[6] = r >> 8 & 0xff;
567		data[7] = r & 0xff;
568		data += 8;
569	}
570}
571
572void
573blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len)
574{
575	uint32_t l, r;
576	uint32_t i;
577
578	for (i = 0; i < len; i += 8) {
579		l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
580		r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
581		Blowfish_decipher(c, &l, &r);
582		data[0] = l >> 24 & 0xff;
583		data[1] = l >> 16 & 0xff;
584		data[2] = l >> 8 & 0xff;
585		data[3] = l & 0xff;
586		data[4] = r >> 24 & 0xff;
587		data[5] = r >> 16 & 0xff;
588		data[6] = r >> 8 & 0xff;
589		data[7] = r & 0xff;
590		data += 8;
591	}
592}
593
594void
595blf_cbc_encrypt(blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len)
596{
597	uint32_t l, r;
598	uint32_t i, j;
599
600	for (i = 0; i < len; i += 8) {
601		for (j = 0; j < 8; j++)
602			data[j] ^= iv[j];
603		l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
604		r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
605		Blowfish_encipher(c, &l, &r);
606		data[0] = l >> 24 & 0xff;
607		data[1] = l >> 16 & 0xff;
608		data[2] = l >> 8 & 0xff;
609		data[3] = l & 0xff;
610		data[4] = r >> 24 & 0xff;
611		data[5] = r >> 16 & 0xff;
612		data[6] = r >> 8 & 0xff;
613		data[7] = r & 0xff;
614		iv = data;
615		data += 8;
616	}
617}
618
619void
620blf_cbc_decrypt(blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len)
621{
622	uint32_t l, r;
623	uint8_t *iv;
624	uint32_t i, j;
625
626	iv = data + len - 16;
627	data = data + len - 8;
628	for (i = len - 8; i >= 8; i -= 8) {
629		l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
630		r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
631		Blowfish_decipher(c, &l, &r);
632		data[0] = l >> 24 & 0xff;
633		data[1] = l >> 16 & 0xff;
634		data[2] = l >> 8 & 0xff;
635		data[3] = l & 0xff;
636		data[4] = r >> 24 & 0xff;
637		data[5] = r >> 16 & 0xff;
638		data[6] = r >> 8 & 0xff;
639		data[7] = r & 0xff;
640		for (j = 0; j < 8; j++)
641			data[j] ^= iv[j];
642		iv -= 8;
643		data -= 8;
644	}
645	l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
646	r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
647	Blowfish_decipher(c, &l, &r);
648	data[0] = l >> 24 & 0xff;
649	data[1] = l >> 16 & 0xff;
650	data[2] = l >> 8 & 0xff;
651	data[3] = l & 0xff;
652	data[4] = r >> 24 & 0xff;
653	data[5] = r >> 16 & 0xff;
654	data[6] = r >> 8 & 0xff;
655	data[7] = r & 0xff;
656	for (j = 0; j < 8; j++)
657		data[j] ^= iva[j];
658}
659
660#if 0
661void
662report(uint32_t data[], uint16_t len)
663{
664	uint16_t i;
665	for (i = 0; i < len; i += 2)
666		printf("Block %0hd: %08lx %08lx.\n",
667		    i / 2, data[i], data[i + 1]);
668}
669void
670main(void)
671{
672
673	blf_ctx c;
674	char    key[] = "AAAAA";
675	char    key2[] = "abcdefghijklmnopqrstuvwxyz";
676
677	uint32_t data[10];
678	uint32_t data2[] =
679	{0x424c4f57l, 0x46495348l};
680
681	uint16_t i;
682
683	/* First test */
684	for (i = 0; i < 10; i++)
685		data[i] = i;
686
687	blf_key(&c, (uint8_t *) key, 5);
688	blf_enc(&c, data, 5);
689	blf_dec(&c, data, 1);
690	blf_dec(&c, data + 2, 4);
691	printf("Should read as 0 - 9.\n");
692	report(data, 10);
693
694	/* Second test */
695	blf_key(&c, (uint8_t *) key2, strlen(key2));
696	blf_enc(&c, data2, 1);
697	printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
698	report(data2, 2);
699	blf_dec(&c, data2, 1);
700	report(data2, 2);
701}
702#endif
703