Ensure that sign deletes key after 2^h signatures and returns -2
This commit is contained in:
parent
4ae726a82b
commit
f56dc0e8a7
8
Makefile
8
Makefile
@ -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 \
|
||||||
@ -60,6 +62,12 @@ 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)
|
||||||
|
|
||||||
|
101
test/xmss_max_signatures.c
Normal file
101
test/xmss_max_signatures.c
Normal file
@ -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;
|
||||||
|
}
|
26
xmss_core.c
26
xmss_core.c
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user