xref: /titanic_52/usr/src/common/net/wanboot/crypt/des.c (revision d583b39bfb4e2571d3e41097c5c357ffe353ad45)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Portable C version of des() and des_key() functions.
31  * This version is very similar to that in Part V of Applied Cryptography
32  * by Bruce Schneier.
33  *
34  * This information is in the public domain 12/15/95 P. Karn
35  */
36 
37 #include <sys/types.h>
38 #include <sys/sysmacros.h>
39 #if defined(_KERNEL) && !defined(_BOOT)
40 #include <sys/systm.h>
41 #else
42 #include <strings.h>
43 #endif
44 
45 #include "des.h"
46 
47 /*
48  * Combined SP lookup table, linked in
49  * For best results, ensure that this is aligned on a 32-bit boundary;
50  */
51 static uint32_t Spbox[8][64] = {
52 	0x01010400U, 0x00000000U, 0x00010000U, 0x01010404U,
53 	0x01010004U, 0x00010404U, 0x00000004U, 0x00010000U,
54 	0x00000400U, 0x01010400U, 0x01010404U, 0x00000400U,
55 	0x01000404U, 0x01010004U, 0x01000000U, 0x00000004U,
56 	0x00000404U, 0x01000400U, 0x01000400U, 0x00010400U,
57 	0x00010400U, 0x01010000U, 0x01010000U, 0x01000404U,
58 	0x00010004U, 0x01000004U, 0x01000004U, 0x00010004U,
59 	0x00000000U, 0x00000404U, 0x00010404U, 0x01000000U,
60 	0x00010000U, 0x01010404U, 0x00000004U, 0x01010000U,
61 	0x01010400U, 0x01000000U, 0x01000000U, 0x00000400U,
62 	0x01010004U, 0x00010000U, 0x00010400U, 0x01000004U,
63 	0x00000400U, 0x00000004U, 0x01000404U, 0x00010404U,
64 	0x01010404U, 0x00010004U, 0x01010000U, 0x01000404U,
65 	0x01000004U, 0x00000404U, 0x00010404U, 0x01010400U,
66 	0x00000404U, 0x01000400U, 0x01000400U, 0x00000000U,
67 	0x00010004U, 0x00010400U, 0x00000000U, 0x01010004U,
68 	0x80108020U, 0x80008000U, 0x00008000U, 0x00108020U,
69 	0x00100000U, 0x00000020U, 0x80100020U, 0x80008020U,
70 	0x80000020U, 0x80108020U, 0x80108000U, 0x80000000U,
71 	0x80008000U, 0x00100000U, 0x00000020U, 0x80100020U,
72 	0x00108000U, 0x00100020U, 0x80008020U, 0x00000000U,
73 	0x80000000U, 0x00008000U, 0x00108020U, 0x80100000U,
74 	0x00100020U, 0x80000020U, 0x00000000U, 0x00108000U,
75 	0x00008020U, 0x80108000U, 0x80100000U, 0x00008020U,
76 	0x00000000U, 0x00108020U, 0x80100020U, 0x00100000U,
77 	0x80008020U, 0x80100000U, 0x80108000U, 0x00008000U,
78 	0x80100000U, 0x80008000U, 0x00000020U, 0x80108020U,
79 	0x00108020U, 0x00000020U, 0x00008000U, 0x80000000U,
80 	0x00008020U, 0x80108000U, 0x00100000U, 0x80000020U,
81 	0x00100020U, 0x80008020U, 0x80000020U, 0x00100020U,
82 	0x00108000U, 0x00000000U, 0x80008000U, 0x00008020U,
83 	0x80000000U, 0x80100020U, 0x80108020U, 0x00108000U,
84 	0x00000208U, 0x08020200U, 0x00000000U, 0x08020008U,
85 	0x08000200U, 0x00000000U, 0x00020208U, 0x08000200U,
86 	0x00020008U, 0x08000008U, 0x08000008U, 0x00020000U,
87 	0x08020208U, 0x00020008U, 0x08020000U, 0x00000208U,
88 	0x08000000U, 0x00000008U, 0x08020200U, 0x00000200U,
89 	0x00020200U, 0x08020000U, 0x08020008U, 0x00020208U,
90 	0x08000208U, 0x00020200U, 0x00020000U, 0x08000208U,
91 	0x00000008U, 0x08020208U, 0x00000200U, 0x08000000U,
92 	0x08020200U, 0x08000000U, 0x00020008U, 0x00000208U,
93 	0x00020000U, 0x08020200U, 0x08000200U, 0x00000000U,
94 	0x00000200U, 0x00020008U, 0x08020208U, 0x08000200U,
95 	0x08000008U, 0x00000200U, 0x00000000U, 0x08020008U,
96 	0x08000208U, 0x00020000U, 0x08000000U, 0x08020208U,
97 	0x00000008U, 0x00020208U, 0x00020200U, 0x08000008U,
98 	0x08020000U, 0x08000208U, 0x00000208U, 0x08020000U,
99 	0x00020208U, 0x00000008U, 0x08020008U, 0x00020200U,
100 	0x00802001U, 0x00002081U, 0x00002081U, 0x00000080U,
101 	0x00802080U, 0x00800081U, 0x00800001U, 0x00002001U,
102 	0x00000000U, 0x00802000U, 0x00802000U, 0x00802081U,
103 	0x00000081U, 0x00000000U, 0x00800080U, 0x00800001U,
104 	0x00000001U, 0x00002000U, 0x00800000U, 0x00802001U,
105 	0x00000080U, 0x00800000U, 0x00002001U, 0x00002080U,
106 	0x00800081U, 0x00000001U, 0x00002080U, 0x00800080U,
107 	0x00002000U, 0x00802080U, 0x00802081U, 0x00000081U,
108 	0x00800080U, 0x00800001U, 0x00802000U, 0x00802081U,
109 	0x00000081U, 0x00000000U, 0x00000000U, 0x00802000U,
110 	0x00002080U, 0x00800080U, 0x00800081U, 0x00000001U,
111 	0x00802001U, 0x00002081U, 0x00002081U, 0x00000080U,
112 	0x00802081U, 0x00000081U, 0x00000001U, 0x00002000U,
113 	0x00800001U, 0x00002001U, 0x00802080U, 0x00800081U,
114 	0x00002001U, 0x00002080U, 0x00800000U, 0x00802001U,
115 	0x00000080U, 0x00800000U, 0x00002000U, 0x00802080U,
116 	0x00000100U, 0x02080100U, 0x02080000U, 0x42000100U,
117 	0x00080000U, 0x00000100U, 0x40000000U, 0x02080000U,
118 	0x40080100U, 0x00080000U, 0x02000100U, 0x40080100U,
119 	0x42000100U, 0x42080000U, 0x00080100U, 0x40000000U,
120 	0x02000000U, 0x40080000U, 0x40080000U, 0x00000000U,
121 	0x40000100U, 0x42080100U, 0x42080100U, 0x02000100U,
122 	0x42080000U, 0x40000100U, 0x00000000U, 0x42000000U,
123 	0x02080100U, 0x02000000U, 0x42000000U, 0x00080100U,
124 	0x00080000U, 0x42000100U, 0x00000100U, 0x02000000U,
125 	0x40000000U, 0x02080000U, 0x42000100U, 0x40080100U,
126 	0x02000100U, 0x40000000U, 0x42080000U, 0x02080100U,
127 	0x40080100U, 0x00000100U, 0x02000000U, 0x42080000U,
128 	0x42080100U, 0x00080100U, 0x42000000U, 0x42080100U,
129 	0x02080000U, 0x00000000U, 0x40080000U, 0x42000000U,
130 	0x00080100U, 0x02000100U, 0x40000100U, 0x00080000U,
131 	0x00000000U, 0x40080000U, 0x02080100U, 0x40000100U,
132 	0x20000010U, 0x20400000U, 0x00004000U, 0x20404010U,
133 	0x20400000U, 0x00000010U, 0x20404010U, 0x00400000U,
134 	0x20004000U, 0x00404010U, 0x00400000U, 0x20000010U,
135 	0x00400010U, 0x20004000U, 0x20000000U, 0x00004010U,
136 	0x00000000U, 0x00400010U, 0x20004010U, 0x00004000U,
137 	0x00404000U, 0x20004010U, 0x00000010U, 0x20400010U,
138 	0x20400010U, 0x00000000U, 0x00404010U, 0x20404000U,
139 	0x00004010U, 0x00404000U, 0x20404000U, 0x20000000U,
140 	0x20004000U, 0x00000010U, 0x20400010U, 0x00404000U,
141 	0x20404010U, 0x00400000U, 0x00004010U, 0x20000010U,
142 	0x00400000U, 0x20004000U, 0x20000000U, 0x00004010U,
143 	0x20000010U, 0x20404010U, 0x00404000U, 0x20400000U,
144 	0x00404010U, 0x20404000U, 0x00000000U, 0x20400010U,
145 	0x00000010U, 0x00004000U, 0x20400000U, 0x00404010U,
146 	0x00004000U, 0x00400010U, 0x20004010U, 0x00000000U,
147 	0x20404000U, 0x20000000U, 0x00400010U, 0x20004010U,
148 	0x00200000U, 0x04200002U, 0x04000802U, 0x00000000U,
149 	0x00000800U, 0x04000802U, 0x00200802U, 0x04200800U,
150 	0x04200802U, 0x00200000U, 0x00000000U, 0x04000002U,
151 	0x00000002U, 0x04000000U, 0x04200002U, 0x00000802U,
152 	0x04000800U, 0x00200802U, 0x00200002U, 0x04000800U,
153 	0x04000002U, 0x04200000U, 0x04200800U, 0x00200002U,
154 	0x04200000U, 0x00000800U, 0x00000802U, 0x04200802U,
155 	0x00200800U, 0x00000002U, 0x04000000U, 0x00200800U,
156 	0x04000000U, 0x00200800U, 0x00200000U, 0x04000802U,
157 	0x04000802U, 0x04200002U, 0x04200002U, 0x00000002U,
158 	0x00200002U, 0x04000000U, 0x04000800U, 0x00200000U,
159 	0x04200800U, 0x00000802U, 0x00200802U, 0x04200800U,
160 	0x00000802U, 0x04000002U, 0x04200802U, 0x04200000U,
161 	0x00200800U, 0x00000000U, 0x00000002U, 0x04200802U,
162 	0x00000000U, 0x00200802U, 0x04200000U, 0x00000800U,
163 	0x04000002U, 0x04000800U, 0x00000800U, 0x00200002U,
164 	0x10001040U, 0x00001000U, 0x00040000U, 0x10041040U,
165 	0x10000000U, 0x10001040U, 0x00000040U, 0x10000000U,
166 	0x00040040U, 0x10040000U, 0x10041040U, 0x00041000U,
167 	0x10041000U, 0x00041040U, 0x00001000U, 0x00000040U,
168 	0x10040000U, 0x10000040U, 0x10001000U, 0x00001040U,
169 	0x00041000U, 0x00040040U, 0x10040040U, 0x10041000U,
170 	0x00001040U, 0x00000000U, 0x00000000U, 0x10040040U,
171 	0x10000040U, 0x10001000U, 0x00041040U, 0x00040000U,
172 	0x00041040U, 0x00040000U, 0x10041000U, 0x00001000U,
173 	0x00000040U, 0x10040040U, 0x00001000U, 0x00041040U,
174 	0x10001000U, 0x00000040U, 0x10000040U, 0x10040000U,
175 	0x10040040U, 0x10000000U, 0x00040000U, 0x10001040U,
176 	0x00000000U, 0x10041040U, 0x00040040U, 0x10000040U,
177 	0x10040000U, 0x10001000U, 0x10001040U, 0x00000000U,
178 	0x10041040U, 0x00041000U, 0x00041000U, 0x00001040U,
179 	0x00001040U, 0x00040040U, 0x10000000U, 0x10041000U,
180 };
181 
182 /*
183  * Primitive function F.
184  * Input is r, subkey array in keys, output is XORed into l.
185  * Each round consumes eight 6-bit subkeys, one for
186  * each of the 8 S-boxes, 2 longs for each round.
187  * Each long contains four 6-bit subkeys, each taking up a byte.
188  * The first long contains, from high to low end, the subkeys for
189  * S-boxes 1, 3, 5 & 7; the second contains the subkeys for S-boxes
190  * 2, 4, 6 & 8 (using the origin-1 S-box numbering in the standard,
191  * not the origin-0 numbering used elsewhere in this code)
192  * See comments elsewhere about the pre-rotated values of r and Spbox.
193  */
194 #define	F(l, r, key) {\
195 	work = ((r >> 4) | (r << 28)) ^ (key)[0];\
196 	l ^= Spbox[6][work & 0x3f];\
197 	l ^= Spbox[4][(work >> 8) & 0x3f];\
198 	l ^= Spbox[2][(work >> 16) & 0x3f];\
199 	l ^= Spbox[0][(work >> 24) & 0x3f];\
200 	work = r ^ (key)[1];\
201 	l ^= Spbox[7][work & 0x3f];\
202 	l ^= Spbox[5][(work >> 8) & 0x3f];\
203 	l ^= Spbox[3][(work >> 16) & 0x3f];\
204 	l ^= Spbox[1][(work >> 24) & 0x3f];\
205 }
206 
207 /* Encrypt or decrypt a block of data in ECB mode */
208 void
209 des(void *cookie, uint8_t *block)
210 {
211 	uint32_t *ks = (uint32_t *)cookie;
212 	uint32_t left;
213 	uint32_t right;
214 	uint32_t work;
215 
216 	/* Read input block and place in left/right in big-endian order */
217 	left = ((uint32_t)block[0] << 24) |
218 	    ((uint32_t)block[1] << 16) |
219 	    ((uint32_t)block[2] << 8) |
220 	    (uint32_t)block[3];
221 	right = ((uint32_t)block[4] << 24) |
222 	    ((uint32_t)block[5] << 16) |
223 	    ((uint32_t)block[6] << 8) |
224 	    (uint32_t)block[7];
225 
226 	/*
227 	 * Hoey's clever initial permutation algorithm, from Outerbridge
228 	 * (see Schneier p 478)
229 	 *
230 	 * The convention here is the same as Outerbridge: rotate each
231 	 * register left by 1 bit, i.e., so that "left" contains permuted
232 	 * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
233 	 * (using origin-1 numbering as in the FIPS). This allows us to avoid
234 	 * one of the two rotates that would otherwise be required in each of
235 	 * the 16 rounds.
236 	 */
237 	work = ((left >> 4) ^ right) & 0x0f0f0f0f;
238 	right ^= work;
239 	left ^= work << 4;
240 	work = ((left >> 16) ^ right) & 0xffff;
241 	right ^= work;
242 	left ^= work << 16;
243 	work = ((right >> 2) ^ left) & 0x33333333;
244 	left ^= work;
245 	right ^= (work << 2);
246 	work = ((right >> 8) ^ left) & 0xff00ff;
247 	left ^= work;
248 	right ^= (work << 8);
249 	right = (right << 1) | (right >> 31);
250 	work = (left ^ right) & 0xaaaaaaaa;
251 	left ^= work;
252 	right ^= work;
253 	left = (left << 1) | (left >> 31);
254 
255 	/* First key */
256 	F(left, right, ks);
257 	F(right, left, ks + 2);
258 	F(left, right, ks + 4);
259 	F(right, left, ks + 6);
260 	F(left, right, ks + 8);
261 	F(right, left, ks + 10);
262 	F(left, right, ks + 12);
263 	F(right, left, ks + 14);
264 	F(left, right, ks + 16);
265 	F(right, left, ks + 18);
266 	F(left, right, ks + 20);
267 	F(right, left, ks + 22);
268 	F(left, right, ks + 24);
269 	F(right, left, ks + 26);
270 	F(left, right, ks + 28);
271 	F(right, left, ks + 30);
272 
273 	/* Inverse permutation, also from Hoey via Outerbridge and Schneier */
274 	right = (right << 31) | (right >> 1);
275 	work = (left ^ right) & 0xaaaaaaaa;
276 	left ^= work;
277 	right ^= work;
278 	left = (left >> 1) | (left  << 31);
279 	work = ((left >> 8) ^ right) & 0xff00ff;
280 	right ^= work;
281 	left ^= work << 8;
282 	work = ((left >> 2) ^ right) & 0x33333333;
283 	right ^= work;
284 	left ^= work << 2;
285 	work = ((right >> 16) ^ left) & 0xffff;
286 	left ^= work;
287 	right ^= work << 16;
288 	work = ((right >> 4) ^ left) & 0x0f0f0f0f;
289 	left ^= work;
290 	right ^= work << 4;
291 
292 	/* Put the block back into the user's buffer with final swap */
293 	block[0] = right >> 24;
294 	block[1] = right >> 16;
295 	block[2] = right >> 8;
296 	block[3] = right;
297 	block[4] = left >> 24;
298 	block[5] = left >> 16;
299 	block[6] = left >> 8;
300 	block[7] = left;
301 }
302 
303 /* Key schedule-related tables from FIPS-46 */
304 
305 /* permuted choice table (key) */
306 static unsigned char pc1[] = {
307 	57, 49, 41, 33, 25, 17, 9,
308 	1, 58, 50, 42, 34, 26, 18,
309 	10, 2, 59, 51, 43, 35, 27,
310 	19, 11, 3, 60, 52, 44, 36,
311 	63, 55, 47, 39, 31, 23, 15,
312 	7, 62, 54, 46, 38, 30, 22,
313 	14, 6, 61, 53, 45, 37, 29,
314 	21, 13, 5, 28, 20, 12, 4
315 };
316 
317 /* number left rotations of pc1 */
318 static unsigned char totrot[] = {
319 	1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
320 };
321 
322 /* permuted choice key (table) */
323 static unsigned char pc2[] = {
324 	14, 17, 11, 24, 1, 5,
325 	3, 28, 15, 6, 21, 10,
326 	23, 19, 12, 4, 26, 8,
327 	16, 7, 27, 20, 13, 2,
328 	41, 52, 31, 37, 47, 55,
329 	30, 40, 51, 45, 33, 48,
330 	44, 49, 39, 56, 34, 53,
331 	46, 42, 50, 36, 29, 32
332 };
333 
334 /* End of DES-defined tables */
335 
336 
337 /* bit 0 is left-most in byte */
338 static int bytebit[] = {
339 	0200, 0100, 040, 020, 010, 04, 02, 01
340 };
341 
342 /*
343  * Generate key schedule for encryption or decryption
344  * depending on the value of "decrypt"
345  */
346 void
347 des_key(DES_KS k, const unsigned char *key, int decrypt)
348 {
349 	unsigned char pc1m[56];		/* place to modify pc1 into */
350 	unsigned char pcr[56];		/* place to rotate pc1 into */
351 	int i;
352 	int j;
353 	int l;
354 	int m;
355 	unsigned char ks[8];
356 
357 	for (j = 0; j < 56; j++) {	/* convert pc1 to bits of key */
358 		l = pc1[j] - 1;		/* integer bit location	 */
359 		m = l & 07;		/* find bit		 */
360 		pc1m[j] = (key[l >>3 ]	/* find which key byte l is in */
361 			& bytebit[m])	/* and which bit of that byte */
362 			? 1 : 0;	/* and store 1-bit result */
363 	}
364 	for (i = 0; i < 16; i++) {	/* key chunk for each iteration */
365 		bzero(ks, sizeof (ks));	/* Clear key schedule */
366 		for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
367 			pcr[j] = pc1m[(l = j + totrot[decrypt ? 15 - i : i]) <
368 			    (j < 28 ? 28 : 56) ? l : l - 28];
369 			/* rotate left and right halves independently */
370 		for (j = 0; j < 48; j++) {	/* select bits individually */
371 			/* check bit that goes to ks[j] */
372 			if (pcr[pc2[j] - 1]) {
373 				/* mask it in if it's there */
374 				l = j % 6;
375 				ks[j/6] |= bytebit[l] >> 2;
376 			}
377 		}
378 		/* Now convert to packed odd/even interleaved form */
379 		k[i][0] = ((uint32_t)ks[0] << 24) |
380 		    ((uint32_t)ks[2] << 16) |
381 		    ((uint32_t)ks[4] << 8) |
382 		    ((uint32_t)ks[6]);
383 		k[i][1] = ((uint32_t)ks[1] << 24) |
384 		    ((uint32_t)ks[3] << 16) |
385 		    ((uint32_t)ks[5] << 8) |
386 		    ((uint32_t)ks[7]);
387 	}
388 }
389