From: Josh Juran (jjuran_at_[hidden])
Date: 2024-07-09 15:41:36


On Jul 9, 2024, at 10:24 AM, Andrey Semashev via Boost <boost_at_[hidden]> wrote:

> On 7/9/24 15:57, Vinnie Falco via Boost wrote:
>
>> In my opinion a secure erase function which works most of the time but not
>> all of the time is worse than not having it at all, as it may imply false
>> claims about security.
>
> As far as secure erase functions go, there's no variance about whether
> it works or not. It either works as specified in the contract or it has
> a bug. And it's fairly easy to make it work as intended anyway.

secret_string::~secret_string()
{
#if HAVE_SECURE_MEMSET

        secure_memset( ptr, ‘\0’, len );

#else

        memset( ptr, ‘\0’, len );

#endif

        free( ptr );
}

The above will work most but not all of the time, depending on toolchain, OS, and even build settings. You might have a compiler that elides the memset() call (perhaps only at certain optimization levels) with an OS or libc that lacks secure_memset(), or you might have neglected to include the header that defines the feature-test macro.

> The question is rather is the secure erase enough to consider your data
> safe from leaks. It definitely is not. But not allowing it to leak into
> heap and remain there for extended periods of time is a necessary step
> towards better security. Even having just that protection alone is
> better than not having anything at all.

You might also consider having the sensitive string XORed with a one-time pad (possibly using a different allocator), so it’s never in the clear in its entirety. But I’m not a security expert and can’t speak to the efficacy of that scheme. At least it probably won’t be inadvertently undone by a sufficiently “smart” compiler.

A more important mitigation IMO is a timing-safe memcmp(), as the information otherwise leaked traverses not just process boundaries, but networks.

Cheers,
Josh