@@ -16,6 +16,8 @@ TESTS = test/wots \ | |||||
test/xmss_fast \ | test/xmss_fast \ | ||||
test/xmssmt \ | test/xmssmt \ | ||||
test/xmssmt_fast \ | test/xmssmt_fast \ | ||||
test/maxsigsxmss \ | |||||
test/maxsigsxmssmt \ | |||||
UI = ui/xmss_keypair \ | UI = ui/xmss_keypair \ | ||||
ui/xmss_sign \ | ui/xmss_sign \ | ||||
@@ -59,7 +61,13 @@ test/speed: test/speed.c $(SOURCES_FAST) $(OBJS) $(HEADERS_FAST) | |||||
test/vectors: test/vectors.c $(SOURCES) $(OBJS) $(HEADERS) | test/vectors: test/vectors.c $(SOURCES) $(OBJS) $(HEADERS) | ||||
$(CC) -DXMSSMT $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) | $(CC) -DXMSSMT $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) | ||||
test/maxsigsxmss: test/xmss_max_signatures.c $(SOURCES_FAST) $(OBJS) $(HEADERS_FAST) | |||||
$(CC) $(CFLAGS) -o $@ $(SOURCES_FAST) $< $(LDLIBS) | |||||
test/maxsigsxmssmt: test/xmss_max_signatures.c $(SOURCES_FAST) $(OBJS) $(HEADERS_FAST) | |||||
$(CC) -DXMSSMT $(CFLAGS) -o $@ $(SOURCES_FAST) $< $(LDLIBS) | |||||
test/%: test/%.c $(SOURCES) $(OBJS) $(HEADERS) | test/%: test/%.c $(SOURCES) $(OBJS) $(HEADERS) | ||||
$(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) | $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) | ||||
@@ -0,0 +1,101 @@ | |||||
#include <stdio.h> | |||||
#include <stdint.h> | |||||
#include <string.h> | |||||
#include <stdlib.h> | |||||
#include "../xmss.h" | |||||
#include "../params.h" | |||||
#include "../randombytes.h" | |||||
#include "../utils.h" | |||||
#define XMSS_MLEN 32 | |||||
// #ifndef XMSS_SIGNATURES | |||||
// #define XMSS_SIGNATURES 16 | |||||
// #endif | |||||
#ifdef XMSSMT | |||||
#define XMSS_PARSE_OID xmssmt_parse_oid | |||||
#define XMSS_STR_TO_OID xmssmt_str_to_oid | |||||
#define XMSS_KEYPAIR xmssmt_keypair | |||||
#define XMSS_SIGN xmssmt_sign | |||||
#define XMSS_SIGN_OPEN xmssmt_sign_open | |||||
#define XMSS_VARIANT "XMSSMT-SHA2_20/2_256" | |||||
#define XMSS_SIGNATURES 1 << 20 | |||||
#else | |||||
#define XMSS_PARSE_OID xmss_parse_oid | |||||
#define XMSS_STR_TO_OID xmss_str_to_oid | |||||
#define XMSS_KEYPAIR xmss_keypair | |||||
#define XMSS_SIGN xmss_sign | |||||
#define XMSS_SIGN_OPEN xmss_sign_open | |||||
#define XMSS_VARIANT "XMSS-SHA2_10_256" | |||||
#define XMSS_SIGNATURES 1 << 10 | |||||
#endif | |||||
int main() | |||||
{ | |||||
xmss_params params; | |||||
uint32_t oid; | |||||
int ret = 0; | |||||
int return_code = 0; | |||||
int i; | |||||
// TODO test more different variants | |||||
XMSS_STR_TO_OID(&oid, XMSS_VARIANT); | |||||
XMSS_PARSE_OID(¶ms, oid); | |||||
unsigned char pk[XMSS_OID_LEN + params.pk_bytes]; | |||||
unsigned char sk[XMSS_OID_LEN + params.sk_bytes]; | |||||
unsigned char *m = malloc(XMSS_MLEN); | |||||
unsigned char *sm = malloc(params.sig_bytes + XMSS_MLEN); | |||||
unsigned char *mout = malloc(params.sig_bytes + XMSS_MLEN); | |||||
unsigned long long smlen; | |||||
unsigned long long idx; | |||||
unsigned long long j; | |||||
randombytes(m, XMSS_MLEN); | |||||
XMSS_KEYPAIR(pk, sk, oid); | |||||
printf("Testing %d %s signatures.. \n", XMSS_SIGNATURES, XMSS_VARIANT); | |||||
for (i = 0; i < XMSS_SIGNATURES; i++) { | |||||
if( (i & 1023) == 0) | |||||
printf(" - iteration #%d:\n", i); | |||||
return_code = XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN); | |||||
if (return_code != 0) { | |||||
printf(" Error! Return code was %d\n",return_code); | |||||
ret = -1; | |||||
} | |||||
} | |||||
if(ret == 0) | |||||
printf("As expected, return code was 0\n"); | |||||
i++; | |||||
printf(" - iteration #%d:\n", i); | |||||
return_code = XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN); | |||||
if (return_code == 0) { | |||||
printf(" Error! Return code was %d\n",return_code); | |||||
ret = -1; | |||||
} | |||||
else { | |||||
printf("Return code as expected [%d].\n", return_code); | |||||
} | |||||
idx = (unsigned long)bytes_to_ull(sk, params.index_bytes); | |||||
printf("Index: %llu\n", idx); | |||||
printf("Secret key: %llu\n", idx); | |||||
for (j = 0; j < XMSS_OID_LEN + params.sk_bytes;j++) | |||||
printf("%d ", sk[j]); | |||||
printf("\n"); | |||||
free(m); | |||||
free(sm); | |||||
free(mout); | |||||
return ret; | |||||
} |
@@ -207,6 +207,32 @@ int xmssmt_core_sign(const xmss_params *params, | |||||
/* Read and use the current index from the secret key. */ | /* Read and use the current index from the secret key. */ | ||||
idx = (unsigned long)bytes_to_ull(sk, params->index_bytes); | idx = (unsigned long)bytes_to_ull(sk, params->index_bytes); | ||||
/* Check if we can still sign with this sk. | |||||
* If not, return -2 | |||||
* | |||||
* If this is the last possible signature (because the max index value | |||||
* is reached), production implementations should delete the secret key | |||||
* to prevent accidental further use. | |||||
* | |||||
* For the case of total tree height of 64 we do not use the last signature | |||||
* to be on the safe side (there is no index value left to indicate that the | |||||
* key is finished, hence external handling would be necessary) | |||||
*/ | |||||
if (idx >= ((1ULL << params->full_height) - 1)) { | |||||
// Delete secret key here. We only do this in memory, production code | |||||
// has to make sure that this happens on disk. | |||||
sk[0] = 255; | |||||
sk[1] = 255; | |||||
sk[2] = 255; | |||||
sk[3] = 255; | |||||
memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); | |||||
if (idx > ((1ULL << params->full_height) - 1)) | |||||
return -2; // We already used all one-time keys | |||||
if ((params->full_height == 64) && (idx = ((1ULL << params->full_height) - 1))) | |||||
return -2; // We already used all one-time keys | |||||
} | |||||
memcpy(sm, sk, params->index_bytes); | memcpy(sm, sk, params->index_bytes); | ||||
/************************************************************************* | /************************************************************************* | ||||
@@ -600,6 +600,32 @@ int xmss_core_sign(const xmss_params *params, | |||||
// Extract SK | // Extract SK | ||||
unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | ||||
/* Check if we can still sign with this sk. | |||||
* If not, return -2 | |||||
* | |||||
* If this is the last possible signature (because the max index value | |||||
* is reached), production implementations should delete the secret key | |||||
* to prevent accidental further use. | |||||
* | |||||
* For the case of total tree height of 64 we do not use the last signature | |||||
* to be on the safe side (there is no index value left to indicate that the | |||||
* key is finished, hence external handling would be necessary) | |||||
*/ | |||||
if (idx >= ((1ULL << params->full_height) - 1)) { | |||||
// Delete secret key here. We only do this in memory, production code | |||||
// has to make sure that this happens on disk. | |||||
sk[0] = 255; | |||||
sk[1] = 255; | |||||
sk[2] = 255; | |||||
sk[3] = 255; | |||||
memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); | |||||
if (idx > ((1ULL << params->full_height) - 1)) | |||||
return -2; // We already used all one-time keys | |||||
if ((params->full_height == 64) && (idx = ((1ULL << params->full_height) - 1))) | |||||
return -2; // We already used all one-time keys | |||||
} | |||||
unsigned char sk_seed[params->n]; | unsigned char sk_seed[params->n]; | ||||
memcpy(sk_seed, sk + params->index_bytes, params->n); | memcpy(sk_seed, sk + params->index_bytes, params->n); | ||||
unsigned char sk_prf[params->n]; | unsigned char sk_prf[params->n]; | ||||
@@ -799,6 +825,31 @@ int xmssmt_core_sign(const xmss_params *params, | |||||
idx |= ((unsigned long long)sk[i]) << 8*(params->index_bytes - 1 - i); | idx |= ((unsigned long long)sk[i]) << 8*(params->index_bytes - 1 - i); | ||||
} | } | ||||
/* Check if we can still sign with this sk. | |||||
* If not, return -2 | |||||
* | |||||
* If this is the last possible signature (because the max index value | |||||
* is reached), production implementations should delete the secret key | |||||
* to prevent accidental further use. | |||||
* | |||||
* For the case of total tree height of 64 we do not use the last signature | |||||
* to be on the safe side (there is no index value left to indicate that the | |||||
* key is finished, hence external handling would be necessary) | |||||
*/ | |||||
if (idx >= ((1ULL << params->full_height) - 1)) { | |||||
// Delete secret key here. We only do this in memory, production code | |||||
// has to make sure that this happens on disk. | |||||
sk[0] = 255; | |||||
sk[1] = 255; | |||||
sk[2] = 255; | |||||
sk[3] = 255; | |||||
memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); | |||||
if (idx > ((1ULL << params->full_height) - 1)) | |||||
return -2; // We already used all one-time keys | |||||
if ((params->full_height == 64) && (idx = ((1ULL << params->full_height) - 1))) | |||||
return -2; // We already used all one-time keys | |||||
} | |||||
memcpy(sk_seed, sk+params->index_bytes, params->n); | memcpy(sk_seed, sk+params->index_bytes, params->n); | ||||
memcpy(sk_prf, sk+params->index_bytes+params->n, params->n); | memcpy(sk_prf, sk+params->index_bytes+params->n, params->n); | ||||
memcpy(pub_seed, sk+params->index_bytes+3*params->n, params->n); | memcpy(pub_seed, sk+params->index_bytes+3*params->n, params->n); | ||||