A blog about the development of a general-purpose solution for mitigating cold-boot attacks on Full-Disk-Encryption solutions.

Lack of cache control

Management of the cache contents isn't over once the cache has been "frozen": it is also important, that the data in the cache (the encryption key) isn't written back to memory. Unfortunately, the Intel architecture allows only very minimalistic cache control:
  • enable / disable cache (systemwide: CR0.CD, per memory-region: MTRR, per page: PAT)
  • flush cache (wbinvd)

That's it. There are no processor instructions for querying the status of the cache (the currently held RAM locations in the individual cache lines) or any other "advanced" cache management functions. Therefore, it is nearly impossible to verify that the encryption key is really only present in the CPU cache. With the frozen cache setup, it's pretty much guaranteed that the key will be present in the cache - but that doesn't say anything about whether that data hasn't been sync'ed to RAM. This happens (in the frozen cache setup) whenever the wbinvd instruction is executed; this instruction can be executed by any code running in ring 0 (kernel). Therefore, it is important to minimize the (kernel) code that runs on the CPU which holds the encryption key in its cache. This is why binding the other schedulable entities (at least all other kernel threads) onto other CPUs (if present) is important, too.

One way to minimize the impact of "unintentional" cache flushes (unintentional from our point of view) is to repeat the cache freezing procedure periodically in order to reverse the effects of "unintentional" cache flushes (wbinvd). Fortunately, there's at least a (theoretically) better solution for Linux: modify the function/macro that executes/wraps the invd/wbinvd instructions in the kernel to trigger the re-execution of the cache freezing (independent of how realistic the chances of integration of such a patch seem).

No comments:

Post a Comment