source: zcrypt.c @ 7c5d060

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 7c5d060 was 60fcd71, checked in by Nelson Elhage <nelhage@mit.edu>, 12 years ago
zcrypt: des_ecb_encrypt doesn't NULL-terminate the output block. Output is a 'unsigned char [8]', so it couldn't even NULL-terminate it in place if it wanted to. So copy the decrypted buffer into a larger buffer that's guaranteed to have a NULL on the end.
  • Property mode set to 100644
File size: 20.7 KB
Line 
1/* zcrypt.c -- Read in a data stream from stdin & dump a decrypted/encrypted *
2 *   datastream.  Reads the string to make the key from from the first       *
3 *   parameter.  Encrypts or decrypts according to -d or -e flag.  (-e is    *
4 *   default.)  Will invoke zwrite if the -c option is provided for          *
5 *   encryption.  If a zephyr class is specified & the keyfile name omitted  *
6 *   the ~/.crypt-table will be checked for "crypt-classname" and then       *
7 *   "crypt-default" for the keyfile name.                                   */
8
9#include <stdio.h>
10
11#include <unistd.h>
12#include <sys/types.h>
13#include <zephyr/zephyr.h>
14#include <glib.h>
15#include <string.h>
16#include <stdlib.h>
17#include <sys/wait.h>
18#include <ctype.h>
19
20#include "config.h"
21
22#ifdef HAVE_KERBEROS_IV
23#include <kerberosIV/des.h>
24#else
25#include <openssl/des.h>
26#endif
27
28#include "filterproc.h"
29
30#define MAX_KEY      128
31#define MAX_LINE     128
32#define MAX_RESULT   4096
33
34#ifndef TRUE
35#define TRUE -1
36#endif
37#ifndef FALSE
38#define FALSE 0
39#endif
40
41#define ZWRITE_OPT_NOAUTH     (1<<0)
42#define ZWRITE_OPT_SIGNATURE  (1<<1)
43#define ZWRITE_OPT_IGNOREVARS (1<<2)
44#define ZWRITE_OPT_VERBOSE    (1<<3)
45#define ZWRITE_OPT_QUIET      (1<<4)
46#define ZCRYPT_OPT_MESSAGE    (1<<5)
47#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
48
49typedef struct
50{
51  int flags;
52  char *signature;
53  char *message;
54} ZWRITEOPTIONS;
55
56char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance);
57int ParseCryptSpec(const char *spec, const char **keyfile);
58char *BuildArgString(char **argv, int start, int end);
59char *read_keystring(const char *keyfile);
60
61int do_encrypt(int zephyr, const char *class, const char *instance,
62               ZWRITEOPTIONS *zoptions, const char* keyfile, int cipher);
63int do_encrypt_des(const char *keyfile, const char *in, int len, FILE *out);
64int do_encrypt_aes(const char *keyfile, const char *in, int len, FILE *out);
65
66int do_decrypt(const char *keyfile, int cipher);
67int do_decrypt_aes(const char *keyfile);
68int do_decrypt_des(const char *keyfile);
69
70
71#define M_NONE            0
72#define M_ZEPHYR_ENCRYPT  1
73#define M_DECRYPT         2
74#define M_ENCRYPT         3
75#define M_RANDOMIZE       4
76#define M_SETKEY          5
77
78enum cipher_algo {
79  CIPHER_DES,
80  CIPHER_AES,
81  NCIPHER
82};
83
84typedef struct {
85  int (*encrypt)(const char *keyfile, const char *in, int len, FILE *out);
86  int (*decrypt)(const char *keyfile);
87} cipher_pair;
88
89cipher_pair ciphers[NCIPHER] = {
90  [CIPHER_DES] { do_encrypt_des, do_decrypt_des},
91  [CIPHER_AES] { do_encrypt_aes, do_decrypt_aes},
92};
93
94static void owl_zcrypt_string_to_schedule(char *keystring, des_key_schedule *schedule) {
95#ifdef HAVE_KERBEROS_IV
96  des_cblock key;
97#else
98  des_cblock _key, *key = &_key;
99#endif
100
101  des_string_to_key(keystring, key);
102  des_key_sched(key, *schedule);
103}
104
105int main(int argc, char *argv[])
106{
107  char *cryptspec = NULL;
108  const char *keyfile;
109  int cipher;
110  int error = FALSE;
111  int zephyr = FALSE;
112  char *class = NULL, *instance = NULL;
113  int mode = M_NONE;
114
115  extern int optind, opterr;
116  extern char *optarg;
117  char c;
118
119  int messageflag = FALSE;
120  ZWRITEOPTIONS zoptions;
121  zoptions.flags = 0;
122
123  while ((c = getopt(argc, argv, "ZDERSF:c:i:advqtluons:f:m")) != (char)EOF)
124  {
125    switch(c)
126    {
127      case 'Z':
128        /* Zephyr encrypt */
129        mode = M_ZEPHYR_ENCRYPT;
130        break;
131      case 'D':
132        /* Decrypt */
133        mode = M_DECRYPT;
134        break;
135      case 'E':
136        /* Encrypt */
137        mode = M_ENCRYPT;
138        break;
139      case 'R':
140        /* Randomize the keyfile */
141        mode = M_RANDOMIZE;
142        break;
143      case 'S':
144        /* Set a new key value from stdin */
145        mode = M_SETKEY;
146        break;
147      case 'F':
148        /* Specify the keyfile explicitly */
149        if (cryptspec != NULL) error = TRUE;
150        cryptspec = optarg;
151        break;
152      case 'c':
153        /* Zwrite/zcrypt: class name */
154        if (class != NULL) error = TRUE;
155        class = optarg;
156        break;
157      case 'i':
158        /* Zwrite/zcrypt: instance name */
159        if (instance != NULL) error = TRUE;
160        instance = optarg;
161        break;
162      case 'a':
163        /* Zwrite: authenticate (default) */
164        zoptions.flags &= ~ZWRITE_OPT_NOAUTH;
165        break;
166      case 'd':
167        /* Zwrite: do not authenticate */
168        zoptions.flags |= ZWRITE_OPT_NOAUTH;
169        break;
170      case 'v':
171        /* Zwrite: verbose */
172        zoptions.flags |= ZWRITE_OPT_VERBOSE;
173        break;
174      case 'q':
175        /* Zwrite: quiet */
176        zoptions.flags |= ZWRITE_OPT_QUIET;
177        break;
178      case 't':
179        /* Zwrite: no expand tabs (ignored) */
180        break;
181      case 'l':
182        /* Zwrite: ignore '.' on a line by itself (ignored) */
183        zoptions.flags |= ZCRYPT_OPT_IGNOREDOT;
184        break;
185      case 'u':
186        /* Zwrite: urgent message */
187        instance = "URGENT";
188        break;
189      case 'o':
190        /* Zwrite: ignore zephyr variables zwrite-class, zwrite-inst, */
191        /*         zwrite-opcode */
192        zoptions.flags |= ZWRITE_OPT_IGNOREVARS;
193        break;
194      case 'n':
195        /* Zwrite: prevent PING message (always used) */
196        break;
197      case 's':
198        /* Zwrite: signature */
199        zoptions.flags |= ZWRITE_OPT_SIGNATURE;
200        zoptions.signature = optarg;
201        break;
202      case 'f':
203        /* Zwrite: file system specification (ignored) */
204        break;
205      case 'm':
206        /* Message on rest of line*/
207        messageflag = TRUE;
208        break;
209      case '?':
210        error = TRUE;
211        break;
212    }
213    if (error || messageflag)
214      break;
215  }
216
217  if (class != NULL || instance != NULL)
218    zephyr = TRUE;
219
220  if (messageflag)
221  {
222    zoptions.flags |= ZCRYPT_OPT_MESSAGE;
223    zoptions.message = BuildArgString(argv, optind, argc);
224    if (!zoptions.message)
225    {
226      fprintf(stderr, "Memory allocation error.\n");
227      error = TRUE;
228    }
229  }
230  else if (optind < argc)
231  {
232    error = TRUE;
233  }
234
235  if (mode == M_NONE)
236    mode = (zephyr?M_ZEPHYR_ENCRYPT:M_ENCRYPT);
237
238  if (mode == M_ZEPHYR_ENCRYPT && !zephyr)
239    error = TRUE;
240
241  if (!error && cryptspec == NULL && (class != NULL || instance != NULL)) {
242    cryptspec = GetZephyrVarKeyFile(argv[0], class, instance);
243    if(!cryptspec) {
244      fprintf(stderr, "Unable to find keyfile for ");
245      if(class != NULL) {
246        fprintf(stderr, "-c %s ", class);
247      }
248      if(instance != NULL) {
249        fprintf(stderr, "-i %s ", instance);
250      }
251      fprintf(stderr, "\n");
252      exit(-1);
253    }
254  }
255
256  if (error || !cryptspec)
257  {
258    fprintf(stderr, "Usage: %s [-Z|-D|-E|-R|-S] [-F Keyfile] [-c class] [-i instance]\n", argv[0]);
259    fprintf(stderr, "       [-advqtluon] [-s signature] [-f arg] [-m message]\n");
260    fprintf(stderr, "  One or more of class, instance, and keyfile must be specified.\n");
261    exit(1);
262  }
263
264  cipher = ParseCryptSpec(cryptspec, &keyfile);
265  if(cipher < 0) {
266    fprintf(stderr, "Invalid cipher specification: %s\n", cryptspec);
267    exit(1);
268  }
269
270
271  if (mode == M_RANDOMIZE)
272  {
273    /* Choose a new, random key */
274    /*
275      FILE *fkey = fopen(fname, "w");
276      if (!fkey)
277      printf("Could not open key file for writing: %s\n", fname);
278      else
279      {
280      char string[100];
281      fputs(fkey, string);
282      fclose(fkey);
283      }
284    */
285    fprintf(stderr, "Feature not yet implemented.\n");
286  }
287  else if (mode == M_SETKEY)
288  {
289    /* Set a new, user-entered key */
290    char newkey[MAX_KEY];
291    FILE *fkey;
292
293    if (isatty(0))
294    {
295      printf("Enter new key: ");
296      /* Really should read without echo!!! */
297    }
298    if(!fgets(newkey, MAX_KEY - 1, stdin)) {
299      fprintf(stderr, "Error reading key.\n");
300      return 1;
301    }
302
303    fkey = fopen(keyfile, "w");
304    if (!fkey)
305      fprintf(stderr, "Could not open key file for writing: %s\n", keyfile);
306    else
307    {
308      if (fputs(newkey, fkey) != strlen(newkey) || putc('\n', fkey) != '\n')
309      {
310        fprintf(stderr, "Error writing to key file.\n");
311        fclose(fkey);
312        exit(1);
313      }
314      else
315      {
316        fclose(fkey);
317        fprintf(stderr, "Key update complete.\n");
318      }
319    }
320  }
321  else
322  {
323    if (mode == M_ZEPHYR_ENCRYPT || mode == M_ENCRYPT)
324      error = !do_encrypt((mode == M_ZEPHYR_ENCRYPT), class, instance,
325                          &zoptions, keyfile, cipher);
326    else
327      error = !do_decrypt(keyfile, cipher);
328  }
329
330  /* Always print the **END** message if -D is specified. */
331  if (mode == M_DECRYPT)
332    printf("**END**\n");
333
334  return error;
335}
336
337int ParseCryptSpec(const char *spec, const char **keyfile) {
338  int cipher = CIPHER_DES;
339  char *cipher_name = strdup(spec);
340  char *colon = strchr(cipher_name, ':');
341
342  *keyfile = spec;
343
344  if (colon) {
345    char *rest = strchr(spec, ':') + 1;
346    while(isspace(*rest)) rest++;
347
348    *colon-- = '\0';
349    while (colon >= cipher_name && isspace(*colon)) {
350      *colon = '\0';
351    }
352
353    if(strcmp(cipher_name, "AES") == 0) {
354      cipher = CIPHER_AES;
355      *keyfile = rest;
356    } else if(strcmp(cipher_name, "DES") == 0) {
357      cipher = CIPHER_DES;
358      *keyfile = rest;
359    }
360  }
361
362  free(cipher_name);
363
364  return cipher;
365}
366
367/* Build a space-separated string from argv from elements between start  *
368 * and end - 1.  malloc()'s the returned string. */
369char *BuildArgString(char **argv, int start, int end)
370{
371  int len = 1;
372  int i;
373  char *result;
374
375  /* Compute the length of the string.  (Plus 1 or 2) */
376  for (i = start; i < end; i++)
377    len += strlen(argv[i]) + 1;
378
379  /* Allocate memory */
380  result = (char *)malloc(len);
381  if (result)
382  {
383    /* Build the string */
384    char *ptr = result;
385    /* Start with an empty string, in case nothing is copied. */
386    *ptr = '\0';
387    /* Copy the arguments */
388    for (i = start; i < end; i++)
389    {
390      char *temp = argv[i];
391      /* Add a space, if not the first argument */
392      if (i != start)
393        *ptr++ = ' ';
394      /* Copy argv[i], leaving ptr pointing to the '\0' copied from temp */
395      while ((*ptr = *temp++))
396        ptr++;
397    }
398  }
399
400  return result;
401}
402
403#define MAX_BUFF 258
404#define MAX_SEARCH 3
405/* Find the class/instance in the .crypt-table */
406char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance)
407{
408  char *keyfile = NULL;
409  char *varname[MAX_SEARCH];
410  int length[MAX_SEARCH], i;
411  char buffer[MAX_BUFF];
412  char *filename;
413  char result[MAX_SEARCH][MAX_BUFF];
414  int numsearch = 0;
415  FILE *fsearch;
416
417  memset(varname, 0, sizeof(varname));
418
419  /* Determine names to look for in .crypt-table */
420  if (instance)
421    varname[numsearch++] = g_strdup_printf("crypt-%s-%s:", (class?class:"message"), instance);
422  if (class)
423    varname[numsearch++] = g_strdup_printf("crypt-%s:", class);
424  varname[numsearch++] = g_strdup("crypt-default:");
425
426  /* Setup the result array, and determine string lengths */
427  for (i = 0; i < numsearch; i++)
428  {
429    result[i][0] = '\0';
430    length[i] = strlen(varname[i]);
431  }
432
433  /* Open~/.crypt-table */
434  filename = g_strdup_printf("%s/.crypt-table", getenv("HOME"));
435  fsearch = fopen(filename, "r");
436  if (fsearch)
437  {
438    /* Scan file for a match */
439    while (!feof(fsearch))
440    {
441      if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break;
442      for (i = 0; i < numsearch; i++)
443        if (strncasecmp(varname[i], buffer, length[i]) == 0)
444        {
445          int j;
446          for (j = length[i]; buffer[j] == ' '; j++)
447            ;
448          strcpy(result[i], &buffer[j]);
449          if (*result[i])
450            if (result[i][strlen(result[i])-1] == '\n')
451              result[i][strlen(result[i])-1] = '\0';
452        }
453    }
454
455    /* Pick the "best" match found */
456    keyfile = NULL;
457    for (i = 0; i < numsearch; i++)
458      if (*result[i])
459      {
460        keyfile = result[i];
461        break;
462      }
463
464    if (keyfile != NULL)
465    {
466      /* Prepare result to be returned */
467      char *temp = keyfile;
468      keyfile = (char *)malloc(strlen(temp) + 1);
469      if (keyfile)
470        strcpy(keyfile, temp);
471      else
472        fprintf(stderr, "Memory allocation error.\n");
473    }
474    fclose(fsearch);
475  }
476  else
477    fprintf(stderr, "Could not open key table file: %s\n", filename);
478
479  for(i = 0; i < MAX_SEARCH; i++) {
480    if(varname[i] != NULL) {
481      g_free(varname[i]);
482    }
483  }
484
485  if(filename != NULL) {
486    g_free(filename);
487  }
488
489  return keyfile;
490}
491
492static pid_t zephyrpipe_pid = 0;
493
494/* Open a pipe to zwrite */
495FILE *GetZephyrPipe(const char *class, const char *instance, const ZWRITEOPTIONS *zoptions)
496{
497  int fildes[2];
498  pid_t pid;
499  FILE *result;
500  const char *argv[20];
501  int argc = 0;
502
503  if (pipe(fildes) < 0)
504    return NULL;
505  pid = fork();
506
507  if (pid < 0)
508  {
509    /* Error: clean up */
510    close(fildes[0]);
511    close(fildes[1]);
512    result = NULL;
513  }
514  else if (pid == 0)
515  {
516    /* Setup child process */
517    argv[argc++] = "zwrite";
518    argv[argc++] = "-n";     /* Always send without ping */
519    if (class)
520    {
521      argv[argc++] = "-c";
522      argv[argc++] = class;
523    }
524    if (instance)
525    {
526      argv[argc++] = "-i";
527      argv[argc++] = instance;
528    }
529    if (zoptions->flags & ZWRITE_OPT_NOAUTH)
530      argv[argc++] = "-d";
531    if (zoptions->flags & ZWRITE_OPT_QUIET)
532      argv[argc++] = "-q";
533    if (zoptions->flags & ZWRITE_OPT_VERBOSE)
534      argv[argc++] = "-v";
535    if (zoptions->flags & ZWRITE_OPT_SIGNATURE)
536    {
537      argv[argc++] = "-s";
538      argv[argc++] = zoptions->signature;
539    }
540    argv[argc++] = "-O";
541    argv[argc++] = "crypt";
542    argv[argc] = NULL;
543    close(fildes[1]);
544    if (fildes[0] != STDIN_FILENO)
545    {
546      if (dup2(fildes[0], STDIN_FILENO) != STDIN_FILENO)
547        exit(0);
548      close(fildes[0]);
549    }
550    close(fildes[0]);
551    execvp(argv[0], (char **)argv);
552    fprintf(stderr, "Exec error: could not run zwrite\n");
553    exit(0);
554  }
555  else
556  {
557    close(fildes[0]);
558    /* Create a FILE * for the zwrite pipe */
559    result = (FILE *)fdopen(fildes[1], "w");
560    zephyrpipe_pid = pid;
561  }
562
563  return result;
564}
565
566/* Close the pipe to zwrite */
567void CloseZephyrPipe(FILE *pipe)
568{
569  fclose(pipe);
570  waitpid(zephyrpipe_pid, NULL, 0);
571  zephyrpipe_pid = 0;
572}
573
574#define BASE_CODE 70
575#define LAST_CODE (BASE_CODE + 15)
576#define OUTPUT_BLOCK_SIZE 16
577
578void block_to_ascii(unsigned char *output, FILE *outfile)
579{
580  int i;
581  for (i = 0; i < 8; i++)
582  {
583    putc(((output[i] & 0xf0) >> 4) + BASE_CODE, outfile);
584    putc( (output[i] & 0x0f)       + BASE_CODE, outfile);
585  }
586}
587
588char *slurp_stdin(int ignoredot, int *length) {
589  char *buf;
590  char *inptr;
591
592  if ((inptr = buf = (char *)malloc(MAX_RESULT)) == NULL)
593  {
594    fprintf(stderr, "Memory allocation error\n");
595    return NULL;
596  }
597  while (inptr - buf < MAX_RESULT - MAX_LINE - 20)
598  {
599    if (fgets(inptr, MAX_LINE, stdin) == NULL)
600      break;
601
602    if (inptr[0])
603    {
604      if (inptr[0] == '.' && inptr[1] == '\n' && !ignoredot)
605      {
606        inptr[0] = '\0';
607        break;
608      }
609      else
610        inptr += strlen(inptr);
611    }
612    else
613      break;
614  }
615  *length = inptr - buf;
616
617  return buf;
618}
619
620char *GetInputBuffer(ZWRITEOPTIONS *zoptions, int *length) {
621  char *buf;
622
623  if (zoptions->flags & ZCRYPT_OPT_MESSAGE)
624  {
625    /* Use the -m message */
626    buf = strdup(zoptions->message);
627    *length = strlen(buf);
628  }
629  else
630  {
631    if (isatty(0)) {
632      /* tty input, so show the "Type your message now..." message */
633      if (zoptions->flags & ZCRYPT_OPT_IGNOREDOT)
634        printf("Type your message now.  End with the end-of-file character.\n");
635      else
636        printf("Type your message now.  End with control-D or a dot on a line by itself.\n");
637    } else {
638      zoptions->flags |= ZCRYPT_OPT_IGNOREDOT;
639    }
640
641    buf = slurp_stdin(zoptions->flags & ZCRYPT_OPT_IGNOREDOT, length);
642  }
643  return buf;
644}
645
646char *read_keystring(const char *keyfile) {
647  char *keystring;
648  FILE *fkey = fopen(keyfile, "r");
649  if(!fkey) {
650    fprintf(stderr, "Unable to open keyfile %s\n", keyfile);
651    return NULL;
652  }
653  keystring = malloc(MAX_KEY);
654  if(!fgets(keystring, MAX_KEY-1, fkey)) {
655    fprintf(stderr, "Unable to read from keyfile: %s\n", keyfile);
656    free(keystring);
657    keystring = NULL;
658  }
659  fclose(fkey);
660  return keystring;
661}
662
663/* Encrypt stdin, with prompt if isatty, and send to stdout, or to zwrite
664   if zephyr is set. */
665int do_encrypt(int zephyr, const char *class, const char *instance,
666               ZWRITEOPTIONS *zoptions, const char *keyfile, int cipher)
667{
668  FILE *outfile = stdout;
669  char *inbuff = NULL;
670  int buflen;
671  int out = TRUE;
672
673  inbuff = GetInputBuffer(zoptions, &buflen);
674
675  if(!inbuff) {
676    fprintf(stderr, "Error reading zcrypt input!\n");
677    return FALSE;
678  }
679
680  if (zephyr) {
681    outfile = GetZephyrPipe(class, instance, zoptions);
682    if (!outfile)
683    {
684      fprintf(stderr, "Could not run zwrite\n");
685      if (inbuff)
686        free(inbuff);
687      return FALSE;
688    }
689  }
690
691  out = ciphers[cipher].encrypt(keyfile, inbuff, buflen, outfile);
692
693  if (zephyr)
694    CloseZephyrPipe(outfile);
695
696  free(inbuff);
697  return out;
698}
699
700int do_encrypt_des(const char *keyfile, const char *in, int length, FILE *outfile)
701{
702  des_key_schedule schedule;
703  unsigned char input[8], output[8];
704  const char *inptr;
705  int num_blocks, last_block_size;
706  char *keystring;
707  int size;
708
709  keystring = read_keystring(keyfile);
710  if(!keystring) {
711    return FALSE;
712  }
713
714  owl_zcrypt_string_to_schedule(keystring, &schedule);
715  free(keystring);
716
717  inptr = in;
718  num_blocks = (length + 7) / 8;
719  last_block_size = ((length + 7) % 8) + 1;
720
721  /* Encrypt the input (inbuff or stdin) and send it to outfile */
722  while (TRUE)
723  {
724    /* Get 8 bytes from buffer */
725    if (num_blocks > 1)
726    {
727      size = 8;
728      memcpy(input, inptr, size);
729      inptr += 8;
730      num_blocks--;
731    }
732    else if (num_blocks == 1)
733    {
734      size = last_block_size;
735      memcpy(input, inptr, size);
736      num_blocks--;
737    }
738    else
739      size = 0;
740
741    /* Check for EOF and pad the string to 8 chars, if needed */
742    if (size == 0)
743      break;
744    if (size < 8)
745      memset(input + size, 0, 8 - size);
746
747    /* Encrypt and output the block */
748    des_ecb_encrypt(&input, &output, schedule, TRUE);
749    block_to_ascii(output, outfile);
750
751    if (size < 8)
752      break;
753  }
754
755  putc('\n', outfile);
756
757  return TRUE;
758}
759
760int do_encrypt_aes(const char *keyfile, const char *in, int length, FILE *outfile)
761{
762  char *out;
763  int err, status;
764  const char *argv[] = {
765    "gpg",
766    "--symmetric",
767    "--batch",
768    "--quiet",
769    "--no-use-agent",
770    "--armor",
771    "--cipher-algo", "AES",
772    "--passphrase-file", keyfile,
773    NULL
774  };
775  err = call_filter("gpg", argv, in, &out, &status);
776  if(err || status) {
777    if(out) g_free(out);
778    return FALSE;
779  }
780  fwrite(out, strlen(out), 1, outfile);
781  g_free(out);
782  return TRUE;
783}
784
785/* Read a half-byte from stdin, skipping invalid characters.  Returns -1
786   if at EOF or file error */
787int read_ascii_nybble(void)
788{
789  char c;
790
791  while (TRUE)
792  {
793    if (fread(&c, 1, 1, stdin) == 0)
794      return -1;
795    else if (c >= BASE_CODE && c <= LAST_CODE)
796      return c - BASE_CODE;
797  }
798}
799
800/* Read both halves of the byte and return the single byte.  Returns -1
801   if at EOF or file error. */
802int read_ascii_byte(void)
803{
804  int c1, c2;
805  c1 = read_ascii_nybble();
806  if (c1 >= 0)
807  {
808    c2 = read_ascii_nybble();
809    if (c2 >= 0)
810    {
811      return c1 * 0x10 + c2;
812    }
813  }
814  return -1;
815}
816
817/* Read an 8-byte DES block from stdin */
818int read_ascii_block(unsigned char *input)
819{
820  int c;
821
822  int i;
823  for (i = 0; i < 8; i++)
824  {
825    c = read_ascii_byte();
826    if (c < 0)
827      return FALSE;
828
829    input[i] = c;
830  }
831
832  return TRUE;
833}
834
835/* Decrypt stdin */
836int do_decrypt(const char *keyfile, int cipher)
837{
838  return ciphers[cipher].decrypt(keyfile);
839}
840
841int do_decrypt_aes(const char *keyfile) {
842  char *in, *out;
843  int length;
844  const char *argv[] = {
845    "gpg",
846    "--decrypt",
847    "--batch",
848    "--no-use-agent",
849    "--quiet",
850    "--passphrase-file", keyfile,
851    NULL
852  };
853  int err, status;
854
855  in = slurp_stdin(TRUE, &length);
856  if(!in) return FALSE;
857
858  err = call_filter("gpg", argv, in, &out, &status);
859  if(err || status) {
860    if(out) g_free(out);
861    return FALSE;
862  }
863  fwrite(out, strlen(out), 1, stdout);
864  g_free(out);
865
866  return TRUE;
867}
868
869int do_decrypt_des(const char *keyfile) {
870  des_key_schedule schedule;
871  unsigned char input[8], output[8];
872  char tmp[9];
873  char *keystring;
874
875  /*
876    DES decrypts 8 bytes at a time. We copy those over into the 9-byte
877    'tmp', which has the final byte zeroed, to ensure that we always
878    have a NULL-terminated string we can call printf/strlen on.
879
880    We don't pass 'tmp' to des_ecb_encrypt directly, because it's
881    prototyped as taking 'unsigned char[8]', and this avoids a stupid
882    cast.
883
884    We zero 'tmp' entirely, not just the final byte, in case there are
885    no input blocks.
886  */
887  memset(tmp, 0, sizeof tmp);
888
889  keystring = read_keystring(keyfile);
890  if(!keystring) return FALSE;
891
892  owl_zcrypt_string_to_schedule(keystring, &schedule);
893
894  free(keystring);
895
896  while (read_ascii_block(input))
897  {
898    des_ecb_encrypt(&input, &output, schedule, FALSE);
899    memcpy(tmp, output, 8);
900    printf("%s", tmp);
901  }
902
903  if (!tmp[0] || tmp[strlen(tmp) - 1] != '\n')
904      printf("\n");
905  return TRUE;
906}
Note: See TracBrowser for help on using the repository browser.