1 /* Copyright (C) 2001 Artifex Software, Inc. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: sarc4.c,v 1.10 2004/01/14 13:45:56 igor Exp $ */
18
19 /* Arcfour cipher and filter implementation */
20
21 #include "memory_.h"
22 #include "gserrors.h"
23 #include "gserror.h"
24 #include "strimpl.h"
25 #include "sarc4.h"
26
27 /* This is an independent implementation of the symmetric block
28 * cipher commonly known as 'arcfour' based on Bruce Schneier's
29 * description of the algorithm in _Applied Cryptography_. Arcfour
30 * is believed to be functionally equivalent to the RC4(tm) cipher
31 * mentioned in the PDF specification. (RC4 is a registered
32 * trademark of RSA Data Security, Inc.)
33 */
34
35 /* stream implementation */
36
37 private_st_arcfour_state(); /* creates a gc object for our state, defined in sarc4.h */
38
39 /* initialize the S box using the given key */
40 int
s_arcfour_set_key(stream_arcfour_state * state,const unsigned char * key,int keylength)41 s_arcfour_set_key(stream_arcfour_state * state, const unsigned char *key,
42 int keylength)
43 {
44 unsigned int x, y;
45 unsigned char s, *S = state->S;
46
47 if (keylength < 1)
48 return_error(gs_error_rangecheck);
49
50 /* initialize to eponymous values */
51 for (x = 0; x < 256; x++)
52 S[x] = x;
53
54 /* scramble based on the key */
55 y = 0;
56 for (x = 0; x < 256; x++) {
57 y = (y + S[x] + key[x % keylength]) & 0xFF;
58 s = S[x];
59 S[x] = S[y];
60 S[y] = s;
61 }
62
63 /* initialize the indicies */
64 state->x = 0;
65 state->y = 0;
66
67 /* return successfully */
68 return 0;
69 }
70
71 /* (de)crypt a section of text--the procedure is the same
72 * in each direction. see strimpl.h for return codes.
73 */
74 private int
s_arcfour_process(stream_state * ss,stream_cursor_read * pr,stream_cursor_write * pw,bool last)75 s_arcfour_process(stream_state * ss, stream_cursor_read * pr,
76 stream_cursor_write * pw, bool last)
77 {
78 stream_arcfour_state *const state = (stream_arcfour_state *) ss;
79 unsigned int x = state->x;
80 unsigned int y = state->y;
81 unsigned char s, *S = state->S;
82 unsigned char z;
83 const unsigned char *limit;
84 int status;
85
86 /* figure out if we're going to run out of space */
87 if ((pr->limit - pr->ptr) > (pw->limit - pw->ptr)) {
88 limit = pr->ptr + (pw->limit - pw->ptr);
89 status = 1;
90 } else {
91 limit = pr->limit;
92 status = last ? EOFC : 0;
93 }
94 /* generate a pseudorandom byte stream and xor it with the input */
95 while (pr->ptr < limit) {
96 x = (x + 1) & 0xFF;
97 y = (y + S[x]) & 0xFF;
98 s = S[x];
99 S[x] = S[y];
100 S[y] = s;
101 z = S[(S[x] + S[y]) & 0xFF];
102
103 *++pw->ptr = (*++pr->ptr) ^ z;
104 }
105 /* save state */
106 state->x = x;
107 state->y = y;
108
109 return status;
110 }
111
112 /* stream template */
113 const stream_template s_arcfour_template = {
114 &st_arcfour_state, NULL, s_arcfour_process, 1, 1
115 };
116
117 /* (de)crypt a section of text in a buffer -- the procedure is the same
118 * in each direction. see strimpl.h for return codes.
119 */
120 int
s_arcfour_process_buffer(stream_arcfour_state * ss,byte * buf,int buf_size)121 s_arcfour_process_buffer(stream_arcfour_state *ss, byte *buf, int buf_size)
122 {
123 stream_cursor_read r;
124 stream_cursor_write w;
125 const bool unused = false;
126
127 r.ptr = w.ptr = buf - 1;
128 r.limit = w.limit = buf - 1 + buf_size;
129 return s_arcfour_process((stream_state *)ss, &r, &w, unused);
130 }
131
132