source: zcrypt.c @ fa00c5c

owl
Last change on this file since fa00c5c was fa00c5c, checked in by James M. Kretchmar <kretch@mit.edu>, 15 years ago
Correct license.
  • Property mode set to 100644
File size: 19.8 KB
Line 
1/* Copyright (c) 2002,2003,2004,2009 James M. Kretchmar
2 *
3 * This file is part of Owl.
4 *
5 * Owl is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Owl is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Owl.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 * ---------------------------------------------------------------
19 *
20 * As of Owl version 2.1.12 there are patches contributed by
21 * developers of the branched BarnOwl project, Copyright (c)
22 * 2006-2009 The BarnOwl Developers. All rights reserved.
23 */
24
25/* The functions here with "owl" in their name were written for the
26 * Owl project.  Other code is from Philip Lisiecki's
27 * (lisiecki@mit.edu) zcrypt program.
28 */
29
30/* zcrypt.c -- Read in a data stream from stdin & dump a decrypted/encrypted *
31 *   datastream.  Reads the string to make the key from from the first       *
32 *   parameter.  Encrypts or decrypts according to -d or -e flag.  (-e is    *
33 *   default.)  Will invoke zwrite if the -c option is provided for          *
34 *   encryption.  If a zephyr class is specified & the keyfile name omitted  *
35 *   the ~/.crypt-table will be checked for "crypt-classname" and then       *
36 *   "crypt-default" for the keyfile name.                                   */
37
38static const char fileIdent[] = "$Id$";
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/types.h>
44#include <sys/wait.h>
45#include "owl.h"
46
47#ifdef OWL_ENABLE_ZCRYPT
48
49#define BASE_CODE 70
50#define LAST_CODE (BASE_CODE + 15)
51#define OUTPUT_BLOCK_SIZE 16
52#include <unistd.h>
53#include <sys/types.h>
54#include <des.h>
55
56#define MAX_KEY 128
57
58#ifndef TRUE
59#define TRUE -1
60#endif
61#ifndef FALSE
62#define FALSE 0
63#endif
64
65#define ZWRITE_OPT_NOAUTH     (1<<0)
66#define ZWRITE_OPT_SIGNATURE  (1<<1)
67#define ZWRITE_OPT_IGNOREVARS (1<<2)
68#define ZWRITE_OPT_VERBOSE    (1<<3)
69#define ZWRITE_OPT_QUIET      (1<<4)
70#define ZCRYPT_OPT_MESSAGE    (1<<5)
71#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
72
73typedef struct
74{
75  int flags;
76  char *signature;
77  char *message;
78} ZWRITEOPTIONS;
79
80char *GetZephyrVarKeyFile(char *whoami, char *class, char *instance);
81char *BuildArgString(char **argv, int start, int end);
82static int do_encrypt(char *keystring, int zephyr, char *class, char *instance, ZWRITEOPTIONS *zoptions, char* keyfile);
83int do_decrypt(char *keystring);
84
85#ifndef HAVE_DES_ECB_ENCRYPT_PROTO
86int des_ecb_encrypt(char [], char [], des_key_schedule, int);
87#endif
88
89#define M_NONE            0
90#define M_ZEPHYR_ENCRYPT  1
91#define M_DECRYPT         2
92#define M_ENCRYPT         3
93#define M_RANDOMIZE       4
94#define M_SETKEY          5
95
96int zcrypt(int argc, char *argv[]) {
97  char *fname = NULL;
98  int error = FALSE;
99  int zephyr = FALSE;
100  char *class = NULL, *instance = NULL;
101  int mode = M_NONE;
102
103  extern int optind, opterr;
104  extern char *optarg;
105  char c;
106
107  int messageflag = FALSE;
108  ZWRITEOPTIONS zoptions;
109  zoptions.flags = 0;
110
111  while ((c = getopt(argc, argv, "ZDERSF:c:i:advqtluons:f:m")) != (char)EOF) {
112    switch(c) {
113      case 'Z':
114        /* Zephyr encrypt */
115        mode = M_ZEPHYR_ENCRYPT;
116        break;
117      case 'D':
118        /* Decrypt */
119        mode = M_DECRYPT;
120        break;
121      case 'E':
122        /* Encrypt */
123        mode = M_ENCRYPT;
124        break;
125      case 'R':
126        /* Randomize the keyfile */
127        mode = M_RANDOMIZE;
128        break;
129      case 'S':
130        /* Set a new key value from stdin */
131        mode = M_SETKEY;
132        break;
133      case 'F':
134        /* Specify the keyfile explicitly */
135        if (fname != NULL) error = TRUE;
136        fname = optarg;
137        break;
138      case 'c':
139        /* Zwrite/zcrypt: class name */
140        if (class != NULL) error = TRUE;
141        class = optarg;
142        break;
143      case 'i':
144        /* Zwrite/zcrypt: instance name */
145        if (instance != NULL) error = TRUE;
146        instance = optarg;
147        break;
148      case 'a':
149        /* Zwrite: authenticate (default) */
150        zoptions.flags &= ~ZWRITE_OPT_NOAUTH;
151        break;
152      case 'd':
153        /* Zwrite: do not authenticate */
154        zoptions.flags |= ZWRITE_OPT_NOAUTH;
155        break;
156      case 'v':
157        /* Zwrite: verbose */
158        zoptions.flags |= ZWRITE_OPT_VERBOSE;
159        break;
160      case 'q':
161        /* Zwrite: quiet */
162        zoptions.flags |= ZWRITE_OPT_QUIET;
163        break;
164      case 't':
165        /* Zwrite: no expand tabs (ignored) */
166        break;
167      case 'l':
168        /* Zwrite: ignore '.' on a line by itself (ignored) */
169        zoptions.flags |= ZCRYPT_OPT_IGNOREDOT;
170        break;
171      case 'u':
172        /* Zwrite: urgent message */
173        instance = "URGENT";
174        break;
175      case 'o':
176        /* Zwrite: ignore zephyr variables zwrite-class, zwrite-inst, */
177        /*         zwrite-opcode */
178        zoptions.flags |= ZWRITE_OPT_IGNOREVARS;
179        break;
180      case 'n':
181        /* Zwrite: prevent PING message (always used) */
182        break;
183      case 's':
184        /* Zwrite: signature */
185        zoptions.flags |= ZWRITE_OPT_SIGNATURE;
186        zoptions.signature = optarg;
187        break;
188      case 'f':
189        /* Zwrite: file system specification (ignored) */
190        break;
191      case 'm':
192        /* Message on rest of line */
193        messageflag = TRUE;
194        break;
195      case '?':
196        error = TRUE;
197        break;
198    }
199    if (error || messageflag) break;
200  }
201
202  if (class != NULL || instance != NULL) {
203    zephyr = TRUE;
204  }
205
206  if (messageflag) {
207    zoptions.flags |= ZCRYPT_OPT_MESSAGE;
208    zoptions.message = BuildArgString(argv, optind, argc);
209    if (!zoptions.message)
210    {
211      printf("Memory allocation error.\n");
212      error = TRUE;
213    }
214  } else if (optind < argc) {
215    error = TRUE;
216  }
217
218  if (mode == M_NONE) mode = (zephyr?M_ZEPHYR_ENCRYPT:M_ENCRYPT);
219
220  if (mode == M_ZEPHYR_ENCRYPT && !zephyr) error = TRUE;
221
222  if (!error && fname == NULL && (class != NULL || instance != NULL)) {
223    fname = GetZephyrVarKeyFile(argv[0], class, instance);
224  }
225
226 
227  if (error || fname == NULL) {
228    printf("Usage: %s [-Z|-D|-E|-R|-S] [-F Keyfile] [-c class] [-i instance]\n", argv[0]);
229    printf("       [-advqtluon] [-s signature] [-f arg] [-m message]\n");
230    printf("  One or more of class, instance, and keyfile must be specified.\n");
231  } else {
232    if (mode == M_RANDOMIZE) {
233      /* Choose a new, random key */
234/*
235      FILE *fkey = fopen(fname, "w");
236      if (!fkey)
237        printf("Could not open key file for writing: %s\n", fname);
238      else
239      {
240        char string[100];
241        fputs(fkey, string);
242        fclose(fkey);
243        }
244 */
245      printf("Feature not yet implemented.\n");
246    } else if (mode == M_SETKEY) {
247      /* Set a new, user-entered key */
248      char newkey[MAX_KEY];
249      FILE *fkey;
250     
251      if (isatty(0)) {
252        printf("Enter new key: ");
253        /* Really should read without echo!!! */
254        fgets(newkey, MAX_KEY - 1, stdin);
255      } else {
256        fgets(newkey, MAX_KEY - 1, stdin);
257      }
258
259      fkey = fopen(fname, "w");
260      if (!fkey) {
261        printf("Could not open key file for writing: %s\n", fname);
262      } else {
263        if (fputs(newkey, fkey) != strlen(newkey) || putc('\n', fkey) != '\n') {
264          printf("Error writing to key file.\n");
265          fclose(fkey);
266        } else {
267          fclose(fkey);
268          printf("Key update complete.\n");
269        }
270      }
271    } else {
272      /* Encrypt/decrypt */
273      FILE *fkey = fopen(fname, "r");
274      if (!fkey) {
275        printf("Could not open key file: %s\n", fname);
276      } else {
277        char keystring[MAX_KEY];
278        fgets(keystring, MAX_KEY-1, fkey);
279        if (mode == M_ZEPHYR_ENCRYPT || mode == M_ENCRYPT) {
280          do_encrypt(keystring, (mode == M_ZEPHYR_ENCRYPT), class, instance,
281                     &zoptions, fname);
282        } else {
283          do_decrypt(keystring);
284        }
285        fclose(fkey);
286      }
287    }
288  }
289
290  /* Always print the **END** message if -D is specified. */
291  if (mode == M_DECRYPT) printf("**END**\n");
292
293  exit(0);
294}
295
296/* The 'owl_zcrypt_decrypt' function was written by kretch for Owl.
297 * Decrypt the message in 'in' on class 'class' and instance
298 * 'instance' and leave the result in 'out'.  Out must be a buffer
299 * allocated by the caller.
300 *
301 * return 0 on success, otherwise -1
302 */
303int owl_zcrypt_decrypt(char *out, char *in, char *class, char *instance) {
304  char *fname, keystring[MAX_KEY], *inptr, *endptr;
305  FILE *fkey;
306  des_cblock key;
307  des_key_schedule schedule;
308  char input[8], output[9];
309  int i, c1, c2;
310 
311  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
312  if (!fname) return(-1);
313  fkey=fopen(fname, "r");
314  if (!fkey) return(-1);
315  fgets(keystring, MAX_KEY-1, fkey);
316  fclose(fkey);
317
318  strcpy(out, "");
319
320  output[0] = '\0';    /* In case no message at all                 */
321  output[8] = '\0';    /* NULL at end will limit string length to 8 */
322
323  des_string_to_key(keystring, key);
324  des_key_sched(key, schedule);
325
326  inptr=in;
327  endptr=in+strlen(in)-1;
328  while (inptr<endptr) {
329    for (i=0; i<8; i++) {
330      c1=(inptr[0])-BASE_CODE;
331      c2=(inptr[1])-BASE_CODE;
332      input[i]=c1 * 0x10 + c2;
333      inptr+=2;
334    }
335    des_ecb_encrypt(input, output, schedule, FALSE);
336    strcat(out, output);
337  }
338
339  if (output[0]) {
340    if (output[strlen(output)-1] != '\n') {
341      strcat(out, "\n");
342    }
343  } else {
344    strcat(out, "\n");
345  }
346  return(0);
347}
348
349int owl_zcrypt_encrypt(char *out, char *in, char *class, char *instance) {
350  /*  static int do_encrypt(char *keystring, int zephyr, char *class, char *instance, ZWRITEOPTIONS *zoptions, char* keyfile) { */
351  char *fname, keystring[MAX_KEY];
352  FILE *fkey;
353  des_cblock key;
354  des_key_schedule schedule;
355  char input[8], output[8];
356  int size, length, i;
357  char *inbuff = NULL, *inptr;
358  int use_buffer = FALSE;
359  int num_blocks=0, last_block_size=0;
360
361  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
362  if (!fname) return(-1);
363  fkey=fopen(fname, "r");
364  if (!fkey) return(-1);
365  fgets(keystring, MAX_KEY-1, fkey);
366  fclose(fkey);
367
368  des_string_to_key(keystring, key);
369  des_key_sched(key, schedule);
370
371  inbuff=in;
372  length=strlen(inbuff);
373  num_blocks=(length+7)/8;
374  last_block_size=((length+7)%8)+1;
375  use_buffer=TRUE;
376
377  strcpy(out, "");
378 
379  inptr=inbuff;
380  while (TRUE) {
381    /* Get 8 bytes from buffer */
382    if (num_blocks > 1) {
383      size = 8;
384      memcpy(input, inptr, size);
385      inptr+=8;
386      num_blocks--;
387    } else if (num_blocks == 1) {
388      size=last_block_size;
389      memcpy(input, inptr, size);
390      num_blocks--;
391    } else {
392      size=0;
393    }
394
395    /* Check for EOF and pad the string to 8 chars, if needed */
396    if (size == 0) break;     /* END OF INPUT: BREAK FROM while LOOP! */
397     
398    if (size<8) memset(input + size, 0, 8 - size);
399
400    /* Encrypt and output the block */
401    des_ecb_encrypt(input, output, schedule, TRUE);
402
403    for (i = 0; i < 8; i++) {
404      sprintf(out + strlen(out), "%c", ((output[i] & 0xf0) >> 4) + BASE_CODE);
405      sprintf(out + strlen(out), "%c", (output[i] & 0x0f)        + BASE_CODE);
406    }
407
408    if (size < 8) break;
409  }
410  return(0);
411}
412
413/* Build a space-separated string from argv from elements between start  *
414 * and end - 1.  malloc()'s the returned string. */
415char *BuildArgString(char **argv, int start, int end) {
416  int len = 1;
417  int i;
418  char *result;
419
420  /* Compute the length of the string.  (Plus 1 or 2) */
421  for (i = start; i < end; i++) {
422    len += strlen(argv[i]) + 1;
423  }
424
425  /* Allocate memory */
426  result = (char *)malloc(len);
427  if (result) {
428    /* Build the string */
429    char *ptr = result;
430    /* Start with an empty string, in case nothing is copied. */
431    *ptr = '\0';
432    /* Copy the arguments */
433    for (i = start; i < end; i++) {
434      char *temp = argv[i];
435      /* Add a space, if not the first argument */
436      if (i != start) *ptr++ = ' ';
437      /* Copy argv[i], leaving ptr pointing to the '\0' copied from temp */
438      while ((*ptr = *temp++)!=0) {
439        ptr++;
440      }
441    }
442  }
443
444  return(result);
445}
446
447#define MAX_BUFF 258
448#define MAX_SEARCH 3
449/* Find the class/instance in the .crypt-table */
450char *GetZephyrVarKeyFile(char *whoami, char *class, char *instance) {
451  char *keyfile = NULL;
452  char *varname[MAX_SEARCH];
453  int length[MAX_SEARCH], i;
454  char buffer[MAX_BUFF];
455  char *filename;
456  char result[MAX_SEARCH][MAX_BUFF];
457  int numsearch = 0;
458  FILE *fsearch;
459
460  memset(varname, 0, sizeof(varname));
461
462  /* Determine names to look for in .crypt-table */
463  if (instance) {
464    varname[numsearch++] = owl_sprintf("crypt-%s-%s:", (class?class:"message"), instance);
465  }
466  if (class) {
467    varname[numsearch++] = owl_sprintf("crypt-%s:", class);
468  }
469  varname[numsearch++] = owl_strdup("crypt-default:");
470
471  /* Setup the result array, and determine string lengths */
472  for (i = 0; i < numsearch; i++) {
473    result[i][0] = '\0';
474    length[i] = strlen(varname[i]);
475  }
476
477  /* Open~/.crypt-table */
478  filename = owl_sprintf("%s/.crypt-table", getenv("HOME"));
479  fsearch = fopen(filename, "r");
480  if (fsearch) {
481    /* Scan file for a match */
482    while (!feof(fsearch)) {
483      fgets(buffer, MAX_BUFF - 3, fsearch);
484      for (i = 0; i < numsearch; i++) {
485        if (strncasecmp(varname[i], buffer, length[i]) == 0) {
486          int j;
487          for (j = length[i]; buffer[j] == ' '; j++)
488            ;
489          strcpy(result[i], &buffer[j]);
490          if (*result[i]) {
491            if (result[i][strlen(result[i])-1] == '\n') {
492              result[i][strlen(result[i])-1] = '\0';
493            }
494          }
495        }
496      }
497    }
498
499    /* Pick the "best" match found */
500    keyfile = NULL;
501    for (i = 0; i < numsearch; i++) {
502      if (*result[i]) {
503        keyfile = result[i];
504        break;
505      }
506    }
507
508    if (keyfile == NULL) {
509      /* printf("Could not find key table entry.\n"); */
510    } else {
511      /* Prepare result to be returned */
512      char *temp = keyfile;
513      keyfile = (char *)malloc(strlen(temp) + 1);
514      if (keyfile) {
515        strcpy(keyfile, temp);
516      } else {
517        /* printf("Memory allocation error.\n"); */
518      }
519    }
520   
521    fclose(fsearch);
522  } else {
523    /* printf("Could not open key table file: %s\n", filename); */
524  }
525
526  for(i = 0; i < MAX_SEARCH; i++) {
527    owl_free(varname[i]);
528  }
529
530  owl_free(filename);
531
532  return(keyfile);
533}
534
535static pid_t zephyrpipe_pid = 0;
536
537/* Open a pipe to zwrite */
538static FILE *GetZephyrPipe(char *class, char *instance, ZWRITEOPTIONS *zoptions) {
539  int fildes[2];
540  pid_t pid;
541  FILE *result;
542  char *argv[20];
543  int argc = 0;
544
545  if (pipe(fildes) < 0) return(NULL);
546  pid = fork();
547
548  if (pid < 0) {
549    /* Error: clean up */
550    close(fildes[0]);
551    close(fildes[1]);
552    result = NULL;
553  } else if (pid == 0) {
554    /* Setup child process */
555    argv[argc++] = "zwrite";
556    argv[argc++] = "-n";     /* Always send without ping */
557    if (class) {
558      argv[argc++] = "-c";
559      argv[argc++] = class;
560    }
561    if (instance) {
562      argv[argc++] = "-i";
563      argv[argc++] = instance;
564    }
565    if (zoptions->flags & ZWRITE_OPT_NOAUTH) argv[argc++] = "-d";
566    if (zoptions->flags & ZWRITE_OPT_QUIET) argv[argc++] = "-q";
567    if (zoptions->flags & ZWRITE_OPT_VERBOSE) argv[argc++] = "-v";
568    if (zoptions->flags & ZWRITE_OPT_SIGNATURE) {
569      argv[argc++] = "-s";
570      argv[argc++] = zoptions->signature;
571    }
572    argv[argc++] = "-O";
573    argv[argc++] = "crypt";
574    argv[argc] = NULL;
575    close(fildes[1]);
576    if (fildes[0] != STDIN_FILENO) {
577      if (dup2(fildes[0], STDIN_FILENO) != STDIN_FILENO) exit(0);
578      close(fildes[0]);
579    }
580    close(fildes[0]);
581    execvp(argv[0], argv);
582    printf("Exec error: could not run zwrite\n");
583    exit(0);
584  } else {
585    close(fildes[0]);
586    /* Create a FILE * for the zwrite pipe */
587    result = (FILE *)fdopen(fildes[1], "w");
588    zephyrpipe_pid = pid;
589  }
590
591  return(result);
592}
593
594/* Close the pipe to zwrite */
595void CloseZephyrPipe(FILE *pipe) {
596  fclose(pipe);
597  waitpid(zephyrpipe_pid, NULL, 0);
598  zephyrpipe_pid = 0;
599}
600
601#define MAX_RESULT 2048
602
603
604void block_to_ascii(char *output, FILE *outfile) {
605  int i;
606  for (i = 0; i < 8; i++) {
607    putc(((output[i] & 0xf0) >> 4) + BASE_CODE, outfile);
608    putc( (output[i] & 0x0f)       + BASE_CODE, outfile);
609  }
610}
611
612#define MAX_LINE 128
613
614/* Encrypt stdin, with prompt if isatty, and send to stdout, or to zwrite
615   if zephyr is set. */
616static int do_encrypt(char *keystring, int zephyr, char *class, char *instance, ZWRITEOPTIONS *zoptions, char* keyfile) {
617  des_cblock key;
618  des_key_schedule schedule;
619  char input[8], output[8];
620  int size;
621  FILE *outfile = stdout;
622  int error = FALSE;
623  char *inbuff = NULL, *inptr;
624  int freein = FALSE;
625  int use_buffer = FALSE;
626  int num_blocks=0, last_block_size=0;
627
628  des_string_to_key(keystring, key);
629  des_key_sched(key, schedule);
630
631  if (zephyr) {
632    if (zoptions->flags & ZCRYPT_OPT_MESSAGE) {
633      /* Use the -m message */
634      int length;
635      inbuff = zoptions->message;     
636      length = strlen(inbuff);
637      num_blocks = (length + 7) / 8;
638      last_block_size = ((length + 7) % 8) + 1;
639      use_buffer = TRUE;
640    } else if (isatty(0)) {
641      /* tty input, so show the "Type your message now..." message */
642      if (zoptions->flags & ZCRYPT_OPT_IGNOREDOT) {
643        printf("Type your message now.  End with the end-of-file character.\n");
644      } else {
645        printf("Type your message now.  End with control-D or a dot on a line by itself.\n");
646      }
647      use_buffer = TRUE;
648      if ((inptr = inbuff = (char *)malloc(MAX_RESULT)) == NULL) {
649        printf("Memory allocation error\n");
650        return FALSE;
651      }
652      while (inptr - inbuff < MAX_RESULT - MAX_LINE - 20) {
653        fgets(inptr, MAX_LINE, stdin);
654        if (inptr[0]) {
655          if (inptr[0] == '.' && inptr[1] == '\n' && 
656              !(zoptions->flags & ZCRYPT_OPT_IGNOREDOT)) {
657            inptr[0] = '\0';
658            break;
659          } else {
660            inptr += strlen(inptr);
661          }
662        } else {
663          break;
664        }
665      }
666      num_blocks = (inptr - inbuff + 7) / 8;
667      last_block_size = ((inptr - inbuff + 7) % 8) + 1;
668      freein = TRUE;
669    }
670
671    /* if (zephyr) */
672    outfile = GetZephyrPipe(class, instance, zoptions);
673    if (!outfile) {
674      printf("Could not run zwrite\n");
675      if (freein && inbuff) {
676        free(inbuff);
677      }
678      return(FALSE);
679    }
680  }
681
682  inptr = inbuff;
683
684  /* Encrypt the input (inbuff or stdin) and send it to outfile */
685  while (TRUE) {
686    if (use_buffer) {
687      /* Get 8 bytes from buffer */
688      if (num_blocks > 1) {
689        size = 8;
690        memcpy(input, inptr, size);
691        inptr += 8;
692        num_blocks--;
693      } else if (num_blocks == 1) {
694        size = last_block_size;
695        memcpy(input, inptr, size);
696        num_blocks--;
697      } else {
698        size = 0;
699      }
700    } else {
701      /* Get 8 bytes from stdin */
702      size = fread(input, 1, 8, stdin);
703    }
704
705    /* Check for EOF and pad the string to 8 chars, if needed */
706    if (size == 0) break;     /* END OF INPUT: BREAK FROM while LOOP! */
707     
708    if (size < 8) memset(input + size, 0, 8 - size);
709
710    /* Encrypt and output the block */
711    des_ecb_encrypt(input, output, schedule, TRUE);
712    block_to_ascii(output, outfile);
713
714    if (size < 8) break;
715  }
716
717  /* Close out the output */
718  if (!error) putc('\n', outfile);
719  if (zephyr) CloseZephyrPipe(outfile);
720
721  /* Free the input buffer, if necessary */
722  if (freein && inbuff) free(inbuff);
723
724  return(!error);
725}
726
727/* Read a half-byte from stdin, skipping invalid characters.  Returns -1
728   if at EOF or file error */
729int read_ascii_nybble() {
730  char c;
731
732  while (TRUE) {
733    if (fread(&c, 1, 1, stdin) == 0) {
734      return(-1);
735    } else if (c >= BASE_CODE && c <= LAST_CODE) {
736      return(c - BASE_CODE);
737    }
738  }
739}
740
741/* Read both halves of the byte and return the single byte.  Returns -1
742   if at EOF or file error. */
743int read_ascii_byte() {
744  int c1, c2;
745  c1 = read_ascii_nybble();
746  if (c1 >= 0) {
747    c2 = read_ascii_nybble();
748    if (c2 >= 0) {
749      return c1 * 0x10 + c2;
750    }
751  }
752  return(-1);
753}
754
755/* Read an 8-byte DES block from stdin */
756int read_ascii_block(char *input) {
757  int c, i;
758
759  for (i = 0; i < 8; i++) {
760    c = read_ascii_byte();
761    if (c < 0) return(FALSE);
762    input[i] = c;
763  }
764
765  return(TRUE);
766}
767
768/* Decrypt stdin */
769int do_decrypt(char *keystring) {
770  des_cblock key;
771  des_key_schedule schedule;
772  char input[8], output[9];
773
774  output[0] = '\0';    /* In case no message at all                 */
775  output[8] = '\0';    /* NULL at end will limit string length to 8 */
776
777  des_string_to_key(keystring, key);
778  des_key_sched(key, schedule);
779
780  while (read_ascii_block(input)) {
781    des_ecb_encrypt(input, output, schedule, FALSE);
782    printf("%s", output);
783  }
784
785  if (output[0]) {
786    if (output[strlen(output)-1] != '\n') {
787      printf("\n");
788    }
789  } else {
790    printf("\n");
791  }
792  return(0);
793}
794
795#endif
Note: See TracBrowser for help on using the repository browser.