Skip to content

Commit

Permalink
Address stateful-sigs comments in #1650 (#1656)
Browse files Browse the repository at this point in the history
* Add sig_stfl to configure.md

* Add OQS_MEM_checked_malloc and OQS_MEM_checked_aligned_alloc

* Use memcpy and checked_malloc
  • Loading branch information
ducnguyen-sb authored and SWilson4 committed Apr 12, 2024
1 parent 86b39cf commit 2aa48d5
Showing 9 changed files with 129 additions and 123 deletions.
28 changes: 15 additions & 13 deletions CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ The following options can be passed to CMake before the build file generation pr
- [CMAKE_INSTALL_PREFIX](#CMAKE_INSTALL_PREFIX)
- [OQS_ALGS_ENABLED](#OQS_ALGS_ENABLED)
- [OQS_BUILD_ONLY_LIB](#OQS_BUILD_ONLY_LIB)
- [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG)
- [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG)
- [OQS_MINIMAL_BUILD](#OQS_MINIMAL_BUILD)
- [OQS_DIST_BUILD](#OQS_DIST_BUILD)
- [OQS_USE_CPUFEATURE_INSTRUCTIONS](OQS_USE_CPUFEATURE_INSTRUCTIONS)
@@ -42,21 +42,23 @@ Can be set to the following values:

See the [CMake documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html).

## OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG
## OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG

Note: `ALG` in `OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG` should be replaced with the specific algorithm name as demonstrated below.
Note: `ALG` in `OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG` should be replaced with the specific algorithm name as demonstrated below.

This can be set to `ON` or `OFF`, and is `ON` by default. When `OFF`, `ALG` and its code are excluded from the build process. When `ON`, made available are additional options whereby individual variants of `ALG` can be excluded from the build process.

For example: if `OQS_ENABLE_KEM_BIKE` is set to `ON`, the options `OQS_ENABLE_KEM_bike_l1`, `OQS_ENABLE_KEM_bike_l3`, and `OQS_ENABLE_KEM_bike_l5` are made available (and are set to be `ON` by default).

To enable `XMSS` stateful signature, set `OQS_ENABLE_SIG_STFL_XMSS` to `ON`, the options `OQS_ENABLE_SIG_STFL_xmss_sha256_h10` and its variants are also set to be `ON` by default. Similarly, `LMS` stateful signature family can also be enabled by setting `OQS_ENABLE_SIG_STFL_LMS` to `ON`.

For a full list of such options and their default values, consult [.CMake/alg_support.cmake](https://github.com/open-quantum-safe/liboqs/blob/master/.CMake/alg_support.cmake).

**Default**: Unset.

## OQS_ALGS_ENABLED

Selects algorithm set enabled. Possible values are "STD" selecting all algorithms standardized by NIST; "NIST_R4" selecting all algorithms evaluated in round 4 of the NIST PQC competition; "All" (or any other value) selecting all algorithms integrated into liboqs. Parameter setting "STD" minimizes library size but may require re-running code generator scripts in projects integrating `liboqs`; e.g., [oqs-provider](https://github.com/open-quantum-safe/oqs-provider) and [oqs-boringssl](https://github.com/open-quantum-safe/boringssl).
A selected algorithm set is enabled. Possible values are "STD" selecting all algorithms standardized by NIST; "NIST_R4" selecting all algorithms evaluated in round 4 of the NIST PQC competition; "All" (or any other value) selecting all algorithms integrated into liboqs. Parameter setting "STD" minimizes library size but may require re-running code generator scripts in projects integrating `liboqs`; e.g., [oqs-provider](https://github.com/open-quantum-safe/oqs-provider) and [oqs-boringssl](https://github.com/open-quantum-safe/boringssl).

**Default**: `All`.

@@ -68,9 +70,9 @@ Can be `ON` or `OFF`. When `ON`, only liboqs is built, and all the targets: `run

## OQS_MINIMAL_BUILD

If set, this defines a semicolon deliminated list of algorithms to be contained in a minimal build of `liboqs`: Only algorithms explicitly set here are included in a build: For example running `cmake -DOQS_MINIMAL_BUILD="KEM_kyber_768;SIG_dilithium_3" ..` will build a minimum-size `liboqs` library only containing support for Kyber768 and Dilithium3.
If set, this defines a semicolon-delimited list of algorithms to be contained in a minimal build of `liboqs`: Only algorithms explicitly set here are included in a build: For example running `cmake -DOQS_MINIMAL_BUILD="KEM_kyber_768;SIG_dilithium_3" ..` will build a minimum-size `liboqs` library only containing support for Kyber768 and Dilithium3.

The full list of identifiers that can set are listed [here for KEM algorithms](https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/kem.h#L34) and [here for Signature algorithms](https://github.com/open-quantum-safe/liboqs/blob/f3caccff9e6225e7c50ca27f5ee6e58b7bc74188/src/sig/sig.h#L34). Default setting is empty, thus including all [supported algorithms](https://github.com/open-quantum-safe/liboqs#supported-algorithms) in the build.
The full list of identifiers that can be set is listed [here for KEM algorithms](https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/kem.h#L34) and [here for Signature algorithms](https://github.com/open-quantum-safe/liboqs/blob/f3caccff9e6225e7c50ca27f5ee6e58b7bc74188/src/sig/sig.h#L34). The default setting is empty, thus including all [supported algorithms](https://github.com/open-quantum-safe/liboqs#supported-algorithms) in the build.

**Default**: Unset.

@@ -90,13 +92,13 @@ When built for use on a single machine, the library will only include the best a

Note: `CPUFEATURE` in `OQS_USE_CPUFEATURE_INSTRUCTIONS` should be replaced with the specific CPU feature as noted below.

These can be set to `ON` or `OFF` and take an effect if liboqs is built for use on a single machine. By default, the CPU features are automatically determined and set to `ON` or `OFF` based on the CPU features available on the build system. The default values can be overridden by providing CMake build options. The available options on x86-64 are: `OQS_USE_ADX_INSTRUCTIONS`, `OQS_USE_AES_INSTRUCTIONS`, `OQS_USE_AVX_INSTRUCTIONS`, `OQS_USE_AVX2_INSTRUCTIONS`, `OQS_USE_AVX512_INSTRUCTIONS`, `OQS_USE_BMI1_INSTRUCTIONS`, `OQS_USE_BMI2_INSTRUCTIONS`, `OQS_USE_PCLMULQDQ_INSTRUCTIONS`, `OQS_USE_VPCLMULQDQ_INSTRUCTIONS`, `OQS_USE_POPCNT_INSTRUCTIONS`, `OQS_USE_SSE_INSTRUCTIONS`, `OQS_USE_SSE2_INSTRUCTIONS` and `OQS_USE_SSE3_INSTRUCTIONS`. The available options on ARM64v8 are `OQS_USE_ARM_AES_INSTRUCTIONS`, `OQS_USE_ARM_SHA2_INSTRUCTIONS`, `OQS_USE_ARM_SHA3_INSTRUCTIONS` and `OQS_USE_ARM_NEON_INSTRUCTIONS`.
These can be set to `ON` or `OFF` and take effect if liboqs is built for use on a single machine. By default, the CPU features are automatically determined and set to `ON` or `OFF` based on the CPU features available on the build system. The default values can be overridden by providing CMake build options. The available options on x86-64 are: `OQS_USE_ADX_INSTRUCTIONS`, `OQS_USE_AES_INSTRUCTIONS`, `OQS_USE_AVX_INSTRUCTIONS`, `OQS_USE_AVX2_INSTRUCTIONS`, `OQS_USE_AVX512_INSTRUCTIONS`, `OQS_USE_BMI1_INSTRUCTIONS`, `OQS_USE_BMI2_INSTRUCTIONS`, `OQS_USE_PCLMULQDQ_INSTRUCTIONS`, `OQS_USE_VPCLMULQDQ_INSTRUCTIONS`, `OQS_USE_POPCNT_INSTRUCTIONS`, `OQS_USE_SSE_INSTRUCTIONS`, `OQS_USE_SSE2_INSTRUCTIONS` and `OQS_USE_SSE3_INSTRUCTIONS`. The available options on ARM64v8 are `OQS_USE_ARM_AES_INSTRUCTIONS`, `OQS_USE_ARM_SHA2_INSTRUCTIONS`, `OQS_USE_ARM_SHA3_INSTRUCTIONS` and `OQS_USE_ARM_NEON_INSTRUCTIONS`.

**Default**: Options valid on the build machine.

## OQS_USE_OPENSSL

In order to save size and limit the amount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option.
To save size and limit the amount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option.

This can be set to `ON` or `OFF`. When `ON`, the additional options `OQS_USE_AES_OPENSSL`, `OQS_USE_SHA2_OPENSSL`, and `OQS_USE_SHA3_OPENSSL` are made available to control whether liboqs uses OpenSSL's AES, SHA-2, and SHA-3 implementations.

@@ -105,7 +107,7 @@ By default,
- `OQS_USE_SHA2_OPENSSL` is `ON`
- `OQS_USE_SHA3_OPENSSL` is `OFF`.

These default choices have been made in order to optimize the default performance of all algorithms. Changing them implies performance penalties.
These default choices have been made to optimize the default performance of all algorithms. Changing them implies performance penalties.

When `OQS_USE_OPENSSL` is `ON`, CMake also scans the filesystem to find the minimum version of OpenSSL required by liboqs (which happens to be 1.1.1). The [OPENSSL_ROOT_DIR](https://cmake.org/cmake/help/latest/module/FindOpenSSL.html) option can be set to aid CMake in its search.

@@ -131,15 +133,15 @@ An optimization target. Only has an effect if the compiler is GCC or Clang and `

Can be `ON` or `OFF`. When `ON`, the benchmarking script will try to use the ARMv8 Performance Monitoring Unit (PMU). This will make cycle counts on ARMv8 platforms significantly more accurate.

In order to use this option, user mode access to the PMU must be enabled via a kernel module. If user mode access is not enabled via kernel module, benchmarking will throw an `Illegal Instruction` error. A kernel module that has been found to work on several platforms can be found [here for linux](https://github.com/mupq/pqax#enable-access-to-performance-counters). Follow the instructions there (i.e., clone the repository, `cd enable_ccr` and `make install`) to load the kernel module, after which benchmarking should work. Superuser permissions are required. Linux header files must also be installed on your platform, which may not be present by default.
In order to use this option, user mode access to the PMU must be enabled via a kernel module. If user mode access is not enabled via the kernel module, benchmarking will throw an `Illegal Instruction` error. A kernel module that has been found to work on several platforms can be found [here for Linux](https://github.com/mupq/pqax#enable-access-to-performance-counters). Follow the instructions there (i.e., clone the repository, `cd enable_ccr` and `make install`) to load the kernel module, after which benchmarking should work. Superuser permissions are required. Linux header files must also be installed on your platform, which may not be present by default.

Note that this option is not known to work on Apple M1 chips.

**Default**: `OFF`.

## USE_SANITIZER

This has effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) is `Debug`. Then, it can be set to:
This has an effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) is `Debug`. Then, it can be set to:

- `Address`: This enables Clang's `AddressSanitizer`
- `Memory`: This enables Clang's `MemorySanitizer`
@@ -154,13 +156,13 @@ This has effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BU

This is used in conjunction with `tests/test_constant_time.py` to use Valgrind to look for instances of secret-dependent control flow. liboqs must also be compiled with [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) set to `Debug`.

See the documentation in [`tests/test_constant_time.py`](https://github.com/open-quantum-safe/liboqs/blob/main/tests/test_constant_time.py) for more information on usage.
See the documentation in [`tests/test_constant_time.py`](https://github.com/open-quantum-safe/liboqs/blob/main/tests/test_constant_time.py) for more usage information.

**Default**: `OFF`.

## OQS_STRICT_WARNINGS

Can be `ON` or `OFF`. When `ON`, all compiler warnings are enabled and treated as errors. This setting is recommended to be enabled prior to submission of a Pull Request as CI runs with this setting active. When `OFF`, significantly fewer compiler warnings are enabled such as to avoid undue build errors triggered by (future) compiler warning features/unknown at development time of this library.
Can be `ON` or `OFF`. When `ON`, all compiler warnings are enabled and treated as errors. This setting is recommended to be enabled prior to submission of a Pull Request as CI runs with this setting active. When `OFF`, significantly fewer compiler warnings are enabled such as to avoid undue build errors triggered by (future) compiler warning features/unknown at the development time of this library.

**Default**: `OFF`.

20 changes: 20 additions & 0 deletions src/common/common.c
Original file line number Diff line number Diff line change
@@ -271,6 +271,26 @@ OQS_API void OQS_MEM_cleanse(void *ptr, size_t len) {
#endif
}

void *OQS_MEM_checked_malloc(size_t len) {
void *ptr = malloc(len);
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}

return ptr;
}

void *OQS_MEM_checked_aligned_alloc(size_t alignment, size_t size) {
void *ptr = OQS_MEM_aligned_alloc(alignment, size);
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}

return ptr;
}

OQS_API void OQS_MEM_secure_free(void *ptr, size_t len) {
if (ptr != NULL) {
OQS_MEM_cleanse(ptr, len);
55 changes: 55 additions & 0 deletions src/common/common.h
Original file line number Diff line number Diff line change
@@ -180,6 +180,59 @@ OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len);
*/
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len);

/**
* Allocates memory of a specified size and checks for successful allocation.
*
* This function attempts to allocate a block of memory of the specified size.
* If the allocation is successful, it returns a pointer to the beginning of the
* memory block. If the allocation fails, it prints an error message to stderr
* and terminates the program.
*
* @param[in] len The size of the memory block to allocate, in bytes.
*
* @return A pointer to the allocated memory block if the allocation is successful.
*
* @note This function is intended to be used when the allocation must succeed,
* and failure to allocate memory is considered a fatal error. As such,
* it does not return if the allocation fails, but instead terminates the
* program with an exit status indicating failure.
*
* @note The memory block returned by this function is not initialized. The caller
* is responsible for initializing the memory if required.
*
* @note The allocated memory should be freed using the standard `free` function
* when it is no longer needed.
*/
void *OQS_MEM_checked_malloc(size_t len);

/**
* Allocates memory of a specified size and alignment and checks for successful allocation.
*
* This function attempts to allocate a block of memory with the specified size
* and alignment. If the allocation is successful, it returns a pointer to the
* memory block. If the allocation fails, it prints an error message to stderr
* and terminates the program.
*
* Alignment must be a power of two and a multiple of sizeof(void *).
*
* @param[in] alignment The alignment of the memory block to allocate.
* @param[in] size The size of the memory block to allocate, in bytes.
*
* @return A pointer to the allocated memory block if the allocation is successful.
*
* @note This function is intended to be used when the allocation must succeed,
* and failure to allocate memory is considered a fatal error. As such,
* it does not return if the allocation fails, but instead terminates the
* program with an exit status indicating failure.
*
* @note The memory block returned by this function is not initialized. The caller
* is responsible for initializing the memory if required.
*
* @note The allocated memory should be freed with `OQS_MEM_aligned_free` when it
* is no longer needed.
*/
void *OQS_MEM_checked_aligned_alloc(size_t alignment, size_t size);

/**
* Zeros out `len` bytes of memory starting at `ptr`, then frees `ptr`.
*
@@ -211,6 +264,8 @@ OQS_API void OQS_MEM_insecure_free(void *ptr);
* Allocates size bytes of uninitialized memory with a base pointer that is
* a multiple of alignment. Alignment must be a power of two and a multiple
* of sizeof(void *). Size must be a multiple of alignment.
* @note The allocated memory should be freed with `OQS_MEM_aligned_free` when it
* is no longer needed.
*/
void *OQS_MEM_aligned_alloc(size_t alignment, size_t size);

20 changes: 6 additions & 14 deletions src/common/sha2/sha2_armv8.c
Original file line number Diff line number Diff line change
@@ -180,10 +180,7 @@ void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const ui
new_in = in;
} else {
// Combine incremental data with final input
tmp_in = malloc(tmp_len);
if (tmp_in == NULL) {
exit(111);
}
tmp_in = OQS_MEM_checked_malloc(tmp_len);

memcpy(tmp_in, state->data, state->data_len);
if (in && inlen) {
@@ -257,10 +254,7 @@ void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_

/* Process any existing incremental data first */
if (state->data_len) {
tmp_in = malloc(buf_len);
if (tmp_in == NULL) {
exit(111);
}
tmp_in = OQS_MEM_checked_malloc(buf_len);

memcpy(tmp_in, state->data, state->data_len);
memcpy(tmp_in + state->data_len, in, buf_len - state->data_len);
@@ -280,17 +274,15 @@ void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_
}

void oqs_sha2_sha256_inc_armv8(sha256ctx *state, const uint8_t *in, size_t len) {
uint64_t bytes = 0;
size_t in_index = 0;
while (len) {
size_t incr = 64 - state->data_len;
if (incr > len) {
incr = len;
}

for (size_t i = 0; i < incr; ++i, state->data_len++, in_index++) {
state->data[state->data_len] = in[in_index];
}
memcpy(state->data + state->data_len, in, incr);
state->data_len += incr;
in += incr;

if (state->data_len < 64) {
break;
@@ -299,7 +291,7 @@ void oqs_sha2_sha256_inc_armv8(sha256ctx *state, const uint8_t *in, size_t len)
/*
* Process a complete block now
*/
bytes = load_bigendian_64(state->ctx + 32) + 64;
uint64_t bytes = load_bigendian_64(state->ctx + 32) + 64;
crypto_hashblocks_sha256_armv8(state->ctx, state->data, 64);
store_bigendian_64(state->ctx + 32, bytes);

Loading

0 comments on commit 2aa48d5

Please sign in to comment.