SecureZero & SecureBuffer Implementations for U++ #269
Replies: 3 comments 2 replies
-
Following up on the previous discussion: Implementation of
|
Beta Was this translation helpful? Give feedback.
-
After some due consideration, I decided to opt for template <class T>
void SecureZero(T* ptr, size_t count)
{
static_assert(std::is_trivially_copyable_v<T>
&& std::is_trivially_destructible_v<T>,
"Upp::SecureZero: T must be trivially copyable & destructible");
if(!ptr || count == 0)
return;
OPENSSL_cleanse(reinterpret_cast<void*>(ptr), count * sizeof(T));
}
Accordingly, a template <class T>
class SecureBuffer : Moveable<SecureBuffer<T>>, NoCopy {
static_assert(std::is_trivially_copyable_v<T>
&& std::is_trivially_destructible_v<T>,
"Upp::SecureBuffer: T must be trivially copyable & destructible");
public:
SecureBuffer() { size = 0; ptr = nullptr; }
SecureBuffer(size_t size_) { New(size_); }
SecureBuffer(SecureBuffer&& src) { size = src.size; ptr = src.ptr; src.ptr = nullptr; src.size = 0; }
~SecureBuffer() { Free(); }
SecureBuffer& operator=(SecureBuffer&& src) { Pick(pick(src)); return *this; }
void Alloc(size_t size) { Free(); New(size); }
void Clear() { Free(); }
void Zero() { SecureZero(ptr, size); };
size_t GetSize() const { return size; }
bool IsEmpty() const { return ptr == nullptr; }
operator T*() { return ptr; }
operator const T*() const { return ptr; }
T *operator~() { return ptr; }
const T *operator~() const { return ptr; }
T *Get() { return ptr; }
const T *Get() const { return ptr; }
T *begin() { return ptr; }
const T *begin() const { return ptr; }
T* Begin() { return ptr; }
const T* Begin() const { return ptr; }
T& operator[](size_t i) { ASSERT(i < size); return ptr[i]; }
const T& operator[](size_t i) const { ASSERT(i < size); return ptr[i]; }
private:
void New(size_t sz);
void Free();
void Pick(SecureBuffer&& src);
void LockMemory();
void UnlockMemory();
T* ptr = nullptr;
size_t size;
};
template<typename T>
void SecureBuffer<T>::New(size_t sz)
{
size = 0;
ptr = nullptr;
if(sz > 0) {
size = sz;
ptr = (T*) MemoryAlloc(size * sizeof(T));
LockMemory();
}
}
template<typename T>
void SecureBuffer<T>::Pick(SecureBuffer&& src)
{
if(this != &src) {
Free();
ptr = src.ptr;
size = src.size;
src.ptr = nullptr;
src.size = 0;
}
}
template<typename T>
void SecureBuffer<T>::Free()
{
if(ptr) {
Zero();
UnlockMemory();
MemoryFree(ptr);
ptr = nullptr;
size = 0;
}
}
template<typename T>
void SecureBuffer<T>::LockMemory()
{
if(!ptr || !size)
return;
#if defined(PLATFORM_WIN32)
VirtualLock((LPVOID) ptr, size * sizeof(T));
#elif defined(PLATFORM_POSIX)
mlock((void *) ptr, size * sizeof(T));
#else
NEVER();
#endif
}
template<typename T>
void SecureBuffer<T>::UnlockMemory()
{
if(!ptr || !size)
return;
#if defined(PLATFORM_WIN32)
VirtualUnlock((LPVOID) ptr, size * sizeof(T));
#elif defined(PLATFORM_POSIX)
munlock((void *) ptr, size * sizeof(T));
#else
NEVER();
#endif
}
Any thoughts? |
Beta Was this translation helpful? Give feedback.
-
Since this is merged (#272) I am closing the discussion. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Overview
This discussion proposes a secure memory handling utility for U++ applications:
SecureZero
andSecureBuffer<T>
. These are designed for use cases involving sensitive data (e.g., cryptographic keys, passwords) that must be actively erased from memory before deallocation.Goals
Provide reliable, cross-platform secure memory zeroing (
SecureZero
).Ensure memory used by sensitive data is zeroed and locked against swapping (
SecureBuffer<T>
).Maintain safety and compatibility with U++ memory management.
SecureZero<T>
A template function that securely clears memory regions of trivially copyable types. It uses platform-specific and cryptographically secure mechanisms to ensure zeroing cannot be optimized out by the compiler.
Key Features
Template-constrained to trivially copyable types via
static_assert
.Uses
OPENSSL_cleanse()
if OpenSSL 0.9.7+ is available.Fallback implementation uses
volatile
byte/dword writes to ensure compiler does not remove memory clearing.Adds an explicit memory barrier with
std::atomic_thread_fence
.SecureBuffer<T>
A RAII container almost identical to
Upp::Buffer
but for sensitive data, ensuring:Template-constrained to trivially copyable types via
static_assert
.Memory is allocated dynamically.
Memory is locked via
mlock
/VirtualLock
to prevent swapping.Memory is zeroed on destruction.
Interface Summary
Highlights
Implements move semantics with secure, automatic zeroing.
Prevents copy semantics to avoid unsafe duplication.
Memory locking is cross-platform (POSIX/Windows).
Platform-specific Zeroing + Locking
Windows: Uses
VirtualLock
/VirtualUnlock
.POSIX: Uses
mlock
/munlock
.Summary
This feature, if accepted, will add secure memory handling to U++ in a modular, reusable, and portable manner. It provides primitives necessary for applications requiring strong control over memory hygiene, such as password managers, secure communication tools, and cryptographic software.
Note: The
SecureZero
andSecureBuffer
implementations, along with unit tests and examples, are ready. I believe they will be beneficial for U++, especially given the increasing security demands. If you agree, please let me know.Beta Was this translation helpful? Give feedback.
All reactions