mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Update xmss.c
This commit is contained in:
342
src/xmss.c
342
src/xmss.c
@@ -37,7 +37,7 @@ static const uint8_t bn256_one[] = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t bn256_two[] = {
|
static const uint8_t hash256_two[] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@@ -1188,7 +1188,7 @@ int xmss_sign_init(XMSS_SIGN_CTX *ctx, XMSS_KEY *key)
|
|||||||
|
|
||||||
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
||||||
hash256_init(&ctx->hash256_ctx);
|
hash256_init(&ctx->hash256_ctx);
|
||||||
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_two, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
|
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
|
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, index_buf, 32);
|
hash256_update(&ctx->hash256_ctx, index_buf, 32);
|
||||||
@@ -1254,7 +1254,7 @@ int xmss_verify_init(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, const uint8_t *sig
|
|||||||
PUTU32(sig_index + 28, ctx->xmss_sig.index);
|
PUTU32(sig_index + 28, ctx->xmss_sig.index);
|
||||||
|
|
||||||
hash256_init(&ctx->hash256_ctx);
|
hash256_init(&ctx->hash256_ctx);
|
||||||
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_two, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
|
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
|
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
|
||||||
hash256_update(&ctx->hash256_ctx, sig_index, 32);
|
hash256_update(&ctx->hash256_ctx, sig_index, 32);
|
||||||
@@ -1539,6 +1539,10 @@ int xmssmt_private_key_from_bytes(XMSSMT_KEY *key, const uint8_t **in, size_t *i
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XMSSMT的密钥生成和密钥更新都是完全一样的,
|
||||||
|
// 密钥生成的区别是需要生成最高层
|
||||||
|
|
||||||
|
|
||||||
int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
|
int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
|
||||||
{
|
{
|
||||||
size_t height;
|
size_t height;
|
||||||
@@ -1548,6 +1552,14 @@ int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
|
|||||||
hash256_t *tree;
|
hash256_t *tree;
|
||||||
uint8_t *xmss_root;
|
uint8_t *xmss_root;
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t index = 0;
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t tree_address;
|
||||||
|
uint32_t tree_index;
|
||||||
|
|
||||||
|
|
||||||
if (!key) {
|
if (!key) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1586,59 +1598,67 @@ int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
|
|||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tree = key->trees;
|
tree = key->trees;
|
||||||
|
|
||||||
for (layer = 0; layer < layers - 1; layer++) {
|
|
||||||
// generate the leftmost tree of the level
|
|
||||||
|
for (layer = 0; layer < layers; layer++) {
|
||||||
|
|
||||||
|
// generate tree of the layer
|
||||||
adrs_set_layer_address(adrs, layer);
|
adrs_set_layer_address(adrs, layer);
|
||||||
adrs_set_tree_address(adrs, 0);
|
adrs_set_tree_address(adrs, xmssmt_tree_address(index, height, layers, layer));
|
||||||
xmss_build_tree(key->secret, key->public_key.seed, adrs, height/layers, tree);
|
xmss_build_tree(key->secret, key->public_key.seed, adrs, height/layers, tree);
|
||||||
xmss_root = tree[tree_root_offset(height/layers)];
|
|
||||||
|
// sign xmss_root with higher layer
|
||||||
|
if (layer < layers - 1) {
|
||||||
|
|
||||||
adrs_set_layer_address(adrs, layer + 1);
|
adrs_set_layer_address(adrs, layer + 1);
|
||||||
adrs_set_tree_address(adrs, 0);
|
adrs_set_tree_address(adrs, xmssmt_tree_address(index, height, layers, layer + 1));
|
||||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||||
adrs_set_ots_address(adrs, 0); // 具体值由index决定!
|
adrs_set_ots_address(adrs, xmssmt_tree_index(index, height, layers, layer + 1));
|
||||||
|
|
||||||
wots_derive_sk(key->secret, key->public_key.seed, adrs, key->wots_sigs[layer]);
|
wots_derive_sk(key->secret, key->public_key.seed, adrs, key->wots_sigs[layer]);
|
||||||
|
|
||||||
|
//tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
|
||||||
|
xmss_root = tree[tree_root_offset(height/layers)];
|
||||||
wots_sign(key->wots_sigs[layer], key->public_key.seed, adrs, xmss_root, key->wots_sigs[layer]);
|
wots_sign(key->wots_sigs[layer], key->public_key.seed, adrs, xmss_root, key->wots_sigs[layer]);
|
||||||
tree += tree_root_offset(height/layers) + 1;
|
|
||||||
|
tree += xmss_tree_num_nodes(height/layers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// highest layer (without signatures)
|
|
||||||
adrs_set_layer_address(adrs, layer);
|
|
||||||
adrs_set_tree_address(adrs, 0);
|
|
||||||
xmss_build_tree(key->secret, key->public_key.seed, adrs, height/layers, tree);
|
|
||||||
xmss_root = tree[tree_root_offset(height/layers)];
|
|
||||||
|
|
||||||
// copy the top-level root
|
// copy the top-level root
|
||||||
memcpy(key->public_key.root, xmss_root, sizeof(hash256_t));
|
memcpy(key->public_key.root, xmss_root, sizeof(hash256_t));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tree = key->trees;
|
tree = key->trees;
|
||||||
|
|
||||||
|
|
||||||
hash256_t root;
|
hash256_t root;
|
||||||
|
|
||||||
size_t i;
|
|
||||||
wots_key_t wots_pk;
|
wots_key_t wots_pk;
|
||||||
|
|
||||||
for (i = 0; i < layers - 1; i++) {
|
for (layer = 0; layer < layers - 1; layer++) {
|
||||||
|
|
||||||
adrs_set_layer_address(adrs, i + 1);
|
|
||||||
adrs_set_tree_address(adrs, 0); //
|
|
||||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
|
||||||
adrs_set_ots_address(adrs, 0); // FIXME: value from index
|
|
||||||
|
|
||||||
uint8_t *dgst = tree[tree_root_offset(height/layers)];
|
uint8_t *dgst = tree[tree_root_offset(height/layers)];
|
||||||
|
|
||||||
wots_sig_to_pk(key->wots_sigs[i], key->public_key.seed, adrs, dgst, wots_pk);
|
tree_address = xmssmt_tree_address(index, height, layers, layer + 1);
|
||||||
|
tree_index = xmssmt_tree_index(index, height, layers, layer + 1);
|
||||||
|
|
||||||
|
adrs_set_layer_address(adrs, layer + 1);
|
||||||
|
adrs_set_tree_address(adrs, tree_address);
|
||||||
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||||
|
adrs_set_ots_address(adrs, tree_index);
|
||||||
|
|
||||||
|
wots_sig_to_pk(key->wots_sigs[layer], key->public_key.seed, adrs, dgst, wots_pk);
|
||||||
|
|
||||||
|
|
||||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
|
||||||
adrs_set_tree_index(adrs, 0); //
|
adrs_set_tree_index(adrs, tree_index);
|
||||||
wots_pk_to_root(wots_pk, key->public_key.seed, adrs, root);
|
wots_pk_to_root(wots_pk, key->public_key.seed, adrs, root);
|
||||||
|
|
||||||
tree += xmss_tree_num_nodes(height/layers);
|
tree += xmss_tree_num_nodes(height/layers);
|
||||||
@@ -2007,12 +2027,62 @@ int xmssmt_signature_print(FILE *fp, int fmt, int ind, const char *label, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
|
|
||||||
|
int xmssmt_key_update(XMSSMT_KEY *key)
|
||||||
{
|
{
|
||||||
hash256_t hash256_index = {0};
|
|
||||||
xmss_adrs_t adrs;
|
|
||||||
size_t height;
|
size_t height;
|
||||||
size_t layers;
|
size_t layers;
|
||||||
|
size_t layer;
|
||||||
|
|
||||||
|
|
||||||
|
if (xmssmt_type_to_height_and_layers(key->public_key.xmssmt_type, &height, &layers) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 这里我们要检查当前的layer
|
||||||
|
for (layer = layers - 1; layer > 0; layer--) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (layer >= layers ) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (layer == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (; layer < layers; layer++) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
|
||||||
|
{
|
||||||
|
size_t height;
|
||||||
|
size_t layers;
|
||||||
|
size_t layer;
|
||||||
|
uint64_t tree_address;
|
||||||
|
uint32_t tree_index;
|
||||||
|
hash256_t hash256_index;
|
||||||
|
xmss_adrs_t adrs;
|
||||||
|
|
||||||
if (!ctx || !key) {
|
if (!ctx || !key) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -2022,56 +2092,67 @@ int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
|
|||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(ctx, 0, sizeof(*ctx));
|
|
||||||
|
|
||||||
// cache public key
|
// init sign ctx
|
||||||
|
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
|
||||||
|
|
||||||
|
// set ctx->xmssmt_public_key
|
||||||
ctx->xmssmt_public_key = key->public_key;
|
ctx->xmssmt_public_key = key->public_key;
|
||||||
|
|
||||||
// key->index => xmssmt_sig.index
|
// copy index
|
||||||
ctx->xmssmt_sig.index = key->index;
|
ctx->xmssmt_sig.index = key->index;
|
||||||
|
|
||||||
|
// copy wots_sigs[1] to wots_sig[layers - 1] from key
|
||||||
|
for (layer = 1; layer < layers; layer++) {
|
||||||
|
memcpy(ctx->xmssmt_sig.wots_sigs[layer], key->wots_sigs[layer - 1], sizeof(wots_sig_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build auth_path
|
||||||
|
for (layer = 0; layer < layers; layer++) {
|
||||||
|
hash256_t *tree;
|
||||||
|
hash256_t *auth_path;
|
||||||
|
tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
|
||||||
|
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
auth_path = ctx->xmssmt_sig.auth_path + (height/layers) * layer;
|
||||||
|
xmss_build_auth_path(tree, height/layers, tree_index, auth_path);
|
||||||
|
}
|
||||||
|
|
||||||
// derive ctx->xmssmt_sig.random
|
// derive ctx->xmssmt_sig.random
|
||||||
PUTU64(hash256_index + 24, key->index);
|
memset(hash256_index, 0, 24);
|
||||||
// r = PRF(SK_PRF, toByte(idx_sig, 32));
|
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
|
||||||
hash256_init(&ctx->hash256_ctx);
|
hash256_init(&ctx->hash256_ctx);
|
||||||
hash256_update(&ctx->hash256_ctx, hash256_three, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_three, sizeof(hash256_t));
|
||||||
hash256_update(&ctx->hash256_ctx, key->sk_prf, 32);
|
hash256_update(&ctx->hash256_ctx, key->sk_prf, sizeof(hash256_t));
|
||||||
hash256_update(&ctx->hash256_ctx, hash256_index, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
|
||||||
hash256_finish(&ctx->hash256_ctx, ctx->xmssmt_sig.random);
|
hash256_finish(&ctx->hash256_ctx, ctx->xmssmt_sig.random);
|
||||||
|
|
||||||
// wots_sk => ctx->xmss_sig.wots_sig
|
// derive wots_sk and save to wots_sigs[0]
|
||||||
adrs_set_layer_address(adrs, 0);
|
layer = 0;
|
||||||
adrs_set_tree_address(adrs, 0); //
|
tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
adrs_set_layer_address(adrs, layer);
|
||||||
|
adrs_set_tree_address(adrs, tree_address);
|
||||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||||
adrs_set_ots_address(adrs, key->index); //
|
adrs_set_ots_address(adrs, tree_index);
|
||||||
wots_derive_sk(key->secret, key->public_key.seed, adrs, ctx->xmssmt_sig.wots_sigs[0]);
|
wots_derive_sk(key->secret, key->public_key.seed, adrs, ctx->xmssmt_sig.wots_sigs[0]);
|
||||||
|
|
||||||
//
|
|
||||||
// xmss_sig.auth_path
|
|
||||||
xmss_build_auth_path(key->trees, height, key->index, ctx->xmssmt_sig.auth_path);
|
|
||||||
|
|
||||||
|
|
||||||
// update key->index
|
|
||||||
key->index++;
|
|
||||||
|
|
||||||
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
||||||
hash256_init(&ctx->hash256_ctx);
|
hash256_init(&ctx->hash256_ctx);
|
||||||
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
|
||||||
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, 32);
|
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
|
||||||
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
|
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
|
||||||
hash256_update(&ctx->hash256_ctx, hash256_index, 32);
|
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
|
||||||
|
|
||||||
|
size_t remaining_signs;
|
||||||
|
|
||||||
size_t i;
|
// 增加key_update
|
||||||
|
if (remaining_signs == 0) {
|
||||||
for (i = 0; i < layers; i++) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return -1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||||
@@ -2088,77 +2169,192 @@ int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen
|
|||||||
|
|
||||||
int xmssmt_sign_finish_ex(XMSSMT_SIGN_CTX *ctx, XMSSMT_SIGNATURE *sig)
|
int xmssmt_sign_finish_ex(XMSSMT_SIGN_CTX *ctx, XMSSMT_SIGNATURE *sig)
|
||||||
{
|
{
|
||||||
xmss_adrs_t adrs;
|
// generate message wots_sig as wots_sigs[0]
|
||||||
size_t height;
|
size_t height;
|
||||||
size_t layers;
|
size_t layers;
|
||||||
|
size_t layer = 0;
|
||||||
uint64_t tree_address;
|
uint64_t tree_address;
|
||||||
|
uint32_t tree_index;
|
||||||
uint8_t dgst[32];
|
xmss_adrs_t adrs;
|
||||||
|
hash256_t dgst;
|
||||||
|
|
||||||
if (!ctx || !sig) {
|
if (!ctx || !sig) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash256_finish(&ctx->hash256_ctx, dgst);
|
||||||
|
|
||||||
if (xmssmt_type_to_height_and_layers(ctx->xmssmt_public_key.xmssmt_type, &height, &layers) != 1) {
|
if (xmssmt_type_to_height_and_layers(ctx->xmssmt_public_key.xmssmt_type, &height, &layers) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
|
||||||
tree_address = sig->index / layers;
|
adrs_set_layer_address(adrs, layer);
|
||||||
|
|
||||||
|
|
||||||
hash256_finish(&ctx->hash256_ctx, dgst);
|
|
||||||
|
|
||||||
adrs_set_layer_address(adrs, 0);
|
|
||||||
adrs_set_tree_address(adrs, tree_address);
|
adrs_set_tree_address(adrs, tree_address);
|
||||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||||
adrs_set_ots_address(adrs, ctx->xmssmt_sig.index);
|
adrs_set_ots_address(adrs, tree_index);
|
||||||
|
|
||||||
wots_sign(ctx->xmssmt_sig.wots_sigs[0], ctx->xmssmt_public_key.seed, adrs, dgst,
|
wots_sign(ctx->xmssmt_sig.wots_sigs[0], ctx->xmssmt_public_key.seed, adrs, dgst,
|
||||||
ctx->xmssmt_sig.wots_sigs[0]);
|
ctx->xmssmt_sig.wots_sigs[0]);
|
||||||
|
|
||||||
|
|
||||||
|
*sig = ctx->xmssmt_sig;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmssmt_sign_finish(XMSSMT_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
int xmssmt_sign_finish(XMSSMT_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||||
{
|
{
|
||||||
|
XMSSMT_SIGNATURE signature;
|
||||||
|
|
||||||
if (!ctx || !sig || !siglen) {
|
if (!ctx || !sig || !siglen) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xmssmt_sign_finish_ex(ctx, &signature) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*siglen = 0;
|
*siglen = 0;
|
||||||
if (xmssmt_signature_to_bytes(&ctx->xmssmt_sig, ctx->xmssmt_public_key.xmssmt_type, &sig, siglen) != 1) {
|
if (xmssmt_signature_to_bytes(&ctx->xmssmt_sig, ctx->xmssmt_public_key.xmssmt_type, &sig, siglen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmssmt_verify_init_ex(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const XMSSMT_SIGNATURE *sig)
|
int xmssmt_verify_init_ex(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const XMSSMT_SIGNATURE *sig)
|
||||||
{
|
{
|
||||||
|
hash256_t hash256_index;
|
||||||
|
xmss_adrs_t adrs;
|
||||||
|
|
||||||
if (!ctx || !key || !sig) {
|
if (!ctx || !key || !sig) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
// init sign ctx
|
||||||
|
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
|
||||||
|
|
||||||
|
// set ctx->xmssmt_public_key
|
||||||
|
ctx->xmssmt_public_key = key->public_key;
|
||||||
|
|
||||||
|
// copy ctx->xmssmt_sig
|
||||||
|
ctx->xmssmt_sig = *sig;
|
||||||
|
|
||||||
|
memset(hash256_index, 0, 24);
|
||||||
|
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
|
||||||
|
|
||||||
|
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
||||||
|
hash256_init(&ctx->hash256_ctx);
|
||||||
|
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmssmt_verify_init(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const uint8_t *sig, size_t siglen)
|
int xmssmt_verify_init(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const uint8_t *sig, size_t siglen)
|
||||||
{
|
{
|
||||||
|
hash256_t hash256_index;
|
||||||
|
xmss_adrs_t adrs;
|
||||||
|
if (!ctx || !key || !sig) {
|
||||||
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init sign ctx
|
||||||
|
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
|
||||||
|
|
||||||
|
// set ctx->xmssmt_public_key
|
||||||
|
ctx->xmssmt_public_key = key->public_key;
|
||||||
|
|
||||||
|
|
||||||
|
if (xmssmt_signature_from_bytes(&ctx->xmssmt_sig, key->public_key.xmssmt_type, &sig, &siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (siglen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset(hash256_index, 0, 24);
|
||||||
|
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
|
||||||
|
|
||||||
|
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
|
||||||
|
hash256_init(&ctx->hash256_ctx);
|
||||||
|
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
|
||||||
|
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int xmssmt_verify_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
int xmssmt_verify_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||||
{
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (data && datalen) {
|
||||||
|
hash256_update(&ctx->hash256_ctx, data, datalen);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int xmssmt_verify_finish(XMSSMT_SIGN_CTX *ctx)
|
int xmssmt_verify_finish(XMSSMT_SIGN_CTX *ctx)
|
||||||
{
|
{
|
||||||
|
size_t height;
|
||||||
|
size_t layers;
|
||||||
|
size_t layer;
|
||||||
|
xmss_adrs_t adrs;
|
||||||
|
hash256_t dgst;
|
||||||
|
|
||||||
|
hash256_finish(&ctx->hash256_ctx, dgst);
|
||||||
|
|
||||||
|
if (xmssmt_type_to_height_and_layers(ctx->xmssmt_public_key.xmssmt_type, &height, &layers) != 1) {
|
||||||
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (layer = 0; layer < layers; layer++) {
|
||||||
|
uint64_t tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
uint32_t tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
|
||||||
|
wots_key_t wots_pk;
|
||||||
|
|
||||||
|
// wots_sig, dgst => wots_pk
|
||||||
|
adrs_set_layer_address(adrs, layer);
|
||||||
|
adrs_set_tree_address(adrs, tree_address);
|
||||||
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||||
|
adrs_set_ots_address(adrs, tree_index);
|
||||||
|
wots_sig_to_pk(ctx->xmssmt_sig.wots_sigs[layer], ctx->xmssmt_public_key.seed, adrs, dgst, wots_pk);
|
||||||
|
|
||||||
|
// wots_pk => wots_root
|
||||||
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
|
||||||
|
adrs_set_ltree_address(adrs, tree_index);
|
||||||
|
wots_pk_to_root(wots_pk, ctx->xmssmt_public_key.seed, adrs, dgst);
|
||||||
|
|
||||||
|
// wots_root, auth_path => xmss_root (as dgst)
|
||||||
|
adrs_set_type(adrs, XMSS_ADRS_TYPE_HASHTREE);
|
||||||
|
adrs_set_padding(adrs, 0);
|
||||||
|
xmss_build_root(dgst, tree_index,
|
||||||
|
ctx->xmssmt_public_key.seed, adrs,
|
||||||
|
ctx->xmssmt_sig.auth_path + (height/layers) * layer, height/layers,
|
||||||
|
dgst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify xmssmt_root (save in dgst)
|
||||||
|
if (memcmp(dgst, ctx->xmssmt_public_key.root, sizeof(hash256_t)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user