2025-01-17 18:27:46 +03:00

165 lines
4.4 KiB
C

/*
* 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 = OQS_ERROR;
/*
* 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 = OQS_MEM_malloc(sig->length_public_key);
sk_fname = OQS_MEM_malloc(strlen(method_name) + strlen(".sk") + 1);
message = OQS_MEM_malloc(message_len);
signature = OQS_MEM_malloc(sig->length_signature);
if ((public_key == NULL) || (message == NULL) || (signature == NULL) || (sk_fname == NULL)) {
fprintf(stderr, "ERROR: OQS_MEM_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_secure_free(message, message_len);
OQS_MEM_insecure_free(signature);
OQS_SIG_STFL_free(sig);
OQS_SIG_STFL_SECRET_KEY_free(secret_key);
return rc;
}
int main(void) {
#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN
OQS_init();
printf("Stateful signature algorithms key and signature generation is not enabled.\n");
if (stfl_example((char *)"XMSS-SHA2_10_256") == OQS_ERROR && stfl_example((char *)"LMS_SHA256_H10_W4") == OQS_ERROR) {
OQS_destroy();
return EXIT_SUCCESS;
} else {
OQS_destroy();
return EXIT_FAILURE;
}
#else
OQS_STATUS lms_status;
OQS_STATUS xmss_status;
OQS_init();
xmss_status = stfl_example((char *)"XMSS-SHA2_10_256");
lms_status = stfl_example((char *)"LMS_SHA256_H10_W4");
OQS_destroy();
#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN
if (xmss_status == OQS_ERROR) {
xmss_status = OQS_SUCCESS;
} else {
xmss_status = OQS_ERROR;
}
#endif
#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN
if (lms_status == OQS_ERROR) {
lms_status = OQS_SUCCESS;
} else {
lms_status = OQS_ERROR;
}
#endif
if ((xmss_status == OQS_SUCCESS) && (lms_status == OQS_SUCCESS)) {
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
#endif
}