diff --git a/.github/actions/config-variations/action.yml b/.github/actions/config-variations/action.yml index dc088afc2..65b2cb1c3 100644 --- a/.github/actions/config-variations/action.yml +++ b/.github/actions/config-variations/action.yml @@ -62,6 +62,7 @@ runs: extra_env: 'ASAN_OPTIONS=detect_leaks=1' examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom zeroization (explicit_bzero)" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'custom-zeroize') }} uses: ./.github/actions/multi-functest @@ -76,6 +77,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom native capability functions (static ON)" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'native-cap-ON') }} uses: ./.github/actions/multi-functest @@ -90,6 +92,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom native capability functions (static OFF)" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'native-cap-OFF') }} uses: ./.github/actions/multi-functest @@ -104,6 +107,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom native capability functions (ID_AA64PFR1_EL1 detection)" if: ${{ (inputs.tests == 'all' || contains(inputs.tests, 'native-cap-ID_AA64PFR1_EL1')) && runner.os == 'Linux' && runner.arch == 'ARM64' }} uses: ./.github/actions/multi-functest @@ -118,6 +122,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom native capability functions (CPUID AVX2 detection)" if: ${{ (inputs.tests == 'all' || contains(inputs.tests, 'native-cap-CPUID_AVX2')) && runner.os == 'Linux' && runner.arch == 'X64' }} uses: ./.github/actions/multi-functest @@ -132,6 +137,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "No ASM" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'no-asm') }} uses: ./.github/actions/multi-functest @@ -146,6 +152,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Serial FIPS202 (no batched Keccak)" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'serial-fips202') }} uses: ./.github/actions/multi-functest @@ -160,6 +167,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom randombytes" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'custom-randombytes') }} uses: ./.github/actions/multi-functest @@ -174,6 +182,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom memcpy" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'custom-memcpy') }} uses: ./.github/actions/multi-functest @@ -188,6 +197,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom memset" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'custom-memset') }} uses: ./.github/actions/multi-functest @@ -202,6 +212,7 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config - name: "Custom stdlib (memcpy + memset)" if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'custom-stdlib') }} uses: ./.github/actions/multi-functest @@ -216,3 +227,4 @@ runs: opt: ${{ inputs.opt }} examples: false # Some examples use a custom config themselves alloc: false # Requires custom config + rng_fail: false # Requires custom config diff --git a/.github/actions/functest/action.yml b/.github/actions/functest/action.yml index dce6b89fb..65013abba 100644 --- a/.github/actions/functest/action.yml +++ b/.github/actions/functest/action.yml @@ -60,6 +60,9 @@ inputs: alloc: description: Determine whether to run alloc tests or not default: "true" + rng_fail: + description: Determine whether to run rng fail tests or not + default: "true" extra_args: description: Additional arguments to pass to the tests script default: "" @@ -81,6 +84,7 @@ runs: echo EXAMPLES="${{ inputs.examples == 'true' && 'examples' || 'no-examples' }}" >> $GITHUB_ENV echo STACK="${{ inputs.stack == 'true' && 'stack' || 'no-stack' }}" >> $GITHUB_ENV echo ALLOC="${{ inputs.alloc == 'true' && 'alloc' || 'no-alloc' }}" >> $GITHUB_ENV + echo RNGFAIL="${{ inputs.rng_fail == 'true' && 'rng-fail' || 'no-rng-fail' }}" >> $GITHUB_ENV - name: Setup nix uses: ./.github/actions/setup-shell with: @@ -111,11 +115,11 @@ runs: - $(python3 --version) - $(${{ inputs.cross_prefix }}${CC} --version | grep -m1 "") EOF - - name: ${{ env.MODE }} ${{ inputs.opt }} tests (${{ env.FUNC }}, ${{ env.KAT }}, ${{ env.EXAMPLES }}, ${{ env.STACK }}, ${{ env.UNIT }}, ${{ env.ALLOC }}) + - name: ${{ env.MODE }} ${{ inputs.opt }} tests (${{ env.FUNC }}, ${{ env.KAT }}, ${{ env.EXAMPLES }}, ${{ env.STACK }}, ${{ env.UNIT }}, ${{ env.ALLOC }}, ${{ env.RNGFAIL }}) shell: ${{ env.SHELL }} run: | make clean - ${{ inputs.extra_env }} ./scripts/tests all ${{ inputs.check_namespace == 'true' && '--check-namespace' || ''}} --exec-wrapper="${{ inputs.exec_wrapper }}" --cross-prefix="${{ inputs.cross_prefix }}" --cflags="${{ inputs.cflags }}" --ldflags="${{ inputs.ldflags }}" --opt=${{ inputs.opt }} --${{ env.FUNC }} --${{ env.KAT }} --${{ env.ACVP }} --${{ env.EXAMPLES }} --${{ env.STACK }} --${{ env.UNIT }} --${{ env.ALLOC }} -v ${{ inputs.extra_args }} + ${{ inputs.extra_env }} ./scripts/tests all ${{ inputs.check_namespace == 'true' && '--check-namespace' || ''}} --exec-wrapper="${{ inputs.exec_wrapper }}" --cross-prefix="${{ inputs.cross_prefix }}" --cflags="${{ inputs.cflags }}" --ldflags="${{ inputs.ldflags }}" --opt=${{ inputs.opt }} --${{ env.FUNC }} --${{ env.KAT }} --${{ env.ACVP }} --${{ env.EXAMPLES }} --${{ env.STACK }} --${{ env.UNIT }} --${{ env.ALLOC }} --${{ env.RNGFAIL }} -v ${{ inputs.extra_args }} - name: Post ${{ env.MODE }} Tests shell: ${{ env.SHELL }} if: success() || failure() diff --git a/.github/actions/multi-functest/action.yml b/.github/actions/multi-functest/action.yml index 603dbd1c0..509c96e30 100644 --- a/.github/actions/multi-functest/action.yml +++ b/.github/actions/multi-functest/action.yml @@ -57,6 +57,9 @@ inputs: alloc: description: Determine whether to run alloc tests or not default: "true" + rng_fail: + description: Determine whether to run rng fail tests or not + default: "true" extra_args: description: Additional arguments to pass to the tests script default: "" @@ -86,6 +89,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross x86_64 Tests @@ -110,6 +114,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross aarch64 Tests @@ -134,6 +139,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross ppc64le Tests @@ -158,6 +164,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross aarch64_be Tests @@ -182,6 +189,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross riscv64 Tests (RVV, VLEN=128) @@ -206,6 +214,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross riscv64 Tests (RVV, VLEN=256) @@ -229,6 +238,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross riscv64 Tests (RVV, VLEN=512) @@ -252,6 +262,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross riscv64 Tests (RVV, VLEN=1024) @@ -275,6 +286,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} - name: Cross riscv32 Tests @@ -299,6 +311,7 @@ runs: check_namespace: ${{ inputs.check_namespace }} stack: ${{ inputs.stack }} alloc: ${{ inputs.alloc }} + rng_fail: ${{ inputs.rng_fail }} extra_args: ${{ inputs.extra_args }} extra_env: ${{ inputs.extra_env }} diff --git a/.github/workflows/baremetal.yml b/.github/workflows/baremetal.yml index 4c235e0b6..f3aba3e23 100644 --- a/.github/workflows/baremetal.yml +++ b/.github/workflows/baremetal.yml @@ -36,3 +36,4 @@ jobs: examples: false stack: false alloc: false + rng_fail: false diff --git a/BIBLIOGRAPHY.md b/BIBLIOGRAPHY.md index da16a0d8e..f6df9b81d 100644 --- a/BIBLIOGRAPHY.md +++ b/BIBLIOGRAPHY.md @@ -53,6 +53,7 @@ source code and documentation. - [test/no_asm_config.h](test/no_asm_config.h) - [test/serial_fips202_config.h](test/serial_fips202_config.h) - [test/test_alloc_config.h](test/test_alloc_config.h) + - [test/test_rng_fail_config.h](test/test_rng_fail_config.h) ### `FIPS202` @@ -107,6 +108,7 @@ source code and documentation. - [test/no_asm_config.h](test/no_asm_config.h) - [test/serial_fips202_config.h](test/serial_fips202_config.h) - [test/test_alloc_config.h](test/test_alloc_config.h) + - [test/test_rng_fail_config.h](test/test_rng_fail_config.h) ### `HYBRID` diff --git a/Makefile b/Makefile index 49ce3b2de..b2adee4ca 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,14 @@ # Copyright (c) The mldsa-native project authors # SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT -.PHONY: func kat acvp stack unit alloc \ - func_44 kat_44 acvp_44 stack_44 unit_44 alloc_44 \ - func_65 kat_65 acvp_65 stack_65 unit_65 alloc_65 \ - func_87 kat_87 acvp_87 stack_87 unit_87 alloc_87 \ - run_func run_kat run_acvp run_stack run_unit run_alloc \ - run_func_44 run_kat_44 run_stack_44 run_unit_44 run_alloc_44 \ - run_func_65 run_kat_65 run_stack_65 run_unit_65 run_alloc_65 \ - run_func_87 run_kat_87 run_stack_87 run_unit_87 run_alloc_87 \ +.PHONY: func kat acvp stack unit alloc rng_fail \ + func_44 kat_44 acvp_44 stack_44 unit_44 alloc_44 rng_fail_44 \ + func_65 kat_65 acvp_65 stack_65 unit_65 alloc_65 rng_fail_65 \ + func_87 kat_87 acvp_87 stack_87 unit_87 alloc_87 rng_fail_87 \ + run_func run_kat run_acvp run_stack run_unit run_alloc run_rng_fail \ + run_func_44 run_kat_44 run_stack_44 run_unit_44 run_alloc_44 run_rng_fail_44 \ + run_func_65 run_kat_65 run_stack_65 run_unit_65 run_alloc_65 run_rng_fail_65 \ + run_func_87 run_kat_87 run_stack_87 run_unit_87 run_alloc_87 run_rng_fail_87 \ bench_44 bench_65 bench_87 bench \ run_bench_44 run_bench_65 run_bench_87 run_bench \ bench_components_44 bench_components_65 bench_components_87 bench_components \ @@ -48,7 +48,7 @@ quickcheck: test build: func kat acvp $(Q)echo " Everything builds fine!" -test: run_kat run_func run_acvp run_unit run_alloc +test: run_kat run_func run_acvp run_unit run_alloc run_rng_fail $(Q)echo " Everything checks fine!" # Detect available SHA256 command @@ -157,6 +157,22 @@ run_alloc_87: alloc_87 $(W) $(MLDSA87_DIR)/bin/test_alloc87 run_alloc: run_alloc_44 run_alloc_65 run_alloc_87 +rng_fail_44: $(MLDSA44_DIR)/bin/test_rng_fail44 + $(Q)echo " RNG_FAIL ML-DSA-44: $^" +rng_fail_65: $(MLDSA65_DIR)/bin/test_rng_fail65 + $(Q)echo " RNG_FAIL ML-DSA-65: $^" +rng_fail_87: $(MLDSA87_DIR)/bin/test_rng_fail87 + $(Q)echo " RNG_FAIL ML-DSA-87: $^" +rng_fail: rng_fail_44 rng_fail_65 rng_fail_87 + +run_rng_fail_44: rng_fail_44 + $(W) $(MLDSA44_DIR)/bin/test_rng_fail44 +run_rng_fail_65: rng_fail_65 + $(W) $(MLDSA65_DIR)/bin/test_rng_fail65 +run_rng_fail_87: rng_fail_87 + $(W) $(MLDSA87_DIR)/bin/test_rng_fail87 +run_rng_fail: run_rng_fail_44 run_rng_fail_65 run_rng_fail_87 + lib: $(BUILD_DIR)/libmldsa.a $(BUILD_DIR)/libmldsa44.a $(BUILD_DIR)/libmldsa65.a $(BUILD_DIR)/libmldsa87.a # Enforce setting CYCLES make variable when diff --git a/examples/basic_deterministic/mldsa_native/mldsa_native_config.h b/examples/basic_deterministic/mldsa_native/mldsa_native_config.h index ac48237c2..18d3be53b 100644 --- a/examples/basic_deterministic/mldsa_native/mldsa_native_config.h +++ b/examples/basic_deterministic/mldsa_native/mldsa_native_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/basic_lowram/mldsa_native/mldsa_native_config.h b/examples/basic_lowram/mldsa_native/mldsa_native_config.h index 2eebeb2d4..66919c50a 100644 --- a/examples/basic_lowram/mldsa_native/mldsa_native_config.h +++ b/examples/basic_lowram/mldsa_native/mldsa_native_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h b/examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h index baba8a033..fd534a435 100644 --- a/examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h +++ b/examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h b/examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h index 48eb42065..f2f78f151 100644 --- a/examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h +++ b/examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h @@ -407,7 +407,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -418,9 +418,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/custom_backend/mldsa_native/mldsa_native_config.h b/examples/custom_backend/mldsa_native/mldsa_native_config.h index 6c064c470..4d3de4b20 100644 --- a/examples/custom_backend/mldsa_native/mldsa_native_config.h +++ b/examples/custom_backend/mldsa_native/mldsa_native_config.h @@ -402,7 +402,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -413,9 +413,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/monolithic_build/mldsa_native/mldsa_native_config.h b/examples/monolithic_build/mldsa_native/mldsa_native_config.h index 68f7ce8b6..d4468d15f 100644 --- a/examples/monolithic_build/mldsa_native/mldsa_native_config.h +++ b/examples/monolithic_build/mldsa_native/mldsa_native_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/monolithic_build_multilevel/mldsa_native/mldsa_native_config.h b/examples/monolithic_build_multilevel/mldsa_native/mldsa_native_config.h index 5247c32e1..1583f4445 100644 --- a/examples/monolithic_build_multilevel/mldsa_native/mldsa_native_config.h +++ b/examples/monolithic_build_multilevel/mldsa_native/mldsa_native_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/monolithic_build_multilevel_native/mldsa_native/mldsa_native_config.h b/examples/monolithic_build_multilevel_native/mldsa_native/mldsa_native_config.h index 99d7142b9..bfdc4dbc9 100644 --- a/examples/monolithic_build_multilevel_native/mldsa_native/mldsa_native_config.h +++ b/examples/monolithic_build_multilevel_native/mldsa_native/mldsa_native_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -424,9 +424,9 @@ #include #include "src/sys.h" #include "test_only_rng/notrandombytes.h" -static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) +static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { - randombytes(ptr, len); + return randombytes(ptr, len); } #endif /* !__ASSEMBLER__ */ diff --git a/examples/monolithic_build_native/mldsa_native/mldsa_native_config.h b/examples/monolithic_build_native/mldsa_native/mldsa_native_config.h index 6b628a326..76961d468 100644 --- a/examples/monolithic_build_native/mldsa_native/mldsa_native_config.h +++ b/examples/monolithic_build_native/mldsa_native/mldsa_native_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/multilevel_build/mldsa_native/mldsa_native_config.h b/examples/multilevel_build/mldsa_native/mldsa_native_config.h index 7af428134..6ffd67951 100644 --- a/examples/multilevel_build/mldsa_native/mldsa_native_config.h +++ b/examples/multilevel_build/mldsa_native/mldsa_native_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/examples/multilevel_build_native/mldsa_native/mldsa_native_config.h b/examples/multilevel_build_native/mldsa_native/mldsa_native_config.h index edf3a9074..431f50bf9 100644 --- a/examples/multilevel_build_native/mldsa_native/mldsa_native_config.h +++ b/examples/multilevel_build_native/mldsa_native/mldsa_native_config.h @@ -403,7 +403,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -414,9 +414,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/integration/liboqs/config_aarch64.h b/integration/liboqs/config_aarch64.h index 4092bd0ab..101846da9 100644 --- a/integration/liboqs/config_aarch64.h +++ b/integration/liboqs/config_aarch64.h @@ -162,7 +162,7 @@ * consumer. * * If this option is not set, mlkem-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mlk_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -174,9 +174,10 @@ #include #include #include "../../mldsa/src/sys.h" -static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) +static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { OQS_randombytes(ptr, len); + return 0; } #endif /* !__ASSEMBLER__ */ diff --git a/integration/liboqs/config_c.h b/integration/liboqs/config_c.h index e68375c0a..eff850f4a 100644 --- a/integration/liboqs/config_c.h +++ b/integration/liboqs/config_c.h @@ -166,7 +166,7 @@ * consumer. * * If this option is not set, mlkem-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mlk_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -178,9 +178,10 @@ #include #include #include "../../mldsa/src/sys.h" -static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) +static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { OQS_randombytes(ptr, len); + return 0; } #endif /* !__ASSEMBLER__ */ diff --git a/integration/liboqs/config_x86_64.h b/integration/liboqs/config_x86_64.h index 40b3f2f5f..14737d449 100644 --- a/integration/liboqs/config_x86_64.h +++ b/integration/liboqs/config_x86_64.h @@ -164,7 +164,7 @@ * consumer. * * If this option is not set, mlkem-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mlk_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -176,9 +176,10 @@ #include #include #include "../../mldsa/src/sys.h" -static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) +static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { OQS_randombytes(ptr, len); + return 0; } #endif /* !__ASSEMBLER__ */ diff --git a/mldsa/mldsa_native.S b/mldsa/mldsa_native.S index 8428fc58a..54e55c931 100644 --- a/mldsa/mldsa_native.S +++ b/mldsa/mldsa_native.S @@ -174,6 +174,7 @@ #undef MLD_DOMAIN_SEPARATION_MAX_BYTES #undef MLD_ERR_FAIL #undef MLD_ERR_OUT_OF_MEMORY +#undef MLD_ERR_RNG_FAIL #undef MLD_H #undef MLD_PREHASH_NONE #undef MLD_PREHASH_SHA2_224 @@ -205,6 +206,7 @@ #undef MLD_EMPTY_CU #undef MLD_ERR_FAIL #undef MLD_ERR_OUT_OF_MEMORY +#undef MLD_ERR_RNG_FAIL #undef MLD_EXTERNAL_API #undef MLD_FIPS202X4_HEADER_FILE #undef MLD_FIPS202_HEADER_FILE diff --git a/mldsa/mldsa_native.c b/mldsa/mldsa_native.c index 9396a7efd..8047ff46e 100644 --- a/mldsa/mldsa_native.c +++ b/mldsa/mldsa_native.c @@ -170,6 +170,7 @@ #undef MLD_DOMAIN_SEPARATION_MAX_BYTES #undef MLD_ERR_FAIL #undef MLD_ERR_OUT_OF_MEMORY +#undef MLD_ERR_RNG_FAIL #undef MLD_H #undef MLD_PREHASH_NONE #undef MLD_PREHASH_SHA2_224 @@ -201,6 +202,7 @@ #undef MLD_EMPTY_CU #undef MLD_ERR_FAIL #undef MLD_ERR_OUT_OF_MEMORY +#undef MLD_ERR_RNG_FAIL #undef MLD_EXTERNAL_API #undef MLD_FIPS202X4_HEADER_FILE #undef MLD_FIPS202_HEADER_FILE diff --git a/mldsa/mldsa_native.h b/mldsa/mldsa_native.h index ecd83a7ce..1e83e2101 100644 --- a/mldsa/mldsa_native.h +++ b/mldsa/mldsa_native.h @@ -129,6 +129,9 @@ /* An allocation failed. This can only happen if MLD_CONFIG_CUSTOM_ALLOC_FREE * is defined and the provided MLD_CUSTOM_ALLOC can fail. */ #define MLD_ERR_OUT_OF_MEMORY -2 +/* An rng failure occured. Might be due to insufficient entropy or + * system misconfiguration. */ +#define MLD_ERR_RNG_FAIL -3 /****************************** Function API **********************************/ @@ -215,6 +218,7 @@ * - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. + * - MLD_ERR_RNG_FAIL: Random number generation failed. * - MLD_ERR_FAIL: Other kinds of failure, incl. PCT failure * if MLD_CONFIG_KEYGEN_PCT is enabled. * @@ -242,10 +246,11 @@ int MLD_API_NAMESPACE(keypair_internal)( * output private key * * Returns: - 0: Success - * - MLD_ERR_FAIL: If MLD_CONFIG_KEYGEN_PCT is enabled and the - * PCT check failed. * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. + * - MLD_ERR_RNG_FAIL: Random number generation failed. + * - MLD_ERR_FAIL: If MLD_CONFIG_KEYGEN_PCT is enabled and the + * PCT check failed. * * Specification: Implements @[FIPS204 Algorithm 1 (ML-DSA.KeyGen)] * @@ -321,7 +326,8 @@ int MLD_API_NAMESPACE(signature_internal)( * - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. - * - MLD_ERR_FAIL: Other kinds of failure + * - MLD_ERR_RNG_FAIL: Random number generation failed. + * - MLD_ERR_FAIL: Other kinds of failure. * * Specification: Implements @[FIPS204 Algorithm 2 (ML-DSA.Sign)] * @@ -351,7 +357,8 @@ int MLD_API_NAMESPACE(signature)( * - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. - * - MLD_ERR_FAIL: Other kinds of failure + * - MLD_ERR_RNG_FAIL: Random number generation failed. + * - MLD_ERR_FAIL: Other kinds of failure. * * Specification: Implements @[FIPS204 Algorithm 2 (ML-DSA.Sign external mu * variant)] diff --git a/mldsa/mldsa_native_config.h b/mldsa/mldsa_native_config.h index 98e87a38a..ccfab6575 100644 --- a/mldsa/mldsa_native_config.h +++ b/mldsa/mldsa_native_config.h @@ -390,7 +390,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -401,9 +401,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/mldsa/src/common.h b/mldsa/src/common.h index 02a73a8e5..6d96d3024 100644 --- a/mldsa/src/common.h +++ b/mldsa/src/common.h @@ -226,6 +226,10 @@ /* An allocation failed. This can only happen if MLD_CONFIG_CUSTOM_ALLOC_FREE * is defined and the provided MLD_CUSTOM_ALLOC can fail. */ #define MLD_ERR_OUT_OF_MEMORY -2 +/* An rng failure occured. Might be due to insufficient entropy or + * system misconfiguration. */ +#define MLD_ERR_RNG_FAIL -3 + #endif /* !__ASSEMBLER__ */ diff --git a/mldsa/src/randombytes.h b/mldsa/src/randombytes.h index 801bcbaa9..da5577241 100644 --- a/mldsa/src/randombytes.h +++ b/mldsa/src/randombytes.h @@ -13,12 +13,13 @@ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API) #if !defined(MLD_CONFIG_CUSTOM_RANDOMBYTES) -void randombytes(uint8_t *out, size_t outlen); -static MLD_INLINE void mld_randombytes(uint8_t *out, size_t outlen) +MLD_MUST_CHECK_RETURN_VALUE +int randombytes(uint8_t *out, size_t outlen); +static MLD_INLINE int mld_randombytes(uint8_t *out, size_t outlen) __contract__( requires(memory_no_alias(out, outlen)) assigns(memory_slice(out, outlen)) -) { randombytes(out, outlen); } +) { return randombytes(out, outlen); } #endif /* !MLD_CONFIG_CUSTOM_RANDOMBYTES */ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */ #endif /* !MLD_RANDOMBYTES_H */ diff --git a/mldsa/src/sign.c b/mldsa/src/sign.c index 2896cf2b6..d3457ea6e 100644 --- a/mldsa/src/sign.c +++ b/mldsa/src/sign.c @@ -61,7 +61,8 @@ __contract__( requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES)) ensures(return_value == 0 || return_value == MLD_ERR_FAIL - || return_value == MLD_ERR_OUT_OF_MEMORY) + || return_value == MLD_ERR_OUT_OF_MEMORY + || return_value == MLD_ERR_RNG_FAIL) ); #if defined(MLD_CONFIG_KEYGEN_PCT) @@ -360,10 +361,15 @@ int crypto_sign_keypair(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], { MLD_ALIGN uint8_t seed[MLDSA_SEEDBYTES]; int ret; - mld_randombytes(seed, MLDSA_SEEDBYTES); + if (mld_randombytes(seed, MLDSA_SEEDBYTES) != 0) + { + ret = MLD_ERR_RNG_FAIL; + goto cleanup; + } MLD_CT_TESTING_SECRET(seed, sizeof(seed)); ret = crypto_sign_keypair_internal(pk, sk, seed); +cleanup: /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */ mld_zeroize(seed, sizeof(seed)); return ret; @@ -789,7 +795,11 @@ int crypto_sign_signature(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, /* Randomized variant of ML-DSA. If you need the deterministic variant, * call crypto_sign_signature_internal directly with all-zero rnd. */ - mld_randombytes(rnd, MLDSA_RNDBYTES); + if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0) + { + ret = MLD_ERR_RNG_FAIL; + goto cleanup; + } MLD_CT_TESTING_SECRET(rnd, sizeof(rnd)); ret = crypto_sign_signature_internal(sig, siglen, m, mlen, pre, pre_len, rnd, @@ -828,12 +838,18 @@ int crypto_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, /* Randomized variant of ML-DSA. If you need the deterministic variant, * call crypto_sign_signature_internal directly with all-zero rnd. */ - mld_randombytes(rnd, MLDSA_RNDBYTES); + if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0) + { + *siglen = 0; + ret = MLD_ERR_RNG_FAIL; + goto cleanup; + } MLD_CT_TESTING_SECRET(rnd, sizeof(rnd)); ret = crypto_sign_signature_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0, rnd, sk, 1); +cleanup: /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */ mld_zeroize(rnd, sizeof(rnd)); diff --git a/mldsa/src/sign.h b/mldsa/src/sign.h index 03cb077f2..27d2b9cae 100644 --- a/mldsa/src/sign.h +++ b/mldsa/src/sign.h @@ -99,6 +99,7 @@ * Returns: - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. + * - MLD_ERR_RNG_FAIL: Random number generation failed. * - MLD_ERR_FAIL: Other kinds of failure, incl. PCT failure * if MLD_CONFIG_KEYGEN_PCT is enabled. * @@ -117,7 +118,7 @@ __contract__( assigns(object_whole(pk)) assigns(object_whole(sk)) ensures(return_value == 0 || return_value == MLD_ERR_FAIL || - return_value == MLD_ERR_OUT_OF_MEMORY) + return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_RNG_FAIL) ); /************************************************* @@ -133,6 +134,7 @@ __contract__( * Returns: - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. + * - MLD_ERR_RNG_FAIL: Random number generation failed. * - MLD_ERR_FAIL: Other kinds of failure, incl. PCT failure * if MLD_CONFIG_KEYGEN_PCT is enabled. * @@ -149,7 +151,7 @@ __contract__( assigns(object_whole(pk)) assigns(object_whole(sk)) ensures(return_value == 0 || return_value == MLD_ERR_FAIL || - return_value == MLD_ERR_OUT_OF_MEMORY) + return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_RNG_FAIL) ); /************************************************* @@ -230,7 +232,8 @@ __contract__( * Returns: - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. - * - MLD_ERR_FAIL: Other kinds of failure + * - MLD_ERR_RNG_FAIL: Random number generation failed. + * - MLD_ERR_FAIL: Other kinds of failure. * * Specification: Implements @[FIPS204 Algorithm 2 (ML-DSA.Sign)]. * @@ -252,7 +255,7 @@ __contract__( assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES)) assigns(object_whole(siglen)) ensures((return_value == 0 && *siglen == MLDSA_CRYPTO_BYTES) || - ((return_value == MLD_ERR_FAIL || return_value == MLD_ERR_OUT_OF_MEMORY) && *siglen == 0)) + ((return_value == MLD_ERR_FAIL || return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_RNG_FAIL) && *siglen == 0)) ); /************************************************* @@ -273,7 +276,8 @@ __contract__( * Returns: - 0: Success * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is * used and an allocation via MLD_CUSTOM_ALLOC returned NULL. - * - MLD_ERR_FAIL: Other kinds of failure + * - MLD_ERR_RNG_FAIL: Random number generation failed. + * - MLD_ERR_FAIL: Other kinds of failure. * * Specification: Implements @[FIPS204 Algorithm 2 (ML-DSA.Sign external mu * variant)] @@ -292,7 +296,7 @@ __contract__( assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES)) assigns(object_whole(siglen)) ensures((return_value == 0 && *siglen == MLDSA_CRYPTO_BYTES) || - ((return_value == MLD_ERR_FAIL || return_value == MLD_ERR_OUT_OF_MEMORY) && *siglen == 0)) + ((return_value == MLD_ERR_FAIL || return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_RNG_FAIL) && *siglen == 0)) ); /************************************************* @@ -333,7 +337,9 @@ __contract__( assigns(memory_slice(sm, MLDSA_CRYPTO_BYTES + mlen)) assigns(object_whole(smlen)) ensures((return_value == 0 && *smlen == MLDSA_CRYPTO_BYTES + mlen) || - (return_value == MLD_ERR_FAIL || return_value == MLD_ERR_OUT_OF_MEMORY)) + (return_value == MLD_ERR_FAIL + || return_value == MLD_ERR_OUT_OF_MEMORY + || return_value == MLD_ERR_RNG_FAIL)) ); /************************************************* diff --git a/scripts/tests b/scripts/tests index 840678c54..9a51f006d 100755 --- a/scripts/tests +++ b/scripts/tests @@ -214,6 +214,7 @@ class TEST_TYPES(Enum): UNIT = 19 ALLOC = 20 BASIC_LOWRAM = 21 + RNG_FAIL = 22 def is_benchmark(self): return self in [TEST_TYPES.BENCH, TEST_TYPES.BENCH_COMPONENTS] @@ -293,6 +294,8 @@ class TEST_TYPES(Enum): return "Unit Test" if self == TEST_TYPES.ALLOC: return "Alloc Test" + if self == TEST_TYPES.RNG_FAIL: + return "RNG Failure Test" def make_dir(self): if self == TEST_TYPES.BRING_YOUR_OWN_FIPS202: @@ -364,6 +367,8 @@ class TEST_TYPES(Enum): return "unit" if self == TEST_TYPES.ALLOC: return "alloc" + if self == TEST_TYPES.RNG_FAIL: + return "rng_fail" def make_run_target(self, scheme): t = self.make_target() @@ -676,6 +681,19 @@ class Tests: self.check_fail() + def rng_fail(self): + def _rng_fail(opt): + self._compile_schemes(TEST_TYPES.RNG_FAIL, opt) + if self.args.run: + self._run_schemes(TEST_TYPES.RNG_FAIL, opt) + + if self.do_no_opt(): + _rng_fail(False) + if self.do_opt(): + _rng_fail(True) + + self.check_fail() + def acvp(self): def _acvp(opt): self._compile_schemes(TEST_TYPES.ACVP, opt) @@ -811,6 +829,7 @@ class Tests: stack = self.args.stack unit = self.args.unit alloc = self.args.alloc + rng_fail = self.args.rng_fail def _all(opt): if func is True: @@ -825,6 +844,8 @@ class Tests: self._compile_schemes(TEST_TYPES.UNIT, opt) if alloc is True: self._compile_schemes(TEST_TYPES.ALLOC, opt) + if rng_fail is True: + self._compile_schemes(TEST_TYPES.RNG_FAIL, opt) if self.args.check_namespace is True: p = subprocess.run( @@ -850,6 +871,8 @@ class Tests: self._run_schemes(TEST_TYPES.UNIT, opt) if alloc is True: self._run_schemes(TEST_TYPES.ALLOC, opt) + if rng_fail is True: + self._run_schemes(TEST_TYPES.RNG_FAIL, opt) if self.do_no_opt(): _all(False) @@ -1239,6 +1262,21 @@ def cli(): help="Do not run alloc tests", ) + rng_fail_group = all_parser.add_mutually_exclusive_group() + rng_fail_group.add_argument( + "--rng-fail", + action="store_true", + dest="rng_fail", + help="Run RNG failure tests", + default=True, + ) + rng_fail_group.add_argument( + "--no-rng-fail", + action="store_false", + dest="rng_fail", + help="Do not run RNG failure tests", + ) + # acvp arguments acvp_parser = cmd_subparsers.add_parser( "acvp", help="Run ACVP client", parents=[common_parser] @@ -1453,6 +1491,13 @@ def cli(): parents=[common_parser], ) + # rng_fail arguments + rng_fail_parser = cmd_subparsers.add_parser( + "rng_fail", + help="Run the RNG failure tests for all parameter sets", + parents=[common_parser], + ) + args = main_parser.parse_args() if not hasattr(args, "mac_taskpolicy"): @@ -1486,6 +1531,8 @@ def cli(): Tests(args).size() elif args.cmd == "alloc": Tests(args).alloc() + elif args.cmd == "rng_fail": + Tests(args).rng_fail() if __name__ == "__main__": diff --git a/test/bench_components_mldsa.c b/test/bench_components_mldsa.c index b633e57fa..fea6f44e2 100644 --- a/test/bench_components_mldsa.c +++ b/test/bench_components_mldsa.c @@ -17,32 +17,44 @@ #define NITERATIONS 300 #define NTESTS 20 +#define CHECK(x) \ + do \ + { \ + int rc; \ + rc = (x); \ + if (!rc) \ + { \ + fprintf(stderr, "ERROR (%s,%d)\n", __FILE__, __LINE__); \ + return 1; \ + } \ + } while (0) + static int cmp_uint64_t(const void *a, const void *b) { return (int)((*((const uint64_t *)a)) - (*((const uint64_t *)b))); } -#define BENCH(txt, code) \ - for (i = 0; i < NTESTS; i++) \ - { \ - mld_randombytes((uint8_t *)data0, sizeof(data0)); \ - mld_randombytes((uint8_t *)&polyvecl_a, sizeof(polyvecl_a)); \ - mld_randombytes((uint8_t *)&polyvecl_b, sizeof(polyvecl_b)); \ - mld_randombytes((uint8_t *)&polymat, sizeof(polymat)); \ - for (j = 0; j < NWARMUP; j++) \ - { \ - code; \ - } \ - \ - t0 = get_cyclecounter(); \ - for (j = 0; j < NITERATIONS; j++) \ - { \ - code; \ - } \ - t1 = get_cyclecounter(); \ - (cyc)[i] = t1 - t0; \ - } \ - qsort((cyc), NTESTS, sizeof(uint64_t), cmp_uint64_t); \ +#define BENCH(txt, code) \ + for (i = 0; i < NTESTS; i++) \ + { \ + CHECK(mld_randombytes((uint8_t *)data0, sizeof(data0)) == 0); \ + CHECK(mld_randombytes((uint8_t *)&polyvecl_a, sizeof(polyvecl_a)) == 0); \ + CHECK(mld_randombytes((uint8_t *)&polyvecl_b, sizeof(polyvecl_b)) == 0); \ + CHECK(mld_randombytes((uint8_t *)&polymat, sizeof(polymat)) == 0); \ + for (j = 0; j < NWARMUP; j++) \ + { \ + code; \ + } \ + \ + t0 = get_cyclecounter(); \ + for (j = 0; j < NITERATIONS; j++) \ + { \ + code; \ + } \ + t1 = get_cyclecounter(); \ + (cyc)[i] = t1 - t0; \ + } \ + qsort((cyc), NTESTS, sizeof(uint64_t), cmp_uint64_t); \ printf(txt " cycles=%" PRIu64 "\n", (cyc)[NTESTS >> 1] / NITERATIONS); static int bench(void) diff --git a/test/bench_mldsa.c b/test/bench_mldsa.c index 7cb068e09..835e5b1e5 100644 --- a/test/bench_mldsa.c +++ b/test/bench_mldsa.c @@ -91,8 +91,8 @@ static int bench(void) for (i = 0; i < NTESTS; i++) { int ret = 0; - mld_randombytes(kg_rand, sizeof(kg_rand)); - mld_randombytes(sig_rand, sizeof(sig_rand)); + CHECK(mld_randombytes(kg_rand, sizeof(kg_rand)) == 0); + CHECK(mld_randombytes(sig_rand, sizeof(sig_rand)) == 0); /* Key-pair generation */ @@ -111,8 +111,8 @@ static int bench(void) /* Signing */ - mld_randombytes(ctx, CTXLEN); - mld_randombytes(m, MLEN); + CHECK(mld_randombytes(ctx, CTXLEN) == 0); + CHECK(mld_randombytes(m, MLEN) == 0); pre[0] = 0; pre[1] = CTXLEN; diff --git a/test/break_pct_config.h b/test/break_pct_config.h index 74de94f0d..2b6827163 100644 --- a/test/break_pct_config.h +++ b/test/break_pct_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/configs.yml b/test/configs.yml index 2e8ba5cf1..0e81b00f7 100644 --- a/test/configs.yml +++ b/test/configs.yml @@ -38,9 +38,9 @@ configs: #include #include "../mldsa/src/sys.h" #include "notrandombytes/notrandombytes.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { - randombytes(ptr, len); + return randombytes(ptr, len); } #endif /* !__ASSEMBLER__ */ @@ -350,9 +350,9 @@ configs: #include #include "src/sys.h" #include "test_only_rng/notrandombytes.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { - randombytes(ptr, len); + return randombytes(ptr, len); } #endif /* !__ASSEMBLER__ */ @@ -426,3 +426,19 @@ configs: #endif /* !__ASSEMBLER__ */ MLD_CONFIG_FILE: comment: "/* No need to set this -- we _are_ already in a custom config */" + + - path: test/test_rng_fail_config.h + description: "Using custom randombytes that can fail at specific invocation" + defines: + MLD_CONFIG_NAMESPACE_PREFIX: mld + MLD_CONFIG_CUSTOM_RANDOMBYTES: + content: | + #define MLD_CONFIG_CUSTOM_RANDOMBYTES + #if !defined(__ASSEMBLER__) + #include + #include + #include "src/sys.h" + int mld_randombytes(uint8_t *out, size_t outlen); + #endif + MLD_CONFIG_FILE: + comment: "/* No need to set this -- we _are_ already in a custom config */" diff --git a/test/custom_heap_alloc_config.h b/test/custom_heap_alloc_config.h index 134c22532..3666c254c 100644 --- a/test/custom_heap_alloc_config.h +++ b/test/custom_heap_alloc_config.h @@ -403,7 +403,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name diff --git a/test/custom_memcpy_config.h b/test/custom_memcpy_config.h index a3993cd03..92a38abeb 100644 --- a/test/custom_memcpy_config.h +++ b/test/custom_memcpy_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_memset_config.h b/test/custom_memset_config.h index 7b1e5d6c7..1b7796444 100644 --- a/test/custom_memset_config.h +++ b/test/custom_memset_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_native_capability_config_0.h b/test/custom_native_capability_config_0.h index 56fc43c43..d03619f0f 100644 --- a/test/custom_native_capability_config_0.h +++ b/test/custom_native_capability_config_0.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_native_capability_config_1.h b/test/custom_native_capability_config_1.h index 4123aa008..b3370e252 100644 --- a/test/custom_native_capability_config_1.h +++ b/test/custom_native_capability_config_1.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_native_capability_config_CPUID_AVX2.h b/test/custom_native_capability_config_CPUID_AVX2.h index 585d6cd3f..3506197bb 100644 --- a/test/custom_native_capability_config_CPUID_AVX2.h +++ b/test/custom_native_capability_config_CPUID_AVX2.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_native_capability_config_ID_AA64PFR1_EL1.h b/test/custom_native_capability_config_ID_AA64PFR1_EL1.h index 1eb1040c6..3ad3d430a 100644 --- a/test/custom_native_capability_config_ID_AA64PFR1_EL1.h +++ b/test/custom_native_capability_config_ID_AA64PFR1_EL1.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_randombytes_config.h b/test/custom_randombytes_config.h index 02dde05dd..09660d77e 100644 --- a/test/custom_randombytes_config.h +++ b/test/custom_randombytes_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,9 @@ #include #include "../mldsa/src/sys.h" #include "notrandombytes/notrandombytes.h" -static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) +static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { - randombytes(ptr, len); + return randombytes(ptr, len); } #endif /* !__ASSEMBLER__ */ diff --git a/test/custom_stdlib_config.h b/test/custom_stdlib_config.h index 1be9ecc3a..7a147c885 100644 --- a/test/custom_stdlib_config.h +++ b/test/custom_stdlib_config.h @@ -406,7 +406,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/custom_zeroize_config.h b/test/custom_zeroize_config.h index ac3861fdf..e3a9c24a9 100644 --- a/test/custom_zeroize_config.h +++ b/test/custom_zeroize_config.h @@ -406,7 +406,7 @@ static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len) * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -417,9 +417,10 @@ static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len) #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/mk/components.mk b/test/mk/components.mk index c3655fbe1..41e7d31f7 100644 --- a/test/mk/components.mk +++ b/test/mk/components.mk @@ -14,7 +14,7 @@ ifeq ($(OPT),1) CFLAGS += -DMLD_CONFIG_USE_NATIVE_BACKEND_ARITH -DMLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 endif -ALL_TESTS = test_mldsa test_unit acvp_mldsa bench_mldsa bench_components_mldsa gen_KAT test_stack test_alloc +ALL_TESTS = test_mldsa test_unit acvp_mldsa bench_mldsa bench_components_mldsa gen_KAT test_stack test_alloc test_rng_fail MLDSA44_DIR = $(BUILD_DIR)/mldsa44 MLDSA65_DIR = $(BUILD_DIR)/mldsa65 @@ -43,6 +43,13 @@ $(MLDSA65_ALLOC_OBJS): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=65 -DMLD_CONFIG_FILE MLDSA87_ALLOC_OBJS = $(call MAKE_OBJS,$(MLDSA87_DIR)/alloc,$(SOURCES) $(FIPS202_SRCS)) $(MLDSA87_ALLOC_OBJS): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=87 -DMLD_CONFIG_FILE=\"../test/test_alloc_config.h\" +# RNG fail test object files - same sources but with custom randombytes config +MLDSA44_RNG_FAIL_OBJS = $(call MAKE_OBJS,$(MLDSA44_DIR)/rng_fail,$(SOURCES) $(FIPS202_SRCS)) +$(MLDSA44_RNG_FAIL_OBJS): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=44 -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" +MLDSA65_RNG_FAIL_OBJS = $(call MAKE_OBJS,$(MLDSA65_DIR)/rng_fail,$(SOURCES) $(FIPS202_SRCS)) +$(MLDSA65_RNG_FAIL_OBJS): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=65 -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" +MLDSA87_RNG_FAIL_OBJS = $(call MAKE_OBJS,$(MLDSA87_DIR)/rng_fail,$(SOURCES) $(FIPS202_SRCS)) +$(MLDSA87_RNG_FAIL_OBJS): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=87 -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" CFLAGS += -Imldsa @@ -61,6 +68,10 @@ $(BUILD_DIR)/libmldsa44_alloc.a: $(MLDSA44_ALLOC_OBJS) $(BUILD_DIR)/libmldsa65_alloc.a: $(MLDSA65_ALLOC_OBJS) $(BUILD_DIR)/libmldsa87_alloc.a: $(MLDSA87_ALLOC_OBJS) +# RNG fail test libraries with custom randombytes config +$(BUILD_DIR)/libmldsa44_rng_fail.a: $(MLDSA44_RNG_FAIL_OBJS) +$(BUILD_DIR)/libmldsa65_rng_fail.a: $(MLDSA65_RNG_FAIL_OBJS) +$(BUILD_DIR)/libmldsa87_rng_fail.a: $(MLDSA87_RNG_FAIL_OBJS) $(BUILD_DIR)/libmldsa.a: $(MLDSA44_OBJS) $(MLDSA65_OBJS) $(MLDSA87_OBJS) @@ -79,6 +90,10 @@ $(MLDSA44_DIR)/test/test_alloc.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_a $(MLDSA65_DIR)/test/test_alloc.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_alloc_config.h\" $(MLDSA87_DIR)/test/test_alloc.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_alloc_config.h\" +$(MLDSA44_DIR)/test/test_rng_fail.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" +$(MLDSA65_DIR)/test/test_rng_fail.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" +$(MLDSA87_DIR)/test/test_rng_fail.c.o: CFLAGS += -DMLD_CONFIG_FILE=\"../test/test_rng_fail_config.h\" + $(MLDSA44_DIR)/bin/test_unit44: CFLAGS += -DMLD_STATIC_TESTABLE= -Wno-missing-prototypes $(MLDSA65_DIR)/bin/test_unit65: CFLAGS += -DMLD_STATIC_TESTABLE= -Wno-missing-prototypes $(MLDSA87_DIR)/bin/test_unit87: CFLAGS += -DMLD_STATIC_TESTABLE= -Wno-missing-prototypes @@ -119,9 +134,14 @@ $(BUILD_DIR)/$(1)/bin/test_alloc$(subst mldsa,,$(1)): LDLIBS += -L$(BUILD_DIR) - $(BUILD_DIR)/$(1)/bin/test_alloc$(subst mldsa,,$(1)): $(BUILD_DIR)/$(1)/test/test_alloc.c.o $(BUILD_DIR)/lib$(1)_alloc.a $(call MAKE_OBJS, $(BUILD_DIR)/$(1), $(wildcard test/notrandombytes/*.c)) endef +# Special rule for test_rng_fail - link against rng_fail libraries with custom randombytes config +define ADD_SOURCE_RNG_FAIL +$(BUILD_DIR)/$(1)/bin/test_rng_fail$(subst mldsa,,$(1)): LDLIBS += -L$(BUILD_DIR) -l$(1)_rng_fail +$(BUILD_DIR)/$(1)/bin/test_rng_fail$(subst mldsa,,$(1)): $(BUILD_DIR)/$(1)/test/test_rng_fail.c.o $(BUILD_DIR)/lib$(1)_rng_fail.a +endef $(foreach scheme,mldsa44 mldsa65 mldsa87, \ - $(foreach test,$(filter-out test_unit test_alloc,$(ALL_TESTS)), \ + $(foreach test,$(filter-out test_unit test_alloc test_rng_fail,$(ALL_TESTS)), \ $(eval $(call ADD_SOURCE,$(scheme),$(test))) \ ) \ ) @@ -134,6 +154,10 @@ $(foreach scheme,mldsa44 mldsa65 mldsa87, \ $(eval $(call ADD_SOURCE_ALLOC,$(scheme))) \ ) +$(foreach scheme,mldsa44 mldsa65 mldsa87, \ + $(eval $(call ADD_SOURCE_RNG_FAIL,$(scheme))) \ +) + $(ALL_TESTS:%=$(MLDSA44_DIR)/bin/%44): $(call MAKE_OBJS, $(MLDSA44_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) $(ALL_TESTS:%=$(MLDSA65_DIR)/bin/%65): $(call MAKE_OBJS, $(MLDSA65_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) $(ALL_TESTS:%=$(MLDSA87_DIR)/bin/%87): $(call MAKE_OBJS, $(MLDSA87_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) diff --git a/test/mk/rules.mk b/test/mk/rules.mk index e4447ebc6..164044ff8 100644 --- a/test/mk/rules.mk +++ b/test/mk/rules.mk @@ -113,3 +113,34 @@ $(BUILD_DIR)/mldsa87/alloc/%.S.o: %.S $(CONFIG) $(Q)echo " AS $@" $(Q)[ -d $(@D) ] || mkdir -p $(@D) $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa44/rng_fail/%.c.o: %.c $(CONFIG) + $(Q)echo " CC $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa44/rng_fail/%.S.o: %.S $(CONFIG) + $(Q)echo " AS $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa65/rng_fail/%.c.o: %.c $(CONFIG) + $(Q)echo " CC $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa65/rng_fail/%.S.o: %.S $(CONFIG) + $(Q)echo " AS $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa87/rng_fail/%.c.o: %.c $(CONFIG) + $(Q)echo " CC $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +$(BUILD_DIR)/mldsa87/rng_fail/%.S.o: %.S $(CONFIG) + $(Q)echo " AS $@" + $(Q)[ -d $(@D) ] || mkdir -p $(@D) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + diff --git a/test/no_asm_config.h b/test/no_asm_config.h index 77d598a35..1e96cb583 100644 --- a/test/no_asm_config.h +++ b/test/no_asm_config.h @@ -407,7 +407,7 @@ static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len) * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -418,9 +418,10 @@ static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len) #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/notrandombytes/notrandombytes.c b/test/notrandombytes/notrandombytes.c index e8bfc8037..ef5a423a9 100644 --- a/test/notrandombytes/notrandombytes.c +++ b/test/notrandombytes/notrandombytes.c @@ -90,7 +90,7 @@ static void surf(void) } } -void randombytes(uint8_t *buf, size_t n) +int randombytes(uint8_t *buf, size_t n) { #ifdef ENABLE_CT_TESTING uint8_t *buf_orig = buf; @@ -126,4 +126,5 @@ void randombytes(uint8_t *buf, size_t n) */ VALGRIND_MAKE_MEM_UNDEFINED(buf_orig, n_orig); #endif /* ENABLE_CT_TESTING */ + return 0; } diff --git a/test/notrandombytes/notrandombytes.h b/test/notrandombytes/notrandombytes.h index e330b36c5..bdf978792 100644 --- a/test/notrandombytes/notrandombytes.h +++ b/test/notrandombytes/notrandombytes.h @@ -29,6 +29,6 @@ */ void randombytes_reset(void); -void randombytes(uint8_t *buf, size_t n); +int randombytes(uint8_t *buf, size_t n); #endif /* !NOTRANDOMBYTES_H */ diff --git a/test/serial_fips202_config.h b/test/serial_fips202_config.h index c8be04a1f..857a00675 100644 --- a/test/serial_fips202_config.h +++ b/test/serial_fips202_config.h @@ -405,7 +405,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -416,9 +416,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/test_alloc_config.h b/test/test_alloc_config.h index 4f2d40dbd..f42799b8e 100644 --- a/test/test_alloc_config.h +++ b/test/test_alloc_config.h @@ -407,7 +407,7 @@ * consumer. * * If this option is not set, mldsa-native expects a function - * void randombytes(uint8_t *out, size_t outlen). + * int randombytes(uint8_t *out, size_t outlen). * * Set this option and define `mld_randombytes` if you want to * use a custom method to sample randombytes with a different name @@ -418,9 +418,10 @@ #if !defined(__ASSEMBLER__) #include #include "src/src.h" - static MLD_INLINE void mld_randombytes(uint8_t *ptr, size_t len) + static MLD_INLINE int mld_randombytes(uint8_t *ptr, size_t len) { ... your implementation ... + return 0; } #endif */ diff --git a/test/test_mldsa.c b/test/test_mldsa.c index 5916e45dd..586356a7d 100644 --- a/test/test_mldsa.c +++ b/test/test_mldsa.c @@ -42,9 +42,9 @@ static int test_sign_core(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(ctx, CTXLEN); + CHECK(randombytes(ctx, CTXLEN) == 0); MLD_CT_TESTING_SECRET(ctx, CTXLEN); - randombytes(m, MLEN); + CHECK(randombytes(m, MLEN) == 0); MLD_CT_TESTING_SECRET(m, MLEN); CHECK(crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk) == 0); @@ -116,7 +116,7 @@ static int test_sign_extmu(void) size_t siglen; CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(mu, MLDSA_CRHBYTES); + CHECK(randombytes(mu, MLDSA_CRHBYTES) == 0); MLD_CT_TESTING_SECRET(mu, sizeof(mu)); CHECK(crypto_sign_signature_extmu(sig, &siglen, mu, sk) == 0); @@ -138,11 +138,11 @@ static int test_sign_pre_hash(void) CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(ctx, CTXLEN); + CHECK(randombytes(ctx, CTXLEN) == 0); MLD_CT_TESTING_SECRET(ctx, sizeof(ctx)); - randombytes(m, MLEN); + CHECK(randombytes(m, MLEN) == 0); MLD_CT_TESTING_SECRET(m, sizeof(m)); - randombytes(rnd, MLDSA_RNDBYTES); + CHECK(randombytes(rnd, MLDSA_RNDBYTES) == 0); MLD_CT_TESTING_SECRET(rnd, sizeof(rnd)); CHECK(crypto_sign_signature_pre_hash_shake256(sig, &siglen, m, MLEN, ctx, @@ -227,15 +227,15 @@ static int test_wrong_pk(void) size_t i; CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(ctx, CTXLEN); + CHECK(randombytes(ctx, CTXLEN) == 0); MLD_CT_TESTING_SECRET(ctx, sizeof(ctx)); - randombytes(m, MLEN); + CHECK(randombytes(m, MLEN) == 0); MLD_CT_TESTING_SECRET(m, sizeof(m)); CHECK(crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk) == 0); /* flip bit in public key */ - randombytes((uint8_t *)&idx, sizeof(size_t)); + CHECK(randombytes((uint8_t *)&idx, sizeof(size_t)) == 0); idx %= MLDSA_CRYPTO_PUBLICKEYBYTES; pk[idx] ^= 1; @@ -278,15 +278,15 @@ static int test_wrong_sig(void) size_t i; CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(ctx, CTXLEN); + CHECK(randombytes(ctx, CTXLEN) == 0); MLD_CT_TESTING_SECRET(ctx, sizeof(ctx)); - randombytes(m, MLEN); + CHECK(randombytes(m, MLEN) == 0); MLD_CT_TESTING_SECRET(m, sizeof(m)); CHECK(crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk) == 0); /* flip bit in signed message */ - randombytes((uint8_t *)&idx, sizeof(size_t)); + CHECK(randombytes((uint8_t *)&idx, sizeof(size_t)) == 0); idx %= MLEN + MLDSA_CRYPTO_BYTES; sm[idx] ^= 1; @@ -330,15 +330,15 @@ static int test_wrong_ctx(void) size_t i; CHECK(crypto_sign_keypair(pk, sk) == 0); - randombytes(ctx, CTXLEN); + CHECK(randombytes(ctx, CTXLEN) == 0); MLD_CT_TESTING_SECRET(ctx, sizeof(ctx)); - randombytes(m, MLEN); + CHECK(randombytes(m, MLEN) == 0); MLD_CT_TESTING_SECRET(m, sizeof(m)); CHECK(crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk) == 0); /* flip bit in ctx */ - randombytes((uint8_t *)&idx, sizeof(size_t)); + CHECK(randombytes((uint8_t *)&idx, sizeof(size_t)) == 0); idx %= CTXLEN; ctx[idx] ^= 1; diff --git a/test/test_rng_fail.c b/test/test_rng_fail.c new file mode 100644 index 000000000..d3d273237 --- /dev/null +++ b/test/test_rng_fail.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) The mldsa-native project authors + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + */ +#include +#include +#include + +/* Expose declaration of randombytes (normally internal) */ +#define MLD_BUILD_INTERNAL +#include "../mldsa/mldsa_native.h" +#include "../mldsa/src/common.h" +#include "notrandombytes/notrandombytes.h" + +/* + * This test checks that we handle randombytes failures correctly by: + * - Returning MLD_ERR_RNG_FAIL when randombytes fails + * - Cleaning up all memory when randombytes fails + * + * This is done through a custom randombytes implementation that can be + * configured to fail at specific invocation counts. + */ + +/* + * Randombytes invocation tracker + */ + +int randombytes_counter = 0; +int randombytes_fail_on_counter = -1; + +static void reset_all(void) +{ + randombytes_reset(); + randombytes_counter = 0; + randombytes_fail_on_counter = -1; +} + +int mld_randombytes(uint8_t *out, size_t outlen) +{ + int current_invocation = randombytes_counter++; + + if (current_invocation == randombytes_fail_on_counter) + { + return -1; + } + + return randombytes(out, outlen); +} + +#define TEST_RNG_FAILURE(test_name, call) \ + do \ + { \ + int num_randombytes_calls, i, rc; \ + /* First pass: count randombytes invocations */ \ + reset_all(); \ + rc = call; \ + if (rc != 0) \ + { \ + fprintf(stderr, \ + "ERROR: %s failed with return code %d " \ + "in dry-run\n", \ + test_name, rc); \ + return 1; \ + } \ + num_randombytes_calls = randombytes_counter; \ + if (num_randombytes_calls == 0) \ + { \ + printf("Skipping %s (no randombytes() calls)\n", test_name); \ + break; \ + } \ + /* Second pass: test each randombytes failure */ \ + for (i = 0; i < num_randombytes_calls; i++) \ + { \ + reset_all(); \ + randombytes_fail_on_counter = i; \ + rc = call; \ + if (rc != MLD_ERR_RNG_FAIL) \ + { \ + int rc2; \ + /* Re-run to ensure clean state */ \ + reset_all(); \ + rc2 = call; \ + (void)rc2; \ + if (rc == 0) \ + { \ + fprintf(stderr, \ + "ERROR: %s unexpectedly succeeded when randombytes " \ + "%d/%d was instrumented to fail\n", \ + test_name, i + 1, num_randombytes_calls); \ + } \ + else \ + { \ + fprintf(stderr, \ + "ERROR: %s failed with wrong error code %d " \ + "(expected %d) when randombytes %d/%d was " \ + "instrumented to fail\n", \ + test_name, rc, MLD_ERR_RNG_FAIL, i + 1, \ + num_randombytes_calls); \ + } \ + return 1; \ + } \ + } \ + printf( \ + "RNG failure test for %s PASSED.\n" \ + " Tested %d randombytes invocation point(s)\n", \ + test_name, num_randombytes_calls); \ + } while (0) + +static int test_keygen_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + + TEST_RNG_FAILURE("mld_keypair", mld_keypair(pk, sk)); + return 0; +} + +static int test_sign_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t msg[32] = {0}; + const uint8_t ctx[] = "test context"; + size_t siglen; + + /* Generate valid keypair first */ + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: mld_keypair failed in sign test setup\n"); + return 1; + } + + TEST_RNG_FAILURE( + "mld_signature", + mld_signature(sig, &siglen, msg, sizeof(msg), ctx, sizeof(ctx) - 1, sk)); + return 0; +} + +static int test_verify_rng_failure(void) +{ + uint8_t pk[MLDSA_PUBLICKEYBYTES(MLD_CONFIG_API_PARAMETER_SET)]; + uint8_t sk[MLDSA_SECRETKEYBYTES(MLD_CONFIG_API_PARAMETER_SET)]; + uint8_t sig[MLDSA_BYTES(MLD_CONFIG_API_PARAMETER_SET)]; + size_t siglen; + uint8_t msg[32] = {0}; + uint8_t ctx[10] = "test"; + + /* Generate valid keypair and signature first */ + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: crypto_sign_keypair failed in verify test setup\n"); + return 1; + } + + if (mld_signature(sig, &siglen, msg, sizeof(msg), ctx, sizeof(ctx), sk) != 0) + { + fprintf(stderr, + "ERROR: crypto_sign_signature failed in verify test setup\n"); + return 1; + } + + TEST_RNG_FAILURE( + "crypto_sign_verify", + mld_verify(sig, siglen, msg, sizeof(msg), ctx, sizeof(ctx), pk)); + return 0; +} + +static int test_sign_combined_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sm[CRYPTO_BYTES + 32]; + uint8_t msg[32] = {0}; + const uint8_t ctx[] = "test context"; + size_t smlen; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: mld_keypair failed in sign combined test setup\n"); + return 1; + } + + TEST_RNG_FAILURE("mld_sign", mld_sign(sm, &smlen, msg, sizeof(msg), ctx, + sizeof(ctx) - 1, sk)); + return 0; +} + +static int test_open_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sm[CRYPTO_BYTES + 32]; + uint8_t msg[32] = {0}; + uint8_t msg_out[CRYPTO_BYTES + 32]; + const uint8_t ctx[] = "test context"; + size_t smlen, mlen; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: mld_keypair failed in open test setup\n"); + return 1; + } + + if (mld_sign(sm, &smlen, msg, sizeof(msg), ctx, sizeof(ctx) - 1, sk) != 0) + { + fprintf(stderr, "ERROR: mld_sign failed in open test setup\n"); + return 1; + } + + TEST_RNG_FAILURE("mld_open", mld_open(msg_out, &mlen, sm, smlen, ctx, + sizeof(ctx) - 1, pk)); + return 0; +} + +static int test_signature_extmu_rng_failure(void) +{ + uint8_t pk[MLDSA_PUBLICKEYBYTES(MLD_CONFIG_API_PARAMETER_SET)]; + uint8_t sk[MLDSA_SECRETKEYBYTES(MLD_CONFIG_API_PARAMETER_SET)]; + uint8_t sig[MLDSA_BYTES(MLD_CONFIG_API_PARAMETER_SET)]; + size_t siglen; + uint8_t mu[MLDSA_CRHBYTES]; + + /* Generate valid keypair first */ + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf( + stderr, + "ERROR: crypto_sign_keypair failed in signature_extmu test setup\n"); + return 1; + } + + /* Fill mu with test data */ + randombytes(mu, sizeof(mu)); + + TEST_RNG_FAILURE("crypto_sign_signature_extmu", + mld_signature_extmu(sig, &siglen, mu, sk)); + return 0; +} + +static int test_verify_extmu_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t mu[64] = {0}; + size_t siglen; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: mld_keypair failed in verify_extmu test setup\n"); + return 1; + } + + if (mld_signature_extmu(sig, &siglen, mu, sk) != 0) + { + fprintf(stderr, + "ERROR: mld_signature_extmu failed in verify_extmu test setup\n"); + return 1; + } + + TEST_RNG_FAILURE("mld_verify_extmu", mld_verify_extmu(sig, siglen, mu, pk)); + return 0; +} + +static int test_signature_pre_hash_shake256_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t msg[32] = {0}; + uint8_t rnd[32] = {0}; + const uint8_t ctx[] = "test context"; + size_t siglen; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, + "ERROR: mld_keypair failed in signature_pre_hash_shake256 test " + "setup\n"); + return 1; + } + + TEST_RNG_FAILURE( + "mld_signature_pre_hash_shake256", + mld_signature_pre_hash_shake256(sig, &siglen, msg, sizeof(msg), ctx, + sizeof(ctx) - 1, rnd, sk)); + return 0; +} + +static int test_verify_pre_hash_shake256_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t msg[32] = {0}; + uint8_t rnd[32] = {0}; + const uint8_t ctx[] = "test context"; + size_t siglen; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, + "ERROR: mld_keypair failed in verify_pre_hash_shake256 test " + "setup\n"); + return 1; + } + + if (mld_signature_pre_hash_shake256(sig, &siglen, msg, sizeof(msg), ctx, + sizeof(ctx) - 1, rnd, sk) != 0) + { + fprintf(stderr, + "ERROR: mld_signature_pre_hash_shake256 failed in " + "verify_pre_hash_shake256 test setup\n"); + return 1; + } + + TEST_RNG_FAILURE("mld_verify_pre_hash_shake256", + mld_verify_pre_hash_shake256(sig, siglen, msg, sizeof(msg), + ctx, sizeof(ctx) - 1, pk)); + return 0; +} + +static int test_pk_from_sk_rng_failure(void) +{ + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + + reset_all(); + if (mld_keypair(pk, sk) != 0) + { + fprintf(stderr, "ERROR: mld_keypair failed in pk_from_sk test setup\n"); + return 1; + } + + TEST_RNG_FAILURE("mld_pk_from_sk", mld_pk_from_sk(pk, sk)); + return 0; +} + +int main(void) +{ + if (test_keygen_rng_failure() != 0) + { + return 1; + } + + if (test_sign_rng_failure() != 0) + { + return 1; + } + + if (test_verify_rng_failure() != 0) + { + return 1; + } + + if (test_sign_combined_rng_failure() != 0) + { + return 1; + } + + if (test_open_rng_failure() != 0) + { + return 1; + } + + if (test_signature_extmu_rng_failure() != 0) + { + return 1; + } + + if (test_verify_extmu_rng_failure() != 0) + { + return 1; + } + + if (test_signature_pre_hash_shake256_rng_failure() != 0) + { + return 1; + } + + if (test_verify_pre_hash_shake256_rng_failure() != 0) + { + return 1; + } + + if (test_pk_from_sk_rng_failure() != 0) + { + return 1; + } + + return 0; +} diff --git a/test/test_rng_fail_config.h b/test/test_rng_fail_config.h new file mode 100644 index 000000000..e87732044 --- /dev/null +++ b/test/test_rng_fail_config.h @@ -0,0 +1,713 @@ +/* + * Copyright (c) The mldsa-native project authors + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + */ + +/* References + * ========== + * + * - [FIPS140_3_IG] + * Implementation Guidance for FIPS 140-3 and the Cryptographic Module + * Validation Program + * National Institute of Standards and Technology + * https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements + * + * - [FIPS204] + * FIPS 204 Module-Lattice-Based Digital Signature Standard + * National Institute of Standards and Technology + * https://csrc.nist.gov/pubs/fips/204/final + */ + +/* + * WARNING: This file is auto-generated from scripts/autogen + * in the mldsa-native repository. + * Do not modify it directly. + */ + +/* + * Test configuration: Using custom randombytes that can fail at specific + * invocation + * + * This configuration differs from the default mldsa/mldsa_native_config.h in + * the following places: + * - MLD_CONFIG_NAMESPACE_PREFIX + * - MLD_CONFIG_CUSTOM_RANDOMBYTES + */ + + +#ifndef MLD_CONFIG_H +#define MLD_CONFIG_H + +/****************************************************************************** + * Name: MLD_CONFIG_PARAMETER_SET + * + * Description: Specifies the parameter set for ML-DSA + * - MLD_CONFIG_PARAMETER_SET=44 corresponds to ML-DSA-44 + * - MLD_CONFIG_PARAMETER_SET=65 corresponds to ML-DSA-65 + * - MLD_CONFIG_PARAMETER_SET=87 corresponds to ML-DSA-87 + * + * If you want to support multiple parameter sets, build the + * library multiple times and set MLD_CONFIG_MULTILEVEL_BUILD. + * See MLD_CONFIG_MULTILEVEL_BUILD for how to do this while + * minimizing code duplication. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#ifndef MLD_CONFIG_PARAMETER_SET +#define MLD_CONFIG_PARAMETER_SET \ + 44 /* Change this for different security strengths */ +#endif + +/****************************************************************************** + * Name: MLD_CONFIG_FILE + * + * Description: If defined, this is a header that will be included instead + * of the default configuration file mldsa/mldsa_native_config.h. + * + * When you need to build mldsa-native in multiple configurations, + * using varying MLD_CONFIG_FILE can be more convenient + * then configuring everything through CFLAGS. + * + * To use, MLD_CONFIG_FILE _must_ be defined prior + * to the inclusion of any mldsa-native headers. For example, + * it can be set by passing `-DMLD_CONFIG_FILE="..."` + * on the command line. + * + *****************************************************************************/ +/* No need to set this -- we _are_ already in a custom config */ +/* #define MLD_CONFIG_FILE "mldsa_native_config.h" */ + +/****************************************************************************** + * Name: MLD_CONFIG_NAMESPACE_PREFIX + * + * Description: The prefix to use to namespace global symbols from mldsa/. + * + * In a multi-level build, level-dependent symbols will + * additionally be prefixed with the parameter set (44/65/87). + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#define MLD_CONFIG_NAMESPACE_PREFIX mld + +/****************************************************************************** + * Name: MLD_CONFIG_MULTILEVEL_BUILD + * + * Description: Set this if the build is part of a multi-level build supporting + * multiple parameter sets. + * + * If you need only a single parameter set, keep this unset. + * + * To build mldsa-native with support for all parameter sets, + * build it three times -- once per parameter set -- and set the + * option MLD_CONFIG_MULTILEVEL_WITH_SHARED for exactly one of + * them, and MLD_CONFIG_MULTILEVEL_NO_SHARED for the others. + * MLD_CONFIG_MULTILEVEL_BUILD should be set for all of them. + * + * See examples/multilevel_build for an example. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +/* #define MLD_CONFIG_MULTILEVEL_BUILD */ + +/****************************************************************************** + * Name: MLD_CONFIG_EXTERNAL_API_QUALIFIER + * + * Description: If set, this option provides an additional function + * qualifier to be added to declarations of mldsa-native's + * public API. + * + * The primary use case for this option are single-CU builds + * where the public API exposed by mldsa-native is wrapped by + * another API in the consuming application. In this case, + * even mldsa-native's public API can be marked `static`. + * + *****************************************************************************/ +/* #define MLD_CONFIG_EXTERNAL_API_QUALIFIER */ + +/****************************************************************************** + * Name: MLD_CONFIG_NO_RANDOMIZED_API + * + * Description: If this option is set, mldsa-native will be built without the + * randomized API functions (crypto_sign_keypair, + * crypto_sign, crypto_sign_signature, and + * crypto_sign_signature_extmu). + * This allows users to build mldsa-native without providing a + * randombytes() implementation if they only need the + * internal deterministic API + * (crypto_sign_keypair_internal, crypto_sign_signature_internal). + * + * NOTE: This option is incompatible with MLD_CONFIG_KEYGEN_PCT + * as the current PCT implementation requires + * crypto_sign_signature(). + * + *****************************************************************************/ +/* #define MLD_CONFIG_NO_RANDOMIZED_API */ + +/****************************************************************************** + * Name: MLD_CONFIG_NO_SUPERCOP + * + * Description: By default, mldsa_native.h exposes the mldsa-native API in the + * SUPERCOP naming convention (crypto_sign_xxx). If you don't need + * this, set MLD_CONFIG_NO_SUPERCOP. + * + * NOTE: You must set this for a multi-level build as the SUPERCOP + * naming does not disambiguate between the parameter sets. + * + *****************************************************************************/ +/* #define MLD_CONFIG_NO_SUPERCOP */ + +/****************************************************************************** + * Name: MLD_CONFIG_CONSTANTS_ONLY + * + * Description: If you only need the size constants (MLDSA_PUBLICKEYBYTES, etc.) + * but no function declarations, set MLD_CONFIG_CONSTANTS_ONLY. + * + * This only affects the public header mldsa_native.h, not + * the implementation. + * + *****************************************************************************/ +/* #define MLD_CONFIG_CONSTANTS_ONLY */ + +/****************************************************************************** + * + * Build-only configuration options + * + * The remaining configurations are build-options only. + * They do not affect the API described in mldsa_native.h. + * + *****************************************************************************/ + +#if defined(MLD_BUILD_INTERNAL) +/****************************************************************************** + * Name: MLD_CONFIG_MULTILEVEL_WITH_SHARED + * + * Description: This is for multi-level builds of mldsa-native only. If you + * need only a single parameter set, keep this unset. + * + * If this is set, all MLD_CONFIG_PARAMETER_SET-independent + * code will be included in the build, including code needed only + * for other parameter sets. + * + * Example: TODO: add example + * + * To build mldsa-native with support for all parameter sets, + * build it three times -- once per parameter set -- and set the + * option MLD_CONFIG_MULTILEVEL_WITH_SHARED for exactly one of + * them, and MLD_CONFIG_MULTILEVEL_NO_SHARED for the others. + * + * See examples/multilevel_build_mldsa for an example. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +/* #define MLD_CONFIG_MULTILEVEL_WITH_SHARED */ + +/****************************************************************************** + * Name: MLD_CONFIG_MULTILEVEL_NO_SHARED + * + * Description: This is for multi-level builds of mldsa-native only. If you + * need only a single parameter set, keep this unset. + * + * If this is set, no MLD_CONFIG_PARAMETER_SET-independent code + * will be included in the build. + * + * To build mldsa-native with support for all parameter sets, + * build it three times -- once per parameter set -- and set the + * option MLD_CONFIG_MULTILEVEL_WITH_SHARED for exactly one of + * them, and MLD_CONFIG_MULTILEVEL_NO_SHARED for the others. + * + * See examples/multilevel_build_mldsa for an example. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +/* #define MLD_CONFIG_MULTILEVEL_NO_SHARED */ + +/****************************************************************************** + * Name: MLD_CONFIG_MONOBUILD_KEEP_SHARED_HEADERS + * + * Description: This is only relevant for single compilation unit (SCU) + * builds of mldsa-native. In this case, it determines whether + * directives defined in parameter-set-independent headers should + * be #undef'ined or not at the of the SCU file. This is needed + * in multilevel builds. + * + * See examples/multilevel_build_native for an example. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +/* #define MLD_CONFIG_MONOBUILD_KEEP_SHARED_HEADERS */ + +/****************************************************************************** + * Name: MLD_CONFIG_USE_NATIVE_BACKEND_ARITH + * + * Description: Determines whether an native arithmetic backend should be used. + * + * The arithmetic backend covers performance critical functions + * such as the number-theoretic transform (NTT). + * + * If this option is unset, the C backend will be used. + * + * If this option is set, the arithmetic backend to be use is + * determined by MLD_CONFIG_ARITH_BACKEND_FILE: If the latter is + * unset, the default backend for your the target architecture + * will be used. If set, it must be the name of a backend metadata + * file. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#if !defined(MLD_CONFIG_USE_NATIVE_BACKEND_ARITH) +/* #define MLD_CONFIG_USE_NATIVE_BACKEND_ARITH */ +#endif + +/****************************************************************************** + * Name: MLD_CONFIG_ARITH_BACKEND_FILE + * + * Description: The arithmetic backend to use. + * + * If MLD_CONFIG_USE_NATIVE_BACKEND_ARITH is unset, this option + * is ignored. + * + * If MLD_CONFIG_USE_NATIVE_BACKEND_ARITH is set, this option must + * either be undefined or the filename of an arithmetic backend. + * If unset, the default backend will be used. + * + * This can be set using CFLAGS. + * + *****************************************************************************/ +#if defined(MLD_CONFIG_USE_NATIVE_BACKEND_ARITH) && \ + !defined(MLD_CONFIG_ARITH_BACKEND_FILE) +#define MLD_CONFIG_ARITH_BACKEND_FILE "native/meta.h" +#endif + +/****************************************************************************** + * Name: MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 + * + * Description: Determines whether an native FIPS202 backend should be used. + * + * The FIPS202 backend covers 1x/2x/4x-fold Keccak-f1600, which is + * the performance bottleneck of SHA3 and SHAKE. + * + * If this option is unset, the C backend will be used. + * + * If this option is set, the FIPS202 backend to be use is + * determined by MLD_CONFIG_FIPS202_BACKEND_FILE: If the latter is + * unset, the default backend for your the target architecture + * will be used. If set, it must be the name of a backend metadata + * file. + * + * This can also be set using CFLAGS. + * + *****************************************************************************/ +#if !defined(MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202) +/* #define MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 */ +#endif + +/****************************************************************************** + * Name: MLD_CONFIG_FIPS202_BACKEND_FILE + * + * Description: The FIPS-202 backend to use. + * + * If MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 is set, this option + * must either be undefined or the filename of a FIPS202 backend. + * If unset, the default backend will be used. + * + * This can be set using CFLAGS. + * + *****************************************************************************/ +#if defined(MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202) && \ + !defined(MLD_CONFIG_FIPS202_BACKEND_FILE) +#define MLD_CONFIG_FIPS202_BACKEND_FILE "fips202/native/auto.h" +#endif + +/****************************************************************************** + * Name: MLD_CONFIG_FIPS202_CUSTOM_HEADER + * + * Description: Custom header to use for FIPS-202 + * + * This should only be set if you intend to use a custom + * FIPS-202 implementation, different from the one shipped + * with mldsa-native. + * + * If set, it must be the name of a file serving as the + * replacement for mldsa/src/fips202/fips202.h, and exposing + * the same API (see FIPS202.md). + * + *****************************************************************************/ +/* #define MLD_CONFIG_FIPS202_CUSTOM_HEADER "SOME_FILE.h" */ + +/****************************************************************************** + * Name: MLD_CONFIG_FIPS202X4_CUSTOM_HEADER + * + * Description: Custom header to use for FIPS-202-X4 + * + * This should only be set if you intend to use a custom + * FIPS-202 implementation, different from the one shipped + * with mldsa-native. + * + * If set, it must be the name of a file serving as the + * replacement for mldsa/src/fips202/fips202x4.h, and exposing + * the same API (see FIPS202.md). + * + *****************************************************************************/ +/* #define MLD_CONFIG_FIPS202X4_CUSTOM_HEADER "SOME_FILE.h" */ + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_ZEROIZE + * + * Description: In compliance with @[FIPS204, Section 3.6.3], mldsa-native, + * zeroizes intermediate stack buffers before returning from + * function calls. + * + * Set this option and define `mld_zeroize_native` if you want to + * use a custom method to zeroize intermediate stack buffers. + * The default implementation uses SecureZeroMemory on Windows + * and a memset + compiler barrier otherwise. If neither of those + * is available on the target platform, compilation will fail, + * and you will need to use MLD_CONFIG_CUSTOM_ZEROIZE to provide + * a custom implementation of `mld_zeroize_native()`. + * + * WARNING: + * The explicit stack zeroization conducted by mldsa-native + * reduces the likelihood of data leaking on the stack, but + * does not eliminate it! The C standard makes no guarantee about + * where a compiler allocates structures and whether/where it makes + * copies of them. Also, in addition to entire structures, there + * may also be potentially exploitable leakage of individual values + * on the stack. + * + * If you need bullet-proof zeroization of the stack, you need to + * consider additional measures instead of what this feature + * provides. In this case, you can set mld_zeroize_native to a + * no-op. + * + *****************************************************************************/ +/* #define MLD_CONFIG_CUSTOM_ZEROIZE + #if !defined(__ASSEMBLER__) + #include + #include "src/src.h" + static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len) + { + ... your implementation ... + } + #endif +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_RANDOMBYTES + * + * Description: mldsa-native does not provide a secure randombytes + * implementation. Such an implementation has to provided by the + * consumer. + * + * If this option is not set, mldsa-native expects a function + * int randombytes(uint8_t *out, size_t outlen). + * + * Set this option and define `mld_randombytes` if you want to + * use a custom method to sample randombytes with a different name + * or signature. + * + *****************************************************************************/ +#define MLD_CONFIG_CUSTOM_RANDOMBYTES +#if !defined(__ASSEMBLER__) +#include +#include +#include "src/sys.h" +int mld_randombytes(uint8_t *out, size_t outlen); +#endif /* !__ASSEMBLER__ */ + + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_CAPABILITY_FUNC + * + * Description: mldsa-native backends may rely on specific hardware features. + * Those backends will only be included in an mldsa-native build + * if support for the respective features is enabled at + * compile-time. However, when building for a heteroneous set + * of CPUs to run the resulting binary/library on, feature + * detection at _runtime_ is needed to decided whether a backend + * can be used or not. + * + * Set this option and define `mld_sys_check_capability` if you + * want to use a custom method to dispatch between implementations. + * + * Return value 1 indicates that a capability is supported. + * Return value 0 indicates that a capability is not supported. + * + * If this option is not set, mldsa-native uses compile-time + * feature detection only to decide which backend to use. + * + * If you compile mldsa-native on a system with different + * capabilities than the system that the resulting binary/library + * will be run on, you must use this option. + * + *****************************************************************************/ +/* #define MLD_CONFIG_CUSTOM_CAPABILITY_FUNC + static MLD_INLINE int mld_sys_check_capability(mld_sys_cap cap) + { + ... your implementation ... + } +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_ALLOC_FREE [EXPERIMENTAL] + * + * Description: Set this option and define `MLD_CUSTOM_ALLOC` and + * `MLD_CUSTOM_FREE` if you want to use custom allocation for + * large local structures or buffers. + * + * By default, all buffers/structures are allocated on the stack. + * If this option is set, most of them will be allocated via + * MLD_CUSTOM_ALLOC. + * + * Parameters to MLD_CUSTOM_ALLOC: + * - T* v: Target pointer to declare. + * - T: Type of structure to be allocated + * - N: Number of elements to be allocated. + * + * Parameters to MLD_CUSTOM_FREE: + * - T* v: Target pointer to free. May be NULL. + * - T: Type of structure to be freed. + * - N: Number of elements to be freed. + * + * WARNING: This option is experimental! + * Its scope, configuration and function/macro signatures may + * change at any time. We expect a stable API for v2. + * + * NOTE: Even if this option is set, some allocations further down + * the call stack will still be made from the stack. Those will + * likely be added to the scope of this option in the future. + * + * NOTE: MLD_CUSTOM_ALLOC need not guarantee a successful + * allocation nor include error handling. Upon failure, the + * target pointer should simply be set to NULL. The calling + * code will handle this case and invoke MLD_CUSTOM_FREE. + * + *****************************************************************************/ +/* #define MLD_CONFIG_CUSTOM_ALLOC_FREE + #if !defined(__ASSEMBLER__) + #include + #define MLD_CUSTOM_ALLOC(v, T, N) \ + T* (v) = (T *)aligned_alloc(MLD_DEFAULT_ALIGN, \ + MLD_ALIGN_UP(sizeof(T) * (N))) + #define MLD_CUSTOM_FREE(v, T, N) free(v) + #endif +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_MEMCPY + * + * Description: Set this option and define `mld_memcpy` if you want to + * use a custom method to copy memory instead of the standard + * library memcpy function. + * + * The custom implementation must have the same signature and + * behavior as the standard memcpy function: + * void *mld_memcpy(void *dest, const void *src, size_t n) + * + *****************************************************************************/ +/* #define MLD_CONFIG_CUSTOM_MEMCPY + #if !defined(__ASSEMBLER__) + #include + #include "src/src.h" + static MLD_INLINE void *mld_memcpy(void *dest, const void *src, size_t n) + { + ... your implementation ... + } + #endif +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_CUSTOM_MEMSET + * + * Description: Set this option and define `mld_memset` if you want to + * use a custom method to set memory instead of the standard + * library memset function. + * + * The custom implementation must have the same signature and + * behavior as the standard memset function: + * void *mld_memset(void *s, int c, size_t n) + * + *****************************************************************************/ +/* #define MLD_CONFIG_CUSTOM_MEMSET + #if !defined(__ASSEMBLER__) + #include + #include "src/src.h" + static MLD_INLINE void *mld_memset(void *s, int c, size_t n) + { + ... your implementation ... + } + #endif +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_INTERNAL_API_QUALIFIER + * + * Description: If set, this option provides an additional function + * qualifier to be added to declarations of internal API. + * + * The primary use case for this option are single-CU builds, + * in which case this option can be set to `static`. + * + *****************************************************************************/ +/* #define MLD_CONFIG_INTERNAL_API_QUALIFIER */ + +/****************************************************************************** + * Name: MLD_CONFIG_CT_TESTING_ENABLED + * + * Description: If set, mldsa-native annotates data as secret / public using + * valgrind's annotations VALGRIND_MAKE_MEM_UNDEFINED and + * VALGRIND_MAKE_MEM_DEFINED, enabling various checks for secret- + * dependent control flow of variable time execution (depending + * on the exact version of valgrind installed). + * + *****************************************************************************/ +/* #define MLD_CONFIG_CT_TESTING_ENABLED */ + +/****************************************************************************** + * Name: MLD_CONFIG_NO_ASM + * + * Description: If this option is set, mldsa-native will be built without + * use of native code or inline assembly. + * + * By default, inline assembly is used to implement value barriers. + * Without inline assembly, mldsa-native will use a global volatile + * 'opt blocker' instead; see ct.h. + * + * Inline assembly is also used to implement a secure zeroization + * function on non-Windows platforms. If this option is set and + * the target platform is not Windows, you MUST set + * MLD_CONFIG_CUSTOM_ZEROIZE and provide a custom zeroization + * function. + * + * If this option is set, MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202 and + * and MLD_CONFIG_USE_NATIVE_BACKEND_ARITH will be ignored, and no + * native backends will be used. + * + *****************************************************************************/ +/* #define MLD_CONFIG_NO_ASM */ + +/****************************************************************************** + * Name: MLD_CONFIG_NO_ASM_VALUE_BARRIER + * + * Description: If this option is set, mldsa-native will be built without + * use of native code or inline assembly for value barriers. + * + * By default, inline assembly (if available) is used to implement + * value barriers. + * Without inline assembly, mldsa-native will use a global volatile + * 'opt blocker' instead; see ct.h. + * + *****************************************************************************/ +/* #define MLD_CONFIG_NO_ASM_VALUE_BARRIER */ + +/****************************************************************************** + * Name: MLD_CONFIG_KEYGEN_PCT + * + * Description: Compliance with @[FIPS140_3_IG, p.87] requires a + * Pairwise Consistency Test (PCT) to be carried out on a freshly + * generated keypair before it can be exported. + * + * Set this option if such a check should be implemented. + * In this case, crypto_sign_keypair_internal and + * crypto_sign_keypair will return a non-zero error code if the + * PCT failed. + * + * NOTE: This feature will drastically lower the performance of + * key generation. + * + *****************************************************************************/ +/* #define MLD_CONFIG_KEYGEN_PCT */ + +/****************************************************************************** + * Name: MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST + * + * Description: If this option is set, the user must provide a runtime + * function `static inline int mld_break_pct() { ... }` to + * indicate whether the PCT should be made fail. + * + * This option only has an effect if MLD_CONFIG_KEYGEN_PCT is set. + * + *****************************************************************************/ +/* #define MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST + #if !defined(__ASSEMBLER__) + #include "src/src.h" + static MLD_INLINE int mld_break_pct(void) + { + ... return 0/1 depending on whether PCT should be broken ... + } + #endif +*/ + +/****************************************************************************** + * Name: MLD_CONFIG_SERIAL_FIPS202_ONLY + * + * Description: Set this to use a FIPS202 implementation with global state + * that supports only one active Keccak computation at a time + * (e.g. some hardware accelerators). + * + * If this option is set, ML-DSA will use FIPS202 operations + * serially, ensuring that only one SHAKE context is active + * at any given time. + * + * This allows offloading Keccak computations to a hardware + * accelerator that holds only a single Keccak state locally, + * rather than requiring support for multiple concurrent + * Keccak states. + * + * NOTE: Depending on the target CPU, this may reduce + * performance when using software FIPS202 implementations. + * Only enable this when you have to. + * + *****************************************************************************/ +/* #define MLD_CONFIG_SERIAL_FIPS202_ONLY */ + +/****************************************************************************** + * Name: MLD_CONFIG_REDUCE_RAM [EXPERIMENTAL] + * + * Description: Set this to reduce RAM usage. + * This trades memory for performance. + * + * For detailed expected memory savings, see the + * mldsa-native README. + * + * This option is useful for embedded systems with tight RAM + * constraints but relaxed performance requirements. + * + * WARNING: This option is experimental! + * CBMC proofs do not currently cover this configuration option. + * Its scope and configuration may change at any time. + * + *****************************************************************************/ +/* #define MLD_CONFIG_REDUCE_RAM */ + +/************************* Config internals ********************************/ + +#endif /* MLD_BUILD_INTERNAL */ + +/* Default namespace + * + * Don't change this. If you need a different namespace, re-define + * MLD_CONFIG_NAMESPACE_PREFIX above instead, and remove the following. + * + * The default MLDSA namespace is + * + * PQCP_MLDSA_NATIVE_MLDSA_ + * + * e.g., PQCP_MLDSA_NATIVE_MLDSA44_ + */ + +#if MLD_CONFIG_PARAMETER_SET == 44 +#define MLD_DEFAULT_NAMESPACE_PREFIX PQCP_MLDSA_NATIVE_MLDSA44 +#elif MLD_CONFIG_PARAMETER_SET == 65 +#define MLD_DEFAULT_NAMESPACE_PREFIX PQCP_MLDSA_NATIVE_MLDSA65 +#elif MLD_CONFIG_PARAMETER_SET == 87 +#define MLD_DEFAULT_NAMESPACE_PREFIX PQCP_MLDSA_NATIVE_MLDSA87 +#endif + +#endif /* !MLD_CONFIG_H */