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