benchmark.c

Go to the documentation of this file.
00001 /* benchmark.c -- Benchmarks how quickly the computer does SHA512 hashing
00002  *
00003  *  GPLv2 only - Copyright (C) 2009 - 2010
00004  *               David Sommerseth <dazo@users.sourceforge.net>
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; version 2
00009  *  of the License.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *
00020  */
00021 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <assert.h>
00036 #include <sys/time.h>
00037 
00038 #include <eurephia_nullsafe.h>
00039 #include <eurephia_context.h>
00040 
00041 #define ROUNDS_MIN 1000         
00042 #define ROUNDS_MAX 999999999    
00044 int pack_saltinfo(char *buf, int buflen, int rounds, int saltlen, const char *pwd);
00045 
00046 inline char *sha512_crypt_r(const char *key, const char *salt, size_t maxrounds_cfg, char *buffer, int buflen);
00047 
00048 int gen_randsaltstr(eurephiaCTX *ctx, char *saltstr, int len);
00049 
00056 void benchmark_hashing(int rounds) {
00057         char *buffer = NULL;
00058         char *pwdhash = NULL;
00059         static char randstr[34];
00060         static int rand_set = 0;
00061         char pwdsalt[64], saltstr[32];
00062 
00063         // Get random data for our salt
00064         if( rand_set == 0 ) {
00065                 memset(&randstr, 0, 34);
00066                 if( gen_randsaltstr(NULL, randstr, 32) == 0 ) {
00067                         fprintf(stderr, "Could not retrieve enough random data for hashing");
00068                         exit(19);
00069                 };
00070                 rand_set = 1;
00071         }
00072 
00073         // Prepare a salt package
00074         memset(&pwdsalt, 0, 64);
00075         memset(&saltstr, 0, 32);
00076         pack_saltinfo(saltstr, 30, rounds, 32, "benchmarkpassword");
00077         strncpy(pwdsalt, saltstr, strlen(saltstr));
00078         strncat(pwdsalt, randstr, 62 - strlen(saltstr));
00079         memset(&randstr, 0, 32);
00080 
00081         buffer = (char *) malloc_nullsafe(NULL, 1024);
00082         assert( buffer != NULL );
00083 
00084         pwdhash = sha512_crypt_r("benchmarkpassword", pwdsalt, ROUNDS_MAX, buffer, 1024);
00085 
00086         free_nullsafe(NULL, buffer);
00087 }
00088 
00089 
00099 int timeval_subtract (result, x, y)
00100      struct timeval *result, *x, *y;
00101 {
00102         /* Perform the carry for the later subtraction by updating y. */
00103         if (x->tv_usec < y->tv_usec) {
00104                 int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
00105                 y->tv_usec -= 1000000 * nsec;
00106                 y->tv_sec += nsec;
00107         }
00108         if (x->tv_usec - y->tv_usec > 1000000) {
00109                 int nsec = (y->tv_usec - x->tv_usec) / 1000000;
00110                 y->tv_usec += 1000000 * nsec;
00111                 y->tv_sec -= nsec;
00112         }
00113 
00114         /* Compute the time remaining to wait.
00115            tv_usec is certainly positive. */
00116         result->tv_sec = x->tv_sec - y->tv_sec;
00117         result->tv_usec = x->tv_usec - y->tv_usec;
00118 
00119         /* Return 1 if result is negative. */
00120         return x->tv_sec < y->tv_sec;
00121 }
00122 
00123 
00131 struct timeval *do_benchmark(int rounds) {
00132         struct timeval start, end, *timediff = NULL;
00133 
00134         timediff = (struct timeval *) malloc_nullsafe(NULL, sizeof(struct timeval)+2);
00135         assert( timediff != NULL );
00136 
00137         gettimeofday(&start, NULL);
00138         benchmark_hashing(rounds);
00139         gettimeofday(&end, NULL);
00140         timeval_subtract(timediff, &end, &start);
00141 
00142         return timediff;
00143 }
00144 
00159 int benchmark(int *min, int *max, int thr_min, int thr_max) {
00160         int i = 0, success = 0;
00161         struct timeval *time = NULL, min_time, max_time ;
00162 
00163         printf("Benchmarking ");
00164         *min = 1000;
00165         *max = 5000;
00166         memset(&min_time, 0, sizeof(struct timeval));
00167         memset(&max_time, 0, sizeof(struct timeval));
00168 
00169         for( i = 1000; i < 100000000; i += 1000 ) {
00170                 printf(".");
00171                 fflush(stdout);
00172                 time = do_benchmark(i);
00173                 // printf("%i rounds: %ld sec %ld ms\n", i, time->tv_sec, time->tv_usec);
00174                 if( time->tv_usec > (thr_max * 1000) ) {
00175                         success = 1;
00176                         free(time);
00177                         break;
00178                 }
00179                 if( (*min == 1000) && (time->tv_usec > (thr_min * 1000)) ) {
00180                         *min = i;
00181                         min_time.tv_usec = time->tv_usec;
00182                 }
00183                 if( (time->tv_usec < (thr_max * 1000)) ) {
00184                         *max = i;
00185                         max_time.tv_usec = time->tv_usec;
00186                 }
00187                 free(time);
00188         }
00189         printf(" Done\n");
00190         if( success == 1 ) {
00191                 printf("Suggested minimum rounds: %i (takes %ldms)\n", *min, min_time.tv_usec/1000);
00192                 printf("Suggested maximum rounds: %i (takes %ldms)\n", *max, max_time.tv_usec/1000);
00193         } else {
00194                 *min = 0;
00195                 *max = 0;
00196                 printf("Could not find any good times, as your computer is too fast for this test.\n");
00197         }
00198         return success;
00199 }
00200 
00201 #if 0
00202 int main() {
00203         int min, max;
00204 
00205         benchmark(&min, &max, 90, 220);
00206         printf("---> %i - %i\n", min, max);
00207         return 0;
00208 }
00209 #endif
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines