Coverage Report

Created: 2025-06-24 07:01

/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
}