Skip to content

Commit

Permalink
Stateful sigs secret key storage callback (#1553)
Browse files Browse the repository at this point in the history
* Callback implemention updating secret key.

* Block XMSS from secret key tests until after support code has been added.

* Remove / from test file names

* Format

* Address SA issues

* Fix mem leak

* Fix mem leak

* Address various comments

* Fix SA issue
  • Loading branch information
ashman-p authored and SWilson4 committed Dec 15, 2023
1 parent 28080ad commit 64a941b
Show file tree
Hide file tree
Showing 8 changed files with 404 additions and 90 deletions.
24 changes: 20 additions & 4 deletions src/sig_stfl/lms/sig_stfl_lms.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include "sig_stfl_lms_wrap.h"
#include "sig_stfl_lms.h"

/* 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);

/* Insert lms byte string in an LMS secret key object */
static OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context);

static void OQS_SECRET_KEY_LMS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context);

// ======================== LMS-SHA256 H5/W1 ======================== //

OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key) {
Expand Down Expand Up @@ -88,13 +96,15 @@ OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W1_new(void) {
/*
* Set Secret Key Saving Function
*/
sk->save_secret_key = NULL;
sk->secure_store_scrt_key = NULL;

/*
* Set Secret Key free function
*/
sk->free_key = OQS_SECRET_KEY_LMS_free;

sk->set_scrt_key_store_cb = OQS_SECRET_KEY_LMS_set_store_cb;

return sk;
}

Expand All @@ -103,11 +113,17 @@ void OQS_SECRET_KEY_LMS_free(OQS_SIG_STFL_SECRET_KEY *sk) {
}

/* Convert LMS secret key object to byte string */
OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr) {
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);
}

/* Insert lms byte string in an LMS secret key object */
OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf) {
return oqs_deserialize_lms_key(sk, sk_len, sk_buf);
static OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context) {
return oqs_deserialize_lms_key(sk, sk_len, sk_buf, context);
}

static void OQS_SECRET_KEY_LMS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) {
if (sk && store_cb && context) {
oqs_lms_key_set_store_cb(sk, store_cb, context);
}
}
9 changes: 2 additions & 7 deletions src/sig_stfl/lms/sig_stfl_lms.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w1_keypair(uint8_t *public_key

OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W1_new(void);

/* Convert LMS secret key object to byte string */
OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr);

/* Insert lms byte string in an LMS secret key object */
OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t key_len, const uint8_t *sk_buf);

OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w1_new(void);

OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_left(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key);
Expand All @@ -39,7 +33,8 @@ int oqs_sig_stfl_lms_verify(const uint8_t *m, size_t mlen, const uint8_t *sm, si
void oqs_secret_lms_key_free(OQS_SIG_STFL_SECRET_KEY *sk);

OQS_STATUS oqs_serialize_lms_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_key);
OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf);
OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context);
void oqs_lms_key_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context);

// ---------------------------- FUNCTIONS INDEPENDENT OF VARIANT -----------------------------------------

Expand Down
79 changes: 64 additions & 15 deletions src/sig_stfl/lms/sig_stfl_lms_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,70 @@ typedef struct OQS_LMS_KEY_DATA {

/* secret key data */
uint8_t *sec_key;

/* app specific */
void *context;
} 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) {

if (secret_key == NULL || message == NULL || signature == NULL) {
OQS_STATUS rc_keyupdate = OQS_ERROR;
oqs_lms_key_data *lms_key_data = NULL;
const OQS_SIG_STFL_SECRET_KEY *sk;
uint8_t *sk_key_buf = NULL;
size_t sk_key_buf_len = 0;
void *context;

if (secret_key == NULL || message == NULL || signature == NULL || signature_length == NULL) {
return OQS_ERROR;
}

/* TODO: Make sure we have a way to update the private key */
/*
* Don't even attempt signing without a way to safe the updated private key
*/
if (secret_key->secure_store_scrt_key == NULL) {
goto err;
}

lms_key_data = (oqs_lms_key_data *)secret_key->secret_key_data;
if (lms_key_data == NULL) {
goto err;
}

if (oqs_sig_stfl_lms_sign(secret_key, signature,
signature_length,
message, message_len) != 0) {
return OQS_ERROR;
goto err;
}

/*
* serialize and securely store the updated private key
* but, delete signature and the serialized key other wise
*/

sk = secret_key;
rc_keyupdate = oqs_serialize_lms_key(sk, &sk_key_buf_len, &sk_key_buf);
if (rc_keyupdate != OQS_SUCCESS) {
goto err;
}

context = lms_key_data->context;
rc_keyupdate = secret_key->secure_store_scrt_key(sk_key_buf, sk_key_buf_len, context);
if (rc_keyupdate != OQS_SUCCESS) {
goto err;
}

/* TODO: Update private key */
OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len);
return OQS_SUCCESS;

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;
}

OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_verify(const uint8_t *message, size_t message_len,
Expand Down Expand Up @@ -356,11 +401,6 @@ void oqs_secret_lms_key_free(OQS_SIG_STFL_SECRET_KEY *sk) {

//TODO: cleanup lock_key

if (sk->sig) {
OQS_MEM_insecure_free(sk->sig);
sk->sig = NULL;
}

if (sk->secret_key_data) {
oqs_lms_key_data *key_data = (oqs_lms_key_data *)sk->secret_key_data;
if (key_data) {
Expand Down Expand Up @@ -426,7 +466,7 @@ OQS_STATUS oqs_serialize_lms_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_l
* Writes secret key + aux data if present
* key_len is priv key length + aux length
*/
OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf) {
OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context) {

oqs_lms_key_data *lms_key_data = NULL;
uint8_t *lms_sk = NULL;
Expand All @@ -451,11 +491,11 @@ OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_
param_set_t lm_ots_type[ MAX_HSS_LEVELS ];

// validate sk_buf for lms params
if (hss_get_parameter_set(&levels,
lm_type,
lm_ots_type,
NULL,
(void *)sk_buf)) {
if (!hss_get_parameter_set(&levels,
lm_type,
lm_ots_type,
NULL,
(void *)sk_buf)) {
return OQS_ERROR;
}

Expand All @@ -469,6 +509,7 @@ OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_
memcpy(lms_sk, sk_buf, lms_sk_len);
lms_key_data->sec_key = lms_sk;
lms_key_data->len_sec_key = lms_sk_len;
lms_key_data->context = context;

if (aux_buf_len) {
lms_aux = malloc(aux_buf_len * sizeof(uint8_t));
Expand All @@ -494,3 +535,11 @@ OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_
success:
return OQS_SUCCESS;
}

void oqs_lms_key_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) {
oqs_lms_key_data *lms_key_data = (oqs_lms_key_data *)sk->secret_key_data;
if (lms_key_data) {
lms_key_data->context = context;
sk->secure_store_scrt_key = store_cb;
}
}
33 changes: 33 additions & 0 deletions src/sig_stfl/sig_stfl.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,36 @@ OQS_API void OQS_SIG_STFL_SECRET_KEY_free(OQS_SIG_STFL_SECRET_KEY *sk) {
}
OQS_MEM_secure_free(sk, sizeof(sk));
}

OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) {
if (sk) {
if (sk->set_scrt_key_store_cb) {
sk->set_scrt_key_store_cb(sk, store_cb, context);
}
}
}

/* Convert secret key object to byte string */
OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf) {
if ((sk == NULL) || (sk_len == NULL) || (sk_buf == NULL)) {
return 0;
}
if (sk->serialize_key) {
return sk->serialize_key(sk, sk_len, sk_buf);
} else {
return 0;
}
}

/* Insert secret key byte string in an Stateful secret key object */
OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t key_len, const uint8_t *sk_buf, void *context) {
if ((sk == NULL) || (sk_buf == NULL)) {
return OQS_ERROR;
}

if (sk->deserialize_key == NULL) {
return OQS_ERROR;
}

return sk->deserialize_key(sk, key_len, sk_buf, context);
}
58 changes: 50 additions & 8 deletions src/sig_stfl/sig_stfl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ extern "C" {

typedef struct OQS_SIG_STFL_SECRET_KEY OQS_SIG_STFL_SECRET_KEY;

/**
* Application provided function to securely store data
* @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
*/
typedef OQS_STATUS (*secure_store_sk)(/*const*/ uint8_t *sk_buf, size_t buf_len, void *context);

/**
* Returns identifiers for available signature schemes in liboqs. Used with OQS_SIG_STFL_new.
*
Expand Down Expand Up @@ -216,13 +225,14 @@ typedef struct OQS_SIG_STFL_SECRET_KEY {
/**
* set Secret Key to internal structure Function
*
* @param[out] sk OQS_SIG_STFL_SECRET_KEY object
* @param[in] sk_len length of the returned byte string
* @param[in] sk_buf The secret key represented as OQS_SIG_STFL_SECRET_KEY object
* @param[in] sk OQS_SIG_STFL_SECRET_KEY object
* @param[in] key_len length of the returned byte string
* @param[in] sk_buf The secret key data to populate key obj
* @param[in] context application specific data
* @returns status of the operation populated with key material none-zero length. Caller
* deletes the buffer. if sk_buf is NULL the function returns the length
*/
OQS_STATUS (*deserialize_key)(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf);
OQS_STATUS (*deserialize_key)(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context);

/**
* Secret Key Locking Function
Expand All @@ -241,12 +251,16 @@ typedef struct OQS_SIG_STFL_SECRET_KEY {
OQS_STATUS (*unlock_key)(OQS_SIG_STFL_SECRET_KEY *sk);

/**
* Secret Key Saving Function
* Store Secret Key Function
* Callback function used to securely store key data
* @param[in] sk_buf The serialized secret key data to secure store
* @param[in] buf_len length of data to secure
* @param[in] context aides the secure writing of data
*
* @param[in] sk The secret key represented as OQS_SIG_STFL_SECRET_KEY object
* @return OQS_SUCCESS or OQS_ERROR
* Idealy written to secure device
*/
OQS_STATUS (*save_secret_key)(const OQS_SIG_STFL_SECRET_KEY *sk);
OQS_STATUS (*secure_store_scrt_key)(/*const*/ uint8_t *sk_buf, size_t buf_len, void *context);

/**
* Secret Key free internal variant specific data
Expand All @@ -255,6 +269,15 @@ typedef struct OQS_SIG_STFL_SECRET_KEY {
* @return none
*/
void (*free_key)(OQS_SIG_STFL_SECRET_KEY *sk);

/**
* Set Secret Key store callback Function
*
* @param[in] sk secret key pointer to be updated
* @param[in] store_cb callback pointer
* @param[in] context secret key specific data/identifier
*/
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 All @@ -281,7 +304,7 @@ OQS_API OQS_SIG_STFL *OQS_SIG_STFL_new(const char *method_name);
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_STFL_keypair(const OQS_SIG_STFL *sig, uint8_t *pk, OQS_SIG_STFL_SECRET_KEY *sk);
OQS_API OQS_STATUS OQS_SIG_STFL_keypair(const OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key);

/**
* Signature generation algorithm.
Expand Down Expand Up @@ -365,6 +388,25 @@ 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_store_cb .
*
* Can be called after creating a new stateful secret key has been generated.
* Allows the lib to securely store and update secret key after a sign operation.
*
* @param[in] sk secret key pointer to be updated
* @param[in] store_cb callback pointer
* @param[in] context secret key specific data/identifier
*
*/
void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context);

OQS_API OQS_STATUS OQS_SECRET_KEY_STFL_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf);

/* Insert lms byte string in an LMS secret key object */
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);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/sig_stfl/xmss/sig_stfl_xmss.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,6 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_sigs_total(unsigned l
OQS_STATUS OQS_SECRET_KEY_XMSS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr);

/* Deserialize XMSS byte string into an XMSS secret key data */
OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf);
OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, void *context);

#endif /* OQS_SIG_STFL_XMSS_H */
8 changes: 7 additions & 1 deletion src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
#include <string.h>
#include "sig_stfl_xmss.h"

#if defined(__GNUC__) || defined(__clang__)
#define XMSS_UNUSED_ATT __attribute__((unused))
#else
#define XMSS_UNUSED_ATT
#endif

/* Serialize XMSS secret key data into a byte string */
OQS_STATUS OQS_SECRET_KEY_XMSS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk, size_t *sk_len, uint8_t **sk_buf_ptr) {
if (sk == NULL || sk_len == NULL || sk_buf_ptr == NULL) {
Expand All @@ -25,7 +31,7 @@ OQS_STATUS OQS_SECRET_KEY_XMSS_serialize_key(const OQS_SIG_STFL_SECRET_KEY *sk,
}

/* Deserialize XMSS byte string into an XMSS secret key data */
OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf) {
OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, XMSS_UNUSED_ATT void *context) {
if (sk == NULL || sk_buf == NULL || (sk_len != sk->length_secret_key)) {
return OQS_ERROR;
}
Expand Down
Loading

0 comments on commit 64a941b

Please sign in to comment.