From: Nikos Mavrogiannopoulos Date: Sun, 27 Jan 2013 18:19:13 +0000 (+0100) Subject: updated test X-Git-Tag: gnutls_3_1_7~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6432335d830ad5226eb02254d25d9734e09085a;p=thirdparty%2Fgnutls.git updated test --- diff --git a/tests/suite/mini-record-timing.c b/tests/suite/mini-record-timing.c index 6363ff226d..dcfe69abe0 100644 --- a/tests/suite/mini-record-timing.c +++ b/tests/suite/mini-record-timing.c @@ -65,7 +65,7 @@ client_log_func (int level, const char *str) } #endif -static void terminate(void); +#undef REHANDSHAKE /* This program tests the robustness of record * decoding. @@ -107,28 +107,31 @@ const gnutls_datum_t server_key = { server_key_pem, /* A very basic TLS client, with anonymous authentication. */ -#define MAX_BUF 1024 -#define MAX_PER_POINT (16*1024) -#define MAX_MEASUREMENTS (MAX_PER_POINT*(sizeof(points)/sizeof(points[0]))) +#define MAX_PER_POINT (684*1024) +#define MAX_MEASUREMENTS(np) (MAX_PER_POINT*(np)) +#define MAX_BUF 1024 struct point_st { unsigned char byte1; unsigned char byte2; unsigned midx; - unsigned long measurements[MAX_PER_POINT]; + unsigned long *measurements; + unsigned long *smeasurements; }; -static struct point_st points[] = { - { 0, 0, 0 }, -// { 1, 1, 0 }, -// { 14, 14, 0 }, - { 253, 253, 0 }, +struct test_st { + struct point_st* points; + unsigned int npoints; + const char* desc; + const char* file; + const char* name; + unsigned text_size; }; -struct point_st *prev_point_ptr = &points[0]; +struct point_st *prev_point_ptr = NULL; unsigned int point_idx = 0; - +static gnutls_session_t cli_session = NULL; static ssize_t push(gnutls_transport_ptr_t tr, const void *_data, size_t len) @@ -143,27 +146,32 @@ push_crippled (gnutls_transport_ptr_t tr, const void *_data, size_t len) { int fd = (long int)tr; unsigned char* data = (void*)_data; -struct point_st * p = &points[point_idx]; +struct point_st * p; +unsigned p_size; +struct test_st * test = gnutls_session_get_ptr(cli_session); + + p = &test->points[point_idx]; + p_size = test->npoints; memcpy(&data[len-32], data+5, 32); -//fprintf(stderr, "sending: %d.%d: %d\n", (unsigned)p->byte1, (unsigned)p->byte2, (int)len); +/*fprintf(stderr, "sending: %d: %d\n", (unsigned)p->byte1, (int)len);*/ data[len-17] ^= p->byte1; data[len-18] ^= p->byte2; prev_point_ptr = p; point_idx++; - if (point_idx >= (sizeof(points)/sizeof(points[0]))) + if (point_idx >= p_size) point_idx = 0; return send(fd, data, len, 0); } -static unsigned long timespec_sub_us(struct timespec *a, struct timespec *b) +static unsigned long timespec_sub_ns(struct timespec *a, struct timespec *b) { - return (a->tv_sec*1000*1000 + a->tv_nsec/1000 - (b->tv_sec *1000*1000 + - b->tv_nsec/1000)); + return (a->tv_sec*1000*1000*1000 + a->tv_nsec - (b->tv_sec*1000*1000*1000 + + b->tv_nsec)); } static @@ -171,11 +179,13 @@ double calc_avg(unsigned long *diffs, unsigned int diffs_size) { double avg = 0; unsigned int i; +unsigned int start = diffs_size/20; +unsigned int stop = diffs_size-diffs_size/20; - for(i=0;inpoints) && ret > 0) { gettime(&stop); - measurements[taken] = timespec_sub_us(&stop, &start); + taken++; + measurement = timespec_sub_ns(&stop, &start); + prev_point_ptr->measurements[prev_point_ptr->midx] = measurement; - if (min > measurements[taken] || min == 0) - min = measurements[taken]; - if (max < measurements[taken]) - max = measurements[taken]; +/*fprintf(stderr, "(%u,%u): %lu\n", (unsigned) prev_point_ptr->byte1, + (unsigned) prev_point_ptr->byte2, measurements[taken]);*/ + memcpy(&measurement, buffer, sizeof(measurement)); + prev_point_ptr->smeasurements[prev_point_ptr->midx] = measurement; + prev_point_ptr->midx++; -//fprintf(stderr, "(%u,%u): %lu\n", (unsigned) prev_point_ptr->byte1, -// (unsigned) prev_point_ptr->byte2, measurements[taken]); - prev_point_ptr->measurements[prev_point_ptr->midx++] = measurements[taken]; - taken++; + /* read server's measurement */ +#ifdef REHANDSHAKE gnutls_deinit(session); - +#endif goto restart; } #ifndef TLS_RECV @@ -343,38 +383,48 @@ restart: gnutls_bye (session, GNUTLS_SHUT_WR); { - double avg1, avg2, var, med; + double avg2, var, med, savg, smed; unsigned i; + FILE* fp = NULL; - printf("Taken %u measurements\n", taken); - avg1 = calc_avg(measurements, taken); - med = calc_median(measurements, taken); - - var = calc_var(measurements, taken, avg1); + if (test->file) + fp = fopen(test->file, "w"); - printf("Average processing time: %.3f microsec, Median: %.3f Variance: %.3f\n", avg1, med, var); - printf("(Min,Max)=(%lu,%lu)\n\n", min, max); + if (fp) /* point, avg, median */ + fprintf(fp, "Delta,TimeAvg,TimeMedian,ServerAvg,ServerMedian\n"); - for (i=0;inpoints;i++) { - avg2 = calc_avg( points[i].measurements, points[i].midx); - var = calc_var(points[i].measurements, points[i].midx, avg2); - med = calc_median(points[i].measurements, points[i].midx); - printf("(%u,%u) Avg: %.3f microsec, Median: %.3f, Variance: %.3f\n", (unsigned)points[i].byte2, (unsigned)points[i].byte1, - avg2, med, var); - if (i > 0) - { - printf("Avg diff (%u,%u)-(%u,%u)=%.3f\n", - (unsigned)points[0].byte2, (unsigned)points[0].byte1, - (unsigned)points[i].byte2, (unsigned)points[i].byte1, - avg1-avg2); - - } - else - avg1 = avg2; + qsort( test->points[i].measurements, test->points[i].midx, + sizeof(test->points[i].measurements[0]), compar); + + qsort( test->points[i].smeasurements, test->points[i].midx, + sizeof(test->points[i].smeasurements[0]), compar); + + avg2 = calc_avg( test->points[i].measurements, test->points[i].midx); + /*var = calc_var( test->points[i].measurements, test->points[i].midx, avg2);*/ + med = calc_median( test->points[i].measurements, test->points[i].midx); + + savg = calc_avg( test->points[i].smeasurements, test->points[i].midx); + /*var = calc_var( test->points[i].measurements, test->points[i].midx, avg2);*/ + smed = calc_median( test->points[i].smeasurements, test->points[i].midx); + /*min = calc_min( test->points[i].measurements, test->points[i].midx);*/ + + if (fp) /* point, avg, median */ + fprintf(fp, "%u,%.2lf,%.2lf,%.2lf,%.2lf\n", (unsigned)test->points[i].byte1, + avg2,med,savg, smed); + + /*printf("(%u) Avg: %.3f nanosec, Median: %.3f, Variance: %.3f\n", (unsigned)test->points[i].byte1, + avg2, med, var);*/ } + + if (fp) + fclose(fp); } + if (test->desc) + fprintf(stderr, "Description: %s\n", test->desc); + close (fd); gnutls_deinit (session); @@ -385,14 +435,6 @@ restart: } -/* These are global */ -pid_t child; - -static void terminate(void) -{ - kill(child, SIGTERM); - exit(1); -} static void server (int fd, const char* prio) @@ -402,6 +444,8 @@ char buffer[MAX_BUF + 1]; gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; const char* err; +struct timespec start, stop; +static unsigned long measurement; setpriority(PRIO_PROCESS, getpid(), -15); @@ -421,18 +465,20 @@ const char* err; if (ret < 0) { fprintf(stderr, "Could not set certificate\n"); - terminate(); + return; } +#ifdef REHANDSHAKE restart: +#endif gnutls_init (&session, GNUTLS_SERVER); /* avoid calling all the priority functions, since the defaults * are adequate. */ - if (gnutls_priority_set_direct (session, prio, &err) < 0) { - fprintf(stderr, "Error in %s\n", err); - terminate(); + if ((ret=gnutls_priority_set_direct (session, prio, &err)) < 0) { + fprintf(stderr, "Error in priority string %s: %s\n", gnutls_strerror(ret), err); + return; } gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred); @@ -451,26 +497,41 @@ restart: if (ret != GNUTLS_E_UNEXPECTED_PACKET_LENGTH) #endif { - close (fd); - gnutls_deinit (session); fprintf( stderr, "server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); - terminate(); } goto finish; } +#ifndef REHANDSHAKE +restart: +#endif + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); + do { ret = gnutls_record_recv (session, buffer, sizeof (buffer)); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); - if (ret < 0) + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop); + + if (ret == GNUTLS_E_DECRYPTION_FAILED) { + gnutls_session_force_valid(session); + measurement = timespec_sub_ns(&stop, &start); do { - ret = gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_RECORD_MAC); + ret = gnutls_record_send(session, &measurement, sizeof(measurement)); + /* GNUTLS_AL_FATAL, GNUTLS_A_BAD_RECORD_MAC); */ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + +#ifdef REHANDSHAKE gnutls_deinit(session); - goto restart; +#endif + if (ret >= 0) + goto restart; } + else if (ret < 0) + fprintf(stderr, "err: %s\n", gnutls_strerror(ret)); + /* do not wait for the peer to close the connection. */ @@ -483,13 +544,13 @@ finish: gnutls_certificate_free_credentials (x509_cred); gnutls_global_deinit (); - } -static void start (const char* prio, unsigned int text_size) +static void start (const char* prio, unsigned int text_size, struct test_st *p) { int fd[2]; int ret; + pid_t child; ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); if (ret < 0) @@ -506,17 +567,17 @@ static void start (const char* prio, unsigned int text_size) exit(1); } - if (child) + if (child != 0) { /* parent */ close(fd[1]); server (fd[0], prio); kill(child, SIGTERM); } - else + else if (child == 0) { close(fd[0]); - client (fd[1], prio, text_size); + client (fd[1], prio, text_size, p); exit(0); } } @@ -532,24 +593,214 @@ int status; fprintf(stderr, "Child died with sigsegv\n"); else fprintf(stderr, "Child died with status %d\n", WEXITSTATUS(status)); - terminate(); } return; } +static struct point_st all_points[256]; +static struct point_st all_points_one[256]; + + +#define NPOINTS(points) (sizeof(points)/sizeof(points[0])) + +/* Test that outputs a graph of the timings + * when manipulating the last record byte (pad) + * for AES-SHA1. + */ +static struct test_st test_sha1 = { + .points = all_points, + .npoints = NPOINTS(all_points), + .text_size = 18*16, + .name = "sha1", + .file = "out-sha1.txt", + .desc = NULL +}; + +/* Test that outputs a graph of the timings + * when manipulating the last record byte (pad) + * for AES-SHA256. + */ +static struct test_st test_sha256 = { + .points = all_points, + .npoints = NPOINTS(all_points), + .text_size = 17*16, + .name = "sha256", + .file = "out-sha256.txt", + .desc = NULL +}; + +/* Test that outputs a graph of the timings + * when manipulating the last record byte (pad) + * for AES-SHA1, on a short message. + */ +static struct test_st test_sha1_short = { + .points = all_points, + .npoints = NPOINTS(all_points), + .text_size = 16*2, + .name = "sha1-short", + .file = "out-sha1-short.txt", + .desc = NULL +}; + +/* Test that outputs a graph of the timings + * when manipulating the last record byte (pad) + * for AES-SHA256. + */ +static struct test_st test_sha256_short = { + .points = all_points, + .npoints = NPOINTS(all_points), + .text_size = 16*2, + .name = "sha256-short", + .file = "out-sha256-short.txt", + .desc = NULL +}; + +/* Test that outputs a graph of the timings + * when manipulating the last record byte (pad) + * for AES-SHA1, on a short message and + * the byte before the last is set to one. + * (i.e. we want to see whether the padding + * [1,1] shows up in the measurements) + */ +static struct test_st test_sha1_one = { + .points = all_points_one, + .npoints = NPOINTS(all_points_one), + .text_size = 16*2, + .name = "sha1-one", + .file = "out-sha1-one.txt", + .desc = NULL +}; + int main(int argc, char** argv) { +unsigned int i; +struct test_st* test; +const char* hash; +char prio[512]; + signal(SIGCHLD, ch_handler); + signal(SIGPIPE, SIG_IGN); - printf("\nAES-SHA1 (GnuTLS attack)\n"); - start("NONE:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0", 18*16); -// start("PERFORMANCE:-CIPHER-ALL:+AES-128-CBC:-MAC-ALL:+SHA1:%COMPAT", 18*16); + if (argc > 1) + { + if (strcmp(argv[1], "sha1")== 0) + { + test = &test_sha1; + hash = "SHA1"; + } + else if (strncmp(argv[1], "sha2", 4)== 0) + { + test = &test_sha256; + hash = "SHA256"; + } + else if (strcmp(argv[1], "sha1-short")== 0) + { + test = &test_sha1_short; + hash = "SHA1"; + } + else if (strcmp(argv[1], "sha256-short")== 0) + { + test = &test_sha256_short; + hash = "SHA256"; + } + else if (strcmp(argv[1], "sha1-one")== 0) + { + test = &test_sha1_one; + hash = "SHA1"; + } + else + { + fprintf(stderr, "Unknown test: %s\n", argv[1]); + exit(1); + } + } + else + { + fprintf(stderr, "Please specify the test, sha1, sha1-one, sha256, sha1-short, sha256-short\n"); + exit(1); + } -// printf("\nAES-SHA1 (full plaintext recovery)\n"); -// start("PERFORMANCE:-CIPHER-ALL:+AES-128-CBC:-MAC-ALL:+SHA1:%COMPAT", 2*16); + memset(&all_points, 0, sizeof(all_points)); + for (i=0;i<256;i++) + { + all_points[i].byte1 = i; + all_points[i].measurements = malloc(MAX_PER_POINT*sizeof(all_points[i].measurements[0])); + all_points[i].smeasurements = malloc(MAX_PER_POINT*sizeof(all_points[i].measurements[0])); + } + + memset(&all_points_one, 0, sizeof(all_points_one)); + for (i=0;i<256;i++) + { + all_points_one[i].byte1 = i; + all_points_one[i].byte2 = 1; + all_points_one[i].measurements = all_points[i].measurements; + all_points_one[i].smeasurements = all_points[i].smeasurements; + } + -// printf("\nAES-SHA256\n"); -// start("PERFORMANCE:-CIPHER-ALL:+AES-128-CBC:-MAC-ALL:+SHA256:%COMPAT"); + remove(test->file); + snprintf(prio, sizeof(prio), "NONE:+COMP-NULL:+AES-128-CBC:+%s:+RSA:%%COMPAT:+VERS-TLS1.2:+VERS-TLS1.1", hash); + + printf("\nAES-%s (calculating different padding timings)\n", hash); + start(prio, test->text_size, test); + + signal(SIGCHLD, SIG_IGN); + +#ifdef PDF + snprintf(prio, sizeof(prio), + "R -e 'pdf(file=\"%s-timings-avg.pdf\");z=read.csv(\"%s\");" + "plot(z$Delta,z$TimeAvg,xlab=\"Delta\",ylab=\"Average timings (ns)\");" + "dev.off();'" + test->name, test->file); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'pdf(file=\"%s-timings-med.pdf\");z=read.csv(\"%s\");" + "plot(z$Delta,z$TimeMedian,xlab=\"Delta\",ylab=\"Median timings (ns)\");" + "dev.off();'"; + test->name, test->file); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'pdf(file=\"%s-server-timings-avg.pdf\");z=read.csv(\"%s\");" + "plot(z$Delta,z$ServerAvg,xlab=\"Delta\",ylab=\"Average timings (ns)\");" + "dev.off();'" + test->name, test->file); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'pdf(file=\"%s-server-timings-med.pdf\");z=read.csv(\"%s\");" + "plot(z$Delta,z$ServerMedian,xlab=\"Delta\",ylab=\"Median timings (ns)\");" + "dev.off();'"; + test->name, test->file); + system(prio); +#else + snprintf(prio, sizeof(prio), + "R -e 'z=read.csv(\"%s\");png(filename = \"%s-timings-avg.png\",width=1024,height=1024,units=\"px\"," + "bg=\"white\");plot(z$Delta,z$TimeAvg,xlab=\"Delta\",ylab=\"Average timings (ns)\");dev.off();'", + test->file, test->name); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'z=read.csv(\"%s\");" + "png(filename = \"%s-timings-med.png\",width=1024,height=1024,units=\"px\"," + "bg=\"white\");plot(z$Delta,z$TimeMedian,xlab=\"Delta\",ylab=\"Median timings (ns)\");dev.off();'", + test->file, test->name); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'z=read.csv(\"%s\");png(filename = \"%s-server-timings-avg.png\",width=1024,height=1024,units=\"px\"," + "bg=\"white\");plot(z$Delta,z$ServerAvg,xlab=\"Delta\",ylab=\"Average timings (ns)\");dev.off();'", + test->file, test->name); + system(prio); + + snprintf(prio, sizeof(prio), + "R -e 'z=read.csv(\"%s\");" + "png(filename = \"%s-server-timings-med.png\",width=1024,height=1024,units=\"px\"," + "bg=\"white\");plot(z$Delta,z$ServerMedian,xlab=\"Delta\",ylab=\"Median timings (ns)\");dev.off();'", + test->file, test->name); + system(prio); +#endif } #endif /* _WIN32 */