Earlier quoted context omitted.
I'm not aware of any language that would be better. Most languages don't even let you touch memory to try to zero it.
Zeroing out an array or struct field is not a C-specific feature.
How to zero a buffer
91–100 of 216 posts
Re: How to zero a buffer
#92Re: How to zero a buffer
#93Well, if the buffer is so critical and yet small, why not just free it and re-allocate the whole thing next time we use it.
Re: How to zero a buffer
#94Earlier quoted context omitted.
The first comment there (by Anonymous) claims that the final technique can also be optimized: (memset_ptr)(p, 0, len); > can be replaced by: if (memset_ptr == memset) { memset(p, 0, len); } else { memset_ptr(p, 0, len); } > Which in turn can be optimized using the other tricks noticed above into: if (memset_ptr != memset) { memset_ptr(p, 0, len); } I'm no expert, but this seems like a believable defeat of the techniq…
That's not quite right since it's now reading memset_ptr twice, but the concept does seem to be right -- the volatile pointer must be read but the standard doesn't require that the function is invoked.
Re: How to zero a buffer
#95Re: How to zero a buffer
#96 static void secure_memset(void *, int, size_t) __attribute__((weakref("memset")));Re: How to zero a buffer
#97The article the completely obvious: /* implemented in another translation unit */ void zero_for_sure(void *data, size_t size); void func(void) { char securedata[42]; /* ... */ zero_for_sure(securedata, sizeof securedata); } The key here is that our zero_for_sure is an external function in a separately translated file. In the absence of a stunningly advanced global optimization that peeks into other previously compile…
From the article, "Some people will try this with secure_memzero in a separate C file. This will trick yet more compilers, but no guarantees — with link-time optimization the compiler may still discover your treachery." https://gcc.gnu.org/wiki/LinkTimeOptimization http://llvm.org/docs/LinkTimeOptimization.html
2. You bring this on yourself; it's not enabled by default by ordinary optimization options like -O2 or -O3. You have to ask for it, and so you must know what you're doing.
3. Under gcc, it looks like only those object files compiled with -flto are prepared for this optimization. You can arrange through your makefile or whatever not to apply -flto to sensitive modules that cannot be inlined or optimized away into other translation units. Those object files won't then contain the GIMPLE bytecode and whatnot needed to be able to peer into their internals at link time.
4. I don't think the dynamic linker in libc (ld.so) does this optimization, so putting code into shared libs may be another good way to hide it.
So, basically, the external function approach is still a very good tool for defeating unwanted inlining and dead code elimination, provided you don't stupidly use some advanced features that bend the standard translation model of the C language. In security-critical code, to boot. External functions are expressed using the standard language; the approach will work under pretty much any compiler.
Re: How to zero a buffer
#98Earlier quoted context omitted.
I'm gonna go ahead and say it: Perhaps in retrospect C is an inappropriate choice of language for these kinds of applications. This "Performance at all costs, including safety and predictability" thing may be appropriate in video games, but for security-critical applications that philosophy is downright negligent.
I'm not aware of any language that would be better. Most languages don't even let you touch memory to try to zero it.
Re: How to zero a buffer
#99Earlier quoted context omitted.
Perhaps in retrospect this was an inappropriate choice of definition, at least for cryptographic operations.
I'm gonna go ahead and say it: Perhaps in retrospect C is an inappropriate choice of language for these kinds of applications. This "Performance at all costs, including safety and predictability" thing may be appropriate in video games, but for security-critical applications that philosophy is downright negligent.
Re: How to zero a buffer
#100Earlier quoted context omitted.
It's because memset is a standard function and has a defined standard way of acting, with the most important part being that it doesn't produce any side-effects. It's also worth noting that accessing memory that's no longer in the current scope is undefined-behavior, so the compiler can assume it doesn't happen. Thus the memset has absolutely zero effect on the actual program and isn't necessary. In general this isn'…
What if one made some trivial use of the block of memory after having performed the memset, say something like this: void dosomethingsensitive(void) { uint8_t key[32]; ... /* Zero sensitive information. */ memset((volatile void *)key, 0, sizeof(key)); key[0] = key[1] + 1; } Would that thwart the optimizer, or would it also see through that usage and eliminate it as well?
void
dosomethingsensitive(void)
{
uint8_t key[32];
/* ... */
int i;
for (i = 0; i
Assuming the optimizer is sufficiently smart, then it'll remove that 'for' and it'll remove the addition after it in the same fashion.