Merge pull request #403 from philljj/xmss_hooks_support

Example for xmss hooks support.
pull/407/head
JacobBarthelmeh 2023-10-13 15:53:52 -06:00 committed by GitHub
commit 27b7119631
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 3386 additions and 13 deletions

7
.gitignore vendored
View File

@ -242,6 +242,13 @@ pk/ed448/*.der
pk/curve25519/curve25519_test pk/curve25519/curve25519_test
pk/hpke/hpke_test pk/hpke/hpke_test
# Post-Quantum Stateful Hash-Based Signatures.
pq/stateful_hash_sig/xmss_example
pq/stateful_hash_sig/xmss_example.key
pq/stateful_hash_sig/lms_example
pq/stateful_hash_sig/lms_example.key
embedded/tls-client-server embedded/tls-client-server
embedded/tls-server-size embedded/tls-server-size
embedded/tls-sock-client embedded/tls-sock-client

View File

@ -1,14 +1,16 @@
# PQ Stateful Hash-Based Signature Examples Makefile # PQ Stateful Hash-Based Signature Examples Makefile
CC = gcc CC = gcc
LIB_PATH = /usr/local LIB_PATH = /usr/local
HSS_INC = <path to hss install> HSS_INC =
CFLAGS = -Wall -I$(LIB_PATH)/include -I$(HSS_INC) XMSS_INC =
CFLAGS = -Wall -I$(LIB_PATH)/include
LIBS = -L$(LIB_PATH)/lib -lm LIBS = -L$(LIB_PATH)/lib -lm
# option variables # option variables
DYN_LIB = -lwolfssl WOLF_DYN_LIB = -lwolfssl
STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a WOLF_STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a
HSS_LIB = <path to hss_lib_thread.a> HSS_LIB =
XMSS_LIB =
DEBUG_FLAGS = -g -DDEBUG DEBUG_FLAGS = -g -DDEBUG
DEBUG_INC_PATHS = -MD DEBUG_INC_PATHS = -MD
OPTIMIZE = -Os OPTIMIZE = -Os
@ -16,9 +18,6 @@ OPTIMIZE = -Os
# Options # Options
#CFLAGS+=$(DEBUG_FLAGS) #CFLAGS+=$(DEBUG_FLAGS)
#CFLAGS+=$(OPTIMIZE) #CFLAGS+=$(OPTIMIZE)
LIBS+=$(STATIC_LIB)
#LIBS+=$(DYN_LIB)
LIBS+=$(HSS_LIB)
# build targets # build targets
SRC=$(wildcard *.c) SRC=$(wildcard *.c)
@ -33,8 +32,16 @@ debug: all
# build template # build template
lms_example: lms_example.c lms_example: lms_example.c
$(CC) -o $@ $< $(CFLAGS) $(LIBS) $(CC) -o $@ $< $(CFLAGS) -I$(HSS_INC) $(LIBS) $(WOLF_STATIC_LIB) $(HSS_LIB)
xmss_example: xmss_example.c
$(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) $(LIBS) $(WOLF_STATIC_LIB) $(XMSS_LIB)
xmss_example_verifyonly: xmss_example.c
$(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) -DWOLFSSL_XMSS_VERIFY_ONLY $(LIBS) $(WOLF_STATIC_LIB) $(XMSS_LIB)
clean: clean:
rm -f $(TARGETS) rm -f $(TARGETS)
rm -f xmss_example_verifyonly
rm -f lms_example.key rm -f lms_example.key
rm -f xmss_example.key

View File

@ -6,15 +6,25 @@ This directory contains:
with configurable LMS/HSS parameters. Requires wolfssl with `--enable-lms=yes` with configurable LMS/HSS parameters. Requires wolfssl with `--enable-lms=yes`
and `--with-liblms=<path to hash-sigs install>`. and `--with-liblms=<path to hash-sigs install>`.
- An example that uses wolfCrypt XMSS/XMSS^MT hooks to sign and verify a message
with a configurable XMSS/XMSS^MT parameter string. Requires wolfssl with `--enable-xmss=yes`
and `--with-libxmss=<path to patched xmss-reference install>`.
# Prerequisites # Prerequisites
The LMS sign verify example requires that hash-sigs has been built, and The LMS/HSS sign verify example requires that hash-sigs has been built, and
wolfSSL has been built with LMS/HSS support enabled. Please see Item 17 wolfSSL has been built with LMS/HSS support enabled. Please see Item 17
in the wolfSSL repo's INSTALL file. in the wolfSSL repo's INSTALL file.
https://github.com/wolfSSL/wolfssl/blob/master/INSTALL https://github.com/wolfSSL/wolfssl/blob/master/INSTALL
## Building the Applications The XMSS/XMSS^MT example requires that the xmss-reference repository has been
cloned, patched, and built. Please see item 20 in the wolfSSL repo's INSTALL file.
The patch to use is `0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch` from this XMSS/XMSS^MT example.
This patch includes an addendum readme, `patch_readme.md`, that lists all changes made and explains their rationale.
# Building the LMS/HSS example
Configure the Makefile to point to your hash-sigs install: Configure the Makefile to point to your hash-sigs install:
@ -29,7 +39,7 @@ HSS_LIB = <path to hss_lib_thread.a>
Then build: Then build:
``` ```
$ make $ make lms_example
``` ```
## Signing and Verifying a Message with LMS/HSS ## Signing and Verifying a Message with LMS/HSS
@ -66,3 +76,147 @@ examples:
description: description:
... ...
``` ```
# Building the XMSS/XMSS^MT example
Configure the Makefile to point to your xmss install:
```
XMSS_INC = <path to patched xmss install>
```
```
XMSS_LIB = <path to xmss_lib.a or xmss_verify_lib.a>
```
Then build:
```
$ make xmss_example
```
Build the verify-only example with
```
$ make xmss_example_verifyonly
```
## Signing and Verifying a Message with XMSS/XMSS^MT
To see the help and usage, run the program without options:
```sh
$ ./xmss_example
usage:
./xmss_example <param string> [num signatures]
examples:
./xmss_example XMSSMT-SHA2_20/4_256 5
./xmss_example XMSSMT-SHA2_60/6_256 100
./xmss_example XMSS-SHA2_10_256 1023
```
The param string may be any name from this table:
```
----------------------------------------------------------
| Name Oid n w len h d |
XMSS: | "XMSS-SHA2_10_256" 0x00000001 32 16 67 10 1 |
| "XMSS-SHA2_16_256" 0x00000002 32 16 67 16 1 |
| "XMSS-SHA2_20_256" 0x00000003 32 16 67 20 1 |
| |
XMSSMT: | "XMSSMT-SHA2_20/2_256" 0x00000001 32 16 67 20 2 |
| "XMSSMT-SHA2_20/4_256" 0x00000002 32 16 67 20 4 |
| "XMSSMT-SHA2_40/2_256" 0x00000003 32 16 67 40 2 |
| "XMSSMT-SHA2_40/4_256" 0x00000004 32 16 67 40 4 |
| "XMSSMT-SHA2_40/8_256" 0x00000005 32 16 67 40 8 |
| "XMSSMT-SHA2_60/3_256" 0x00000006 32 16 67 60 3 |
| "XMSSMT-SHA2_60/6_256" 0x00000007 32 16 67 60 6 |
| "XMSSMT-SHA2_60/12_256" 0x00000008 32 16 67 60 12 |
----------------------------------------------------------
```
Here `n=32` is the number of bytes in the SHA256 has function, `w=16`
is the Winternitz parameter, `len=67` is the length of Winternitz chains,
`h` is the is the total height of the tree or hyper-tree, and `d` is the
number of levels in the hyper-tree. The number of signatures available
is `N = 2 ** (h)`.
The main contributor to key generation time is the ratio `h/d`.
Not surprisingly, be aware that `XMSS-SHA2_20_256`, and `XMSSMT-SHA2_60/3_256`, are particularly
CPU intensive because of the large number of hash operations involved, and
may take a long time. E.g. on an Intel i7 linux system these examples took
approximately 24 min, and 1 hour, respectively.
The other examples will be much faster.
An interesting facet of XMSS/XMSS^MT is that the private key format
and size is implementation specific. The wolfSSL XMSS/XMSS^MT hooks
feature uses the "fast" implementation from xmss-reference, which
has larger private key sizes.
For example:
```
$ ./xmss_example "XMSSMT-SHA2_20/2_256" 200
using parameters: XMSSMT-SHA2_20/2_256
signature length: 4963
priv key length: 6002
pub key length: 68
...done!
signing and verifying 200 signatures...
...done!
finished
```
```
$ ./xmss_example "XMSSMT-SHA2_40/4_256" 200
using parameters: XMSSMT-SHA2_40/4_256
signature length: 9893
priv key length: 15256
pub key length: 68
...done!
signing and verifying 200 signatures...
...done!
finished
```
## Using the verify-only XMSS/XMSS^MT example
The usage for the verify-only example is:
```
$ ./xmss_example_verifyonly
usage:
./xmss_example_verifyonly <param string> <pub file> <sig file> <msg file>
For simplicity message is assumed to be 32 bytes in size.
examples:
./xmss_example_verifyonly XMSSMT-SHA2_20/4_256 xmss_pub.key xmss_sig.bin msg.bin
./xmss_example_verifyonly XMSSMT-SHA2_60/6_256 xmss_pub.key xmss_sig.bin msg.bin
./xmss_example_verifyonly XMSS-SHA2_10_256 xmss_pub.key xmss_sig.bin msg.bin
```
An example:
```
$./xmss_example_verifyonly XMSSMT-SHA2_20/2_256 pk.bin sig.bin msg.bin
using parameters: XMSSMT-SHA2_20/2_256
pub:
0x00 0x00 0x00 0x01 0x2B 0xC1 0xA4 0x8D
0x32 0x4B 0x15 0xA8 0xF6 0xEA 0x04 0xC0
0x96 0x52 0x70 0x4D 0x4C 0x19 0x94 0xA4
0x2D 0x2E 0xDA 0x52 0xA4 0x5F 0xF7 0xA8
0x50 0x0A 0xE1 0xB3 0x77 0xD6 0x85 0x33
0xB0 0x8A 0x4F 0x9D 0x54 0x6B 0xE9 0xFE
0x4B 0x3B 0xCB 0x5A 0x7A 0x92 0x86 0x0C
0x4B 0x7F 0xBF 0x2E 0xA0 0x1F 0x47 0x6F
0xDB 0x35 0x1C 0x61
msg:
0xF1 0x91 0x9C 0xC0 0xA7 0xDC 0xEB 0xCE
0x38 0x96 0xEC 0x28 0x3A 0x9E 0xE1 0xA0
0xA3 0x2F 0x94 0x1E 0xE7 0xB0 0x56 0x15
0x54 0x8C 0x17 0xF4 0x65 0xFF 0xCB 0x08
signature length: 4963
pub key length: 68
Verify good!
finished
```

View File

@ -1,6 +1,6 @@
/* lms_example.c /* lms_example.c
* *
* Copyright (C) 2022 wolfSSL Inc. * Copyright (C) 2023 wolfSSL Inc.
* *
* This file is part of wolfSSL. * This file is part of wolfSSL.
* *

View File

@ -0,0 +1,552 @@
/* xmss_example.c
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef HAVE_LIBXMSS
#include <wolfssl/wolfcrypt/xmss.h>
#include <wolfssl/wolfcrypt/ext_xmss.h>
static void dump_hex(const char * what, const uint8_t * buf, size_t len);
static void print_usage(void);
#if !defined WOLFSSL_XMSS_VERIFY_ONLY
static int write_key_file(const byte * priv, word32 privSz, void * context);
static int read_key_file(byte * priv, word32 privSz, void * context);
static int do_xmss_example(const char * params, size_t sigs_to_do);
static WC_RNG rng;
static byte * read_buf = NULL;
int
main(int argc,
char * argv[])
{
const char * params = NULL;
size_t sigs_to_do = 1;
int ret = 0;
if (argc < 2 || argc > 3) {
print_usage();
return EXIT_FAILURE;
}
params = argv[1];
if (argc == 3) {
sigs_to_do = atoll(argv[2]);
}
ret = wc_InitRng(&rng);
if (ret) {
fprintf(stderr, "error: wc_InitRng returned %d\n", ret);
return EXIT_FAILURE;
}
ret = do_xmss_example(params, sigs_to_do);
wc_FreeRng(&rng);
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
static void
print_usage(void)
{
fprintf(stderr, "usage:\n");
fprintf(stderr, " ./xmss_example <param string> [num signatures]\n");
fprintf(stderr, "\n");
fprintf(stderr, "examples:\n");
fprintf(stderr, " ./xmss_example XMSSMT-SHA2_20/4_256 5\n");
fprintf(stderr, " ./xmss_example XMSSMT-SHA2_60/6_256 100\n");
fprintf(stderr, " ./xmss_example XMSS-SHA2_10_256 1023\n");
exit(EXIT_FAILURE);
}
static int
write_key_file(const byte * priv,
word32 privSz,
void * context)
{
FILE * file = NULL;
const char * filename = NULL;
int n_cmp = 0;
size_t n_read = 0;
size_t n_write = 0;
int err = 0;
if (priv == NULL || context == NULL || privSz == 0) {
fprintf(stderr, "error: invalid write args\n");
return WC_XMSS_RC_BAD_ARG;
}
filename = context;
/* Open file for read and write. */
file = fopen(filename, "r+");
if (!file) {
/* Create the file if it didn't exist. */
file = fopen(filename, "w+");
if (!file) {
fprintf(stderr, "error: fopen(%s, \"w+\") failed: %d\n", filename,
ferror(file));
return WC_XMSS_RC_WRITE_FAIL;
}
}
n_write = fwrite(priv, 1, privSz, file);
if (n_write != privSz) {
fprintf(stderr, "error: wrote %zu, expected %d: %d\n", n_write, privSz,
ferror(file));
return WC_XMSS_RC_WRITE_FAIL;
}
/* Verify data has actually been written to disk correctly. */
rewind(file);
XMEMSET(read_buf, 0, n_write);
n_read = fread(read_buf, 1, n_write, file);
if (n_read != n_write) {
fprintf(stderr, "error: read %zu, expected %zu: %d\n", n_read, n_write,
ferror(file));
return WC_XMSS_RC_WRITE_FAIL;
}
n_cmp = XMEMCMP(read_buf, priv, n_write);
if (n_cmp != 0) {
fprintf(stderr, "error: write data was corrupted: %d\n", n_cmp);
return WC_XMSS_RC_WRITE_FAIL;
}
err = fclose(file);
if (err) {
fprintf(stderr, "error: fclose returned %d\n", err);
return WC_XMSS_RC_WRITE_FAIL;
}
return WC_XMSS_RC_SAVED_TO_NV_MEMORY;
}
static int
read_key_file(byte * priv,
word32 privSz,
void * context)
{
FILE * file = NULL;
const char * filename = NULL;
size_t n_read = 0;
if (priv == NULL || context == NULL || privSz == 0) {
fprintf(stderr, "error: invalid read args\n");
return WC_XMSS_RC_BAD_ARG;
}
filename = context;
file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "error: fopen(%s, \"rb\") failed\n", filename);
return WC_XMSS_RC_READ_FAIL;
}
n_read = fread(priv, 1, privSz, file);
if (n_read != privSz) {
fprintf(stderr, "error: read %zu, expected %d: %d\n", n_read, privSz,
ferror(file));
return WC_XMSS_RC_READ_FAIL;
}
fclose(file);
return WC_XMSS_RC_READ_TO_MEMORY;
}
static int
do_xmss_example(const char * params,
size_t sigs_to_do)
{
XmssKey signingKey;
XmssKey verifyKey;
const char * msg = "wolfSSL XMSS example message!";
const char * filename = "xmss_example.key";
int ret = 0;
byte * sig = NULL;
word32 sigSz = 0;
word32 privSz = 0;
word32 pubSz = 0;
printf("using parameters: %s\n", params);
ret = wc_XmssKey_Init(&signingKey, NULL, 0);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_Init(&verifyKey, NULL, 0);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_SetParamStr(&signingKey, params);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_SetParameters(%s) returned %d\n",
params, ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_SetWriteCb(&signingKey, write_key_file);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_SetWriteCb failed: %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_SetReadCb(&signingKey, read_key_file);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_SetReadCb failed: %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_SetContext(&signingKey, (void *) filename);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_SetContext failed: %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_GetSigLen(&signingKey, &sigSz);
if (ret || sigSz == 0) {
fprintf(stderr, "error: wc_XmssKey_GetSigLen returned: %d, %d\n",
ret, sigSz);
goto exit_xmss_example;
}
ret = wc_XmssKey_GetPubLen(&signingKey, &pubSz);
if (ret || pubSz == 0) {
fprintf(stderr, "error: wc_XmssKey_GetPubLen returned: %d, %d\n",
ret, pubSz);
goto exit_xmss_example;
}
ret = wc_XmssKey_GetPrivLen(&signingKey, &privSz);
if (ret || pubSz == 0) {
fprintf(stderr, "error: wc_XmssKey_GetPrivLen returned: %d, %d\n",
ret, privSz);
goto exit_xmss_example;
}
printf("signature length: %d\n", sigSz);
printf("priv key length: %d\n", privSz);
printf("pub key length: %d\n", pubSz);
read_buf = malloc(privSz);
if (read_buf == NULL) {
fprintf(stderr, "error: malloc read_buf failed\n");
goto exit_xmss_example;
}
printf("making key with %s parameters...\n", params);
ret = wc_XmssKey_MakeKey(&signingKey, &rng);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_MakeKey returned %d\n", ret);
goto exit_xmss_example;
}
printf("...done!\n");
if (sigs_to_do == 0) {
read_key_file(read_buf, privSz, (void *) filename);
dump_hex("priv", read_buf, privSz);
dump_hex("pub", signingKey.pk, pubSz);
goto exit_xmss_example;
}
sig = malloc(sigSz);
if (sig == NULL) {
fprintf(stderr, "error: malloc(%d) failed\n", sigSz);
goto exit_xmss_example;
}
ret = wc_XmssKey_ExportPub(&verifyKey, &signingKey);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_ExportPub returned %d\n", ret);
goto exit_xmss_example;
}
printf("signing and verifying %zu signatures...\n", sigs_to_do);
for (size_t i = 0; i < sigs_to_do; ++i) {
ret = wc_XmssKey_Sign(&signingKey, sig, &sigSz,(byte *) msg,
strlen(msg));
if (ret) {
fprintf(stderr, "error: %zu: wc_XmssKey_Sign returned %d\n", i, ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (const byte *) msg,
strlen(msg));
if (ret) {
fprintf(stderr, "error: %zu: wc_XmssKey_Verify returned %d\n", i, ret);
goto exit_xmss_example;
}
}
printf("...done!\n");
printf("finished\n");
exit_xmss_example:
if (sig != NULL) {
free(sig);
sig = NULL;
}
if (read_buf != NULL) {
free(read_buf);
read_buf = NULL;
}
wc_XmssKey_Free(&signingKey);
wc_XmssKey_Free(&verifyKey);
return ret;
}
#else /* if !defined WOLFSSL_XMSS_VERIFY_ONLY */
static int read_file(byte * data, word32 len, const char * filename);
static int do_xmss_example(const char * params, const char * pubfile,
const char * sigfile, const char * msgfile);
int
main(int argc,
char * argv[])
{
const char * params = NULL;
const char * pubfile = NULL;
const char * sigfile = NULL;
const char * msgfile = NULL;
int ret = 0;
if (argc != 5) {
print_usage();
}
params = argv[1];
pubfile = argv[2];
sigfile = argv[3];
msgfile = argv[4];
ret = do_xmss_example(params, pubfile, sigfile, msgfile);
return ret;
}
static void
print_usage(void)
{
fprintf(stderr, "usage:\n");
fprintf(stderr, " ./xmss_example_verifyonly <param string> <pub file> <sig file> <msg file>\n");
fprintf(stderr, "\n");
fprintf(stderr, "For simplicity message is assumed to be 32 bytes in size.\n");
fprintf(stderr, "\n");
fprintf(stderr, "examples:\n");
fprintf(stderr, " ./xmss_example_verifyonly XMSSMT-SHA2_20/4_256 xmss_pub.key xmss_sig.bin msg.bin\n");
fprintf(stderr, " ./xmss_example_verifyonly XMSSMT-SHA2_60/6_256 xmss_pub.key xmss_sig.bin msg.bin\n");
fprintf(stderr, " ./xmss_example_verifyonly XMSS-SHA2_10_256 xmss_pub.key xmss_sig.bin msg.bin\n");
exit(EXIT_FAILURE);
}
static int
do_xmss_example(const char * params,
const char * pubfile,
const char * sigfile,
const char * msgfile)
{
int ret = 0;
XmssKey verifyKey;
byte * sig = NULL;
word32 sigSz = 0;
word32 pubSz = 0;
byte pub[XMSS_SHA256_PUBLEN];
byte msg[32];
printf("using parameters: %s\n", params);
ret = wc_XmssKey_Init(&verifyKey, NULL, 0);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_SetParamStr(&verifyKey, params);
if (ret) {
fprintf(stderr, "error: wc_XmssKey_SetParameters(%s) returned %d\n",
params, ret);
goto exit_xmss_example;
}
ret = wc_XmssKey_GetSigLen(&verifyKey, &sigSz);
if (ret || sigSz == 0) {
fprintf(stderr, "error: wc_XmssKey_GetSigLen returned: %d, %d\n",
ret, sigSz);
goto exit_xmss_example;
}
ret = wc_XmssKey_GetPubLen(&verifyKey, &pubSz);
if (ret || pubSz == 0) {
fprintf(stderr, "error: wc_XmssKey_GetPubLen returned: %d, %d\n",
ret, pubSz);
goto exit_xmss_example;
}
ret = read_file(msg, sizeof(msg), msgfile);
if (ret) {
fprintf(stderr, "error: read_file(%s) failed\n", msgfile);
goto exit_xmss_example;
}
sig = malloc(sigSz);
if (sig == NULL) {
fprintf(stderr, "error: malloc(%d) failed\n", sigSz);
goto exit_xmss_example;
}
ret = read_file(sig, sigSz, sigfile) ;
if (ret) {
fprintf(stderr, "error: read_file(%s) failed\n", sigfile);
goto exit_xmss_example;
}
ret = read_file(pub, XMSS_SHA256_PUBLEN, pubfile);
if (ret) {
fprintf(stderr, "error: read_file(%s) failed\n", pubfile);
goto exit_xmss_example;
}
ret = wc_XmssKey_ImportPubRaw(&verifyKey, pub, sizeof(pub));
if (ret != 0) {
/* Something is wrong with the pub key or LMS parameters. */
fprintf(stderr, "error: wc_XmssKey_ImportPubRaw" \
" returned %d\n", ret);
goto exit_xmss_example;
}
dump_hex("pub: ", pub, sizeof(pub));
dump_hex("msg: ", msg, sizeof(msg));
printf("signature length: %d\n", sigSz);
printf("pub key length: %d\n", pubSz);
ret = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (const byte *) msg,
sizeof(msg));
if (ret) {
fprintf(stderr, "error: wc_XmssKey_Verify returned %d\n", ret);
goto exit_xmss_example;
}
printf("Verify good!\n");
printf("finished\n");
exit_xmss_example:
if (sig != NULL) {
free(sig);
sig = NULL;
}
wc_XmssKey_Free(&verifyKey);
return ret;
}
static int
read_file(byte * data,
word32 len,
const char * filename)
{
FILE * file = NULL;
size_t n_read = 0;
if (data == NULL || filename == NULL || len == 0) {
fprintf(stderr, "error: invalid read_file args\n");
return -1;
}
file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "error: fopen(%s, \"rb\") failed\n", filename);
return -1;
}
n_read = fread(data, 1, len, file);
if (n_read != len) {
fprintf(stderr, "error: read %zu, expected %d: %d\n", n_read, len,
ferror(file));
return -1;
}
fclose(file);
return 0;
}
#endif /* if !defined WOLFSSL_XMSS_VERIFY_ONLY */
static void
dump_hex(const char * what,
const uint8_t * buf,
size_t len)
{
printf("%s\n", what);
for (size_t i = 0; i < len; ++i) {
printf("0x%02X ", buf[i]);
if ((i + 1) % 8 == 0) {
printf("\n");
}
}
if (len % 8) {
printf("\n");
}
return;
}
#else
int main(int argc, char** argv) {
printf("This requires the --with-libxmss flag.\n");
return 0;
}
#endif /* WITH_LIBXMSS */