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@gmail.com> wrote:
On Fri, Dec 18, 2020 at 7:55 AM Daniel Papke via SG14 <sg14@lists.isocpp.org> 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