Add wrapper that allows for runtime parameters

This commit is contained in:
Joost Rijneveld 2017-08-01 15:31:42 +02:00
bovenliggende 65ee8202d8
commit 9b35b00d98
Geen bekende sleutel gevonden voor deze handtekening in de database
GPG sleutel-ID: 307BC77F47D58EE2
8 gewijzigde bestanden met toevoegingen van 752 en 2 verwijderingen

2
.gitignore vendored
Bestand weergeven

@ -1,8 +1,10 @@
test/test_chacha
test/test_wots
test/test_horst
test/test_xmss
test/test_xmss_core
test/test_xmss_core_fast
test/test_xmssmt
test/test_xmssmt_core
test/test_xmssmt_core_fast
test/test_xmss_core_XMSS*

Bestand weergeven

@ -4,8 +4,10 @@ CFLAGS = -Wall -g -O3 -Wextra
all: test/test_wots \
test/test_xmss_core_XMSS_SHA2-256_W16_H10 \
test/test_xmss_core_fast_XMSS_SHA2-256_W16_H10 \
test/test_xmss \
test/test_xmssmt_core_fast_XMSSMT_SHA2-256_W16_H20_D4 \
test/test_xmssmt_core_XMSSMT_SHA2-256_W16_H20_D4 \
test/test_xmssmt
.PHONY: clean
.PRECIOUS: params_%.h
@ -33,14 +35,23 @@ test/test_xmssmt_core_fast_XMSSMT_%: params_XMSSMT_%.h hash.c fips202.c hash_add
ln -sf params_XMSSMT_$(patsubst test/test_xmssmt_core_fast_XMSSMT_%,%,$@).h params.h
$(CC) $(CFLAGS) hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmssmt_core_fast.c -o $@ -lcrypto -lm
test/test_xmss: params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c params_runtime.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h
ln -sf params_runtime.h params.h
$(CC) $(CFLAGS) params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c -o $@ -lcrypto -lm
test/test_xmssmt: params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c params_runtime.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h
ln -sf params_runtime.h params.h
$(CC) $(CFLAGS) params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c -o $@ -lcrypto -lm
clean:
-rm *.o *.s
-rm test/test_wots
-rm test/test_xmss_core_XMSS*
-rm test/test_xmss_core_fast_XMSS*
-rm test/test_xmss
-rm test/test_xmssmt_core_XMSS*
-rm test/test_xmssmt_core_fast_XMSS*
-rm test/test_xmssmt
distclean:
distclean: clean
-rm params.h
-rm params_XMSS*.h

341
params_runtime.c Normal file
Bestand weergeven

@ -0,0 +1,341 @@
#include <stdint.h>
#include "params_runtime.h"
unsigned int XMSS_FUNC;
unsigned int XMSS_N;
unsigned int XMSS_WOTS_W;
unsigned int XMSS_WOTS_LOG_W;
unsigned int XMSS_WOTS_LEN1;
unsigned int XMSS_WOTS_LEN2;
unsigned int XMSS_WOTS_LEN;
unsigned int XMSS_WOTS_KEYSIZE;
unsigned int XMSS_FULLHEIGHT;
unsigned int XMSS_TREEHEIGHT;
unsigned int XMSS_D;
unsigned int XMSS_INDEX_LEN;
unsigned int XMSS_BYTES;
unsigned int XMSS_PUBLICKEY_BYTES;
unsigned int XMSS_PRIVATEKEY_BYTES;
unsigned int XMSS_OID_LEN;
unsigned int XMSS_BDS_K;
int xmss_parse_oid(uint32_t oid)
{
switch (oid) {
case 0x01000001:
case 0x02000002:
case 0x03000003:
case 0x04000004:
case 0x05000005:
case 0x06000006:
XMSS_FUNC = XMSS_SHA2;
break;
case 0x07000007:
case 0x08000008:
case 0x09000009:
case 0x0a00000a:
case 0x0b00000b:
case 0x0c00000c:
XMSS_FUNC = XMSS_SHAKE;
break;
default:
return 1;
}
switch (oid) {
case 0x01000001:
case 0x02000002:
case 0x03000003:
case 0x07000007:
case 0x08000008:
case 0x09000009:
XMSS_N = 32;
break;
case 0x04000004:
case 0x05000005:
case 0x06000006:
case 0x0a00000a:
case 0x0b00000b:
case 0x0c00000c:
XMSS_N = 64;
break;
default:
return 1;
}
switch (oid) {
case 0x01000001:
case 0x04000004:
case 0x07000007:
case 0x0a00000a:
XMSS_FULLHEIGHT = 10;
break;
case 0x02000002:
case 0x05000005:
case 0x08000008:
case 0x0b00000b:
XMSS_FULLHEIGHT = 16;
break;
case 0x03000003:
case 0x06000006:
case 0x09000009:
case 0x0c00000c:
XMSS_FULLHEIGHT = 20;
break;
default:
return 1;
}
XMSS_D = 1;
XMSS_TREEHEIGHT = XMSS_FULLHEIGHT / XMSS_D;
XMSS_WOTS_W = 16;
XMSS_WOTS_LOG_W = 4;
if (XMSS_N == 32) {
XMSS_WOTS_LEN1 = 64;
}
else {
XMSS_WOTS_LEN1 = 128;
}
XMSS_WOTS_LEN2 = 3;
XMSS_WOTS_LEN = XMSS_WOTS_LEN1 + XMSS_WOTS_LEN2;
XMSS_WOTS_KEYSIZE = XMSS_WOTS_LEN * XMSS_N;
XMSS_INDEX_LEN = 4;
XMSS_BYTES = (XMSS_INDEX_LEN + XMSS_N + XMSS_D*XMSS_WOTS_KEYSIZE
+ XMSS_FULLHEIGHT*XMSS_N);
XMSS_PUBLICKEY_BYTES = 2*XMSS_N;
XMSS_PRIVATEKEY_BYTES = 4*XMSS_N + XMSS_INDEX_LEN;
XMSS_OID_LEN = 4;
// TODO figure out sensible and legal values for this based on the above
XMSS_BDS_K = 0;
return 0;
}
int xmssmt_parse_oid(uint32_t oid)
{
switch (oid) {
case 0x01000001:
case 0x02000002:
case 0x03000003:
case 0x04000004:
case 0x05000005:
case 0x06000006:
case 0x07000007:
case 0x08000008:
case 0x09000009:
case 0x0a00000a:
case 0x0b00000b:
case 0x0c00000c:
case 0x0d00000d:
case 0x0e00000e:
case 0x0f00000f:
case 0x01010101:
XMSS_FUNC = XMSS_SHA2;
break;
case 0x02010102:
case 0x03010103:
case 0x04010104:
case 0x05010105:
case 0x06010106:
case 0x07010107:
case 0x08010108:
case 0x09010109:
case 0x0a01010a:
case 0x0b01010b:
case 0x0c01010c:
case 0x0d01010d:
case 0x0e01010e:
case 0x0f01010f:
case 0x01020201:
case 0x02020202:
XMSS_FUNC = XMSS_SHAKE;
break;
default:
return 1;
}
switch (oid) {
case 0x01000001:
case 0x02000002:
case 0x03000003:
case 0x04000004:
case 0x05000005:
case 0x06000006:
case 0x07000007:
case 0x08000008:
case 0x02010102:
case 0x03010103:
case 0x04010104:
case 0x05010105:
case 0x06010106:
case 0x07010107:
case 0x08010108:
case 0x09010109:
XMSS_N = 32;
break;
case 0x09000009:
case 0x0a00000a:
case 0x0b00000b:
case 0x0c00000c:
case 0x0d00000d:
case 0x0e00000e:
case 0x0f00000f:
case 0x01010101:
case 0x0a01010a:
case 0x0b01010b:
case 0x0c01010c:
case 0x0d01010d:
case 0x0e01010e:
case 0x0f01010f:
case 0x01020201:
case 0x02020202:
XMSS_N = 64;
break;
default:
return 1;
}
switch (oid) {
case 0x01000001:
case 0x02000002:
case 0x09000009:
case 0x0a00000a:
case 0x02010102:
case 0x03010103:
case 0x0a01010a:
case 0x0b01010b:
XMSS_FULLHEIGHT = 20;
break;
case 0x03000003:
case 0x04000004:
case 0x05000005:
case 0x0b00000b:
case 0x0c00000c:
case 0x0d00000d:
case 0x04010104:
case 0x05010105:
case 0x06010106:
case 0x0c01010c:
case 0x0d01010d:
case 0x0e01010e:
XMSS_FULLHEIGHT = 40;
break;
case 0x06000006:
case 0x07000007:
case 0x08000008:
case 0x0e00000e:
case 0x0f00000f:
case 0x01010101:
case 0x07010107:
case 0x08010108:
case 0x09010109:
case 0x0f01010f:
case 0x01020201:
case 0x02020202:
XMSS_FULLHEIGHT = 60;
break;
default:
return 1;
}
switch (oid) {
case 0x01000001:
case 0x03000003:
case 0x09000009:
case 0x0b00000b:
case 0x02010102:
case 0x04010104:
case 0x0a01010a:
case 0x0c01010c:
XMSS_D = 2;
break;
case 0x02000002:
case 0x04000004:
case 0x0a00000a:
case 0x0c00000c:
case 0x03010103:
case 0x05010105:
case 0x0b01010b:
case 0x0d01010d:
XMSS_D = 4;
break;
case 0x05000005:
case 0x0d00000d:
case 0x06010106:
case 0x0e01010e:
XMSS_D = 8;
break;
case 0x06000006:
case 0x0e00000e:
case 0x07010107:
case 0x0f01010f:
XMSS_D = 3;
break;
case 0x07000007:
case 0x0f00000f:
case 0x08010108:
case 0x01020201:
XMSS_D = 6;
break;
case 0x08000008:
case 0x01010101:
case 0x09010109:
case 0x02020202:
XMSS_D = 12;
break;
default:
return 1;
}
XMSS_TREEHEIGHT = XMSS_FULLHEIGHT / XMSS_D;
XMSS_WOTS_W = 16;
XMSS_WOTS_LOG_W = 4;
if (XMSS_N == 32) {
XMSS_WOTS_LEN1 = 64;
}
else {
XMSS_WOTS_LEN1 = 128;
}
XMSS_WOTS_LEN2 = 3;
XMSS_WOTS_LEN = XMSS_WOTS_LEN1 + XMSS_WOTS_LEN2;
XMSS_WOTS_KEYSIZE = XMSS_WOTS_LEN * XMSS_N;
XMSS_INDEX_LEN = 4;
XMSS_BYTES = (XMSS_INDEX_LEN + XMSS_N + XMSS_D*XMSS_WOTS_KEYSIZE
+ XMSS_FULLHEIGHT*XMSS_N);
XMSS_PUBLICKEY_BYTES = 2*XMSS_N;
XMSS_PRIVATEKEY_BYTES = 4*XMSS_N + XMSS_INDEX_LEN;
XMSS_OID_LEN = 4;
// TODO figure out sensible and legal values for this based on the above
XMSS_BDS_K = 0;
return 0;
}

31
params_runtime.h Normal file
Bestand weergeven

@ -0,0 +1,31 @@
#ifndef PARAMS_H
#define PARAMS_H
#include <stdint.h>
// These are simply internal identifiers for the supported hash functions
#define XMSS_SHA2 0
#define XMSS_SHAKE 1
extern unsigned int XMSS_FUNC;
extern unsigned int XMSS_N;
extern unsigned int XMSS_WOTS_W;
extern unsigned int XMSS_WOTS_LOG_W;
extern unsigned int XMSS_WOTS_LEN1;
extern unsigned int XMSS_WOTS_LEN2;
extern unsigned int XMSS_WOTS_LEN;
extern unsigned int XMSS_WOTS_KEYSIZE;
extern unsigned int XMSS_FULLHEIGHT;
extern unsigned int XMSS_TREEHEIGHT;
extern unsigned int XMSS_D;
extern unsigned int XMSS_INDEX_LEN;
extern unsigned int XMSS_BYTES;
extern unsigned int XMSS_PUBLICKEY_BYTES;
extern unsigned int XMSS_PRIVATEKEY_BYTES;
extern unsigned int XMSS_OID_LEN;
extern unsigned int XMSS_BDS_K;
int xmss_parse_oid(uint32_t oid);
int xmssmt_parse_oid(uint32_t oid);
#endif

124
test/test_xmss.c Normal file
Bestand weergeven

@ -0,0 +1,124 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "../xmss.h"
#include "../params.h"
#include "../randombytes.h"
#define MLEN 3491
#define SIGNATURES 5
unsigned char mi[MLEN];
unsigned long long smlen;
unsigned long long mlen;
int main()
{
// TODO test more different OIDs
uint32_t oid = 0x01000001;
xmss_parse_oid(oid); // Parse it to make sure the sizes are set
int r;
unsigned long long i, j;
unsigned long errors = 0;
unsigned char sk[XMSS_OID_LEN + XMSS_PRIVATEKEY_BYTES];
unsigned char pk[XMSS_OID_LEN + XMSS_PUBLICKEY_BYTES];
unsigned char mo[MLEN+XMSS_BYTES];
unsigned char sm[MLEN+XMSS_BYTES];
printf("keypair\n");
xmss_keypair(pk, sk, oid);
// check pub_seed in SK
for (i = 0; i < XMSS_N; i++) {
if (pk[XMSS_OID_LEN+XMSS_N+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i);
if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i);
}
// check index
unsigned long idx = ((unsigned long)sk[4] << 24) | ((unsigned long)sk[5] << 16) | ((unsigned long)sk[6] << 8) | sk[7];
if (idx) printf("\nidx != 0 %lu\n",idx);
for (i = 0; i < SIGNATURES; i++) {
randombytes(mi, MLEN);
printf("sign\n");
xmss_sign(sk, sm, &smlen, mi, MLEN);
idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3];
printf("\nidx = %lu\n",idx);
for (j = 0; j < smlen; j++) {
printf("%02X", sm[j]);
}
printf("\n");
r = memcmp(mi, sm+XMSS_BYTES,MLEN);
printf("%d\n", r);
/* Test valid signature */
printf("verify\n");
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r);
if (r != 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", r);
printf("%llu\n", MLEN-mlen);
/* Test with modified message */
sm[XMSS_BYTES+10] ^= 1;
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
if (r == 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
/* Test with modified signature */
/* Modified index */
sm[XMSS_BYTES+10] ^= 1;
sm[2] ^= 1;
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
if (r == 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
/* Modified R */
sm[2] ^= 1;
sm[5] ^= 1;
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
if (r == 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
/* Modified OTS sig */
sm[5] ^= 1;
sm[240] ^= 1;
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
if (r == 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
/* Modified AUTH */
sm[240] ^= 1;
sm[XMSS_BYTES - 10] ^= 1;
r = xmss_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
if (r == 0) errors++;
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
}
printf("#errors = %lu\n", errors);
return 0;
}

96
test/test_xmssmt.c Normal file
Bestand weergeven

@ -0,0 +1,96 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "../xmss.h"
#include "../params.h"
#include "../randombytes.h"
#define MLEN 3491
#define SIGNATURES 5
unsigned char mi[MLEN];
unsigned long long smlen;
unsigned long long mlen;
int main()
{
// TODO test more different OIDs
uint32_t oid = 0x01000001;
xmssmt_parse_oid(oid); // Parse it to make sure the sizes are set
int r;
unsigned long long i,j;
unsigned char sk[XMSS_OID_LEN + XMSS_PRIVATEKEY_BYTES];
unsigned char pk[XMSS_OID_LEN + XMSS_PUBLICKEY_BYTES];
unsigned char mo[MLEN+XMSS_BYTES];
unsigned char sm[MLEN+XMSS_BYTES];
printf("keypair\n");
xmssmt_keypair(pk, sk, oid);
// check pub_seed in SK
for (i = 0; i < XMSS_N; i++) {
if (pk[XMSS_OID_LEN+XMSS_N+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i);
if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i);
}
printf("pk checked\n");
// check index
unsigned long long idx = 0;
for (i = 0; i < XMSS_INDEX_LEN; i++) {
idx |= ((unsigned long long)sk[i + XMSS_OID_LEN]) << 8*(XMSS_INDEX_LEN - 1 - i);
}
if (idx) printf("\nidx != 0: %llu\n",idx);
for (i = 0; i < SIGNATURES; i++) {
randombytes(mi, MLEN);
printf("sign\n");
xmssmt_sign(sk, sm, &smlen, mi, MLEN);
idx = 0;
for (j = 0; j < XMSS_INDEX_LEN; j++) {
idx += ((unsigned long long)sm[j]) << 8*(XMSS_INDEX_LEN - 1 - j);
}
printf("\nidx = %llu\n",idx);
r = memcmp(mi, sm+XMSS_BYTES,MLEN);
printf("%d\n", r);
for (j = 0; j < smlen; j++) {
printf("%02X", sm[j]);
}
printf("\n");
/* Test valid signature */
printf("verify\n");
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r);
r = memcmp(mi,mo,MLEN);
printf("%d\n", r);
printf("%llu\n", MLEN-mlen);
/* Test with modified message */
sm[52] ^= 1;
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
/* Test with modified signature */
sm[260] ^= 1;
sm[52] ^= 1;
sm[2] ^= 1;
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk);
printf("%d\n", r+1);
r = memcmp(mi,mo,MLEN);
printf("%d\n", (r!=0) - 1);
printf("%llu\n", mlen+1);
}
return 0;
}

101
xmss.c Normal file
Bestand weergeven

@ -0,0 +1,101 @@
#include <stdint.h>
#include "params_runtime.h"
#include "xmss_core.h"
/* This file provides wrapper functions that take keys that include OIDs to
identify the parameter set to be used. After setting the parameters accordingly
it falls back to the regular XMSS core functions. */
int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
{
unsigned int i;
if (xmss_parse_oid(oid)) {
return 1;
}
for (i = 0; i < XMSS_OID_LEN; i++) {
pk[i] = (oid >> (8 * i)) & 0xFF;
/* For an implementation that uses runtime parameters, it is crucial
that the OID is part of the secret key as well. */
sk[i] = (oid >> (8 * i)) & 0xFF;
}
return xmss_core_keypair(pk + XMSS_OID_LEN, sk + XMSS_OID_LEN);
}
int xmss_sign(unsigned char *sk,
unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen)
{
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[i] << (i * 8);
}
if (xmss_parse_oid(oid)) {
return 1;
}
return xmss_core_sign(sk + XMSS_OID_LEN, sm, smlen, m, mlen);
}
int xmss_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk)
{
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= pk[i] << (i * 8);
}
if (xmss_parse_oid(oid)) {
return 1;
}
return xmss_core_sign_open(m, mlen, sm, smlen, pk + XMSS_OID_LEN);
}
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
{
unsigned int i;
if (xmssmt_parse_oid(oid)) {
return 1;
}
for (i = 0; i < XMSS_OID_LEN; i++) {
pk[i] = (oid >> (8 * i)) & 0xFF;
sk[i] = (oid >> (8 * i)) & 0xFF;
}
return xmssmt_core_keypair(pk + XMSS_OID_LEN, sk + XMSS_OID_LEN);
}
int xmssmt_sign(unsigned char *sk,
unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen)
{
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[i] << (i * 8);
}
if (xmssmt_parse_oid(oid)) {
return 1;
}
return xmssmt_core_sign(sk + XMSS_OID_LEN, sm, smlen, m, mlen);
}
int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk)
{
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= pk[i] << (i * 8);
}
if (xmssmt_parse_oid(oid)) {
return 1;
}
return xmssmt_core_sign_open(m, mlen, sm, smlen, pk + XMSS_OID_LEN);
}

44
xmss.h Normal file
Bestand weergeven

@ -0,0 +1,44 @@
#ifndef XMSS_H
#define XMSS_H
#include <stdint.h>
/**
* Generates a XMSS key pair for a given parameter set.
* Format sk: [oid || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [oid || root || PUB_SEED]
*/
int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
/**
* Signs a message.
* Returns
* 1. an array containing the signature followed by the message AND
* 2. an updated secret key!
*/
int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen);
/**
* Verifies a given message signature pair under a given public key.
*
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg).
*/
int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk);
/*
* Generates a XMSSMT key pair for a given parameter set.
* Format sk: [oid || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
* Format pk: [oid || root || PUB_SEED]
*/
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
/**
* Signs a message.
* Returns
* 1. an array containing the signature followed by the message AND
* 2. an updated secret key!
*/
int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen);
/**
* Verifies a given message signature pair under a given public key.
*/
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk);
#endif