From 1a0f443159168e4123d01a28a45c5b51f5893481 Mon Sep 17 00:00:00 2001 From: Zi Lin Date: Fri, 23 Apr 2021 03:50:05 +0000 Subject: [PATCH] Allow the last signature to be created correctly. - This fixes the tests at the moment. - Clear the private key after the last signature is generated. --- xmss_core.c | 41 +++++++++++++------------ xmss_core_fast.c | 78 +++++++++++++++++++++++++----------------------- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/xmss_core.c b/xmss_core.c index af9f8d1..3b9f9d9 100644 --- a/xmss_core.c +++ b/xmss_core.c @@ -207,29 +207,21 @@ int xmssmt_core_sign(const xmss_params *params, /* Read and use the current index from the secret key. */ 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 + * + * 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. - memset(sk, 0xFF, params->index_bytes); - 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 + */ + 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); /************************************************************************* @@ -269,5 +261,16 @@ int xmssmt_core_sign(const xmss_params *params, sm += params->tree_height*params->n; } + /* 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. + */ + 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. + memset(sk, 0xFF, params->index_bytes); + memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); + } + return 0; } diff --git a/xmss_core_fast.c b/xmss_core_fast.c index cbf87ec..8301d24 100644 --- a/xmss_core_fast.c +++ b/xmss_core_fast.c @@ -600,29 +600,20 @@ int xmss_core_sign(const xmss_params *params, // Extract SK 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 + * + * 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. - memset(sk, 0xFF, params->index_bytes); - 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 + */ + 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]; memcpy(sk_seed, sk + params->index_bytes, params->n); unsigned char sk_prf[params->n]; @@ -716,6 +707,17 @@ int xmss_core_sign(const xmss_params *params, /* Write the updated BDS state back into sk. */ xmss_serialize_state(params, sk, &state); + /* 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. + */ + 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. + memset(sk, 0xFF, params->index_bytes); + memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); + } + return 0; } @@ -824,26 +826,17 @@ int xmssmt_core_sign(const xmss_params *params, /* 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 + * + * 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. - memset(sk, 0xFF, params->index_bytes); - 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 + */ + 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_prf, sk+params->index_bytes+params->n, params->n); memcpy(pub_seed, sk+params->index_bytes+3*params->n, params->n); @@ -984,5 +977,16 @@ int xmssmt_core_sign(const xmss_params *params, xmssmt_serialize_state(params, sk, states); + /* 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. + */ + 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. + memset(sk, 0xFF, params->index_bytes); + memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes)); + } + return 0; }