/* * Secure Memory Buffers * (C) 1999-2007,2012 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_SECURE_MEMORY_BUFFERS_H_ #define BOTAN_SECURE_MEMORY_BUFFERS_H_ #include // IWYU pragma: export #include // IWYU pragma: export #include // IWYU pragma: export #include #include #include namespace Botan { template class secure_allocator { public: /* * Assert exists to prevent someone from doing something that will * probably crash anyway (like secure_vector where ~non_POD_t * deletes a member pointer which was zeroed before it ran). * MSVC in debug mode uses non-integral proxy types in container types * like std::vector, thus we disable the check there. */ #if !defined(_ITERATOR_DEBUG_LEVEL) || _ITERATOR_DEBUG_LEVEL == 0 static_assert(std::is_integral::value, "secure_allocator supports only integer types"); #endif typedef T value_type; typedef std::size_t size_type; #ifdef BOTAN_BUILD_COMPILER_IS_MSVC_2013 secure_allocator() = default; secure_allocator(const secure_allocator&) = default; secure_allocator& operator=(const secure_allocator&) = default; ~secure_allocator() = default; template struct rebind { typedef secure_allocator other; }; void construct(value_type* mem, const value_type& value) { std::_Construct(mem, value); } void destroy(value_type* mem) { std::_Destroy(mem); } #else secure_allocator() BOTAN_NOEXCEPT = default; secure_allocator(const secure_allocator&) BOTAN_NOEXCEPT = default; secure_allocator& operator=(const secure_allocator&) BOTAN_NOEXCEPT = default; ~secure_allocator() BOTAN_NOEXCEPT = default; #endif template secure_allocator(const secure_allocator&) BOTAN_NOEXCEPT {} T* allocate(std::size_t n) { return static_cast(allocate_memory(n, sizeof(T))); } void deallocate(T* p, std::size_t n) { deallocate_memory(p, n, sizeof(T)); } }; template inline bool operator==(const secure_allocator&, const secure_allocator&) { return true; } template inline bool operator!=(const secure_allocator&, const secure_allocator&) { return false; } template using secure_vector = std::vector>; template using secure_deque = std::deque>; // For better compatability with 1.10 API template using SecureVector = secure_vector; template std::vector unlock(const secure_vector& in) { std::vector out(in.size()); copy_mem(out.data(), in.data(), in.size()); return out; } template size_t buffer_insert(std::vector& buf, size_t buf_offset, const T input[], size_t input_length) { const size_t to_copy = std::min(input_length, buf.size() - buf_offset); if(to_copy > 0) { copy_mem(&buf[buf_offset], input, to_copy); } return to_copy; } template size_t buffer_insert(std::vector& buf, size_t buf_offset, const std::vector& input) { const size_t to_copy = std::min(input.size(), buf.size() - buf_offset); if(to_copy > 0) { copy_mem(&buf[buf_offset], input.data(), to_copy); } return to_copy; } template std::vector& operator+=(std::vector& out, const std::vector& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.size()); if(in.size() > 0) { copy_mem(&out[copy_offset], in.data(), in.size()); } return out; } template std::vector& operator+=(std::vector& out, T in) { out.push_back(in); return out; } template std::vector& operator+=(std::vector& out, const std::pair& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.second); if(in.second > 0) { copy_mem(&out[copy_offset], in.first, in.second); } return out; } template std::vector& operator+=(std::vector& out, const std::pair& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.second); if(in.second > 0) { copy_mem(&out[copy_offset], in.first, in.second); } return out; } /** * Zeroise the values; length remains unchanged * @param vec the vector to zeroise */ template void zeroise(std::vector& vec) { clear_mem(vec.data(), vec.size()); } /** * Zeroise the values then free the memory * @param vec the vector to zeroise and free */ template void zap(std::vector& vec) { zeroise(vec); vec.clear(); vec.shrink_to_fit(); } } #endif