2021-06-25 09:05:54 +01:00
|
|
|
// Those tests work only with Clang and Memory Sanitizer
|
|
|
|
|
2021-06-17 08:27:29 +01:00
|
|
|
#include <gtest/gtest.h>
|
2021-06-25 09:05:54 +01:00
|
|
|
#include <common/ct_check.h>
|
2021-07-10 00:33:09 +01:00
|
|
|
#include <common/utils.h>
|
2021-06-25 09:05:54 +01:00
|
|
|
|
2021-07-10 00:55:39 +01:00
|
|
|
TEST(ConstantTime, CtCheck_Negative) {
|
2021-06-25 09:05:54 +01:00
|
|
|
unsigned char a[16], b[16];
|
|
|
|
unsigned i;
|
|
|
|
memset(a, 42, 16);
|
|
|
|
memset(b, 42, 16);
|
|
|
|
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_poison(a, 16);
|
2021-06-25 09:05:54 +01:00
|
|
|
for (i = 0; i < 16; i++) {
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-06-25 09:05:54 +01:00
|
|
|
if (a[i] != b[i]) {
|
|
|
|
break;
|
|
|
|
}
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-06-25 09:05:54 +01:00
|
|
|
}
|
|
|
|
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_purify(a, 16);
|
2021-06-25 09:05:54 +01:00
|
|
|
// Ensure buffers are not optimized-out
|
|
|
|
ASSERT_EQ(a[0], b[0]);
|
|
|
|
}
|
|
|
|
|
2021-07-10 00:55:39 +01:00
|
|
|
TEST(ConstantTime, CtCheck_Positive_NoAccess) {
|
2021-06-25 09:05:54 +01:00
|
|
|
unsigned i;
|
|
|
|
char result = 0;
|
|
|
|
unsigned char a[16], b[16];
|
|
|
|
memset(a, 42, sizeof(a));
|
|
|
|
memset(b, 42, sizeof(b));
|
|
|
|
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_poison(a, 16);
|
2021-06-25 09:05:54 +01:00
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
result |= a[i] ^ b[i];
|
|
|
|
}
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_purify(a, 16);
|
2021-06-25 09:05:54 +01:00
|
|
|
|
|
|
|
// Purify result, to allow check that otherwise
|
|
|
|
// would be not constant-time.
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_purify(&result, 1);
|
2021-06-25 09:05:54 +01:00
|
|
|
ASSERT_EQ(result, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-10 00:55:39 +01:00
|
|
|
TEST(ConstantTime, CtCheck_Negative_UseSecretAsIndex) {
|
2021-06-25 09:05:54 +01:00
|
|
|
static const unsigned char tab[2] = {1, 0};
|
|
|
|
unsigned char a[16];
|
|
|
|
unsigned char result;
|
|
|
|
memset(a, 42, sizeof(a));
|
2021-06-17 08:27:29 +01:00
|
|
|
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_poison(a, 16);
|
2021-06-17 08:27:29 +01:00
|
|
|
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-06-25 09:05:54 +01:00
|
|
|
result = tab[a[0] & 1];
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-06-17 08:27:29 +01:00
|
|
|
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_purify(a, 16);
|
2021-06-17 08:27:29 +01:00
|
|
|
|
2021-06-25 09:05:54 +01:00
|
|
|
// Ensure variables are not optimized-out
|
2021-06-28 23:43:55 +01:00
|
|
|
ct_purify(&result, 1);
|
2021-06-25 09:05:54 +01:00
|
|
|
ASSERT_EQ(result, 1);
|
2021-06-17 08:27:29 +01:00
|
|
|
}
|
2021-07-10 00:33:09 +01:00
|
|
|
|
|
|
|
TEST(ConstantTime, CtCheck_memcmp) {
|
|
|
|
unsigned char a[16], b[16];
|
|
|
|
memset(a, 42, sizeof(a));
|
|
|
|
memset(b, 42, sizeof(b));
|
|
|
|
uint8_t ret;
|
|
|
|
|
|
|
|
ct_poison(a, 16);
|
|
|
|
ret = ct_memcmp(a,b,16);
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
// Doesn't matter what we check. It's just to
|
|
|
|
// enusre UMR is triggered.
|
|
|
|
if (!ret) ASSERT_EQ(ret, 0);
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
ct_purify(&ret, 1);
|
|
|
|
|
|
|
|
b[1] = 0;
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
ret = ct_memcmp(a,b,16);
|
|
|
|
if (ret) ASSERT_EQ(ret,1);
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
ct_purify(&ret, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ConstantTime, CtCheck_memcmp_chained) {
|
|
|
|
unsigned char a[16], b[16], c[16], d[16];
|
|
|
|
memset(a, 42, sizeof(a));
|
|
|
|
memset(b, 42, sizeof(b));
|
|
|
|
memset(d, 42, sizeof(b));
|
|
|
|
memset(c, 41, sizeof(c));
|
|
|
|
uint8_t ret;
|
|
|
|
|
|
|
|
ct_poison(a, 16);
|
|
|
|
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
// obviously must generate UMR if first check fails
|
|
|
|
// and second is not done
|
|
|
|
ret = (ct_memcmp(a,c,16)==0) && (ct_memcmp(a,b,16)==0);
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
ct_purify(&ret, 1);
|
|
|
|
ASSERT_EQ(ret,0);
|
|
|
|
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_expect_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
// it's still UMR even if both checks are OK
|
|
|
|
ret = (ct_memcmp(a,d,16)==0) && (ct_memcmp(a,b,16)==0);
|
2021-07-16 10:57:34 +01:00
|
|
|
ct_require_uum();
|
2021-07-10 00:33:09 +01:00
|
|
|
|
|
|
|
ct_purify(&ret, 1);
|
|
|
|
ASSERT_EQ(ret,1);
|
|
|
|
}
|