1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*************************************************
* CFB Mode Source File *
* (C) 1999-2005 The Botan Project *
*************************************************/
#include <botan/cfb.h>
#include <botan/lookup.h>
#include <botan/parsing.h>
#include <botan/bit_ops.h>
namespace Botan {
namespace {
/*************************************************
* Check the feedback size *
*************************************************/
void check_feedback(u32bit BLOCK_SIZE, u32bit FEEDBACK_SIZE, u32bit bits,
const std::string& name)
{
if(FEEDBACK_SIZE == 0 || FEEDBACK_SIZE > BLOCK_SIZE || bits % 8 != 0)
throw Invalid_Argument(name + ": Invalid feedback size " +
to_string(bits));
}
}
/*************************************************
* CFB Encryption Constructor *
*************************************************/
CFB_Encryption::CFB_Encryption(const std::string& cipher_name,
u32bit fback_bits) :
BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1),
FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE)
{
check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
}
/*************************************************
* CFB Encryption Constructor *
*************************************************/
CFB_Encryption::CFB_Encryption(const std::string& cipher_name,
const SymmetricKey& key,
const InitializationVector& iv,
u32bit fback_bits) :
BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1),
FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE)
{
check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
set_key(key);
set_iv(iv);
}
/*************************************************
* Encrypt data in CFB mode *
*************************************************/
void CFB_Encryption::write(const byte input[], u32bit length)
{
while(length)
{
u32bit xored = std::min(FEEDBACK_SIZE - position, length);
xor_buf(buffer + position, input, xored);
send(buffer + position, xored);
input += xored;
length -= xored;
position += xored;
if(position == FEEDBACK_SIZE)
feedback();
}
}
/*************************************************
* Do the feedback *
*************************************************/
void CFB_Encryption::feedback()
{
for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; j++)
state[j] = state[j + FEEDBACK_SIZE];
state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE);
cipher->encrypt(state, buffer);
position = 0;
}
/*************************************************
* CFB Decryption Constructor *
*************************************************/
CFB_Decryption::CFB_Decryption(const std::string& cipher_name,
u32bit fback_bits) :
BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1),
FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE)
{
check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
}
/*************************************************
* CFB Decryption Constructor *
*************************************************/
CFB_Decryption::CFB_Decryption(const std::string& cipher_name,
const SymmetricKey& key,
const InitializationVector& iv,
u32bit fback_bits) :
BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1),
FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE)
{
check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
set_key(key);
set_iv(iv);
}
/*************************************************
* Decrypt data in CFB mode *
*************************************************/
void CFB_Decryption::write(const byte input[], u32bit length)
{
while(length)
{
u32bit xored = std::min(FEEDBACK_SIZE - position, length);
xor_buf(buffer + position, input, xored);
send(buffer + position, xored);
buffer.copy(position, input, xored);
input += xored;
length -= xored;
position += xored;
if(position == FEEDBACK_SIZE)
feedback();
}
}
/*************************************************
* Do the feedback *
*************************************************/
void CFB_Decryption::feedback()
{
for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; j++)
state[j] = state[j + FEEDBACK_SIZE];
state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE);
cipher->encrypt(state, buffer);
position = 0;
}
}
|