1 /*
2 * Utilities for constant-time cryptography.
3 *
4 * Author: Emilia Kasper ([email protected])
5 * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
6 * (Google).
7 * ====================================================================
8 * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * "This product includes cryptographic software written by
21 * Eric Young ([email protected])"
22 * The word 'cryptographic' can be left out if the rouines from the library
23 * being used are not cryptographic related :-).
24 * 4. If you include any Windows specific code (or a derivative thereof) from
25 * the apps directory (application code) you must include an acknowledgement:
26 * "This product includes software written by Tim Hudson ([email protected])"
27 *
28 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * The licence and distribution terms for any publically available version or
41 * derivative of this code cannot be changed. i.e. this code cannot simply be
42 * copied and put under another distribution licence
43 * [including the GNU Public Licence.]
44 */
45
46 #include "internal.h"
47
48 #include <limits.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51
52 #include <limits>
53
54 #include <gtest/gtest.h>
55 #include "test/test_util.h"
56
57 #include <openssl/mem.h>
58 #include <openssl/rand.h>
59
60
FromBool8(bool b)61 static uint8_t FromBool8(bool b) {
62 return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
63 }
64
FromBoolW(bool b)65 static crypto_word_t FromBoolW(bool b) {
66 return b ? CONSTTIME_TRUE_W : CONSTTIME_FALSE_W;
67 }
68
69 static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
70
71 static crypto_word_t test_values_w[] = {
72 0,
73 1,
74 1024,
75 12345,
76 32000,
77 #if defined(OPENSSL_64_BIT)
78 0xffffffff / 2 - 1,
79 0xffffffff / 2,
80 0xffffffff / 2 + 1,
81 0xffffffff - 1,
82 0xffffffff,
83 #endif
84 std::numeric_limits<crypto_word_t>::max() / 2 - 1,
85 std::numeric_limits<crypto_word_t>::max() / 2,
86 std::numeric_limits<crypto_word_t>::max() / 2 + 1,
87 std::numeric_limits<crypto_word_t>::max() - 1,
88 std::numeric_limits<crypto_word_t>::max(),
89 };
90
91 static int signed_test_values[] = {
92 0, 1, -1, 1024, -1024, 12345, -12345,
93 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
94
TEST(ConstantTimeTest,Test)95 TEST(ConstantTimeTest, Test) {
96 for (crypto_word_t a : test_values_w) {
97 SCOPED_TRACE(a);
98
99 EXPECT_EQ(FromBoolW(a == 0), constant_time_is_zero_w(a));
100 EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
101
102 for (crypto_word_t b : test_values_w) {
103 SCOPED_TRACE(b);
104
105 EXPECT_EQ(FromBoolW(a < b), constant_time_lt_w(a, b));
106 EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
107
108 EXPECT_EQ(FromBoolW(a >= b), constant_time_ge_w(a, b));
109 EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
110
111 EXPECT_EQ(FromBoolW(a == b), constant_time_eq_w(a, b));
112 EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
113
114 EXPECT_EQ(a, constant_time_select_w(CONSTTIME_TRUE_W, a, b));
115 EXPECT_EQ(b, constant_time_select_w(CONSTTIME_FALSE_W, a, b));
116 }
117 }
118
119 for (int a : signed_test_values) {
120 SCOPED_TRACE(a);
121 for (int b : signed_test_values) {
122 SCOPED_TRACE(b);
123
124 EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_W, a, b));
125 EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_W, a, b));
126
127 EXPECT_EQ(FromBoolW(a == b), constant_time_eq_int(a, b));
128 EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
129 }
130 }
131
132 for (uint8_t a : test_values_8) {
133 SCOPED_TRACE(static_cast<int>(a));
134 for (uint8_t b : test_values_8) {
135 SCOPED_TRACE(static_cast<int>(b));
136 EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
137 EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
138 }
139 }
140 }
141
TEST(ConstantTimeTest,MemCmp)142 TEST(ConstantTimeTest, MemCmp) {
143 uint8_t buf[256], copy[256];
144 RAND_bytes(buf, sizeof(buf));
145
146 OPENSSL_memcpy(copy, buf, sizeof(buf));
147 EXPECT_EQ(0, CRYPTO_memcmp(buf, copy, sizeof(buf)));
148
149 for (size_t i = 0; i < sizeof(buf); i++) {
150 for (uint8_t bit = 1; bit != 0; bit <<= 1) {
151 OPENSSL_memcpy(copy, buf, sizeof(buf));
152 copy[i] ^= bit;
153 EXPECT_NE(0, CRYPTO_memcmp(buf, copy, sizeof(buf)));
154 }
155 }
156 }
157
TEST(ConstantTimeTest,ValueBarrier)158 TEST(ConstantTimeTest, ValueBarrier) {
159 for (int i = 0; i < 10; i++) {
160 crypto_word_t word;
161 RAND_bytes(reinterpret_cast<uint8_t *>(&word), sizeof(word));
162 EXPECT_EQ(word, value_barrier_w(word));
163
164 uint32_t u32;
165 RAND_bytes(reinterpret_cast<uint8_t *>(&u32), sizeof(u32));
166 EXPECT_EQ(u32, value_barrier_u32(u32));
167
168 uint64_t u64;
169 RAND_bytes(reinterpret_cast<uint8_t *>(&u64), sizeof(u64));
170 EXPECT_EQ(u64, value_barrier_u64(u64));
171 }
172 }
173
TEST(ConstantTimeTest,MemCmov)174 TEST(ConstantTimeTest, MemCmov) {
175 for (int i = 0; i < 100; i++) {
176 uint8_t out[256], in[256];
177 RAND_bytes(out, sizeof(out));
178 RAND_bytes(in, sizeof(in));
179
180 uint8_t b = 0;
181 RAND_bytes(&b, 1);
182 b = constant_time_is_zero_8(b & 0xf);
183
184 uint8_t ref_in[256];
185 OPENSSL_memcpy(ref_in, in, sizeof(in));
186
187 uint8_t ref_out[256];
188 OPENSSL_memcpy(ref_out, out, sizeof(out));
189 if (b) {
190 OPENSSL_memcpy(ref_out, in, sizeof(in));
191 }
192
193 CONSTTIME_SECRET(out, sizeof(out));
194 CONSTTIME_SECRET(in, sizeof(in));
195 CONSTTIME_SECRET(&b, 1);
196
197 constant_time_conditional_memcpy(out, in, sizeof(out), b);
198
199 CONSTTIME_DECLASSIFY(&in, sizeof(in));
200 CONSTTIME_DECLASSIFY(&out, sizeof(out));
201
202 EXPECT_EQ(Bytes(in), Bytes(ref_in));
203 EXPECT_EQ(Bytes(out), Bytes(ref_out));
204 }
205 }
206
TEST(ConstantTimeTest,MemCxor)207 TEST(ConstantTimeTest, MemCxor) {
208 for (int i = 0; i < 100; i++) {
209 uint8_t out[256], in[256];
210 RAND_bytes(out, sizeof(out));
211 RAND_bytes(in, sizeof(in));
212
213 uint8_t b = 0;
214 RAND_bytes(&b, 1);
215 b = constant_time_is_zero_8(b & 0xf);
216
217 uint8_t ref_in[256];
218 OPENSSL_memcpy(ref_in, in, sizeof(in));
219
220 uint8_t ref_out[256];
221 OPENSSL_memcpy(ref_out, out, sizeof(out));
222 if (b) {
223 for (size_t j = 0; j < sizeof(ref_out); ++j) {
224 ref_out[j] ^= in[j];
225 }
226 }
227
228 CONSTTIME_SECRET(out, sizeof(out));
229 CONSTTIME_SECRET(in, sizeof(in));
230 CONSTTIME_SECRET(&b, 1);
231
232 constant_time_conditional_memxor(out, in, sizeof(out), b);
233
234 CONSTTIME_DECLASSIFY(&in, sizeof(in));
235 CONSTTIME_DECLASSIFY(&out, sizeof(out));
236
237 EXPECT_EQ(Bytes(in), Bytes(ref_in));
238 EXPECT_EQ(Bytes(out), Bytes(ref_out));
239 }
240 }
241