Botan  1.11.15
src/lib/compression/compression.cpp
Go to the documentation of this file.
00001 /*
00002 * Compression Transform
00003 * (C) 2014 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/compression.h>
00009 #include <botan/internal/compress_utils.h>
00010 #include <botan/mem_ops.h>
00011 #include <cstdlib>
00012 
00013 namespace Botan {
00014 
00015 void* Compression_Alloc_Info::do_malloc(size_t n, size_t size)
00016    {
00017    const size_t total_sz = n * size;
00018 
00019    void* ptr = std::malloc(total_sz);
00020    m_current_allocs[ptr] = total_sz;
00021    return ptr;
00022    }
00023 
00024 void Compression_Alloc_Info::do_free(void* ptr)
00025    {
00026    if(ptr)
00027       {
00028       auto i = m_current_allocs.find(ptr);
00029 
00030       if(i == m_current_allocs.end())
00031          throw std::runtime_error("Compression_Alloc_Info::free got pointer not allocated by us");
00032 
00033       zero_mem(ptr, i->second);
00034       std::free(ptr);
00035       m_current_allocs.erase(i);
00036       }
00037    }
00038 
00039 Transform* make_compressor(const std::string& type, size_t level)
00040    {
00041    const std::string comp_suffix = "_Compression(" + std::to_string(level) + ")";
00042 
00043    if(type == "zlib")
00044       return get_transform("Zlib" + comp_suffix);
00045    if(type == "deflate")
00046       return get_transform("Deflate" + comp_suffix);
00047    if(type == "gzip" || type == "gz")
00048       return get_transform("Gzip" + comp_suffix);
00049    if(type == "bzip2" || type == "bz2")
00050       return get_transform("Bzip2" + comp_suffix);
00051    if(type == "lzma" || type == "xz")
00052       return get_transform("LZMA" + comp_suffix);
00053 
00054    return nullptr;
00055    }
00056 
00057 Transform* make_decompressor(const std::string& type)
00058    {
00059    if(type == "zlib")
00060       return get_transform("Zlib_Decompression");
00061    if(type == "deflate")
00062       return get_transform("Deflate_Decompression");
00063    if(type == "gzip" || type == "gz")
00064       return get_transform("Gzip_Decompression");
00065    if(type == "bzip2" || type == "bz2")
00066       return get_transform("Bzip2_Decompression");
00067    if(type == "lzma" || type == "xz")
00068       return get_transform("LZMA_Decompression");
00069 
00070    return nullptr;
00071    }
00072 
00073 void Stream_Compression::clear()
00074    {
00075    m_stream.reset();
00076    }
00077 
00078 secure_vector<byte> Stream_Compression::start_raw(const byte[], size_t nonce_len)
00079    {
00080    if(!valid_nonce_length(nonce_len))
00081       throw Invalid_IV_Length(name(), nonce_len);
00082 
00083    m_stream.reset(make_stream());
00084    return secure_vector<byte>();
00085    }
00086 
00087 void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags)
00088    {
00089    BOTAN_ASSERT(m_stream, "Initialized");
00090    BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
00091 
00092    if(m_buffer.size() < buf.size() + offset)
00093       m_buffer.resize(buf.size() + offset);
00094 
00095    m_stream->next_in(&buf[offset], buf.size() - offset);
00096    m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset);
00097 
00098    while(true)
00099       {
00100       m_stream->run(flags);
00101 
00102       if(m_stream->avail_out() == 0)
00103          {
00104          const size_t added = 8 + m_buffer.size();
00105          m_buffer.resize(m_buffer.size() + added);
00106          m_stream->next_out(&m_buffer[m_buffer.size() - added], added);
00107          }
00108       else if(m_stream->avail_in() == 0)
00109          {
00110          m_buffer.resize(m_buffer.size() - m_stream->avail_out());
00111          break;
00112          }
00113       }
00114 
00115    copy_mem(&m_buffer[0], &buf[0], offset);
00116    buf.swap(m_buffer);
00117    }
00118 
00119 void Stream_Compression::update(secure_vector<byte>& buf, size_t offset)
00120    {
00121    process(buf, offset, m_stream->run_flag());
00122    }
00123 
00124 void Stream_Compression::flush(secure_vector<byte>& buf, size_t offset)
00125    {
00126    process(buf, offset, m_stream->flush_flag());
00127    }
00128 
00129 void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset)
00130    {
00131    process(buf, offset, m_stream->finish_flag());
00132    clear();
00133    }
00134 
00135 void Stream_Decompression::clear()
00136    {
00137    m_stream.reset();
00138    }
00139 
00140 secure_vector<byte> Stream_Decompression::start_raw(const byte[], size_t nonce_len)
00141    {
00142    if(!valid_nonce_length(nonce_len))
00143       throw Invalid_IV_Length(name(), nonce_len);
00144 
00145    m_stream.reset(make_stream());
00146 
00147    return secure_vector<byte>();
00148    }
00149 
00150 void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags)
00151    {
00152    BOTAN_ASSERT(m_stream, "Initialized");
00153    BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
00154 
00155    if(m_buffer.size() < buf.size() + offset)
00156       m_buffer.resize(buf.size() + offset);
00157 
00158    m_stream->next_in(&buf[offset], buf.size() - offset);
00159    m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset);
00160 
00161    while(true)
00162       {
00163       const bool stream_end = m_stream->run(flags);
00164 
00165       if(stream_end)
00166          {
00167          if(m_stream->avail_in() == 0) // all data consumed?
00168             {
00169             m_buffer.resize(m_buffer.size() - m_stream->avail_out());
00170             clear();
00171             break;
00172             }
00173 
00174          // More data follows: try to process as a following stream
00175          const size_t read = (buf.size() - offset) - m_stream->avail_in();
00176          start();
00177          m_stream->next_in(&buf[offset + read], buf.size() - offset - read);
00178          }
00179 
00180       if(m_stream->avail_out() == 0)
00181          {
00182          const size_t added = 8 + m_buffer.size();
00183          m_buffer.resize(m_buffer.size() + added);
00184          m_stream->next_out(&m_buffer[m_buffer.size() - added], added);
00185          }
00186       else if(m_stream->avail_in() == 0)
00187          {
00188          m_buffer.resize(m_buffer.size() - m_stream->avail_out());
00189          break;
00190          }
00191       }
00192 
00193    copy_mem(&m_buffer[0], &buf[0], offset);
00194    buf.swap(m_buffer);
00195    }
00196 
00197 void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset)
00198    {
00199    process(buf, offset, m_stream->run_flag());
00200    }
00201 
00202 void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset)
00203    {
00204    if(buf.size() != offset || m_stream.get())
00205       process(buf, offset, m_stream->finish_flag());
00206 
00207    if(m_stream.get())
00208       throw std::runtime_error(name() + " finished but not at stream end");
00209    }
00210 
00211 }