Botan  1.11.15
src/lib/stream/rc4/rc4.cpp
Go to the documentation of this file.
00001 /*
00002 * RC4
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/stream_utils.h>
00009 #include <botan/rc4.h>
00010 
00011 namespace Botan {
00012 
00013 BOTAN_REGISTER_NAMED_T(StreamCipher, "RC4", RC4, RC4::make);
00014 
00015 RC4* RC4::make(const Spec& spec)
00016    {
00017    if(spec.algo_name() == "RC4")
00018       return new RC4(spec.arg_as_integer(0, 0));
00019    if(spec.algo_name() == "RC4_drop")
00020       return new RC4(768);
00021    return nullptr;
00022    }
00023 
00024 /*
00025 * Combine cipher stream with message
00026 */
00027 void RC4::cipher(const byte in[], byte out[], size_t length)
00028    {
00029    while(length >= buffer.size() - position)
00030       {
00031       xor_buf(out, in, &buffer[position], buffer.size() - position);
00032       length -= (buffer.size() - position);
00033       in += (buffer.size() - position);
00034       out += (buffer.size() - position);
00035       generate();
00036       }
00037    xor_buf(out, in, &buffer[position], length);
00038    position += length;
00039    }
00040 
00041 /*
00042 * Generate cipher stream
00043 */
00044 void RC4::generate()
00045    {
00046    byte SX, SY;
00047    for(size_t i = 0; i != buffer.size(); i += 4)
00048       {
00049       SX = state[X+1]; Y = (Y + SX) % 256; SY = state[Y];
00050       state[X+1] = SY; state[Y] = SX;
00051       buffer[i] = state[(SX + SY) % 256];
00052 
00053       SX = state[X+2]; Y = (Y + SX) % 256; SY = state[Y];
00054       state[X+2] = SY; state[Y] = SX;
00055       buffer[i+1] = state[(SX + SY) % 256];
00056 
00057       SX = state[X+3]; Y = (Y + SX) % 256; SY = state[Y];
00058       state[X+3] = SY; state[Y] = SX;
00059       buffer[i+2] = state[(SX + SY) % 256];
00060 
00061       X = (X + 4) % 256;
00062       SX = state[X]; Y = (Y + SX) % 256; SY = state[Y];
00063       state[X] = SY; state[Y] = SX;
00064       buffer[i+3] = state[(SX + SY) % 256];
00065       }
00066    position = 0;
00067    }
00068 
00069 /*
00070 * RC4 Key Schedule
00071 */
00072 void RC4::key_schedule(const byte key[], size_t length)
00073    {
00074    state.resize(256);
00075    buffer.resize(256);
00076 
00077    position = X = Y = 0;
00078 
00079    for(size_t i = 0; i != 256; ++i)
00080       state[i] = static_cast<byte>(i);
00081 
00082    for(size_t i = 0, state_index = 0; i != 256; ++i)
00083       {
00084       state_index = (state_index + key[i % length] + state[i]) % 256;
00085       std::swap(state[i], state[state_index]);
00086       }
00087 
00088    for(size_t i = 0; i <= SKIP; i += buffer.size())
00089       generate();
00090 
00091    position += (SKIP % buffer.size());
00092    }
00093 
00094 /*
00095 * Return the name of this type
00096 */
00097 std::string RC4::name() const
00098    {
00099    if(SKIP == 0)   return "RC4";
00100    if(SKIP == 256) return "MARK-4";
00101    else            return "RC4_skip(" + std::to_string(SKIP) + ")";
00102    }
00103 
00104 /*
00105 * Clear memory of sensitive data
00106 */
00107 void RC4::clear()
00108    {
00109    zap(state);
00110    zap(buffer);
00111    position = X = Y = 0;
00112    }
00113 
00114 /*
00115 * RC4 Constructor
00116 */
00117 RC4::RC4(size_t s) : SKIP(s) {}
00118 
00119 }