xref: /plan9/sys/src/cmd/postscript/misc/pscrypt.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier  *
3*219b2ee8SDavid du Colombier  * Adobe's encryption/decryption algorithm for eexec and show. Runs in
4*219b2ee8SDavid du Colombier  * eexec mode unless told otherwise. Use,
5*219b2ee8SDavid du Colombier  *
6*219b2ee8SDavid du Colombier  *		pscrypt file.cypher > file.clear
7*219b2ee8SDavid du Colombier  *
8*219b2ee8SDavid du Colombier  * to decrypt eexec input. Assumes file.cypher is hex with the key as the
9*219b2ee8SDavid du Colombier  * first four bytes, and writes file.clear as binary (omitting the key).
10*219b2ee8SDavid du Colombier  * Use
11*219b2ee8SDavid du Colombier  *
12*219b2ee8SDavid du Colombier  *		pscrypt -e12ab34ef file.clear >file.cypher
13*219b2ee8SDavid du Colombier  *
14*219b2ee8SDavid du Colombier  * to encrypt file.clear (for eexec) using 12ab34ef as the key. Input is
15*219b2ee8SDavid du Colombier  * binary and output is hex. The key must be given as a hex number. Use
16*219b2ee8SDavid du Colombier  * -sshow to encrypt or decrypt a CharString or Subr,
17*219b2ee8SDavid du Colombier  *
18*219b2ee8SDavid du Colombier  *		pscrypt -sshow file.cypher > file.clear
19*219b2ee8SDavid du Colombier  *
20*219b2ee8SDavid du Colombier  * Use -b or -x to read binary or hex input, and -B or -X to output binary
21*219b2ee8SDavid du Colombier  * or hex.
22*219b2ee8SDavid du Colombier  *
23*219b2ee8SDavid du Colombier  */
24*219b2ee8SDavid du Colombier 
25*219b2ee8SDavid du Colombier #include <stdio.h>
26*219b2ee8SDavid du Colombier #include <ctype.h>
27*219b2ee8SDavid du Colombier 
28*219b2ee8SDavid du Colombier #define ENCRYPT		0
29*219b2ee8SDavid du Colombier #define DECRYPT		1
30*219b2ee8SDavid du Colombier 
31*219b2ee8SDavid du Colombier #define NOTSET		-1
32*219b2ee8SDavid du Colombier #define BINARY		0
33*219b2ee8SDavid du Colombier #define HEX		1
34*219b2ee8SDavid du Colombier #define LINELENGTH	40
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier #define CHARSTRING	4330
37*219b2ee8SDavid du Colombier #define EEXEC		55665
38*219b2ee8SDavid du Colombier #define MAGIC1		52845
39*219b2ee8SDavid du Colombier #define MAGIC2		22719
40*219b2ee8SDavid du Colombier 
41*219b2ee8SDavid du Colombier int	argc;
42*219b2ee8SDavid du Colombier char	**argv;
43*219b2ee8SDavid du Colombier 
44*219b2ee8SDavid du Colombier int	mode = DECRYPT;
45*219b2ee8SDavid du Colombier int	input = NOTSET;
46*219b2ee8SDavid du Colombier int	output = NOTSET;
47*219b2ee8SDavid du Colombier int	outoffset = NOTSET;
48*219b2ee8SDavid du Colombier int	inoffset = NOTSET;
49*219b2ee8SDavid du Colombier 
50*219b2ee8SDavid du Colombier int	cryptkey = 0;			/* encryption key set with -e */
51*219b2ee8SDavid du Colombier int	linelength = LINELENGTH;	/* only for hex output */
52*219b2ee8SDavid du Colombier int	lastchar = 0;
53*219b2ee8SDavid du Colombier 
54*219b2ee8SDavid du Colombier unsigned long	seed = EEXEC;
55*219b2ee8SDavid du Colombier unsigned long	key;
56*219b2ee8SDavid du Colombier 
57*219b2ee8SDavid du Colombier FILE	*fp_in = stdin;
58*219b2ee8SDavid du Colombier 
59*219b2ee8SDavid du Colombier /*****************************************************************************/
60*219b2ee8SDavid du Colombier 
main(agc,agv)61*219b2ee8SDavid du Colombier main(agc, agv)
62*219b2ee8SDavid du Colombier 
63*219b2ee8SDavid du Colombier     int		agc;
64*219b2ee8SDavid du Colombier     char	*agv[];
65*219b2ee8SDavid du Colombier 
66*219b2ee8SDavid du Colombier {
67*219b2ee8SDavid du Colombier 
68*219b2ee8SDavid du Colombier /*
69*219b2ee8SDavid du Colombier  *
70*219b2ee8SDavid du Colombier  * Implementation of the encryption/decryption used by eexec and show.
71*219b2ee8SDavid du Colombier  *
72*219b2ee8SDavid du Colombier  */
73*219b2ee8SDavid du Colombier 
74*219b2ee8SDavid du Colombier     argc = agc;
75*219b2ee8SDavid du Colombier     argv = agv;
76*219b2ee8SDavid du Colombier 
77*219b2ee8SDavid du Colombier     options();
78*219b2ee8SDavid du Colombier     initialize();
79*219b2ee8SDavid du Colombier     arguments();
80*219b2ee8SDavid du Colombier 
81*219b2ee8SDavid du Colombier     exit(0);
82*219b2ee8SDavid du Colombier 
83*219b2ee8SDavid du Colombier }   /* End of main */
84*219b2ee8SDavid du Colombier 
85*219b2ee8SDavid du Colombier /*****************************************************************************/
86*219b2ee8SDavid du Colombier 
options()87*219b2ee8SDavid du Colombier options()
88*219b2ee8SDavid du Colombier 
89*219b2ee8SDavid du Colombier {
90*219b2ee8SDavid du Colombier 
91*219b2ee8SDavid du Colombier     int		ch;
92*219b2ee8SDavid du Colombier     char	*names = "bde:l:os:xBSX";
93*219b2ee8SDavid du Colombier 
94*219b2ee8SDavid du Colombier     extern char	*optarg;
95*219b2ee8SDavid du Colombier     extern int	optind;
96*219b2ee8SDavid du Colombier 
97*219b2ee8SDavid du Colombier /*
98*219b2ee8SDavid du Colombier  *
99*219b2ee8SDavid du Colombier  * Command line options.
100*219b2ee8SDavid du Colombier  *
101*219b2ee8SDavid du Colombier  */
102*219b2ee8SDavid du Colombier 
103*219b2ee8SDavid du Colombier     while ( (ch = getopt(argc, argv, names)) != EOF )
104*219b2ee8SDavid du Colombier 	switch ( ch ) {
105*219b2ee8SDavid du Colombier 	    case 'b':			/* binary input */
106*219b2ee8SDavid du Colombier 		    input = BINARY;
107*219b2ee8SDavid du Colombier 		    break;
108*219b2ee8SDavid du Colombier 
109*219b2ee8SDavid du Colombier 	    case 'd':			/* decrypt */
110*219b2ee8SDavid du Colombier 		    mode = DECRYPT;
111*219b2ee8SDavid du Colombier 		    break;
112*219b2ee8SDavid du Colombier 
113*219b2ee8SDavid du Colombier 	    case 'e':			/* encrypt */
114*219b2ee8SDavid du Colombier 		    mode = ENCRYPT;
115*219b2ee8SDavid du Colombier 		    if ( *optarg == '0' && *optarg == 'x' )
116*219b2ee8SDavid du Colombier 			optarg += 2;
117*219b2ee8SDavid du Colombier 		    sscanf(optarg, "%8x", &cryptkey);
118*219b2ee8SDavid du Colombier 		    break;
119*219b2ee8SDavid du Colombier 
120*219b2ee8SDavid du Colombier 	    case 'l':			/* line length hex output */
121*219b2ee8SDavid du Colombier 		    linelength = atoi(optarg);
122*219b2ee8SDavid du Colombier 		    break;
123*219b2ee8SDavid du Colombier 
124*219b2ee8SDavid du Colombier 	    case 'o':			/* output all bytes - debugging */
125*219b2ee8SDavid du Colombier 		    outoffset = 0;
126*219b2ee8SDavid du Colombier 		    break;
127*219b2ee8SDavid du Colombier 
128*219b2ee8SDavid du Colombier 	    case 's':			/* seed */
129*219b2ee8SDavid du Colombier 		    if ( *optarg == 'e' )
130*219b2ee8SDavid du Colombier 			seed = EEXEC;
131*219b2ee8SDavid du Colombier 		    else if ( *optarg == 's' )
132*219b2ee8SDavid du Colombier 			seed = CHARSTRING;
133*219b2ee8SDavid du Colombier 		    else if ( *optarg == '0' && *(optarg+1) == 'x' )
134*219b2ee8SDavid du Colombier 			sscanf(optarg+2, "%x", &seed);
135*219b2ee8SDavid du Colombier 		    else if ( *optarg == '0' )
136*219b2ee8SDavid du Colombier 			sscanf(optarg, "%o", &seed);
137*219b2ee8SDavid du Colombier 		    else sscanf(optarg, "%d", &seed);
138*219b2ee8SDavid du Colombier 		    break;
139*219b2ee8SDavid du Colombier 
140*219b2ee8SDavid du Colombier 	    case 'x':			/* hex input */
141*219b2ee8SDavid du Colombier 		    input = HEX;
142*219b2ee8SDavid du Colombier 		    break;
143*219b2ee8SDavid du Colombier 
144*219b2ee8SDavid du Colombier 	    case 'B':			/* binary output */
145*219b2ee8SDavid du Colombier 		    output = BINARY;
146*219b2ee8SDavid du Colombier 		    break;
147*219b2ee8SDavid du Colombier 
148*219b2ee8SDavid du Colombier 	    case 'X':			/* hex output */
149*219b2ee8SDavid du Colombier 		    output = HEX;
150*219b2ee8SDavid du Colombier 		    break;
151*219b2ee8SDavid du Colombier 
152*219b2ee8SDavid du Colombier 	    case '?':			/* don't understand the option */
153*219b2ee8SDavid du Colombier 		    fprintf(stderr, "bad option -%c\n", ch);
154*219b2ee8SDavid du Colombier 		    exit(1);
155*219b2ee8SDavid du Colombier 		    break;
156*219b2ee8SDavid du Colombier 
157*219b2ee8SDavid du Colombier 	    default:			/* don't know what to do for ch */
158*219b2ee8SDavid du Colombier 		    fprintf(stderr, "missing case for option -%c\n", ch);
159*219b2ee8SDavid du Colombier 		    exit(1);
160*219b2ee8SDavid du Colombier 		    break;
161*219b2ee8SDavid du Colombier 	}   /* End switch */
162*219b2ee8SDavid du Colombier 
163*219b2ee8SDavid du Colombier     argc -= optind;			/* get ready for non-option args */
164*219b2ee8SDavid du Colombier     argv += optind;
165*219b2ee8SDavid du Colombier 
166*219b2ee8SDavid du Colombier }   /* End of options */
167*219b2ee8SDavid du Colombier 
168*219b2ee8SDavid du Colombier /*****************************************************************************/
169*219b2ee8SDavid du Colombier 
initialize()170*219b2ee8SDavid du Colombier initialize()
171*219b2ee8SDavid du Colombier 
172*219b2ee8SDavid du Colombier {
173*219b2ee8SDavid du Colombier 
174*219b2ee8SDavid du Colombier /*
175*219b2ee8SDavid du Colombier  *
176*219b2ee8SDavid du Colombier  * Initialization that has to be done after the options.
177*219b2ee8SDavid du Colombier  *
178*219b2ee8SDavid du Colombier  */
179*219b2ee8SDavid du Colombier 
180*219b2ee8SDavid du Colombier     key = seed;
181*219b2ee8SDavid du Colombier 
182*219b2ee8SDavid du Colombier     if ( mode == DECRYPT ) {
183*219b2ee8SDavid du Colombier 	input = (input == NOTSET) ? HEX : input;
184*219b2ee8SDavid du Colombier 	output = (output == NOTSET) ? BINARY : output;
185*219b2ee8SDavid du Colombier 	inoffset = (inoffset == NOTSET) ? 0 : inoffset;
186*219b2ee8SDavid du Colombier 	outoffset = (outoffset == NOTSET) ? -4 : outoffset;
187*219b2ee8SDavid du Colombier     } else {
188*219b2ee8SDavid du Colombier 	input = (input == NOTSET) ? BINARY : input;
189*219b2ee8SDavid du Colombier 	output = (output == NOTSET) ? HEX : output;
190*219b2ee8SDavid du Colombier 	inoffset = (inoffset == NOTSET) ? 4 : inoffset;
191*219b2ee8SDavid du Colombier 	outoffset = (outoffset == NOTSET) ? 0 : outoffset;
192*219b2ee8SDavid du Colombier     }	/* End else */
193*219b2ee8SDavid du Colombier 
194*219b2ee8SDavid du Colombier     if ( linelength <= 0 )
195*219b2ee8SDavid du Colombier 	linelength = LINELENGTH;
196*219b2ee8SDavid du Colombier 
197*219b2ee8SDavid du Colombier }   /* End of initialize */
198*219b2ee8SDavid du Colombier 
199*219b2ee8SDavid du Colombier /*****************************************************************************/
200*219b2ee8SDavid du Colombier 
arguments()201*219b2ee8SDavid du Colombier arguments()
202*219b2ee8SDavid du Colombier 
203*219b2ee8SDavid du Colombier {
204*219b2ee8SDavid du Colombier 
205*219b2ee8SDavid du Colombier /*
206*219b2ee8SDavid du Colombier  *
207*219b2ee8SDavid du Colombier  * Everything left is an input file. No arguments or '-' means stdin.
208*219b2ee8SDavid du Colombier  *
209*219b2ee8SDavid du Colombier  */
210*219b2ee8SDavid du Colombier 
211*219b2ee8SDavid du Colombier     if ( argc < 1 )
212*219b2ee8SDavid du Colombier 	crypt();
213*219b2ee8SDavid du Colombier     else
214*219b2ee8SDavid du Colombier 	while ( argc > 0 ) {
215*219b2ee8SDavid du Colombier 	    if ( strcmp(*argv, "-") == 0 )
216*219b2ee8SDavid du Colombier 		fp_in = stdin;
217*219b2ee8SDavid du Colombier 	    else if ( (fp_in = fopen(*argv, "r")) == NULL ) {
218*219b2ee8SDavid du Colombier 		fprintf(stderr, "can't open %s\n", *argv);
219*219b2ee8SDavid du Colombier 		exit(1);
220*219b2ee8SDavid du Colombier 	    }	/* End if */
221*219b2ee8SDavid du Colombier 	    crypt();
222*219b2ee8SDavid du Colombier 	    if ( fp_in != stdin )
223*219b2ee8SDavid du Colombier 		fclose(fp_in);
224*219b2ee8SDavid du Colombier 	    argc--;
225*219b2ee8SDavid du Colombier 	    argv++;
226*219b2ee8SDavid du Colombier 	}   /* End while */
227*219b2ee8SDavid du Colombier 
228*219b2ee8SDavid du Colombier }   /* End of arguments */
229*219b2ee8SDavid du Colombier 
230*219b2ee8SDavid du Colombier /*****************************************************************************/
231*219b2ee8SDavid du Colombier 
crypt()232*219b2ee8SDavid du Colombier crypt()
233*219b2ee8SDavid du Colombier 
234*219b2ee8SDavid du Colombier {
235*219b2ee8SDavid du Colombier 
236*219b2ee8SDavid du Colombier     unsigned int	cypher;
237*219b2ee8SDavid du Colombier     unsigned int	clear;
238*219b2ee8SDavid du Colombier 
239*219b2ee8SDavid du Colombier /*
240*219b2ee8SDavid du Colombier  *
241*219b2ee8SDavid du Colombier  * Runs the encryption/decryption algorithm.
242*219b2ee8SDavid du Colombier  *
243*219b2ee8SDavid du Colombier  */
244*219b2ee8SDavid du Colombier 
245*219b2ee8SDavid du Colombier     while ( lastchar != EOF ) {
246*219b2ee8SDavid du Colombier 	cypher = nextbyte();
247*219b2ee8SDavid du Colombier 	clear = ((key >> 8) ^ cypher) & 0xFF;
248*219b2ee8SDavid du Colombier 	key = (key + (mode == DECRYPT ? cypher : clear)) * MAGIC1 + MAGIC2;
249*219b2ee8SDavid du Colombier 	if ( ++outoffset > 0 && lastchar != EOF ) {
250*219b2ee8SDavid du Colombier 	    if ( output == HEX ) {
251*219b2ee8SDavid du Colombier 		printf("%.2X", clear);
252*219b2ee8SDavid du Colombier 		if ( linelength > 0 && (outoffset % linelength) == 0 )
253*219b2ee8SDavid du Colombier 		    putchar('\n');
254*219b2ee8SDavid du Colombier 	    } else putchar(clear);
255*219b2ee8SDavid du Colombier 	}   /* End if */
256*219b2ee8SDavid du Colombier     }	/* End while */
257*219b2ee8SDavid du Colombier 
258*219b2ee8SDavid du Colombier }   /* End of crypt */
259*219b2ee8SDavid du Colombier 
260*219b2ee8SDavid du Colombier /*****************************************************************************/
261*219b2ee8SDavid du Colombier 
nextbyte()262*219b2ee8SDavid du Colombier nextbyte()
263*219b2ee8SDavid du Colombier 
264*219b2ee8SDavid du Colombier {
265*219b2ee8SDavid du Colombier 
266*219b2ee8SDavid du Colombier     int		val = EOF;
267*219b2ee8SDavid du Colombier 
268*219b2ee8SDavid du Colombier /*
269*219b2ee8SDavid du Colombier  *
270*219b2ee8SDavid du Colombier  * Returns the next byte. Uses cryptkey (i.e. what followed -e) while inoffset is
271*219b2ee8SDavid du Colombier  * positive, otherwise reads (hex or binary) from fp_in.
272*219b2ee8SDavid du Colombier  *
273*219b2ee8SDavid du Colombier  */
274*219b2ee8SDavid du Colombier 
275*219b2ee8SDavid du Colombier     if ( inoffset-- > 0 )
276*219b2ee8SDavid du Colombier 	val = (cryptkey >> (inoffset*8)) & 0xFF;
277*219b2ee8SDavid du Colombier     else if ( input == HEX ) {
278*219b2ee8SDavid du Colombier 	if ( (val = nexthexchar()) != EOF )
279*219b2ee8SDavid du Colombier 	    val = (val << 4) | nexthexchar();
280*219b2ee8SDavid du Colombier     } else if ( input == BINARY )
281*219b2ee8SDavid du Colombier 	val = Getc(fp_in);
282*219b2ee8SDavid du Colombier 
283*219b2ee8SDavid du Colombier     return(val);
284*219b2ee8SDavid du Colombier 
285*219b2ee8SDavid du Colombier }   /* End of nextbyte */
286*219b2ee8SDavid du Colombier 
287*219b2ee8SDavid du Colombier /*****************************************************************************/
288*219b2ee8SDavid du Colombier 
nexthexchar()289*219b2ee8SDavid du Colombier nexthexchar()
290*219b2ee8SDavid du Colombier 
291*219b2ee8SDavid du Colombier {
292*219b2ee8SDavid du Colombier 
293*219b2ee8SDavid du Colombier     int		ch;
294*219b2ee8SDavid du Colombier 
295*219b2ee8SDavid du Colombier /*
296*219b2ee8SDavid du Colombier  *
297*219b2ee8SDavid du Colombier  * Reads the next hex character.
298*219b2ee8SDavid du Colombier  *
299*219b2ee8SDavid du Colombier  */
300*219b2ee8SDavid du Colombier 
301*219b2ee8SDavid du Colombier     while ( (ch = Getc(fp_in)) != EOF && ! isxdigit(ch) ) ;
302*219b2ee8SDavid du Colombier 
303*219b2ee8SDavid du Colombier     if ( isdigit(ch) )
304*219b2ee8SDavid du Colombier 	ch -= '0';
305*219b2ee8SDavid du Colombier     else if ( isupper(ch) )
306*219b2ee8SDavid du Colombier 	ch -= 'A' - 10;
307*219b2ee8SDavid du Colombier     else if ( islower(ch) )
308*219b2ee8SDavid du Colombier 	ch -= 'a' - 10;
309*219b2ee8SDavid du Colombier 
310*219b2ee8SDavid du Colombier     return(ch);
311*219b2ee8SDavid du Colombier 
312*219b2ee8SDavid du Colombier }   /* End of nexthexchar */
313*219b2ee8SDavid du Colombier 
314*219b2ee8SDavid du Colombier /*****************************************************************************/
315*219b2ee8SDavid du Colombier 
Getc(fp)316*219b2ee8SDavid du Colombier Getc(fp)
317*219b2ee8SDavid du Colombier 
318*219b2ee8SDavid du Colombier     FILE	*fp;
319*219b2ee8SDavid du Colombier 
320*219b2ee8SDavid du Colombier {
321*219b2ee8SDavid du Colombier 
322*219b2ee8SDavid du Colombier /*
323*219b2ee8SDavid du Colombier  *
324*219b2ee8SDavid du Colombier  * Reads the next byte from *fp, sets lastchar, and returns the character.
325*219b2ee8SDavid du Colombier  *
326*219b2ee8SDavid du Colombier  */
327*219b2ee8SDavid du Colombier 
328*219b2ee8SDavid du Colombier     return(lastchar = getc(fp));
329*219b2ee8SDavid du Colombier 
330*219b2ee8SDavid du Colombier }   /* End of Getc */
331*219b2ee8SDavid du Colombier 
332*219b2ee8SDavid du Colombier /*****************************************************************************/
333*219b2ee8SDavid du Colombier 
334