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
rdtsc(void)29 static 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 */
benchmark()51 static 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
main()108 int main() {
109 benchmark();
110 return ARGON2_OK;
111 }
112