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