summaryrefslogtreecommitdiff
path: root/toxcore/crypto_core_test.cc
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-06-23 12:32:41 +0000
committeriphydf <iphydf@users.noreply.github.com>2018-06-24 20:17:53 +0000
commit29b2dd6315ffe29cd212c4d5a846479f56b33d52 (patch)
tree881ba80e88fc461a688c0416abb10956fe14e247 /toxcore/crypto_core_test.cc
parent5c2600d87bd000b32b2a37c5a74275912ddd5328 (diff)
Use clang-format for C++ code.
`clang-format -style='{BasedOnStyle: Google, ColumnLimit: 100}'`
Diffstat (limited to 'toxcore/crypto_core_test.cc')
-rw-r--r--toxcore/crypto_core_test.cc91
1 files changed, 91 insertions, 0 deletions
diff --git a/toxcore/crypto_core_test.cc b/toxcore/crypto_core_test.cc
new file mode 100644
index 00000000..1fbdd296
--- /dev/null
+++ b/toxcore/crypto_core_test.cc
@@ -0,0 +1,91 @@
1#include "crypto_core.h"
2
3#include <algorithm>
4
5#include <gtest/gtest.h>
6
7namespace {
8
9enum {
10 /**
11 * The size of the arrays to compare. This was chosen to take around 2000
12 * CPU clocks on x86_64.
13 */
14 CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024, // 1 MiB
15 /**
16 * The number of times we run memcmp in the test.
17 *
18 * We compute the median time taken to reduce error margins.
19 */
20 CRYPTO_TEST_MEMCMP_ITERATIONS = 500,
21 /**
22 * The margin of error (in clocks) we allow for this test.
23 *
24 * Should be within 0.5% of ~2000 CPU clocks. In reality, the code is much
25 * more precise and is usually within 1 CPU clock.
26 */
27 CRYPTO_TEST_MEMCMP_EPS = 10,
28};
29
30clock_t memcmp_time(void *a, void *b, size_t len) {
31 clock_t start = clock();
32 crypto_memcmp(a, b, len);
33 return clock() - start;
34}
35
36/**
37 * This function performs the actual timing. It interleaves comparison of
38 * equal and non-equal arrays to reduce the influence of external effects
39 * such as the machine being a little more busy 1 second later.
40 */
41void memcmp_median(void *src, void *same, void *not_same, size_t len, clock_t *same_median,
42 clock_t *not_same_median) {
43 clock_t same_results[CRYPTO_TEST_MEMCMP_ITERATIONS];
44 clock_t not_same_results[CRYPTO_TEST_MEMCMP_ITERATIONS];
45
46 for (size_t i = 0; i < CRYPTO_TEST_MEMCMP_ITERATIONS; i++) {
47 same_results[i] = memcmp_time(src, same, len);
48 not_same_results[i] = memcmp_time(src, not_same, len);
49 }
50
51 std::sort(same_results, same_results + CRYPTO_TEST_MEMCMP_ITERATIONS);
52 *same_median = same_results[CRYPTO_TEST_MEMCMP_ITERATIONS / 2];
53 std::sort(not_same_results, not_same_results + CRYPTO_TEST_MEMCMP_ITERATIONS);
54 *not_same_median = not_same_results[CRYPTO_TEST_MEMCMP_ITERATIONS / 2];
55}
56
57/**
58 * This test checks whether crypto_memcmp takes the same time for equal and
59 * non-equal chunks of memory.
60 */
61TEST(CryptoCore, MemcmpTimingIsDataIndependent) {
62 // A random piece of memory.
63 auto *src = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
64 random_bytes(src, CRYPTO_TEST_MEMCMP_SIZE);
65
66 // A separate piece of memory containing the same data.
67 auto *same = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
68 memcpy(same, src, CRYPTO_TEST_MEMCMP_SIZE);
69
70 // Another piece of memory containing different data.
71 auto *not_same = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
72 random_bytes(not_same, CRYPTO_TEST_MEMCMP_SIZE);
73
74 clock_t same_median;
75 clock_t not_same_median;
76 memcmp_median(src, same, not_same, CRYPTO_TEST_MEMCMP_SIZE, &same_median, &not_same_median);
77
78 delete[] not_same;
79 delete[] same;
80 delete[] src;
81
82 clock_t const delta =
83 same_median > not_same_median ? same_median - not_same_median : not_same_median - same_median;
84
85 EXPECT_LT(delta, CRYPTO_TEST_MEMCMP_EPS)
86 << "Delta time is too long (" << delta << " >= " << CRYPTO_TEST_MEMCMP_EPS << ")\n"
87 << "Time of the same data comparation: " << same_median << " clocks\n"
88 << "Time of the different data comparation: " << not_same_median << " clocks";
89}
90
91} // namespace