1/* 2 * Argon2 reference source code package - reference C implementations 3 * 4 * Copyright 2015 5 * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves 6 * 7 * You may use this work under the terms of a Creative Commons CC0 1.0 8 * License/Waiver or the Apache Public License 2.0, at your option. The terms of 9 * these licenses can be found at: 10 * 11 * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 12 * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * You should have received a copy of both of these licenses along with this 15 * software. If not, they may be obtained at the above URLs. 16 */ 17 18#include <stdio.h> 19#include <stdint.h> 20#include <stdlib.h> 21#include <string.h> 22#include <time.h> 23#ifdef _MSC_VER 24#include <intrin.h> 25#endif 26 27#include "argon2.h" 28 29static uint64_t rdtsc(void) { 30#ifdef _MSC_VER 31 return __rdtsc(); 32#else 33#if defined(__amd64__) || defined(__x86_64__) 34 uint64_t rax, rdx; 35 __asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : :); 36 return (rdx << 32) | rax; 37#elif defined(__i386__) || defined(__i386) || defined(__X86__) 38 uint64_t rax; 39 __asm__ __volatile__("rdtsc" : "=A"(rax) : :); 40 return rax; 41#else 42#error "Not implemented!" 43#endif 44#endif 45} 46 47/* 48 * Benchmarks Argon2 with salt length 16, password length 16, t_cost 3, 49 and different m_cost and threads 50 */ 51static void benchmark() { 52#define BENCH_OUTLEN 16 53#define BENCH_INLEN 16 54 const uint32_t inlen = BENCH_INLEN; 55 const unsigned outlen = BENCH_OUTLEN; 56 unsigned char out[BENCH_OUTLEN]; 57 unsigned char pwd_array[BENCH_INLEN]; 58 unsigned char salt_array[BENCH_INLEN]; 59#undef BENCH_INLEN 60#undef BENCH_OUTLEN 61 62 uint32_t t_cost = 3; 63 uint32_t m_cost; 64 uint32_t thread_test[4] = {1, 2, 4, 8}; 65 argon2_type types[3] = {Argon2_i, Argon2_d, Argon2_id}; 66 67 memset(pwd_array, 0, inlen); 68 memset(salt_array, 1, inlen); 69 70 for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) { 71 unsigned i; 72 for (i = 0; i < 4; ++i) { 73 double run_time = 0; 74 uint32_t thread_n = thread_test[i]; 75 76 unsigned j; 77 for (j = 0; j < 3; ++j) { 78 clock_t start_time, stop_time; 79 uint64_t start_cycles, stop_cycles; 80 uint64_t delta; 81 double mcycles; 82 83 argon2_type type = types[j]; 84 start_time = clock(); 85 start_cycles = rdtsc(); 86 87 argon2_hash(t_cost, m_cost, thread_n, pwd_array, inlen, 88 salt_array, inlen, out, outlen, NULL, 0, type, 89 ARGON2_VERSION_NUMBER); 90 91 stop_cycles = rdtsc(); 92 stop_time = clock(); 93 94 delta = (stop_cycles - start_cycles) / (m_cost); 95 mcycles = (double)(stop_cycles - start_cycles) / (1UL << 20); 96 run_time += ((double)stop_time - start_time) / (CLOCKS_PER_SEC); 97 98 printf("%s %d iterations %d MiB %d threads: %2.2f cpb %2.2f " 99 "Mcycles \n", argon2_type2string(type, 1), t_cost, 100 m_cost >> 10, thread_n, (float)delta / 1024, mcycles); 101 } 102 103 printf("%2.4f seconds\n\n", run_time); 104 } 105 } 106} 107 108int main() { 109 benchmark(); 110 return ARGON2_OK; 111} 112