Botan 3.6.1
Crypto and TLS for C&
rc4.cpp
Go to the documentation of this file.
1/*
2* RC4
3* (C) 1999-2007 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/rc4.h>
9
10#include <botan/exceptn.h>
11#include <botan/mem_ops.h>
12
13namespace Botan {
14
15/*
16* Combine cipher stream with message
17*/
18void RC4::cipher_bytes(const uint8_t in[], uint8_t out[], size_t length) {
20
21 while(length >= m_buffer.size() - m_position) {
22 xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
23 length -= (m_buffer.size() - m_position);
24 in += (m_buffer.size() - m_position);
25 out += (m_buffer.size() - m_position);
26 generate();
27 }
28 xor_buf(out, in, &m_buffer[m_position], length);
29 m_position += length;
30}
31
32std::unique_ptr<StreamCipher> RC4::new_object() const {
33 return std::make_unique<RC4>(m_SKIP);
34}
35
36size_t RC4::buffer_size() const {
37 return 256;
38}
39
43
44void RC4::set_iv_bytes(const uint8_t* /*iv*/, size_t length) {
45 if(length > 0) {
46 throw Invalid_IV_Length("RC4", length);
47 }
48}
49
50/*
51* Generate cipher stream
52*/
53void RC4::generate() {
54 uint8_t SX, SY;
55 for(size_t i = 0; i != m_buffer.size(); i += 4) {
56 SX = m_state[m_X + 1];
57 m_Y = (m_Y + SX) % 256;
58 SY = m_state[m_Y];
59 m_state[m_X + 1] = SY;
60 m_state[m_Y] = SX;
61 m_buffer[i] = m_state[(SX + SY) % 256];
62
63 SX = m_state[m_X + 2];
64 m_Y = (m_Y + SX) % 256;
65 SY = m_state[m_Y];
66 m_state[m_X + 2] = SY;
67 m_state[m_Y] = SX;
68 m_buffer[i + 1] = m_state[(SX + SY) % 256];
69
70 SX = m_state[m_X + 3];
71 m_Y = (m_Y + SX) % 256;
72 SY = m_state[m_Y];
73 m_state[m_X + 3] = SY;
74 m_state[m_Y] = SX;
75 m_buffer[i + 2] = m_state[(SX + SY) % 256];
76
77 m_X = (m_X + 4) % 256;
78 SX = m_state[m_X];
79 m_Y = (m_Y + SX) % 256;
80 SY = m_state[m_Y];
81 m_state[m_X] = SY;
82 m_state[m_Y] = SX;
83 m_buffer[i + 3] = m_state[(SX + SY) % 256];
84 }
85 m_position = 0;
86}
87
89 return !m_state.empty();
90}
91
92/*
93* RC4 Key Schedule
94*/
95void RC4::key_schedule(std::span<const uint8_t> key) {
96 m_state.resize(256);
97 m_buffer.resize(256);
98
99 m_position = m_X = m_Y = 0;
100
101 for(size_t i = 0; i != 256; ++i) {
102 m_state[i] = static_cast<uint8_t>(i);
103 }
104
105 for(size_t i = 0, state_index = 0; i != 256; ++i) {
106 state_index = (state_index + key[i % key.size()] + m_state[i]) % 256;
107 std::swap(m_state[i], m_state[state_index]);
108 }
109
110 for(size_t i = 0; i <= m_SKIP; i += m_buffer.size()) {
111 generate();
112 }
113
114 m_position += (m_SKIP % m_buffer.size());
115}
116
117/*
118* Return the name of this type
119*/
120std::string RC4::name() const {
121 if(m_SKIP == 0) {
122 return "RC4";
123 } else if(m_SKIP == 256) {
124 return "MARK-4";
125 } else {
126 return "RC4(" + std::to_string(m_SKIP) + ")";
127 }
128}
129
130/*
131* Clear memory of sensitive data
132*/
134 zap(m_state);
135 zap(m_buffer);
136 m_position = m_X = m_Y = 0;
137}
138
139/*
140* RC4 Constructor
141*/
142RC4::RC4(size_t s) : m_SKIP(s) {}
143
144void RC4::seek(uint64_t /*offset*/) {
145 throw Not_Implemented("RC4 does not support seeking");
146}
147} // namespace Botan
Key_Length_Specification key_spec() const override
Definition rc4.cpp:40
std::string name() const override
Definition rc4.cpp:120
std::unique_ptr< StreamCipher > new_object() const override
Definition rc4.cpp:32
void clear() override
Definition rc4.cpp:133
RC4(size_t skip=0)
Definition rc4.cpp:142
size_t buffer_size() const override
Definition rc4.cpp:36
void seek(uint64_t offset) override
Definition rc4.cpp:144
bool has_keying_material() const override
Definition rc4.cpp:88
void assert_key_material_set() const
Definition sym_algo.h:139
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:117
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:341