Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 22 additions & 19 deletions xmss_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*************************************************************************
Expand Down Expand Up @@ -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;
}
78 changes: 41 additions & 37 deletions xmss_core_fast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}