crypt.c (3913B)
1 /* 2 * "enigma.c" is in file cbw.tar from 3 * anonymous FTP host watmsg.waterloo.edu: pub/crypt/cbw.tar.Z 4 * 5 * A one-rotor machine designed along the lines of Enigma 6 * but considerably trivialized. 7 * 8 * A public-domain replacement for the UNIX "crypt" command. 9 * 10 * Upgraded to function properly on 64-bit machines. 11 */ 12 13 #include "config.h" 14 15 #if HAVE_ERR 16 #include <err.h> 17 #endif 18 #if HAVE_READPASSPHRASE 19 #include <readpassphrase.h> 20 #endif 21 #include <stdint.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "des.h" 28 29 #define CRYPTKEY_ENV "CrYpTkEy" 30 #define ROTORSZ 256 31 #define MASK 0377 32 33 static char t1[ROTORSZ] = {0}; 34 static char t2[ROTORSZ] = {0}; 35 static char t3[ROTORSZ] = {0}; 36 static char deck[ROTORSZ] = {0}; 37 static char buf[13] = {0}; 38 39 static void shuffle(void); 40 static void setup(char *); 41 42 static void 43 setup(char *passwd) 44 { 45 int32_t ic, i, k; 46 static int32_t seed = 123; 47 uint32_t rnd; 48 char salt[3], cryptpw[DES_BUFFER_SIZE], temp; 49 50 strlcpy(salt, passwd, sizeof(salt)); 51 52 if (des(passwd, salt, cryptpw) == -1) 53 errx(1, "des"); 54 55 memcpy(buf, cryptpw, sizeof(buf)); 56 explicit_bzero(passwd, sizeof(passwd)); 57 explicit_bzero(salt, sizeof(salt)); 58 explicit_bzero(cryptpw, sizeof(cryptpw)); 59 60 for (i = 0; i < 13; i++) 61 seed = seed * buf[i] + i; 62 63 for (i = 0; i < ROTORSZ; i++) 64 t1[i] = deck[i] = i; 65 66 for (i = 0; i < ROTORSZ; i++) { 67 seed = 5 * seed + buf[i % 13]; 68 rnd = seed % 65521; 69 k = ROTORSZ - 1 - i; 70 ic = (rnd & MASK) % (k + 1); 71 rnd >>= 8; 72 73 temp = t1[k]; 74 t1[k] = t1[ic]; 75 t1[ic] = temp; 76 77 if (t3[k] != 0) 78 continue; 79 80 ic = (rnd & MASK) % k; 81 while (t3[ic] != 0) 82 ic = (ic + 1) % k; 83 84 t3[k] = ic; 85 t3[ic] = k; 86 } 87 88 for (i = 0; i < ROTORSZ; i++) 89 t2[t1[i] & MASK] = i; 90 } 91 92 int 93 main(int argc, char **argv) 94 { 95 int i, n1, n2, nr1, nr2, ch; 96 int kflag = 0, sflag = 0; 97 char *cryptkey, passbuf[31]; 98 99 #if HAVE_PLEDGE 100 if (pledge("stdio tty", NULL) == -1) 101 err(1, "pledge"); 102 #endif 103 104 while ((ch = getopt(argc, argv, "ks")) != -1) { 105 switch (ch) { 106 case 'k': 107 kflag = 1; 108 break; 109 case 's': 110 sflag = 1; 111 break; 112 default: 113 goto usage; 114 } 115 } 116 argc -= optind; 117 argv += optind; 118 119 if (argc > 1) 120 errx(1, "Too many arguments, have %d", argc); 121 122 if (kflag) { 123 if ((cryptkey = getenv(CRYPTKEY_ENV)) == NULL) 124 errx(1, "%s is unset", CRYPTKEY_ENV); 125 setup(cryptkey); 126 } else if (argc == 0) { 127 if (readpassphrase("Enter Key: ", passbuf, sizeof(passbuf), 128 RPP_REQUIRE_TTY) == NULL) 129 errx(1, "unable to read password"); 130 cryptkey = passbuf; 131 } else { 132 cryptkey = argv[0]; 133 } 134 135 #if HAVE_PLEDGE 136 if (pledge("stdio", NULL) == -1) 137 err(1, "pledge"); 138 #endif 139 140 /* 141 * The first two bytes of the key are used as the salt, 142 * and since we skip the salt check with crypt_set_format(), 143 * we should check it here. 144 */ 145 if (strspn(cryptkey, DES_SALT_ALPHABET) != strlen(cryptkey)) 146 errx(1, "key contains invalid characters"); 147 setup(cryptkey); 148 149 n1 = n2 = nr2 = 0; 150 while ((i = getchar()) != EOF) { 151 if (sflag) { 152 nr1 = deck[n1] & MASK; 153 nr2 = deck[nr1] & MASK; 154 } else { 155 nr1 = n1; 156 } 157 158 i = t2[(t3[(t1[(i+nr1)&MASK]+nr2)&MASK]-nr2)&MASK]-nr1; 159 if (putchar(i) == EOF) 160 err(1, "putchar"); 161 162 n1++; 163 if (n1 == ROTORSZ) { 164 n1 = 0; 165 n2++; 166 167 if (n2 == ROTORSZ) 168 n2 = 0; 169 170 if (sflag) 171 shuffle(); 172 else 173 nr2 = n2; 174 } 175 } 176 177 explicit_bzero(buf, sizeof(buf)); 178 179 if (ferror(stdin)) 180 err(1, "ferror"); 181 if (fclose(stdout) == EOF) 182 err(1, "stdout"); 183 184 return 0; 185 186 usage: 187 fprintf(stderr, "usage: %s [-ks] password\n", getprogname()); 188 189 return 1; 190 } 191 192 static void 193 shuffle(void) 194 { 195 int32_t i, ic, k; 196 static int32_t seed = 123; 197 uint32_t rnd; 198 char temp; 199 200 for (i = 0; i < ROTORSZ; i++) { 201 seed = 5 * seed + buf[i % 13]; 202 rnd = seed % 65521; 203 k = ROTORSZ - 1 - i; 204 ic = (rnd & MASK) % (k + 1); 205 206 temp = deck[k]; 207 deck[k] = deck[ic]; 208 deck[ic] = temp; 209 } 210 }