réplica de
https://github.com/henrydcase/pqc.git
sincronizado 2024-11-22 07:35:38 +00:00
ct: use inline static instead of macros
Este cometimento está contido em:
ascendente
caa97d8dfb
cometimento
90aa01eaa4
@ -1,49 +1,55 @@
|
||||
#ifndef CT_CHECK_H
|
||||
#define CT_CHECK_H
|
||||
|
||||
// helper
|
||||
#define VOID(V) ((void)V)
|
||||
|
||||
// Uses Clang's Memory Sanitizer
|
||||
#if defined(PQC_USE_CTSANITIZER)
|
||||
#if defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
|
||||
#if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
|
||||
#include <stddef.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)
|
||||
#include <valgrind/valgrind.h>
|
||||
#include <valgrind/memcheck.h>
|
||||
// Set sz bytes of memory starting at x as uninitialized. Switches on
|
||||
// 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()
|
||||
#endif
|
||||
|
||||
#elif // no ct-checks
|
||||
#define CT_DYE(x,sz)
|
||||
#define CT_PURIFY(x, sz)
|
||||
#define CT_EXPECT_UMR()
|
||||
#define CT_REQUIRE_UMR()
|
||||
#endif // defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
|
||||
// Set sz bytes of memory starting at address p as uninitialized. Switches on constat time checks.
|
||||
static inline void ct_poison(const volatile void *p, size_t sz) {
|
||||
#if defined(PQC_USE_CTSANITIZER) && defined(__clang__) && defined(__has_feature) && __has_feature(memory_sanitizer)
|
||||
__msan_allocated_memory(p,sz);
|
||||
#elif defined(PQC_USE_CTGRIND)
|
||||
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
|
||||
|
29
test/ct.cpp
29
test/ct.cpp
@ -3,11 +3,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <common/ct_check.h>
|
||||
#include <stdio.h>
|
||||
// tests from https://github.com/agl/ctgrind/blob/master/test.c
|
||||
|
||||
void nothing(void) {
|
||||
printf("exiting...");
|
||||
}
|
||||
|
||||
TEST(ConstantTime, CtGrind_Negative) {
|
||||
unsigned char a[16], b[16];
|
||||
@ -15,16 +10,16 @@ TEST(ConstantTime, CtGrind_Negative) {
|
||||
memset(a, 42, 16);
|
||||
memset(b, 42, 16);
|
||||
|
||||
CT_DYE(a, 16);
|
||||
ct_poison(a, 16);
|
||||
for (i = 0; i < 16; i++) {
|
||||
CT_EXPECT_UMR();
|
||||
ct_expect_umr();
|
||||
if (a[i] != b[i]) {
|
||||
break;
|
||||
}
|
||||
CT_REQUIRE_UMR();
|
||||
ct_require_umr();
|
||||
}
|
||||
|
||||
CT_PURIFY(a, 16);
|
||||
ct_purify(a, 16);
|
||||
// Ensure buffers are not optimized-out
|
||||
ASSERT_EQ(a[0], b[0]);
|
||||
}
|
||||
@ -36,16 +31,16 @@ TEST(ConstantTime, CtGrind_Positive_NoAccess) {
|
||||
memset(a, 42, sizeof(a));
|
||||
memset(b, 42, sizeof(b));
|
||||
|
||||
CT_DYE(a, 16);
|
||||
ct_poison(a, 16);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
result |= a[i] ^ b[i];
|
||||
}
|
||||
CT_PURIFY(a, 16);
|
||||
ct_purify(a, 16);
|
||||
|
||||
// Purify result, to allow check that otherwise
|
||||
// would be not constant-time.
|
||||
CT_PURIFY(&result, 1);
|
||||
ct_purify(&result, 1);
|
||||
ASSERT_EQ(result, 0);
|
||||
}
|
||||
|
||||
@ -56,15 +51,15 @@ TEST(ConstantTime, CtGrind_Negative_UseSecretAsIndex) {
|
||||
unsigned char result;
|
||||
memset(a, 42, sizeof(a));
|
||||
|
||||
CT_DYE(a, 16);
|
||||
ct_poison(a, 16);
|
||||
|
||||
CT_EXPECT_UMR();
|
||||
ct_expect_umr();
|
||||
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
|
||||
CT_PURIFY(&result, 1);
|
||||
ct_purify(&result, 1);
|
||||
ASSERT_EQ(result, 1);
|
||||
}
|
||||
|
Carregando…
Criar uma nova questão referindo esta
Bloquear um utilizador