1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  23 /*        All Rights Reserved   */
  24 
  25 
  26 /*
  27  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 /*
  32  *      A one-rotor machine designed along the lines of Enigma
  33  *      but considerably trivialized.
  34  */
  35 
  36 #define ECHO 010
  37 #include <stdio.h>
  38 #include <stdlib.h>
  39 #include <unistd.h>
  40 #include <string.h>
  41 #include <crypt.h>
  42 #include <errno.h>
  43 
  44 #define ROTORSZ 256
  45 #define MASK 0377
  46 char    t1[ROTORSZ];
  47 char    t2[ROTORSZ];
  48 char    t3[ROTORSZ];
  49 
  50 static void
  51 setup(pw)
  52 char *pw;
  53 {
  54         int ic, i, k, temp;
  55         unsigned random;
  56         char buf[13];
  57         long seed;
  58         char *ret;
  59         int err;
  60 
  61         (void) strncpy(buf, pw, 8);
  62         buf[8] = buf[0];
  63         buf[9] = buf[1];
  64         errno = 0;
  65         ret = des_crypt(buf, &buf[8]);
  66         if (ret == NULL) {
  67                 err = errno;
  68                 (void) fprintf(stderr, "crypt: setup failed, unable to"
  69                     " initialize rotors: %s\n", strerror(err));
  70                 exit(1);
  71         }
  72         (void) strncpy(buf, ret, 13);
  73         seed = 123;
  74         for (i = 0; i < 13; i++)
  75                 seed = seed*buf[i] + i;
  76         for (i = 0; i < ROTORSZ; i++) {
  77                 t1[i] = i;
  78                 t3[i] = 0;
  79         }
  80         for (i = 0; i < ROTORSZ; i++) {
  81                 seed = 5*seed + buf[i%13];
  82                 random = seed % 65521;
  83                 k = ROTORSZ-1 - i;
  84                 ic = (random&MASK)%(k+1);
  85                 random >>= 8;
  86                 temp = t1[k];
  87                 t1[k] = t1[ic];
  88                 t1[ic] = temp;
  89                 if (t3[k] != 0) continue;
  90                 ic = (random&MASK) % k;
  91                 while (t3[ic] != 0) ic = (ic+1) % k;
  92                 t3[k] = ic;
  93                 t3[ic] = k;
  94         }
  95         for (i = 0; i < ROTORSZ; i++)
  96                 t2[t1[i]&MASK] = i;
  97 }
  98 
  99 int
 100 main(int argc, char **argv)
 101 {
 102         extern int optind;
 103         char *p1;
 104         int i, n1, n2, nchar;
 105         int c;
 106         struct {
 107                 long offset;
 108                 unsigned int count;
 109         } header;
 110         int pflag = 0;
 111         int kflag = 0;
 112         char *buf;
 113         char key[8];
 114         char keyvar[] = "CrYpTkEy=XXXXXXXX";
 115         char *s;
 116 
 117         if (argc < 2) {
 118                 if ((buf = (char *)getpass("Enter key:")) == NULL) {
 119                         (void) fprintf(stderr, "Cannot open /dev/tty\n");
 120                         exit(1);
 121                 }
 122                 setup(buf);
 123         } else {
 124                 while ((c = getopt(argc, argv, "pk")) != EOF)
 125                         switch (c) {
 126                         case 'p':
 127                         /* notify editor that exec has succeeded */
 128                                 if (write(1, "y", 1) != 1)
 129                                         exit(1);
 130                                 if (read(0, key, 8) != 8)
 131                                         exit(1);
 132                                 setup(key);
 133                                 pflag = 1;
 134                                 break;
 135                         case 'k':
 136                                 if ((s = getenv("CrYpTkEy")) == (char *)NULL) {
 137                                         (void) fprintf(stderr,
 138                                             "CrYpTkEy not set.\n");
 139                                         exit(1);
 140                                 }
 141                                 (void) strncpy(key, s, 8);
 142                                 setup(key);
 143                                 kflag = 1;
 144                                 break;
 145                         case '?':
 146                                 (void) fprintf(stderr,
 147                                     "usage: crypt [ -k ] [ key]\n");
 148                                 exit(2);
 149                         }
 150                 if (pflag == 0 && kflag == 0) {
 151                         (void) strncpy(keyvar+9, argv[optind], 8);
 152                         (void) putenv(keyvar);
 153                         (void) execlp("crypt", "crypt", "-k", 0);
 154                 }
 155         }
 156         if (pflag)
 157                 for (;;) {
 158                         if ((nchar = read(0, (char *)&header, sizeof (header)))
 159                             != sizeof (header))
 160                                 exit(nchar);
 161                         n1 = (int)(header.offset&MASK);
 162                         n2 = (int)((header.offset >> 8) &MASK);
 163                         nchar = header.count;
 164                         buf = (char *)malloc(nchar);
 165                         p1 = buf;
 166                         if (read(0, buf, nchar) != nchar)
 167                                 exit(1);
 168                         while (nchar--) {
 169                                 *p1 = t2[(t3[(t1[(*p1 + n1)&MASK]+
 170                                     n2)&MASK] - n2)&MASK] - n1;
 171                                 n1++;
 172                                 if (n1 == ROTORSZ) {
 173                                         n1 = 0;
 174                                         n2++;
 175                                         if (n2 == ROTORSZ) n2 = 0;
 176                                 }
 177                                 p1++;
 178                         }
 179                         nchar = header.count;
 180                         if (write(1, buf, nchar) != nchar)
 181                                 exit(1);
 182                         free(buf);
 183                 }
 184 
 185         n1 = 0;
 186         n2 = 0;
 187 
 188         while ((i = getchar()) >= 0) {
 189                 i = t2[(t3[(t1[(i+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
 190                 (void) putchar(i);
 191                 n1++;
 192                 if (n1 == ROTORSZ) {
 193                         n1 = 0;
 194                         n2++;
 195                         if (n2 == ROTORSZ) n2 = 0;
 196                 }
 197         }
 198         return (0);
 199 }