Botan
1.11.15
|
00001 /* 00002 * CFB Mode 00003 * (C) 1999-2007,2013 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/mode_utils.h> 00009 #include <botan/cfb.h> 00010 #include <botan/parsing.h> 00011 00012 namespace Botan { 00013 00014 BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(CFB_Encryption, CFB_Decryption, 0); 00015 00016 CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) : 00017 m_cipher(cipher), 00018 m_feedback_bytes(feedback_bits ? feedback_bits / 8 : cipher->block_size()) 00019 { 00020 if(feedback_bits % 8 || feedback() > cipher->block_size()) 00021 throw std::invalid_argument(name() + ": feedback bits " + 00022 std::to_string(feedback_bits) + " not supported"); 00023 } 00024 00025 void CFB_Mode::clear() 00026 { 00027 m_cipher->clear(); 00028 m_shift_register.clear(); 00029 } 00030 00031 std::string CFB_Mode::name() const 00032 { 00033 if(feedback() == cipher().block_size()) 00034 return cipher().name() + "/CFB"; 00035 else 00036 return cipher().name() + "/CFB(" + std::to_string(feedback()*8) + ")"; 00037 } 00038 00039 size_t CFB_Mode::output_length(size_t input_length) const 00040 { 00041 return input_length; 00042 } 00043 00044 size_t CFB_Mode::update_granularity() const 00045 { 00046 return feedback(); 00047 } 00048 00049 size_t CFB_Mode::minimum_final_size() const 00050 { 00051 return 0; 00052 } 00053 00054 Key_Length_Specification CFB_Mode::key_spec() const 00055 { 00056 return cipher().key_spec(); 00057 } 00058 00059 size_t CFB_Mode::default_nonce_length() const 00060 { 00061 return cipher().block_size(); 00062 } 00063 00064 bool CFB_Mode::valid_nonce_length(size_t n) const 00065 { 00066 return (n == cipher().block_size()); 00067 } 00068 00069 void CFB_Mode::key_schedule(const byte key[], size_t length) 00070 { 00071 m_cipher->set_key(key, length); 00072 } 00073 00074 secure_vector<byte> CFB_Mode::start_raw(const byte nonce[], size_t nonce_len) 00075 { 00076 if(!valid_nonce_length(nonce_len)) 00077 throw Invalid_IV_Length(name(), nonce_len); 00078 00079 m_shift_register.assign(nonce, nonce + nonce_len); 00080 m_keystream_buf.resize(m_shift_register.size()); 00081 cipher().encrypt(m_shift_register, m_keystream_buf); 00082 00083 return secure_vector<byte>(); 00084 } 00085 00086 void CFB_Encryption::update(secure_vector<byte>& buffer, size_t offset) 00087 { 00088 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00089 size_t sz = buffer.size() - offset; 00090 byte* buf = &buffer[offset]; 00091 00092 const size_t BS = cipher().block_size(); 00093 00094 secure_vector<byte>& state = shift_register(); 00095 const size_t shift = feedback(); 00096 00097 while(sz) 00098 { 00099 const size_t took = std::min(shift, sz); 00100 xor_buf(&buf[0], &keystream_buf()[0], took); 00101 00102 // Assumes feedback-sized block except for last input 00103 copy_mem(&state[0], &state[shift], BS - shift); 00104 copy_mem(&state[BS-shift], &buf[0], took); 00105 cipher().encrypt(state, keystream_buf()); 00106 00107 buf += took; 00108 sz -= took; 00109 } 00110 } 00111 00112 void CFB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) 00113 { 00114 update(buffer, offset); 00115 } 00116 00117 void CFB_Decryption::update(secure_vector<byte>& buffer, size_t offset) 00118 { 00119 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00120 size_t sz = buffer.size() - offset; 00121 byte* buf = &buffer[offset]; 00122 00123 const size_t BS = cipher().block_size(); 00124 00125 secure_vector<byte>& state = shift_register(); 00126 const size_t shift = feedback(); 00127 00128 while(sz) 00129 { 00130 const size_t took = std::min(shift, sz); 00131 00132 // first update shift register with ciphertext 00133 copy_mem(&state[0], &state[shift], BS - shift); 00134 copy_mem(&state[BS-shift], &buf[0], took); 00135 00136 // then decrypt 00137 xor_buf(&buf[0], &keystream_buf()[0], took); 00138 00139 // then update keystream 00140 cipher().encrypt(state, keystream_buf()); 00141 00142 buf += took; 00143 sz -= took; 00144 } 00145 } 00146 00147 void CFB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) 00148 { 00149 update(buffer, offset); 00150 } 00151 00152 }