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
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.
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]
23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Portable C version of des() and des_key() functions.
31 * This version is very similar to that in Part V of Applied Cryptography
34 * This information is in the public domain 12/15/95 P. Karn
37 #include <sys/types.h>
38 #include <sys/sysmacros.h>
39 #if defined(_KERNEL) && !defined(_BOOT)
40 #include <sys/systm.h>
48 * Combined SP lookup table, linked in
49 * For best results, ensure that this is aligned on a 32-bit boundary;
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
,
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.
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];\
207 /* Encrypt or decrypt a block of data in ECB mode */
209 des(void *cookie
, uint8_t *block
)
211 uint32_t *ks
= (uint32_t *)cookie
;
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) |
221 right
= ((uint32_t)block
[4] << 24) |
222 ((uint32_t)block
[5] << 16) |
223 ((uint32_t)block
[6] << 8) |
227 * Hoey's clever initial permutation algorithm, from Outerbridge
228 * (see Schneier p 478)
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
237 work
= ((left
>> 4) ^ right
) & 0x0f0f0f0f;
240 work
= ((left
>> 16) ^ right
) & 0xffff;
243 work
= ((right
>> 2) ^ left
) & 0x33333333;
245 right
^= (work
<< 2);
246 work
= ((right
>> 8) ^ left
) & 0xff00ff;
248 right
^= (work
<< 8);
249 right
= (right
<< 1) | (right
>> 31);
250 work
= (left
^ right
) & 0xaaaaaaaa;
253 left
= (left
<< 1) | (left
>> 31);
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);
273 /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
274 right
= (right
<< 31) | (right
>> 1);
275 work
= (left
^ right
) & 0xaaaaaaaa;
278 left
= (left
>> 1) | (left
<< 31);
279 work
= ((left
>> 8) ^ right
) & 0xff00ff;
282 work
= ((left
>> 2) ^ right
) & 0x33333333;
285 work
= ((right
>> 16) ^ left
) & 0xffff;
288 work
= ((right
>> 4) ^ left
) & 0x0f0f0f0f;
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;
297 block
[4] = left
>> 24;
298 block
[5] = left
>> 16;
299 block
[6] = left
>> 8;
303 /* Key schedule-related tables from FIPS-46 */
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
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
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
334 /* End of DES-defined tables */
337 /* bit 0 is left-most in byte */
338 static int bytebit
[] = {
339 0200, 0100, 040, 020, 010, 04, 02, 01
343 * Generate key schedule for encryption or decryption
344 * depending on the value of "decrypt"
347 des_key(DES_KS k
, const unsigned char *key
, int decrypt
)
349 unsigned char pc1m
[56]; /* place to modify pc1 into */
350 unsigned char pcr
[56]; /* place to rotate pc1 into */
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 */
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 */
375 ks
[j
/6] |= bytebit
[l
] >> 2;
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) |
383 k
[i
][1] = ((uint32_t)ks
[1] << 24) |
384 ((uint32_t)ks
[3] << 16) |
385 ((uint32_t)ks
[5] << 8) |