enigma.c revision 78781
140767Sjoerg/* 240767Sjoerg * "enigma.c" is in file cbw.tar from 340767Sjoerg * anonymous FTP host watmsg.waterloo.edu: pub/crypt/cbw.tar.Z 440767Sjoerg * 540767Sjoerg * A one-rotor machine designed along the lines of Enigma 640767Sjoerg * but considerably trivialized. 740767Sjoerg * 840767Sjoerg * A public-domain replacement for the UNIX "crypt" command. 940767Sjoerg * 1040767Sjoerg * Upgraded to function properly on 64-bit machines. 1140767Sjoerg */ 1240767Sjoerg 1378310Seric#ifndef lint 1478310Sericstatic const char rcsid[] = 1578310Seric "$FreeBSD: head/usr.bin/enigma/enigma.c 78781 2001-06-25 21:25:27Z dd $"; 1678310Seric#endif /* not lint */ 1778310Seric 1840769Sjoerg#include <sys/types.h> 1940769Sjoerg#include <sys/wait.h> 2040769Sjoerg 2140769Sjoerg#include <stdio.h> 2240769Sjoerg#include <stdlib.h> 2340769Sjoerg#include <string.h> 2440769Sjoerg#include <unistd.h> 2540769Sjoerg 2640769Sjoerg#define MINUSKVAR "CrYpTkEy" 2740769Sjoerg 2840767Sjoerg#define ECHO 010 2940767Sjoerg#define ROTORSZ 256 3040767Sjoerg#define MASK 0377 3140767Sjoergchar t1[ROTORSZ]; 3240767Sjoergchar t2[ROTORSZ]; 3340767Sjoergchar t3[ROTORSZ]; 3440767Sjoergchar deck[ROTORSZ]; 3540767Sjoergchar buf[13]; 3640767Sjoerg 3740769Sjoergvoid shuffle(char *); 3878781Sddvoid setup(char *); 3940767Sjoerg 4040767Sjoergvoid 4140767Sjoergsetup(pw) 4240769Sjoerg char *pw; 4340767Sjoerg{ 4440767Sjoerg int ic, i, k, temp, pf[2], pid; 4578781Sdd unsigned rnd; 4640767Sjoerg long seed; 4740767Sjoerg 4840767Sjoerg strncpy(buf, pw, 8); 4940767Sjoerg while (*pw) 5040767Sjoerg *pw++ = '\0'; 5140767Sjoerg buf[8] = buf[0]; 5240767Sjoerg buf[9] = buf[1]; 5340767Sjoerg pipe(pf); 5440767Sjoerg if ((pid=fork())==0) { 5540767Sjoerg close(0); 5640767Sjoerg close(1); 5740767Sjoerg dup(pf[0]); 5840767Sjoerg dup(pf[1]); 5940767Sjoerg execlp("makekey", "-", 0); 6040767Sjoerg execl("/usr/libexec/makekey", "-", 0); /* BSDI */ 6140767Sjoerg execl("/usr/lib/makekey", "-", 0); 6240767Sjoerg execl("/usr/bin/makekey", "-", 0); /* IBM */ 6340767Sjoerg execl("/lib/makekey", "-", 0); 6440767Sjoerg perror("makekey"); 6540767Sjoerg fprintf(stderr, "enigma: cannot execute 'makekey', aborting\n"); 6640767Sjoerg exit(1); 6740767Sjoerg } 6840767Sjoerg write(pf[1], buf, 10); 6940767Sjoerg close(pf[1]); 7040767Sjoerg i=wait((int *)NULL); 7140767Sjoerg if (i<0) perror("enigma: wait"); 7240767Sjoerg if (i!=pid) { 7340767Sjoerg fprintf(stderr, "enigma: expected pid %d, got pid %d\n", pid, i); 7440767Sjoerg exit(1); 7540767Sjoerg } 7640767Sjoerg if ((i=read(pf[0], buf, 13)) != 13) { 7740767Sjoerg fprintf(stderr, "enigma: cannot generate key, read %d\n",i); 7840767Sjoerg exit(1); 7940767Sjoerg } 8040767Sjoerg seed = 123; 8140767Sjoerg for (i=0; i<13; i++) 8240767Sjoerg seed = seed*buf[i] + i; 8340767Sjoerg for(i=0;i<ROTORSZ;i++) { 8440767Sjoerg t1[i] = i; 8540767Sjoerg deck[i] = i; 8640767Sjoerg } 8740767Sjoerg for(i=0;i<ROTORSZ;i++) { 8840767Sjoerg seed = 5*seed + buf[i%13]; 8940767Sjoerg if( sizeof(long) > 4 ) { 9040767Sjoerg /* Force seed to stay in 32-bit signed math */ 9140767Sjoerg if( seed & 0x80000000 ) 9240767Sjoerg seed = seed | (-1L & ~0xFFFFFFFFL); 9340767Sjoerg else 9440767Sjoerg seed &= 0x7FFFFFFF; 9540767Sjoerg } 9678781Sdd rnd = seed % 65521; 9740767Sjoerg k = ROTORSZ-1 - i; 9878781Sdd ic = (rnd&MASK)%(k+1); 9978781Sdd rnd >>= 8; 10040767Sjoerg temp = t1[k]; 10140767Sjoerg t1[k] = t1[ic]; 10240767Sjoerg t1[ic] = temp; 10340767Sjoerg if(t3[k]!=0) continue; 10478781Sdd ic = (rnd&MASK) % k; 10540767Sjoerg while(t3[ic]!=0) ic = (ic+1) % k; 10640767Sjoerg t3[k] = ic; 10740767Sjoerg t3[ic] = k; 10840767Sjoerg } 10940767Sjoerg for(i=0;i<ROTORSZ;i++) 11040767Sjoerg t2[t1[i]&MASK] = i; 11140767Sjoerg} 11240767Sjoerg 11340769Sjoergint 11440767Sjoergmain(argc, argv) 11578781Sdd int argc; 11640769Sjoerg char *argv[]; 11740767Sjoerg{ 11840767Sjoerg register int i, n1, n2, nr1, nr2; 11940769Sjoerg int secureflg = 0, kflag = 0; 12040769Sjoerg char *cp; 12140767Sjoerg 12240769Sjoerg if (argc > 1 && argv[1][0] == '-') { 12340769Sjoerg if (argv[1][1] == 's') { 12440769Sjoerg argc--; 12540769Sjoerg argv++; 12640769Sjoerg secureflg = 1; 12740769Sjoerg } else if (argv[1][1] == 'k') { 12840769Sjoerg argc--; 12940769Sjoerg argv++; 13040769Sjoerg kflag = 1; 13140769Sjoerg } 13240767Sjoerg } 13340769Sjoerg if (kflag) { 13440769Sjoerg if ((cp = getenv(MINUSKVAR)) == NULL) { 13540769Sjoerg fprintf(stderr, "%s not set\n", MINUSKVAR); 13640769Sjoerg exit(1); 13740769Sjoerg } 13840769Sjoerg setup(cp); 13940769Sjoerg } else if (argc != 2) { 14040767Sjoerg setup(getpass("Enter key:")); 14140767Sjoerg } 14240767Sjoerg else 14340767Sjoerg setup(argv[1]); 14440767Sjoerg n1 = 0; 14540767Sjoerg n2 = 0; 14640767Sjoerg nr2 = 0; 14740767Sjoerg 14840769Sjoerg while((i=getchar()) != -1) { 14940767Sjoerg if (secureflg) { 15040767Sjoerg nr1 = deck[n1]&MASK; 15140767Sjoerg nr2 = deck[nr1]&MASK; 15240767Sjoerg } else { 15340767Sjoerg nr1 = n1; 15440767Sjoerg } 15540767Sjoerg i = t2[(t3[(t1[(i+nr1)&MASK]+nr2)&MASK]-nr2)&MASK]-nr1; 15640767Sjoerg putchar(i); 15740767Sjoerg n1++; 15840767Sjoerg if(n1==ROTORSZ) { 15940767Sjoerg n1 = 0; 16040767Sjoerg n2++; 16140767Sjoerg if(n2==ROTORSZ) n2 = 0; 16240767Sjoerg if (secureflg) { 16340767Sjoerg shuffle(deck); 16440767Sjoerg } else { 16540767Sjoerg nr2 = n2; 16640767Sjoerg } 16740767Sjoerg } 16840767Sjoerg } 16940769Sjoerg 17040769Sjoerg return 0; 17140767Sjoerg} 17240767Sjoerg 17340767Sjoergvoid 17478781Sddshuffle(deckary) 17578781Sdd char deckary[]; 17640767Sjoerg{ 17740767Sjoerg int i, ic, k, temp; 17878781Sdd unsigned rnd; 17940767Sjoerg static long seed = 123; 18040767Sjoerg 18140767Sjoerg for(i=0;i<ROTORSZ;i++) { 18240767Sjoerg seed = 5*seed + buf[i%13]; 18378781Sdd rnd = seed % 65521; 18440767Sjoerg k = ROTORSZ-1 - i; 18578781Sdd ic = (rnd&MASK)%(k+1); 18678781Sdd temp = deckary[k]; 18778781Sdd deckary[k] = deckary[ic]; 18878781Sdd deckary[ic] = temp; 18940767Sjoerg } 19040767Sjoerg} 191