1/*	$KAME: kame/kame/sys/crypto/des/des_enc.c,v 1.1 2001/09/10 04:03:58 itojun Exp $	*/
2/*	$FreeBSD: src/sys/crypto/des/des_enc.c,v 1.1.2.1 2002/03/26 10:12:24 ume Exp $	*/
3
4/* crypto/des/des_enc.c */
5/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
6 * All rights reserved.
7 *
8 * This package is an SSL implementation written
9 * by Eric Young (eay@cryptsoft.com).
10 * The implementation was written so as to conform with Netscapes SSL.
11 *
12 * This library is free for commercial and non-commercial use as long as
13 * the following conditions are aheared to.  The following conditions
14 * apply to all code found in this distribution, be it the RC4, RSA,
15 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
16 * included with this distribution is covered by the same copyright terms
17 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
18 *
19 * Copyright remains Eric Young's, and as such any Copyright notices in
20 * the code are not to be removed.
21 * If this package is used in a product, Eric Young should be given attribution
22 * as the author of the parts of the library used.
23 * This can be in the form of a textual message at program startup or
24 * in documentation (online or textual) provided with the package.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the copyright
30 *    notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 *    notice, this list of conditions and the following disclaimer in the
33 *    documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 *    must display the following acknowledgement:
36 *    "This product includes cryptographic software written by
37 *     Eric Young (eay@cryptsoft.com)"
38 *    The word 'cryptographic' can be left out if the rouines from the library
39 *    being used are not cryptographic related :-).
40 * 4. If you include any Windows specific code (or a derivative thereof) from
41 *    the apps directory (application code) you must include an acknowledgement:
42 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
43 *
44 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 * The licence and distribution terms for any publically available version or
57 * derivative of this code cannot be changed.  i.e. this code cannot simply be
58 * copied and put under another distribution licence
59 * [including the GNU Public Licence.]
60 */
61
62#include <sys/types.h>
63#include <crypto/des/des_locl.h>
64
65extern	const DES_LONG des_SPtrans[8][64];
66
67void des_encrypt1(DES_LONG *data, des_key_schedule ks, int enc)
68{
69	register DES_LONG l,r,t,u;
70#ifdef DES_PTR
71	register const unsigned char *des_SP=(const unsigned char *)des_SPtrans;
72#endif
73#ifndef DES_UNROLL
74	register int i;
75#endif
76	register DES_LONG *s;
77
78	r=data[0];
79	l=data[1];
80
81	IP(r,l);
82	/* Things have been modified so that the initial rotate is
83	 * done outside the loop.  This required the
84	 * des_SPtrans values in sp.h to be rotated 1 bit to the right.
85	 * One perl script later and things have a 5% speed up on a sparc2.
86	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
87	 * for pointing this out. */
88	/* clear the top bits on machines with 8byte longs */
89	/* shift left by 2 */
90	r=ROTATE(r,29)&0xffffffffL;
91	l=ROTATE(l,29)&0xffffffffL;
92
93	s=ks->ks.deslong;
94	/* I don't know if it is worth the effort of loop unrolling the
95	 * inner loop */
96	if (enc)
97		{
98#ifdef DES_UNROLL
99		D_ENCRYPT(l,r, 0); /*  1 */
100		D_ENCRYPT(r,l, 2); /*  2 */
101		D_ENCRYPT(l,r, 4); /*  3 */
102		D_ENCRYPT(r,l, 6); /*  4 */
103		D_ENCRYPT(l,r, 8); /*  5 */
104		D_ENCRYPT(r,l,10); /*  6 */
105		D_ENCRYPT(l,r,12); /*  7 */
106		D_ENCRYPT(r,l,14); /*  8 */
107		D_ENCRYPT(l,r,16); /*  9 */
108		D_ENCRYPT(r,l,18); /*  10 */
109		D_ENCRYPT(l,r,20); /*  11 */
110		D_ENCRYPT(r,l,22); /*  12 */
111		D_ENCRYPT(l,r,24); /*  13 */
112		D_ENCRYPT(r,l,26); /*  14 */
113		D_ENCRYPT(l,r,28); /*  15 */
114		D_ENCRYPT(r,l,30); /*  16 */
115#else
116		for (i=0; i<32; i+=8)
117			{
118			D_ENCRYPT(l,r,i+0); /*  1 */
119			D_ENCRYPT(r,l,i+2); /*  2 */
120			D_ENCRYPT(l,r,i+4); /*  3 */
121			D_ENCRYPT(r,l,i+6); /*  4 */
122			}
123#endif
124		}
125	else
126		{
127#ifdef DES_UNROLL
128		D_ENCRYPT(l,r,30); /* 16 */
129		D_ENCRYPT(r,l,28); /* 15 */
130		D_ENCRYPT(l,r,26); /* 14 */
131		D_ENCRYPT(r,l,24); /* 13 */
132		D_ENCRYPT(l,r,22); /* 12 */
133		D_ENCRYPT(r,l,20); /* 11 */
134		D_ENCRYPT(l,r,18); /* 10 */
135		D_ENCRYPT(r,l,16); /*  9 */
136		D_ENCRYPT(l,r,14); /*  8 */
137		D_ENCRYPT(r,l,12); /*  7 */
138		D_ENCRYPT(l,r,10); /*  6 */
139		D_ENCRYPT(r,l, 8); /*  5 */
140		D_ENCRYPT(l,r, 6); /*  4 */
141		D_ENCRYPT(r,l, 4); /*  3 */
142		D_ENCRYPT(l,r, 2); /*  2 */
143		D_ENCRYPT(r,l, 0); /*  1 */
144#else
145		for (i=30; i>0; i-=8)
146			{
147			D_ENCRYPT(l,r,i-0); /* 16 */
148			D_ENCRYPT(r,l,i-2); /* 15 */
149			D_ENCRYPT(l,r,i-4); /* 14 */
150			D_ENCRYPT(r,l,i-6); /* 13 */
151			}
152#endif
153		}
154
155	/* rotate and clear the top bits on machines with 8byte longs */
156	l=ROTATE(l,3)&0xffffffffL;
157	r=ROTATE(r,3)&0xffffffffL;
158
159	FP(r,l);
160	data[0]=l;
161	data[1]=r;
162	l=r=t=u=0;
163}
164
165void des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc)
166{
167	register DES_LONG l,r,t,u;
168#ifdef DES_PTR
169	register const unsigned char *des_SP=(const unsigned char *)des_SPtrans;
170#endif
171#ifndef DES_UNROLL
172	register int i;
173#endif
174	register DES_LONG *s;
175
176	r=data[0];
177	l=data[1];
178
179	/* Things have been modified so that the initial rotate is
180	 * done outside the loop.  This required the
181	 * des_SPtrans values in sp.h to be rotated 1 bit to the right.
182	 * One perl script later and things have a 5% speed up on a sparc2.
183	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
184	 * for pointing this out. */
185	/* clear the top bits on machines with 8byte longs */
186	r=ROTATE(r,29)&0xffffffffL;
187	l=ROTATE(l,29)&0xffffffffL;
188
189	s=ks->ks.deslong;
190	/* I don't know if it is worth the effort of loop unrolling the
191	 * inner loop */
192	if (enc)
193		{
194#ifdef DES_UNROLL
195		D_ENCRYPT(l,r, 0); /*  1 */
196		D_ENCRYPT(r,l, 2); /*  2 */
197		D_ENCRYPT(l,r, 4); /*  3 */
198		D_ENCRYPT(r,l, 6); /*  4 */
199		D_ENCRYPT(l,r, 8); /*  5 */
200		D_ENCRYPT(r,l,10); /*  6 */
201		D_ENCRYPT(l,r,12); /*  7 */
202		D_ENCRYPT(r,l,14); /*  8 */
203		D_ENCRYPT(l,r,16); /*  9 */
204		D_ENCRYPT(r,l,18); /*  10 */
205		D_ENCRYPT(l,r,20); /*  11 */
206		D_ENCRYPT(r,l,22); /*  12 */
207		D_ENCRYPT(l,r,24); /*  13 */
208		D_ENCRYPT(r,l,26); /*  14 */
209		D_ENCRYPT(l,r,28); /*  15 */
210		D_ENCRYPT(r,l,30); /*  16 */
211#else
212		for (i=0; i<32; i+=8)
213			{
214			D_ENCRYPT(l,r,i+0); /*  1 */
215			D_ENCRYPT(r,l,i+2); /*  2 */
216			D_ENCRYPT(l,r,i+4); /*  3 */
217			D_ENCRYPT(r,l,i+6); /*  4 */
218			}
219#endif
220		}
221	else
222		{
223#ifdef DES_UNROLL
224		D_ENCRYPT(l,r,30); /* 16 */
225		D_ENCRYPT(r,l,28); /* 15 */
226		D_ENCRYPT(l,r,26); /* 14 */
227		D_ENCRYPT(r,l,24); /* 13 */
228		D_ENCRYPT(l,r,22); /* 12 */
229		D_ENCRYPT(r,l,20); /* 11 */
230		D_ENCRYPT(l,r,18); /* 10 */
231		D_ENCRYPT(r,l,16); /*  9 */
232		D_ENCRYPT(l,r,14); /*  8 */
233		D_ENCRYPT(r,l,12); /*  7 */
234		D_ENCRYPT(l,r,10); /*  6 */
235		D_ENCRYPT(r,l, 8); /*  5 */
236		D_ENCRYPT(l,r, 6); /*  4 */
237		D_ENCRYPT(r,l, 4); /*  3 */
238		D_ENCRYPT(l,r, 2); /*  2 */
239		D_ENCRYPT(r,l, 0); /*  1 */
240#else
241		for (i=30; i>0; i-=8)
242			{
243			D_ENCRYPT(l,r,i-0); /* 16 */
244			D_ENCRYPT(r,l,i-2); /* 15 */
245			D_ENCRYPT(l,r,i-4); /* 14 */
246			D_ENCRYPT(r,l,i-6); /* 13 */
247			}
248#endif
249		}
250	/* rotate and clear the top bits on machines with 8byte longs */
251	data[0]=ROTATE(l,3)&0xffffffffL;
252	data[1]=ROTATE(r,3)&0xffffffffL;
253	l=r=t=u=0;
254}
255
256void des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2,
257	     des_key_schedule ks3)
258{
259	register DES_LONG l,r;
260
261	l=data[0];
262	r=data[1];
263	IP(l,r);
264	data[0]=l;
265	data[1]=r;
266	des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT);
267	des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT);
268	des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT);
269	l=data[0];
270	r=data[1];
271	FP(r,l);
272	data[0]=l;
273	data[1]=r;
274}
275
276void des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2,
277	     des_key_schedule ks3)
278{
279	register DES_LONG l,r;
280
281	l=data[0];
282	r=data[1];
283	IP(l,r);
284	data[0]=l;
285	data[1]=r;
286	des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT);
287	des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT);
288	des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT);
289	l=data[0];
290	r=data[1];
291	FP(r,l);
292	data[0]=l;
293	data[1]=r;
294}
295