source: zcrypt.c @ 78f6c35

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