Skip to content

Commit

Permalink
Added stateful example application and review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ashman-p committed Dec 9, 2023
1 parent a7a0952 commit 82a7d48
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ The list below indicates all algorithms supported by liboqs, but not all those a
- **Falcon**: Falcon-512, Falcon-1024
- **SPHINCS+-SHA2**: SPHINCS+-SHA2-128f-simple, SPHINCS+-SHA2-128s-simple, SPHINCS+-SHA2-192f-simple, SPHINCS+-SHA2-192s-simple, SPHINCS+-SHA2-256f-simple, SPHINCS+-SHA2-256s-simple
- **SPHINCS+-SHAKE**: SPHINCS+-SHAKE-128f-simple, SPHINCS+-SHAKE-128s-simple, SPHINCS+-SHAKE-192f-simple, SPHINCS+-SHAKE-192s-simple, SPHINCS+-SHAKE-256f-simple, SPHINCS+-SHAKE-256s-simple
- **XMSS**: Variants of XMSS stateful signature scheames. e.g XMSS-SHA2_10_256, XMSSMT-SHA2_60/6, XMSSMT-SHA2_40/4_256
- **LMS**: Variants of LMS stateful signature scheames. e.g LMS_SHA256_H5_W8, LMS_SHA256_H10_W8, LMS_SHA256_H10_W8_H10_W8
- **XMSS**: XMSS-SHA2_10_256, XMSS-SHA2_16_256, XMSS-SHA2_20_256, XMSS-SHAKE_10_256, XMSS-SHAKE_16_256, XMSS-SHAKE_20_256, XMSS-SHA2_10_512, XMSS-SHA2_16_512, XMSS-SHA2_20_512, XMSS-SHAKE_10_512, XMSS-SHAKE_16_512, XMSS-SHAKE_20_512, XMSSMT-SHA2_20/2_256, XMSSMT-SHA2_20/4_256, XMSSMT-SHA2_40/2_256, XMSSMT-SHA2_40/4_256, XMSSMT-SHA2_40/8_256, XMSSMT-SHA2_60/3_256, XMSSMT-SHA2_60/6_256, XMSSMT-SHA2_60/12_256, XMSSMT-SHAKE_20/2_256, XMSSMT-SHAKE_20/4_256, XMSSMT-SHAKE_40/2_256, XMSSMT-SHAKE_40/4_256, XMSSMT-SHAKE_40/8_256, XMSSMT-SHAKE_60/3_256, XMSSMT-SHAKE_60/6_256, XMSSMT-SHAKE_60/12_256
- **LMS**: LMS_SHA256_H5_W1, LMS_SHA256_H5_W2, LMS_SHA256_H5_W4, LMS_SHA256_H5_W8, LMS_SHA256_H10_W1, LMS_SHA256_H10_W2, LMS_SHA256_H10_W4, LMS_SHA256_H10_W8, LMS_SHA256_H15_W1, LMS_SHA256_H15_W2, LMS_SHA256_H15_W4, LMS_SHA256_H15_W8, LMS_SHA256_H20_W1, LMS_SHA256_H20_W2, LMS_SHA256_H20_W4, LMS_SHA256_H20_W8, LMS_SHA256_H25_W1, LMS_SHA256_H25_W2, LMS_SHA256_H25_W4, LMS_SHA256_H25_W8, LMS_SHA256_H5_W8_H5_W8, LMS_SHA256_H10_W4_H5_W8, LMS_SHA256_H10_W8_H5_W8, LMS_SHA256_H10_W2_H10_W2, LMS_SHA256_H10_W4_H10_W4, LMS_SHA256_H10_W8_H10_W8, LMS_SHA256_H15_W8_H5_W8, LMS_SHA256_H15_W8_H10_W8, LMS_SHA256_H15_W8_H15_W8, LMS_SHA256_H20_W8_H5_W8, LMS_SHA256_H20_W8_H10_W8, LMS_SHA256_H20_W8_H15_W8, LMS_SHA256_H20_W8_H20_W8
<!--- OQS_TEMPLATE_FRAGMENT_LIST_SIGS_END -->

Note that for algorithms marked with a dagger (†), liboqs contains at least one implementation that uses a large amount of stack space; this may cause failures when run in threads or in constrained environments. For more information, consult the algorithm information sheets in the [docs/algorithms](https://github.com/open-quantum-safe/liboqs/tree/main/docs/algorithms) folder.
Expand Down
16 changes: 9 additions & 7 deletions src/sig_stfl/sig_stfl.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ typedef struct OQS_SIG_STFL_SECRET_KEY {

/**
* Store Secret Key Function
* Callback function used to securely store key data
* Callback function used to securely store key data after a signature generation
* @param[in] sk_buf The serialized secret key data to secure store
* @param[in] buf_len length of data to secure
* @param[in] context application supplied data used to locate where this secret key
Expand All @@ -364,7 +364,8 @@ typedef struct OQS_SIG_STFL_SECRET_KEY {
*
* @param[in] sk secret key pointer to be updated
* @param[in] store_cb callback pointer
* @param[in] context application data related to secret key data/identifier storage
* @param[in] context application data related to secret key data/identifier storage.
* Provided when OQS_SIG_STFL_SECRET_KEY_SET_store_cb() is called.
*/
void (*set_scrt_key_store_cb)(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context);
} OQS_SIG_STFL_SECRET_KEY;
Expand Down Expand Up @@ -532,7 +533,8 @@ OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk);
*
* @param[in] sk secret key pointer to be updated
* @param[in] store_cb callback pointer
* @param[in] context application data related to where how secret key data storage
* @param[in] context application data related to where/how secret key data storage.
* Applications allocates, tracks, deallocates this. Signature generation fails without this set.
*
*/
void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context);
Expand All @@ -551,14 +553,14 @@ void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_st
OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk);

/**
* OQS_SECRET_KEY_STFL_serialize_key .
* OQS_SECRET_KEY_STFL_deserialize_key .
*
* Insert stateful byte string into a secret key object.
* Users are responsible for deallocating buffer `sk_buf`.
*
* @param[in] sk secret key pointer to be serialize
* @param[in] sk_len size of the buffer returned
* @param[in] sk_buf secret key buffer returned. Caller deletes.
* @param[in] sk secret key pointer to be populated
* @param[in] sk_len size of the supplied buffer
* @param[in] sk_buf secret key buffer. Caller deletes.
* @param[in] context application managed data related to where/how secret key data is stored.
*/
OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, size_t key_len, const uint8_t *sk_buf, void *context);
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ target_link_libraries(speed_kem PRIVATE ${API_TEST_DEPS})
add_executable(example_sig example_sig.c)
target_link_libraries(example_sig PRIVATE ${API_TEST_DEPS})

# Stateful SIG API tests
add_executable(example_sig_stfl example_sig_stfl.c)
target_link_libraries(example_sig_stfl PRIVATE ${API_TEST_DEPS})

add_executable(kat_sig kat_sig.c)
target_link_libraries(kat_sig PRIVATE ${API_TEST_DEPS})

Expand Down
133 changes: 133 additions & 0 deletions tests/example_sig_stfl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* example_sig_stfl.c
*
* Minimal example of using a post-quantum stateful signature implemented in liboqs.
*
* SPDX-License-Identifier: MIT
*/

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <oqs/oqs.h>

#define MESSAGE_LEN 50

static OQS_STATUS do_nothing_save(uint8_t *key_buf, size_t buf_len, void *context) {
(void)(context);
(void)(buf_len);
return key_buf != NULL ? OQS_SUCCESS : OQS_ERROR;
}

/* This function gives an example of the signing operations,
* allocating variables dynamically on the heap and calling the
* OQS_SIG_STFL and OQS_SIG_STFL_SECRET_KEY objects.
*
* 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 stfl_example(char *method_name) {

OQS_SIG_STFL *sig = NULL;
uint8_t *public_key = NULL;
OQS_SIG_STFL_SECRET_KEY *secret_key = NULL;
uint8_t *message = NULL;
uint8_t *signature = NULL;
size_t message_len = MESSAGE_LEN;
size_t signature_len;
char *sk_fname = NULL;
OQS_STATUS rc;

/*
* Steps
* 1. create stateful signature object
* 2. create secret key object
* 3. set key storage callback function
* set mutex if necessary
* 4. Generate key-pair
* 5. Signature generation
* 6. verify signature
*/
sig = OQS_SIG_STFL_new(method_name);
if (sig == NULL) {
printf("[Stateful sig] %s new failed.\n", method_name);
return OQS_ERROR;
}

secret_key = OQS_SIG_STFL_SECRET_KEY_new(method_name);
if (secret_key == NULL) {
printf("[Stateful secret key] %s new failed.\n", method_name);
goto err;
}

/*
* Allocate storage for public key, secret key filename, message and signature
*/
public_key = malloc(sig->length_public_key);
sk_fname = malloc(strlen(method_name) + strlen(".sk"));
message = malloc(message_len);
signature = malloc(sig->length_signature);
if ((public_key == NULL) || (message == NULL) || (signature == NULL) || (sk_fname == NULL)) {
fprintf(stderr, "ERROR: malloc failed!\n");
goto err;
}

strcpy(sk_fname, method_name);
strcat(sk_fname, ".sk");
/*
* set callback to securely store the secret key
* secret keys are one time use only. So after a signature gen
* the secret key most be advanced to the next
*/
OQS_SIG_STFL_SECRET_KEY_SET_store_cb(secret_key, do_nothing_save, (void *)sk_fname);

/*
* Generate key pair
*/
rc = OQS_SIG_STFL_keypair(sig, public_key, secret_key);
if (rc != OQS_SUCCESS) {
printf("[Stateful key pair generation] %s new failed.\n", method_name);
goto err;
}

// let's create a random test message to sign
OQS_randombytes(message, message_len);

rc = OQS_SIG_STFL_sign(sig, signature, &signature_len, message, message_len, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_STFL_sign failed %s!\n", method_name);
goto err;
}
rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_STFL_verify failed %s!\n", method_name);
goto err;
}

printf("[Stateful signature] %s operations completed.\n", method_name);
err:
//cleanup
OQS_MEM_insecure_free(public_key);
OQS_MEM_insecure_free(sk_fname);
OQS_MEM_insecure_free(message);
OQS_MEM_insecure_free(signature);
OQS_SIG_STFL_free(sig);
OQS_SIG_STFL_SECRET_KEY_free(secret_key);

return rc;
}

int main(void) {
OQS_init();
if (stfl_example("XMSS-SHA2_10_256") == OQS_SUCCESS && stfl_example("LMS_SHA256_H10_W4") == OQS_SUCCESS) {
OQS_destroy();
return EXIT_SUCCESS;
} else {
OQS_destroy();
return EXIT_FAILURE;
}
}

0 comments on commit 82a7d48

Please sign in to comment.