-
Notifications
You must be signed in to change notification settings - Fork 485
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added stateful example application and review comments
- Loading branch information
Showing
4 changed files
with
148 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
|