diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7a47840..7e5ffd1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,5 @@ # ~~~ -# Copyright 2025 CryptoLab, Inc. +# Copyright 2026 CryptoLab, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed8e825..d2c938d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ fail_fast: false default_install_hook_types: [pre-commit] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -16,6 +16,6 @@ repos: hooks: - id: cmake-format - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v20.1.6 + rev: v22.1.0 hooks: - id: clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a20a36..2310eab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~ -# Copyright 2025 CryptoLab, Inc. +# Copyright 2026 CryptoLab, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ cmake_minimum_required(VERSION 3.21) project( alea - VERSION 0.1.5 + VERSION 0.1.7 LANGUAGES C DESCRIPTION "CryptoLab's official pseudo-random number generator") @@ -37,19 +37,20 @@ include(cmake/warnings.cmake) include(cmake/CPM.cmake) add_library(alea) -target_sources(alea PRIVATE include/alea/alea.h include/alea/algorithms.h - src/alea.c src/alea-internal.h src/alea-hkdf.c) +target_sources(alea PRIVATE src/alea.c src/alea-internal.c src/alea-hkdf.c) set_my_project_warnings(alea) target_compile_definitions(alea PUBLIC ALEA_EXPORTS) -target_link_libraries(alea PRIVATE ${CRYPTO_LIB_NAME} m) +target_link_libraries(alea PRIVATE ${CRYPTO_LIB_NAME}) +if(NOT MSVC) + target_link_libraries(alea PRIVATE m) +endif() target_include_directories( alea PUBLIC $ $) set(CRYPTO_LIB_NAME "") set(CRYPTO_LIB_COMPILE_DEFINITION "ALEA_BUILTIN") -target_sources(alea PRIVATE src/fips202.h src/fips202.c src/alea-builtin.h - src/alea-builtin.c) +target_sources(alea PRIVATE src/fips202.c src/alea-builtin.c) target_compile_definitions(alea PRIVATE ${CRYPTO_LIB_COMPILE_DEFINITION}) diff --git a/README.md b/README.md index b6d6423..a2b105f 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ You should supply `$ALEA_BUILD_DIR` for your preference. ### Build Options -| Build Options | What it is | Default | -| --------------------- | ---------------------------------------------------------- | ----------- | -| `BUILD_SHARED_LIBS` | Build a shared library instead of a static one | `OFF` | +| Build Options | What it is | Default | +| --------------------- | -------------------------------------------------------------------------- | ------- | +| `BUILD_SHARED_LIBS` | Build a shared library instead of a static one | `OFF` | | `ALEA_BUILD_TEST` | Build and enable the CTest-based unit tests | `ON` | | `ALEA_BUILD_DOXYGEN` | Generate API documentation via Doxygen | `OFF` | | `ALEA_INSTALL` | Install the Alea library, headers, and CMake package configuration files | `ON` | diff --git a/cmake/aleaConfig.cmake.in b/cmake/aleaConfig.cmake.in index d731332..9022435 100644 --- a/cmake/aleaConfig.cmake.in +++ b/cmake/aleaConfig.cmake.in @@ -1,5 +1,5 @@ # ~~~ -# Copyright 2025 CryptoLab, Inc. +# Copyright 2026 CryptoLab, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/cmake/warnings.cmake b/cmake/warnings.cmake index 8667cb6..11ed7ce 100644 --- a/cmake/warnings.cmake +++ b/cmake/warnings.cmake @@ -1,5 +1,5 @@ # ~~~ -# Copyright 2025 CryptoLab, Inc. +# Copyright 2026 CryptoLab, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/include/alea/alea.h b/include/alea/alea.h index 5d5fc39..3647276 100644 --- a/include/alea/alea.h +++ b/include/alea/alea.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/include/alea/algorithms.h b/include/alea/algorithms.h index b9dcc60..9d590ef 100644 --- a/include/alea/algorithms.h +++ b/include/alea/algorithms.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/alea-builtin.c b/src/alea-builtin.c index 96d68ca..b6f9721 100644 --- a/src/alea-builtin.c +++ b/src/alea-builtin.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/alea-builtin.h b/src/alea-builtin.h index 036b218..1600dc6 100644 --- a/src/alea-builtin.h +++ b/src/alea-builtin.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/alea-hkdf.c b/src/alea-hkdf.c index bcf23c9..c08df20 100644 --- a/src/alea-hkdf.c +++ b/src/alea-hkdf.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/alea-hkdf.h b/src/alea-hkdf.h index 4c09107..e0129fc 100644 --- a/src/alea-hkdf.h +++ b/src/alea-hkdf.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/alea-internal.c b/src/alea-internal.c new file mode 100644 index 0000000..3a62e28 --- /dev/null +++ b/src/alea-internal.c @@ -0,0 +1,76 @@ +/* + * Copyright 2026 CryptoLab, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Request C11 Annex K interfaces (memset_s) before any standard header. */ +#if !defined(__STDC_WANT_LIB_EXT1__) +#define __STDC_WANT_LIB_EXT1__ 1 +#endif + +#include "alea-internal.h" + +#ifdef _MSC_VER +#define NOINLINE __declspec(noinline) +#elif defined(__GNUC__) || defined(__clang__) +#define NOINLINE __attribute__((noinline)) +#else +#define NOINLINE +#endif + +/* Compile-time detection of secure memory-zeroing primitive. + * Priority: + * 1. explicit_bzero – glibc >= 2.25, OpenBSD, FreeBSD >= 11, NetBSD, macOS + * 2. SecureZeroMemory – Windows + * 3. memset_s – C11 Annex K (implementation defines __STDC_LIB_EXT1__) + * 4. volatile loop – fallback + * + * On glibc without _GNU_SOURCE, string.h does not declare explicit_bzero even + * though the symbol exists in libc; supply a forward declaration in that case. + */ +#if defined(__GLIBC__) && \ + (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#define ALEA_HAVE_EXPLICIT_BZERO 1 +#ifndef _GNU_SOURCE +extern void explicit_bzero(void *, size_t); +#endif +#elif defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 11) || \ + defined(__NetBSD__) +#define ALEA_HAVE_EXPLICIT_BZERO 1 +#elif defined(_WIN32) +#include +#define ALEA_HAVE_SECURE_ZERO_MEMORY 1 +#elif defined(__STDC_LIB_EXT1__) +#define ALEA_HAVE_MEMSET_S 1 +#endif + +NOINLINE void safe_memzero(void *ptr, size_t ptr_len) { + if (ptr == NULL || ptr_len == 0) { + return; + } + +#if defined(ALEA_HAVE_EXPLICIT_BZERO) + explicit_bzero(ptr, ptr_len); +#elif defined(ALEA_HAVE_SECURE_ZERO_MEMORY) + SecureZeroMemory(ptr, ptr_len); +#elif defined(ALEA_HAVE_MEMSET_S) + memset_s(ptr, ptr_len, 0, ptr_len); +#else + /* volatile fallback */ + volatile unsigned char *p = (volatile unsigned char *)ptr; + while (ptr_len--) { + *p++ = 0; + } +#endif +} diff --git a/src/alea-internal.h b/src/alea-internal.h index de440b7..19ee1bf 100644 --- a/src/alea-internal.h +++ b/src/alea-internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,10 @@ #include #include +void safe_memzero(void *ptr, size_t ptr_len); + static inline void safe_free(void *ptr, size_t ptr_len) { - memset(ptr, 0, ptr_len); + safe_memzero(ptr, ptr_len); free(ptr); } diff --git a/src/alea.c b/src/alea.c index c894591..7bb76a3 100644 --- a/src/alea.c +++ b/src/alea.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -174,10 +174,9 @@ inline static alea_return alea_rejection_sampling_mod(alea_state *state, uint64_t n = (uint64_t)dst_len; uint64_t rnd, m, l, t, s; - for (uint64_t i = 0; i < n - 1; i++) { - s = n - 1 - i; + for (uint64_t i = 0; i < n; i++) { + s = n - i; t = two_to_L % s; - // Unbiased uniform sampling from [0, n - 1 - i) // Rejection sampling ensures that ⌊x · s/2L⌋ is unbiasedly // sampled from [0, s) do { diff --git a/src/fips202.h b/src/fips202.h index 9211b31..ff42c39 100644 --- a/src/fips202.h +++ b/src/fips202.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index df3ef7a..43936f0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~ -# Copyright 2025 CryptoLab, Inc. +# Copyright 2026 CryptoLab, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/test/dudect_wrapper.c b/test/dudect_wrapper.c index 8cab0c2..e63a3b8 100644 --- a/test/dudect_wrapper.c +++ b/test/dudect_wrapper.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/dudect_wrapper.h b/test/dudect_wrapper.h index 0788ba2..2621d24 100644 --- a/test/dudect_wrapper.h +++ b/test/dudect_wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/functionality-test.c b/test/functionality-test.c index 4200997..f2984a5 100644 --- a/test/functionality-test.c +++ b/test/functionality-test.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,9 @@ #include "unity.h" +#ifdef _MSC_VER +#include +#endif #include #include #include @@ -26,7 +29,7 @@ #define TEST_SIZE 100000 #define TEST_RANGE_32 100 -#define TEST_RANGE_64 (1UL << 33) +#define TEST_RANGE_64 (1ULL << 30) #define TEST_HWT (TEST_SIZE * 2 / 3) #define TEST_CBD 21 #define TEST_STD 3.2 @@ -67,8 +70,8 @@ } \ if (range > size) \ return; \ - int count[range]; \ - memset(count, 0, sizeof(count)); \ + int *count = malloc(range * sizeof(int)); \ + memset(count, 0, range * sizeof(*count)); \ for (size_t i = 0; i < size; ++i) { \ count[dst[i]] += 1; \ } \ @@ -81,6 +84,7 @@ } \ } \ TEST_ASSERT_LESS_OR_EQUAL(range * VERIFY_SIGMA_TOLER, count_out_of_range); \ + free(count); \ } #define CHECK_HWT(bit) \ @@ -157,16 +161,19 @@ void tearDown(void) { alea_free(g_state_256); } -#define CHECK_FUNTION_LIST \ +#define CHECK_FUNCTION_LIST \ Y(RANGE) \ Y(HWT) \ Y(CBD) \ Y(GAUSSIAN) -#define Y(NAME) CHECK_##NAME(32) CHECK_##NAME(64) -CHECK_FUNTION_LIST -CHECK_HWT(8) +#define Y(NAME) \ + CHECK_##NAME(32); \ + CHECK_##NAME(64); + +CHECK_FUNCTION_LIST #undef Y +CHECK_HWT(8) #define X(NAME, API, TYPE, SIZE, OPT) \ DEFINE_FUNCTIONALITY_TEST(NAME, API, TYPE, SIZE, OPT) diff --git a/test/lowlevel-test.c b/test/lowlevel-test.c index 928b81f..86c3fa0 100644 --- a/test/lowlevel-test.c +++ b/test/lowlevel-test.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/timing-test.c b/test/timing-test.c index a794588..3c8ff85 100644 --- a/test/timing-test.c +++ b/test/timing-test.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 CryptoLab, Inc. + * Copyright 2026 CryptoLab, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.