source: branches/samba-3.5.x/source4/heimdal/lib/hcrypto/des.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 33.0 KB
Line 
1/*
2 * Copyright (c) 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/**
35 * @page page_des DES - Data Encryption Standard crypto interface
36 *
37 * See the library functions here: @ref hcrypto_des
38 *
39 * DES was created by IBM, modififed by NSA and then adopted by NBS
40 * (now NIST) and published ad FIPS PUB 46 (updated by FIPS 46-1).
41 *
42 * Since the 19th May 2005 DES was withdrawn by NIST and should no
43 * longer be used. See @ref page_evp for replacement encryption
44 * algorithms and interfaces.
45 *
46 * Read more the iteresting history of DES on Wikipedia
47 * http://www.wikipedia.org/wiki/Data_Encryption_Standard .
48 *
49 * @section des_keygen DES key generation
50 *
51 * To generate a DES key safely you have to use the code-snippet
52 * below. This is because the DES_random_key() can fail with an
53 * abort() in case of and failure to start the random generator.
54 *
55 * There is a replacement function DES_new_random_key(), however that
56 * function does not exists in OpenSSL.
57 *
58 * @code
59 * DES_cblock key;
60 * do {
61 * if (RAND_rand(&key, sizeof(key)) != 1)
62 * goto failure;
63 * DES_set_odd_parity(key);
64 * } while (DES_is_weak_key(&key));
65 * @endcode
66 *
67 * @section des_impl DES implementation history
68 *
69 * There was no complete BSD licensed, fast, GPL compatible
70 * implementation of DES, so Love wrote the part that was missing,
71 * fast key schedule setup and adapted the interface to the orignal
72 * libdes.
73 *
74 * The document that got me started for real was "Efficient
75 * Implementation of the Data Encryption Standard" by Dag Arne Osvik.
76 * I never got to the PC1 transformation was working, instead I used
77 * table-lookup was used for all key schedule setup. The document was
78 * very useful since it de-mystified other implementations for me.
79 *
80 * The core DES function (SBOX + P transformation) is from Richard
81 * Outerbridge public domain DES implementation. My sanity is saved
82 * thanks to his work. Thank you Richard.
83 */
84
85#include <config.h>
86
87#define HC_DEPRECATED
88
89#include <stdio.h>
90#include <stdlib.h>
91#include <string.h>
92#include <krb5-types.h>
93#include <assert.h>
94
95#include "des.h"
96#include "ui.h"
97
98static void desx(uint32_t [2], DES_key_schedule *, int);
99static void IP(uint32_t [2]);
100static void FP(uint32_t [2]);
101
102#include "des-tables.h"
103
104#define ROTATE_LEFT28(x,one) \
105 if (one) { \
106 x = ( ((x)<<(1)) & 0xffffffe) | ((x) >> 27); \
107 } else { \
108 x = ( ((x)<<(2)) & 0xffffffc) | ((x) >> 26); \
109 }
110
111/**
112 * Set the parity of the key block, used to generate a des key from a
113 * random key. See @ref des_keygen.
114 *
115 * @param key key to fixup the parity for.
116 * @ingroup hcrypto_des
117 */
118
119void
120DES_set_odd_parity(DES_cblock *key)
121{
122 unsigned int i;
123 for (i = 0; i < DES_CBLOCK_LEN; i++)
124 (*key)[i] = odd_parity[(*key)[i]];
125}
126
127/**
128 * Check if the key have correct parity.
129 *
130 * @param key key to check the parity.
131 * @return 1 on success, 0 on failure.
132 * @ingroup hcrypto_des
133 */
134
135int HC_DEPRECATED
136DES_check_key_parity(DES_cblock *key)
137{
138 unsigned int i;
139
140 for (i = 0; i < DES_CBLOCK_LEN; i++)
141 if ((*key)[i] != odd_parity[(*key)[i]])
142 return 0;
143 return 1;
144}
145
146/*
147 *
148 */
149
150/* FIPS 74 */
151static DES_cblock weak_keys[] = {
152 {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, /* weak keys */
153 {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
154 {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
155 {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
156 {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, /* semi-weak keys */
157 {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
158 {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
159 {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
160 {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
161 {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
162 {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
163 {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
164 {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
165 {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
166 {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
167 {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}
168};
169
170/**
171 * Checks if the key is any of the weaks keys that makes DES attacks
172 * trival.
173 *
174 * @param key key to check.
175 *
176 * @return 1 if the key is weak, 0 otherwise.
177 * @ingroup hcrypto_des
178 */
179
180int
181DES_is_weak_key(DES_cblock *key)
182{
183 int i;
184
185 for (i = 0; i < sizeof(weak_keys)/sizeof(weak_keys[0]); i++) {
186 if (memcmp(weak_keys[i], key, DES_CBLOCK_LEN) == 0)
187 return 1;
188 }
189 return 0;
190}
191
192/**
193 * Setup a des key schedule from a key. Deprecated function, use
194 * DES_set_key_unchecked() or DES_set_key_checked() instead.
195 *
196 * @param key a key to initialize the key schedule with.
197 * @param ks a key schedule to initialize.
198 *
199 * @return 0 on success
200 * @ingroup hcrypto_des
201 */
202
203int HC_DEPRECATED
204DES_set_key(DES_cblock *key, DES_key_schedule *ks)
205{
206 return DES_set_key_checked(key, ks);
207}
208
209/**
210 * Setup a des key schedule from a key. The key is no longer needed
211 * after this transaction and can cleared.
212 *
213 * Does NOT check that the key is weak for or have wrong parity.
214 *
215 * @param key a key to initialize the key schedule with.
216 * @param ks a key schedule to initialize.
217 *
218 * @return 0 on success
219 * @ingroup hcrypto_des
220 */
221
222int
223DES_set_key_unchecked(DES_cblock *key, DES_key_schedule *ks)
224{
225 uint32_t t1, t2;
226 uint32_t c, d;
227 int shifts[16] = { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
228 uint32_t *k = &ks->ks[0];
229 int i;
230
231 t1 = (*key)[0] << 24 | (*key)[1] << 16 | (*key)[2] << 8 | (*key)[3];
232 t2 = (*key)[4] << 24 | (*key)[5] << 16 | (*key)[6] << 8 | (*key)[7];
233
234 c = (pc1_c_3[(t1 >> (5 )) & 0x7] << 3)
235 | (pc1_c_3[(t1 >> (5 + 8 )) & 0x7] << 2)
236 | (pc1_c_3[(t1 >> (5 + 8 + 8 )) & 0x7] << 1)
237 | (pc1_c_3[(t1 >> (5 + 8 + 8 + 8)) & 0x7] << 0)
238 | (pc1_c_4[(t2 >> (4 )) & 0xf] << 3)
239 | (pc1_c_4[(t2 >> (4 + 8 )) & 0xf] << 2)
240 | (pc1_c_4[(t2 >> (4 + 8 + 8 )) & 0xf] << 1)
241 | (pc1_c_4[(t2 >> (4 + 8 + 8 + 8)) & 0xf] << 0);
242
243
244 d = (pc1_d_3[(t2 >> (1 )) & 0x7] << 3)
245 | (pc1_d_3[(t2 >> (1 + 8 )) & 0x7] << 2)
246 | (pc1_d_3[(t2 >> (1 + 8 + 8 )) & 0x7] << 1)
247 | (pc1_d_3[(t2 >> (1 + 8 + 8 + 8)) & 0x7] << 0)
248 | (pc1_d_4[(t1 >> (1 )) & 0xf] << 3)
249 | (pc1_d_4[(t1 >> (1 + 8 )) & 0xf] << 2)
250 | (pc1_d_4[(t1 >> (1 + 8 + 8 )) & 0xf] << 1)
251 | (pc1_d_4[(t1 >> (1 + 8 + 8 + 8)) & 0xf] << 0);
252
253 for (i = 0; i < 16; i++) {
254 uint32_t kc, kd;
255
256 ROTATE_LEFT28(c, shifts[i]);
257 ROTATE_LEFT28(d, shifts[i]);
258
259 kc = pc2_c_1[(c >> 22) & 0x3f] |
260 pc2_c_2[((c >> 16) & 0x30) | ((c >> 15) & 0xf)] |
261 pc2_c_3[((c >> 9 ) & 0x3c) | ((c >> 8 ) & 0x3)] |
262 pc2_c_4[((c >> 2 ) & 0x20) | ((c >> 1) & 0x18) | (c & 0x7)];
263 kd = pc2_d_1[(d >> 22) & 0x3f] |
264 pc2_d_2[((d >> 15) & 0x30) | ((d >> 14) & 0xf)] |
265 pc2_d_3[ (d >> 7 ) & 0x3f] |
266 pc2_d_4[((d >> 1 ) & 0x3c) | ((d ) & 0x3)];
267
268 /* Change to byte order used by the S boxes */
269 *k = (kc & 0x00fc0000L) << 6;
270 *k |= (kc & 0x00000fc0L) << 10;
271 *k |= (kd & 0x00fc0000L) >> 10;
272 *k++ |= (kd & 0x00000fc0L) >> 6;
273 *k = (kc & 0x0003f000L) << 12;
274 *k |= (kc & 0x0000003fL) << 16;
275 *k |= (kd & 0x0003f000L) >> 4;
276 *k++ |= (kd & 0x0000003fL);
277 }
278
279 return 0;
280}
281
282/**
283 * Just like DES_set_key_unchecked() except checking that the key is
284 * not weak for or have correct parity.
285 *
286 * @param key a key to initialize the key schedule with.
287 * @param ks a key schedule to initialize.
288 *
289 * @return 0 on success, -1 on invalid parity, -2 on weak key.
290 * @ingroup hcrypto_des
291 */
292
293int
294DES_set_key_checked(DES_cblock *key, DES_key_schedule *ks)
295{
296 if (!DES_check_key_parity(key)) {
297 memset(ks, 0, sizeof(*ks));
298 return -1;
299 }
300 if (DES_is_weak_key(key)) {
301 memset(ks, 0, sizeof(*ks));
302 return -2;
303 }
304 return DES_set_key_unchecked(key, ks);
305}
306
307/**
308 * Compatibility function for eay libdes, works just like
309 * DES_set_key_checked().
310 *
311 * @param key a key to initialize the key schedule with.
312 * @param ks a key schedule to initialize.
313 *
314 * @return 0 on success, -1 on invalid parity, -2 on weak key.
315 * @ingroup hcrypto_des
316 */
317
318int
319DES_key_sched(DES_cblock *key, DES_key_schedule *ks)
320{
321 return DES_set_key_checked(key, ks);
322}
323
324/*
325 *
326 */
327
328static void
329load(const unsigned char *b, uint32_t v[2])
330{
331 v[0] = b[0] << 24;
332 v[0] |= b[1] << 16;
333 v[0] |= b[2] << 8;
334 v[0] |= b[3] << 0;
335 v[1] = b[4] << 24;
336 v[1] |= b[5] << 16;
337 v[1] |= b[6] << 8;
338 v[1] |= b[7] << 0;
339}
340
341static void
342store(const uint32_t v[2], unsigned char *b)
343{
344 b[0] = (v[0] >> 24) & 0xff;
345 b[1] = (v[0] >> 16) & 0xff;
346 b[2] = (v[0] >> 8) & 0xff;
347 b[3] = (v[0] >> 0) & 0xff;
348 b[4] = (v[1] >> 24) & 0xff;
349 b[5] = (v[1] >> 16) & 0xff;
350 b[6] = (v[1] >> 8) & 0xff;
351 b[7] = (v[1] >> 0) & 0xff;
352}
353
354/**
355 * Encrypt/decrypt a block using DES. Also called ECB mode
356 *
357 * @param u data to encrypt
358 * @param ks key schedule to use
359 * @param encp if non zero, encrypt. if zero, decrypt.
360 *
361 * @ingroup hcrypto_des
362 */
363
364void
365DES_encrypt(uint32_t u[2], DES_key_schedule *ks, int encp)
366{
367 IP(u);
368 desx(u, ks, encp);
369 FP(u);
370}
371
372/**
373 * Encrypt/decrypt a block using DES.
374 *
375 * @param input data to encrypt
376 * @param output data to encrypt
377 * @param ks key schedule to use
378 * @param encp if non zero, encrypt. if zero, decrypt.
379 *
380 * @ingroup hcrypto_des
381 */
382
383void
384DES_ecb_encrypt(DES_cblock *input, DES_cblock *output,
385 DES_key_schedule *ks, int encp)
386{
387 uint32_t u[2];
388 load(*input, u);
389 DES_encrypt(u, ks, encp);
390 store(u, *output);
391}
392
393/**
394 * Encrypt/decrypt a block using DES in Chain Block Cipher mode (cbc).
395 *
396 * The IV must always be diffrent for diffrent input data blocks.
397 *
398 * @param in data to encrypt
399 * @param out data to encrypt
400 * @param length length of data
401 * @param ks key schedule to use
402 * @param iv initial vector to use
403 * @param encp if non zero, encrypt. if zero, decrypt.
404 *
405 * @ingroup hcrypto_des
406 */
407
408void
409DES_cbc_encrypt(const void *in, void *out, long length,
410 DES_key_schedule *ks, DES_cblock *iv, int encp)
411{
412 const unsigned char *input = in;
413 unsigned char *output = out;
414 uint32_t u[2];
415 uint32_t uiv[2];
416
417 load(*iv, uiv);
418
419 if (encp) {
420 while (length >= DES_CBLOCK_LEN) {
421 load(input, u);
422 u[0] ^= uiv[0]; u[1] ^= uiv[1];
423 DES_encrypt(u, ks, 1);
424 uiv[0] = u[0]; uiv[1] = u[1];
425 store(u, output);
426
427 length -= DES_CBLOCK_LEN;
428 input += DES_CBLOCK_LEN;
429 output += DES_CBLOCK_LEN;
430 }
431 if (length) {
432 unsigned char tmp[DES_CBLOCK_LEN];
433 memcpy(tmp, input, length);
434 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
435 load(tmp, u);
436 u[0] ^= uiv[0]; u[1] ^= uiv[1];
437 DES_encrypt(u, ks, 1);
438 store(u, output);
439 }
440 } else {
441 uint32_t t[2];
442 while (length >= DES_CBLOCK_LEN) {
443 load(input, u);
444 t[0] = u[0]; t[1] = u[1];
445 DES_encrypt(u, ks, 0);
446 u[0] ^= uiv[0]; u[1] ^= uiv[1];
447 store(u, output);
448 uiv[0] = t[0]; uiv[1] = t[1];
449
450 length -= DES_CBLOCK_LEN;
451 input += DES_CBLOCK_LEN;
452 output += DES_CBLOCK_LEN;
453 }
454 if (length) {
455 unsigned char tmp[DES_CBLOCK_LEN];
456 memcpy(tmp, input, length);
457 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
458 load(tmp, u);
459 DES_encrypt(u, ks, 0);
460 u[0] ^= uiv[0]; u[1] ^= uiv[1];
461 store(u, output);
462 }
463 }
464 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
465}
466
467/**
468 * Encrypt/decrypt a block using DES in Propagating Cipher Block
469 * Chaining mode. This mode is only used for Kerberos 4, and it should
470 * stay that way.
471 *
472 * The IV must always be diffrent for diffrent input data blocks.
473 *
474 * @param in data to encrypt
475 * @param out data to encrypt
476 * @param length length of data
477 * @param ks key schedule to use
478 * @param iv initial vector to use
479 * @param encp if non zero, encrypt. if zero, decrypt.
480 *
481 * @ingroup hcrypto_des
482 */
483
484void
485DES_pcbc_encrypt(const void *in, void *out, long length,
486 DES_key_schedule *ks, DES_cblock *iv, int encp)
487{
488 const unsigned char *input = in;
489 unsigned char *output = out;
490 uint32_t u[2];
491 uint32_t uiv[2];
492
493 load(*iv, uiv);
494
495 if (encp) {
496 uint32_t t[2];
497 while (length >= DES_CBLOCK_LEN) {
498 load(input, u);
499 t[0] = u[0]; t[1] = u[1];
500 u[0] ^= uiv[0]; u[1] ^= uiv[1];
501 DES_encrypt(u, ks, 1);
502 uiv[0] = u[0] ^ t[0]; uiv[1] = u[1] ^ t[1];
503 store(u, output);
504
505 length -= DES_CBLOCK_LEN;
506 input += DES_CBLOCK_LEN;
507 output += DES_CBLOCK_LEN;
508 }
509 if (length) {
510 unsigned char tmp[DES_CBLOCK_LEN];
511 memcpy(tmp, input, length);
512 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
513 load(tmp, u);
514 u[0] ^= uiv[0]; u[1] ^= uiv[1];
515 DES_encrypt(u, ks, 1);
516 store(u, output);
517 }
518 } else {
519 uint32_t t[2];
520 while (length >= DES_CBLOCK_LEN) {
521 load(input, u);
522 t[0] = u[0]; t[1] = u[1];
523 DES_encrypt(u, ks, 0);
524 u[0] ^= uiv[0]; u[1] ^= uiv[1];
525 store(u, output);
526 uiv[0] = t[0] ^ u[0]; uiv[1] = t[1] ^ u[1];
527
528 length -= DES_CBLOCK_LEN;
529 input += DES_CBLOCK_LEN;
530 output += DES_CBLOCK_LEN;
531 }
532 if (length) {
533 unsigned char tmp[DES_CBLOCK_LEN];
534 memcpy(tmp, input, length);
535 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
536 load(tmp, u);
537 DES_encrypt(u, ks, 0);
538 u[0] ^= uiv[0]; u[1] ^= uiv[1];
539 }
540 }
541 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
542}
543
544/*
545 *
546 */
547
548static void
549_des3_encrypt(uint32_t u[2], DES_key_schedule *ks1, DES_key_schedule *ks2,
550 DES_key_schedule *ks3, int encp)
551{
552 IP(u);
553 if (encp) {
554 desx(u, ks1, 1); /* IP + FP cancel out each other */
555 desx(u, ks2, 0);
556 desx(u, ks3, 1);
557 } else {
558 desx(u, ks3, 0);
559 desx(u, ks2, 1);
560 desx(u, ks1, 0);
561 }
562 FP(u);
563}
564
565/**
566 * Encrypt/decrypt a block using triple DES using EDE mode,
567 * encrypt/decrypt/encrypt.
568 *
569 * @param input data to encrypt
570 * @param output data to encrypt
571 * @param ks1 key schedule to use
572 * @param ks2 key schedule to use
573 * @param ks3 key schedule to use
574 * @param encp if non zero, encrypt. if zero, decrypt.
575 *
576 * @ingroup hcrypto_des
577 */
578
579void
580DES_ecb3_encrypt(DES_cblock *input,
581 DES_cblock *output,
582 DES_key_schedule *ks1,
583 DES_key_schedule *ks2,
584 DES_key_schedule *ks3,
585 int encp)
586{
587 uint32_t u[2];
588 load(*input, u);
589 _des3_encrypt(u, ks1, ks2, ks3, encp);
590 store(u, *output);
591 return;
592}
593
594/**
595 * Encrypt/decrypt using Triple DES in Chain Block Cipher mode (cbc).
596 *
597 * The IV must always be diffrent for diffrent input data blocks.
598 *
599 * @param in data to encrypt
600 * @param out data to encrypt
601 * @param length length of data
602 * @param ks1 key schedule to use
603 * @param ks2 key schedule to use
604 * @param ks3 key schedule to use
605 * @param iv initial vector to use
606 * @param encp if non zero, encrypt. if zero, decrypt.
607 *
608 * @ingroup hcrypto_des
609 */
610
611void
612DES_ede3_cbc_encrypt(const void *in, void *out,
613 long length, DES_key_schedule *ks1,
614 DES_key_schedule *ks2, DES_key_schedule *ks3,
615 DES_cblock *iv, int encp)
616{
617 const unsigned char *input = in;
618 unsigned char *output = out;
619 uint32_t u[2];
620 uint32_t uiv[2];
621
622 load(*iv, uiv);
623
624 if (encp) {
625 while (length >= DES_CBLOCK_LEN) {
626 load(input, u);
627 u[0] ^= uiv[0]; u[1] ^= uiv[1];
628 _des3_encrypt(u, ks1, ks2, ks3, 1);
629 uiv[0] = u[0]; uiv[1] = u[1];
630 store(u, output);
631
632 length -= DES_CBLOCK_LEN;
633 input += DES_CBLOCK_LEN;
634 output += DES_CBLOCK_LEN;
635 }
636 if (length) {
637 unsigned char tmp[DES_CBLOCK_LEN];
638 memcpy(tmp, input, length);
639 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
640 load(tmp, u);
641 u[0] ^= uiv[0]; u[1] ^= uiv[1];
642 _des3_encrypt(u, ks1, ks2, ks3, 1);
643 store(u, output);
644 }
645 } else {
646 uint32_t t[2];
647 while (length >= DES_CBLOCK_LEN) {
648 load(input, u);
649 t[0] = u[0]; t[1] = u[1];
650 _des3_encrypt(u, ks1, ks2, ks3, 0);
651 u[0] ^= uiv[0]; u[1] ^= uiv[1];
652 store(u, output);
653 uiv[0] = t[0]; uiv[1] = t[1];
654
655 length -= DES_CBLOCK_LEN;
656 input += DES_CBLOCK_LEN;
657 output += DES_CBLOCK_LEN;
658 }
659 if (length) {
660 unsigned char tmp[DES_CBLOCK_LEN];
661 memcpy(tmp, input, length);
662 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
663 load(tmp, u);
664 _des3_encrypt(u, ks1, ks2, ks3, 0);
665 u[0] ^= uiv[0]; u[1] ^= uiv[1];
666 store(u, output);
667 }
668 }
669 store(uiv, *iv);
670 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
671}
672
673/**
674 * Encrypt/decrypt using DES in cipher feedback mode with 64 bit
675 * feedback.
676 *
677 * The IV must always be diffrent for diffrent input data blocks.
678 *
679 * @param in data to encrypt
680 * @param out data to encrypt
681 * @param length length of data
682 * @param ks key schedule to use
683 * @param iv initial vector to use
684 * @param num offset into in cipher block encryption/decryption stop last time.
685 * @param encp if non zero, encrypt. if zero, decrypt.
686 *
687 * @ingroup hcrypto_des
688 */
689
690void
691DES_cfb64_encrypt(const void *in, void *out,
692 long length, DES_key_schedule *ks, DES_cblock *iv,
693 int *num, int encp)
694{
695 const unsigned char *input = in;
696 unsigned char *output = out;
697 unsigned char tmp[DES_CBLOCK_LEN];
698 uint32_t uiv[2];
699
700 load(*iv, uiv);
701
702 assert(*num >= 0 && *num < DES_CBLOCK_LEN);
703
704 if (encp) {
705 int i = *num;
706
707 while (length > 0) {
708 if (i == 0)
709 DES_encrypt(uiv, ks, 1);
710 store(uiv, tmp);
711 for (; i < DES_CBLOCK_LEN && i < length; i++) {
712 output[i] = tmp[i] ^ input[i];
713 }
714 if (i == DES_CBLOCK_LEN)
715 load(output, uiv);
716 output += i;
717 input += i;
718 length -= i;
719 if (i == DES_CBLOCK_LEN)
720 i = 0;
721 }
722 store(uiv, *iv);
723 *num = i;
724 } else {
725 int i = *num;
726 unsigned char c;
727
728 while (length > 0) {
729 if (i == 0) {
730 DES_encrypt(uiv, ks, 1);
731 store(uiv, tmp);
732 }
733 for (; i < DES_CBLOCK_LEN && i < length; i++) {
734 c = input[i];
735 output[i] = tmp[i] ^ input[i];
736 (*iv)[i] = c;
737 }
738 output += i;
739 input += i;
740 length -= i;
741 if (i == DES_CBLOCK_LEN) {
742 i = 0;
743 load(*iv, uiv);
744 }
745 }
746 store(uiv, *iv);
747 *num = i;
748 }
749}
750
751/**
752 * Crete a checksum using DES in CBC encryption mode. This mode is
753 * only used for Kerberos 4, and it should stay that way.
754 *
755 * The IV must always be diffrent for diffrent input data blocks.
756 *
757 * @param in data to checksum
758 * @param output the checksum
759 * @param length length of data
760 * @param ks key schedule to use
761 * @param iv initial vector to use
762 *
763 * @ingroup hcrypto_des
764 */
765
766uint32_t
767DES_cbc_cksum(const void *in, DES_cblock *output,
768 long length, DES_key_schedule *ks, DES_cblock *iv)
769{
770 const unsigned char *input = in;
771 uint32_t uiv[2];
772 uint32_t u[2] = { 0, 0 };
773
774 load(*iv, uiv);
775
776 while (length >= DES_CBLOCK_LEN) {
777 load(input, u);
778 u[0] ^= uiv[0]; u[1] ^= uiv[1];
779 DES_encrypt(u, ks, 1);
780 uiv[0] = u[0]; uiv[1] = u[1];
781
782 length -= DES_CBLOCK_LEN;
783 input += DES_CBLOCK_LEN;
784 }
785 if (length) {
786 unsigned char tmp[DES_CBLOCK_LEN];
787 memcpy(tmp, input, length);
788 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
789 load(tmp, u);
790 u[0] ^= uiv[0]; u[1] ^= uiv[1];
791 DES_encrypt(u, ks, 1);
792 }
793 if (output)
794 store(u, *output);
795
796 uiv[0] = 0; u[0] = 0; uiv[1] = 0;
797 return u[1];
798}
799
800/*
801 *
802 */
803
804static unsigned char
805bitswap8(unsigned char b)
806{
807 unsigned char r = 0;
808 int i;
809 for (i = 0; i < 8; i++) {
810 r = r << 1 | (b & 1);
811 b = b >> 1;
812 }
813 return r;
814}
815
816/**
817 * Convert a string to a DES key. Use something like
818 * PKCS5_PBKDF2_HMAC_SHA1() to create key from passwords.
819 *
820 * @param str The string to convert to a key
821 * @param key the resulting key
822 *
823 * @ingroup hcrypto_des
824 */
825
826void
827DES_string_to_key(const char *str, DES_cblock *key)
828{
829 const unsigned char *s;
830 unsigned char *k;
831 DES_key_schedule ks;
832 size_t i, len;
833
834 memset(key, 0, sizeof(*key));
835 k = *key;
836 s = (const unsigned char *)str;
837
838 len = strlen(str);
839 for (i = 0; i < len; i++) {
840 if ((i % 16) < 8)
841 k[i % 8] ^= s[i] << 1;
842 else
843 k[7 - (i % 8)] ^= bitswap8(s[i]);
844 }
845 DES_set_odd_parity(key);
846 if (DES_is_weak_key(key))
847 k[7] ^= 0xF0;
848 DES_set_key(key, &ks);
849 DES_cbc_cksum(s, key, len, &ks, key);
850 memset(&ks, 0, sizeof(ks));
851 DES_set_odd_parity(key);
852 if (DES_is_weak_key(key))
853 k[7] ^= 0xF0;
854}
855
856/**
857 * Read password from prompt and create a DES key. Internal uses
858 * DES_string_to_key(). Really, go use a really string2key function
859 * like PKCS5_PBKDF2_HMAC_SHA1().
860 *
861 * @param key key to convert to
862 * @param prompt prompt to display user
863 * @param verify prompt twice.
864 *
865 * @return 1 on success, non 1 on failure.
866 */
867
868int
869DES_read_password(DES_cblock *key, char *prompt, int verify)
870{
871 char buf[512];
872 int ret;
873
874 ret = UI_UTIL_read_pw_string(buf, sizeof(buf) - 1, prompt, verify);
875 if (ret == 1)
876 DES_string_to_key(buf, key);
877 return ret;
878}
879
880/*
881 *
882 */
883
884
885void
886_DES_ipfp_test(void)
887{
888 DES_cblock k = "\x01\x02\x04\x08\x10\x20\x40\x80", k2;
889 uint32_t u[2] = { 1, 0 };
890 IP(u);
891 FP(u);
892 IP(u);
893 FP(u);
894 if (u[0] != 1 || u[1] != 0)
895 abort();
896
897 load(k, u);
898 store(u, k2);
899 if (memcmp(k, k2, 8) != 0)
900 abort();
901}
902
903/* D3DES (V5.09) -
904 *
905 * A portable, public domain, version of the Data Encryption Standard.
906 *
907 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
908 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
909 * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
910 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
911 * for humouring me on.
912 *
913 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
914 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
915 */
916
917static uint32_t SP1[64] = {
918 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
919 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
920 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
921 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
922 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
923 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
924 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
925 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
926 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
927 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
928 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
929 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
930 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
931 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
932 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
933 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
934
935static uint32_t SP2[64] = {
936 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
937 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
938 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
939 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
940 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
941 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
942 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
943 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
944 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
945 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
946 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
947 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
948 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
949 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
950 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
951 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
952
953static uint32_t SP3[64] = {
954 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
955 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
956 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
957 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
958 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
959 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
960 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
961 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
962 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
963 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
964 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
965 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
966 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
967 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
968 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
969 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
970
971static uint32_t SP4[64] = {
972 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
973 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
974 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
975 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
976 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
977 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
978 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
979 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
980 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
981 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
982 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
983 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
984 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
985 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
986 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
987 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
988
989static uint32_t SP5[64] = {
990 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
991 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
992 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
993 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
994 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
995 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
996 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
997 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
998 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
999 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
1000 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
1001 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
1002 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
1003 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
1004 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
1005 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
1006
1007static uint32_t SP6[64] = {
1008 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
1009 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
1010 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
1011 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
1012 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
1013 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
1014 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
1015 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
1016 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
1017 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
1018 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
1019 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
1020 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
1021 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
1022 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
1023 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
1024
1025static uint32_t SP7[64] = {
1026 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
1027 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
1028 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
1029 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
1030 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
1031 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
1032 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
1033 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
1034 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
1035 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
1036 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
1037 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
1038 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
1039 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
1040 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
1041 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
1042
1043static uint32_t SP8[64] = {
1044 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
1045 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
1046 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
1047 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
1048 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
1049 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
1050 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
1051 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
1052 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
1053 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
1054 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
1055 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
1056 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
1057 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
1058 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
1059 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
1060
1061static void
1062IP(uint32_t v[2])
1063{
1064 uint32_t work;
1065
1066 work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
1067 v[1] ^= work;
1068 v[0] ^= (work << 4);
1069 work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
1070 v[1] ^= work;
1071 v[0] ^= (work << 16);
1072 work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
1073 v[0] ^= work;
1074 v[1] ^= (work << 2);
1075 work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
1076 v[0] ^= work;
1077 v[1] ^= (work << 8);
1078 v[1] = ((v[1] << 1) | ((v[1] >> 31) & 1L)) & 0xffffffffL;
1079 work = (v[0] ^ v[1]) & 0xaaaaaaaaL;
1080 v[0] ^= work;
1081 v[1] ^= work;
1082 v[0] = ((v[0] << 1) | ((v[0] >> 31) & 1L)) & 0xffffffffL;
1083}
1084
1085static void
1086FP(uint32_t v[2])
1087{
1088 uint32_t work;
1089
1090 v[0] = (v[0] << 31) | (v[0] >> 1);
1091 work = (v[1] ^ v[0]) & 0xaaaaaaaaL;
1092 v[1] ^= work;
1093 v[0] ^= work;
1094 v[1] = (v[1] << 31) | (v[1] >> 1);
1095 work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
1096 v[0] ^= work;
1097 v[1] ^= (work << 8);
1098 work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
1099 v[0] ^= work;
1100 v[1] ^= (work << 2);
1101 work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
1102 v[1] ^= work;
1103 v[0] ^= (work << 16);
1104 work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
1105 v[1] ^= work;
1106 v[0] ^= (work << 4);
1107}
1108
1109static void
1110desx(uint32_t block[2], DES_key_schedule *ks, int encp)
1111{
1112 uint32_t *keys;
1113 uint32_t fval, work, right, left;
1114 int round;
1115
1116 left = block[0];
1117 right = block[1];
1118
1119 if (encp) {
1120 keys = &ks->ks[0];
1121
1122 for( round = 0; round < 8; round++ ) {
1123 work = (right << 28) | (right >> 4);
1124 work ^= *keys++;
1125 fval = SP7[ work & 0x3fL];
1126 fval |= SP5[(work >> 8) & 0x3fL];
1127 fval |= SP3[(work >> 16) & 0x3fL];
1128 fval |= SP1[(work >> 24) & 0x3fL];
1129 work = right ^ *keys++;
1130 fval |= SP8[ work & 0x3fL];
1131 fval |= SP6[(work >> 8) & 0x3fL];
1132 fval |= SP4[(work >> 16) & 0x3fL];
1133 fval |= SP2[(work >> 24) & 0x3fL];
1134 left ^= fval;
1135 work = (left << 28) | (left >> 4);
1136 work ^= *keys++;
1137 fval = SP7[ work & 0x3fL];
1138 fval |= SP5[(work >> 8) & 0x3fL];
1139 fval |= SP3[(work >> 16) & 0x3fL];
1140 fval |= SP1[(work >> 24) & 0x3fL];
1141 work = left ^ *keys++;
1142 fval |= SP8[ work & 0x3fL];
1143 fval |= SP6[(work >> 8) & 0x3fL];
1144 fval |= SP4[(work >> 16) & 0x3fL];
1145 fval |= SP2[(work >> 24) & 0x3fL];
1146 right ^= fval;
1147 }
1148 } else {
1149 keys = &ks->ks[30];
1150
1151 for( round = 0; round < 8; round++ ) {
1152 work = (right << 28) | (right >> 4);
1153 work ^= *keys++;
1154 fval = SP7[ work & 0x3fL];
1155 fval |= SP5[(work >> 8) & 0x3fL];
1156 fval |= SP3[(work >> 16) & 0x3fL];
1157 fval |= SP1[(work >> 24) & 0x3fL];
1158 work = right ^ *keys++;
1159 fval |= SP8[ work & 0x3fL];
1160 fval |= SP6[(work >> 8) & 0x3fL];
1161 fval |= SP4[(work >> 16) & 0x3fL];
1162 fval |= SP2[(work >> 24) & 0x3fL];
1163 left ^= fval;
1164 work = (left << 28) | (left >> 4);
1165 keys -= 4;
1166 work ^= *keys++;
1167 fval = SP7[ work & 0x3fL];
1168 fval |= SP5[(work >> 8) & 0x3fL];
1169 fval |= SP3[(work >> 16) & 0x3fL];
1170 fval |= SP1[(work >> 24) & 0x3fL];
1171 work = left ^ *keys++;
1172 fval |= SP8[ work & 0x3fL];
1173 fval |= SP6[(work >> 8) & 0x3fL];
1174 fval |= SP4[(work >> 16) & 0x3fL];
1175 fval |= SP2[(work >> 24) & 0x3fL];
1176 right ^= fval;
1177 keys -= 4;
1178 }
1179 }
1180 block[0] = right;
1181 block[1] = left;
1182}
Note: See TracBrowser for help on using the repository browser.