Botan  1.11.15
src/lib/alloc/secmem.h
Go to the documentation of this file.
00001 /*
00002 * Secure Memory Buffers
00003 * (C) 1999-2007,2012 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
00009 #define BOTAN_SECURE_MEMORY_BUFFERS_H__
00010 
00011 #include <botan/mem_ops.h>
00012 #include <algorithm>
00013 #include <vector>
00014 #include <deque>
00015 
00016 #if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
00017   #include <botan/locking_allocator.h>
00018 #endif
00019 
00020 namespace Botan {
00021 
00022 template<typename T>
00023 class secure_allocator
00024    {
00025    public:
00026       typedef T          value_type;
00027 
00028       typedef T*         pointer;
00029       typedef const T*   const_pointer;
00030 
00031       typedef T&         reference;
00032       typedef const T&   const_reference;
00033 
00034       typedef std::size_t     size_type;
00035       typedef std::ptrdiff_t  difference_type;
00036 
00037       secure_allocator() noexcept {}
00038 
00039       ~secure_allocator() noexcept {}
00040 
00041       pointer address(reference x) const noexcept
00042          { return std::addressof(x); }
00043 
00044       const_pointer address(const_reference x) const noexcept
00045          { return std::addressof(x); }
00046 
00047       pointer allocate(size_type n, const void* = 0)
00048          {
00049 #if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
00050          if(pointer p = static_cast<pointer>(mlock_allocator::instance().allocate(n, sizeof(T))))
00051             return p;
00052 #endif
00053 
00054          pointer p = new T[n];
00055          clear_mem(p, n);
00056          return p;
00057          }
00058 
00059       void deallocate(pointer p, size_type n)
00060          {
00061          zero_mem(p, n);
00062 
00063 #if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
00064          if(mlock_allocator::instance().deallocate(p, n, sizeof(T)))
00065             return;
00066 #endif
00067 
00068          delete [] p;
00069          }
00070 
00071       size_type max_size() const noexcept
00072          {
00073          return static_cast<size_type>(-1) / sizeof(T);
00074          }
00075 
00076       template<typename U, typename... Args>
00077       void construct(U* p, Args&&... args)
00078          {
00079          ::new(static_cast<void*>(p)) U(std::forward<Args>(args)...);
00080          }
00081 
00082       template<typename U> void destroy(U* p) { p->~U(); }
00083    };
00084 
00085 template<typename T> inline bool
00086 operator==(const secure_allocator<T>&, const secure_allocator<T>&)
00087    { return true; }
00088 
00089 template<typename T> inline bool
00090 operator!=(const secure_allocator<T>&, const secure_allocator<T>&)
00091    { return false; }
00092 
00093 template<typename T> using secure_vector = std::vector<T, secure_allocator<T>>;
00094 template<typename T> using secure_deque = std::deque<T, secure_allocator<T>>;
00095 
00096 template<typename T>
00097 std::vector<T> unlock(const secure_vector<T>& in)
00098    {
00099    std::vector<T> out(in.size());
00100    copy_mem(&out[0], &in[0], in.size());
00101    return out;
00102    }
00103 
00104 template<typename T, typename Alloc>
00105 size_t buffer_insert(std::vector<T, Alloc>& buf,
00106                      size_t buf_offset,
00107                      const T input[],
00108                      size_t input_length)
00109    {
00110    const size_t to_copy = std::min(input_length, buf.size() - buf_offset);
00111    copy_mem(&buf[buf_offset], input, to_copy);
00112    return to_copy;
00113    }
00114 
00115 template<typename T, typename Alloc, typename Alloc2>
00116 size_t buffer_insert(std::vector<T, Alloc>& buf,
00117                      size_t buf_offset,
00118                      const std::vector<T, Alloc2>& input)
00119    {
00120    const size_t to_copy = std::min(input.size(), buf.size() - buf_offset);
00121    copy_mem(&buf[buf_offset], &input[0], to_copy);
00122    return to_copy;
00123    }
00124 
00125 template<typename T, typename Alloc, typename Alloc2>
00126 std::vector<T, Alloc>&
00127 operator+=(std::vector<T, Alloc>& out,
00128            const std::vector<T, Alloc2>& in)
00129    {
00130    const size_t copy_offset = out.size();
00131    out.resize(out.size() + in.size());
00132    copy_mem(&out[copy_offset], &in[0], in.size());
00133    return out;
00134    }
00135 
00136 template<typename T, typename Alloc>
00137 std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, T in)
00138    {
00139    out.push_back(in);
00140    return out;
00141    }
00142 
00143 template<typename T, typename Alloc, typename L>
00144 std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
00145                                   const std::pair<const T*, L>& in)
00146    {
00147    const size_t copy_offset = out.size();
00148    out.resize(out.size() + in.second);
00149    copy_mem(&out[copy_offset], in.first, in.second);
00150    return out;
00151    }
00152 
00153 template<typename T, typename Alloc, typename L>
00154 std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
00155                                   const std::pair<T*, L>& in)
00156    {
00157    const size_t copy_offset = out.size();
00158    out.resize(out.size() + in.second);
00159    copy_mem(&out[copy_offset], in.first, in.second);
00160    return out;
00161    }
00162 
00163 /**
00164 * Zeroise the values; length remains unchanged
00165 * @param vec the vector to zeroise
00166 */
00167 template<typename T, typename Alloc>
00168 void zeroise(std::vector<T, Alloc>& vec)
00169    {
00170    clear_mem(&vec[0], vec.size());
00171    }
00172 
00173 /**
00174 * Zeroise the values then free the memory
00175 * @param vec the vector to zeroise and free
00176 */
00177 template<typename T, typename Alloc>
00178 void zap(std::vector<T, Alloc>& vec)
00179    {
00180    zeroise(vec);
00181    vec.clear();
00182    vec.shrink_to_fit();
00183    }
00184 
00185 }
00186 
00187 #endif