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