Commit | Line | Data |
---|---|---|
44a1bce2 AM |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Matt Bishop of Dartmouth College. | |
7 | * | |
8 | * The United States Government has rights in this work pursuant | |
9 | * to contract no. NAG 2-680 between the National Aeronautics and | |
10 | * Space Administration and Dartmouth College. | |
11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions and the following disclaimer. | |
17 | * 2. Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * 3. All advertising materials mentioning features or use of this software | |
21 | * must display the following acknowledgement: | |
22 | * This product includes software developed by the University of | |
23 | * California, Berkeley and its contributors. | |
24 | * 4. Neither the name of the University nor the names of its contributors | |
25 | * may be used to endorse or promote products derived from this software | |
26 | * without specific prior written permission. | |
27 | * | |
28 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
38 | * SUCH DAMAGE. | |
39 | */ | |
40 | ||
41 | #ifndef lint | |
42 | char copyright[] = | |
43 | "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ | |
44 | All rights reserved.\n"; | |
45 | #endif /* not lint */ | |
46 | ||
47 | #ifndef lint | |
48 | static char sccsid[] = "@(#)bdes.c 5.5 (Berkeley) 6/27/91"; | |
49 | #endif /* not lint */ | |
50 | ||
51 | /* | |
52 | * BDES -- DES encryption package for Berkeley Software Distribution 4.4 | |
53 | * options: | |
54 | * -a key is in ASCII | |
55 | * -b use ECB (electronic code book) mode | |
56 | * -d invert (decrypt) input | |
57 | * -f b use b-bit CFB (cipher feedback) mode | |
58 | * -F b use b-bit CFB (cipher feedback) alternative mode | |
59 | * -k key use key as the cryptographic key | |
60 | * -m b generate a MAC of length b | |
61 | * -o b use b-bit OFB (output feedback) mode | |
62 | * -p don't reset the parity bit | |
63 | * -v v use v as the initialization vector (ignored for ECB) | |
64 | * note: the last character of the last block is the integer indicating | |
65 | * how many characters of that block are to be output | |
66 | * | |
67 | * Author: Matt Bishop | |
68 | * Department of Mathematics and Computer Science | |
69 | * Dartmouth College | |
70 | * Hanover, NH 03755 | |
71 | * Email: Matt.Bishop@dartmouth.edu | |
72 | * ...!decvax!dartvax!Matt.Bishop | |
73 | * | |
74 | * See Technical Report PCS-TR91-158, Department of Mathematics and Computer | |
75 | * Science, Dartmouth College, for a detailed description of the implemen- | |
76 | * tation and differences between it and Sun's. The DES is described in | |
77 | * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page | |
78 | * or the technical report for a complete reference). | |
79 | */ | |
80 | ||
406810fb AM |
81 | #include <errno.h> |
82 | #include <unistd.h> | |
83 | #include <stdio.h> | |
84 | #include <ctype.h> | |
85 | #include <stdlib.h> | |
86 | #include <string.h> | |
87 | ||
44a1bce2 AM |
88 | #ifndef DES |
89 | main() | |
90 | { | |
91 | fprintf(stderr, "Crypt not available\n"); | |
92 | _exit(1); | |
93 | } | |
94 | #else | |
95 | ||
44a1bce2 AM |
96 | /* |
97 | * BSD and System V systems offer special library calls that do | |
98 | * block moves and fills, so if possible we take advantage of them | |
99 | */ | |
100 | #define MEMCPY(dest,src,len) bcopy((src),(dest),(len)) | |
101 | #define MEMZERO(dest,len) bzero((dest),(len)) | |
102 | ||
103 | /* Hide the calls to the primitive encryption routines. */ | |
104 | #define FASTWAY | |
105 | #ifdef FASTWAY | |
106 | #define DES_KEY(buf) \ | |
107 | if (des_setkey(buf)) \ | |
108 | err("des_setkey", 0); | |
109 | #define DES_XFORM(buf) \ | |
110 | if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \ | |
111 | err("des_cipher", 0); | |
112 | #else | |
113 | #define DES_KEY(buf) { \ | |
114 | char bits1[64]; /* bits of key */ \ | |
115 | expand(buf, bits1); \ | |
116 | if (setkey(bits1)) \ | |
117 | err("setkey", 0); \ | |
118 | } | |
119 | #define DES_XFORM(buf) { \ | |
120 | char bits1[64]; /* bits of message */ \ | |
121 | expand(buf, bits1); \ | |
122 | if (encrypt(bits1, inverse)) \ | |
123 | err("encrypt", 0); \ | |
124 | compress(bits1, buf); \ | |
125 | } | |
126 | #endif | |
127 | ||
128 | /* | |
129 | * this does an error-checking write | |
130 | */ | |
131 | #define READ(buf, n) fread(buf, sizeof(char), n, stdin) | |
132 | #define WRITE(buf,n) \ | |
133 | if (fwrite(buf, sizeof(char), n, stdout) != n) \ | |
134 | err(bn, NULL); | |
135 | ||
136 | /* | |
137 | * some things to make references easier | |
138 | */ | |
139 | typedef char Desbuf[8]; | |
140 | #define CHAR(x,i) (x[i]) | |
141 | #define UCHAR(x,i) (x[i]) | |
142 | #define BUFFER(x) (x) | |
143 | #define UBUFFER(x) (x) | |
144 | ||
145 | /* | |
146 | * global variables and related macros | |
147 | */ | |
148 | #define KEY_DEFAULT 0 /* interpret radix of key from key */ | |
149 | #define KEY_ASCII 1 /* key is in ASCII characters */ | |
150 | int keybase = KEY_DEFAULT; /* how to interpret the key */ | |
151 | ||
152 | enum { /* encrypt, decrypt, authenticate */ | |
153 | MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE | |
154 | } mode = MODE_ENCRYPT; | |
155 | enum { /* ecb, cbc, cfb, cfba, ofb? */ | |
156 | ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA | |
157 | } alg = ALG_CBC; | |
158 | ||
159 | Desbuf ivec; /* initialization vector */ | |
160 | char bits[] = { /* used to extract bits from a char */ | |
161 | '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' | |
162 | }; | |
163 | int inverse; /* 0 to encrypt, 1 to decrypt */ | |
164 | int macbits = -1; /* number of bits in authentication */ | |
165 | int fbbits = -1; /* number of feedback bits */ | |
166 | int pflag; /* 1 to preserve parity bits */ | |
167 | ||
168 | main(ac, av) | |
169 | int ac; /* arg count */ | |
170 | char **av; /* arg vector */ | |
171 | { | |
172 | extern int optind; /* option (argument) number */ | |
173 | extern char *optarg; /* argument to option if any */ | |
174 | register int i; /* counter in a for loop */ | |
175 | register char *p; /* used to obtain the key */ | |
176 | Desbuf msgbuf; /* I/O buffer */ | |
177 | int kflag; /* command-line encryptiooon key */ | |
178 | int argc; /* the real arg count */ | |
179 | char **argv; /* the real argument vector */ | |
180 | ||
181 | /* | |
182 | * Hide the arguments from ps(1) by making private copies of them | |
183 | * and clobbering the global (visible to ps(1)) ones. | |
184 | */ | |
185 | argc = ac; | |
186 | ac = 1; | |
187 | argv = malloc((argc + 1) * sizeof(char *)); | |
188 | for (i = 0; i < argc; ++i) { | |
189 | argv[i] = strdup(av[i]); | |
190 | MEMZERO(av[i], strlen(av[i])); | |
191 | } | |
192 | argv[argc] = NULL; | |
193 | ||
194 | /* initialize the initialization vctor */ | |
195 | MEMZERO(ivec, 8); | |
196 | ||
197 | /* process the argument list */ | |
198 | kflag = 0; | |
199 | while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != EOF) | |
200 | switch(i) { | |
201 | case 'a': /* key is ASCII */ | |
202 | keybase = KEY_ASCII; | |
203 | break; | |
204 | case 'b': /* use ECB mode */ | |
205 | alg = ALG_ECB; | |
206 | break; | |
207 | case 'd': /* decrypt */ | |
208 | mode = MODE_DECRYPT; | |
209 | break; | |
210 | case 'F': /* use alternative CFB mode */ | |
211 | alg = ALG_CFBA; | |
212 | if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0) | |
213 | err(-1, "-F: number must be 1-56 inclusive"); | |
214 | else if (fbbits == -1) | |
215 | err(-1, "-F: number must be a multiple of 7"); | |
216 | break; | |
217 | case 'f': /* use CFB mode */ | |
218 | alg = ALG_CFB; | |
219 | if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) | |
220 | err(-1, "-f: number must be 1-64 inclusive"); | |
221 | else if (fbbits == -1) | |
222 | err(-1, "-f: number must be a multiple of 8"); | |
223 | break; | |
224 | case 'k': /* encryption key */ | |
225 | kflag = 1; | |
226 | cvtkey(BUFFER(msgbuf), optarg); | |
227 | break; | |
228 | case 'm': /* number of bits for MACing */ | |
229 | mode = MODE_AUTHENTICATE; | |
230 | if ((macbits = setbits(optarg, 1)) > 64) | |
231 | err(-1, "-m: number must be 0-64 inclusive"); | |
232 | break; | |
233 | case 'o': /* use OFB mode */ | |
234 | alg = ALG_OFB; | |
235 | if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) | |
236 | err(-1, "-o: number must be 1-64 inclusive"); | |
237 | else if (fbbits == -1) | |
238 | err(-1, "-o: number must be a multiple of 8"); | |
239 | break; | |
240 | case 'p': /* preserve parity bits */ | |
241 | pflag = 1; | |
242 | break; | |
243 | case 'v': /* set initialization vector */ | |
244 | cvtkey(BUFFER(ivec), optarg); | |
245 | break; | |
246 | default: /* error */ | |
247 | usage(); | |
248 | } | |
249 | ||
250 | if (!kflag) { | |
251 | /* | |
252 | * if the key's not ASCII, assume it is | |
253 | */ | |
254 | keybase = KEY_ASCII; | |
255 | /* | |
256 | * get the key | |
257 | */ | |
258 | p = getpass("Enter key: "); | |
259 | /* | |
260 | * copy it, nul-padded, into the key area | |
261 | */ | |
262 | cvtkey(BUFFER(msgbuf), p); | |
263 | } | |
264 | ||
265 | makekey(msgbuf); | |
266 | inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT; | |
267 | ||
268 | switch(alg) { | |
269 | case ALG_CBC: | |
270 | switch(mode) { | |
271 | case MODE_AUTHENTICATE: /* authenticate using CBC mode */ | |
272 | cbcauth(); | |
273 | break; | |
274 | case MODE_DECRYPT: /* decrypt using CBC mode */ | |
275 | cbcdec(); | |
276 | break; | |
277 | case MODE_ENCRYPT: /* encrypt using CBC mode */ | |
278 | cbcenc(); | |
279 | break; | |
280 | } | |
281 | break; | |
282 | case ALG_CFB: | |
283 | switch(mode) { | |
284 | case MODE_AUTHENTICATE: /* authenticate using CFB mode */ | |
285 | cfbauth(); | |
286 | break; | |
287 | case MODE_DECRYPT: /* decrypt using CFB mode */ | |
288 | cfbdec(); | |
289 | break; | |
290 | case MODE_ENCRYPT: /* encrypt using CFB mode */ | |
291 | cfbenc(); | |
292 | break; | |
293 | } | |
294 | break; | |
295 | case ALG_CFBA: | |
296 | switch(mode) { | |
297 | case MODE_AUTHENTICATE: /* authenticate using CFBA mode */ | |
298 | err(-1, "can't authenticate with CFBA mode"); | |
299 | break; | |
300 | case MODE_DECRYPT: /* decrypt using CFBA mode */ | |
301 | cfbadec(); | |
302 | break; | |
303 | case MODE_ENCRYPT: /* encrypt using CFBA mode */ | |
304 | cfbaenc(); | |
305 | break; | |
306 | } | |
307 | break; | |
308 | case ALG_ECB: | |
309 | switch(mode) { | |
310 | case MODE_AUTHENTICATE: /* authenticate using ECB mode */ | |
311 | err(-1, "can't authenticate with ECB mode"); | |
312 | break; | |
313 | case MODE_DECRYPT: /* decrypt using ECB mode */ | |
314 | ecbdec(); | |
315 | break; | |
316 | case MODE_ENCRYPT: /* encrypt using ECB mode */ | |
317 | ecbenc(); | |
318 | break; | |
319 | } | |
320 | break; | |
321 | case ALG_OFB: | |
322 | switch(mode) { | |
323 | case MODE_AUTHENTICATE: /* authenticate using OFB mode */ | |
324 | err(-1, "can't authenticate with OFB mode"); | |
325 | break; | |
326 | case MODE_DECRYPT: /* decrypt using OFB mode */ | |
327 | ofbdec(); | |
328 | break; | |
329 | case MODE_ENCRYPT: /* encrypt using OFB mode */ | |
330 | ofbenc(); | |
331 | break; | |
332 | } | |
333 | break; | |
334 | } | |
335 | exit(0); | |
336 | } | |
337 | ||
338 | /* | |
339 | * print a warning message and, possibly, terminate | |
340 | */ | |
341 | err(n, s) | |
342 | int n; /* offending block number */ | |
343 | char *s; /* the message */ | |
344 | { | |
345 | if (n > 0) | |
346 | (void)fprintf(stderr, "bdes (block %d): ", n); | |
347 | else | |
348 | (void)fprintf(stderr, "bdes: "); | |
349 | (void)fprintf(stderr, "%s\n", s ? s : strerror(errno)); | |
350 | exit(1); | |
351 | } | |
352 | ||
353 | /* | |
354 | * map a hex character to an integer | |
355 | */ | |
356 | tobinhex(c, radix) | |
357 | char c; /* char to be converted */ | |
358 | int radix; /* base (2 to 16) */ | |
359 | { | |
360 | switch(c) { | |
361 | case '0': return(0x0); | |
362 | case '1': return(0x1); | |
363 | case '2': return(radix > 2 ? 0x2 : -1); | |
364 | case '3': return(radix > 3 ? 0x3 : -1); | |
365 | case '4': return(radix > 4 ? 0x4 : -1); | |
366 | case '5': return(radix > 5 ? 0x5 : -1); | |
367 | case '6': return(radix > 6 ? 0x6 : -1); | |
368 | case '7': return(radix > 7 ? 0x7 : -1); | |
369 | case '8': return(radix > 8 ? 0x8 : -1); | |
370 | case '9': return(radix > 9 ? 0x9 : -1); | |
371 | case 'A': case 'a': return(radix > 10 ? 0xa : -1); | |
372 | case 'B': case 'b': return(radix > 11 ? 0xb : -1); | |
373 | case 'C': case 'c': return(radix > 12 ? 0xc : -1); | |
374 | case 'D': case 'd': return(radix > 13 ? 0xd : -1); | |
375 | case 'E': case 'e': return(radix > 14 ? 0xe : -1); | |
376 | case 'F': case 'f': return(radix > 15 ? 0xf : -1); | |
377 | } | |
378 | /* | |
379 | * invalid character | |
380 | */ | |
381 | return(-1); | |
382 | } | |
383 | ||
384 | /* | |
385 | * convert the key to a bit pattern | |
386 | */ | |
387 | cvtkey(obuf, ibuf) | |
388 | char *obuf; /* bit pattern */ | |
389 | char *ibuf; /* the key itself */ | |
390 | { | |
391 | register int i, j; /* counter in a for loop */ | |
392 | int nbuf[64]; /* used for hex/key translation */ | |
393 | ||
394 | /* | |
395 | * just switch on the key base | |
396 | */ | |
397 | switch(keybase) { | |
398 | case KEY_ASCII: /* ascii to integer */ | |
399 | (void)strncpy(obuf, ibuf, 8); | |
400 | return; | |
401 | case KEY_DEFAULT: /* tell from context */ | |
402 | /* | |
403 | * leading '0x' or '0X' == hex key | |
404 | */ | |
405 | if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) { | |
406 | ibuf = &ibuf[2]; | |
407 | /* | |
408 | * now translate it, bombing on any illegal hex digit | |
409 | */ | |
410 | for (i = 0; ibuf[i] && i < 16; i++) | |
411 | if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1) | |
412 | err(-1, "bad hex digit in key"); | |
413 | while (i < 16) | |
414 | nbuf[i++] = 0; | |
415 | for (i = 0; i < 8; i++) | |
416 | obuf[i] = | |
417 | ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf); | |
418 | /* preserve parity bits */ | |
419 | pflag = 1; | |
420 | return; | |
421 | } | |
422 | /* | |
423 | * leading '0b' or '0B' == binary key | |
424 | */ | |
425 | if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) { | |
426 | ibuf = &ibuf[2]; | |
427 | /* | |
428 | * now translate it, bombing on any illegal binary digit | |
429 | */ | |
430 | for (i = 0; ibuf[i] && i < 16; i++) | |
431 | if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1) | |
432 | err(-1, "bad binary digit in key"); | |
433 | while (i < 64) | |
434 | nbuf[i++] = 0; | |
435 | for (i = 0; i < 8; i++) | |
436 | for (j = 0; j < 8; j++) | |
437 | obuf[i] = (obuf[i]<<1)|nbuf[8*i+j]; | |
438 | /* preserve parity bits */ | |
439 | pflag = 1; | |
440 | return; | |
441 | } | |
442 | /* | |
443 | * no special leader -- ASCII | |
444 | */ | |
445 | (void)strncpy(obuf, ibuf, 8); | |
446 | } | |
447 | } | |
448 | ||
449 | /* | |
450 | * convert an ASCII string into a decimal number: | |
451 | * 1. must be between 0 and 64 inclusive | |
452 | * 2. must be a valid decimal number | |
453 | * 3. must be a multiple of mult | |
454 | */ | |
455 | setbits(s, mult) | |
456 | char *s; /* the ASCII string */ | |
457 | int mult; /* what it must be a multiple of */ | |
458 | { | |
459 | register char *p; /* pointer in a for loop */ | |
460 | register int n = 0; /* the integer collected */ | |
461 | ||
462 | /* | |
463 | * skip white space | |
464 | */ | |
465 | while (isspace(*s)) | |
466 | s++; | |
467 | /* | |
468 | * get the integer | |
469 | */ | |
470 | for (p = s; *p; p++) { | |
471 | if (isdigit(*p)) | |
472 | n = n * 10 + *p - '0'; | |
473 | else { | |
474 | err(-1, "bad decimal digit in MAC length"); | |
475 | } | |
476 | } | |
477 | /* | |
478 | * be sure it's a multiple of mult | |
479 | */ | |
480 | return((n % mult != 0) ? -1 : n); | |
481 | } | |
482 | ||
483 | /***************** | |
484 | * DES FUNCTIONS * | |
485 | *****************/ | |
486 | /* | |
487 | * This sets the DES key and (if you're using the deszip version) | |
488 | * the direction of the transformation. This uses the Sun | |
489 | * to map the 64-bit key onto the 56 bits that the key schedule | |
490 | * generation routines use: the old way, which just uses the user- | |
491 | * supplied 64 bits as is, and the new way, which resets the parity | |
492 | * bit to be the same as the low-order bit in each character. The | |
493 | * new way generates a greater variety of key schedules, since many | |
494 | * systems set the parity (high) bit of each character to 0, and the | |
495 | * DES ignores the low order bit of each character. | |
496 | */ | |
497 | makekey(buf) | |
498 | Desbuf buf; /* key block */ | |
499 | { | |
500 | register int i, j; /* counter in a for loop */ | |
501 | register int par; /* parity counter */ | |
502 | ||
503 | /* | |
504 | * if the parity is not preserved, flip it | |
505 | */ | |
506 | if (!pflag) { | |
507 | for (i = 0; i < 8; i++) { | |
508 | par = 0; | |
509 | for (j = 1; j < 8; j++) | |
510 | if ((bits[j]&UCHAR(buf, i)) != 0) | |
511 | par++; | |
512 | if ((par&01) == 01) | |
513 | UCHAR(buf, i) = UCHAR(buf, i)&0177; | |
514 | else | |
515 | UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200; | |
516 | } | |
517 | } | |
518 | ||
519 | DES_KEY(UBUFFER(buf)); | |
520 | } | |
521 | ||
522 | /* | |
523 | * This encrypts using the Electronic Code Book mode of DES | |
524 | */ | |
525 | ecbenc() | |
526 | { | |
527 | register int n; /* number of bytes actually read */ | |
528 | register int bn; /* block number */ | |
529 | Desbuf msgbuf; /* I/O buffer */ | |
530 | ||
531 | for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) { | |
532 | /* | |
533 | * do the transformation | |
534 | */ | |
535 | DES_XFORM(UBUFFER(msgbuf)); | |
536 | WRITE(BUFFER(msgbuf), 8); | |
537 | } | |
538 | /* | |
539 | * at EOF or last block -- in either ase, the last byte contains | |
540 | * the character representation of the number of bytes in it | |
541 | */ | |
542 | bn++; | |
543 | MEMZERO(&CHAR(msgbuf, n), 8 - n); | |
544 | CHAR(msgbuf, 7) = n; | |
545 | DES_XFORM(UBUFFER(msgbuf)); | |
546 | WRITE(BUFFER(msgbuf), 8); | |
547 | ||
548 | } | |
549 | ||
550 | /* | |
551 | * This decrypts using the Electronic Code Book mode of DES | |
552 | */ | |
553 | ecbdec() | |
554 | { | |
555 | register int n; /* number of bytes actually read */ | |
556 | register int c; /* used to test for EOF */ | |
557 | register int bn; /* block number */ | |
558 | Desbuf msgbuf; /* I/O buffer */ | |
559 | ||
560 | for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) { | |
561 | /* | |
562 | * do the transformation | |
563 | */ | |
564 | DES_XFORM(UBUFFER(msgbuf)); | |
565 | /* | |
566 | * if the last one, handle it specially | |
567 | */ | |
568 | if ((c = getchar()) == EOF) { | |
569 | n = CHAR(msgbuf, 7); | |
570 | if (n < 0 || n > 7) | |
571 | err(bn, "decryption failed (block corrupted)"); | |
572 | } | |
573 | else | |
574 | (void)ungetc(c, stdin); | |
575 | WRITE(BUFFER(msgbuf), n); | |
576 | } | |
577 | if (n > 0) | |
578 | err(bn, "decryption failed (incomplete block)"); | |
579 | } | |
580 | ||
581 | /* | |
582 | * This encrypts using the Cipher Block Chaining mode of DES | |
583 | */ | |
584 | cbcenc() | |
585 | { | |
586 | register int n; /* number of bytes actually read */ | |
587 | register int bn; /* block number */ | |
588 | Desbuf msgbuf; /* I/O buffer */ | |
589 | ||
590 | /* | |
591 | * do the transformation | |
592 | */ | |
593 | for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) { | |
594 | for (n = 0; n < 8; n++) | |
595 | CHAR(msgbuf, n) ^= CHAR(ivec, n); | |
596 | DES_XFORM(UBUFFER(msgbuf)); | |
597 | MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8); | |
598 | WRITE(BUFFER(msgbuf), 8); | |
599 | } | |
600 | /* | |
601 | * at EOF or last block -- in either case, the last byte contains | |
602 | * the character representation of the number of bytes in it | |
603 | */ | |
604 | bn++; | |
605 | MEMZERO(&CHAR(msgbuf, n), 8 - n); | |
606 | CHAR(msgbuf, 7) = n; | |
607 | for (n = 0; n < 8; n++) | |
608 | CHAR(msgbuf, n) ^= CHAR(ivec, n); | |
609 | DES_XFORM(UBUFFER(msgbuf)); | |
610 | WRITE(BUFFER(msgbuf), 8); | |
611 | ||
612 | } | |
613 | ||
614 | /* | |
615 | * This decrypts using the Cipher Block Chaining mode of DES | |
616 | */ | |
617 | cbcdec() | |
618 | { | |
619 | register int n; /* number of bytes actually read */ | |
620 | Desbuf msgbuf; /* I/O buffer */ | |
621 | Desbuf ibuf; /* temp buffer for initialization vector */ | |
622 | register int c; /* used to test for EOF */ | |
623 | register int bn; /* block number */ | |
624 | ||
625 | for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) { | |
626 | /* | |
627 | * do the transformation | |
628 | */ | |
629 | MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8); | |
630 | DES_XFORM(UBUFFER(msgbuf)); | |
631 | for (c = 0; c < 8; c++) | |
632 | UCHAR(msgbuf, c) ^= UCHAR(ivec, c); | |
633 | MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8); | |
634 | /* | |
635 | * if the last one, handle it specially | |
636 | */ | |
637 | if ((c = getchar()) == EOF) { | |
638 | n = CHAR(msgbuf, 7); | |
639 | if (n < 0 || n > 7) | |
640 | err(bn, "decryption failed (block corrupted)"); | |
641 | } | |
642 | else | |
643 | (void)ungetc(c, stdin); | |
644 | WRITE(BUFFER(msgbuf), n); | |
645 | } | |
646 | if (n > 0) | |
647 | err(bn, "decryption failed (incomplete block)"); | |
648 | } | |
649 | ||
650 | /* | |
651 | * This authenticates using the Cipher Block Chaining mode of DES | |
652 | */ | |
653 | cbcauth() | |
654 | { | |
655 | register int n, j; /* number of bytes actually read */ | |
656 | Desbuf msgbuf; /* I/O buffer */ | |
657 | Desbuf encbuf; /* encryption buffer */ | |
658 | ||
659 | /* | |
660 | * do the transformation | |
661 | * note we DISCARD the encrypted block; | |
662 | * we only care about the last one | |
663 | */ | |
664 | while ((n = READ(BUFFER(msgbuf), 8)) == 8) { | |
665 | for (n = 0; n < 8; n++) | |
666 | CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n); | |
667 | DES_XFORM(UBUFFER(encbuf)); | |
668 | MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8); | |
669 | } | |
670 | /* | |
671 | * now compute the last one, right padding with '\0' if need be | |
672 | */ | |
673 | if (n > 0) { | |
674 | MEMZERO(&CHAR(msgbuf, n), 8 - n); | |
675 | for (n = 0; n < 8; n++) | |
676 | CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n); | |
677 | DES_XFORM(UBUFFER(encbuf)); | |
678 | } | |
679 | /* | |
680 | * drop the bits | |
681 | * we write chars until fewer than 7 bits, | |
682 | * and then pad the last one with 0 bits | |
683 | */ | |
684 | for (n = 0; macbits > 7; n++, macbits -= 8) | |
685 | (void)putchar(CHAR(encbuf, n)); | |
686 | if (macbits > 0) { | |
687 | CHAR(msgbuf, 0) = 0x00; | |
688 | for (j = 0; j < macbits; j++) | |
689 | CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]); | |
690 | (void)putchar(CHAR(msgbuf, 0)); | |
691 | } | |
692 | } | |
693 | ||
694 | /* | |
695 | * This encrypts using the Cipher FeedBack mode of DES | |
696 | */ | |
697 | cfbenc() | |
698 | { | |
699 | register int n; /* number of bytes actually read */ | |
700 | register int nbytes; /* number of bytes to read */ | |
701 | register int bn; /* block number */ | |
702 | char ibuf[8]; /* input buffer */ | |
703 | Desbuf msgbuf; /* encryption buffer */ | |
704 | ||
705 | /* | |
706 | * do things in bytes, not bits | |
707 | */ | |
708 | nbytes = fbbits / 8; | |
709 | /* | |
710 | * do the transformation | |
711 | */ | |
712 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
713 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
714 | DES_XFORM(UBUFFER(msgbuf)); | |
715 | for (n = 0; n < 8 - nbytes; n++) | |
716 | UCHAR(ivec, n) = UCHAR(ivec, n+nbytes); | |
717 | for (n = 0; n < nbytes; n++) | |
718 | UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n); | |
719 | WRITE(&CHAR(ivec, 8-nbytes), nbytes); | |
720 | } | |
721 | /* | |
722 | * at EOF or last block -- in either case, the last byte contains | |
723 | * the character representation of the number of bytes in it | |
724 | */ | |
725 | bn++; | |
726 | MEMZERO(&ibuf[n], nbytes - n); | |
727 | ibuf[nbytes - 1] = n; | |
728 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
729 | DES_XFORM(UBUFFER(msgbuf)); | |
730 | for (n = 0; n < nbytes; n++) | |
731 | ibuf[n] ^= UCHAR(msgbuf, n); | |
732 | WRITE(ibuf, nbytes); | |
733 | } | |
734 | ||
735 | /* | |
736 | * This decrypts using the Cipher Block Chaining mode of DES | |
737 | */ | |
738 | cfbdec() | |
739 | { | |
740 | register int n; /* number of bytes actually read */ | |
741 | register int c; /* used to test for EOF */ | |
742 | register int nbytes; /* number of bytes to read */ | |
743 | register int bn; /* block number */ | |
744 | char ibuf[8]; /* input buffer */ | |
745 | char obuf[8]; /* output buffer */ | |
746 | Desbuf msgbuf; /* encryption buffer */ | |
747 | ||
748 | /* | |
749 | * do things in bytes, not bits | |
750 | */ | |
751 | nbytes = fbbits / 8; | |
752 | /* | |
753 | * do the transformation | |
754 | */ | |
755 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
756 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
757 | DES_XFORM(UBUFFER(msgbuf)); | |
758 | for (c = 0; c < 8 - nbytes; c++) | |
759 | CHAR(ivec, c) = CHAR(ivec, c+nbytes); | |
760 | for (c = 0; c < nbytes; c++) { | |
761 | CHAR(ivec, 8-nbytes+c) = ibuf[c]; | |
762 | obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c); | |
763 | } | |
764 | /* | |
765 | * if the last one, handle it specially | |
766 | */ | |
767 | if ((c = getchar()) == EOF) { | |
768 | n = obuf[nbytes-1]; | |
769 | if (n < 0 || n > nbytes-1) | |
770 | err(bn, "decryption failed (block corrupted)"); | |
771 | } | |
772 | else | |
773 | (void)ungetc(c, stdin); | |
774 | WRITE(obuf, n); | |
775 | } | |
776 | if (n > 0) | |
777 | err(bn, "decryption failed (incomplete block)"); | |
778 | } | |
779 | ||
780 | /* | |
781 | * This encrypts using the alternative Cipher FeedBack mode of DES | |
782 | */ | |
783 | cfbaenc() | |
784 | { | |
785 | register int n; /* number of bytes actually read */ | |
786 | register int nbytes; /* number of bytes to read */ | |
787 | register int bn; /* block number */ | |
788 | char ibuf[8]; /* input buffer */ | |
789 | char obuf[8]; /* output buffer */ | |
790 | Desbuf msgbuf; /* encryption buffer */ | |
791 | ||
792 | /* | |
793 | * do things in bytes, not bits | |
794 | */ | |
795 | nbytes = fbbits / 7; | |
796 | /* | |
797 | * do the transformation | |
798 | */ | |
799 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
800 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
801 | DES_XFORM(UBUFFER(msgbuf)); | |
802 | for (n = 0; n < 8 - nbytes; n++) | |
803 | UCHAR(ivec, n) = UCHAR(ivec, n+nbytes); | |
804 | for (n = 0; n < nbytes; n++) | |
805 | UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n)) | |
806 | |0200; | |
807 | for (n = 0; n < nbytes; n++) | |
808 | obuf[n] = CHAR(ivec, 8-nbytes+n)&0177; | |
809 | WRITE(obuf, nbytes); | |
810 | } | |
811 | /* | |
812 | * at EOF or last block -- in either case, the last byte contains | |
813 | * the character representation of the number of bytes in it | |
814 | */ | |
815 | bn++; | |
816 | MEMZERO(&ibuf[n], nbytes - n); | |
817 | ibuf[nbytes - 1] = ('0' + n)|0200; | |
818 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
819 | DES_XFORM(UBUFFER(msgbuf)); | |
820 | for (n = 0; n < nbytes; n++) | |
821 | ibuf[n] ^= UCHAR(msgbuf, n); | |
822 | WRITE(ibuf, nbytes); | |
823 | } | |
824 | ||
825 | /* | |
826 | * This decrypts using the alternative Cipher Block Chaining mode of DES | |
827 | */ | |
828 | cfbadec() | |
829 | { | |
830 | register int n; /* number of bytes actually read */ | |
831 | register int c; /* used to test for EOF */ | |
832 | register int nbytes; /* number of bytes to read */ | |
833 | register int bn; /* block number */ | |
834 | char ibuf[8]; /* input buffer */ | |
835 | char obuf[8]; /* output buffer */ | |
836 | Desbuf msgbuf; /* encryption buffer */ | |
837 | ||
838 | /* | |
839 | * do things in bytes, not bits | |
840 | */ | |
841 | nbytes = fbbits / 7; | |
842 | /* | |
843 | * do the transformation | |
844 | */ | |
845 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
846 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
847 | DES_XFORM(UBUFFER(msgbuf)); | |
848 | for (c = 0; c < 8 - nbytes; c++) | |
849 | CHAR(ivec, c) = CHAR(ivec, c+nbytes); | |
850 | for (c = 0; c < nbytes; c++) { | |
851 | CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200; | |
852 | obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177; | |
853 | } | |
854 | /* | |
855 | * if the last one, handle it specially | |
856 | */ | |
857 | if ((c = getchar()) == EOF) { | |
858 | if ((n = (obuf[nbytes-1] - '0')) < 0 | |
859 | || n > nbytes-1) | |
860 | err(bn, "decryption failed (block corrupted)"); | |
861 | } | |
862 | else | |
863 | (void)ungetc(c, stdin); | |
864 | WRITE(obuf, n); | |
865 | } | |
866 | if (n > 0) | |
867 | err(bn, "decryption failed (incomplete block)"); | |
868 | } | |
869 | ||
870 | ||
871 | /* | |
872 | * This encrypts using the Output FeedBack mode of DES | |
873 | */ | |
874 | ofbenc() | |
875 | { | |
876 | register int n; /* number of bytes actually read */ | |
877 | register int c; /* used to test for EOF */ | |
878 | register int nbytes; /* number of bytes to read */ | |
879 | register int bn; /* block number */ | |
880 | char ibuf[8]; /* input buffer */ | |
881 | char obuf[8]; /* output buffer */ | |
882 | Desbuf msgbuf; /* encryption buffer */ | |
883 | ||
884 | /* | |
885 | * do things in bytes, not bits | |
886 | */ | |
887 | nbytes = fbbits / 8; | |
888 | /* | |
889 | * do the transformation | |
890 | */ | |
891 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
892 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
893 | DES_XFORM(UBUFFER(msgbuf)); | |
894 | for (n = 0; n < 8 - nbytes; n++) | |
895 | UCHAR(ivec, n) = UCHAR(ivec, n+nbytes); | |
896 | for (n = 0; n < nbytes; n++) { | |
897 | UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n); | |
898 | obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n); | |
899 | } | |
900 | WRITE(obuf, nbytes); | |
901 | } | |
902 | /* | |
903 | * at EOF or last block -- in either case, the last byte contains | |
904 | * the character representation of the number of bytes in it | |
905 | */ | |
906 | bn++; | |
907 | MEMZERO(&ibuf[n], nbytes - n); | |
908 | ibuf[nbytes - 1] = n; | |
909 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
910 | DES_XFORM(UBUFFER(msgbuf)); | |
911 | for (c = 0; c < nbytes; c++) | |
912 | ibuf[c] ^= UCHAR(msgbuf, c); | |
913 | WRITE(ibuf, nbytes); | |
914 | } | |
915 | ||
916 | /* | |
917 | * This decrypts using the Output Block Chaining mode of DES | |
918 | */ | |
919 | ofbdec() | |
920 | { | |
921 | register int n; /* number of bytes actually read */ | |
922 | register int c; /* used to test for EOF */ | |
923 | register int nbytes; /* number of bytes to read */ | |
924 | register int bn; /* block number */ | |
925 | char ibuf[8]; /* input buffer */ | |
926 | char obuf[8]; /* output buffer */ | |
927 | Desbuf msgbuf; /* encryption buffer */ | |
928 | ||
929 | /* | |
930 | * do things in bytes, not bits | |
931 | */ | |
932 | nbytes = fbbits / 8; | |
933 | /* | |
934 | * do the transformation | |
935 | */ | |
936 | for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { | |
937 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
938 | DES_XFORM(UBUFFER(msgbuf)); | |
939 | for (c = 0; c < 8 - nbytes; c++) | |
940 | CHAR(ivec, c) = CHAR(ivec, c+nbytes); | |
941 | for (c = 0; c < nbytes; c++) { | |
942 | CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c); | |
943 | obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c); | |
944 | } | |
945 | /* | |
946 | * if the last one, handle it specially | |
947 | */ | |
948 | if ((c = getchar()) == EOF) { | |
949 | n = obuf[nbytes-1]; | |
950 | if (n < 0 || n > nbytes-1) | |
951 | err(bn, "decryption failed (block corrupted)"); | |
952 | } | |
953 | else | |
954 | (void)ungetc(c, stdin); | |
955 | /* | |
956 | * dump it | |
957 | */ | |
958 | WRITE(obuf, n); | |
959 | } | |
960 | if (n > 0) | |
961 | err(bn, "decryption failed (incomplete block)"); | |
962 | } | |
963 | ||
964 | /* | |
965 | * This authenticates using the Cipher FeedBack mode of DES | |
966 | */ | |
967 | cfbauth() | |
968 | { | |
969 | register int n, j; /* number of bytes actually read */ | |
970 | register int nbytes; /* number of bytes to read */ | |
971 | char ibuf[8]; /* input buffer */ | |
972 | Desbuf msgbuf; /* encryption buffer */ | |
973 | ||
974 | /* | |
975 | * do things in bytes, not bits | |
976 | */ | |
977 | nbytes = fbbits / 8; | |
978 | /* | |
979 | * do the transformation | |
980 | */ | |
981 | while ((n = READ(ibuf, nbytes)) == nbytes) { | |
982 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
983 | DES_XFORM(UBUFFER(msgbuf)); | |
984 | for (n = 0; n < 8 - nbytes; n++) | |
985 | UCHAR(ivec, n) = UCHAR(ivec, n+nbytes); | |
986 | for (n = 0; n < nbytes; n++) | |
987 | UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n); | |
988 | } | |
989 | /* | |
990 | * at EOF or last block -- in either case, the last byte contains | |
991 | * the character representation of the number of bytes in it | |
992 | */ | |
993 | MEMZERO(&ibuf[n], nbytes - n); | |
994 | ibuf[nbytes - 1] = '0' + n; | |
995 | MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8); | |
996 | DES_XFORM(UBUFFER(msgbuf)); | |
997 | for (n = 0; n < nbytes; n++) | |
998 | ibuf[n] ^= UCHAR(msgbuf, n); | |
999 | /* | |
1000 | * drop the bits | |
1001 | * we write chars until fewer than 7 bits, | |
1002 | * and then pad the last one with 0 bits | |
1003 | */ | |
1004 | for (n = 0; macbits > 7; n++, macbits -= 8) | |
1005 | (void)putchar(CHAR(msgbuf, n)); | |
1006 | if (macbits > 0) { | |
1007 | CHAR(msgbuf, 0) = 0x00; | |
1008 | for (j = 0; j < macbits; j++) | |
1009 | CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]); | |
1010 | (void)putchar(CHAR(msgbuf, 0)); | |
1011 | } | |
1012 | } | |
1013 | ||
1014 | #ifndef FASTWAY | |
1015 | /* | |
1016 | * change from 8 bits/Uchar to 1 bit/Uchar | |
1017 | */ | |
1018 | expand(from, to) | |
1019 | Desbuf from; /* 8bit/unsigned char string */ | |
1020 | char *to; /* 1bit/char string */ | |
1021 | { | |
1022 | register int i, j; /* counters in for loop */ | |
1023 | ||
1024 | for (i = 0; i < 8; i++) | |
1025 | for (j = 0; j < 8; j++) | |
1026 | *to++ = (CHAR(from, i)>>(7-j))&01; | |
1027 | } | |
1028 | ||
1029 | /* | |
1030 | * change from 1 bit/char to 8 bits/Uchar | |
1031 | */ | |
1032 | compress(from, to) | |
1033 | char *from; /* 1bit/char string */ | |
1034 | Desbuf to; /* 8bit/unsigned char string */ | |
1035 | { | |
1036 | register int i, j; /* counters in for loop */ | |
1037 | ||
1038 | for (i = 0; i < 8; i++) { | |
1039 | CHAR(to, i) = 0; | |
1040 | for (j = 0; j < 8; j++) | |
1041 | CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i); | |
1042 | } | |
1043 | } | |
1044 | #endif | |
1045 | ||
1046 | /* | |
1047 | * message about usage | |
1048 | */ | |
1049 | usage() | |
1050 | { | |
1051 | (void)fprintf(stderr, "%s\n", | |
1052 | "usage: bdes [-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]"); | |
1053 | exit(1); | |
1054 | } | |
1055 | ||
1056 | #endif /* DES */ |