Doesn't actually seem true. OK, running the decrypt leaves the key and data in SSE registers that are rarely used where it might be looked up later by attackers. There isn't any portable way to explicitly clear the registers. Then why not just run the decrypt again with nonsense inputs when you are done to leave junk in there instead? Yes, inefficient, but a clear counter example. You could then work on just doing en…
> Then why not just run the decrypt again with nonsense inputs when you are done to leave junk in there instead? Because the compiler is perfectly within its rights to optimize that out!
Zeroing buffers is insufficient
91–100 of 134 posts
Re: Zeroing buffers is insufficient
#92Computer programs of all kinds are being executed on top of increasingly complicated abstractions. E.g., once upon a time, memory was memory; today it is an abstraction. The proposed attribute seems workable if you compile and execute a C program in the "normal" way. But what if, say, you compile C into asm.js?
Saying, "So don't do that" doesn't cut it. In not too many years I might compile my OS and run the result on some cloud instance sitting on top of who-knows-what abstraction written in who-knows-what language. Then someone downloads a carefully constructed security-related program and runs it on that OS. And this proposed ironclad security attribute becomes meaningless.
So I'm thinking we need to do better. But I don't know how that might happen.
Re: Zeroing buffers is insufficient
#93Earlier quoted context omitted.
> Is the compiler still allowed to optimize away the zeroing in this case? Yes, completely. In the snippet below, the compiler is allowed to eliminate all code after “leave secrets in array c”. { char c[2]; ... /* leave secrets in array c */ memset(c, 0, 2); c[0] = 0; c[1] = 0; memset(c, 0, 2); if (c[0] || c[1]) exit 1; } The compiler is also allowed to compile the last three instructions below as if they were “retur…
> In the snippet below, the compiler is allowed to eliminate all code after “leave secrets in array c” gcc 4.4.5 doesn't though (-O3), it still clears the stack once and performs the comparison. I believe these optimizations can be defeated by declaring a global volatile char fill = 0; and using that instead of 0 in memset().
Re: Zeroing buffers is insufficient
#94Earlier quoted context omitted.
Its about footprint. We certainly will run Linux on the Mill, but its work we don't have to put on the critical path. L4 is just a familiar lightweight OS, and we're keen to play with Mill-specific security features which are particularly applicable to microkernels too. When we do port Linux, I expect it to become much more microkernel like, as in why would you want your disk drivers to be able to read write video me…
> why would you want your disk drivers to be able to read write video memory etc? That is a much bigger issue than the CPU architecture, as it has more to do with how the peripheral hardware works (firmware, DMA, etc.), but I appreciate the effort.
Re: Zeroing buffers is insufficient
#95Earlier quoted context omitted.
> Then why not just run the decrypt again with nonsense inputs when you are done to leave junk in there instead? Because the compiler is perfectly within its rights to optimize that out!
Not if you write the junk output to volatile variable, right?
If you use a deterministic nonsense value, the compiler can turn the result of decrypt(nonsense) into a constant at compile time, and just directly output the constant to the volatile variable, without actually ever calling decrypt again at runtime. So it can turn this:
decrypt(real);
nonsense = ;
volatile junk = hash(decrypt(nonsense));
Into this: decrypt(real);
volatile junk = ;
But even if you nonsense is non-deterministic (although I question where you are getting the entropy - if you're using a syscall / random / etc your performance has potentially just gone out the window), the compiler is well within its rights to optimize the second junk decrypt of the nonsense input differently than the first (real) decrypt - in such a way that it does not overwrite everything left behind by the first decryption.(Same with encryption)
Re: Zeroing buffers is insufficient
#96Now, if your decryption hardware was an actual separate box, where the user inserts their keys via some mechanism and you can't run any software on it, but simply say "please decrypt this data with key X", then we'd be on to something. It could be just a small SoC which plugs into your USB port.
Or you could have a special crypto machine kept completely unconnected to anything, in a Faraday cage. You take the encrypted data, you enter your key in the machine, you enter the data and you copy the decrypted data back. No chance of keys leaking in any way.
Re: Zeroing buffers is insufficient
#97This article makes a good point, but I think the problem is even worse than he describes. Computer programs of all kinds are being executed on top of increasingly complicated abstractions. E.g., once upon a time, memory was memory; today it is an abstraction. The proposed attribute seems workable if you compile and execute a C program in the "normal" way. But what if, say, you compile C into asm.js? Saying, "So don't…
Re: Zeroing buffers is insufficient
#98Earlier quoted context omitted.
The briar patch of OpenSSL is more in the high level protocol code, and not the asm crypto (the perl obfuscation layer makes it fun, but isn't a major source of bugs). I would not want to write a robust asn.1 parser in assembly. Lots of other cruft works around the presence or absence of various #define values in header files. Rewriting in assembly is not going to solve the problem of deciding how big socklen_t is.
Mm, true: the long grass of the libcrypto part pales in comparison to the thorny nightmare that is the rest of it. Thank you to OpenBSD's LibReSSL for beginning to clear away the worst of the bramble (and uncovering the occasional juicy blackberry in the Valhalla rampage process). There's a crypto library, and then there's a protocol library. And TLS, to put it politely, has lots of hairy bits, and I hope and pray TL…
In short: imperfect buffer zeroing probably reduces risk enough that it drops below several other concerns.
Re: Zeroing buffers is insufficient
#99If I have enough control to the point where I can read your memory in some way, I can just use ptrace. Heck, I could attach a debugger. It seems ludicrous to want that level of protection out of a normal program running on Mac/Win/Linux. Now, if your decryption hardware was an actual separate box, where the user inserts their keys via some mechanism and you can't run any software on it, but simply say "please decrypt…
Re: Zeroing buffers is insufficient
#100If I have enough control to the point where I can read your memory in some way, I can just use ptrace. Heck, I could attach a debugger. It seems ludicrous to want that level of protection out of a normal program running on Mac/Win/Linux. Now, if your decryption hardware was an actual separate box, where the user inserts their keys via some mechanism and you can't run any software on it, but simply say "please decrypt…
What you're describing is called a smartcard, and readily available on the market. I keep my PGP key on one.