Botan
1.11.15
|
00001 /* 00002 * Counter mode 00003 * (C) 1999-2011,2014 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/ctr.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_NAMED_T(StreamCipher, "CTR-BE", CTR_BE, CTR_BE::make); 00014 00015 CTR_BE* CTR_BE::make(const Spec& spec) 00016 { 00017 if(spec.algo_name() == "CTR-BE" && spec.arg_count() == 1) 00018 { 00019 if(BlockCipher* c = Algo_Registry<BlockCipher>::global_registry().make(spec.arg(0))) 00020 return new CTR_BE(c); 00021 } 00022 return nullptr; 00023 } 00024 00025 CTR_BE::CTR_BE(BlockCipher* ciph) : 00026 m_cipher(ciph), 00027 m_counter(m_cipher->parallel_bytes()), 00028 m_pad(m_counter.size()), 00029 m_pad_pos(0) 00030 { 00031 } 00032 00033 void CTR_BE::clear() 00034 { 00035 m_cipher->clear(); 00036 zeroise(m_pad); 00037 zeroise(m_counter); 00038 m_pad_pos = 0; 00039 } 00040 00041 void CTR_BE::key_schedule(const byte key[], size_t key_len) 00042 { 00043 m_cipher->set_key(key, key_len); 00044 00045 // Set a default all-zeros IV 00046 set_iv(nullptr, 0); 00047 } 00048 00049 std::string CTR_BE::name() const 00050 { 00051 return ("CTR-BE(" + m_cipher->name() + ")"); 00052 } 00053 00054 void CTR_BE::cipher(const byte in[], byte out[], size_t length) 00055 { 00056 while(length >= m_pad.size() - m_pad_pos) 00057 { 00058 xor_buf(out, in, &m_pad[m_pad_pos], m_pad.size() - m_pad_pos); 00059 length -= (m_pad.size() - m_pad_pos); 00060 in += (m_pad.size() - m_pad_pos); 00061 out += (m_pad.size() - m_pad_pos); 00062 increment_counter(); 00063 } 00064 xor_buf(out, in, &m_pad[m_pad_pos], length); 00065 m_pad_pos += length; 00066 } 00067 00068 void CTR_BE::set_iv(const byte iv[], size_t iv_len) 00069 { 00070 if(!valid_iv_length(iv_len)) 00071 throw Invalid_IV_Length(name(), iv_len); 00072 00073 const size_t bs = m_cipher->block_size(); 00074 00075 zeroise(m_counter); 00076 00077 const size_t n_wide = m_counter.size() / m_cipher->block_size(); 00078 buffer_insert(m_counter, 0, iv, iv_len); 00079 00080 // Set m_counter blocks to IV, IV + 1, ... IV + n 00081 for(size_t i = 1; i != n_wide; ++i) 00082 { 00083 buffer_insert(m_counter, i*bs, &m_counter[(i-1)*bs], bs); 00084 00085 for(size_t j = 0; j != bs; ++j) 00086 if(++m_counter[i*bs + (bs - 1 - j)]) 00087 break; 00088 } 00089 00090 m_cipher->encrypt_n(&m_counter[0], &m_pad[0], n_wide); 00091 m_pad_pos = 0; 00092 } 00093 00094 /* 00095 * Increment the counter and update the buffer 00096 */ 00097 void CTR_BE::increment_counter() 00098 { 00099 const size_t bs = m_cipher->block_size(); 00100 const size_t n_wide = m_counter.size() / bs; 00101 00102 for(size_t i = 0; i != n_wide; ++i) 00103 { 00104 uint16_t carry = n_wide; 00105 for(size_t j = 0; carry && j != bs; ++j) 00106 { 00107 const size_t off = i*bs + (bs-1-j); 00108 const uint16_t cnt = static_cast<uint16_t>(m_counter[off]) + carry; 00109 m_counter[off] = static_cast<byte>(cnt); 00110 carry = (cnt >> 8); 00111 } 00112 } 00113 00114 m_cipher->encrypt_n(&m_counter[0], &m_pad[0], n_wide); 00115 m_pad_pos = 0; 00116 } 00117 00118 }