Botan  1.11.15
src/lib/modes/cbc/cbc.cpp
Go to the documentation of this file.
00001 /*
00002 * CBC 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/cbc.h>
00010 #include <botan/mode_pad.h>
00011 
00012 namespace Botan {
00013 
00014 template<typename CBC_T, typename CTS_T>
00015 Transform* make_cbc_mode(const Transform::Spec& spec)
00016    {
00017    std::unique_ptr<BlockCipher> bc(Algo_Registry<BlockCipher>::global_registry().make(spec.arg(0)));
00018 
00019    if(bc)
00020       {
00021       const std::string padding = spec.arg(1, "PKCS7");
00022 
00023       if(padding == "CTS")
00024          return new CTS_T(bc.release());
00025       else
00026          return new CBC_T(bc.release(), get_bc_pad(padding));
00027       }
00028 
00029    return nullptr;
00030    }
00031 
00032 BOTAN_REGISTER_TRANSFORM(CBC_Encryption, (make_cbc_mode<CBC_Encryption,CTS_Encryption>));
00033 BOTAN_REGISTER_TRANSFORM(CBC_Decryption, (make_cbc_mode<CBC_Decryption,CTS_Decryption>));
00034 
00035 CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
00036    m_cipher(cipher),
00037    m_padding(padding),
00038    m_state(m_cipher->block_size())
00039    {
00040    if(m_padding && !m_padding->valid_blocksize(cipher->block_size()))
00041       throw std::invalid_argument("Padding " + m_padding->name() +
00042                                   " cannot be used with " +
00043                                   cipher->name() + "/CBC");
00044    }
00045 
00046 void CBC_Mode::clear()
00047    {
00048    m_cipher->clear();
00049    m_state.clear();
00050    }
00051 
00052 std::string CBC_Mode::name() const
00053    {
00054    if(m_padding)
00055       return cipher().name() + "/CBC/" + padding().name();
00056    else
00057       return cipher().name() + "/CBC/CTS";
00058    }
00059 
00060 size_t CBC_Mode::update_granularity() const
00061    {
00062    return cipher().parallel_bytes();
00063    }
00064 
00065 Key_Length_Specification CBC_Mode::key_spec() const
00066    {
00067    return cipher().key_spec();
00068    }
00069 
00070 size_t CBC_Mode::default_nonce_length() const
00071    {
00072    return cipher().block_size();
00073    }
00074 
00075 bool CBC_Mode::valid_nonce_length(size_t n) const
00076    {
00077    return (n == 0 || n == cipher().block_size());
00078    }
00079 
00080 void CBC_Mode::key_schedule(const byte key[], size_t length)
00081    {
00082    m_cipher->set_key(key, length);
00083    }
00084 
00085 secure_vector<byte> CBC_Mode::start_raw(const byte nonce[], size_t nonce_len)
00086    {
00087    if(!valid_nonce_length(nonce_len))
00088       throw Invalid_IV_Length(name(), nonce_len);
00089 
00090    /*
00091    * A nonce of zero length means carry the last ciphertext value over
00092    * as the new IV, as unfortunately some protocols require this. If
00093    * this is the first message then we use an IV of all zeros.
00094    */
00095    if(nonce_len)
00096       m_state.assign(nonce, nonce + nonce_len);
00097 
00098    return secure_vector<byte>();
00099    }
00100 
00101 size_t CBC_Encryption::minimum_final_size() const
00102    {
00103    return 0;
00104    }
00105 
00106 size_t CBC_Encryption::output_length(size_t input_length) const
00107    {
00108    return round_up(input_length, cipher().block_size());
00109    }
00110 
00111 void CBC_Encryption::update(secure_vector<byte>& buffer, size_t offset)
00112    {
00113    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00114    const size_t sz = buffer.size() - offset;
00115    byte* buf = &buffer[offset];
00116 
00117    const size_t BS = cipher().block_size();
00118 
00119    BOTAN_ASSERT(sz % BS == 0, "CBC input is full blocks");
00120    const size_t blocks = sz / BS;
00121 
00122    const byte* prev_block = state_ptr();
00123 
00124    if(blocks)
00125       {
00126       for(size_t i = 0; i != blocks; ++i)
00127          {
00128          xor_buf(&buf[BS*i], prev_block, BS);
00129          cipher().encrypt(&buf[BS*i]);
00130          prev_block = &buf[BS*i];
00131          }
00132 
00133       state().assign(&buf[BS*(blocks-1)], &buf[BS*blocks]);
00134       }
00135    }
00136 
00137 void CBC_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
00138    {
00139    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00140 
00141    const size_t BS = cipher().block_size();
00142 
00143    const size_t bytes_in_final_block = (buffer.size()-offset) % BS;
00144 
00145    padding().add_padding(buffer, bytes_in_final_block, BS);
00146 
00147    if((buffer.size()-offset) % BS)
00148       throw std::runtime_error("Did not pad to full block size in " + name());
00149 
00150    update(buffer, offset);
00151    }
00152 
00153 bool CTS_Encryption::valid_nonce_length(size_t n) const
00154    {
00155    return (n == cipher().block_size());
00156    }
00157 
00158 size_t CTS_Encryption::minimum_final_size() const
00159    {
00160    return cipher().block_size() + 1;
00161    }
00162 
00163 size_t CTS_Encryption::output_length(size_t input_length) const
00164    {
00165    return input_length; // no ciphertext expansion in CTS
00166    }
00167 
00168 void CTS_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
00169    {
00170    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00171    byte* buf = &buffer[offset];
00172    const size_t sz = buffer.size() - offset;
00173 
00174    const size_t BS = cipher().block_size();
00175 
00176    if(sz < BS + 1)
00177       throw Encoding_Error(name() + ": insufficient data to encrypt");
00178 
00179    if(sz % BS == 0)
00180       {
00181       update(buffer, offset);
00182 
00183       // swap last two blocks
00184       for(size_t i = 0; i != BS; ++i)
00185          std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]);
00186       }
00187    else
00188       {
00189       const size_t full_blocks = ((sz / BS) - 1) * BS;
00190       const size_t final_bytes = sz - full_blocks;
00191       BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range");
00192 
00193       secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes);
00194       buffer.resize(full_blocks + offset);
00195       update(buffer, offset);
00196 
00197       xor_buf(&last[0], state_ptr(), BS);
00198       cipher().encrypt(&last[0]);
00199 
00200       for(size_t i = 0; i != final_bytes - BS; ++i)
00201          {
00202          last[i] ^= last[i + BS];
00203          last[i + BS] ^= last[i];
00204          }
00205 
00206       cipher().encrypt(&last[0]);
00207 
00208       buffer += last;
00209       }
00210    }
00211 
00212 size_t CBC_Decryption::output_length(size_t input_length) const
00213    {
00214    return input_length; // precise for CTS, worst case otherwise
00215    }
00216 
00217 size_t CBC_Decryption::minimum_final_size() const
00218    {
00219    return cipher().block_size();
00220    }
00221 
00222 void CBC_Decryption::update(secure_vector<byte>& buffer, size_t offset)
00223    {
00224    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00225    const size_t sz = buffer.size() - offset;
00226    byte* buf = &buffer[offset];
00227 
00228    const size_t BS = cipher().block_size();
00229 
00230    BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
00231    size_t blocks = sz / BS;
00232 
00233    while(blocks)
00234       {
00235       const size_t to_proc = std::min(BS * blocks, m_tempbuf.size());
00236 
00237       cipher().decrypt_n(buf, &m_tempbuf[0], to_proc / BS);
00238 
00239       xor_buf(&m_tempbuf[0], state_ptr(), BS);
00240       xor_buf(&m_tempbuf[BS], buf, to_proc - BS);
00241       copy_mem(state_ptr(), buf + (to_proc - BS), BS);
00242 
00243       copy_mem(buf, &m_tempbuf[0], to_proc);
00244 
00245       buf += to_proc;
00246       blocks -= to_proc / BS;
00247       }
00248    }
00249 
00250 void CBC_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
00251    {
00252    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00253    const size_t sz = buffer.size() - offset;
00254 
00255    const size_t BS = cipher().block_size();
00256 
00257    if(sz == 0 || sz % BS)
00258       throw Decoding_Error(name() + ": Ciphertext not a multiple of block size");
00259 
00260    update(buffer, offset);
00261 
00262    const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS);
00263    buffer.resize(buffer.size() - pad_bytes); // remove padding
00264    }
00265 
00266 bool CTS_Decryption::valid_nonce_length(size_t n) const
00267    {
00268    return (n == cipher().block_size());
00269    }
00270 
00271 size_t CTS_Decryption::minimum_final_size() const
00272    {
00273    return cipher().block_size() + 1;
00274    }
00275 
00276 void CTS_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
00277    {
00278    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
00279    const size_t sz = buffer.size() - offset;
00280    byte* buf = &buffer[offset];
00281 
00282    const size_t BS = cipher().block_size();
00283 
00284    if(sz < BS + 1)
00285       throw Encoding_Error(name() + ": insufficient data to decrypt");
00286 
00287    if(sz % BS == 0)
00288       {
00289       // swap last two blocks
00290 
00291       for(size_t i = 0; i != BS; ++i)
00292          std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]);
00293 
00294       update(buffer, offset);
00295       }
00296    else
00297       {
00298       const size_t full_blocks = ((sz / BS) - 1) * BS;
00299       const size_t final_bytes = sz - full_blocks;
00300       BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range");
00301 
00302       secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes);
00303       buffer.resize(full_blocks + offset);
00304       update(buffer, offset);
00305 
00306       cipher().decrypt(&last[0]);
00307 
00308       xor_buf(&last[0], &last[BS], final_bytes - BS);
00309 
00310       for(size_t i = 0; i != final_bytes - BS; ++i)
00311          std::swap(last[i], last[i + BS]);
00312 
00313       cipher().decrypt(&last[0]);
00314       xor_buf(&last[0], state_ptr(), BS);
00315 
00316       buffer += last;
00317       }
00318    }
00319 
00320 }