mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-10-04 00:02:01 -04:00
add C++ linking test (#1971)
Signed-off-by: Aiden Fox Ivey <aiden@aidenfoxivey.com>
This commit is contained in:
parent
60af4a99e2
commit
05257da106
44
.github/workflows/basic.yml
vendored
44
.github/workflows/basic.yml
vendored
@ -6,7 +6,6 @@ permissions:
|
||||
on: [workflow_call, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
|
||||
workflowcheck:
|
||||
name: Check validity of GitHub workflows
|
||||
runs-on: ubuntu-latest
|
||||
@ -19,7 +18,7 @@ jobs:
|
||||
|
||||
stylecheck:
|
||||
name: Check code formatting
|
||||
needs: [ workflowcheck ]
|
||||
needs: [workflowcheck]
|
||||
runs-on: ubuntu-latest
|
||||
container: openquantumsafe/ci-ubuntu-latest:latest
|
||||
steps:
|
||||
@ -34,7 +33,7 @@ jobs:
|
||||
|
||||
upstreamcheck:
|
||||
name: Check upstream code is properly integrated
|
||||
needs: [ workflowcheck ]
|
||||
needs: [workflowcheck]
|
||||
runs-on: ubuntu-latest
|
||||
container: openquantumsafe/ci-ubuntu-latest:latest
|
||||
steps:
|
||||
@ -47,19 +46,19 @@ jobs:
|
||||
git config --global --add safe.directory "$PWD" && \
|
||||
echo "LIBOQS_DIR=$PWD" >> "$GITHUB_ENV"
|
||||
- name: Verify copy_from_upstream state after copy
|
||||
working-directory: 'scripts/copy_from_upstream'
|
||||
working-directory: "scripts/copy_from_upstream"
|
||||
run: |
|
||||
python3 copy_from_upstream.py copy && \
|
||||
! git status | grep -i modified
|
||||
- name: Verify copy_from_upstream state after libjade
|
||||
working-directory: 'scripts/copy_from_upstream'
|
||||
working-directory: "scripts/copy_from_upstream"
|
||||
run: |
|
||||
python3 copy_from_upstream.py libjade && \
|
||||
! git status | grep -i modified
|
||||
|
||||
buildcheck:
|
||||
name: Check that code passes a basic build
|
||||
needs: [ workflowcheck, stylecheck, upstreamcheck ]
|
||||
needs: [workflowcheck, stylecheck, upstreamcheck]
|
||||
runs-on: ubuntu-latest
|
||||
container: openquantumsafe/ci-ubuntu-latest:latest
|
||||
env:
|
||||
@ -86,10 +85,39 @@ jobs:
|
||||
run: ninja gen_docs
|
||||
working-directory: build
|
||||
|
||||
|
||||
cppcheck:
|
||||
name: Check C++ linking with example program
|
||||
runs-on: ubuntu-latest
|
||||
container: openquantumsafe/ci-ubuntu-latest:latest
|
||||
env:
|
||||
SIG_NAME: dilithium_2
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # pin@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
cmake -GNinja -DOQS_STRICT_WARNINGS=ON \
|
||||
-GNinja \
|
||||
-DOQS_MINIMAL_BUILD="SIG_$SIG_NAME" \
|
||||
--warn-uninitialized .. > config.log 2>&1 && \
|
||||
cat config.log && \
|
||||
cmake -LA -N .. && \
|
||||
! (grep -i "uninitialized variable" config.log)
|
||||
- name: Build liboqs
|
||||
run: ninja
|
||||
working-directory: build
|
||||
- name: Link with C++ program
|
||||
run: |
|
||||
g++ ../cpp/sig_linking_test.cpp -g \
|
||||
-I./include -L./lib -loqs -lcrypto -std=c++11 -o example_sig && \
|
||||
./example_sig
|
||||
working-directory: build
|
||||
|
||||
fuzzbuildcheck:
|
||||
name: Check that code passes a basic fuzzing build
|
||||
needs: [ workflowcheck, stylecheck, upstreamcheck ]
|
||||
needs: [workflowcheck, stylecheck, upstreamcheck]
|
||||
runs-on: ubuntu-latest
|
||||
container: openquantumsafe/ci-ubuntu-latest:latest
|
||||
env:
|
||||
|
182
cpp/sig_linking_test.cpp
Normal file
182
cpp/sig_linking_test.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* example_sig.cpp
|
||||
*
|
||||
* Minimal C++ example of using a post-quantum signature implemented in liboqs.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <oqs/oqs.h>
|
||||
|
||||
constexpr size_t MESSAGE_LEN = 50;
|
||||
|
||||
/* Cleaning up memory etc */
|
||||
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len);
|
||||
|
||||
struct OQSSecureDeleter {
|
||||
size_t length;
|
||||
|
||||
explicit OQSSecureDeleter(size_t len) : length(len) {}
|
||||
|
||||
void operator()(uint8_t* ptr) const {
|
||||
if (ptr) {
|
||||
OQS_MEM_secure_free(ptr, length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct OQSInsecureDeleter {
|
||||
void operator()(uint8_t* ptr) {
|
||||
if (ptr) {
|
||||
OQS_MEM_insecure_free(ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct OQSSigDeleter {
|
||||
void operator()(OQS_SIG* sig) {
|
||||
if (sig) {
|
||||
OQS_SIG_free(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.
|
||||
*
|
||||
* <oqs/oqsconfig.h>, which is included in <oqs/oqs.h>, 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) {
|
||||
std::cerr << "ERROR: OQS_SIG_dilithium_2_keypair failed!" << std::endl;
|
||||
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) {
|
||||
std::cerr << "ERROR: OQS_SIG_dilithium_2_sign failed!" << std::endl;
|
||||
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) {
|
||||
std::cerr << "ERROR: OQS_SIG_dilithium_2_verify failed!" << std::endl;
|
||||
cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key);
|
||||
return OQS_ERROR;
|
||||
}
|
||||
|
||||
std::cout << "[example_stack] OQS_SIG_dilithium_2 operations completed" << std::endl;
|
||||
cleanup_stack(secret_key, OQS_SIG_dilithium_2_length_secret_key);
|
||||
return OQS_SUCCESS; // success!
|
||||
|
||||
#else
|
||||
|
||||
std::cout << "[example_stack] OQS_SIG_dilithium_2 was not enabled at compile-time" << std::endl;
|
||||
return OQS_SUCCESS;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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 nullptr.
|
||||
*/
|
||||
static OQS_STATUS example_heap(void) {
|
||||
|
||||
#ifdef OQS_ENABLE_SIG_dilithium_2
|
||||
|
||||
size_t message_len = MESSAGE_LEN;
|
||||
size_t signature_len;
|
||||
OQS_STATUS rc;
|
||||
|
||||
std::unique_ptr<OQS_SIG, OQSSigDeleter> sig(OQS_SIG_new((OQS_SIG_alg_dilithium_2)));
|
||||
if (sig == nullptr) {
|
||||
throw std::runtime_error("[example_heap] OQS_SIG_alg_dilithium_2 was not enabled at compile-time.");
|
||||
}
|
||||
std::unique_ptr<uint8_t[], OQSInsecureDeleter> public_key(static_cast<uint8_t*>(malloc(sig->length_public_key)));
|
||||
std::unique_ptr<uint8_t[], OQSSecureDeleter> secret_key(static_cast<uint8_t*>(malloc(sig->length_secret_key)), OQSSecureDeleter(sig->length_secret_key));
|
||||
std::unique_ptr<uint8_t[], OQSInsecureDeleter> message(static_cast<uint8_t*>(malloc(message_len)));
|
||||
std::unique_ptr<uint8_t[], OQSInsecureDeleter> signature(static_cast<uint8_t*>(malloc(sig->length_signature)));
|
||||
if ((public_key == nullptr) || (secret_key == nullptr) || (message == nullptr) || (signature == nullptr)) {
|
||||
throw std::runtime_error("ERROR: malloc failed!");
|
||||
}
|
||||
|
||||
// let's create a random test message to sign
|
||||
OQS_randombytes(message.get(), message_len);
|
||||
|
||||
rc = OQS_SIG_keypair(sig.get(), public_key.get(), secret_key.get());
|
||||
if (rc != OQS_SUCCESS) {
|
||||
throw std::runtime_error("ERROR: OQS_SIG_keypair failed!");
|
||||
}
|
||||
rc = OQS_SIG_sign(sig.get(), signature.get(), &signature_len, message.get(), message_len, secret_key.get());
|
||||
if (rc != OQS_SUCCESS) {
|
||||
throw std::runtime_error("ERROR: OQS_SIG_sign failed!");
|
||||
}
|
||||
rc = OQS_SIG_verify(sig.get(), message.get(), message_len, signature.get(), signature_len, public_key.get());
|
||||
if (rc != OQS_SUCCESS) {
|
||||
throw std::runtime_error("ERROR: OQS_SIG_verify failed!");
|
||||
}
|
||||
|
||||
std::cout << "[example_heap] OQS_SIG_dilithium_2 operations completed." << std::endl;
|
||||
return OQS_SUCCESS; // success
|
||||
#else
|
||||
|
||||
std::cout << "[example_heap] OQS_SIG_dilithium_2 was not enabled at compile-time." << std::endl;
|
||||
return OQS_SUCCESS;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
OQS_init();
|
||||
try {
|
||||
example_stack();
|
||||
example_heap();
|
||||
}
|
||||
catch (std::exception e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
OQS_destroy();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
OQS_destroy();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len) {
|
||||
OQS_MEM_cleanse(secret_key, secret_key_len);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user