1// arc4.cpp - written and placed in the public domain by Wei Dai
2
3// The ARC4 algorithm was first revealed in an anonymous email to the
4// cypherpunks mailing list. This file originally contained some
5// code copied from this email. The code has since been rewritten in order
6// to clarify the copyright status of this file. It should now be
7// completely in the public domain.
8
9#include "pch.h"
10#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
11#include "arc4.h"
12
13NAMESPACE_BEGIN(CryptoPP)
14namespace Weak1 {
15
16void ARC4_TestInstantiations()
17{
18	ARC4 x;
19}
20
21ARC4_Base::~ARC4_Base()
22{
23	m_x = m_y = 0;
24}
25
26void ARC4_Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs &params)
27{
28	AssertValidKeyLength(keyLen);
29
30	m_x = 1;
31	m_y = 0;
32
33	unsigned int i;
34	for (i=0; i<256; i++)
35		m_state[i] = i;
36
37	unsigned int keyIndex = 0, stateIndex = 0;
38	for (i=0; i<256; i++)
39	{
40		unsigned int a = m_state[i];
41		stateIndex += key[keyIndex] + a;
42		stateIndex &= 0xff;
43		m_state[i] = m_state[stateIndex];
44		m_state[stateIndex] = a;
45		if (++keyIndex >= keyLen)
46			keyIndex = 0;
47	}
48
49	int discardBytes = params.GetIntValueWithDefault("DiscardBytes", GetDefaultDiscardBytes());
50	DiscardBytes(discardBytes);
51}
52
53template <class T>
54static inline unsigned int MakeByte(T &x, T &y, byte *s)
55{
56	unsigned int a = s[x];
57	y = (y+a) & 0xff;
58	unsigned int b = s[y];
59	s[x] = b;
60	s[y] = a;
61	x = (x+1) & 0xff;
62	return s[(a+b) & 0xff];
63}
64
65void ARC4_Base::GenerateBlock(byte *output, size_t size)
66{
67	while (size--)
68		*output++ = MakeByte(m_x, m_y, m_state);
69}
70
71void ARC4_Base::ProcessData(byte *outString, const byte *inString, size_t length)
72{
73	if (length == 0)
74		return;
75
76	byte *const s = m_state;
77	unsigned int x = m_x;
78	unsigned int y = m_y;
79
80	if (inString == outString)
81	{
82		do
83		{
84			*outString++ ^= MakeByte(x, y, s);
85		} while (--length);
86	}
87	else
88	{
89		do
90		{
91			*outString++ = *inString++ ^ MakeByte(x, y, s);
92		}
93		while(--length);
94	}
95
96	m_x = x;
97	m_y = y;
98}
99
100void ARC4_Base::DiscardBytes(size_t length)
101{
102	if (length == 0)
103		return;
104
105	byte *const s = m_state;
106	unsigned int x = m_x;
107	unsigned int y = m_y;
108
109	do
110	{
111		MakeByte(x, y, s);
112	}
113	while(--length);
114
115	m_x = x;
116	m_y = y;
117}
118
119}
120NAMESPACE_END
121