From 575817c645d1589a1e1c9303b6d4c1de52808413 Mon Sep 17 00:00:00 2001 From: Daniel Gruss Date: Tue, 12 May 2015 11:45:53 +0200 Subject: [PATCH] add calibration utility --- .gitignore | 6 +++ README.md | 24 ++++++++++- cacheutils.h | 56 ++++++++++++++++++++++++++ calibration/Makefile | 3 ++ calibration/calibration.c | 83 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 cacheutils.h create mode 100644 calibration/Makefile create mode 100644 calibration/calibration.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e735e76 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +spy +victim +*~ +core +calibration diff --git a/README.md b/README.md index 805d155..d2c0379 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,22 @@ -# cache_template_attacks -This repository contains several tools to perform Cache Template Attacks +# Cache Template Attacks +This repository contains several tools to perform Cache Template Attacks. + +Cache Template Attacks are a new generic attack technique, allowing to profile and exploit cache-based information leakage of any program automatically, without prior knowledge of specific software versions or even specific system information. + +The underlying cache attack used in this repository is Flush+Reload as presented by Yarom and Falkner in "[FLUSH+RELOAD: a High Resolution, Low Noise, L3 Cache Side-Channel Attack](https://eprint.iacr.org/2013/448.pdf)" (2014). + +# Getting started: Calibration +Before starting the Cache Template Attack you have to find the cache hit/miss threshold of your system. + +Use the calibration tool for this purpose: +``` +cd calibration +make +./calibration +``` +This program should print a histogram for cache hits and cache misses. Based on the histogram it suggests a suitable threshold value (this value is also returned by the program). + +# Getting started: Keypresses +It is helpful to start with well observable events like key strokes and an application which is known to process such events (for instance an editor). + + diff --git a/cacheutils.h b/cacheutils.h new file mode 100644 index 0000000..09496a0 --- /dev/null +++ b/cacheutils.h @@ -0,0 +1,56 @@ +#ifndef CACHEUTILS_H +#define CACHEUTILS_H + +#ifndef HIDEMINMAX +#define MAX(X,Y) (((X) > (Y)) ? (X) : (Y)) +#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y)) +#endif + +uint64_t rdtsc_nofence() { + uint64_t a, d; + asm volatile ("rdtsc" : "=a" (a), "=d" (d)); + a = (d<<32) | a; + return a; +} + +uint64_t rdtsc() { + uint64_t a, d; + asm volatile ("mfence"); + asm volatile ("rdtsc" : "=a" (a), "=d" (d)); + a = (d<<32) | a; + asm volatile ("mfence"); + return a; +} + +void maccess(void* p) +{ + asm volatile ("movq (%0), %%rax\n" + : + : "c" (p) + : "rax"); +} + +void flush(void* p) { + asm volatile ("clflush 0(%0)\n" + : + : "c" (p) + : "rax"); +} + +void prefetch(void* p) +{ + asm volatile ("prefetcht1 %0" : : "m" (p)); +} + +void longnop() +{ + asm volatile ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" + "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); +} +#endif diff --git a/calibration/Makefile b/calibration/Makefile new file mode 100644 index 0000000..204a133 --- /dev/null +++ b/calibration/Makefile @@ -0,0 +1,3 @@ +all: calibration +calibration: calibration.c ../cacheutils.h + gcc -std=gnu11 -O2 -o $@ $@.c diff --git a/calibration/calibration.c b/calibration/calibration.c new file mode 100644 index 0000000..a7c8a78 --- /dev/null +++ b/calibration/calibration.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include "../cacheutils.h" + +size_t array[5*1024]; + +size_t hit_histogram[80]; +size_t miss_histogram[80]; + +size_t onlyreload(void* addr) +{ + size_t time = rdtsc(); + maccess(addr); + size_t delta = rdtsc() - time; + return delta; +} + +size_t flushandreload(void* addr) +{ + size_t time = rdtsc(); + maccess(addr); + size_t delta = rdtsc() - time; + flush(addr); + return delta; +} + +int main(int argc, char** argv) +{ + memset(array,-1,5*1024*sizeof(size_t)); + maccess(array + 2*1024); + sched_yield(); + for (int i = 0; i < 4*1024*1024; ++i) + { + size_t d = onlyreload(array+2*1024); + hit_histogram[MIN(79,d/5)]++; + sched_yield(); + } + flush(array+1024); + for (int i = 0; i < 4*1024*1024; ++i) + { + size_t d = flushandreload(array+2*1024); + miss_histogram[MIN(79,d/5)]++; + sched_yield(); + } + printf(".\n"); + size_t hit_max = 0; + size_t hit_max_i = 0; + size_t miss_min_i = 0; + for (int i = 0; i < 80; ++i) + { + printf("%3d: %10zu %10zu\n",i*5,hit_histogram[i],miss_histogram[i]); + if (hit_max < hit_histogram[i]) + { + hit_max = hit_histogram[i]; + hit_max_i = i; + } + if (miss_histogram[i] > 3 && miss_min_i == 0) + miss_min_i = i; + } + if (miss_min_i > hit_max_i+4) + printf("Flush+Reload possible!\n"); + else if (miss_min_i > hit_max_i+2) + printf("Flush+Reload probably possible!\n"); + else if (miss_min_i < hit_max_i+2) + printf("Flush+Reload maybe not possible!\n"); + else + printf("Flush+Reload not possible!\n"); + size_t min = -1UL; + size_t min_i = 0; + for (int i = hit_max_i; i < miss_min_i; ++i) + { + if (min > (hit_histogram[i] + miss_histogram[i])) + { + min = hit_histogram[i] + miss_histogram[i]; + min_i = i; + } + } + printf("The lower the threshold, the lower the number of false positives.\n"); + printf("Suggested cache hit/miss threshold: %zu\n",min_i * 5); + return min_i * 5; +}