This also reduces some duplication between XMSS and XMSSMTmaster
@@ -225,26 +225,14 @@ int xmss_parse_oid(xmss_params *params, const uint32_t oid) | |||||
default: | default: | ||||
return -1; | return -1; | ||||
} | } | ||||
params->d = 1; | params->d = 1; | ||||
params->tree_height = params->full_height / params->d; | |||||
params->wots_w = 16; | params->wots_w = 16; | ||||
params->wots_log_w = 4; | |||||
params->wots_len1 = 8 * params->n / params->wots_log_w; | |||||
/* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ | |||||
params->wots_len2 = 3; | |||||
params->wots_len = params->wots_len1 + params->wots_len2; | |||||
params->wots_sig_bytes = params->wots_len * params->n; | |||||
params->index_bytes = 4; | |||||
params->sig_bytes = (params->index_bytes + params->n | |||||
+ params->d * params->wots_sig_bytes | |||||
+ params->full_height * params->n); | |||||
// TODO figure out sensible and legal values for this based on the above | // TODO figure out sensible and legal values for this based on the above | ||||
params->bds_k = 0; | params->bds_k = 0; | ||||
params->pk_bytes = 2 * params->n; | |||||
params->sk_bytes = xmss_core_sk_bytes(params); | |||||
return 0; | |||||
return xmss_xmssmt_initialize_params(params); | |||||
} | } | ||||
int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) | int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) | ||||
@@ -444,24 +432,65 @@ int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) | |||||
return -1; | return -1; | ||||
} | } | ||||
params->tree_height = params->full_height / params->d; | |||||
params->wots_w = 16; | params->wots_w = 16; | ||||
params->wots_log_w = 4; | |||||
params->wots_len1 = 8 * params->n / params->wots_log_w; | |||||
/* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ | |||||
params->wots_len2 = 3; | |||||
// TODO figure out sensible and legal values for this based on the above | |||||
params->bds_k = 0; | |||||
return xmss_xmssmt_initialize_params(params); | |||||
} | |||||
/** | |||||
* Given a params struct where the following properties have been initialized; | |||||
* - full_height; the height of the complete (hyper)tree | |||||
* - n; the number of bytes of hash function output | |||||
* - d; the number of layers (d > 1 implies XMSSMT) | |||||
* - func; one of {XMSS_SHA2, XMSS_SHAKE} | |||||
* - wots_w; the Winternitz parameter | |||||
* - optionally, bds_k; the BDS traversal trade-off parameter, | |||||
* this function initializes the remainder of the params structure. | |||||
*/ | |||||
int xmss_xmssmt_initialize_params(xmss_params *params) | |||||
{ | |||||
params->tree_height = params->full_height / params->d; | |||||
if (params->wots_w == 4) { | |||||
params->wots_log_w = 2; | |||||
params->wots_len1 = 8 * params->n / params->wots_log_w; | |||||
/* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ | |||||
params->wots_len2 = 5; | |||||
} | |||||
else if (params->wots_w == 16) { | |||||
params->wots_log_w = 4; | |||||
params->wots_len1 = 8 * params->n / params->wots_log_w; | |||||
/* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ | |||||
params->wots_len2 = 3; | |||||
} | |||||
else if (params->wots_w == 256) { | |||||
params->wots_log_w = 8; | |||||
params->wots_len1 = 8 * params->n / params->wots_log_w; | |||||
/* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ | |||||
params->wots_len2 = 2; | |||||
} | |||||
else { | |||||
return -1; | |||||
} | |||||
params->wots_len = params->wots_len1 + params->wots_len2; | params->wots_len = params->wots_len1 + params->wots_len2; | ||||
params->wots_sig_bytes = params->wots_len * params->n; | params->wots_sig_bytes = params->wots_len * params->n; | ||||
/* Round index_bytes up to nearest byte. */ | |||||
params->index_bytes = (params->full_height + 7) / 8; | |||||
if (params->d == 1) { // Assume this is XMSS, not XMSS^MT | |||||
/* In XMSS, always use fixed 4 bytes for index_bytes */ | |||||
params->index_bytes = 4; | |||||
} | |||||
else { | |||||
/* In XMSS^MT, round index_bytes up to nearest byte. */ | |||||
params->index_bytes = (params->full_height + 7) / 8; | |||||
} | |||||
params->sig_bytes = (params->index_bytes + params->n | params->sig_bytes = (params->index_bytes + params->n | ||||
+ params->d * params->wots_sig_bytes | + params->d * params->wots_sig_bytes | ||||
+ params->full_height * params->n); | + params->full_height * params->n); | ||||
// TODO figure out sensible and legal values for this based on the above | |||||
params->bds_k = 0; | |||||
params->pk_bytes = 2 * params->n; | params->pk_bytes = 2 * params->n; | ||||
params->sk_bytes = xmssmt_core_sk_bytes(params); | |||||
params->sk_bytes = xmss_xmssmt_core_sk_bytes(params); | |||||
return 0; | return 0; | ||||
} | } |
@@ -56,4 +56,15 @@ int xmss_parse_oid(xmss_params *params, const uint32_t oid); | |||||
*/ | */ | ||||
int xmssmt_parse_oid(xmss_params *params, const uint32_t oid); | int xmssmt_parse_oid(xmss_params *params, const uint32_t oid); | ||||
/* Given a params struct where the following properties have been initialized; | |||||
- full_height; the height of the complete (hyper)tree | |||||
- n; the number of bytes of hash function output | |||||
- d; the number of layers (d > 1 implies XMSSMT) | |||||
- func; one of {XMSS_SHA2, XMSS_SHAKE} | |||||
- wots_w; the Winternitz parameter | |||||
- optionally, bds_k; the BDS traversal trade-off parameter, | |||||
this function initializes the remainder of the params structure. */ | |||||
int xmss_xmssmt_initialize_params(xmss_params *params); | |||||
#endif | #endif |
@@ -90,7 +90,7 @@ static void treehash(const xmss_params *params, | |||||
* This is implementation specific, as varying choices in tree traversal will | * This is implementation specific, as varying choices in tree traversal will | ||||
* result in varying requirements for state storage. | * result in varying requirements for state storage. | ||||
*/ | */ | ||||
unsigned long long xmss_core_sk_bytes(const xmss_params *params) | |||||
unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) | |||||
{ | { | ||||
return params->index_bytes + 4 * params->n; | return params->index_bytes + 4 * params->n; | ||||
} | } | ||||
@@ -125,16 +125,6 @@ int xmss_core_sign(const xmss_params *params, | |||||
return xmssmt_core_sign(params, sk, sm, smlen, m, mlen); | return xmssmt_core_sign(params, sk, sm, smlen, m, mlen); | ||||
} | } | ||||
/** | |||||
* Given a set of parameters, this function returns the size of the secret key. | |||||
* This is implementation specific, as varying choices in tree traversal will | |||||
* result in varying requirements for state storage. | |||||
*/ | |||||
unsigned long long xmssmt_core_sk_bytes(const xmss_params *params) | |||||
{ | |||||
return params->index_bytes + 4 * params->n; | |||||
} | |||||
/* | /* | ||||
* Generates a XMSSMT key pair for a given parameter set. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
@@ -7,8 +7,10 @@ | |||||
* Given a set of parameters, this function returns the size of the secret key. | * Given a set of parameters, this function returns the size of the secret key. | ||||
* This is implementation specific, as varying choices in tree traversal will | * This is implementation specific, as varying choices in tree traversal will | ||||
* result in varying requirements for state storage. | * result in varying requirements for state storage. | ||||
* | |||||
* This function handles both XMSS and XMSSMT parameter sets. | |||||
*/ | */ | ||||
unsigned long long xmss_core_sk_bytes(const xmss_params *params); | |||||
unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params); | |||||
/* | /* | ||||
* Generates a XMSS key pair for a given parameter set. | * Generates a XMSS key pair for a given parameter set. | ||||
@@ -36,13 +38,6 @@ int xmss_core_sign_open(const xmss_params *params, | |||||
const unsigned char *sm, unsigned long long smlen, | const unsigned char *sm, unsigned long long smlen, | ||||
const unsigned char *pk); | const unsigned char *pk); | ||||
/** | |||||
* Given a set of parameters, this function returns the size of the secret key. | |||||
* This is implementation specific, as varying choices in tree traversal will | |||||
* result in varying requirements for state storage. | |||||
*/ | |||||
unsigned long long xmssmt_core_sk_bytes(const xmss_params *params); | |||||
/* | /* | ||||
* Generates a XMSSMT key pair for a given parameter set. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
@@ -511,10 +511,23 @@ static void bds_round(const xmss_params *params, | |||||
* Given a set of parameters, this function returns the size of the secret key. | * Given a set of parameters, this function returns the size of the secret key. | ||||
* This is implementation specific, as varying choices in tree traversal will | * This is implementation specific, as varying choices in tree traversal will | ||||
* result in varying requirements for state storage. | * result in varying requirements for state storage. | ||||
* | |||||
* This function handles both XMSS and XMSSMT parameter sets. | |||||
*/ | */ | ||||
unsigned long long xmss_core_sk_bytes(const xmss_params *params) | |||||
unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) | |||||
{ | { | ||||
return xmssmt_core_sk_bytes(params); | |||||
return params->index_bytes + 4 * params->n | |||||
+ (2 * params->d - 1) * ( | |||||
(params->tree_height + 1) * params->n | |||||
+ 4 | |||||
+ params->tree_height + 1 | |||||
+ params->tree_height * params->n | |||||
+ (params->tree_height >> 1) * params->n | |||||
+ (params->tree_height - params->bds_k) * (7 + params->n) | |||||
+ ((1 << params->bds_k) - params->bds_k - 1) * params->n | |||||
+ 4 | |||||
) | |||||
+ (params->d - 1) * params->wots_sig_bytes; | |||||
} | } | ||||
/* | /* | ||||
@@ -683,27 +696,6 @@ int xmss_core_sign(const xmss_params *params, | |||||
return 0; | return 0; | ||||
} | } | ||||
/** | |||||
* Given a set of parameters, this function returns the size of the secret key. | |||||
* This is implementation specific, as varying choices in tree traversal will | |||||
* result in varying requirements for state storage. | |||||
*/ | |||||
unsigned long long xmssmt_core_sk_bytes(const xmss_params *params) | |||||
{ | |||||
return params->index_bytes + 4 * params->n | |||||
+ (2 * params->d - 1) * ( | |||||
(params->tree_height + 1) * params->n | |||||
+ 4 | |||||
+ params->tree_height + 1 | |||||
+ params->tree_height * params->n | |||||
+ (params->tree_height >> 1) * params->n | |||||
+ (params->tree_height - params->bds_k) * (7 + params->n) | |||||
+ ((1 << params->bds_k) - params->bds_k - 1) * params->n | |||||
+ 4 | |||||
) | |||||
+ (params->d - 1) * params->wots_sig_bytes; | |||||
} | |||||
/* | /* | ||||
* Generates a XMSSMT key pair for a given parameter set. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||