Botan  1.11.15
src/lib/stream/ctr/ctr.cpp
Go to the documentation of this file.
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 }