CacheSC is a library for L1 and L2 cache side-channel attacks. It implements Prime+Probe
attacks on contemporary hardware. It features:
- Simple interface to abstract low-level complications of performing cache attacks, including precise time measurements in the presence of out-of-order execution.
- Privileged and unprivileged methods to attack physically indexed caches (such as L2 on many devices).
- Handy plotting scripts to visualise side-channel oberservations.
This code was developed and tested on a Dell Latitude E6430 with Ivy Bridge processors (Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz) running Ubuntu 18.04. Since cache side-channels are highly architecture-dependent, the library might require some adaptions for other hardware. However, we expect the basic concepts and underlying problems to be present on other architectures due to its fundamental trade-off with performance.
This library was developed in the context of a student project at the LASEC departement of EPFL. The rationale behind the design of this library, in-depth discussion of the demo applications and cache side-channels in general can be found in our report.
Abstract:
Microarchitectural side-channels exploit observations on the internal state of (cryptographic) algorithms obtained by measuring side-effects such as contention on a shared resource. In this project, we focus on cache side-channels, which were among the first practically exploited information leakages. We provide an overview of the extensive research on cache timing attacks and a more in-depth analysis of the wide-spread Prime+Probe technique. We find that due to the empirical approach on cache side-channels, the results are often tailored to specific software and hardware versions. However, we consider it beneficial to revisit cache attacks and adapt them to new environments as the side-channels’ underlying root causes are likely to persist over time and architectures because of their fundamental relation to performance. Therefore, we revisit a classical chosen-plaintext attack, targeting OpenSSL’s AES-CBC implementation, and apply it on contemporary hardware. We explain the challenges of implementing this attack in the presence of out-of-order execution, dynamic frequency scaling, hardware prefetching, line-fill buffers and other optimisations. Furthermore, we especially highlight the importance of an appropriate data structure to cope with the previous challenges while minimising cache side-effects of the measurement itself.
Moreover, we contribute CacheSC, a library that implements different variants of Prime+Probe targeting not only on virtually indexed caches but also including two methods to attack physically indexed caches. The first attack requires superuser privileges and translates virtual to physical addresses in user space by parsing the pagemap file. The second approach uses collision detection to build the cache attack data structure without requiring special privileges. Finally, we use CacheSC to conduct an initial review of the AES key scheduling algorithm as well as Argon2 and provide starting points for novel applications of cache side-channels.
I would like to thank Muhammed Fatih Balli for supervising this project and many productive discussions and good inputs. Moreover, I would like to thank Prof. Serge Vaudenay for making this project possible.
Basic utilities required for compiling the library and using the Python plotting scripts.
$ sudo apt-get install git build-essential gcc python3 python3-pip
Clone the repository:
$ git clone git@github.com:Miro-H/CacheSC.git
Before you compile the library, configure your device specific hardware parameters. It is essential for the cache attacks that you enter the correct cache dimensions (and other constants) in ./src/device_conf.h
. Useful commands to gather this information are x86info -c
, cat /proc/cpuinfo
, lscpu
, and getconf -a | grep CACHE
.
Compile the library and demo code:
$ cd CacheSC
$ make
This will produce libcachesc.a
in ./lib
and the available header files in ./include
. Link this library in your C files as usual (see demo files). To use a custom installation path, run:
$ INST_PATH=/your/custom/installation/path make
In case you want to use the plotting scripts, you need to install the Python packages.
$ pip3 install -r install/pip_requirements.txt
In case new package updates cause problems, the last version of the packages with which the library was tested can be installed by using install/pip_requirements_exact.txt
.
The folder ./demo
contains some example uses of the CacheSC library.
In this scenario, we show case the library by measuring a single cache line access, i.e. the scenario is:
for #samples do
prime
access cache line
probe
Compile this demonstration attack by running the following command inside the ./demo
folder:
$ make single-eviction
Run the demonstration code and store its output in a log file:
$ ./demo/single-eviction 10000 > /tmp/attack.log
This performs 10000
Prime+Probe measurements.
Plot the results:
$ ./scripts/plot-log.py -o /tmp -v -t /tmp/attack.log
For many attacks, it is advantageous to normalize the measurements, e.g. to filter secret-independent cache accesses. The following commands run the same test with normalization and plots the normalized results:
$ cd ./demo
$ NORMALIZE=1 make rebuild
$ cd ..
$ ./demo/single-eviction 10000 > /tmp/attack.log
$ ./scripts/plot-log.py -o /tmp/cachesc -v -t -n /tmp/attack.log
This demo attack can also be run on physically indexed caches (such as L2). For this purpose, uncomment the following three macros in single-eviction.c
, and comment out the definitions for L1.
// Uncomment for L2 attack
#define TARGET_CACHE L2
#define MSRMTS_PER_SAMPLE L2_SETS
#define PRIME prime_rev
There is a priviliged and unprivileged version of this attack on physically indexed caches. The library will choose itself, based on the available privileges. The privileged version is significantly faster, building the data structure without privileges can require several minutes.
This attack uses CacheSC to implement the classic chosen-plaintext attack, similar to the one-round attack from Osvik, Shamir, and Tromer (presented in Cache Attacks and Countermeasures: the Case of AES), to recover half of any key byte of the AES-CBC encryption. However, instead of Evict+Time we use Prime+Probe for this attack. Our report provides an in-depth discussion of this attack.
Compile the attack by running the following in ./demo
:
$ OPENSSL_INCL=/path/to/openssl/include OPENSSL_LIB=/path/to/openssl/lib make openssl-aes-cbc
Where OPENSSL_INCL
and OPENSSL_LIB
point to your local OpenSSL installation. Specifying those environment variables is optional. Their defaults are /usr/local/include
respectively /usr/local/lib
.
Note that you have to ensure that the vulnerable AES-CBC implementation of OpenSSL is run, i.e. not hardware optimizations such as AES-NI
(OpenSSL checks on runtime, if AES-NI
is available and may use it, unless you deactivate this). We tested this attack on OpenSSL-0.9.8
(the original version used by Osvik et al.), compiled with the no-asm
flag.
It is again advisable to normalize the results, i.e. compile with the NORMALIZE=1
flag.
The expected plots (obtained as in the previous demo example) are:
This is no full attack. It rather provides an entry point for an asynchronous attack which builds on observing cache access patterns of passwords hashed with Argon2d. We argue in our report that precise cache side-channel observations on Argon2d could be used for more efficient password cracking, bypassing Argon's parameterizable number of passes through memory.
Compile the attack by running the following in ./demo
:
$ ARGON_INCL=/path/to/argon2/include ARGON_LIB=/path/to/argon2/lib make argon2d-attacker argon2d-victim
Where ARGON_INCL
and ARGON_LIB
point to the local installation of Argon2. Those variables are again optional and default to /usr/include
respectively /usr/lib/x86_64-linux-gnu
.
Start the victim and (privileged) attacker using the following commands:
$ sudo ./argon2d-attacker > /tmp/attacker.log &
$ sleep 1
$ ./argon2d-victim 10 > /tmp/victim.log
$ sudo pkill -SIGINT -f argon2d-attacker
The accuracy of those observations could be evaluated by patching Argon2d
(e.g. the index_alpha
function in opt.c
) to also print a timestamp and then observe how many blocks are processed between two scheduling periods of the attacker. We discuss the results of such a comparison in our report.
$ ./scripts/plot-log.py -h
usage: plot-log.py [-h] [-o OUTPUT_FOLDER] [--ylims YLIMS] [-n] [-t] [-v]
log_file
positional arguments:
log_file path to log file to parse
optional arguments:
-h, --help show this help message and exit
-o OUTPUT_FOLDER, --output_folder OUTPUT_FOLDER
path to folder for the produced plots
--ylims YLIMS fix y axis of plot, tuple (y_min, y_max)
-n, --normalize normalize samples using an additional data set with
uninfluenced data points
-t, --transpose transpose data set, i.e. average overthe i-th entries
of each sample
-v, --verbose print debug output