1160814Ssimon/*	$FreeBSD$	*/
2160814Ssimon/*	$KAME: des_locl.h,v 1.7 2001/09/10 04:03:58 itojun Exp $	*/
3160814Ssimon
4160814Ssimon/* crypto/des/des_locl.h */
5160814Ssimon/* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)
6160814Ssimon * All rights reserved.
7160814Ssimon *
8160814Ssimon * This file is part of an SSL implementation written
9160814Ssimon * by Eric Young (eay@mincom.oz.au).
10160814Ssimon * The implementation was written so as to conform with Netscapes SSL
11160814Ssimon * specification.  This library and applications are
12160814Ssimon * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
13280304Sjkim * as long as the following conditions are aheared to.
14160814Ssimon *
15160814Ssimon * Copyright remains Eric Young's, and as such any Copyright notices in
16160814Ssimon * the code are not to be removed.  If this code is used in a product,
17160814Ssimon * Eric Young should be given attribution as the author of the parts used.
18160814Ssimon * This can be in the form of a textual message at program startup or
19160814Ssimon * in documentation (online or textual) provided with the package.
20160814Ssimon *
21160814Ssimon * Redistribution and use in source and binary forms, with or without
22160814Ssimon * modification, are permitted provided that the following conditions
23160814Ssimon * are met:
24160814Ssimon * 1. Redistributions of source code must retain the copyright
25160814Ssimon *    notice, this list of conditions and the following disclaimer.
26160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
27160814Ssimon *    notice, this list of conditions and the following disclaimer in the
28160814Ssimon *    documentation and/or other materials provided with the distribution.
29160814Ssimon * 3. All advertising materials mentioning features or use of this software
30160814Ssimon *    must display the following acknowledgement:
31160814Ssimon *    This product includes software developed by Eric Young (eay@mincom.oz.au)
32160814Ssimon *
33160814Ssimon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
34160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36160814Ssimon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
37160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43160814Ssimon * SUCH DAMAGE.
44160814Ssimon *
45160814Ssimon * The licence and distribution terms for any publically available version or
46160814Ssimon * derivative of this code cannot be changed.  i.e. this code cannot simply be
47160814Ssimon * copied and put under another distribution licence
48160814Ssimon * [including the GNU Public Licence.]
49160814Ssimon */
50160814Ssimon
51160814Ssimon#ifndef HEADER_DES_LOCL_H
52160814Ssimon#define HEADER_DES_LOCL_H
53160814Ssimon
54160814Ssimon#include <crypto/des/des.h>
55160814Ssimon
56160814Ssimon#undef DES_PTR
57160814Ssimon
58160814Ssimon#ifdef __STDC__
59160814Ssimon#undef NOPROTO
60160814Ssimon#endif
61160814Ssimon
62280304Sjkim#define ITERATIONS 16
63280304Sjkim#define HALF_ITERATIONS 8
64280304Sjkim
65280304Sjkim/* used in des_read and des_write */
66280304Sjkim#define MAXWRITE	(1024*16)
67194206Ssimon#define BSIZE		(MAXWRITE+4)
68194206Ssimon
69160814Ssimon#define c2l(c,l)	(l =((DES_LONG)(*((c)++)))    , \
70194206Ssimon			 l|=((DES_LONG)(*((c)++)))<< 8L, \
71280304Sjkim			 l|=((DES_LONG)(*((c)++)))<<16L, \
72280304Sjkim			 l|=((DES_LONG)(*((c)++)))<<24L)
73280304Sjkim
74280304Sjkim/* NOTE - c is not incremented as per c2l */
75280304Sjkim#define c2ln(c,l1,l2,n)	{ \
76194206Ssimon			c+=n; \
77280304Sjkim			l1=l2=0; \
78280304Sjkim			switch (n) { \
79280304Sjkim			case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \
80280304Sjkim			case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \
81194206Ssimon			case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \
82280304Sjkim			case 5: l2|=((DES_LONG)(*(--(c))));     \
83280304Sjkim			case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \
84280304Sjkim			case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \
85280304Sjkim			case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \
86280304Sjkim			case 1: l1|=((DES_LONG)(*(--(c))));     \
87280304Sjkim				} \
88280304Sjkim			}
89194206Ssimon
90280304Sjkim#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
91280304Sjkim			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
92280304Sjkim			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
93280304Sjkim			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
94280304Sjkim
95280304Sjkim/* replacements for htonl and ntohl since I have no idea what to do
96194206Ssimon * when faced with machines with 8 byte longs. */
97280304Sjkim#define HDRSIZE 4
98280304Sjkim
99280304Sjkim#define n2l(c,l)	(l =((DES_LONG)(*((c)++)))<<24L, \
100280304Sjkim			 l|=((DES_LONG)(*((c)++)))<<16L, \
101280304Sjkim			 l|=((DES_LONG)(*((c)++)))<< 8L, \
102280304Sjkim			 l|=((DES_LONG)(*((c)++))))
103280304Sjkim
104280304Sjkim#define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
105280304Sjkim			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
106280304Sjkim			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
107280304Sjkim			 *((c)++)=(unsigned char)(((l)     )&0xff))
108280304Sjkim
109194206Ssimon/* NOTE - c is not incremented as per l2c */
110280304Sjkim#define l2cn(l1,l2,c,n)	{ \
111280304Sjkim			c+=n; \
112280304Sjkim			switch (n) { \
113280304Sjkim			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
114280304Sjkim			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
115280304Sjkim			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
116194206Ssimon			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
117280304Sjkim			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
118280304Sjkim			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
119280304Sjkim			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
120280304Sjkim			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
121280304Sjkim				} \
122280304Sjkim			}
123280304Sjkim
124280304Sjkim#define	ROTATE(a,n)	(((a)>>(n))+((a)<<(32-(n))))
125280304Sjkim
126280304Sjkim#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g)
127280304Sjkim#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \
128280304Sjkim	u=R^s[S  ]; \
129194206Ssimon	t=R^s[S+1]
130280304Sjkim
131280304Sjkim/* The changes to this macro may help or hinder, depending on the
132280304Sjkim * compiler and the achitecture.  gcc2 always seems to do well :-).
133280304Sjkim * Inspired by Dana How <how@isl.stanford.edu>
134280304Sjkim * DO NOT use the alternative version on machines with 8 byte longs.
135280304Sjkim * It does not seem to work on the Alpha, even when DES_LONG is 4
136160814Ssimon * bytes, probably an issue of accessing non-word aligned objects :-( */
137280304Sjkim#ifdef DES_PTR
138280304Sjkim
139280304Sjkim/* It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there
140280304Sjkim * is no reason to not xor all the sub items together.  This potentially
141280304Sjkim * saves a register since things can be xored directly into L */
142280304Sjkim
143280304Sjkim#if defined(DES_RISC1) || defined(DES_RISC2)
144194206Ssimon#ifdef DES_RISC1
145280304Sjkim#define D_ENCRYPT(LL,R,S) { \
146280304Sjkim        unsigned int u1,u2,u3; \
147280304Sjkim        LOAD_DATA(R,S,u,t,E0,E1,u1); \
148280304Sjkim        u2=(int)u>>8L; \
149280304Sjkim        u1=(int)u&0xfc; \
150280304Sjkim        u2&=0xfc; \
151280304Sjkim        t=ROTATE(t,4); \
152160814Ssimon        u>>=16L; \
153194206Ssimon        LL^= *(const DES_LONG *)(des_SP      +u1); \
154280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x200+u2); \
155280304Sjkim        u3=(int)(u>>8L); \
156280304Sjkim        u1=(int)u&0xfc; \
157280304Sjkim        u3&=0xfc; \
158280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x400+u1); \
159194206Ssimon        LL^= *(const DES_LONG *)(des_SP+0x600+u3); \
160280304Sjkim        u2=(int)t>>8L; \
161280304Sjkim        u1=(int)t&0xfc; \
162280304Sjkim        u2&=0xfc; \
163280304Sjkim        t>>=16L; \
164194206Ssimon        LL^= *(const DES_LONG *)(des_SP+0x100+u1); \
165280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x300+u2); \
166280304Sjkim        u3=(int)t>>8L; \
167280304Sjkim        u1=(int)t&0xfc; \
168280304Sjkim        u3&=0xfc; \
169280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x500+u1); \
170280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x700+u3); }
171194206Ssimon#endif /* DES_RISC1 */
172280304Sjkim#ifdef DES_RISC2
173280304Sjkim#define D_ENCRYPT(LL,R,S) { \
174280304Sjkim        unsigned int u1,u2,s1,s2; \
175280304Sjkim        LOAD_DATA(R,S,u,t,E0,E1,u1); \
176280304Sjkim        u2=(int)u>>8L; \
177280304Sjkim        u1=(int)u&0xfc; \
178194206Ssimon        u2&=0xfc; \
179280304Sjkim        t=ROTATE(t,4); \
180280304Sjkim        LL^= *(const DES_LONG *)(des_SP      +u1); \
181280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x200+u2); \
182280304Sjkim        s1=(int)(u>>16L); \
183280304Sjkim        s2=(int)(u>>24L); \
184280304Sjkim        s1&=0xfc; \
185280304Sjkim        s2&=0xfc; \
186280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x400+s1); \
187280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x600+s2); \
188280304Sjkim        u2=(int)t>>8L; \
189280304Sjkim        u1=(int)t&0xfc; \
190280304Sjkim        u2&=0xfc; \
191194206Ssimon        LL^= *(const DES_LONG *)(des_SP+0x100+u1); \
192280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x300+u2); \
193280304Sjkim        s1=(int)(t>>16L); \
194280304Sjkim        s2=(int)(t>>24L); \
195280304Sjkim        s1&=0xfc; \
196280304Sjkim        s2&=0xfc; \
197280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x400+s1); \
198194206Ssimon        LL^= *(const DES_LONG *)(des_SP+0x600+s2); \
199280304Sjkim        u2=(int)t>>8L; \
200280304Sjkim        u1=(int)t&0xfc; \
201280304Sjkim        u2&=0xfc; \
202280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x100+u1); \
203280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x300+u2); \
204280304Sjkim        s1=(int)(t>>16L); \
205280304Sjkim        s2=(int)(t>>24L); \
206280304Sjkim        s1&=0xfc; \
207280304Sjkim        s2&=0xfc; \
208280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x500+s1); \
209280304Sjkim        LL^= *(const DES_LONG *)(des_SP+0x700+s2); }
210280304Sjkim#endif /* DES_RISC2 */
211194206Ssimon#else  /* DES_RISC1 || DES_RISC2 */
212280304Sjkim#define D_ENCRYPT(LL,R,S) { \
213280304Sjkim	LOAD_DATA_tmp(R,S,u,t,E0,E1); \
214280304Sjkim	t=ROTATE(t,4); \
215280304Sjkim	LL^= \
216280304Sjkim	*(const DES_LONG *)(des_SP      +((u     )&0xfc))^ \
217280304Sjkim	*(const DES_LONG *)(des_SP+0x200+((u>> 8L)&0xfc))^ \
218280304Sjkim	*(const DES_LONG *)(des_SP+0x400+((u>>16L)&0xfc))^ \
219280304Sjkim	*(const DES_LONG *)(des_SP+0x600+((u>>24L)&0xfc))^ \
220280304Sjkim	*(const DES_LONG *)(des_SP+0x100+((t     )&0xfc))^ \
221280304Sjkim	*(const DES_LONG *)(des_SP+0x300+((t>> 8L)&0xfc))^ \
222280304Sjkim	*(const DES_LONG *)(des_SP+0x500+((t>>16L)&0xfc))^ \
223280304Sjkim	*(const DES_LONG *)(des_SP+0x700+((t>>24L)&0xfc)); }
224194206Ssimon#endif /* DES_RISC1 || DES_RISC2 */
225280304Sjkim#else /* original version */
226280304Sjkim
227280304Sjkim#if defined(DES_RISC1) || defined(DES_RISC2)
228280304Sjkim#ifdef DES_RISC1
229280304Sjkim#define D_ENCRYPT(LL,R,S) {\
230280304Sjkim	unsigned int u1,u2,u3; \
231280304Sjkim	LOAD_DATA(R,S,u,t,E0,E1,u1); \
232194206Ssimon	u>>=2L; \
233280304Sjkim	t=ROTATE(t,6); \
234160814Ssimon	u2=(int)u>>8L; \
235160814Ssimon	u1=(int)u&0x3f; \
236280304Sjkim	u2&=0x3f; \
237280304Sjkim	u>>=16L; \
238280304Sjkim	LL^=des_SPtrans[0][u1]; \
239280304Sjkim	LL^=des_SPtrans[2][u2]; \
240280304Sjkim	u3=(int)u>>8L; \
241280304Sjkim	u1=(int)u&0x3f; \
242280304Sjkim	u3&=0x3f; \
243194206Ssimon	LL^=des_SPtrans[4][u1]; \
244280304Sjkim	LL^=des_SPtrans[6][u3]; \
245280304Sjkim	u2=(int)t>>8L; \
246280304Sjkim	u1=(int)t&0x3f; \
247280304Sjkim	u2&=0x3f; \
248280304Sjkim	t>>=16L; \
249280304Sjkim	LL^=des_SPtrans[1][u1]; \
250280304Sjkim	LL^=des_SPtrans[3][u2]; \
251194206Ssimon	u3=(int)t>>8L; \
252280304Sjkim	u1=(int)t&0x3f; \
253280304Sjkim	u3&=0x3f; \
254280304Sjkim	LL^=des_SPtrans[5][u1]; \
255280304Sjkim	LL^=des_SPtrans[7][u3]; }
256280304Sjkim#endif /* DES_RISC1 */
257280304Sjkim#ifdef DES_RISC2
258280304Sjkim#define D_ENCRYPT(LL,R,S) {\
259194206Ssimon	unsigned int u1,u2,s1,s2; \
260280304Sjkim	LOAD_DATA(R,S,u,t,E0,E1,u1); \
261280304Sjkim	u>>=2L; \
262280304Sjkim	t=ROTATE(t,6); \
263280304Sjkim	u2=(int)u>>8L; \
264280304Sjkim	u1=(int)u&0x3f; \
265280304Sjkim	u2&=0x3f; \
266280304Sjkim	LL^=des_SPtrans[0][u1]; \
267194206Ssimon	LL^=des_SPtrans[2][u2]; \
268280304Sjkim	s1=(int)u>>16L; \
269280304Sjkim	s2=(int)u>>24L; \
270280304Sjkim	s1&=0x3f; \
271280304Sjkim	s2&=0x3f; \
272280304Sjkim	LL^=des_SPtrans[4][s1]; \
273280304Sjkim	LL^=des_SPtrans[6][s2]; \
274280304Sjkim	u2=(int)t>>8L; \
275194206Ssimon	u1=(int)t&0x3f; \
276160814Ssimon	u2&=0x3f; \
277280304Sjkim	LL^=des_SPtrans[1][u1]; \
278280304Sjkim	LL^=des_SPtrans[3][u2]; \
279280304Sjkim	s1=(int)t>>16; \
280160814Ssimon	s2=(int)t>>24L; \
281160814Ssimon	s1&=0x3f; \
282280304Sjkim	s2&=0x3f; \
283280304Sjkim	LL^=des_SPtrans[5][s1]; \
284280304Sjkim	LL^=des_SPtrans[7][s2]; }
285160814Ssimon#endif /* DES_RISC2 */
286160814Ssimon
287280304Sjkim#else /* DES_RISC1 || DES_RISC2 */
288280304Sjkim
289280304Sjkim#define D_ENCRYPT(LL,R,S) {\
290160814Ssimon	LOAD_DATA_tmp(R,S,u,t,E0,E1); \
291160814Ssimon	t=ROTATE(t,4); \
292280304Sjkim	LL^=\
293280304Sjkim        	des_SPtrans[0][(u>> 2L)&0x3f]^ \
294280304Sjkim        	des_SPtrans[2][(u>>10L)&0x3f]^ \
295160814Ssimon        	des_SPtrans[4][(u>>18L)&0x3f]^ \
296160814Ssimon        	des_SPtrans[6][(u>>26L)&0x3f]^ \
297280304Sjkim        	des_SPtrans[1][(t>> 2L)&0x3f]^ \
298280304Sjkim        	des_SPtrans[3][(t>>10L)&0x3f]^ \
299280304Sjkim        	des_SPtrans[5][(t>>18L)&0x3f]^ \
300160814Ssimon        	des_SPtrans[7][(t>>26L)&0x3f]; }
301264331Sjkim#endif /* DES_RISC1 || DES_RISC2 */
302280304Sjkim#endif /* DES_PTR */
303280304Sjkim
304160814Ssimon	/* IP and FP
305194206Ssimon	 * The problem is more of a geometric problem that random bit fiddling.
306280304Sjkim	 0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
307194206Ssimon	 8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
308280304Sjkim	16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
309280304Sjkim	24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
310280304Sjkim
311280304Sjkim	32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
312280304Sjkim	40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
313194206Ssimon	48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
314264331Sjkim	56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
315280304Sjkim
316280304Sjkim	The output has been subject to swaps of the form
317264331Sjkim	0 1 -> 3 1 but the odd and even bits have been put into
318280304Sjkim	2 3    2 0
319280304Sjkim	different words.  The main trick is to remember that
320280304Sjkim	t=((l>>size)^r)&(mask);
321160814Ssimon	r^=t;
322160814Ssimon	l^=(t<<size);
323280304Sjkim	can be used to swap and move bits between words.
324280304Sjkim
325194206Ssimon	So l =  0  1  2  3  r = 16 17 18 19
326194206Ssimon	        4  5  6  7      20 21 22 23
327194206Ssimon	        8  9 10 11      24 25 26 27
328194206Ssimon	       12 13 14 15      28 29 30 31
329280304Sjkim	becomes (for size == 2 and mask == 0x3333)
330280304Sjkim	   t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19
331280304Sjkim		 6^20  7^21 -- --        4  5 20 21       6  7 22 23
332280304Sjkim		10^24 11^25 -- --        8  9 24 25      10 11 24 25
333238405Sjkim		14^28 15^29 -- --       12 13 28 29      14 15 28 29
334238405Sjkim
335238405Sjkim	Thanks for hints from Richard Outerbridge - he told me IP&FP
336238405Sjkim	could be done in 15 xor, 10 shifts and 5 ands.
337238405Sjkim	When I finally started to think of the problem in 2D
338238405Sjkim	I first got ~42 operations without xors.  When I remembered
339238405Sjkim	how to use xors :-) I got it to its final state.
340160814Ssimon	*/
341280304Sjkim#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
342280304Sjkim	(b)^=(t),\
343280304Sjkim	(a)^=((t)<<(n)))
344280304Sjkim
345280304Sjkim#define IP(l,r) \
346280304Sjkim	{ \
347280304Sjkim	register DES_LONG tt; \
348280304Sjkim	PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \
349280304Sjkim	PERM_OP(l,r,tt,16,0x0000ffffL); \
350280304Sjkim	PERM_OP(r,l,tt, 2,0x33333333L); \
351280304Sjkim	PERM_OP(l,r,tt, 8,0x00ff00ffL); \
352280304Sjkim	PERM_OP(r,l,tt, 1,0x55555555L); \
353238405Sjkim	}
354238405Sjkim
355238405Sjkim#define FP(l,r) \
356238405Sjkim	{ \
357238405Sjkim	register DES_LONG tt; \
358280304Sjkim	PERM_OP(l,r,tt, 1,0x55555555L); \
359160814Ssimon	PERM_OP(r,l,tt, 8,0x00ff00ffL); \
360160814Ssimon	PERM_OP(l,r,tt, 2,0x33333333L); \
361280304Sjkim	PERM_OP(r,l,tt,16,0x0000ffffL); \
362280304Sjkim	PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \
363280304Sjkim	}
364280304Sjkim#endif
365280304Sjkim