Hacker News new | ask | show | jobs
by tromp 466 days ago
The article details how current techniques for preventing timing attack are becoming ineffective for the following reasons:

> 1. Compilers are applying optimization techniques that are heuristically good for performance on general software, but happen to leak information through timing-based sidechannels when used on secret data. Since general-purpose CPUs and compilers are applied to a wide variety of tasks, compilers have no reason to stop doing such optimizations.

> 2. Constant-time coding techniques mostly aim at fooling the compiler, to prevent it from applying these optimizations. Since compilers keep getting smarter, theses techniques lose their efficiency.

> 3. Just-in-time (JIT) compilers have access to runtime data; they can, and will, use such information to perform extra optimizations that static compilers cannot do, and further destroy the developer’s attempt at achieving constant-time code.

> 4. JIT compilation is becoming pervasive and is now employed in various contexts, in particular inside CPUs. Such compilers can do the same optimizations as “external” JIT compilers, but are not publicly documented, and the output of their “machine” code translation cannot be inspected to detect deviations from constant-time execution.

> 5. Modern hardware and software stacks use a very layered structure, with each layer striving to hide its internal functioning details from upper layers. The socio-economic context which allowed such hardware to exist inherently relies on such abstraction (under the name of “industrial secrecy”). An effective constant-time coding process would require a model of computation with strong guarantees on timing-related characteristics, that would be maintained through all these layers, down to the semiconductors that implement the logic gates. This industry-wide vertical cooperation is unlikely to happen.

1 comments

Why is cooperation unlikely? AFAIK it’s not too hard to make a compiler support a function attribute that says “do not optimize this function at all”; I assume in most compilers the translation and optimization phases are mostly separate, and inter-procedural optimizations can treat them as externally-linked (untouchable). I’m less familiar with assembly. but couldn’t processors expose instructions to enable or disable their JIT?

I imagine it’s not easy* easy, because it requires every layer to cooperate, but if there’s demand I think it would be done.

IPv6 is in a similar situation where it requires widespread adoption, but I also suspect most people have issues with it and there isn’t much demand because NATs and whatever support for cellular networks has made it unnecessary.

> Why is cooperation unlikely? AFAIK it’s not too hard to make a compiler support a function attribute that says “do not optimize this function at all”

Compilers like Clang actually generate terrible code; it's expected that a sufficiently smart optimizer (of which LLVM is a member) will clean it up anyway, so Clang makes no attempt to generate good code. Rust is similar. For example, a simple for-loop's induction variable is stored/loaded to an alloca (ie stack) on every use, it isn't an SSA variable. So one of the first things in the optimization pipeline is to promote those to SSA registers/variables. Disabling that would cost a ton of perf just right there, nevermind the impact on instruction combining/value tracking/scalar evolution, and crypto is pretty perf sensitive after security.

BTW, Clang/LLVM already has such a function-level attribute, `optnone`, which was actually added to support LTO. But it's all or nothing; LLVM IR/Clang doesn't have the info needed to know what instructions are timing sensitive.

> it’s not too hard to make a compiler support a function attribute that says “do not optimize this function at all”

Note that memset_s() is an existing special case already. https://en.cppreference.com/w/c/string/byte/memset