Coverage Report

Created: 2025-06-10 06:49

/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
0
{
42
0
    unsigned int x, y;
43
0
    unsigned char s, *S = state->S;
44
45
0
    if (keylength < 1)
46
0
        return_error(gs_error_rangecheck);
47
48
    /* initialize to eponymous values */
49
0
    for (x = 0; x < 256; x++)
50
0
        S[x] = x;
51
52
    /* scramble based on the key */
53
0
    y = 0;
54
0
    for (x = 0; x < 256; x++) {
55
0
        y = (y + S[x] + key[x % keylength]) & 0xFF;
56
0
        s = S[x];
57
0
        S[x] = S[y];
58
0
        S[y] = s;
59
0
    }
60
61
    /* initialize the indicies */
62
0
    state->x = 0;
63
0
    state->y = 0;
64
65
    /* return successfully */
66
0
    return 0;
67
0
}
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
0
{
76
0
    stream_arcfour_state *const state = (stream_arcfour_state *) ss;
77
0
    unsigned int x = state->x;
78
0
    unsigned int y = state->y;
79
0
    unsigned char s, *S = state->S;
80
0
    unsigned char z;
81
0
   const unsigned char *limit;
82
0
    int status;
83
84
    /* figure out if we're going to run out of space */
85
0
    if ((pr->limit - pr->ptr) > (pw->limit - pw->ptr)) {
86
0
        limit = pr->ptr + (pw->limit - pw->ptr);
87
0
        status = 1;
88
0
    } else {
89
0
        limit = pr->limit;
90
0
        status = last ? EOFC : 0;
91
0
    }
92
    /* generate a pseudorandom byte stream and xor it with the input */
93
0
    while (pr->ptr < limit) {
94
0
        x = (x + 1) & 0xFF;
95
0
        y = (y + S[x]) & 0xFF;
96
0
        s = S[x];
97
0
        S[x] = S[y];
98
0
        S[y] = s;
99
0
        z = S[(S[x] + S[y]) & 0xFF];
100
101
0
        *++pw->ptr = (*++pr->ptr) ^ z;
102
0
    }
103
    /* save state */
104
0
    state->x = x;
105
0
    state->y = y;
106
107
0
    return status;
108
0
}
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
}