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