Live data from Hacker News

Zeroing buffers is insufficient

daemonology.net

61–70 of 134 posts

Re: Zeroing buffers is insufficient

#61
> For encryption operations these aren't catastrophic things to leak — the final block of output is ciphertext, and the final AES round key, while theoretically dangerous, is not enough on its own to permit an attack on AES

This is incorrect. The AES key schedule is bijective, which makes recovering the last round key as dangerous as recovering the first.

Re: Zeroing buffers is insufficient

#62
post #28
post #14

Earlier quoted context omitted.

Another good reason to write crypto in assembly is to ensure that the implementation is not susceptible to timing attacks. If your code has different code paths that take different amounts of clock time attackers can use that. This can be difficult to achieve in a high level language.

Using assembly won't preclude timing attacks vulnerability, esp on x64. Nowadays beating even the C compiler performance wise is exceeding difficult with hand written assembly.

The point isn't to be faster, it is to be consistent.

Re: Zeroing buffers is insufficient

#63
post #59

Even if the proposed feature is added to C and implemented, there is still the (practical) problem of OS-level task switching: when your process is interrupted by the scheduler, its registers are dumped into memory, from where they might even go into swap space. It would be consequential (but utterly impractical) to add another C-level primitive to prevent OS-level task suspension during critical code paths. Good luc…

The obvious fix is to address "might go into swap space". However, the real problem is that the process can be interrupted at any time and examined, not that the registers might go to swap.

If someone has the root privs to peek at your memory, they can also stop your process at any time and examine all the registers, whether they were swapped out to disk or not.

Moving the crypto code into the kernel and running with disabled interrupts doesn't help because the attacker is already assumed to have super-user privileges (they can peek at arbitrary RAM, after all). There are also non-maskable interrupts.

You basically cannot hide the machine state from someone who controls the machine: not without splitting the machine itself into additional privilege levels, such that there is a security level that is not accessible even to the OS kernel. The sensitive crypto routines run in that level. The manufacturer of the SoC provides these as firmware, and the regular kernel has no visibility to the internals.

ARM has a security model that supports this.

There is also something even more paranoid called TrustZone: http://en.wikipedia.org/wiki/ARM_architecture#Security_exten...

Re: Zeroing buffers is insufficient

#64

Every time I read one of these posts about a clever "attack vector", how something can be gleaned from this special register, or a timing attack, somesuch, I remember about a theory that the sound of a dinosaurs scream can be extracted from the waves impact made on a rocks crystal structure. I googled pretty hard for real life example uses of a timing attack, and now using of stale data on the register, but couldn't…

A few examples:

"Remote Timing Attacks are Practical" https://crypto.stanford.edu/~dabo/papers/ssl-timing.pdf

"RSA Key Extraction via Low-Bandwidth Acoustic Cryptanalysis" http://www.tau.ac.il/~tromer/acoustic/

Re: Zeroing buffers is insufficient

#65
post #23

Earlier quoted context omitted.

That depends how much the compiler can optimize (away). If the next call is free(), it's quite trivial to skip the zeroing and just take the correct branch. I am still uncertain while people want to just 'zero' it. Filling random data (just one random() call) and then using inline PRNG, then summing the result, storing it globally in volatile would reliable 'zero' the data but it's quite CPU intense.

You still are not guaranteed to clear the buffer like that. for (int i=0; i Using loop fusion, the compiler can optimize this to: int sum=0; for (int i=0; i Which it can then optimize to: int sum=0; for (int i=0; i In fact, as the article points out, the compiler can legally transform: reallyZeroBuffer(sensitiveBuffer); into pointlesslyCopy(sensitiveBuffer); reallyZeroBuffer(sensitiveBuffer);

not like that: Not exactly like that: I didn't mean simple that way, more like hash alike. The 1st example is not optimal but shows the idea.

I disagree about "pointlessCopy". Of course it's permitted by the standard but it's not an optimization. Using such a broken compiler is beyond help.

------- volatileVar *= random(); for (int i=0;i

  for (int i=0; i

Re: Zeroing buffers is insufficient

#66
post #62
post #28

Earlier quoted context omitted.

Using assembly won't preclude timing attacks vulnerability, esp on x64. Nowadays beating even the C compiler performance wise is exceeding difficult with hand written assembly.

The point isn't to be faster, it is to be consistent.

That's what I mean actually getting it consistent is hard as the performance is really hard to predict and may change even with CPU stepping. Even then it requires very solid planning as well.

Re: Zeroing buffers is insufficient

#67
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 enough of the nonsense step to overwrite the registers.

Re: Zeroing buffers is insufficient

#68
post #67

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…

That's just a workaround though. It still does not invalidate the basic thrust "I can't write code to handle keys in C and be sure I have not left copies anywhere"

The proposal seems goods

Re: Zeroing buffers is insufficient

#69
post #67

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!

Post reply on HN