#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;
}
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;
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;
}
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");
OQS_SIG_STFL_SECRET_KEY_SET_store_cb(secret_key, do_nothing_save, (void *)sk_fname);
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;
}
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:
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
}