Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

compress_utils.cpp
Go to the documentation of this file.
1 /*
2 * Compression Utils
3 * (C) 2014,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/internal/compress_utils.h>
9 #include <botan/exceptn.h>
10
11 namespace Botan {
12
13 void* Compression_Alloc_Info::do_malloc(size_t n, size_t size)
14 {
15 const size_t total_size = n * size;
16
17 BOTAN_ASSERT_EQUAL(total_size / size, n, "Overflow check");
18
19 // TODO maximum length check here?
20
21 void* ptr = std::malloc(total_size);
22
23 /*
24 * Return null rather than throwing here as we are being called by a
25 * C library and it may not be possible for an exception to unwind
26 * the call stack from here. The compression library is expecting a
27 * function written in C and a null return on error, which it will
28 * send upwards to the compression wrappers.
29 */
30
31 if(ptr)
32 {
33 std::memset(ptr, 0, total_size);
34 m_current_allocs[ptr] = total_size;
35 }
36
37 return ptr;
38 }
39
40 void Compression_Alloc_Info::do_free(void* ptr)
41 {
42 if(ptr)
43 {
44 auto i = m_current_allocs.find(ptr);
45
46 if(i == m_current_allocs.end())
47 throw Exception("Compression_Alloc_Info::free got pointer not allocated by us");
48
49 secure_scrub_memory(ptr, i->second);
50 std::free(ptr);
51 m_current_allocs.erase(i);
52 }
53 }
54
55 void Stream_Compression::clear()
56 {
57 m_stream.reset();
58 }
59
60 void Stream_Compression::start(size_t level)
61 {
62 m_stream.reset(make_stream(level));
63 }
64
65 void Stream_Compression::process(secure_vector<uint8_t>& buf, size_t offset, uint32_t flags)
66 {
67 BOTAN_ASSERT(m_stream, "Initialized");
68 BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
69
70 if(m_buffer.size() < buf.size() + offset)
71 m_buffer.resize(buf.size() + offset);
72
73 // If the output buffer has zero length, .data() might return nullptr. This would
74 // make some compression algorithms (notably those provided by zlib) fail.
75 // Any small positive value works fine, but we choose 32 as it is the smallest power
76 // of two that is large enough to hold all the headers and trailers of the common
77 // formats, preventing further resizings to make room for output data.
78 if(m_buffer.size() == 0)
79 m_buffer.resize(32);
80
81 m_stream->next_in(buf.data() + offset, buf.size() - offset);
82 m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset);
83
84 while(true)
85 {
86 m_stream->run(flags);
87
88 if(m_stream->avail_out() == 0)
89 {
90 const size_t added = 8 + m_buffer.size();
91 m_buffer.resize(m_buffer.size() + added);
92 m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added);
93 }
94 else if(m_stream->avail_in() == 0)
95 {
96 m_buffer.resize(m_buffer.size() - m_stream->avail_out());
97 break;
98 }
99 }
100
101 copy_mem(m_buffer.data(), buf.data(), offset);
102 buf.swap(m_buffer);
103 }
104
105 void Stream_Compression::update(secure_vector<uint8_t>& buf, size_t offset, bool flush)
106 {
107 BOTAN_ASSERT(m_stream, "Initialized");
108 process(buf, offset, flush ? m_stream->flush_flag() : m_stream->run_flag());
109 }
110
111 void Stream_Compression::finish(secure_vector<uint8_t>& buf, size_t offset)
112 {
113 BOTAN_ASSERT(m_stream, "Initialized");
114 process(buf, offset, m_stream->finish_flag());
115 clear();
116 }
117
118 void Stream_Decompression::clear()
119 {
120 m_stream.reset();
121 }
122
123 void Stream_Decompression::start()
124 {
125 m_stream.reset(make_stream());
126 }
127
128 void Stream_Decompression::process(secure_vector<uint8_t>& buf, size_t offset, uint32_t flags)
129 {
130 BOTAN_ASSERT(m_stream, "Initialized");
131 BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
132
133 if(m_buffer.size() < buf.size() + offset)
134 m_buffer.resize(buf.size() + offset);
135
136 m_stream->next_in(buf.data() + offset, buf.size() - offset);
137 m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset);
138
139 while(true)
140 {
141 const bool stream_end = m_stream->run(flags);
142
143 if(stream_end)
144 {
145 if(m_stream->avail_in() == 0) // all data consumed?
146 {
147 m_buffer.resize(m_buffer.size() - m_stream->avail_out());
148 clear();
149 break;
150 }
151
152 // More data follows: try to process as a following stream
153 const size_t read = (buf.size() - offset) - m_stream->avail_in();
154 start();
155 m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read);
156 }
157
158 if(m_stream->avail_out() == 0)
159 {
160 const size_t added = 8 + m_buffer.size();
161 m_buffer.resize(m_buffer.size() + added);
162 m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added);
163 }
164 else if(m_stream->avail_in() == 0)
165 {
166 m_buffer.resize(m_buffer.size() - m_stream->avail_out());
167 break;
168 }
169 }
170
171 copy_mem(m_buffer.data(), buf.data(), offset);
172 buf.swap(m_buffer);
173 }
174
175 void Stream_Decompression::update(secure_vector<uint8_t>& buf, size_t offset)
176 {
177 process(buf, offset, m_stream->run_flag());
178 }
179
180 void Stream_Decompression::finish(secure_vector<uint8_t>& buf, size_t offset)
181 {
182 if(buf.size() != offset || m_stream.get())
183 process(buf, offset, m_stream->finish_flag());
184
185 if(m_stream.get())
186 throw Exception(name() + " finished but not at stream end");
187 }
188
189 }
Botan::secure_scrub_memory
void secure_scrub_memory(void *ptr, size_t n)
Definition: mem_ops.cpp:17
Botan::Exception
Definition: exceptn.h:21
Botan::Stream_Decompression::finish
void finish(secure_vector< uint8_t > &buf, size_t offset) finaloverride
Definition: compress_utils.cpp:180
Botan::Stream_Decompression::update
void update(secure_vector< uint8_t > &buf, size_t offset) finaloverride
Definition: compress_utils.cpp:175
Botan::Stream_Compression::update
void update(secure_vector< uint8_t > &buf, size_t offset, bool flush) finaloverride
Definition: compress_utils.cpp:105
Botan::PKCS11::flags
Flags flags(Flag flags)
Definition: p11.h:858
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
BOTAN_ASSERT_EQUAL
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:53
Botan::Stream_Compression::finish
void finish(secure_vector< uint8_t > &buf, size_t offset) finaloverride
Definition: compress_utils.cpp:111
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Botan
Definition: alg_id.cpp:13
Botan::Stream_Compression::clear
void clear() finaloverride
Definition: compress_utils.cpp:55
Botan::Decompression_Algorithm::name
virtual std::string name() const =0
Botan::Stream_Decompression::clear
void clear() finaloverride
Definition: compress_utils.cpp:118