source: zcrypt.c

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