Skip to content

Commit

Permalink
Na statful sig lock (#1559)
Browse files Browse the repository at this point in the history
* Add mutex protection around access to stateful secret key

* Formatting.

* Clean up warnings

* Exclude XMSS from some tests temporarily

* Remove commented code.

* Document use of callback functions for secret key thread safe protection and storage.
  • Loading branch information
ashman-p authored and cothan committed Apr 2, 2024
1 parent 897209e commit e5bcfa1
Show file tree
Hide file tree
Showing 5 changed files with 572 additions and 16 deletions.
12 changes: 11 additions & 1 deletion src/sig_stfl/lms/sig_stfl_lms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
31 changes: 26 additions & 5 deletions src/sig_stfl/lms/sig_stfl_lms_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
*/
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}

Expand Down
49 changes: 49 additions & 0 deletions src/sig_stfl/sig_stfl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
110 changes: 103 additions & 7 deletions src/sig_stfl/sig_stfl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@

#include <oqs/oqs.h>

/*
* 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
Expand Down Expand Up @@ -66,9 +89,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)(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 (*secure_store_sk)(/*const*/ uint8_t *sk_buf, size_t buf_len, void *context);
typedef OQS_STATUS (*unlock_key)(void *mutex);

/**
* Returns identifiers for available signature schemes in liboqs. Used with OQS_SIG_STFL_new.
Expand Down Expand Up @@ -205,6 +244,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);

Expand Down Expand Up @@ -237,18 +279,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
Expand All @@ -260,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
Expand Down Expand Up @@ -388,6 +430,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 .
Expand Down
Loading

0 comments on commit e5bcfa1

Please sign in to comment.