Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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