Botan 3.9.0
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 for(size_t i = 0; i != m_buffer.size(); i += 4) {
55 uint8_t SX = m_state[m_X + 1];
56 m_Y = (m_Y + SX) % 256;
57 uint8_t SY = m_state[m_Y];
58 m_state[m_X + 1] = SY;
59 m_state[m_Y] = SX;
60 m_buffer[i] = m_state[(SX + SY) % 256];
61
62 SX = m_state[m_X + 2];
63 m_Y = (m_Y + SX) % 256;
64 SY = m_state[m_Y];
65 m_state[m_X + 2] = SY;
66 m_state[m_Y] = SX;
67 m_buffer[i + 1] = m_state[(SX + SY) % 256];
68
69 SX = m_state[m_X + 3];
70 m_Y = (m_Y + SX) % 256;
71 SY = m_state[m_Y];
72 m_state[m_X + 3] = SY;
73 m_state[m_Y] = SX;
74 m_buffer[i + 2] = m_state[(SX + SY) % 256];
75
76 m_X = (m_X + 4) % 256;
77 SX = m_state[m_X];
78 m_Y = (m_Y + SX) % 256;
79 SY = m_state[m_Y];
80 m_state[m_X] = SY;
81 m_state[m_Y] = SX;
82 m_buffer[i + 3] = m_state[(SX + SY) % 256];
83 }
84 m_position = 0;
85}
86
88 return !m_state.empty();
89}
90
91/*
92* RC4 Key Schedule
93*/
94void RC4::key_schedule(std::span<const uint8_t> key) {
95 m_state.resize(256);
96 m_buffer.resize(256);
97
98 m_position = m_X = m_Y = 0;
99
100 for(size_t i = 0; i != 256; ++i) {
101 m_state[i] = static_cast<uint8_t>(i);
102 }
103
104 for(size_t i = 0, state_index = 0; i != 256; ++i) {
105 state_index = (state_index + key[i % key.size()] + m_state[i]) % 256;
106 std::swap(m_state[i], m_state[state_index]);
107 }
108
109 for(size_t i = 0; i <= m_SKIP; i += m_buffer.size()) {
110 generate();
111 }
112
113 m_position += (m_SKIP % m_buffer.size());
114}
115
116/*
117* Return the name of this type
118*/
119std::string RC4::name() const {
120 if(m_SKIP == 0) {
121 return "RC4";
122 } else if(m_SKIP == 256) {
123 return "MARK-4";
124 } else {
125 return "RC4(" + std::to_string(m_SKIP) + ")";
126 }
127}
128
129/*
130* Clear memory of sensitive data
131*/
133 zap(m_state);
134 zap(m_buffer);
135 m_position = m_X = m_Y = 0;
136}
137
138/*
139* RC4 Constructor
140*/
141RC4::RC4(size_t s) : m_SKIP(s) {}
142
143void RC4::seek(uint64_t /*offset*/) {
144 throw Not_Implemented("RC4 does not support seeking");
145}
146} // namespace Botan
Key_Length_Specification key_spec() const override
Definition rc4.cpp:40
std::string name() const override
Definition rc4.cpp:119
std::unique_ptr< StreamCipher > new_object() const override
Definition rc4.cpp:32
void clear() override
Definition rc4.cpp:132
RC4(size_t skip=0)
Definition rc4.cpp:141
size_t buffer_size() const override
Definition rc4.cpp:36
void seek(uint64_t offset) override
Definition rc4.cpp:143
bool has_keying_material() const override
Definition rc4.cpp:87
void assert_key_material_set() const
Definition sym_algo.h:146
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:134
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:342