1 // Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "internal.h"
16
17 #include <limits.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 #include <limits>
22
23 #include <gtest/gtest.h>
24 #include "test/test_util.h"
25
26 #include <openssl/mem.h>
27 #include <openssl/rand.h>
28
29
FromBool8(bool b)30 static uint8_t FromBool8(bool b) {
31 return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
32 }
33
FromBoolW(bool b)34 static crypto_word_t FromBoolW(bool b) {
35 return b ? CONSTTIME_TRUE_W : CONSTTIME_FALSE_W;
36 }
37
38 static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
39
40 static crypto_word_t test_values_w[] = {
41 0,
42 1,
43 1024,
44 12345,
45 32000,
46 #if defined(OPENSSL_64_BIT)
47 0xffffffff / 2 - 1,
48 0xffffffff / 2,
49 0xffffffff / 2 + 1,
50 0xffffffff - 1,
51 0xffffffff,
52 #endif
53 std::numeric_limits<crypto_word_t>::max() / 2 - 1,
54 std::numeric_limits<crypto_word_t>::max() / 2,
55 std::numeric_limits<crypto_word_t>::max() / 2 + 1,
56 std::numeric_limits<crypto_word_t>::max() - 1,
57 std::numeric_limits<crypto_word_t>::max(),
58 };
59
60 static int signed_test_values[] = {
61 0, 1, -1, 1024, -1024, 12345, -12345,
62 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
63
TEST(ConstantTimeTest,Test)64 TEST(ConstantTimeTest, Test) {
65 for (crypto_word_t a : test_values_w) {
66 SCOPED_TRACE(a);
67
68 EXPECT_EQ(FromBoolW(a == 0), constant_time_is_zero_w(a));
69 EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
70
71 for (crypto_word_t b : test_values_w) {
72 SCOPED_TRACE(b);
73
74 EXPECT_EQ(FromBoolW(a < b), constant_time_lt_w(a, b));
75 EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
76
77 EXPECT_EQ(FromBoolW(a >= b), constant_time_ge_w(a, b));
78 EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
79
80 EXPECT_EQ(FromBoolW(a == b), constant_time_eq_w(a, b));
81 EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
82
83 EXPECT_EQ(a, constant_time_select_w(CONSTTIME_TRUE_W, a, b));
84 EXPECT_EQ(b, constant_time_select_w(CONSTTIME_FALSE_W, a, b));
85 }
86 }
87
88 for (int a : signed_test_values) {
89 SCOPED_TRACE(a);
90 for (int b : signed_test_values) {
91 SCOPED_TRACE(b);
92
93 EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_W, a, b));
94 EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_W, a, b));
95
96 EXPECT_EQ(FromBoolW(a == b), constant_time_eq_int(a, b));
97 EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
98 }
99 }
100
101 for (uint8_t a : test_values_8) {
102 SCOPED_TRACE(static_cast<int>(a));
103 for (uint8_t b : test_values_8) {
104 SCOPED_TRACE(static_cast<int>(b));
105 EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
106 EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
107 }
108 }
109 }
110
TEST(ConstantTimeTest,MemCmp)111 TEST(ConstantTimeTest, MemCmp) {
112 uint8_t buf[256], copy[256];
113 RAND_bytes(buf, sizeof(buf));
114
115 OPENSSL_memcpy(copy, buf, sizeof(buf));
116 EXPECT_EQ(0, CRYPTO_memcmp(buf, copy, sizeof(buf)));
117
118 for (size_t i = 0; i < sizeof(buf); i++) {
119 for (uint8_t bit = 1; bit != 0; bit <<= 1) {
120 OPENSSL_memcpy(copy, buf, sizeof(buf));
121 copy[i] ^= bit;
122 EXPECT_NE(0, CRYPTO_memcmp(buf, copy, sizeof(buf)));
123 }
124 }
125 }
126
TEST(ConstantTimeTest,ValueBarrier)127 TEST(ConstantTimeTest, ValueBarrier) {
128 for (int i = 0; i < 10; i++) {
129 crypto_word_t word;
130 RAND_bytes(reinterpret_cast<uint8_t *>(&word), sizeof(word));
131 EXPECT_EQ(word, value_barrier_w(word));
132
133 uint32_t u32;
134 RAND_bytes(reinterpret_cast<uint8_t *>(&u32), sizeof(u32));
135 EXPECT_EQ(u32, value_barrier_u32(u32));
136
137 uint64_t u64;
138 RAND_bytes(reinterpret_cast<uint8_t *>(&u64), sizeof(u64));
139 EXPECT_EQ(u64, value_barrier_u64(u64));
140 }
141 }
142
TEST(ConstantTimeTest,MemCmov)143 TEST(ConstantTimeTest, MemCmov) {
144 for (int i = 0; i < 100; i++) {
145 uint8_t out[256], in[256];
146 RAND_bytes(out, sizeof(out));
147 RAND_bytes(in, sizeof(in));
148
149 uint8_t b = 0;
150 RAND_bytes(&b, 1);
151 b = constant_time_is_zero_8(b & 0xf);
152
153 uint8_t ref_in[256];
154 OPENSSL_memcpy(ref_in, in, sizeof(in));
155
156 uint8_t ref_out[256];
157 OPENSSL_memcpy(ref_out, out, sizeof(out));
158 if (b) {
159 OPENSSL_memcpy(ref_out, in, sizeof(in));
160 }
161
162 CONSTTIME_SECRET(out, sizeof(out));
163 CONSTTIME_SECRET(in, sizeof(in));
164 CONSTTIME_SECRET(&b, 1);
165
166 constant_time_conditional_memcpy(out, in, sizeof(out), b);
167
168 CONSTTIME_DECLASSIFY(&in, sizeof(in));
169 CONSTTIME_DECLASSIFY(&out, sizeof(out));
170
171 EXPECT_EQ(Bytes(in), Bytes(ref_in));
172 EXPECT_EQ(Bytes(out), Bytes(ref_out));
173 }
174 }
175
TEST(ConstantTimeTest,MemCxor)176 TEST(ConstantTimeTest, MemCxor) {
177 for (int i = 0; i < 100; i++) {
178 uint8_t out[256], in[256];
179 RAND_bytes(out, sizeof(out));
180 RAND_bytes(in, sizeof(in));
181
182 uint8_t b = 0;
183 RAND_bytes(&b, 1);
184 b = constant_time_is_zero_8(b & 0xf);
185
186 uint8_t ref_in[256];
187 OPENSSL_memcpy(ref_in, in, sizeof(in));
188
189 uint8_t ref_out[256];
190 OPENSSL_memcpy(ref_out, out, sizeof(out));
191 if (b) {
192 for (size_t j = 0; j < sizeof(ref_out); ++j) {
193 ref_out[j] ^= in[j];
194 }
195 }
196
197 CONSTTIME_SECRET(out, sizeof(out));
198 CONSTTIME_SECRET(in, sizeof(in));
199 CONSTTIME_SECRET(&b, 1);
200
201 constant_time_conditional_memxor(out, in, sizeof(out), b);
202
203 CONSTTIME_DECLASSIFY(&in, sizeof(in));
204 CONSTTIME_DECLASSIFY(&out, sizeof(out));
205
206 EXPECT_EQ(Bytes(in), Bytes(ref_in));
207 EXPECT_EQ(Bytes(out), Bytes(ref_out));
208 }
209 }
210