Skip to content

Commit

Permalink
RC4 fix only (#81)
Browse files Browse the repository at this point in the history
* Stream factory allows 0 size of dummy stream

Used for RC4's IV, but in future, it can be usefull elsewhere as well

* Fix reinitialization of RC4 internal state after each function call

* Fix intended reinitialization of RC4
  • Loading branch information
Bender250 authored Jun 18, 2018
1 parent 066e17e commit a861663
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 7 deletions.
2 changes: 1 addition & 1 deletion streams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ std::unique_ptr<stream> make_stream(const json &config,
core::optional<stream *> stream) {
const std::string type = config.at("type");

if (osize == 0)
if (osize == 0 and type != "dummy_stream") // we allow dummy stream with 0 size
throw std::runtime_error("Stream " + type + " cannot have osize 0.");

// trivial source only streams
Expand Down
10 changes: 6 additions & 4 deletions streams/stream_ciphers/other/rc4/rc4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ static void arcfour_key_setup(std::uint8_t state[state_size], const std::uint8_t

// This does not hold state between calls. It always generates the
// stream starting from the first output byte.
static void arcfour_generate_stream(std::uint8_t state[], std::uint8_t out[], const size_t len)
// indices i and j has to be part of internal state - they were added to the former API
static void arcfour_generate_stream(std::uint8_t state[], std::uint8_t out[], const size_t len, int &i, int &j)
{
int i, j;
size_t idx;
std::uint8_t t;

for (idx = 0, i = 0, j = 0; idx < len; ++idx) {
for (idx = 0; idx < len; ++idx) {
i = (i + 1) % 256;
j = (j + state[i]) % 256;
t = state[i];
Expand All @@ -55,6 +55,8 @@ static void arcfour_generate_stream(std::uint8_t state[], std::uint8_t out[], co
}

void rc4::keysetup(const u8* key, const u32 key_bitsize, const u32 iv_bitsize) {
_ctx.i = 0;
_ctx.j = 0;
_ctx.key = std::make_unique<std::uint8_t[]>(key_bitsize / 8);
std::copy_n(key, key_bitsize / 8, _ctx.key.get());
arcfour_key_setup(_ctx.state, _ctx.key.get(), int(key_bitsize / 8));
Expand All @@ -67,7 +69,7 @@ void rc4::ivsetup(const u8* iv) { }
void rc4::encrypt_bytes(const u8 *plaintext, u8 *ciphertext, const u32 ptx_size) {
// prepare stream
auto stream = std::make_unique<std::uint8_t[]>(ptx_size);
arcfour_generate_stream(_ctx.state, stream.get(), ptx_size);
arcfour_generate_stream(_ctx.state, stream.get(), ptx_size, _ctx.i, _ctx.j);
// xor it with input
for (unsigned i = 0; i < ptx_size; ++i) {
ciphertext[i] = plaintext[i] ^ stream[i];
Expand Down
4 changes: 2 additions & 2 deletions streams/stream_ciphers/other/rc4/rc4.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ class rc4 : public stream_interface {
struct rc4_ctx {

rc4_ctx()
: state{0}
, key_size(0) {}
: state{0} {}

std::uint8_t state[256];
std::unique_ptr<std::uint8_t[]> key;
std::uint32_t key_size;
int i, j;
} _ctx;

public:
Expand Down

0 comments on commit a861663

Please sign in to comment.