C++ Logo

SG14

Advanced search

Subject: Re: secure_clear follow-up
From: Daniel Papke (danielpapke_at_[hidden])
Date: 2020-12-18 10:33:17


The key problem with memset is not being *certain* that the overwrite
occurred. In that sense, a read-back at the user's level is meant for two
purposes:
1. Prove to security-minded skeptics that the sensitive data is being
cleared. (See note 1 below)
2. Allow for side effects such as logging "if" the clear does not occur
correctly.

For both A and B above, the issues are that memset cannot be relied upon,
and that logging may be required on failure. The only way to confirm that
the erasure has occurred is to check it, or to trust the compiler (if
secure_clear guarantees read-back). See note 1 below. Basically, the
problem boils down to this for me: Either we use memset + read-back (and
audit on failure), or we use secure_clear (and possibly audit on failure).
If I can't verify and audit on failure, then I'd probably never use the
secure_clear.

*Note 1*: In my experience, security-minded certifiers may not understand
or have a lot of faith in the compiler. This may not be an accurate view of
the world, but it's a very difficult view to argue with. More importantly,
often we would want to require multiple faults before a failure occurs
(i.e. part of normal reliable system design). In this case, either
read-back or multiple overwrites could ensure multiple faults must occur to
cause a failure (to clear sensitive data). When a failure *does* occur, you
probably want to create some kind of log so the event can be traced and
corrected in the future. Hence, the ability to introspect the buffer of
sensitive data afterwards is important.

*Note 2*: Regarding the multiple translation units comment, I think the
biggest problem there is a lack of clarity. I'm not certain your average
software developer may appreciate the subtleties of compilation and
linking. Relying on that sort of behavior today would not be desirable, in
the same way that relying on a memset w/ no read-back is undesirable. Put
differently: I would prefer explicit behavior to implicit behavior.

Maybe the problem here at root is that for people with low trust or high
security requirements, a secure_clear() just won't be "good" enough. Still,
there's an argument that a secure_clear should be good enough for the
average developer. Maybe that's enough.

Daniel

On Fri, Dec 18, 2020 at 9:57 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:

> On Fri, Dec 18, 2020 at 7:55 AM Daniel Papke via SG14 <
> sg14_at_[hidden]> wrote:
>
>> During last week's meeting, I stepped away briefly, but I don't believe
>> we covered the secure_clear proposal in any depth. Having read through it,
>> I have a concern with the proposal.
>> P1315R5 secure_clear (
>> http://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p1315r5.html)
>>
>> Secure clear is definitely a useful function. However, I'm concerned
>> that the description here is not specific about the resulting value [...]
>> I suggest that secure_clear should allow the user to specify a value for
>> the overwrite.
>>
>
> So instead of (or in addition to) P1315R5's example
> char *buf2 = ...;
> std::secure_clear(buf2, sizeof(buf2)); // OK, explicit
> you would also like the ability to write
> std::secure_clear(buf2, sizeof(buf2), 0xAA);
> for example?
>
> How is that observably different from
> // A
> std::secure_clear(buf2, sizeof(buf2));
> std::memset(buf2, 0xAA, sizeof(buf2));
> ?
> How is it observably different from
> // B
> std::memset(buf2, 0xAA, sizeof(buf2));
> std::secure_clear(buf2, sizeof(buf2));
> ?
>
> Since P1315R5 is already supposing some magic way to ensure that the
> secure_clear's *write* "really happens," it seems like it would be easy
> to specify that secure_clear also *reads* the values in the buffer. So if
> you want to ensure that 0xAA definitely gets written prior to the "random"
> overwrite, it seems like option B would do that foolproofly.
>
> You can actually use option B today, as long as secure_clear is defined in
> a different translation unit. The compiler can't tell that secure_clear
> *doesn't* read the contents of buf2, and so it must ensure that the
> memset has really happened prior to the call instruction that calls
> secure_clear. (Of course this doesn't stop extra copies of the sensitive
> data appearing on the stack, hanging around in cache, etc. P1315R5
> specifically doesn't attempt to solve the problem of securely eliminating
> all *copies* of secrets.)
>
> -Arthur
>



SG14 list run by sg14-owner@lists.isocpp.org

Older Archives on Google Groups