From 13c638c54b0f25a98e94f7ca4ffef21df51da537 Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 14:51:23 +0300 Subject: [PATCH 1/6] fix secure_zero in hpp --- include/hmac_cpp/secure_buffer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hmac_cpp/secure_buffer.hpp b/include/hmac_cpp/secure_buffer.hpp index 9f109e7..c2d0c4b 100644 --- a/include/hmac_cpp/secure_buffer.hpp +++ b/include/hmac_cpp/secure_buffer.hpp @@ -30,7 +30,7 @@ namespace hmac_cpp { /// \brief Securely zeroes a memory region. /// \param ptr Pointer to the memory to wipe. /// \param len Number of bytes to set to zero. -inline void secure_zero(void* ptr, size_t len) { +static inline void secure_zero(void* ptr, size_t len) { #if defined(__STDC_LIB_EXT1__) (void)memset_s(ptr, len, 0, len); #elif defined(HAVE_EXPLICIT_BZERO) From 1bc3149ecaab767b28b2feeb232659f1d2d917be Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 15:15:07 +0300 Subject: [PATCH 2/6] add secure_zero odr test --- .github/workflows/secure_zero_odr.yml | 31 +++++++++++++++++++++++++++ tests/odr/main.cpp | 16 ++++++++++++++ tests/odr/tu_manual.cpp | 26 ++++++++++++++++++++++ tests/odr/tu_memsets.cpp | 26 ++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 .github/workflows/secure_zero_odr.yml create mode 100644 tests/odr/main.cpp create mode 100644 tests/odr/tu_manual.cpp create mode 100644 tests/odr/tu_memsets.cpp diff --git a/.github/workflows/secure_zero_odr.yml b/.github/workflows/secure_zero_odr.yml new file mode 100644 index 0000000..4a92d75 --- /dev/null +++ b/.github/workflows/secure_zero_odr.yml @@ -0,0 +1,31 @@ +name: secure_zero ODR check + +on: + push + +jobs: + secure-zero-odr-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Install toolchain + run: | + sudo apt-get update + sudo apt-get install -y g++ make + + - name: Build secure_zero ODR test + run: | + mkdir -p build-tests + g++ -std=c++17 -O2 -Wall -Wextra \ + tests/odr/main.cpp \ + tests/odr/tu_manual.cpp \ + tests/odr/tu_memsets.cpp \ + -Iinclude \ + -o build-tests/secure_zero_test + + - name: Run secure_zero ODR test + run: | + ./build-tests/secure_zero_test diff --git a/tests/odr/main.cpp b/tests/odr/main.cpp new file mode 100644 index 0000000..2824f06 --- /dev/null +++ b/tests/odr/main.cpp @@ -0,0 +1,16 @@ +#include + +extern "C" int secure_zero_branch_memsets(); +extern "C" int secure_zero_branch_manual(); + +int main() { + const auto a = secure_zero_branch_memsets(); + const auto b = secure_zero_branch_manual(); + if (a == b) { + std::cout << "secure_zero branch matches across TUs: " << a << "\n"; + return 0; + } + + std::cout << "secure_zero branch mismatch across TUs: " << a << " vs " << b << "\n"; + return 1; +} \ No newline at end of file diff --git a/tests/odr/tu_manual.cpp b/tests/odr/tu_manual.cpp new file mode 100644 index 0000000..715ac9f --- /dev/null +++ b/tests/odr/tu_manual.cpp @@ -0,0 +1,26 @@ +#include +#include + +#undef __STDC_WANT_LIB_EXT1__ +#undef __STDC_LIB_EXT1__ +#undef HAVE_EXPLICIT_BZERO + +#include + +namespace { +constexpr int detect_branch() { +#if defined(__STDC_LIB_EXT1__) + return 1; +#elif defined(HAVE_EXPLICIT_BZERO) + return 2; +#else + return 3; +#endif +} +} + +extern "C" int secure_zero_branch_manual() { + std::array buffer{{0xBB}}; + hmac_cpp::secure_zero(buffer.data(), buffer.size()); + return detect_branch(); +} \ No newline at end of file diff --git a/tests/odr/tu_memsets.cpp b/tests/odr/tu_memsets.cpp new file mode 100644 index 0000000..f3864e7 --- /dev/null +++ b/tests/odr/tu_memsets.cpp @@ -0,0 +1,26 @@ +#include +#include + +#define __STDC_WANT_LIB_EXT1__ 1 +#define __STDC_LIB_EXT1__ 1 +#undef HAVE_EXPLICIT_BZERO + +#include + +namespace { +constexpr int detect_branch() { +#if defined(__STDC_LIB_EXT1__) + return 1; // secure_zero uses memset_s branch +#elif defined(HAVE_EXPLICIT_BZERO) + return 2; // secure_zero uses explicit_bzero branch +#else + return 3; // fallback manual zeroing +#endif +} +} + +extern "C" int secure_zero_branch_memsets() { + std::array buffer{{0xAA}}; + hmac_cpp::secure_zero(buffer.data(), buffer.size()); + return detect_branch(); +} \ No newline at end of file From 9bc6ebb460c7f2b191bb254d0c444fada0a1eb69 Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 15:21:33 +0300 Subject: [PATCH 3/6] upd ci odr check --- .github/workflows/secure_zero_odr.yml | 40 +++++++++++++++++---------- tests/odr/stubs.cpp | 12 ++++++++ tests/odr/tu_memsets.cpp | 2 ++ 3 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 tests/odr/stubs.cpp diff --git a/.github/workflows/secure_zero_odr.yml b/.github/workflows/secure_zero_odr.yml index 4a92d75..988424d 100644 --- a/.github/workflows/secure_zero_odr.yml +++ b/.github/workflows/secure_zero_odr.yml @@ -1,31 +1,41 @@ -name: secure_zero ODR check +name: ODR checks on: push jobs: - secure-zero-odr-test: + odr: runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Install toolchain + - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y g++ make + sudo apt-get install -y build-essential + + - name: Check inline API decorations + run: | + if rg --no-heading --line-number "^\s*inline[^{;]*HMAC_CPP_API" include; then + echo "Detected inline functions annotated with HMAC_CPP_API (expected failure)" + else + echo "No inline functions annotated with HMAC_CPP_API were found" + exit 1 + fi - - name: Build secure_zero ODR test + - name: Build secure_zero conflict sample run: | - mkdir -p build-tests - g++ -std=c++17 -O2 -Wall -Wextra \ + g++ -std=c++11 -Wall -Wextra -pedantic -DHMAC_CPP_STATIC -Iinclude \ tests/odr/main.cpp \ - tests/odr/tu_manual.cpp \ tests/odr/tu_memsets.cpp \ - -Iinclude \ - -o build-tests/secure_zero_test + tests/odr/tu_manual.cpp \ + tests/odr/stubs.cpp \ + -o secure_zero_conflict - - name: Run secure_zero ODR test + - name: Expect secure_zero mismatch run: | - ./build-tests/secure_zero_test + if ./secure_zero_conflict; then + echo "secure_zero conflict binary unexpectedly succeeded" + exit 1 + fi + echo "secure_zero conflict binary correctly reported mismatch" \ No newline at end of file diff --git a/tests/odr/stubs.cpp b/tests/odr/stubs.cpp new file mode 100644 index 0000000..d9c4050 --- /dev/null +++ b/tests/odr/stubs.cpp @@ -0,0 +1,12 @@ +#include +#include + +extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count) { + (void)destsz; + std::memset(dest, ch, count); + return 0; +} + +extern "C" void explicit_bzero(void* dest, size_t count) { + std::memset(dest, 0, count); +} \ No newline at end of file diff --git a/tests/odr/tu_memsets.cpp b/tests/odr/tu_memsets.cpp index f3864e7..8a499fa 100644 --- a/tests/odr/tu_memsets.cpp +++ b/tests/odr/tu_memsets.cpp @@ -1,6 +1,8 @@ #include #include +extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count); + #define __STDC_WANT_LIB_EXT1__ 1 #define __STDC_LIB_EXT1__ 1 #undef HAVE_EXPLICIT_BZERO From bfb1a30a1f97c90a2e9c2ac615475b6774a866fa Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 15:23:35 +0300 Subject: [PATCH 4/6] upd odr ci --- .github/workflows/secure_zero_odr.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/secure_zero_odr.yml b/.github/workflows/secure_zero_odr.yml index 988424d..1ee7bc7 100644 --- a/.github/workflows/secure_zero_odr.yml +++ b/.github/workflows/secure_zero_odr.yml @@ -14,15 +14,6 @@ jobs: sudo apt-get update sudo apt-get install -y build-essential - - name: Check inline API decorations - run: | - if rg --no-heading --line-number "^\s*inline[^{;]*HMAC_CPP_API" include; then - echo "Detected inline functions annotated with HMAC_CPP_API (expected failure)" - else - echo "No inline functions annotated with HMAC_CPP_API were found" - exit 1 - fi - - name: Build secure_zero conflict sample run: | g++ -std=c++11 -Wall -Wextra -pedantic -DHMAC_CPP_STATIC -Iinclude \ From 4e1da74f2075cb7033c33aade22241e9ae501158 Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 15:58:34 +0300 Subject: [PATCH 5/6] fix secure_zero odr --- .github/workflows/secure_zero_odr.yml | 23 +++++++++------------- tests/odr/main.cpp | 22 +++++++++++---------- tests/odr/stubs.cpp | 12 ------------ tests/odr/tu_manual.cpp | 26 ------------------------- tests/odr/tu_memsets.cpp | 28 --------------------------- 5 files changed, 21 insertions(+), 90 deletions(-) delete mode 100644 tests/odr/stubs.cpp delete mode 100644 tests/odr/tu_manual.cpp delete mode 100644 tests/odr/tu_memsets.cpp diff --git a/.github/workflows/secure_zero_odr.yml b/.github/workflows/secure_zero_odr.yml index 1ee7bc7..479bd85 100644 --- a/.github/workflows/secure_zero_odr.yml +++ b/.github/workflows/secure_zero_odr.yml @@ -13,20 +13,15 @@ jobs: run: | sudo apt-get update sudo apt-get install -y build-essential - - - name: Build secure_zero conflict sample + + - name: Build secure_zero ODR sample run: | g++ -std=c++11 -Wall -Wextra -pedantic -DHMAC_CPP_STATIC -Iinclude \ tests/odr/main.cpp \ - tests/odr/tu_memsets.cpp \ - tests/odr/tu_manual.cpp \ - tests/odr/stubs.cpp \ - -o secure_zero_conflict - - - name: Expect secure_zero mismatch - run: | - if ./secure_zero_conflict; then - echo "secure_zero conflict binary unexpectedly succeeded" - exit 1 - fi - echo "secure_zero conflict binary correctly reported mismatch" \ No newline at end of file + tests/odr/tu_memset.cpp \ + tests/odr/tu_explicit.cpp \ + tests/odr/platform_stubs.cpp \ + -o secure_zero_odr + + - name: Run secure_zero ODR sample + run: ./secure_zero_odr \ No newline at end of file diff --git a/tests/odr/main.cpp b/tests/odr/main.cpp index 2824f06..276f950 100644 --- a/tests/odr/main.cpp +++ b/tests/odr/main.cpp @@ -1,16 +1,18 @@ #include -extern "C" int secure_zero_branch_memsets(); -extern "C" int secure_zero_branch_manual(); +extern "C" bool secure_zero_memset_s_branch(); +extern "C" bool secure_zero_explicit_bzero_branch(); int main() { - const auto a = secure_zero_branch_memsets(); - const auto b = secure_zero_branch_manual(); - if (a == b) { - std::cout << "secure_zero branch matches across TUs: " << a << "\n"; - return 0; - } + const bool memset_ok = secure_zero_memset_s_branch(); + const bool explicit_ok = secure_zero_explicit_bzero_branch(); - std::cout << "secure_zero branch mismatch across TUs: " << a << " vs " << b << "\n"; - return 1; + if (!memset_ok || !explicit_ok) { + std::cout << "secure_zero failed: memset_s=" << memset_ok + << ", explicit_bzero=" << explicit_ok << "\n"; + return 1; + } + + std::cout << "secure_zero zeroed buffers across translation units\n"; + return 0; } \ No newline at end of file diff --git a/tests/odr/stubs.cpp b/tests/odr/stubs.cpp deleted file mode 100644 index d9c4050..0000000 --- a/tests/odr/stubs.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count) { - (void)destsz; - std::memset(dest, ch, count); - return 0; -} - -extern "C" void explicit_bzero(void* dest, size_t count) { - std::memset(dest, 0, count); -} \ No newline at end of file diff --git a/tests/odr/tu_manual.cpp b/tests/odr/tu_manual.cpp deleted file mode 100644 index 715ac9f..0000000 --- a/tests/odr/tu_manual.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -#undef __STDC_WANT_LIB_EXT1__ -#undef __STDC_LIB_EXT1__ -#undef HAVE_EXPLICIT_BZERO - -#include - -namespace { -constexpr int detect_branch() { -#if defined(__STDC_LIB_EXT1__) - return 1; -#elif defined(HAVE_EXPLICIT_BZERO) - return 2; -#else - return 3; -#endif -} -} - -extern "C" int secure_zero_branch_manual() { - std::array buffer{{0xBB}}; - hmac_cpp::secure_zero(buffer.data(), buffer.size()); - return detect_branch(); -} \ No newline at end of file diff --git a/tests/odr/tu_memsets.cpp b/tests/odr/tu_memsets.cpp deleted file mode 100644 index 8a499fa..0000000 --- a/tests/odr/tu_memsets.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count); - -#define __STDC_WANT_LIB_EXT1__ 1 -#define __STDC_LIB_EXT1__ 1 -#undef HAVE_EXPLICIT_BZERO - -#include - -namespace { -constexpr int detect_branch() { -#if defined(__STDC_LIB_EXT1__) - return 1; // secure_zero uses memset_s branch -#elif defined(HAVE_EXPLICIT_BZERO) - return 2; // secure_zero uses explicit_bzero branch -#else - return 3; // fallback manual zeroing -#endif -} -} - -extern "C" int secure_zero_branch_memsets() { - std::array buffer{{0xAA}}; - hmac_cpp::secure_zero(buffer.data(), buffer.size()); - return detect_branch(); -} \ No newline at end of file From 927b9866ff2f36d0a991e0ab6f521df340bc4aa5 Mon Sep 17 00:00:00 2001 From: Anastasia Prokop Date: Tue, 28 Oct 2025 16:02:18 +0300 Subject: [PATCH 6/6] add missed files --- tests/odr/platform_stubs.cpp | 12 ++++++++++++ tests/odr/tu_explicit.cpp | 22 ++++++++++++++++++++++ tests/odr/tu_memset.cpp | 22 ++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/odr/platform_stubs.cpp create mode 100644 tests/odr/tu_explicit.cpp create mode 100644 tests/odr/tu_memset.cpp diff --git a/tests/odr/platform_stubs.cpp b/tests/odr/platform_stubs.cpp new file mode 100644 index 0000000..74b4d99 --- /dev/null +++ b/tests/odr/platform_stubs.cpp @@ -0,0 +1,12 @@ +#include +#include + +extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count) { + (void)destsz; + std::memset(dest, ch, count); + return 0; +} + +extern "C" void explicit_bzero(void* dest, size_t count) noexcept { + std::memset(dest, 0, count); +} \ No newline at end of file diff --git a/tests/odr/tu_explicit.cpp b/tests/odr/tu_explicit.cpp new file mode 100644 index 0000000..02c91fc --- /dev/null +++ b/tests/odr/tu_explicit.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +extern "C" void explicit_bzero(void* dest, size_t count) noexcept; + +#undef __STDC_WANT_LIB_EXT1__ +#undef __STDC_LIB_EXT1__ +#define HAVE_EXPLICIT_BZERO 1 + +#include + +extern "C" bool secure_zero_explicit_bzero_branch() { + std::array buffer{}; + buffer.fill(0xBB); + + hmac_cpp::secure_zero(buffer.data(), buffer.size()); + + return std::all_of(buffer.begin(), buffer.end(), [](unsigned char value) { + return value == 0; + }); +} \ No newline at end of file diff --git a/tests/odr/tu_memset.cpp b/tests/odr/tu_memset.cpp new file mode 100644 index 0000000..1517dc3 --- /dev/null +++ b/tests/odr/tu_memset.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +extern "C" int memset_s(void* dest, size_t destsz, int ch, size_t count); + +#define __STDC_WANT_LIB_EXT1__ 1 +#define __STDC_LIB_EXT1__ 1 +#undef HAVE_EXPLICIT_BZERO + +#include + +extern "C" bool secure_zero_memset_s_branch() { + std::array buffer{}; + buffer.fill(0xAA); + + hmac_cpp::secure_zero(buffer.data(), buffer.size()); + + return std::all_of(buffer.begin(), buffer.end(), [](unsigned char value) { + return value == 0; + }); +} \ No newline at end of file