source: zcrypt.c @ fe73d0c

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