From d364b337cfc646cbd2d135088ff8c3de605608d9 Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Sun, 24 Sep 2023 18:09:10 -0400 Subject: [PATCH 1/6] Add mutex protection around access to stateful secret key --- src/sig_stfl/lms/sig_stfl_lms.c | 12 +- src/sig_stfl/lms/sig_stfl_lms_functions.c | 31 +- src/sig_stfl/sig_stfl.c | 49 +++ src/sig_stfl/sig_stfl.h | 85 ++++- tests/test_sig_stfl.c | 362 +++++++++++++++++++++- 5 files changed, 520 insertions(+), 19 deletions(-) diff --git a/src/sig_stfl/lms/sig_stfl_lms.c b/src/sig_stfl/lms/sig_stfl_lms.c index 582b50b3e4..7f50424160 100644 --- a/src/sig_stfl/lms/sig_stfl_lms.c +++ b/src/sig_stfl/lms/sig_stfl_lms.c @@ -114,7 +114,17 @@ void OQS_SECRET_KEY_LMS_free(OQS_SIG_STFL_SECRET_KEY *sk) { /* Convert LMS secret key object to byte string */ static OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr) { - return oqs_serialize_lms_key(sk, sk_len, sk_buf_ptr); + OQS_STATUS status; + if (sk->lock_key && sk->mutex) { + sk->lock_key(sk->mutex); + } + + status = oqs_serialize_lms_key(sk, sk_len, sk_buf_ptr); + + if (sk->unlock_key && sk->mutex) { + sk->unlock_key(sk->mutex); + } + return status; } /* Insert lms byte string in an LMS secret key object */ diff --git a/src/sig_stfl/lms/sig_stfl_lms_functions.c b/src/sig_stfl/lms/sig_stfl_lms_functions.c index d918cbdac4..59cd49415f 100644 --- a/src/sig_stfl/lms/sig_stfl_lms_functions.c +++ b/src/sig_stfl/lms/sig_stfl_lms_functions.c @@ -47,7 +47,7 @@ typedef struct OQS_LMS_KEY_DATA { OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signature_length, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { - + OQS_STATUS status = OQS_ERROR; OQS_STATUS rc_keyupdate = OQS_ERROR; oqs_lms_key_data *lms_key_data = NULL; const OQS_SIG_STFL_SECRET_KEY *sk; @@ -59,6 +59,11 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signatu return OQS_ERROR; } + /* Lock secret to ensure OTS use */ + if ((secret_key->lock_key) && (secret_key->mutex)) { + secret_key->lock_key(secret_key->mutex); + } + /* * Don't even attempt signing without a way to safe the updated private key */ @@ -94,16 +99,23 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signatu goto err; } - OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); - return OQS_SUCCESS; + status = OQS_SUCCESS; + goto passed; err: - OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); if (*signature_length) { memset(signature, 0, *signature_length); } *signature_length = 0; - return OQS_ERROR; + +passed: + OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); + + /* Unlock secret to ensure OTS use */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } + return status; } OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_verify(const uint8_t *message, size_t message_len, @@ -128,8 +140,17 @@ OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_left(unsigned long long *remain, const if (remain == NULL || secret_key == NULL) { return OQS_ERROR; } + /* Lock secret key to ensure data integrity use */ + if ((secret_key->lock_key) && (secret_key->mutex)) { + secret_key->lock_key(secret_key->mutex); + } remain = 0; + + /* Unlock secret key */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } return OQS_SUCCESS; } diff --git a/src/sig_stfl/sig_stfl.c b/src/sig_stfl/sig_stfl.c index 5480af5dd2..fe7a2b61d4 100644 --- a/src/sig_stfl/sig_stfl.c +++ b/src/sig_stfl/sig_stfl.c @@ -716,3 +716,52 @@ OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_deserialize_key(OQS_SIG_STFL_SECRET_KEY * return sk->deserialize_key(sk, key_len, sk_buf, context); } + + + +/* OQS_SIG_STFL_SECRET_KEY_SET_lock callback function*/ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_lock(OQS_SIG_STFL_SECRET_KEY *sk, lock_key lock) { + if (sk == NULL) { + return; + } + sk->lock_key = lock; +} + +/* OQS_SIG_STFL_SECRET_KEY_SET_unlock callback function */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_unlock(OQS_SIG_STFL_SECRET_KEY *sk, unlock_key unlock) { + if (sk == NULL) { + return; + } + sk->unlock_key = unlock; +} + +/* OQS_SIG_STFL_SECRET_KEY_SET_mutex */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_mutex(OQS_SIG_STFL_SECRET_KEY *sk, void *mutex) { + if (sk == NULL) { + return; + } + sk->mutex = mutex; +} + +/* OQS_SIG_STFL_SECRET_KEY_lock */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_lock(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + if (sk->lock_key == NULL) { + return OQS_SUCCESS; + } + + return (sk->lock_key(sk->mutex)); +} + +/* OQS_SIG_STFL_SECRET_KEY_unlock */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + if(sk->unlock_key == NULL) { + return OQS_SUCCESS; + } + return (sk->unlock_key(sk->mutex)); +} diff --git a/src/sig_stfl/sig_stfl.h b/src/sig_stfl/sig_stfl.h index 1320ff02d3..5b865b9f4e 100644 --- a/src/sig_stfl/sig_stfl.h +++ b/src/sig_stfl/sig_stfl.h @@ -66,9 +66,25 @@ typedef struct OQS_SIG_STFL_SECRET_KEY OQS_SIG_STFL_SECRET_KEY; * @param[in] sk_buf pointer to the data to be saved * @param[in] buf_len length of the the data to be store * @param[out] context pointer to application relevant data. - * @retrun OQS_SUCCESS if successful, otherwise OQS_ERROR + * return OQS_SUCCESS if successful, otherwise OQS_ERROR */ -typedef OQS_STATUS (*secure_store_sk)(/*const*/ uint8_t *sk_buf, size_t buf_len, void *context); +typedef OQS_STATUS (*secure_store_sk)(uint8_t *sk_buf, size_t buf_len, void *context); + +/** + * Application provided function to lock secret key object serialize access + * @param[in] sk pointer to secret key object to lock + * @param[in] mutex pointer to mutex struct + * return OQS_SUCCESS if successful, otherwise OQS_ERROR + */ +typedef OQS_STATUS (*lock_key)(void *mutex); + +/** + * Application provided function to unlock secret key object + * @param[in] sk pointer to secret key object to unlock + * @param[in] mutex pointer to mutex struct + * return OQS_SUCCESS if successful, otherwise OQS_ERROR + */ +typedef OQS_STATUS (*unlock_key)(void *mutex); /** * Returns identifiers for available signature schemes in liboqs. Used with OQS_SIG_STFL_new. @@ -205,6 +221,9 @@ typedef struct OQS_SIG_STFL_SECRET_KEY { /* The variant specific secret key data */ void *secret_key_data; + /* mutual exclusion struct */ + void *mutex; + /* Function that returns the total number of signatures for the secret key */ uint64_t (*sigs_total)(const OQS_SIG_STFL_SECRET_KEY *secret_key); @@ -237,18 +256,18 @@ typedef struct OQS_SIG_STFL_SECRET_KEY { /** * Secret Key Locking Function * - * @param[in] sk The secret key represented as OQS_SIG_STFL_SECRET_KEY object + * @param[in] mutex application defined mutex * @return OQS_SUCCESS or OQS_ERROR */ - OQS_STATUS (*lock_key)(OQS_SIG_STFL_SECRET_KEY *sk); + OQS_STATUS (*lock_key)(void *mutex); /** * Secret Key Unlocking / Releasing Function * - * @param[in] sk The secret key represented as OQS_SIG_STFL_SECRET_KEY object + * @param[in] mutex application defined mutex * @return OQS_SUCCESS or OQS_ERROR */ - OQS_STATUS (*unlock_key)(OQS_SIG_STFL_SECRET_KEY *sk); + OQS_STATUS (*unlock_key)(void *mutex); /** * Store Secret Key Function @@ -388,6 +407,60 @@ void OQS_SECRET_KEY_XMSS_free(OQS_SIG_STFL_SECRET_KEY *sk); */ OQS_API void OQS_SIG_STFL_SECRET_KEY_free(OQS_SIG_STFL_SECRET_KEY *sk); +/** + * OQS_SIG_STFL_SECRET_KEY_SET_lock . + * + * Sets function to prevent multiple processes from using the sk at the same time. + * + * @param[in] sk secret key pointer to be updated + * @param[in] lock function pointer + * + */ +void OQS_SIG_STFL_SECRET_KEY_SET_lock(OQS_SIG_STFL_SECRET_KEY *sk, lock_key lock); + +/** + * OQS_SIG_STFL_SECRET_KEY_SET_unlock . + * + * Sets function to prevent multiple processes from using the sk at the same time. + * + * @param[in] sk secret key pointer to be updated + * @param[in] unlock function pointer + * + */ +void OQS_SIG_STFL_SECRET_KEY_SET_unlock(OQS_SIG_STFL_SECRET_KEY *sk, unlock_key unlock); + +/** + * OQS_SIG_STFL_SECRET_KEY_SET_mutex . + * + * Sets function to prevent multiple processes from using the sk at the same time. + * + * @param[in] sk secret key pointer to be updated + * @param[in] mutex function pointer + * + */ +void OQS_SIG_STFL_SECRET_KEY_SET_mutex(OQS_SIG_STFL_SECRET_KEY *sk, void *mutex); + +/** + * OQS_SIG_STFL_SECRET_KEY_lock . + * + * Locks sk so only one application that holds the lock can access it. + * + * @param[in] sk secret key pointer to be locked + * @return OQS_SUCCESS if successful, or OQS_ERROR if the object fails to apply the lock + * + */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_lock(OQS_SIG_STFL_SECRET_KEY *sk); + +/** + * OQS_SIG_STFL_SECRET_KEY_unlock . + * + * Unlocks the resouces so that th enext process can access it. + * + * @param[in] sk secret key pointer + * @return OQS_SUCCESS if successful, or OQS_ERROR if the object fails to release the lock + * + */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk); /** * OQS_SIG_STFL_SECRET_KEY_SET_store_cb . diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index 0a0f08cd4b..7c4551bf89 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -9,6 +9,9 @@ #include #include +#include +#include + #include #include "tmp_store.c" @@ -33,6 +36,18 @@ */ #define MAX_MARKER_LEN 50 +static OQS_SIG_STFL_SECRET_KEY *lock_test_sk = NULL; +static OQS_SIG_STFL *lock_test_sig_obj = NULL; +static uint8_t *lock_test_public_key = NULL; +static char *lock_test_context = NULL; +static uint8_t *signature_1 = NULL; +static uint8_t *signature_2 = NULL; +static size_t signature_len_1; +static size_t signature_len_2; +static uint8_t message_1[] = "The quick brown fox ..."; +static uint8_t message_2[] = "The quick brown fox jumped from the tree."; +static pthread_mutex_t *test_sk_lock = NULL; + /* * Write stateful secret keys to disk. */ @@ -52,6 +67,38 @@ static OQS_STATUS test_save_secret_key(uint8_t *key_buf, size_t buf_len, void *c return OQS_ERROR; } +#if OQS_USE_PTHREADS_IN_TESTS +static OQS_STATUS lock_sk_key(void *mutex) { + if (mutex == NULL) { + return OQS_ERROR; + } + + if (!(pthread_mutex_lock((pthread_mutex_t*)mutex))) { + return OQS_SUCCESS; + } + return OQS_ERROR; +} + +static OQS_STATUS unlock_sk_key(void *mutex) { + if (mutex == NULL) { + return OQS_ERROR; + } + + if (!(pthread_mutex_unlock((pthread_mutex_t*)mutex))) { + return OQS_SUCCESS; + } + return OQS_ERROR; +} +#else +static OQS_STATUS lock_sk_key(void *mutex) { + return sk != NULL ? OQS_SUCCESS : OQS_ERROR; +} + +static OQS_STATUS unlock_sk_key(void *mutex) { + return sk != NULL ? OQS_SUCCESS : OQS_ERROR; +} +#endif + // // ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) // @@ -313,6 +360,22 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char secret_key = OQS_SIG_STFL_SECRET_KEY_new(sig->method_name); secret_key_rd = OQS_SIG_STFL_SECRET_KEY_new(sig->method_name); + + OQS_SIG_STFL_SECRET_KEY_SET_lock(secret_key, lock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_unlock(secret_key, unlock_sk_key); + +#if OQS_USE_PTHREADS_IN_TESTS + pthread_mutex_t *sk_lock; + sk_lock=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (sk_lock == NULL) { + goto err; + } + + if (0 != pthread_mutex_init(sk_lock, 0)) { + goto err; + } + OQS_SIG_STFL_SECRET_KEY_SET_mutex(secret_key, sk_lock); +#endif public_key = malloc(sig->length_public_key + 2 * sizeof(magic_t)); message = malloc(message_len + 2 * sizeof(magic_t)); signature = malloc(sig->length_signature + 2 * sizeof(magic_t)); @@ -479,6 +542,13 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char OQS_MEM_insecure_free(read_pk_buf); OQS_MEM_insecure_free(context); + +#if OQS_USE_PTHREADS_IN_TESTS + if(sk_lock) { + pthread_mutex_destroy(sk_lock); + OQS_MEM_insecure_free(sk_lock); + } +#endif return ret; } @@ -616,7 +686,6 @@ static OQS_STATUS sig_stfl_test_secret_key(const char *method_name) { if (!sk->secret_key_data) { fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); - OQS_MEM_insecure_free(public_key); goto err; } @@ -670,10 +739,211 @@ static OQS_STATUS sig_stfl_test_secret_key(const char *method_name) { return rc; } +static OQS_STATUS sig_stfl_test_query_key(const char *method_name) { + OQS_STATUS rc = OQS_SUCCESS; + + uint8_t message_1[] = "The quick brown fox ..."; + uint8_t message_2[] = "The quick brown fox jumped from the tree."; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); + + printf("================================================================================\n"); + printf("Testing stateful Signature Verification %s\n", method_name); + printf("================================================================================\n"); + + if( lock_test_sk == NULL || lock_test_sig_obj == NULL || signature_1 == NULL + || signature_2 == NULL || lock_test_public_key == NULL) { + return OQS_ERROR; + } + + + printf("================================================================================\n"); + printf("Sig Verify 1 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_1, message_len_1, signature_1, signature_len_1, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Sig Verify 2 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_2, message_len_2, signature_2, signature_len_2, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + rc = OQS_SUCCESS; + printf("================================================================================\n"); + printf("Stateful Signature Verification %s Passed.\n", method_name); + printf("================================================================================\n"); + goto end_it; +err: + rc = OQS_ERROR; +end_it: + + return rc; +} + +static OQS_STATUS sig_stfl_test_sig_gen(const char *method_name) { + OQS_STATUS rc = OQS_SUCCESS; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); + + + printf("================================================================================\n"); + printf("Testing stateful Signature Generation %s\n", method_name); + printf("================================================================================\n"); + + if( lock_test_sk == NULL || lock_test_sig_obj == NULL) { + return OQS_ERROR; + } + + + printf("================================================================================\n"); + printf("Sig Gen 1 %s\n", method_name); + printf("================================================================================\n"); + + signature_1 = malloc(lock_test_sig_obj->length_signature); + + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_1, &signature_len_1, message_1, message_len_1, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } + +// sleep(3); + + printf("================================================================================\n"); + printf("Sig Gen 2 %s\n", method_name); + printf("================================================================================\n"); + + signature_2 = malloc(lock_test_sig_obj->length_signature); + + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_2, &signature_len_2, message_2, message_len_2, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } + rc = OQS_SUCCESS; + printf("================================================================================\n"); + printf("Stateful Key Gen %s Passed.\n", method_name); + printf("================================================================================\n"); + goto end_it; +err: + rc = OQS_ERROR; +end_it: + + return rc; +} + + +static OQS_STATUS sig_stfl_test_secret_key_lock(const char *method_name) { + OQS_STATUS rc = OQS_SUCCESS; + + /* + * Temporarily skip algs with long key generation times. + */ + + if (strcmp(method_name, OQS_SIG_STFL_alg_lms_sha256_n32_h5_w1) != 0) { + goto skip_test; + } else { + goto keep_going; + } + +skip_test: + printf("Skip slow test %s.\n", method_name); + return rc; + +keep_going: + + printf("================================================================================\n"); + printf("Testing stateful Signature locks %s\n", method_name); + printf("================================================================================\n"); + + printf("================================================================================\n"); + printf("Create stateful Signature %s\n", method_name); + printf("================================================================================\n"); + + lock_test_sig_obj = OQS_SIG_STFL_new(method_name); + if (lock_test_sig_obj == NULL) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); + goto err; + } + + lock_test_public_key = malloc(lock_test_sig_obj->length_public_key * sizeof(uint8_t)); + + printf("================================================================================\n"); + printf("Create stateful Secret Key %s\n", method_name); + printf("================================================================================\n"); + + lock_test_sk = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (lock_test_sk == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new failed\n"); + goto err; + } + + OQS_SIG_STFL_SECRET_KEY_SET_lock(lock_test_sk, lock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_unlock(lock_test_sk, unlock_sk_key); + +#if OQS_USE_PTHREADS_IN_TESTS + + test_sk_lock=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (test_sk_lock == NULL) { + goto err; + } + + if (0 != pthread_mutex_init(test_sk_lock, 0)) { + goto err; + } + OQS_SIG_STFL_SECRET_KEY_SET_mutex(lock_test_sk, test_sk_lock); +#endif + + printf("================================================================================\n"); + printf("Generate keypair %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_keypair(lock_test_sig_obj, lock_test_public_key, lock_test_sk); + + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key gen failed.\n"); + goto err; + } + + + + if (!lock_test_sk->secret_key_data) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); + goto err; + } + + /* set context and secure store callback */ + if (lock_test_sk->set_scrt_key_store_cb) { + lock_test_context = strdup(((method_name))); + lock_test_sk->set_scrt_key_store_cb(lock_test_sk, test_save_secret_key, (void *)lock_test_context); + } + + printf("Test Secret Key Creator Thread created Stateful Signature and Secret Key objects.\n"); + goto end_it; + +err: + rc = OQS_ERROR; +end_it: + return rc; +} + #ifdef OQS_ENABLE_TEST_CONSTANT_TIME static void TEST_SIG_STFL_randombytes(uint8_t *random_array, size_t bytes_to_read) { // We can't make direct calls to the system randombytes on some platforms, // so we have to swap out the OQS_randombytes provider. + OQS_randombytes_switch_algorithm("system"); OQS_randombytes(random_array, bytes_to_read); OQS_randombytes_custom_algorithm(&TEST_SIG_STFL_randombytes); @@ -693,12 +963,46 @@ struct thread_data { OQS_STATUS rc1; }; -void *test_wrapper(void *arg) { - struct thread_data *td = arg; - td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); - td->rc1 = sig_stfl_test_secret_key(td->alg_name); +struct lock_test_data { + const char *alg_name; + OQS_STATUS rc; +}; + +struct lock_sign_data { + const char *alg_name; + OQS_STATUS rc; +}; + +void *test_query_key(void *arg) { + struct lock_test_data *td = arg; + printf("%s: Start Query Stateful Key info\n", __FUNCTION__); + td->rc = sig_stfl_test_query_key(td->alg_name); + printf("%s: End Query Stateful Key info\n", __FUNCTION__); + return NULL; +} + +void *test_sig_gen(void *arg) { + struct lock_test_data *td = arg; + printf("%s: Start Generate Stateful Signature\n", __FUNCTION__); + td->rc = sig_stfl_test_sig_gen(td->alg_name); + printf("%s: End Generate Stateful Signature\n", __FUNCTION__); + return NULL; +} + +void *test_locks(void *arg) { + struct lock_test_data *td = arg; + printf("%s: Start Generate Keys\n", __FUNCTION__); + td->rc = sig_stfl_test_secret_key_lock(td->alg_name); + printf("%s: End Generate Stateful Keys\n", __FUNCTION__); return NULL; } + +void *test_wrapper(void *arg) { + struct thread_data *td = arg; + td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); + td->rc1 = sig_stfl_test_secret_key(td->alg_name); + return NULL; +} #endif int main(int argc, char **argv) { @@ -737,13 +1041,21 @@ int main(int argc, char **argv) { OQS_randombytes_switch_algorithm("system"); #endif - OQS_STATUS rc, rc1; + OQS_STATUS rc, rc1, rc_lck, rc_sig, rc_qry; #if OQS_USE_PTHREADS_IN_TESTS #define MAX_LEN_SIG_NAME_ 64 + pthread_t thread; + pthread_t tst_lck_thread; + pthread_mutex_t *lock; struct thread_data td; td.alg_name = alg_name; td.katfile = katfile; + + struct lock_test_data td_lock; + td_lock.alg_name = alg_name; + + int trc = pthread_create(&thread, NULL, test_wrapper, &td); if (trc) { fprintf(stderr, "ERROR: Creating pthread\n"); @@ -753,11 +1065,47 @@ int main(int argc, char **argv) { pthread_join(thread, NULL); rc = td.rc; rc1 = td.rc1; + + int trc_2 = pthread_create(&thread, NULL, test_locks, &td_lock); + if (trc_2) { + fprintf(stderr, "ERROR: Creating pthread for stateful key gen test\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_lck = td_lock.rc; + + int trc_3 = pthread_create(&thread, NULL, test_sig_gen, &td_lock); + if (trc_3) { + fprintf(stderr, "ERROR: Creating pthread for sig gen test\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_sig = td_lock.rc; + + int trc_4 = pthread_create(&thread, NULL, test_query_key, &td_lock); + if (trc_4) { + fprintf(stderr, "ERROR: Creating pthread for query key test.\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_qry = td_lock.rc; #else rc = sig_stfl_test_correctness(alg_name, katfile); rc1 = sig_stfl_test_secret_key(alg_name); #endif - if ((rc != OQS_SUCCESS) || (rc1 != OQS_SUCCESS)) { + + OQS_SIG_STFL_SECRET_KEY_free(lock_test_sk); + OQS_MEM_insecure_free(lock_test_public_key); + OQS_SIG_STFL_free(lock_test_sig_obj); + OQS_MEM_insecure_free(lock_test_context); + OQS_MEM_insecure_free(signature_1); + OQS_MEM_insecure_free(signature_2); + + if ((rc != OQS_SUCCESS) || (rc1 != OQS_SUCCESS) || (rc_lck != OQS_SUCCESS) || (rc_sig != OQS_SUCCESS) + || (rc_qry != OQS_SUCCESS)) { OQS_destroy(); return EXIT_FAILURE; } From 316c0c69e1f87dc6255a649998d3940cb2507e88 Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Sun, 24 Sep 2023 21:41:32 -0400 Subject: [PATCH 2/6] Formatting. --- src/sig_stfl/lms/sig_stfl_lms.c | 18 +- src/sig_stfl/lms/sig_stfl_lms_functions.c | 30 +- src/sig_stfl/sig_stfl.c | 54 +-- tests/test_sig_stfl.c | 452 +++++++++++----------- 4 files changed, 277 insertions(+), 277 deletions(-) diff --git a/src/sig_stfl/lms/sig_stfl_lms.c b/src/sig_stfl/lms/sig_stfl_lms.c index 7f50424160..e6c30e66d5 100644 --- a/src/sig_stfl/lms/sig_stfl_lms.c +++ b/src/sig_stfl/lms/sig_stfl_lms.c @@ -114,17 +114,17 @@ void OQS_SECRET_KEY_LMS_free(OQS_SIG_STFL_SECRET_KEY *sk) { /* Convert LMS secret key object to byte string */ static OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr) { - OQS_STATUS status; - if (sk->lock_key && sk->mutex) { - sk->lock_key(sk->mutex); - } + OQS_STATUS status; + if (sk->lock_key && sk->mutex) { + sk->lock_key(sk->mutex); + } - status = oqs_serialize_lms_key(sk, sk_len, sk_buf_ptr); + status = oqs_serialize_lms_key(sk, sk_len, sk_buf_ptr); - if (sk->unlock_key && sk->mutex) { - sk->unlock_key(sk->mutex); - } - return status; + if (sk->unlock_key && sk->mutex) { + sk->unlock_key(sk->mutex); + } + return status; } /* Insert lms byte string in an LMS secret key object */ diff --git a/src/sig_stfl/lms/sig_stfl_lms_functions.c b/src/sig_stfl/lms/sig_stfl_lms_functions.c index 59cd49415f..59265f3110 100644 --- a/src/sig_stfl/lms/sig_stfl_lms_functions.c +++ b/src/sig_stfl/lms/sig_stfl_lms_functions.c @@ -47,7 +47,7 @@ typedef struct OQS_LMS_KEY_DATA { OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signature_length, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { - OQS_STATUS status = OQS_ERROR; + OQS_STATUS status = OQS_ERROR; OQS_STATUS rc_keyupdate = OQS_ERROR; oqs_lms_key_data *lms_key_data = NULL; const OQS_SIG_STFL_SECRET_KEY *sk; @@ -61,7 +61,7 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signatu /* Lock secret to ensure OTS use */ if ((secret_key->lock_key) && (secret_key->mutex)) { - secret_key->lock_key(secret_key->mutex); + secret_key->lock_key(secret_key->mutex); } /* @@ -109,12 +109,12 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signatu *signature_length = 0; passed: - OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); + OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); - /* Unlock secret to ensure OTS use */ - if ((secret_key->unlock_key) && (secret_key->mutex)) { - secret_key->unlock_key(secret_key->mutex); - } + /* Unlock secret to ensure OTS use */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } return status; } @@ -140,17 +140,17 @@ OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_left(unsigned long long *remain, const if (remain == NULL || secret_key == NULL) { return OQS_ERROR; } - /* Lock secret key to ensure data integrity use */ - if ((secret_key->lock_key) && (secret_key->mutex)) { - secret_key->lock_key(secret_key->mutex); - } + /* Lock secret key to ensure data integrity use */ + if ((secret_key->lock_key) && (secret_key->mutex)) { + secret_key->lock_key(secret_key->mutex); + } remain = 0; - /* Unlock secret key */ - if ((secret_key->unlock_key) && (secret_key->mutex)) { - secret_key->unlock_key(secret_key->mutex); - } + /* Unlock secret key */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } return OQS_SUCCESS; } diff --git a/src/sig_stfl/sig_stfl.c b/src/sig_stfl/sig_stfl.c index fe7a2b61d4..023d4e1df3 100644 --- a/src/sig_stfl/sig_stfl.c +++ b/src/sig_stfl/sig_stfl.c @@ -721,47 +721,47 @@ OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_deserialize_key(OQS_SIG_STFL_SECRET_KEY * /* OQS_SIG_STFL_SECRET_KEY_SET_lock callback function*/ OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_lock(OQS_SIG_STFL_SECRET_KEY *sk, lock_key lock) { - if (sk == NULL) { - return; - } - sk->lock_key = lock; + if (sk == NULL) { + return; + } + sk->lock_key = lock; } /* OQS_SIG_STFL_SECRET_KEY_SET_unlock callback function */ OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_unlock(OQS_SIG_STFL_SECRET_KEY *sk, unlock_key unlock) { - if (sk == NULL) { - return; - } - sk->unlock_key = unlock; + if (sk == NULL) { + return; + } + sk->unlock_key = unlock; } /* OQS_SIG_STFL_SECRET_KEY_SET_mutex */ OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_mutex(OQS_SIG_STFL_SECRET_KEY *sk, void *mutex) { - if (sk == NULL) { - return; - } - sk->mutex = mutex; + if (sk == NULL) { + return; + } + sk->mutex = mutex; } /* OQS_SIG_STFL_SECRET_KEY_lock */ OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_lock(OQS_SIG_STFL_SECRET_KEY *sk) { - if (sk == NULL) { - return OQS_ERROR; - } - if (sk->lock_key == NULL) { - return OQS_SUCCESS; - } - - return (sk->lock_key(sk->mutex)); + if (sk == NULL) { + return OQS_ERROR; + } + if (sk->lock_key == NULL) { + return OQS_SUCCESS; + } + + return (sk->lock_key(sk->mutex)); } /* OQS_SIG_STFL_SECRET_KEY_unlock */ OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk) { - if (sk == NULL) { - return OQS_ERROR; - } - if(sk->unlock_key == NULL) { - return OQS_SUCCESS; - } - return (sk->unlock_key(sk->mutex)); + if (sk == NULL) { + return OQS_ERROR; + } + if (sk->unlock_key == NULL) { + return OQS_SUCCESS; + } + return (sk->unlock_key(sk->mutex)); } diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index 7c4551bf89..5a3803e47b 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -69,33 +69,33 @@ static OQS_STATUS test_save_secret_key(uint8_t *key_buf, size_t buf_len, void *c #if OQS_USE_PTHREADS_IN_TESTS static OQS_STATUS lock_sk_key(void *mutex) { - if (mutex == NULL) { - return OQS_ERROR; - } - - if (!(pthread_mutex_lock((pthread_mutex_t*)mutex))) { - return OQS_SUCCESS; - } - return OQS_ERROR; + if (mutex == NULL) { + return OQS_ERROR; + } + + if (!(pthread_mutex_lock((pthread_mutex_t *)mutex))) { + return OQS_SUCCESS; + } + return OQS_ERROR; } static OQS_STATUS unlock_sk_key(void *mutex) { - if (mutex == NULL) { - return OQS_ERROR; - } - - if (!(pthread_mutex_unlock((pthread_mutex_t*)mutex))) { - return OQS_SUCCESS; - } - return OQS_ERROR; + if (mutex == NULL) { + return OQS_ERROR; + } + + if (!(pthread_mutex_unlock((pthread_mutex_t *)mutex))) { + return OQS_SUCCESS; + } + return OQS_ERROR; } #else static OQS_STATUS lock_sk_key(void *mutex) { - return sk != NULL ? OQS_SUCCESS : OQS_ERROR; + return sk != NULL ? OQS_SUCCESS : OQS_ERROR; } static OQS_STATUS unlock_sk_key(void *mutex) { - return sk != NULL ? OQS_SUCCESS : OQS_ERROR; + return sk != NULL ? OQS_SUCCESS : OQS_ERROR; } #endif @@ -366,15 +366,15 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char #if OQS_USE_PTHREADS_IN_TESTS pthread_mutex_t *sk_lock; - sk_lock=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); if (sk_lock == NULL) { - goto err; + goto err; } - if (0 != pthread_mutex_init(sk_lock, 0)) { - goto err; - } - OQS_SIG_STFL_SECRET_KEY_SET_mutex(secret_key, sk_lock); + if (0 != pthread_mutex_init(sk_lock, 0)) { + goto err; + } + OQS_SIG_STFL_SECRET_KEY_SET_mutex(secret_key, sk_lock); #endif public_key = malloc(sig->length_public_key + 2 * sizeof(magic_t)); message = malloc(message_len + 2 * sizeof(magic_t)); @@ -544,10 +544,10 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char OQS_MEM_insecure_free(context); #if OQS_USE_PTHREADS_IN_TESTS - if(sk_lock) { - pthread_mutex_destroy(sk_lock); - OQS_MEM_insecure_free(sk_lock); - } + if (sk_lock) { + pthread_mutex_destroy(sk_lock); + OQS_MEM_insecure_free(sk_lock); + } #endif return ret; } @@ -740,203 +740,203 @@ static OQS_STATUS sig_stfl_test_secret_key(const char *method_name) { } static OQS_STATUS sig_stfl_test_query_key(const char *method_name) { - OQS_STATUS rc = OQS_SUCCESS; - - uint8_t message_1[] = "The quick brown fox ..."; - uint8_t message_2[] = "The quick brown fox jumped from the tree."; - size_t message_len_1 = sizeof(message_1); - size_t message_len_2 = sizeof(message_2); - - printf("================================================================================\n"); - printf("Testing stateful Signature Verification %s\n", method_name); - printf("================================================================================\n"); - - if( lock_test_sk == NULL || lock_test_sig_obj == NULL || signature_1 == NULL - || signature_2 == NULL || lock_test_public_key == NULL) { - return OQS_ERROR; - } - - - printf("================================================================================\n"); - printf("Sig Verify 1 %s\n", method_name); - printf("================================================================================\n"); - - rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_1, message_len_1, signature_1, signature_len_1, lock_test_public_key); - OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); - if (rc != OQS_SUCCESS) { - fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); - goto err; - } - - printf("================================================================================\n"); - printf("Sig Verify 2 %s\n", method_name); - printf("================================================================================\n"); - - rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_2, message_len_2, signature_2, signature_len_2, lock_test_public_key); - OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); - if (rc != OQS_SUCCESS) { - fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); - goto err; - } - rc = OQS_SUCCESS; - printf("================================================================================\n"); - printf("Stateful Signature Verification %s Passed.\n", method_name); - printf("================================================================================\n"); - goto end_it; + OQS_STATUS rc = OQS_SUCCESS; + + uint8_t message_1[] = "The quick brown fox ..."; + uint8_t message_2[] = "The quick brown fox jumped from the tree."; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); + + printf("================================================================================\n"); + printf("Testing stateful Signature Verification %s\n", method_name); + printf("================================================================================\n"); + + if ( lock_test_sk == NULL || lock_test_sig_obj == NULL || signature_1 == NULL + || signature_2 == NULL || lock_test_public_key == NULL) { + return OQS_ERROR; + } + + + printf("================================================================================\n"); + printf("Sig Verify 1 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_1, message_len_1, signature_1, signature_len_1, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Sig Verify 2 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_2, message_len_2, signature_2, signature_len_2, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + rc = OQS_SUCCESS; + printf("================================================================================\n"); + printf("Stateful Signature Verification %s Passed.\n", method_name); + printf("================================================================================\n"); + goto end_it; err: - rc = OQS_ERROR; + rc = OQS_ERROR; end_it: - return rc; + return rc; } static OQS_STATUS sig_stfl_test_sig_gen(const char *method_name) { - OQS_STATUS rc = OQS_SUCCESS; - size_t message_len_1 = sizeof(message_1); - size_t message_len_2 = sizeof(message_2); + OQS_STATUS rc = OQS_SUCCESS; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); - printf("================================================================================\n"); - printf("Testing stateful Signature Generation %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Testing stateful Signature Generation %s\n", method_name); + printf("================================================================================\n"); - if( lock_test_sk == NULL || lock_test_sig_obj == NULL) { - return OQS_ERROR; - } + if ( lock_test_sk == NULL || lock_test_sig_obj == NULL) { + return OQS_ERROR; + } - printf("================================================================================\n"); - printf("Sig Gen 1 %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Sig Gen 1 %s\n", method_name); + printf("================================================================================\n"); - signature_1 = malloc(lock_test_sig_obj->length_signature); + signature_1 = malloc(lock_test_sig_obj->length_signature); - rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_1, &signature_len_1, message_1, message_len_1, lock_test_sk); - OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); - if (rc != OQS_SUCCESS) { - fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); - goto err; - } + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_1, &signature_len_1, message_1, message_len_1, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } // sleep(3); - printf("================================================================================\n"); - printf("Sig Gen 2 %s\n", method_name); - printf("================================================================================\n"); - - signature_2 = malloc(lock_test_sig_obj->length_signature); - - rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_2, &signature_len_2, message_2, message_len_2, lock_test_sk); - OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); - if (rc != OQS_SUCCESS) { - fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); - goto err; - } - rc = OQS_SUCCESS; - printf("================================================================================\n"); - printf("Stateful Key Gen %s Passed.\n", method_name); - printf("================================================================================\n"); - goto end_it; + printf("================================================================================\n"); + printf("Sig Gen 2 %s\n", method_name); + printf("================================================================================\n"); + + signature_2 = malloc(lock_test_sig_obj->length_signature); + + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_2, &signature_len_2, message_2, message_len_2, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } + rc = OQS_SUCCESS; + printf("================================================================================\n"); + printf("Stateful Key Gen %s Passed.\n", method_name); + printf("================================================================================\n"); + goto end_it; err: - rc = OQS_ERROR; + rc = OQS_ERROR; end_it: - return rc; + return rc; } static OQS_STATUS sig_stfl_test_secret_key_lock(const char *method_name) { - OQS_STATUS rc = OQS_SUCCESS; + OQS_STATUS rc = OQS_SUCCESS; - /* - * Temporarily skip algs with long key generation times. - */ + /* + * Temporarily skip algs with long key generation times. + */ - if (strcmp(method_name, OQS_SIG_STFL_alg_lms_sha256_n32_h5_w1) != 0) { - goto skip_test; - } else { - goto keep_going; - } + if (strcmp(method_name, OQS_SIG_STFL_alg_lms_sha256_n32_h5_w1) != 0) { + goto skip_test; + } else { + goto keep_going; + } skip_test: - printf("Skip slow test %s.\n", method_name); - return rc; + printf("Skip slow test %s.\n", method_name); + return rc; keep_going: - printf("================================================================================\n"); - printf("Testing stateful Signature locks %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Testing stateful Signature locks %s\n", method_name); + printf("================================================================================\n"); - printf("================================================================================\n"); - printf("Create stateful Signature %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Create stateful Signature %s\n", method_name); + printf("================================================================================\n"); - lock_test_sig_obj = OQS_SIG_STFL_new(method_name); - if (lock_test_sig_obj == NULL) { - fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); - goto err; - } + lock_test_sig_obj = OQS_SIG_STFL_new(method_name); + if (lock_test_sig_obj == NULL) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); + goto err; + } - lock_test_public_key = malloc(lock_test_sig_obj->length_public_key * sizeof(uint8_t)); + lock_test_public_key = malloc(lock_test_sig_obj->length_public_key * sizeof(uint8_t)); - printf("================================================================================\n"); - printf("Create stateful Secret Key %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Create stateful Secret Key %s\n", method_name); + printf("================================================================================\n"); - lock_test_sk = OQS_SIG_STFL_SECRET_KEY_new(method_name); - if (lock_test_sk == NULL) { - fprintf(stderr, "ERROR: OQS_SECRET_KEY_new failed\n"); - goto err; - } + lock_test_sk = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (lock_test_sk == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new failed\n"); + goto err; + } - OQS_SIG_STFL_SECRET_KEY_SET_lock(lock_test_sk, lock_sk_key); - OQS_SIG_STFL_SECRET_KEY_SET_unlock(lock_test_sk, unlock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_lock(lock_test_sk, lock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_unlock(lock_test_sk, unlock_sk_key); #if OQS_USE_PTHREADS_IN_TESTS - test_sk_lock=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); - if (test_sk_lock == NULL) { - goto err; - } + test_sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (test_sk_lock == NULL) { + goto err; + } - if (0 != pthread_mutex_init(test_sk_lock, 0)) { - goto err; - } - OQS_SIG_STFL_SECRET_KEY_SET_mutex(lock_test_sk, test_sk_lock); + if (0 != pthread_mutex_init(test_sk_lock, 0)) { + goto err; + } + OQS_SIG_STFL_SECRET_KEY_SET_mutex(lock_test_sk, test_sk_lock); #endif - printf("================================================================================\n"); - printf("Generate keypair %s\n", method_name); - printf("================================================================================\n"); + printf("================================================================================\n"); + printf("Generate keypair %s\n", method_name); + printf("================================================================================\n"); - rc = OQS_SIG_STFL_keypair(lock_test_sig_obj, lock_test_public_key, lock_test_sk); + rc = OQS_SIG_STFL_keypair(lock_test_sig_obj, lock_test_public_key, lock_test_sk); - if (rc != OQS_SUCCESS) { - fprintf(stderr, "OQS STFL key gen failed.\n"); - goto err; - } + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key gen failed.\n"); + goto err; + } - if (!lock_test_sk->secret_key_data) { - fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); - goto err; - } + if (!lock_test_sk->secret_key_data) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); + goto err; + } - /* set context and secure store callback */ - if (lock_test_sk->set_scrt_key_store_cb) { - lock_test_context = strdup(((method_name))); - lock_test_sk->set_scrt_key_store_cb(lock_test_sk, test_save_secret_key, (void *)lock_test_context); - } + /* set context and secure store callback */ + if (lock_test_sk->set_scrt_key_store_cb) { + lock_test_context = strdup(((method_name))); + lock_test_sk->set_scrt_key_store_cb(lock_test_sk, test_save_secret_key, (void *)lock_test_context); + } - printf("Test Secret Key Creator Thread created Stateful Signature and Secret Key objects.\n"); - goto end_it; + printf("Test Secret Key Creator Thread created Stateful Signature and Secret Key objects.\n"); + goto end_it; err: - rc = OQS_ERROR; + rc = OQS_ERROR; end_it: - return rc; + return rc; } #ifdef OQS_ENABLE_TEST_CONSTANT_TIME @@ -964,29 +964,29 @@ struct thread_data { }; struct lock_test_data { - const char *alg_name; - OQS_STATUS rc; + const char *alg_name; + OQS_STATUS rc; }; struct lock_sign_data { - const char *alg_name; - OQS_STATUS rc; + const char *alg_name; + OQS_STATUS rc; }; void *test_query_key(void *arg) { - struct lock_test_data *td = arg; - printf("%s: Start Query Stateful Key info\n", __FUNCTION__); - td->rc = sig_stfl_test_query_key(td->alg_name); - printf("%s: End Query Stateful Key info\n", __FUNCTION__); - return NULL; + struct lock_test_data *td = arg; + printf("%s: Start Query Stateful Key info\n", __FUNCTION__); + td->rc = sig_stfl_test_query_key(td->alg_name); + printf("%s: End Query Stateful Key info\n", __FUNCTION__); + return NULL; } void *test_sig_gen(void *arg) { - struct lock_test_data *td = arg; - printf("%s: Start Generate Stateful Signature\n", __FUNCTION__); - td->rc = sig_stfl_test_sig_gen(td->alg_name); - printf("%s: End Generate Stateful Signature\n", __FUNCTION__); - return NULL; + struct lock_test_data *td = arg; + printf("%s: Start Generate Stateful Signature\n", __FUNCTION__); + td->rc = sig_stfl_test_sig_gen(td->alg_name); + printf("%s: End Generate Stateful Signature\n", __FUNCTION__); + return NULL; } void *test_locks(void *arg) { @@ -998,10 +998,10 @@ void *test_locks(void *arg) { } void *test_wrapper(void *arg) { - struct thread_data *td = arg; - td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); - td->rc1 = sig_stfl_test_secret_key(td->alg_name); - return NULL; + struct thread_data *td = arg; + td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); + td->rc1 = sig_stfl_test_secret_key(td->alg_name); + return NULL; } #endif @@ -1046,14 +1046,14 @@ int main(int argc, char **argv) { #define MAX_LEN_SIG_NAME_ 64 pthread_t thread; - pthread_t tst_lck_thread; + pthread_t tst_lck_thread; pthread_mutex_t *lock; struct thread_data td; td.alg_name = alg_name; td.katfile = katfile; - struct lock_test_data td_lock; - td_lock.alg_name = alg_name; + struct lock_test_data td_lock; + td_lock.alg_name = alg_name; int trc = pthread_create(&thread, NULL, test_wrapper, &td); @@ -1066,43 +1066,43 @@ int main(int argc, char **argv) { rc = td.rc; rc1 = td.rc1; - int trc_2 = pthread_create(&thread, NULL, test_locks, &td_lock); - if (trc_2) { - fprintf(stderr, "ERROR: Creating pthread for stateful key gen test\n"); - OQS_destroy(); - return EXIT_FAILURE; - } - pthread_join(thread, NULL); - rc_lck = td_lock.rc; - - int trc_3 = pthread_create(&thread, NULL, test_sig_gen, &td_lock); - if (trc_3) { - fprintf(stderr, "ERROR: Creating pthread for sig gen test\n"); - OQS_destroy(); - return EXIT_FAILURE; - } - pthread_join(thread, NULL); - rc_sig = td_lock.rc; - - int trc_4 = pthread_create(&thread, NULL, test_query_key, &td_lock); - if (trc_4) { - fprintf(stderr, "ERROR: Creating pthread for query key test.\n"); - OQS_destroy(); - return EXIT_FAILURE; - } - pthread_join(thread, NULL); - rc_qry = td_lock.rc; + int trc_2 = pthread_create(&thread, NULL, test_locks, &td_lock); + if (trc_2) { + fprintf(stderr, "ERROR: Creating pthread for stateful key gen test\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_lck = td_lock.rc; + + int trc_3 = pthread_create(&thread, NULL, test_sig_gen, &td_lock); + if (trc_3) { + fprintf(stderr, "ERROR: Creating pthread for sig gen test\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_sig = td_lock.rc; + + int trc_4 = pthread_create(&thread, NULL, test_query_key, &td_lock); + if (trc_4) { + fprintf(stderr, "ERROR: Creating pthread for query key test.\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + pthread_join(thread, NULL); + rc_qry = td_lock.rc; #else rc = sig_stfl_test_correctness(alg_name, katfile); rc1 = sig_stfl_test_secret_key(alg_name); #endif - OQS_SIG_STFL_SECRET_KEY_free(lock_test_sk); - OQS_MEM_insecure_free(lock_test_public_key); - OQS_SIG_STFL_free(lock_test_sig_obj); - OQS_MEM_insecure_free(lock_test_context); - OQS_MEM_insecure_free(signature_1); - OQS_MEM_insecure_free(signature_2); + OQS_SIG_STFL_SECRET_KEY_free(lock_test_sk); + OQS_MEM_insecure_free(lock_test_public_key); + OQS_SIG_STFL_free(lock_test_sig_obj); + OQS_MEM_insecure_free(lock_test_context); + OQS_MEM_insecure_free(signature_1); + OQS_MEM_insecure_free(signature_2); if ((rc != OQS_SUCCESS) || (rc1 != OQS_SUCCESS) || (rc_lck != OQS_SUCCESS) || (rc_sig != OQS_SUCCESS) || (rc_qry != OQS_SUCCESS)) { From 981990965093c9cbd994ed9c3bb736a82a959cf5 Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Sun, 24 Sep 2023 22:43:08 -0400 Subject: [PATCH 3/6] Clean up warnings --- tests/test_sig_stfl.c | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index 5a3803e47b..24db1abc63 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -365,7 +365,7 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char OQS_SIG_STFL_SECRET_KEY_SET_unlock(secret_key, unlock_sk_key); #if OQS_USE_PTHREADS_IN_TESTS - pthread_mutex_t *sk_lock; + pthread_mutex_t *sk_lock = NULL; sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); if (sk_lock == NULL) { goto err; @@ -818,7 +818,7 @@ static OQS_STATUS sig_stfl_test_sig_gen(const char *method_name) { goto err; } -// sleep(3); + sleep(3); printf("================================================================================\n"); printf("Sig Gen 2 %s\n", method_name); @@ -968,32 +968,27 @@ struct lock_test_data { OQS_STATUS rc; }; -struct lock_sign_data { - const char *alg_name; - OQS_STATUS rc; -}; - void *test_query_key(void *arg) { struct lock_test_data *td = arg; - printf("%s: Start Query Stateful Key info\n", __FUNCTION__); + printf("\n%s: Start Query Stateful Key info\n", __FUNCTION__); td->rc = sig_stfl_test_query_key(td->alg_name); - printf("%s: End Query Stateful Key info\n", __FUNCTION__); + printf("%s: End Query Stateful Key info\n\n", __FUNCTION__); return NULL; } void *test_sig_gen(void *arg) { struct lock_test_data *td = arg; - printf("%s: Start Generate Stateful Signature\n", __FUNCTION__); + printf("\n%s: Start Generate Stateful Signature\n", __FUNCTION__); td->rc = sig_stfl_test_sig_gen(td->alg_name); - printf("%s: End Generate Stateful Signature\n", __FUNCTION__); + printf("%s: End Generate Stateful Signature\n\n", __FUNCTION__); return NULL; } -void *test_locks(void *arg) { +void *test_create_keys(void *arg) { struct lock_test_data *td = arg; - printf("%s: Start Generate Keys\n", __FUNCTION__); + printf("\n%s: Start Generate Keys\n", __FUNCTION__); td->rc = sig_stfl_test_secret_key_lock(td->alg_name); - printf("%s: End Generate Stateful Keys\n", __FUNCTION__); + printf("%s: End Generate Stateful Keys\n\n", __FUNCTION__); return NULL; } @@ -1046,14 +1041,19 @@ int main(int argc, char **argv) { #define MAX_LEN_SIG_NAME_ 64 pthread_t thread; - pthread_t tst_lck_thread; - pthread_mutex_t *lock; + pthread_t create_key_thread; + pthread_t sign_key_thread; + pthread_t query_key_thread; struct thread_data td; td.alg_name = alg_name; td.katfile = katfile; - struct lock_test_data td_lock; - td_lock.alg_name = alg_name; + struct lock_test_data td_create; + struct lock_test_data td_sign; + struct lock_test_data td_query; + td_create.alg_name = alg_name; + td_sign.alg_name = alg_name; + td_query.alg_name = alg_name; int trc = pthread_create(&thread, NULL, test_wrapper, &td); @@ -1066,32 +1066,32 @@ int main(int argc, char **argv) { rc = td.rc; rc1 = td.rc1; - int trc_2 = pthread_create(&thread, NULL, test_locks, &td_lock); + int trc_2 = pthread_create(&create_key_thread, NULL, test_create_keys, &td_create); if (trc_2) { fprintf(stderr, "ERROR: Creating pthread for stateful key gen test\n"); OQS_destroy(); return EXIT_FAILURE; } - pthread_join(thread, NULL); - rc_lck = td_lock.rc; + pthread_join(create_key_thread, NULL); + rc_lck = td_create.rc; - int trc_3 = pthread_create(&thread, NULL, test_sig_gen, &td_lock); + int trc_3 = pthread_create(&sign_key_thread, NULL, test_sig_gen, &td_sign); if (trc_3) { fprintf(stderr, "ERROR: Creating pthread for sig gen test\n"); OQS_destroy(); return EXIT_FAILURE; } - pthread_join(thread, NULL); - rc_sig = td_lock.rc; + pthread_join(sign_key_thread, NULL); + rc_sig = td_sign.rc; - int trc_4 = pthread_create(&thread, NULL, test_query_key, &td_lock); + int trc_4 = pthread_create(&query_key_thread, NULL, test_query_key, &td_query); if (trc_4) { fprintf(stderr, "ERROR: Creating pthread for query key test.\n"); OQS_destroy(); return EXIT_FAILURE; } - pthread_join(thread, NULL); - rc_qry = td_lock.rc; + pthread_join(query_key_thread, NULL); + rc_qry = td_query.rc; #else rc = sig_stfl_test_correctness(alg_name, katfile); rc1 = sig_stfl_test_secret_key(alg_name); From d873aa09c6c113fbe323ac5c19f722f18aaf294a Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Sun, 24 Sep 2023 23:34:57 -0400 Subject: [PATCH 4/6] Exclude XMSS from some tests temporarily --- tests/test_sig_stfl.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index 24db1abc63..13a7a57dc0 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -341,6 +341,10 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char size_t sk_buf_len = 0; size_t read_pk_len = 0; +#if OQS_USE_PTHREADS_IN_TESTS + pthread_mutex_t *sk_lock = NULL; +#endif + OQS_STATUS rc, ret = OQS_ERROR; //The magic numbers are random values. @@ -365,7 +369,6 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char OQS_SIG_STFL_SECRET_KEY_SET_unlock(secret_key, unlock_sk_key); #if OQS_USE_PTHREADS_IN_TESTS - pthread_mutex_t *sk_lock = NULL; sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); if (sk_lock == NULL) { goto err; @@ -742,11 +745,30 @@ static OQS_STATUS sig_stfl_test_secret_key(const char *method_name) { static OQS_STATUS sig_stfl_test_query_key(const char *method_name) { OQS_STATUS rc = OQS_SUCCESS; - uint8_t message_1[] = "The quick brown fox ..."; - uint8_t message_2[] = "The quick brown fox jumped from the tree."; size_t message_len_1 = sizeof(message_1); size_t message_len_2 = sizeof(message_2); + /* + * Temporarily skip algs with long key generation times. + */ + + if (strcmp(method_name, OQS_SIG_STFL_alg_lms_sha256_n32_h5_w1) != 0) { + goto skip_test; + } else { + goto keep_going; + } + +skip_test: + printf("Skip slow alg %s.\n", method_name); + return rc; + +keep_going: + +// uint8_t message_1[] = "The quick brown fox ..."; +// uint8_t message_2[] = "The quick brown fox jumped from the tree."; +// size_t message_len_1 = sizeof(message_1); +// size_t message_len_2 = sizeof(message_2); + printf("================================================================================\n"); printf("Testing stateful Signature Verification %s\n", method_name); printf("================================================================================\n"); @@ -795,6 +817,21 @@ static OQS_STATUS sig_stfl_test_sig_gen(const char *method_name) { size_t message_len_1 = sizeof(message_1); size_t message_len_2 = sizeof(message_2); + /* + * Temporarily skip algs with long key generation times. + */ + + if (strcmp(method_name, OQS_SIG_STFL_alg_lms_sha256_n32_h5_w1) != 0) { + goto skip_test; + } else { + goto keep_going; + } + +skip_test: + printf("Skip slow alg %s.\n", method_name); + return rc; + +keep_going: printf("================================================================================\n"); printf("Testing stateful Signature Generation %s\n", method_name); From 403cbf3f5b09eba392b5af2beb105873b341ddac Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Sun, 24 Sep 2023 23:36:51 -0400 Subject: [PATCH 5/6] Remove commented code. --- tests/test_sig_stfl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index 13a7a57dc0..8a3cb2252d 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -764,11 +764,6 @@ static OQS_STATUS sig_stfl_test_query_key(const char *method_name) { keep_going: -// uint8_t message_1[] = "The quick brown fox ..."; -// uint8_t message_2[] = "The quick brown fox jumped from the tree."; -// size_t message_len_1 = sizeof(message_1); -// size_t message_len_2 = sizeof(message_2); - printf("================================================================================\n"); printf("Testing stateful Signature Verification %s\n", method_name); printf("================================================================================\n"); From 8dfd330bf11b092a51c64a02cb89085c5c6eb8b5 Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Thu, 28 Sep 2023 09:52:48 -0400 Subject: [PATCH 6/6] Document use of callback functions for secret key thread safe protection and storage. --- src/sig_stfl/sig_stfl.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/sig_stfl/sig_stfl.h b/src/sig_stfl/sig_stfl.h index 5b865b9f4e..a9bffdfdd8 100644 --- a/src/sig_stfl/sig_stfl.h +++ b/src/sig_stfl/sig_stfl.h @@ -16,6 +16,29 @@ #include +/* + * Developer's Notes: + * Stateful signatures are based on one-time use of a secret key. A pool of secret keys are created for this purpose. + * The state of these keys are tracked to ensure that they are used only once to generate a signature. + * + * As such, product specific environments do play a role in ensuring the safety of the keys. + * Secret keys must be store securely. + * The key index/counter must be updated after each signature generation. + * Secret key must be protected in a thread-save manner. + * + * Application therefore are required to provide environment specific callback functions to + * - store private key + * - lock/unlock private key + * + * See below for details + * OQS_SIG_STFL_SECRET_KEY_SET_lock + * OQS_SIG_STFL_SECRET_KEY_SET_unlock + * OQS_SIG_STFL_SECRET_KEY_SET_mutex + * OQS_SIG_STFL_SECRET_KEY_SET_store_cb + * + */ + + #if defined(__cplusplus) extern "C" { #endif @@ -279,7 +302,7 @@ typedef struct OQS_SIG_STFL_SECRET_KEY { * @return OQS_SUCCESS or OQS_ERROR * Idealy written to secure device */ - OQS_STATUS (*secure_store_scrt_key)(/*const*/ uint8_t *sk_buf, size_t buf_len, void *context); + OQS_STATUS (*secure_store_scrt_key)(uint8_t *sk_buf, size_t buf_len, void *context); /** * Secret Key free internal variant specific data