source: zcrypt.c @ 8bd190d

release-1.10release-1.6release-1.7release-1.8release-1.9
Last change on this file since 8bd190d was 8bd190d, checked in by Nelson Elhage <nelhage@ksplice.com>, 14 years ago
zcrypt: Implement AES encryption support using GPG.
  • Property mode set to 100644
File size: 20.0 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#ifdef HAVE_KERBEROS_IV
21#include <kerberosIV/des.h>
22#else
23#include <openssl/des.h>
24#endif
25
26#include "filterproc.h"
27
28#define MAX_KEY      128
29#define MAX_LINE     128
30#define MAX_RESULT   4096
31
32#ifndef TRUE
33#define TRUE -1
34#endif
35#ifndef FALSE
36#define FALSE 0
37#endif
38
39#define ZWRITE_OPT_NOAUTH     (1<<0)
40#define ZWRITE_OPT_SIGNATURE  (1<<1)
41#define ZWRITE_OPT_IGNOREVARS (1<<2)
42#define ZWRITE_OPT_VERBOSE    (1<<3)
43#define ZWRITE_OPT_QUIET      (1<<4)
44#define ZCRYPT_OPT_MESSAGE    (1<<5)
45#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
46
47typedef struct
48{
49  int flags;
50  char *signature;
51  char *message;
52} ZWRITEOPTIONS;
53
54char *GetZephyrVarKeyFile(char *whoami, char *class, char *instance);
55int ParseCryptSpec(char *spec, char **keyfile);
56char *BuildArgString(char **argv, int start, int end);
57char *read_keystring(char *keyfile);
58
59int do_encrypt(int zephyr, char *class, char *instance,
60               ZWRITEOPTIONS *zoptions, char* keyfile, int cipher);
61int do_encrypt_des(char *keyfile, char *in, int len, FILE *out);
62int do_encrypt_aes(char *keyfile, char *in, int len, FILE *out);
63
64int do_decrypt(char *keyfile, int cipher);
65int do_decrypt_aes(char *keyfile);
66int do_decrypt_des(char *keyfile);
67
68
69#define M_NONE            0
70#define M_ZEPHYR_ENCRYPT  1
71#define M_DECRYPT         2
72#define M_ENCRYPT         3
73#define M_RANDOMIZE       4
74#define M_SETKEY          5
75
76#define CIPHER_ERR        -1
77#define CIPHER_DES        0
78#define CIPHER_AES        1
79
80static void owl_zcrypt_string_to_schedule(char *keystring, des_key_schedule *schedule) {
81#ifdef HAVE_KERBEROS_IV
82  des_cblock key;
83#else
84  des_cblock _key, *key = &_key;
85#endif
86
87  des_string_to_key(keystring, key);
88  des_key_sched(key, *schedule);
89}
90
91int main(int argc, char *argv[])
92{
93  char *cryptspec = NULL;
94  char *keyfile;
95  int cipher;
96  int error = FALSE;
97  int zephyr = FALSE;
98  char *class = NULL, *instance = NULL;
99  int mode = M_NONE;
100
101  extern int optind, opterr;
102  extern char *optarg;
103  char c;
104
105  int messageflag = FALSE;
106  ZWRITEOPTIONS zoptions;
107  zoptions.flags = 0;
108
109  while ((c = getopt(argc, argv, "ZDERSF:c:i:advqtluons:f:m")) != (char)EOF)
110  {
111    switch(c)
112    {
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 (cryptspec != NULL) error = TRUE;
136        cryptspec = 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)
200      break;
201  }
202
203  if (class != NULL || instance != NULL)
204    zephyr = TRUE;
205
206  if (messageflag)
207  {
208    zoptions.flags |= ZCRYPT_OPT_MESSAGE;
209    zoptions.message = BuildArgString(argv, optind, argc);
210    if (!zoptions.message)
211    {
212      fprintf(stderr, "Memory allocation error.\n");
213      error = TRUE;
214    }
215  }
216  else if (optind < argc)
217  {
218    error = TRUE;
219  }
220
221  if (mode == M_NONE)
222    mode = (zephyr?M_ZEPHYR_ENCRYPT:M_ENCRYPT);
223
224  if (mode == M_ZEPHYR_ENCRYPT && !zephyr)
225    error = TRUE;
226
227  if (!error && cryptspec == NULL && (class != NULL || instance != NULL)) {
228    cryptspec = GetZephyrVarKeyFile(argv[0], class, instance);
229    if(!cryptspec) {
230      fprintf(stderr, "Unable to find keyfile for ");
231      if(class != NULL) {
232        fprintf(stderr, "-c %s ", class);
233      }
234      if(instance != NULL) {
235        fprintf(stderr, "-i %s ", instance);
236      }
237      fprintf(stderr, "\n");
238      exit(-1);
239    }
240  }
241
242  if (error)
243  {
244    fprintf(stderr, "Usage: %s [-Z|-D|-E|-R|-S] [-F Keyfile] [-c class] [-i instance]\n", argv[0]);
245    fprintf(stderr, "       [-advqtluon] [-s signature] [-f arg] [-m message]\n");
246    fprintf(stderr, "  One or more of class, instance, and keyfile must be specified.\n");
247    exit(1);
248  }
249
250  cipher = ParseCryptSpec(cryptspec, &keyfile);
251  if(cipher < 0) {
252    fprintf(stderr, "Invalid cipher specification: %s\n", cryptspec);
253    exit(1);
254  }
255
256
257  if (mode == M_RANDOMIZE)
258  {
259    /* Choose a new, random key */
260    /*
261      FILE *fkey = fopen(fname, "w");
262      if (!fkey)
263      printf("Could not open key file for writing: %s\n", fname);
264      else
265      {
266      char string[100];
267      fputs(fkey, string);
268      fclose(fkey);
269      }
270    */
271    fprintf(stderr, "Feature not yet implemented.\n");
272  }
273  else if (mode == M_SETKEY)
274  {
275    /* Set a new, user-entered key */
276    char newkey[MAX_KEY];
277    FILE *fkey;
278
279    if (isatty(0))
280    {
281      printf("Enter new key: ");
282      /* Really should read without echo!!! */
283    }
284    if(!fgets(newkey, MAX_KEY - 1, stdin)) {
285      fprintf(stderr, "Error reading key.\n");
286      return 1;
287    }
288
289    fkey = fopen(keyfile, "w");
290    if (!fkey)
291      fprintf(stderr, "Could not open key file for writing: %s\n", keyfile);
292    else
293    {
294      if (fputs(newkey, fkey) != strlen(newkey) || putc('\n', fkey) != '\n')
295      {
296        fprintf(stderr, "Error writing to key file.\n");
297        fclose(fkey);
298        exit(1);
299      }
300      else
301      {
302        fclose(fkey);
303        fprintf(stderr, "Key update complete.\n");
304      }
305    }
306  }
307  else
308  {
309    if (mode == M_ZEPHYR_ENCRYPT || mode == M_ENCRYPT)
310      error = !do_encrypt((mode == M_ZEPHYR_ENCRYPT), class, instance,
311                          &zoptions, keyfile, cipher);
312    else
313      error = !do_decrypt(keyfile, cipher);
314  }
315
316  /* Always print the **END** message if -D is specified. */
317  if (mode == M_DECRYPT)
318    printf("**END**\n");
319
320  return error;
321}
322
323int ParseCryptSpec(char *spec, char **keyfile) {
324  int cipher = CIPHER_DES;
325  char *cipher_name = strdup(spec);
326  char *colon = strchr(cipher_name, ':');
327
328  *keyfile = spec;
329
330  if (colon) {
331    char *rest = strchr(spec, ':') + 1;
332    while(isspace(*rest)) rest++;
333
334    *colon-- = '\0';
335    while (colon >= cipher_name && isspace(*colon)) {
336      *colon = '\0';
337    }
338
339    if(strcmp(cipher_name, "AES") == 0) {
340      cipher = CIPHER_AES;
341      *keyfile = rest;
342    } else if(strcmp(cipher_name, "DES") == 0) {
343      cipher = CIPHER_DES;
344      *keyfile = rest;
345    }
346  }
347
348  free(cipher_name);
349
350  return cipher;
351}
352
353/* Build a space-separated string from argv from elements between start  *
354 * and end - 1.  malloc()'s the returned string. */
355char *BuildArgString(char **argv, int start, int end)
356{
357  int len = 1;
358  int i;
359  char *result;
360
361  /* Compute the length of the string.  (Plus 1 or 2) */
362  for (i = start; i < end; i++)
363    len += strlen(argv[i]) + 1;
364
365  /* Allocate memory */
366  result = (char *)malloc(len);
367  if (result)
368  {
369    /* Build the string */
370    char *ptr = result;
371    /* Start with an empty string, in case nothing is copied. */
372    *ptr = '\0';
373    /* Copy the arguments */
374    for (i = start; i < end; i++)
375    {
376      char *temp = argv[i];
377      /* Add a space, if not the first argument */
378      if (i != start)
379        *ptr++ = ' ';
380      /* Copy argv[i], leaving ptr pointing to the '\0' copied from temp */
381      while ((*ptr = *temp++))
382        ptr++;
383    }
384  }
385
386  return result;
387}
388
389#define MAX_BUFF 258
390#define MAX_SEARCH 3
391/* Find the class/instance in the .crypt-table */
392char *GetZephyrVarKeyFile(char *whoami, char *class, char *instance)
393{
394  char *keyfile = NULL;
395  char *varname[MAX_SEARCH];
396  int length[MAX_SEARCH], i;
397  char buffer[MAX_BUFF];
398  char *filename;
399  char result[MAX_SEARCH][MAX_BUFF];
400  int numsearch = 0;
401  FILE *fsearch;
402
403  memset(varname, 0, sizeof(varname));
404
405  /* Determine names to look for in .crypt-table */
406  if (instance)
407    varname[numsearch++] = g_strdup_printf("crypt-%s-%s:", (class?class:"message"), instance);
408  if (class)
409    varname[numsearch++] = g_strdup_printf("crypt-%s:", class);
410  varname[numsearch++] = g_strdup("crypt-default:");
411
412  /* Setup the result array, and determine string lengths */
413  for (i = 0; i < numsearch; i++)
414  {
415    result[i][0] = '\0';
416    length[i] = strlen(varname[i]);
417  }
418
419  /* Open~/.crypt-table */
420  filename = g_strdup_printf("%s/.crypt-table", getenv("HOME"));
421  fsearch = fopen(filename, "r");
422  if (fsearch)
423  {
424    /* Scan file for a match */
425    while (!feof(fsearch))
426    {
427      if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break;
428      for (i = 0; i < numsearch; i++)
429        if (strncasecmp(varname[i], buffer, length[i]) == 0)
430        {
431          int j;
432          for (j = length[i]; buffer[j] == ' '; j++)
433            ;
434          strcpy(result[i], &buffer[j]);
435          if (*result[i])
436            if (result[i][strlen(result[i])-1] == '\n')
437              result[i][strlen(result[i])-1] = '\0';
438        }
439    }
440
441    /* Pick the "best" match found */
442    keyfile = NULL;
443    for (i = 0; i < numsearch; i++)
444      if (*result[i])
445      {
446        keyfile = result[i];
447        break;
448      }
449
450    if (keyfile != NULL)
451    {
452      /* Prepare result to be returned */
453      char *temp = keyfile;
454      keyfile = (char *)malloc(strlen(temp) + 1);
455      if (keyfile)
456        strcpy(keyfile, temp);
457      else
458        fprintf(stderr, "Memory allocation error.\n");
459    }
460    fclose(fsearch);
461  }
462  else
463    fprintf(stderr, "Could not open key table file: %s\n", filename);
464
465  for(i = 0; i < MAX_SEARCH; i++) {
466    if(varname[i] != NULL) {
467      g_free(varname[i]);
468    }
469  }
470
471  if(filename != NULL) {
472    g_free(filename);
473  }
474
475  return keyfile;
476}
477
478static pid_t zephyrpipe_pid = 0;
479
480/* Open a pipe to zwrite */
481FILE *GetZephyrPipe(char *class, char *instance, ZWRITEOPTIONS *zoptions)
482{
483  int fildes[2];
484  pid_t pid;
485  FILE *result;
486  char *argv[20];
487  int argc = 0;
488
489  if (pipe(fildes) < 0)
490    return NULL;
491  pid = fork();
492
493  if (pid < 0)
494  {
495    /* Error: clean up */
496    close(fildes[0]);
497    close(fildes[1]);
498    result = NULL;
499  }
500  else if (pid == 0)
501  {
502    /* Setup child process */
503    argv[argc++] = "zwrite";
504    argv[argc++] = "-n";     /* Always send without ping */
505    if (class)
506    {
507      argv[argc++] = "-c";
508      argv[argc++] = class;
509    }
510    if (instance)
511    {
512      argv[argc++] = "-i";
513      argv[argc++] = instance;
514    }
515    if (zoptions->flags & ZWRITE_OPT_NOAUTH)
516      argv[argc++] = "-d";
517    if (zoptions->flags & ZWRITE_OPT_QUIET)
518      argv[argc++] = "-q";
519    if (zoptions->flags & ZWRITE_OPT_VERBOSE)
520      argv[argc++] = "-v";
521    if (zoptions->flags & ZWRITE_OPT_SIGNATURE)
522    {
523      argv[argc++] = "-s";
524      argv[argc++] = zoptions->signature;
525    }
526    argv[argc++] = "-O";
527    argv[argc++] = "crypt";
528    argv[argc] = NULL;
529    close(fildes[1]);
530    if (fildes[0] != STDIN_FILENO)
531    {
532      if (dup2(fildes[0], STDIN_FILENO) != STDIN_FILENO)
533        exit(0);
534      close(fildes[0]);
535    }
536    close(fildes[0]);
537    execvp(argv[0], argv);
538    fprintf(stderr, "Exec error: could not run zwrite\n");
539    exit(0);
540  }
541  else
542  {
543    close(fildes[0]);
544    /* Create a FILE * for the zwrite pipe */
545    result = (FILE *)fdopen(fildes[1], "w");
546    zephyrpipe_pid = pid;
547  }
548
549  return result;
550}
551
552/* Close the pipe to zwrite */
553void CloseZephyrPipe(FILE *pipe)
554{
555  fclose(pipe);
556  waitpid(zephyrpipe_pid, NULL, 0);
557  zephyrpipe_pid = 0;
558}
559
560#define BASE_CODE 70
561#define LAST_CODE (BASE_CODE + 15)
562#define OUTPUT_BLOCK_SIZE 16
563
564void block_to_ascii(unsigned char *output, FILE *outfile)
565{
566  int i;
567  for (i = 0; i < 8; i++)
568  {
569    putc(((output[i] & 0xf0) >> 4) + BASE_CODE, outfile);
570    putc( (output[i] & 0x0f)       + BASE_CODE, outfile);
571  }
572}
573
574char *slurp_stdin(int ignoredot, int *length) {
575  char *buf;
576  char *inptr;
577
578  if ((inptr = buf = (char *)malloc(MAX_RESULT)) == NULL)
579  {
580    fprintf(stderr, "Memory allocation error\n");
581    return NULL;
582  }
583  while (inptr - buf < MAX_RESULT - MAX_LINE - 20)
584  {
585    if (fgets(inptr, MAX_LINE, stdin) == NULL)
586      break;
587
588    if (inptr[0])
589    {
590      if (inptr[0] == '.' && inptr[1] == '\n' && !ignoredot)
591      {
592        inptr[0] = '\0';
593        break;
594      }
595      else
596        inptr += strlen(inptr);
597    }
598    else
599      break;
600  }
601  *length = inptr - buf;
602
603  return buf;
604}
605
606char *GetInputBuffer(ZWRITEOPTIONS *zoptions, int *length) {
607  char *buf;
608
609  if (zoptions->flags & ZCRYPT_OPT_MESSAGE)
610  {
611    /* Use the -m message */
612    buf = strdup(zoptions->message);
613    *length = strlen(buf);
614  }
615  else
616  {
617    if (isatty(0)) {
618      /* tty input, so show the "Type your message now..." message */
619      if (zoptions->flags & ZCRYPT_OPT_IGNOREDOT)
620        printf("Type your message now.  End with the end-of-file character.\n");
621      else
622        printf("Type your message now.  End with control-D or a dot on a line by itself.\n");
623    } else {
624      zoptions->flags |= ZCRYPT_OPT_IGNOREDOT;
625    }
626
627    buf = slurp_stdin(zoptions->flags & ZCRYPT_OPT_IGNOREDOT, length);
628  }
629  return buf;
630}
631
632char *read_keystring(char *keyfile) {
633  char *keystring;
634  FILE *fkey = fopen(keyfile, "r");
635  if(!fkey) {
636    fprintf(stderr, "Unable to open keyfile %s\n", keyfile);
637    return NULL;
638  }
639  keystring = malloc(MAX_KEY);
640  if(!fgets(keystring, MAX_KEY-1, fkey)) {
641    fprintf(stderr, "Unable to read from keyfile: %s\n", keyfile);
642    free(keystring);
643    keystring = NULL;
644  }
645  fclose(fkey);
646  return keystring;
647}
648
649/* Encrypt stdin, with prompt if isatty, and send to stdout, or to zwrite
650   if zephyr is set. */
651int do_encrypt(int zephyr, char *class, char *instance,
652               ZWRITEOPTIONS *zoptions, char* keyfile, int cipher)
653{
654  FILE *outfile = stdout;
655  char *inbuff = NULL;
656  int buflen;
657  int out = TRUE;
658
659  inbuff = GetInputBuffer(zoptions, &buflen);
660
661  if(!inbuff) {
662    fprintf(stderr, "Error reading zcrypt input!\n");
663    return FALSE;
664  }
665
666  if (zephyr) {
667    outfile = GetZephyrPipe(class, instance, zoptions);
668    if (!outfile)
669    {
670      fprintf(stderr, "Could not run zwrite\n");
671      if (inbuff)
672        free(inbuff);
673      return FALSE;
674    }
675  }
676
677  switch(cipher) {
678  case CIPHER_DES:
679    out = do_encrypt_des(keyfile, inbuff, buflen, outfile);
680    break;
681  case CIPHER_AES:
682    out = do_encrypt_aes(keyfile, inbuff, buflen, outfile);
683    break;
684  }
685
686  if (zephyr)
687    CloseZephyrPipe(outfile);
688
689  free(inbuff);
690  return out;
691}
692
693int do_encrypt_des(char *keyfile, char *in, int length, FILE *outfile)
694{
695  des_key_schedule schedule;
696  unsigned char input[8], output[8];
697  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(char *keyfile, 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    if(out) 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(char *keyfile, int cipher)
830{
831  switch(cipher) {
832  case CIPHER_DES:
833    return do_decrypt_des(keyfile);
834  case CIPHER_AES:
835    return do_decrypt_aes(keyfile);
836  default:
837    return FALSE;
838  }
839}
840
841int do_decrypt_aes(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(char *keyfile) {
870  des_key_schedule schedule;
871  unsigned char input[8], output[8];
872  char *keystring;
873
874  output[0] = '\0';    /* In case no message at all                 */
875
876  keystring = read_keystring(keyfile);
877  if(!keystring) return FALSE;
878
879  owl_zcrypt_string_to_schedule(keystring, &schedule);
880
881  free(keystring);
882
883  while (read_ascii_block(input))
884  {
885    des_ecb_encrypt(&input, &output, schedule, FALSE);
886    printf("%s", output);
887  }
888
889  if (!output[0] || output[strlen((const char*)output) - 1] != '\n')
890      printf("\n");
891  return TRUE;
892}
Note: See TracBrowser for help on using the repository browser.