1
1
mirror of https://github.com/henrydcase/pqc.git synced 2024-11-22 23:48:58 +00:00

ct: use inline static instead of macros

This commit is contained in:
Henry Case 2021-06-28 23:43:55 +01:00
parent caa97d8dfb
commit 55719e929c
2 changed files with 56 additions and 55 deletions

View File

@ -1,49 +1,55 @@
#ifndef CT_CHECK_H #ifndef CT_CHECK_H
#define CT_CHECK_H #define CT_CHECK_H
// helper
#define VOID(V) ((void)V)
// Uses Clang's Memory Sanitizer // Uses Clang's Memory Sanitizer
#if defined(PQC_USE_CTSANITIZER) #if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
#if defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer) #include <stddef.h>
#include <sanitizer/msan_interface.h> #include <sanitizer/msan_interface.h>
// Set sz bytes of memory starting at x as uninitialized. Switches on
// constat time checks.
#define CT_DYE(x,sz) __msan_allocated_memory(x,sz)
// Set sz bytes of memory starting at x as initialized. Switches off
// constat time checks.
#define CT_PURIFY(x, sz) __msan_unpoison(x, sz)
// This macro is useful for testing. It instructs memory sanitizer
// that code expects to do reads from unintialized memory.
#define CT_EXPECT_UMR() __msan_set_expect_umr(1)
// This macro works in tandem with CT_EXPECT_UMR. It checks if
// unintialized memory read has occured, if not, it will report
// an error. In current version, code needs to be compiled
// with `-mllvm -msan-keep-going=1` flags in order to work
// correctly (otherwise, runtime will be stopped between
// macros with message "Existing").
#define CT_REQUIRE_UMR() __msan_set_expect_umr(0)
#else
#error("Clang is required to use CT_SANITIZER.")
#endif
// Uses Valgrind's Memcheck (aka ctgrind)
#elif defined(PQC_USE_CTGRIND) #elif defined(PQC_USE_CTGRIND)
#include <valgrind/valgrind.h> #include <valgrind/valgrind.h>
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
// Set sz bytes of memory starting at x as uninitialized. Switches on #endif
// constat time checks.
#define CT_DYE(p,sz) VALGRIND_MAKE_MEM_UNDEFINED(p,sz)
// Set sz bytes of memory starting at x as initialized. Switches off
// constat time checks.
#define CT_PURIFY(p,sz) VALGRIND_MAKE_MEM_DEFINED(p,sz)
// Not supported in Valgrind
#define CT_EXPECT_UMR()
// Not supported in Valgrind
#define CT_REQUIRE_UMR()
#elif // no ct-checks // Set sz bytes of memory starting at address p as uninitialized. Switches on constat time checks.
#define CT_DYE(x,sz) static inline void ct_poison(const volatile void *p, size_t sz) {
#define CT_PURIFY(x, sz) #if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
#define CT_EXPECT_UMR() __msan_allocated_memory(p,sz);
#define CT_REQUIRE_UMR() #elif defined(PQC_USE_CTGRIND)
#endif // defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer) VALGRIND_MAKE_MEM_UNDEFINED(p,sz);
#else
VOID(p), VOID(sz);
#endif
}
// Set sz bytes of memory starting at p as initialized. Switches off constat time checks.
static inline void ct_purify(const volatile void *p, size_t sz) {
#if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
__msan_unpoison(p,sz);
#elif defined(PQC_USE_CTGRIND)
VALGRIND_MAKE_MEM_DEFINED(p,sz);
#else
VOID(p), VOID(sz);
#endif
}
// Function instructs memory sanitizer that code expects to do operation on unintialized memory.
static inline void ct_expect_umr() {
#if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
__msan_set_expect_umr(1);
#endif
}
// Checks if action on unintialized memory has occured. If this is not a case
// then error is reported. It works in tandem with ct_expect_umr(). In current version of
// MSan, the code needs to be compiled with `-mllvm -msan-keep-going=1` flags in order to work
// correctly.
static inline void ct_require_umr() {
#if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
__msan_set_expect_umr(0);
#endif
}
#endif // CT_CHECK_H #endif // CT_CHECK_H

View File

@ -3,11 +3,6 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <common/ct_check.h> #include <common/ct_check.h>
#include <stdio.h> #include <stdio.h>
// tests from https://github.com/agl/ctgrind/blob/master/test.c
void nothing(void) {
printf("exiting...");
}
TEST(ConstantTime, CtGrind_Negative) { TEST(ConstantTime, CtGrind_Negative) {
unsigned char a[16], b[16]; unsigned char a[16], b[16];
@ -15,16 +10,16 @@ TEST(ConstantTime, CtGrind_Negative) {
memset(a, 42, 16); memset(a, 42, 16);
memset(b, 42, 16); memset(b, 42, 16);
CT_DYE(a, 16); ct_poison(a, 16);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
CT_EXPECT_UMR(); ct_expect_umr();
if (a[i] != b[i]) { if (a[i] != b[i]) {
break; break;
} }
CT_REQUIRE_UMR(); ct_require_umr();
} }
CT_PURIFY(a, 16); ct_purify(a, 16);
// Ensure buffers are not optimized-out // Ensure buffers are not optimized-out
ASSERT_EQ(a[0], b[0]); ASSERT_EQ(a[0], b[0]);
} }
@ -36,16 +31,16 @@ TEST(ConstantTime, CtGrind_Positive_NoAccess) {
memset(a, 42, sizeof(a)); memset(a, 42, sizeof(a));
memset(b, 42, sizeof(b)); memset(b, 42, sizeof(b));
CT_DYE(a, 16); ct_poison(a, 16);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
result |= a[i] ^ b[i]; result |= a[i] ^ b[i];
} }
CT_PURIFY(a, 16); ct_purify(a, 16);
// Purify result, to allow check that otherwise // Purify result, to allow check that otherwise
// would be not constant-time. // would be not constant-time.
CT_PURIFY(&result, 1); ct_purify(&result, 1);
ASSERT_EQ(result, 0); ASSERT_EQ(result, 0);
} }
@ -56,15 +51,15 @@ TEST(ConstantTime, CtGrind_Negative_UseSecretAsIndex) {
unsigned char result; unsigned char result;
memset(a, 42, sizeof(a)); memset(a, 42, sizeof(a));
CT_DYE(a, 16); ct_poison(a, 16);
CT_EXPECT_UMR(); ct_expect_umr();
result = tab[a[0] & 1]; result = tab[a[0] & 1];
CT_REQUIRE_UMR(); ct_require_umr();
CT_PURIFY(a, 16); ct_purify(a, 16);
// Ensure variables are not optimized-out // Ensure variables are not optimized-out
CT_PURIFY(&result, 1); ct_purify(&result, 1);
ASSERT_EQ(result, 1); ASSERT_EQ(result, 1);
} }