### OQS-Provider Release Test Setup Source: https://github.com/open-quantum-safe/liboqs/wiki/Release-process Commands to set up and run the release tests for the oqs-provider subproject. This involves cloning repositories, setting environment variables for branches, and installing dependencies. ```bash git clone https://github.com/open-quantum-safe/oqs-provider cd oqs-provider export LIBOQS_BRANCH="x.y.z-rc-branch" export OPENSSL_BRANCH="openssl-3.2.2" git clone git@github.com:open-quantum-safe/liboqs.git --single-branch --branch $LIBOQS_BRANCH --depth 1 # set up Python environment, such as with pyenv + venv pip install --upgrade pip wheel setuptools pytest pytest-xdist psutil jinja2 PyYAML tabulate ./scripts/release-test.sh ``` -------------------------------- ### Install Build Dependencies and Build liboqs Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Installs necessary dependencies on Ubuntu and then clones, builds, and installs liboqs. Supports building as a shared library and installing to a custom prefix. ```bash # Install build dependencies (Ubuntu) sudo apt install astyle cmake gcc ninja-build libssl-dev python3-pytest \ python3-pytest-xdist unzip xsltproc doxygen graphviz python3-yaml valgrind # Clone and build git clone -b main https://github.com/open-quantum-safe/liboqs.git cd liboqs mkdir build && cd build cmake -GNinja .. ninja # Build as shared library cmake -GNinja -DBUILD_SHARED_LIBS=ON .. ninja # Install to a custom prefix cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local .. ninja install # Run the test suite ninja run_tests # Generate HTML API documentation ninja gen_docs # Open docs/html/index.html in a browser # Link an application against the installed library gcc -Ibuild/include -Lbuild/lib myapp.c -o myapp -loqs -lssl -lcrypto ``` -------------------------------- ### Create Install Package Source: https://github.com/open-quantum-safe/liboqs/blob/main/README.md Creates an installable package for the liboqs library. ```bash ninja package ``` -------------------------------- ### Install liboqs Source: https://github.com/open-quantum-safe/liboqs/blob/main/README.md Installs the built liboqs library and header files to a specified location. The installation prefix can be set using CMAKE_INSTALL_PREFIX. ```bash ninja install ``` -------------------------------- ### Install Linux Dependencies (Ubuntu) Source: https://github.com/open-quantum-safe/liboqs/blob/main/README.md Installs necessary development tools and libraries for building liboqs on Ubuntu systems. ```bash sudo apt install astyle cmake gcc ninja-build libssl-dev python3-pytest python3-pytest-xdist unzip xsltproc doxygen graphviz python3-yaml valgrind ``` -------------------------------- ### Configure liboqs Build with CMake Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Examples of CMake commands to configure the liboqs build. Options control library type, enabled algorithms, installation paths, and specific build features like sanitizers or GPU acceleration. ```bash # Standard library build (static, all algorithms, release mode) cmake -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=OFF \ -DOQS_ALGS_ENABLED=All \ .. ``` ```bash # Shared library, only NIST standards, installed to /opt/liboqs cmake -GNinja \ -DBUILD_SHARED_LIBS=ON \ -DOQS_ALGS_ENABLED=STD \ -DCMAKE_INSTALL_PREFIX=/opt/liboqs \ .. ``` ```bash # Distribution build (runtime CPU dispatch for x86-64) cmake -GNinja -DOQS_DIST_BUILD=ON .. ``` ```bash # Debug build with AddressSanitizer cmake -GNinja \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_C_COMPILER=clang \ -DUSE_SANITIZER=Address \ .. ``` ```bash # Disable OpenSSL dependency entirely cmake -GNinja -DOQS_USE_OPENSSL=OFF .. ``` ```bash # Embedded / bare-metal build (no OS entropy; supply custom RNG via callback) cmake -GNinja -DOQS_EMBEDDED_BUILD=ON .. ``` ```bash # Enable XMSS/LMS stateful signatures (hazardous: key reuse is catastrophic) cmake -GNinja \ -DOQS_ENABLE_SIG_STFL_XMSS=ON \ -DOQS_ENABLE_SIG_STFL_LMS=ON \ -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON \ .. ``` ```bash # GPU-accelerated ML-KEM via ICICLE (requires pre-built icicle_pqc_package) cmake -GNinja -DOQS_USE_ICICLE=ON .. ``` ```bash # Memory-optimized build (lower RAM, potential performance cost) cmake -GNinja -DOQS_MEMOPT_BUILD=ON .. ``` ```bash # Fuzzing build with clang + AddressSanitizer cmake -GNinja \ -DCMAKE_C_COMPILER=clang \ -DOQS_BUILD_FUZZ_TESTS=ON \ -DCMAKE_C_FLAGS="-fsanitize=address,fuzzer-no-link" \ .. ``` -------------------------------- ### Compile Example KEM Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-KEM This bash command shows how to compile the example KEM code. Ensure liboqs is built with the desired KEM algorithm enabled. You may need to link additional libraries like OpenSSL. ```bash $CC -Ibuild/include -Lbuild/lib tests/example_kem.c -o example_kem -loqs ``` -------------------------------- ### Post-Quantum Signature Example (C) Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-signature This C code demonstrates a minimal example of using a post-quantum signature algorithm. It includes functions for key generation, signing, verification, and memory cleanup. Ensure liboqs is built with the desired algorithm enabled. ```c uint8_t *public_key = NULL; size_t public_key_len = 0; uint8_t *secret_key = NULL; size_t secret_key_len = 0; uint8_t *message = NULL; size_t message_len = 0; uint8_t *signature = NULL; size_t signature_len = 0; OQS_SIG *sig = NULL; OQS_RAND *rand = NULL; rand = OQS_RAND_new(OQS_RAND_alg_system); if (rand == NULL) { return OQS_ERROR; } sig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); if (sig == NULL) { OQS_RAND_free(rand); return OQS_ERROR; } public_key_len = OQS_SIG_public_key_length(sig); secret_key_len = OQS_SIG_secret_key_length(sig); signature_len = OQS_SIG_signature_length(sig); public_key = (uint8_t *)malloc(public_key_len); secret_key = (uint8_t *)malloc(secret_key_len); if (public_key == NULL || secret_key == NULL) { OQS_MEM_secure_free(secret_key, secret_key_len); OQS_MEM_insecure_free(public_key); OQS_SIG_free(sig); OQS_RAND_free(rand); return OQS_ERROR; } if (OQS_SIG_keypair(sig, public_key, secret_key) != OQS_SUCCESS) { OQS_MEM_secure_free(secret_key, secret_key_len); OQS_MEM_insecure_free(public_key); OQS_SIG_free(sig); OQS_RAND_free(rand); return OQS_ERROR; } message_len = 100; message = (uint8_t *)malloc(message_len); signature = (uint8_t *)malloc(signature_len); if (message == NULL || signature == NULL) { OQS_MEM_secure_free(secret_key, secret_key_len); OQS_MEM_insecure_free(public_key); OQS_MEM_insecure_free(message); OQS_MEM_insecure_free(signature); OQS_SIG_free(sig); OQS_RAND_free(rand); return OQS_ERROR; } // Fill message with arbitrary data for (size_t i = 0; i < message_len; i++) { message[i] = (uint8_t)i; } if (OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key) != OQS_SUCCESS) { cleanup_heap(public_key, secret_key, message, signature, sig); OQS_RAND_free(rand); return OQS_ERROR; } if (OQS_SIG_verify(sig, signature, signature_len, message, message_len, public_key) != OQS_SUCCESS) { cleanup_heap(public_key, secret_key, message, signature, sig); OQS_RAND_free(rand); return OQS_ERROR; } cleanup_heap(public_key, secret_key, message, signature, sig); OQS_RAND_free(rand); return OQS_SUCCESS; // success } ``` -------------------------------- ### Compile Example (Bash) Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-signature This command compiles the C example code in a POSIX-like environment. Ensure liboqs is built with Dilithium-2 enabled. You may need to add OpenSSL libraries if your build uses it for symmetric cryptography. ```bash $CC -Ibuild/include -Lbuild/lib tests/example_sig.c -o example_sig -loqs ``` -------------------------------- ### Dilithium-2 Signature Example (Stack Allocation) Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-signature Performs Dilithium-2 key generation, signing, and verification using static memory allocation on the stack. This example is conditional on OQS_ENABLE_SIG_dilithium_2 being defined at compile time. ```C #include #include #include #include #include #define MESSAGE_LEN 50 /* Cleaning up memory etc */ void cleanup_stack(uint8_t *secret_key, size_t secret_key_len); void cleanup_heap(uint8_t *public_key, uint8_t *secret_key, uint8_t *message, uint8_t *signature, OQS_SIG *sig); /* This function gives an example of the signing operations * using only compile-time macros and allocating variables * statically on the stack, calling a specific algorithm's functions * directly. * * The macros OQS_SIG_dilithium_2_length_* and the functions OQS_SIG_dilithium_2_* * are only defined if the algorithm dilithium_2 was enabled at compile-time * which must be checked using the OQS_ENABLE_SIG_dilithium_2 macro. * * , which is included in , contains macros * indicating which algorithms were enabled when this instance of liboqs * was compiled. */ static OQS_STATUS example_stack(void) { #ifdef OQS_ENABLE_SIG_dilithium_2 OQS_STATUS rc; uint8_t public_key[OQS_SIG_dilithium_2_length_public_key]; uint8_t secret_key[OQS_SIG_dilithium_2_length_secret_key]; uint8_t message[MESSAGE_LEN]; uint8_t signature[OQS_SIG_dilithium_2_length_signature]; size_t message_len = MESSAGE_LEN; size_t signature_len; // let's create a random test message to sign OQS_randombytes(message, message_len); rc = OQS_SIG_dilithium_2_keypair(public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_dilithium_2_keypair failed!\n"); cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key); return OQS_ERROR; } rc = OQS_SIG_dilithium_2_sign(signature, &signature_len, message, message_len, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_dilithium_2_sign failed!\n"); cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key); return OQS_ERROR; } rc = OQS_SIG_dilithium_2_verify(message, message_len, signature, signature_len, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_dilithium_2_verify failed!\n"); cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key); return OQS_ERROR; } printf("[example_stack] OQS_SIG_dilithium_2 operations completed.\n"); cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key); return OQS_SUCCESS; // success! #else printf("[example_stack] OQS_SIG_dilithium_2 was not enabled at compile-time.\n"); return OQS_ERROR; #endif } ``` -------------------------------- ### Install macOS Dependencies (Homebrew) Source: https://github.com/open-quantum-safe/liboqs/blob/main/README.md Installs required dependencies for liboqs on macOS using Homebrew and pip. ```bash brew install cmake ninja openssl@3 wget doxygen graphviz astyle valgrind pip3 install pytest pytest-xdist pyyaml ``` -------------------------------- ### Install MSYS2/MinGW-w64 64-bit Dependencies Source: https://github.com/open-quantum-safe/liboqs/wiki/Platform-specific-notes-for-building-liboqs Installs necessary build tools for 64-bit Windows development using MSYS2 and MinGW-w64. ```bash pacman -S git \ mingw-w64-x86_64-cmake \ mingw-w64-x86_64-ninja \ mingw-w64-x86_64-python-pytest \ mingw-w64-x86_64-python-pytest-xdist \ mingw-w64-x86_64-toolchain ``` -------------------------------- ### Install MSYS2/MinGW-w64 32-bit Dependencies Source: https://github.com/open-quantum-safe/liboqs/wiki/Platform-specific-notes-for-building-liboqs Installs necessary build tools for 32-bit Windows development using MSYS2 and MinGW-w64. ```bash pacman -S git \ mingw-w64-i686-cmake \ mingw-w64-i686-ninja \ mingw-w64-i686-python-pytest \ mingw-w64-i686-python-pytest-xdist \ mingw-w64-i686-toolchain ``` -------------------------------- ### Install OpenBSD Dependencies Source: https://github.com/open-quantum-safe/liboqs/wiki/Platform-specific-notes-for-building-liboqs Installs CMake, Ninja, and Python testing tools on OpenBSD using pkg_add and pip3. ```bash pkg_add cmake ninja pkg_add -r python pip3 install pytest pytest-xdist ``` -------------------------------- ### GitHub Action Pinning Example: Before and After Source: https://github.com/open-quantum-safe/liboqs/blob/main/docs/PROCEDURES.md Illustrates the transformation of a GitHub Actions step before and after using the 'pin-github-action' tool for version updates. ```yaml uses: actions/checkout@v3 ``` ```yaml uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # pin@v3 ``` ```yaml uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # pin@v4 ``` -------------------------------- ### KEM Stack API Example with Static Allocation Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Demonstrates KEM operations using static buffers and compile-time macros for algorithms like ML-KEM-768. Ensure the algorithm is enabled via feature macros. ```c #include #include #include int main(void) { OQS_init(); #ifdef OQS_ENABLE_KEM_ml_kem_768 // All buffers on the stack — no heap allocation uint8_t public_key[OQS_KEM_ml_kem_768_length_public_key]; uint8_t secret_key[OQS_KEM_ml_kem_768_length_secret_key]; uint8_t ciphertext[OQS_KEM_ml_kem_768_length_ciphertext]; uint8_t shared_secret_e[OQS_KEM_ml_kem_768_length_shared_secret]; uint8_t shared_secret_d[OQS_KEM_ml_kem_768_length_shared_secret]; OQS_STATUS rc = OQS_KEM_ml_kem_768_keypair(public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "Keypair generation failed\n"); goto cleanup; } rc = OQS_KEM_ml_kem_768_encaps(ciphertext, shared_secret_e, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "Encapsulation failed\n"); goto cleanup; } rc = OQS_KEM_ml_kem_768_decaps(shared_secret_d, ciphertext, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "Decapsulation failed\n"); goto cleanup; } printf("ML-KEM-768 stack example succeeded\n"); cleanup: // Wipe secret material before leaving scope OQS_MEM_cleanse(secret_key, OQS_KEM_ml_kem_768_length_secret_key); OQS_MEM_cleanse(shared_secret_e, OQS_KEM_ml_kem_768_length_shared_secret); OQS_MEM_cleanse(shared_secret_d, OQS_KEM_ml_kem_768_length_shared_secret); #else printf("ML-KEM-768 not enabled at compile time\n"); #endif OQS_destroy(); return EXIT_SUCCESS; } ``` -------------------------------- ### CMake Configuration and Compilation Source: https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/bike/additional_r4/README.md Configure the build with CMake and then compile the project. Ensure you have CMake version 3 or above installed. ```bash cmake -DCMAKE_BUILD_TYPE=Release .. make ``` -------------------------------- ### Build liboqs on Windows with Visual Studio Source: https://github.com/open-quantum-safe/liboqs/blob/main/README.md Instructions for building liboqs on Windows using Visual Studio 2019 with CMake Tools. This example shows how to generate Visual Studio build files. ```bash cmake -G "Visual Studio 16 2019" .. msbuild ALL_BUILD.vcxproj msbuild INSTALL.vcxproj ``` -------------------------------- ### Stack-allocated FrodoKEM-640-AES Example Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-KEM Performs key generation, encapsulation, and decapsulation using FrodoKEM-640-AES with variables allocated statically on the stack. This example requires the FrodoKEM-640-AES algorithm to be enabled at compile-time. ```C /* * example_kem.c * * Minimal example of a Diffie-Hellman-style post-quantum key encapsulation * implemented in liboqs. * */ #include #include #include #include #include /* Cleaning up memory etc */ void cleanup_stack(uint8_t *secret_key, size_t secret_key_len, uint8_t *shared_secret_e, uint8_t *shared_secret_d, size_t shared_secret_len); void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e, uint8_t *shared_secret_d, uint8_t *public_key, uint8_t *ciphertext, OQS_KEM *kem); /* This function gives an example of the operations performed by both * the decapsulator and the encapsulator in a single KEM session, * using only compile-time macros and allocating variables * statically on the stack, calling a specific algorithm's functions * directly. * * The macros OQS_KEM_frodokem_640_aes_length_* and the functions * OQS_KEM_frodokem_640_aes_* are only defined if the algorithm * FrodoKEM-640-AES was enabled at compile-time which must be * checked using the OQS_ENABLE_KEM_frodokem_640_aes macro. * * , which is included in , contains macros * indicating which algorithms were enabled when this instance of liboqs * was compiled. */ OQS_STATUS example_stack() { #ifndef OQS_ENABLE_KEM_frodokem_640_aes // if FrodoKEM-640-AES was not enabled at compile-time printf("[example_stack] OQS_KEM_frodokem_640_aes was not enabled at " "compile-time.\n"); return OQS_ERROR; #else uint8_t public_key[OQS_KEM_frodokem_640_aes_length_public_key]; uint8_t secret_key[OQS_KEM_frodokem_640_aes_length_secret_key]; uint8_t ciphertext[OQS_KEM_frodokem_640_aes_length_ciphertext]; uint8_t shared_secret_e[OQS_KEM_frodokem_640_aes_length_shared_secret]; uint8_t shared_secret_d[OQS_KEM_frodokem_640_aes_length_shared_secret]; OQS_STATUS rc = OQS_KEM_frodokem_640_aes_keypair(public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_keypair failed!\n"); cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key, shared_secret_e, shared_secret_d, OQS_KEM_frodokem_640_aes_length_shared_secret); return OQS_ERROR; } rc = OQS_KEM_frodokem_640_aes_encaps(ciphertext, shared_secret_e, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_encaps failed!\n"); cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key, shared_secret_e, shared_secret_d, OQS_KEM_frodokem_640_aes_length_shared_secret); return OQS_ERROR; } rc = OQS_KEM_frodokem_640_aes_decaps(shared_secret_d, ciphertext, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_decaps failed!\n"); cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key, shared_secret_e, shared_secret_d, OQS_KEM_frodokem_640_aes_length_shared_secret); return OQS_ERROR; } printf("[example_stack] OQS_KEM_frodokem_640_aes operations completed.\n"); return OQS_SUCCESS; // success! #endif } ``` -------------------------------- ### Public KEM Function Call Example Source: https://github.com/open-quantum-safe/liboqs/wiki/Coding-conventions Illustrates how to call a public Key Encapsulation Mechanism (KEM) function and check for success using the OQS_SUCCESS status. ```c ret = OQS_KEM_encaps(...); if (ret == OQS_SUCCESS) { ... } ``` -------------------------------- ### Construct KEM Object and Get Parameters Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Use OQS_KEM_new to create a KEM object for a specific algorithm. Check if the algorithm is available and print its parameters. Ensure OQS_init() and OQS_destroy() are called. ```c #include #include #include int main(void) { OQS_init(); // Enumerate available KEMs printf("Available KEMs (%d total):\n", OQS_KEM_alg_count()); for (int i = 0; i < OQS_KEM_alg_count(); i++) { const char *name = OQS_KEM_alg_identifier(i); printf(" [%s] %s\n", OQS_KEM_alg_is_enabled(name) ? "enabled " : "disabled", name); } // Construct a KEM object (runtime algorithm selection) OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ml_kem_768); if (kem == NULL) { fprintf(stderr, "ML-KEM-768 not available\n"); OQS_destroy(); return EXIT_FAILURE; } printf("\nML-KEM-768 parameters:\n"); printf(" Public key length : %zu bytes\n", kem->length_public_key); printf(" Secret key length : %zu bytes\n", kem->length_secret_key); printf(" Ciphertext length : %zu bytes\n", kem->length_ciphertext); printf(" Shared secret len : %zu bytes\n", kem->length_shared_secret); printf(" NIST level : %u\n", kem->claimed_nist_level); printf(" IND-CCA : %s\n", kem->ind_cca ? "yes" : "no"); OQS_KEM_free(kem); OQS_destroy(); return EXIT_SUCCESS; } ``` -------------------------------- ### Dilithium-2 Signature Example (Heap Allocation) Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-signature Performs Dilithium-2 key generation, signing, and verification using dynamic memory allocation on the heap via the generic OQS_SIG object. This method does not require compile-time macro checks for algorithm enablement. ```C /* This function gives an example of the signing operations, * allocating variables dynamically on the heap and calling the generic * OQS_SIG object. * * This does not require the use of compile-time macros to check if the * algorithm in question was enabled at compile-time; instead, the caller * must check that the OQS_SIG object returned is not NULL. */ static OQS_STATUS example_heap(void) { OQS_SIG *sig = NULL; uint8_t *public_key = NULL; uint8_t *secret_key = NULL; uint8_t *message = NULL; uint8_t *signature = NULL; size_t message_len = MESSAGE_LEN; size_t signature_len; OQS_STATUS rc; sig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); if (sig == NULL) { printf("[example_heap] OQS_SIG_alg_dilithium_2 was not enabled at compile-time.\n"); return OQS_ERROR; } public_key = malloc(sig->length_public_key); secret_key = malloc(sig->length_secret_key); message = malloc(message_len); signature = malloc(sig->length_signature); if ((public_key == NULL) || (secret_key == NULL) || (message == NULL) || (signature == NULL)) { fprintf(stderr, "ERROR: malloc failed!\n"); cleanup_heap(public_key, secret_key, message, signature, sig); return OQS_ERROR; } // let's create a random test message to sign OQS_randombytes(message, message_len); rc = OQS_SIG_keypair(sig, public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_keypair failed!\n"); cleanup_heap(public_key, secret_key, message, signature, sig); return OQS_ERROR; } rc = OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_sign failed!\n"); cleanup_heap(public_key, secret_key, message, signature, sig); return OQS_ERROR; } rc = OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_SIG_verify failed!\n"); cleanup_heap(public_key, secret_key, message, signature, sig); return OQS_ERROR; } printf("[example_heap] OQS_SIG_dilithium_2 operations completed.\n"); ``` -------------------------------- ### Random Number Generation with liboqs Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Shows how to use `OQS_randombytes` to generate random data. Demonstrates switching between system and OpenSSL RNGs, and installing a custom RNG callback for specific environments. ```c #include #include #include // Custom RNG callback (e.g., from an HSM or embedded TRNG) static void my_rng(uint8_t *buf, size_t len) { // Replace with hardware entropy source in production for (size_t i = 0; i < len; i++) { buf[i] = (uint8_t)(i ^ 0xA5); // placeholder } } int main(void) { OQS_init(); // Use system RNG (default) uint8_t buf1[32]; OQS_randombytes(buf1, sizeof(buf1)); printf("System RNG (first 8 bytes): "); for (int i = 0; i < 8; i++) printf("%02x", buf1[i]); printf("\n"); // Switch to OpenSSL RNG if (OQS_randombytes_switch_algorithm(OQS_RAND_alg_openssl) == OQS_SUCCESS) { uint8_t buf2[32]; OQS_randombytes(buf2, sizeof(buf2)); printf("OpenSSL RNG (first 8 bytes): "); for (int i = 0; i < 8; i++) printf("%02x", buf2[i]); printf("\n"); } // Install a custom RNG (e.g., for embedded/FIPS environments) OQS_randombytes_custom_algorithm(my_rng); uint8_t buf3[32]; OQS_randombytes(buf3, sizeof(buf3)); printf("Custom RNG (first 8 bytes): "); for (int i = 0; i < 8; i++) printf("%02x", buf3[i]); printf("\n"); OQS_destroy(); return EXIT_SUCCESS; } ``` -------------------------------- ### Deterministic KEM Example with Explicit Seeds Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Shows how to perform KEM operations deterministically using explicit seeds for key generation and encapsulation. This is useful for reproducible tests. Ensure seeds are properly managed and securely generated in production. ```c #include #include #include #include int main(void) { OQS_init(); OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ml_kem_512); if (!kem) { OQS_destroy(); return EXIT_FAILURE; } // Allocate fixed seeds (in practice, use secure random or NIST test vectors) uint8_t *keypair_seed = OQS_MEM_malloc(kem->length_keypair_seed); uint8_t *encaps_seed = OQS_MEM_malloc(kem->length_encaps_seed); uint8_t *public_key = OQS_MEM_malloc(kem->length_public_key); uint8_t *secret_key = OQS_MEM_malloc(kem->length_secret_key); uint8_t *ciphertext = OQS_MEM_malloc(kem->length_ciphertext); uint8_t *shared_secret = OQS_MEM_malloc(kem->length_shared_secret); // Fill seeds (example: all-zero seed for reproducibility; use real entropy in production) memset(keypair_seed, 0x00, kem->length_keypair_seed); memset(encaps_seed, 0x01, kem->length_encaps_seed); // Deterministic key generation if (OQS_KEM_keypair_derand(kem, public_key, secret_key, keypair_seed) != OQS_SUCCESS) { fprintf(stderr, "Deterministic keypair failed\n"); goto cleanup; } // Deterministic encapsulation if (OQS_KEM_encaps_derand(kem, ciphertext, shared_secret, public_key, encaps_seed) != OQS_SUCCESS) { fprintf(stderr, "Deterministic encaps failed\n"); goto cleanup; } printf("Deterministic KEM (ML-KEM-512) succeeded\n"); printf("Shared secret (first 8 bytes): "); for (int i = 0; i < 8; i++) printf("%02x", shared_secret[i]); printf("...\n"); cleanup: OQS_MEM_secure_free(keypair_seed, kem->length_keypair_seed); OQS_MEM_secure_free(encaps_seed, kem->length_encaps_seed); OQS_MEM_secure_free(secret_key, kem->length_secret_key); OQS_MEM_secure_free(shared_secret, kem->length_shared_secret); OQS_MEM_insecure_free(public_key); OQS_MEM_insecure_free(ciphertext); OQS_KEM_free(kem); OQS_destroy(); return EXIT_SUCCESS; } ``` -------------------------------- ### KEM Operations: Stack and Heap Examples Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-KEM This C code demonstrates KEM operations using both stack and heap memory allocations. It includes key generation, encapsulation, and decapsulation, along with memory cleanup functions. ```c int example_stack() { OQS_KEM *kem = NULL; uint8_t *public_key = NULL; uint8_t *secret_key = NULL; uint8_t *ciphertext = NULL; uint8_t *shared_secret_e = NULL; uint8_t *shared_secret_d = NULL; kem = OQS_KEM_new(OQS_KEM_alg_frodo_640_aes); if (kem == NULL) { fprintf(stderr, "ERROR: OQS_KEM_new failed!\n"); return OQS_ERROR; } public_key = malloc(kem->length_public_key); secret_key = malloc(kem->length_secret_key); shared_secret_e = malloc(kem->length_shared_secret); shared_secret_d = malloc(kem->length_shared_secret); ciphertext = malloc(kem->length_ciphertext); if (public_key == NULL || secret_key == NULL || shared_secret_e == NULL || shared_secret_d == NULL || ciphertext == NULL) { fprintf(stderr, "ERROR: malloc failed!\n"); cleanup_stack(secret_key, kem->length_secret_key, shared_secret_e, shared_secret_d, kem->length_shared_secret); OQS_KEM_free(kem); return OQS_ERROR; } rc = OQS_KEM_keypair(kem, public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_keypair failed!\n"); cleanup_stack(secret_key, kem->length_secret_key, shared_secret_e, shared_secret_d, kem->length_shared_secret); OQS_KEM_free(kem); return OQS_ERROR; } rc = OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_encaps failed!\n"); cleanup_stack(secret_key, kem->length_secret_key, shared_secret_e, shared_secret_d, kem->length_shared_secret); OQS_KEM_free(kem); return OQS_ERROR; } rc = OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_decaps failed!\n"); cleanup_stack(secret_key, kem->length_secret_key, shared_secret_e, shared_secret_d, kem->length_shared_secret); OQS_KEM_free(kem); return OQS_ERROR; } printf("[example_stack] OQS_KEM_frodokem_640_aes operations completed.\n"); cleanup_stack(secret_key, kem->length_secret_key, shared_secret_e, shared_secret_d, kem->length_shared_secret); OQS_KEM_free(kem); return OQS_SUCCESS; // success } int example_heap() { OQS_KEM *kem = NULL; uint8_t *public_key = NULL; uint8_t *secret_key = NULL; uint8_t *ciphertext = NULL; uint8_t *shared_secret_e = NULL; uint8_t *shared_secret_d = NULL; kem = OQS_KEM_new(OQS_KEM_alg_frodo_640_aes); if (kem == NULL) { fprintf(stderr, "ERROR: OQS_KEM_new failed!\n"); return OQS_ERROR; } public_key = OQS_MEM_secure_malloc(kem->length_public_key); secret_key = OQS_MEM_secure_malloc(kem->length_secret_key); shared_secret_e = OQS_MEM_secure_malloc(kem->length_shared_secret); shared_secret_d = OQS_MEM_secure_malloc(kem->length_shared_secret); ciphertext = OQS_MEM_insecure_malloc(kem->length_ciphertext); if (public_key == NULL || secret_key == NULL || shared_secret_e == NULL || shared_secret_d == NULL || ciphertext == NULL) { fprintf(stderr, "ERROR: OQS_MEM_secure_malloc or OQS_MEM_insecure_malloc failed!\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_ERROR; } rc = OQS_KEM_keypair(kem, public_key, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_keypair failed!\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_ERROR; } rc = OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_encaps failed!\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_ERROR; } rc = OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "ERROR: OQS_KEM_decaps failed!\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_ERROR; } printf("[example_heap] OQS_KEM_frodokem_640_aes operations completed.\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_SUCCESS; // success } int main(void) { if (example_stack() == OQS_SUCCESS && example_heap() == OQS_SUCCESS) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } } void cleanup_stack(uint8_t *secret_key, size_t secret_key_len, uint8_t *shared_secret_e, uint8_t *shared_secret_d, size_t shared_secret_len) { OQS_MEM_cleanse(secret_key, secret_key_len); OQS_MEM_cleanse(shared_secret_e, shared_secret_len); OQS_MEM_cleanse(shared_secret_d, shared_secret_len); } void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e, uint8_t *shared_secret_d, uint8_t *public_key, uint8_t *ciphertext, OQS_KEM *kem) { if (kem != NULL) { OQS_MEM_secure_free(secret_key, kem->length_secret_key); OQS_MEM_secure_free(shared_secret_e, kem->length_shared_secret); OQS_MEM_secure_free(shared_secret_d, kem->length_shared_secret); } OQS_MEM_insecure_free(public_key); OQS_MEM_insecure_free(ciphertext); OQS_KEM_free(kem); } ``` -------------------------------- ### Heap-allocated FrodoKEM-640-AES Example using Generic API Source: https://github.com/open-quantum-safe/liboqs/wiki/Minimal-example-of-a-post-quantum-KEM Performs key generation, encapsulation, and decapsulation using FrodoKEM-640-AES with variables allocated dynamically on the heap and utilizing the generic OQS_KEM API. This approach checks for algorithm availability at runtime via OQS_KEM_new. ```C /* This function gives an example of the operations performed by both * the decapsulator and the encapsulator in a single KEM session, * allocating variables dynamically on the heap and calling the generic * OQS_KEM object. * * This does not require the use of compile-time macros to check if the * algorithm in question was enabled at compile-time; instead, the caller * must check that the OQS_KEM object returned is not NULL. */ OQS_STATUS example_heap() { OQS_KEM *kem = NULL; uint8_t *public_key = NULL; uint8_t *secret_key = NULL; uint8_t *ciphertext = NULL; uint8_t *shared_secret_e = NULL; uint8_t *shared_secret_d = NULL; kem = OQS_KEM_new(OQS_KEM_alg_frodokem_640_aes); if (kem == NULL) { printf("[example_heap] OQS_KEM_frodokem_640_aes was not enabled at " "compile-time.\n"); return OQS_ERROR; } public_key = malloc(kem->length_public_key); secret_key = malloc(kem->length_secret_key); ciphertext = malloc(kem->length_ciphertext); shared_secret_e = malloc(kem->length_shared_secret); shared_secret_d = malloc(kem->length_shared_secret); if ((public_key == NULL) || (secret_key == NULL) || (ciphertext == NULL) || (shared_secret_e == NULL) || (shared_secret_d == NULL)) { fprintf(stderr, "ERROR: malloc failed!\n"); cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key, ciphertext, kem); return OQS_ERROR; } OQS_STATUS rc = OQS_KEM_keypair(kem, public_key, secret_key); if (rc != OQS_SUCCESS) { ``` -------------------------------- ### Create Build Directory Source: https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/bike/additional_r4/README.md Use these commands to create a build directory and navigate into it before compiling. ```bash mkdir build cd build ``` -------------------------------- ### Add Executable for Stateful SIG API Example Source: https://github.com/open-quantum-safe/liboqs/blob/main/tests/CMakeLists.txt Defines an executable for the stateful SIG API example, linking it against test dependencies. ```cmake add_executable(example_sig_stfl example_sig_stfl.c) target_link_libraries(example_sig_stfl PRIVATE ${TEST_DEPS}) ``` -------------------------------- ### Full Signature Cycle: Keypair, Sign, Verify, and Tamper Detection Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Demonstrates the complete signature process: generating a key pair, signing a message, verifying the signature, and confirming that a tampered message is rejected. Ensure OQS_init() and OQS_destroy() are called, and use OQS_MEM_secure_free for secret keys. ```c #include #include #include #include #define MESSAGE_LEN 64 int main(void) { OQS_init(); OQS_SIG *sig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65); if (!sig) { OQS_destroy(); return EXIT_FAILURE; } uint8_t *public_key = OQS_MEM_malloc(sig->length_public_key); uint8_t *secret_key = OQS_MEM_malloc(sig->length_secret_key); uint8_t *message = OQS_MEM_malloc(MESSAGE_LEN); uint8_t *signature = OQS_MEM_malloc(sig->length_signature); size_t signature_len; if (!public_key || !secret_key || !message || !signature) { fprintf(stderr, "Allocation failed\n"); goto cleanup; } // Fill message with random bytes OQS_randombytes(message, MESSAGE_LEN); // Key generation if (OQS_SIG_keypair(sig, public_key, secret_key) != OQS_SUCCESS) { fprintf(stderr, "Keypair generation failed\n"); goto cleanup; } // Sign if (OQS_SIG_sign(sig, signature, &signature_len, message, MESSAGE_LEN, secret_key) != OQS_SUCCESS) { fprintf(stderr, "Signing failed\n"); goto cleanup; } printf("Signature length: %zu bytes\n", signature_len); // Verify — must return OQS_SUCCESS if (OQS_SIG_verify(sig, message, MESSAGE_LEN, signature, signature_len, public_key) != OQS_SUCCESS) { fprintf(stderr, "Verification FAILED\n"); goto cleanup; } printf("Signature verified successfully\n"); // Tamper detection: mutate one byte and re-verify message[0] ^= 0xFF; if (OQS_SIG_verify(sig, message, MESSAGE_LEN, signature, signature_len, public_key) == OQS_SUCCESS) { fprintf(stderr, "ERROR: tampered message accepted\n"); } else { printf("Tampered message correctly rejected\n"); } cleanup: OQS_MEM_secure_free(secret_key, sig->length_secret_key); OQS_MEM_insecure_free(public_key); OQS_MEM_insecure_free(message); OQS_MEM_insecure_free(signature); OQS_SIG_free(sig); OQS_destroy(); return EXIT_SUCCESS; } // Expected output: // Signature length: 3309 bytes // Signature verified successfully // Tampered message correctly rejected ``` -------------------------------- ### Install Dependencies for Cross-compiling on Arch Linux Source: https://github.com/open-quantum-safe/liboqs/wiki/Platform-specific-notes-for-building-liboqs Installs the necessary packages for cross-compiling liboqs for Windows on Arch Linux, including CMake, toolchain, and ninja. ```bash pacman -S git \ mingw-w64-cmake \ mingw-w64-openssl \ mingw-w64-toolchain \ ninja ``` -------------------------------- ### Run Benchmarks and Tests for liboqs Source: https://context7.com/open-quantum-safe/liboqs/llms.txt Commands to execute the test harnesses, KAT generators, and benchmarking programs included in the liboqs build. Demonstrates running all tests, specific algorithms, and memory usage checks. ```bash cd build # Run all tests via the build system ninja run_tests ``` ```bash # Test all enabled KEMs ./tests/test_kem ``` ```bash # Test a single KEM algorithm ./tests/test_kem ML-KEM-768 ``` ```bash # Benchmark all KEM algorithms (operations/second + cycles) ./tests/speed_kem ``` ```bash # Benchmark a specific algorithm ./tests/speed_kem ML-KEM-768 ``` ```bash # Benchmark signature schemes ./tests/speed_sig ML-DSA-65 ``` ```bash # Generate NIST Known Answer Test (KAT) vectors for KEMs ./tests/kat_kem ``` ```bash # Generate KAT vectors for signature schemes ./tests/kat_sig ``` ```bash # Check memory usage of KEM operations ./tests/test_kem_mem ```