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 /* EXPORT DELETE START */
  37 #define ECHO 010
  38 #include <stdio.h>
  39 #include <stdlib.h>
  40 #include <unistd.h>
  41 #include <string.h>
  42 #include <crypt.h>
  43 #include <errno.h>
  44 
  45 #define ROTORSZ 256
  46 #define MASK 0377
  47 char    t1[ROTORSZ];
  48 char    t2[ROTORSZ];
  49 char    t3[ROTORSZ];
  50 
  51 static void
  52 setup(pw)
  53 char *pw;
  54 {
  55         int ic, i, k, temp;
  56         unsigned random;
  57         char buf[13];
  58         long seed;
  59         char *ret;
  60         int err;
  61 
  62         (void) strncpy(buf, pw, 8);
  63         buf[8] = buf[0];
  64         buf[9] = buf[1];
  65         errno = 0;
  66         ret = des_crypt(buf, &buf[8]);
  67         if (ret == NULL) {
  68                 err = errno;
  69                 (void) fprintf(stderr, "crypt: setup failed, unable to"
  70                     " initialize rotors: %s\n", strerror(err));
  71                 exit(1);
  72         }
  73         (void) strncpy(buf, ret, 13);
  74         seed = 123;
  75         for (i = 0; i < 13; i++)
  76                 seed = seed*buf[i] + i;
  77         for (i = 0; i < ROTORSZ; i++) {
  78                 t1[i] = i;
  79                 t3[i] = 0;
  80         }
  81         for (i = 0; i < ROTORSZ; i++) {
  82                 seed = 5*seed + buf[i%13];
  83                 random = seed % 65521;
  84                 k = ROTORSZ-1 - i;
  85                 ic = (random&MASK)%(k+1);
  86                 random >>= 8;
  87                 temp = t1[k];
  88                 t1[k] = t1[ic];
  89                 t1[ic] = temp;
  90                 if (t3[k] != 0) continue;
  91                 ic = (random&MASK) % k;
  92                 while (t3[ic] != 0) ic = (ic+1) % k;
  93                 t3[k] = ic;
  94                 t3[ic] = k;
  95         }
  96         for (i = 0; i < ROTORSZ; i++)
  97                 t2[t1[i]&MASK] = i;
  98 }
  99 /* EXPORT DELETE END */
 100 
 101 int
 102 main(int argc, char **argv)
 103 {
 104 /* EXPORT DELETE START */
 105         extern int optind;
 106         char *p1;
 107         int i, n1, n2, nchar;
 108         int c;
 109         struct {
 110                 long offset;
 111                 unsigned int count;
 112         } header;
 113         int pflag = 0;
 114         int kflag = 0;
 115         char *buf;
 116         char key[8];
 117         char keyvar[] = "CrYpTkEy=XXXXXXXX";
 118         char *s;
 119 
 120         if (argc < 2) {
 121                 if ((buf = (char *)getpass("Enter key:")) == NULL) {
 122                         (void) fprintf(stderr, "Cannot open /dev/tty\n");
 123                         exit(1);
 124                 }
 125                 setup(buf);
 126         } else {
 127                 while ((c = getopt(argc, argv, "pk")) != EOF)
 128                         switch (c) {
 129                         case 'p':
 130                         /* notify editor that exec has succeeded */
 131                                 if (write(1, "y", 1) != 1)
 132                                         exit(1);
 133                                 if (read(0, key, 8) != 8)
 134                                         exit(1);
 135                                 setup(key);
 136                                 pflag = 1;
 137                                 break;
 138                         case 'k':
 139                                 if ((s = getenv("CrYpTkEy")) == (char *)NULL) {
 140                                         (void) fprintf(stderr,
 141                                             "CrYpTkEy not set.\n");
 142                                         exit(1);
 143                                 }
 144                                 (void) strncpy(key, s, 8);
 145                                 setup(key);
 146                                 kflag = 1;
 147                                 break;
 148                         case '?':
 149                                 (void) fprintf(stderr,
 150                                     "usage: crypt [ -k ] [ key]\n");
 151                                 exit(2);
 152                         }
 153                 if (pflag == 0 && kflag == 0) {
 154                         (void) strncpy(keyvar+9, argv[optind], 8);
 155                         (void) putenv(keyvar);
 156                         (void) execlp("crypt", "crypt", "-k", 0);
 157                 }
 158         }
 159         if (pflag)
 160                 for (;;) {
 161                         if ((nchar = read(0, (char *)&header, sizeof (header)))
 162                             != sizeof (header))
 163                                 exit(nchar);
 164                         n1 = (int)(header.offset&MASK);
 165                         n2 = (int)((header.offset >> 8) &MASK);
 166                         nchar = header.count;
 167                         buf = (char *)malloc(nchar);
 168                         p1 = buf;
 169                         if (read(0, buf, nchar) != nchar)
 170                                 exit(1);
 171                         while (nchar--) {
 172                                 *p1 = t2[(t3[(t1[(*p1 + n1)&MASK]+
 173                                     n2)&MASK] - n2)&MASK] - n1;
 174                                 n1++;
 175                                 if (n1 == ROTORSZ) {
 176                                         n1 = 0;
 177                                         n2++;
 178                                         if (n2 == ROTORSZ) n2 = 0;
 179                                 }
 180                                 p1++;
 181                         }
 182                         nchar = header.count;
 183                         if (write(1, buf, nchar) != nchar)
 184                                 exit(1);
 185                         free(buf);
 186                 }
 187 
 188         n1 = 0;
 189         n2 = 0;
 190 
 191         while ((i = getchar()) >= 0) {
 192                 i = t2[(t3[(t1[(i+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
 193                 (void) putchar(i);
 194                 n1++;
 195                 if (n1 == ROTORSZ) {
 196                         n1 = 0;
 197                         n2++;
 198                         if (n2 == ROTORSZ) n2 = 0;
 199                 }
 200         }
 201         return (0);
 202 /* EXPORT DELETE END */
 203 }