xref: /aosp_15_r20/external/boringssl/src/crypto/constant_time_test.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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