I rarely jump into these discussions, but that list of cons for secure_memset seems like a bunch of extreme edge cases. [...]
> It will get swapped to disk
This seems like a strawman argument, it _could_ get swapped out to disk, but typically your getting the secret using it then clearing it, for it to be swapped out to disk the OS needs to have determined that between that period of time that it felt it was crucial to swap it to disk which is going to be rare, and only in a multi-threaded environment would something inside that process see it.
> memset will zero out the L1 cache but fail to zero out the L2/L3 cache or main memory
This seems like another strawman argument, most read primitives are just that, a read primitive, I would love to see what technique you'll use for a common read primitive to gain access to that memory with a common read primitive? I assume this would be hoping to use different threads and race for it hoping that cache coherence doesn't get in the way. At the same time why don't we account for someone sniffing the network, reading from disk, etc.
> your magic memset will zero out the buffer you pointed it at, but it won't zero out the other copies of that same data that the optimizer caused to be made (trivially, thus undetectably) all over the stack, under the As-If Rule
This is the only semi-reasonable one in your list, however I'm not certain that it really stands up much either. [i.e. the optimizer probably doesn't make secret copies of strings, and most secrets are (non-SSO) strings...]
The API you use might make copies (e.g. copy to a buffer to send over the network) but that's within the control of the person writing the code (and whatever libraries they use).
This is where instead of guaranteeing that it will be removed which is impossible [...]
Well, I mean, I'm not really trying to die on the hill of "secure_clear was a silly idea," especially as that hill has already been taken (WG14 adopted the feature). But all of your rebuttals could be viewed as pretty weak too. Imagine going to any security firm with a list of potential exploits, and imagine they responded with "Well, that _could_ happen, but typically it would be rare," and "Well, sure that could happen, but at that point why don't we account for someone sniffing the network too," and "I'm not certain that the optimizer would do that [but I'm not certain it wouldn't, either]," and "Yes, after we scrub the secrets we might call into a third-party API that leaks them right away, but that's their coding problem not ours," and so on. The challenge may have been weak, but the rebuttal isn't terribly strong either!
As long as the entire exercise remains hypothetical, I don't think we can say whether either side is "correct."
If we discover, 10 years from now, that some libc vendor is shipping a `memset_explicit` implementation that is recognized as a dead write by GCC and optimized away, then we'll certainly know that `memset_explicit` was worse than useless (because it lulled people into a false sense of security). But assuming that never happens, then everyone will just have their respective vague feelings.
I don't think we should let perfect get in the way of implementing an obvious solution which has been done by industry for quite a while.
It's totally reasonable to say "industry does this, let's standardize it" [cough trivial relocatability cough]. But the flip side is — as WG21 recently discussed in Kona re `benchmark::DoNotOptimize` — for some things industry has long experience, and the great benefit of a single implementation. Moving something like `benchmark::DoNotOptimize` or `SecureZeroMemory` from Google Benchmark resp. Win32 into the STL, means replacing one old battle-scarred implementation with three brand-new implementations. It's not clear that that's better.
(But, on the pro side, here the library vendor is not so much replacing SecureZeroMemory, explicit_bzero, etc., as providing a thin façade over one of them. And on the con side: the vendor can't actually do that, because all the prior art is shaped like `bzero` whereas the thing WG14 standardized is shaped like `memset`! I actually don't know what vendors are going to do about that. Maybe do a secure clear, optionally followed by an "insecure memset" in the case that the `c` argument can't be statically proven to be '\0'? I think that should work fine.)
Do you have any CVEs or realistic PoCs to show that cases where things like secure_memset have been used have still led to secrets leaking? Or is it just all hypothetical?
As far as I know, all of the arguments pro and con have been hypothetical.
This entire subthread is basically recapped at
so maybe I should have just pointed there in the first place. ;D But I think my original point was that any proposal like Robin's of the form "We should standardize a library function that makes things secure by magic" is likely to encounter a lot of pushback (citing various physical reasons that feel more or less plausible to different people) and he should study the archives re: P1315 for a sense of how it might go.
Cheers,
Arthur