mirror of
https://github.com/openssl/openssl.git
synced 2025-04-06 20:20:50 +08:00
Added return code checks to SLH_DSA Hash functions and propogated the
values thru the calling functions. Reviewed-by: Paul Dale <ppzgs1@gmail.com> Reviewed-by: Viktor Dukhovni <viktor@openssl.org> Reviewed-by: Tim Hudson <tjh@openssl.org> (Merged from https://github.com/openssl/openssl/pull/25882)
This commit is contained in:
parent
5901ca87ba
commit
30a55b0cf1
@ -82,11 +82,11 @@ static int slh_sign_internal(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *priv,
|
||||
|
||||
adrsf->zero(adrs);
|
||||
/* calculate Randomness value r, and output to the signature */
|
||||
hashf->PRF_MSG(hctx, SLH_DSA_SK_PRF(priv), opt_rand, msg, msg_len, r);
|
||||
|
||||
/* generate a digest of size |params->m| bytes where m is (30..49) */
|
||||
hashf->H_MSG(hctx, r, pk_seed, SLH_DSA_PK_ROOT(priv), msg, msg_len,
|
||||
m_digest);
|
||||
if (!hashf->PRF_MSG(hctx, SLH_DSA_SK_PRF(priv), opt_rand, msg, msg_len, r)
|
||||
/* generate a digest of size |params->m| bytes where m is (30..49) */
|
||||
|| !hashf->H_MSG(hctx, r, pk_seed, SLH_DSA_PK_ROOT(priv), msg, msg_len,
|
||||
m_digest))
|
||||
return 0;
|
||||
/* Grab selected bytes from the digest to select tree and leaf id's */
|
||||
get_tree_ids(m_digest, params, &tree_id, &leaf_id);
|
||||
|
||||
@ -96,13 +96,11 @@ static int slh_sign_internal(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *priv,
|
||||
|
||||
/* generate the FORS signature and append it to the signature */
|
||||
md = m_digest;
|
||||
ossl_slh_fors_sign(ctx, md, sk_seed, pk_seed, adrs, sig_fors, sig_fors_len);
|
||||
/* Calculate the FORS public key */
|
||||
ossl_slh_fors_pk_from_sig(ctx, sig_fors, md, pk_seed, adrs, pk_fors);
|
||||
|
||||
ossl_slh_ht_sign(ctx, pk_fors, sk_seed, pk_seed, tree_id, leaf_id,
|
||||
sig_ht, sig_ht_len);
|
||||
return 1;
|
||||
return ossl_slh_fors_sign(ctx, md, sk_seed, pk_seed, adrs, sig_fors, sig_fors_len)
|
||||
/* Calculate the FORS public key */
|
||||
&& ossl_slh_fors_pk_from_sig(ctx, sig_fors, md, pk_seed, adrs, pk_fors)
|
||||
&& ossl_slh_ht_sign(ctx, pk_fors, sk_seed, pk_seed, tree_id, leaf_id,
|
||||
sig_ht, sig_ht_len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,15 +153,17 @@ static int slh_verify_internal(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *pub,
|
||||
pk_seed = SLH_DSA_PK_SEED(pub);
|
||||
pk_root = SLH_DSA_PK_ROOT(pub);
|
||||
|
||||
hashf->H_MSG(hctx, r, pk_seed, pk_root, msg, msg_len, mdigest);
|
||||
if (!hashf->H_MSG(hctx, r, pk_seed, pk_root, msg, msg_len, mdigest))
|
||||
return 0;
|
||||
md = mdigest;
|
||||
get_tree_ids(mdigest, params, &tree_id, &leaf_id);
|
||||
|
||||
adrsf->set_tree_address(adrs, tree_id);
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_FORS_TREE);
|
||||
adrsf->set_keypair_address(adrs, leaf_id);
|
||||
ossl_slh_fors_pk_from_sig(ctx, sig_fors, md, pk_seed, adrs, pk_fors);
|
||||
return ossl_slh_ht_verify(ctx, pk_fors, sig_ht, pk_seed, tree_id, leaf_id, pk_root);
|
||||
return ossl_slh_fors_pk_from_sig(ctx, sig_fors, md, pk_seed, adrs, pk_fors)
|
||||
&& ossl_slh_ht_verify(ctx, pk_fors, sig_ht, pk_seed,
|
||||
tree_id, leaf_id, pk_root);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,6 +221,7 @@ static uint8_t *msg_encode(const uint8_t *msg, size_t msg_len,
|
||||
|
||||
/**
|
||||
* See FIPS 205 Section 10.2.1 Algorithm 22
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
int ossl_slh_dsa_sign(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *priv,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
@ -246,6 +247,7 @@ int ossl_slh_dsa_sign(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *priv,
|
||||
|
||||
/**
|
||||
* See FIPS 205 Section 10.3 Algorithm 24
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
int ossl_slh_dsa_verify(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *pub,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
|
@ -219,7 +219,7 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
|
||||
* @param ctx Contains SLH_DSA algorithm functions and constants.
|
||||
* @param out A SLH_DSA key containing the private key (seed and prf) and public key seed.
|
||||
* The public root key is written to this key.
|
||||
* @returns 1 if the root key is generated.
|
||||
* @returns 1 if the root key is generated, or 0 on error.
|
||||
*/
|
||||
static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out)
|
||||
{
|
||||
@ -232,9 +232,8 @@ static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out)
|
||||
adrsf->zero(adrs);
|
||||
adrsf->set_layer_address(adrs, params->d - 1);
|
||||
/* Generate the ROOT public key */
|
||||
ossl_slh_xmss_node(ctx, SLH_DSA_SK_SEED(out), 0, params->hm,
|
||||
SLH_DSA_PK_SEED(out), adrs, SLH_DSA_PK_ROOT(out));
|
||||
return 1;
|
||||
return ossl_slh_xmss_node(ctx, SLH_DSA_SK_SEED(out), 0, params->hm,
|
||||
SLH_DSA_PK_SEED(out), adrs, SLH_DSA_PK_ROOT(out));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,40 +46,42 @@ struct slh_dsa_ctx_st {
|
||||
SLH_HASH_CTX hash_ctx;
|
||||
};
|
||||
|
||||
void ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out);
|
||||
void ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len);
|
||||
void ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, uint8_t *adrs,
|
||||
uint8_t *pk_out);
|
||||
__owur int ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out);
|
||||
__owur int ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len);
|
||||
__owur int ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, uint8_t *adrs,
|
||||
uint8_t *pk_out);
|
||||
|
||||
void ossl_slh_xmss_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
uint32_t node_id, uint32_t height,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint8_t *pk_out);
|
||||
void ossl_slh_xmss_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, uint32_t node_id,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *sig, size_t sig_len);
|
||||
void ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *pk_out);
|
||||
__owur int ossl_slh_xmss_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
uint32_t node_id, uint32_t height,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *pk_out);
|
||||
__owur int ossl_slh_xmss_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, uint32_t node_id,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *sig, size_t sig_len);
|
||||
__owur int ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *pk_out);
|
||||
|
||||
void ossl_slh_ht_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
uint64_t tree_id, uint32_t leaf_id,
|
||||
uint8_t *sig_out, size_t sig_out_len);
|
||||
int ossl_slh_ht_verify(SLH_DSA_CTX *ctx, const uint8_t *msg, const uint8_t *sig,
|
||||
const uint8_t *pk_seed, uint64_t tree_id, uint32_t leaf_id,
|
||||
const uint8_t *pk_root);
|
||||
__owur int ossl_slh_ht_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
uint64_t tree_id, uint32_t leaf_id,
|
||||
uint8_t *sig_out, size_t sig_out_len);
|
||||
__owur int ossl_slh_ht_verify(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sig, const uint8_t *pk_seed,
|
||||
uint64_t tree_id, uint32_t leaf_id,
|
||||
const uint8_t *pk_root);
|
||||
|
||||
void ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len);
|
||||
void ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
const uint8_t *md, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out);
|
||||
__owur int ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len);
|
||||
__owur int ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
const uint8_t *md, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out);
|
||||
|
@ -34,10 +34,11 @@ static void slh_base_2b(const uint8_t *in, uint32_t b, uint32_t *out, size_t out
|
||||
* @param id The index of the FORS secret value within the sets of FORS trees.
|
||||
* (which must be < 2^(hm - height)
|
||||
* @param pk_out The generated FORS secret value of size |n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
static void slh_fors_sk_gen(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint32_t id,
|
||||
uint8_t *sk_out)
|
||||
static int slh_fors_sk_gen(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint32_t id,
|
||||
uint8_t *sk_out)
|
||||
{
|
||||
SLH_ADRS_DECLARE(sk_adrs);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -46,7 +47,7 @@ static void slh_fors_sk_gen(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_FORS_PRF);
|
||||
adrsf->copy_keypair_address(sk_adrs, adrs);
|
||||
adrsf->set_tree_index(sk_adrs, id);
|
||||
ctx->hash_func->PRF(&ctx->hash_ctx, pk_seed, sk_seed, sk_adrs, sk_out);
|
||||
return ctx->hash_func->PRF(&ctx->hash_ctx, pk_seed, sk_seed, sk_adrs, sk_out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,29 +68,35 @@ static void slh_fors_sk_gen(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
* @param node_id The target node index
|
||||
* @param height The target node height
|
||||
* @param node The returned hash for a node of size|n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
static void slh_fors_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint32_t node_id,
|
||||
uint32_t height, uint8_t *node)
|
||||
static int slh_fors_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint32_t node_id,
|
||||
uint32_t height, uint8_t *node)
|
||||
{
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
uint8_t sk[SLH_MAX_N], lnode[SLH_MAX_N], rnode[SLH_MAX_N];
|
||||
uint32_t n = ctx->params->n;
|
||||
|
||||
if (height == 0) {
|
||||
slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs, node_id, sk);
|
||||
if (!slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs, node_id, sk))
|
||||
return 0;
|
||||
adrsf->set_tree_height(adrs, 0);
|
||||
adrsf->set_tree_index(adrs, node_id);
|
||||
ctx->hash_func->F(&ctx->hash_ctx, pk_seed, adrs, sk, n, node);
|
||||
if (!ctx->hash_func->F(&ctx->hash_ctx, pk_seed, adrs, sk, n, node))
|
||||
return 0;
|
||||
} else {
|
||||
slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id, height - 1,
|
||||
lnode);
|
||||
slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id + 1, height - 1,
|
||||
rnode);
|
||||
if (!slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id, height - 1,
|
||||
lnode)
|
||||
|| !slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id + 1,
|
||||
height - 1, rnode))
|
||||
return 0;
|
||||
adrsf->set_tree_height(adrs, height);
|
||||
adrsf->set_tree_index(adrs, node_id);
|
||||
ctx->hash_func->H(&ctx->hash_ctx, pk_seed, adrs, lnode, rnode, node);
|
||||
if (!ctx->hash_func->H(&ctx->hash_ctx, pk_seed, adrs, lnode, rnode, node))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,10 +114,11 @@ static void slh_fors_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
* @param sig_out The generated XMSS signature which consists of a WOTS+
|
||||
* signature and authentication path
|
||||
* @param sig_len The size of |sig| which is (2 * n + 3) * n + tree_height * n.
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len)
|
||||
int ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len)
|
||||
{
|
||||
uint32_t i, j, s;
|
||||
uint32_t ids[SLH_MAX_K];
|
||||
@ -131,20 +139,23 @@ void ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
for (i = 0; i < k; ++i) {
|
||||
uint32_t id = ids[i]; /* |id| = |a| bits */
|
||||
|
||||
slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs,
|
||||
id + t_times_i, psig);
|
||||
if (!slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs,
|
||||
id + t_times_i, psig))
|
||||
return 0;
|
||||
psig += n;
|
||||
|
||||
for (j = 0; j < a; ++j) {
|
||||
s = id ^ 1;
|
||||
slh_fors_node(ctx, sk_seed, pk_seed, adrs, s + i * (1 << (a - j)),
|
||||
j, psig);
|
||||
if (!slh_fors_node(ctx, sk_seed, pk_seed, adrs, s + i * (1 << (a - j)),
|
||||
j, psig))
|
||||
return 0;
|
||||
id >>= 1;
|
||||
psig += n;
|
||||
}
|
||||
t_times_i += t;
|
||||
}
|
||||
assert((size_t)(psig - sig) == sig_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,10 +171,11 @@ void ossl_slh_fors_sign(SLH_DSA_CTX *ctx, const uint8_t *md,
|
||||
* the type set to FORS_TREE, and the keypair address set to the
|
||||
* index of the WOTS+ key that signs the FORS key.
|
||||
* @param pk_out The returned candidate FORS public key of size |n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
const uint8_t *md, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out)
|
||||
int ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
const uint8_t *md, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out)
|
||||
{
|
||||
SLH_ADRS_DECLARE(pk_adrs);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -191,7 +203,8 @@ void ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
|
||||
set_tree_height(adrs, 0);
|
||||
set_tree_index(adrs, node_id);
|
||||
F(hctx, pk_seed, adrs, sig, n, node);
|
||||
if (!F(hctx, pk_seed, adrs, sig, n, node))
|
||||
return 0;
|
||||
sig += n;
|
||||
|
||||
for (j = 0; j < a; ++j) {
|
||||
@ -199,11 +212,13 @@ void ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
if ((id & 1) == 0) {
|
||||
node_id >>= 1;
|
||||
set_tree_index(adrs, node_id);
|
||||
H(hctx, pk_seed, adrs, node, sig, node);
|
||||
if (!H(hctx, pk_seed, adrs, node, sig, node))
|
||||
return 0;
|
||||
} else {
|
||||
node_id = (node_id - 1) >> 1;
|
||||
set_tree_index(adrs, node_id);
|
||||
H(hctx, pk_seed, adrs, sig, node, node);
|
||||
if (!H(hctx, pk_seed, adrs, sig, node, node))
|
||||
return 0;
|
||||
}
|
||||
id >>= 1;
|
||||
sig += n;
|
||||
@ -217,7 +232,7 @@ void ossl_slh_fors_pk_from_sig(SLH_DSA_CTX *ctx, const uint8_t *sig,
|
||||
adrsf->copy(pk_adrs, adrs);
|
||||
adrsf->set_type_and_clear(pk_adrs, SLH_ADRS_TYPE_FORS_ROOTS);
|
||||
adrsf->copy_keypair_address(pk_adrs, adrs);
|
||||
hashf->T(hctx, pk_seed, pk_adrs, roots, node - roots, pk_out);
|
||||
return hashf->T(hctx, pk_seed, pk_adrs, roots, node - roots, pk_out);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +157,7 @@ static ossl_inline int xof_digest_4(EVP_MD_CTX *ctx,
|
||||
}
|
||||
|
||||
/* See FIPS 205 Section 11.1 */
|
||||
static void
|
||||
static int
|
||||
slh_hmsg_shake(SLH_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
|
||||
const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
|
||||
uint8_t *out)
|
||||
@ -165,53 +165,59 @@ slh_hmsg_shake(SLH_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
|
||||
size_t m = hctx->m;
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_4(hctx->md_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len, out, m);
|
||||
return xof_digest_4(hctx->md_ctx, r, n, pk_seed, n, pk_root, n,
|
||||
msg, msg_len, out, m);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_prf_shake(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *sk_seed,
|
||||
const SLH_ADRS adrs, uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, sk_seed, n, out, n);
|
||||
return xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
|
||||
sk_seed, n, out, n);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_prf_msg_shake(SLH_HASH_CTX *hctx, const uint8_t *sk_prf,
|
||||
const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len,
|
||||
uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_3(hctx->md_ctx, sk_prf, n, opt_rand, n, msg, msg_len, out, n);
|
||||
return xof_digest_3(hctx->md_ctx, sk_prf, n, opt_rand, n,
|
||||
msg, msg_len, out, n);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_f_shake(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *m1, size_t m1_len, uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, m1_len, out, n);
|
||||
return xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
|
||||
m1, m1_len, out, n);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_h_shake(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *m1, const uint8_t *m2, uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_4(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, n, m2, n, out, n);
|
||||
return xof_digest_4(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
|
||||
m1, n, m2, n, out, n);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_t_shake(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *ml, size_t ml_len, uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, ml, ml_len, out, n);
|
||||
return xof_digest_3(hctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
|
||||
ml, ml_len, out, n);
|
||||
}
|
||||
|
||||
static ossl_inline int
|
||||
@ -230,7 +236,7 @@ digest_4(EVP_MD_CTX *ctx,
|
||||
|
||||
/* FIPS 205 Section 11.2.1 and 11.2.2 */
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_hmsg_sha2(SLH_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
|
||||
const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
|
||||
uint8_t *out)
|
||||
@ -245,19 +251,20 @@ slh_hmsg_sha2(SLH_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
|
||||
|
||||
memcpy(seed, r, n);
|
||||
memcpy(seed + n, pk_seed, n);
|
||||
digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len,
|
||||
seed + 2 * n);
|
||||
PKCS1_MGF1(out, hctx->m, seed, seed_len, hctx->md);
|
||||
return digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len,
|
||||
seed + 2 * n)
|
||||
&& (PKCS1_MGF1(out, hctx->m, seed, seed_len, hctx->md) == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_prf_msg_sha2(SLH_HASH_CTX *hctx,
|
||||
const uint8_t *sk_prf, const uint8_t *opt_rand,
|
||||
const uint8_t *msg, size_t msg_len, uint8_t *out)
|
||||
{
|
||||
int ret;
|
||||
EVP_MAC_CTX *mctx = hctx->hmac_ctx;
|
||||
size_t n = hctx->n;
|
||||
uint8_t mac[MAX_DIGEST_SIZE];
|
||||
uint8_t mac[MAX_DIGEST_SIZE] = {0};
|
||||
OSSL_PARAM *p = NULL;
|
||||
OSSL_PARAM params[3];
|
||||
|
||||
@ -278,47 +285,50 @@ slh_prf_msg_sha2(SLH_HASH_CTX *hctx,
|
||||
hctx->hmac_digest = NULL;
|
||||
}
|
||||
|
||||
EVP_MAC_init(mctx, sk_prf, n, p);
|
||||
EVP_MAC_update(mctx, opt_rand, n);
|
||||
EVP_MAC_update(mctx, msg, msg_len);
|
||||
EVP_MAC_final(mctx, mac, NULL, sizeof(mac));
|
||||
ret = EVP_MAC_init(mctx, sk_prf, n, p) == 1
|
||||
&& EVP_MAC_update(mctx, opt_rand, n) == 1
|
||||
&& EVP_MAC_update(mctx, msg, msg_len) == 1
|
||||
&& EVP_MAC_final(mctx, mac, NULL, sizeof(mac)) == 1;
|
||||
memcpy(out, mac, n); /* Truncate output to n bytes */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ossl_inline void
|
||||
static ossl_inline int
|
||||
do_hash(EVP_MD_CTX *ctx, size_t n, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *m, size_t m_len, size_t b, uint8_t *out)
|
||||
{
|
||||
int ret;
|
||||
uint8_t zeros[128] = { 0 };
|
||||
uint8_t digest[MAX_DIGEST_SIZE];
|
||||
|
||||
assert(b - n < sizeof(zeros));
|
||||
|
||||
digest_4(ctx, pk_seed, n, zeros, b - n, adrs, SLH_ADRSC_SIZE, m, m_len,
|
||||
digest);
|
||||
ret = digest_4(ctx, pk_seed, n, zeros, b - n, adrs, SLH_ADRSC_SIZE,
|
||||
m, m_len, digest);
|
||||
/* Truncated returned value is n = 16 bytes */
|
||||
memcpy(out, digest, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_prf_sha2(SLH_HASH_CTX *hctx, const uint8_t *pk_seed,
|
||||
const uint8_t *sk_seed, const SLH_ADRS adrs, uint8_t *out)
|
||||
{
|
||||
size_t n = hctx->n;
|
||||
|
||||
do_hash(hctx->md_ctx, n, pk_seed, adrs, sk_seed, n,
|
||||
SHA2_NUM_ZEROS_BOUND1, out);
|
||||
return do_hash(hctx->md_ctx, n, pk_seed, adrs, sk_seed, n,
|
||||
SHA2_NUM_ZEROS_BOUND1, out);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_f_sha2(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *m1, size_t m1_len, uint8_t *out)
|
||||
{
|
||||
do_hash(hctx->md_ctx, hctx->n, pk_seed, adrs, m1, m1_len,
|
||||
SHA2_NUM_ZEROS_BOUND1, out);
|
||||
return do_hash(hctx->md_ctx, hctx->n, pk_seed, adrs, m1, m1_len,
|
||||
SHA2_NUM_ZEROS_BOUND1, out);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_h_sha2(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *m1, const uint8_t *m2, uint8_t *out)
|
||||
{
|
||||
@ -327,16 +337,16 @@ slh_h_sha2(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
|
||||
memcpy(m, m1, n);
|
||||
memcpy(m + n, m2, n);
|
||||
do_hash(hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n,
|
||||
hctx->sha2_h_and_t_bound, out);
|
||||
return do_hash(hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n,
|
||||
hctx->sha2_h_and_t_bound, out);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
slh_t_sha2(SLH_HASH_CTX *hctx, const uint8_t *pk_seed, const SLH_ADRS adrs,
|
||||
const uint8_t *ml, size_t ml_len, uint8_t *out)
|
||||
{
|
||||
do_hash(hctx->md_big_ctx, hctx->n, pk_seed, adrs, ml, ml_len,
|
||||
hctx->sha2_h_and_t_bound, out);
|
||||
return do_hash(hctx->md_big_ctx, hctx->n, pk_seed, adrs, ml, ml_len,
|
||||
hctx->sha2_h_and_t_bound, out);
|
||||
}
|
||||
|
||||
const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake)
|
||||
|
@ -38,23 +38,23 @@ typedef struct slh_hash_ctx_st {
|
||||
/*
|
||||
* @params out is |m| bytes which ranges from (30..49) bytes
|
||||
*/
|
||||
typedef void (OSSL_SLH_HASHFUNC_H_MSG)(SLH_HASH_CTX *ctx, const uint8_t *r,
|
||||
typedef int (OSSL_SLH_HASHFUNC_H_MSG)(SLH_HASH_CTX *ctx, const uint8_t *r,
|
||||
const uint8_t *pk_seed, const uint8_t *pk_root,
|
||||
const uint8_t *msg, size_t msg_len, uint8_t *out);
|
||||
|
||||
typedef void (OSSL_SLH_HASHFUNC_PRF)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
typedef int (OSSL_SLH_HASHFUNC_PRF)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
const uint8_t *sk_seed, const SLH_ADRS adrs, uint8_t *out);
|
||||
|
||||
typedef void (OSSL_SLH_HASHFUNC_PRF_MSG)(SLH_HASH_CTX *ctx, const uint8_t *sk_prf,
|
||||
typedef int (OSSL_SLH_HASHFUNC_PRF_MSG)(SLH_HASH_CTX *ctx, const uint8_t *sk_prf,
|
||||
const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len, uint8_t *out);
|
||||
|
||||
typedef void (OSSL_SLH_HASHFUNC_F)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
typedef int (OSSL_SLH_HASHFUNC_F)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
const SLH_ADRS adrs, const uint8_t *m1, size_t m1_len, uint8_t *out);
|
||||
|
||||
typedef void (OSSL_SLH_HASHFUNC_H)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
typedef int (OSSL_SLH_HASHFUNC_H)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
const SLH_ADRS adrs, const uint8_t *m1, const uint8_t *m2, uint8_t *out);
|
||||
|
||||
typedef void (OSSL_SLH_HASHFUNC_T)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
typedef int (OSSL_SLH_HASHFUNC_T)(SLH_HASH_CTX *ctx, const uint8_t *pk_seed,
|
||||
const SLH_ADRS adrs, const uint8_t *m1, size_t m1_len, uint8_t *out);
|
||||
|
||||
typedef struct slh_hash_func_st {
|
||||
@ -68,9 +68,9 @@ typedef struct slh_hash_func_st {
|
||||
|
||||
const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake);
|
||||
|
||||
int ossl_slh_hash_ctx_init(SLH_HASH_CTX *ctx, OSSL_LIB_CTX *libctx,
|
||||
const char *propq, int is_shake,
|
||||
int security_category, size_t n, size_t m);
|
||||
__owur int ossl_slh_hash_ctx_init(SLH_HASH_CTX *ctx, OSSL_LIB_CTX *libctx,
|
||||
const char *propq, int is_shake,
|
||||
int security_category, size_t n, size_t m);
|
||||
void ossl_slh_hash_ctx_cleanup(SLH_HASH_CTX *ctx);
|
||||
|
||||
#endif
|
||||
|
@ -25,12 +25,13 @@
|
||||
* @param leaf_id Index of the WOTS+ key within the XMSS tree that will signed the message
|
||||
* @param sig The returned Hypertree Signature (which is |d| XMSS signatures)
|
||||
* @param sig_len The size of |sig| which is (|h| + |d| * |len|) * |n|)
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_ht_sign(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *msg, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed,
|
||||
uint64_t tree_id, uint32_t leaf_id,
|
||||
uint8_t *sig, size_t sig_len)
|
||||
int ossl_slh_ht_sign(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *msg, const uint8_t *sk_seed,
|
||||
const uint8_t *pk_seed,
|
||||
uint64_t tree_id, uint32_t leaf_id,
|
||||
uint8_t *sig, size_t sig_len)
|
||||
{
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
SLH_ADRS_DECLARE(adrs);
|
||||
@ -50,15 +51,20 @@ void ossl_slh_ht_sign(SLH_DSA_CTX *ctx,
|
||||
for (layer = 0; layer < d; ++layer) {
|
||||
adrsf->set_layer_address(adrs, layer);
|
||||
adrsf->set_tree_address(adrs, tree_id);
|
||||
ossl_slh_xmss_sign(ctx, root, sk_seed, leaf_id, pk_seed, adrs,
|
||||
psig, xmss_sig_len);
|
||||
if (layer < d - 1)
|
||||
ossl_slh_xmss_pk_from_sig(ctx, leaf_id, psig, root, pk_seed, adrs, root);
|
||||
if (!ossl_slh_xmss_sign(ctx, root, sk_seed, leaf_id, pk_seed, adrs,
|
||||
psig, xmss_sig_len))
|
||||
return 0;
|
||||
if (layer < d - 1) {
|
||||
if (!ossl_slh_xmss_pk_from_sig(ctx, leaf_id, psig, root,
|
||||
pk_seed, adrs, root))
|
||||
return 0;
|
||||
}
|
||||
psig += xmss_sig_len;
|
||||
leaf_id = tree_id & mask;
|
||||
tree_id >>= hm;
|
||||
}
|
||||
assert((size_t)(psig - sig) == sig_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +103,9 @@ int ossl_slh_ht_verify(SLH_DSA_CTX *ctx, const uint8_t *msg, const uint8_t *sig,
|
||||
for (layer = 0; layer < d; ++layer) {
|
||||
adrsf->set_layer_address(adrs, layer);
|
||||
adrsf->set_tree_address(adrs, tree_id);
|
||||
ossl_slh_xmss_pk_from_sig(ctx, leaf_id, sig, node, pk_seed, adrs, node);
|
||||
if (!ossl_slh_xmss_pk_from_sig(ctx, leaf_id, sig, node,
|
||||
pk_seed, adrs, node))
|
||||
return 0;
|
||||
sig += len;
|
||||
leaf_id = tree_id & mask;
|
||||
tree_id >>= tree_height;
|
||||
|
@ -89,10 +89,11 @@ static ossl_inline void compute_checksum_nibbles(const uint8_t *in, size_t in_le
|
||||
* @param adrs An ADRS object which has a type of WOTS_HASH, and has a layer
|
||||
* address, tree address, key pair address and chain address
|
||||
* @param pk_seed A public key seed (which is added to the hash)
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
static void slh_wots_chain(SLH_DSA_CTX *ctx, const uint8_t *in,
|
||||
uint8_t start_index, uint8_t steps,
|
||||
const uint8_t *pk_seed, uint8_t *adrs, uint8_t *out)
|
||||
static int slh_wots_chain(SLH_DSA_CTX *ctx, const uint8_t *in,
|
||||
uint8_t start_index, uint8_t steps,
|
||||
const uint8_t *pk_seed, uint8_t *adrs, uint8_t *out)
|
||||
{
|
||||
SLH_HASH_FUNC_DECLARE(ctx, hashf, hctx);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -105,8 +106,10 @@ static void slh_wots_chain(SLH_DSA_CTX *ctx, const uint8_t *in,
|
||||
|
||||
for (j = start_index; j < end_index; ++j) {
|
||||
set_hash_address(adrs, j);
|
||||
F(hctx, pk_seed, adrs, out, n, out);
|
||||
if (!F(hctx, pk_seed, adrs, out, n, out))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,10 +122,11 @@ static void slh_wots_chain(SLH_DSA_CTX *ctx, const uint8_t *in,
|
||||
* @param adrs An ADRS object containing the layer address, tree address and
|
||||
* keypair address of the WOTS+ public key to generate.
|
||||
* @param pk_out The generated public key of size |n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out)
|
||||
int ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *pk_out)
|
||||
{
|
||||
SLH_HASH_FUNC_DECLARE(ctx, hashf, hctx);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -142,10 +146,12 @@ void ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
len = SLH_WOTS_LEN(n); /* See Section 5 intro */
|
||||
for (i = 0; i < len; ++i) {
|
||||
set_chain_address(sk_adrs, i);
|
||||
PRF(hctx, pk_seed, sk_seed, sk_adrs, sk);
|
||||
if (!PRF(hctx, pk_seed, sk_seed, sk_adrs, sk))
|
||||
return 0;
|
||||
|
||||
set_chain_address(adrs, i);
|
||||
slh_wots_chain(ctx, sk, 0, NIBBLE_MASK, pk_seed, adrs, ptmp);
|
||||
if (!slh_wots_chain(ctx, sk, 0, NIBBLE_MASK, pk_seed, adrs, ptmp))
|
||||
return 0;
|
||||
ptmp += n;
|
||||
}
|
||||
|
||||
@ -153,7 +159,7 @@ void ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
adrsf->copy(wots_pk_adrs, adrs);
|
||||
adrsf->set_type_and_clear(wots_pk_adrs, SLH_ADRS_TYPE_WOTS_PK);
|
||||
adrsf->copy_keypair_address(wots_pk_adrs, adrs);
|
||||
hashf->T(hctx, pk_seed, wots_pk_adrs, tmp, len, pk_out);
|
||||
return hashf->T(hctx, pk_seed, wots_pk_adrs, tmp, len, pk_out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,10 +176,11 @@ void ossl_slh_wots_pk_gen(SLH_DSA_CTX *ctx,
|
||||
* @param sig The returned signature.
|
||||
* @param sig_len The size of |sig| which should be len * |n| bytes.
|
||||
* (where len = 2 * |n| + 3)
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len)
|
||||
int ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs, uint8_t *sig, size_t sig_len)
|
||||
{
|
||||
SLH_HASH_FUNC_DECLARE(ctx, hashf, hctx);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -204,13 +211,17 @@ void ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
for (i = 0; i < len; ++i) {
|
||||
set_chain_address(sk_adrs, i);
|
||||
/* compute chain i secret */
|
||||
PRF(hctx, pk_seed, sk_seed, sk_adrs, sk);
|
||||
if (!PRF(hctx, pk_seed, sk_seed, sk_adrs, sk))
|
||||
return 0;
|
||||
set_chain_address(adrs, i);
|
||||
/* compute chain i signature */
|
||||
slh_wots_chain(ctx, sk, 0, msg_and_csum_nibbles[i], pk_seed, adrs, psig);
|
||||
if (!slh_wots_chain(ctx, sk, 0, msg_and_csum_nibbles[i],
|
||||
pk_seed, adrs, psig))
|
||||
return 0;
|
||||
psig += n;
|
||||
}
|
||||
assert(sig_len == (size_t)(psig - sig));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,11 +235,12 @@ void ossl_slh_wots_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
* @param adrs An ADRS object containing the layer address, tree address and
|
||||
* key pair address that of the WOTS+ key used to sign the message.
|
||||
* @param pk_out The returned public key candidate of size |n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, uint8_t *adrs,
|
||||
uint8_t *pk_out)
|
||||
int ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, uint8_t *adrs,
|
||||
uint8_t *pk_out)
|
||||
{
|
||||
SLH_HASH_FUNC_DECLARE(ctx, hashf, hctx);
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
@ -247,9 +259,10 @@ void ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
/* Compute the end nodes for each of the chains */
|
||||
for (i = 0; i < len; ++i) {
|
||||
set_chain_address(adrs, i);
|
||||
slh_wots_chain(ctx, sig, msg_and_csum_nibbles[i],
|
||||
NIBBLE_MASK - msg_and_csum_nibbles[i],
|
||||
pk_seed, adrs, ptmp);
|
||||
if (!slh_wots_chain(ctx, sig, msg_and_csum_nibbles[i],
|
||||
NIBBLE_MASK - msg_and_csum_nibbles[i],
|
||||
pk_seed, adrs, ptmp))
|
||||
return 0;
|
||||
sig += n;
|
||||
ptmp += n;
|
||||
}
|
||||
@ -257,5 +270,5 @@ void ossl_slh_wots_pk_from_sig(SLH_DSA_CTX *ctx,
|
||||
adrsf->copy(wots_pk_adrs, adrs);
|
||||
adrsf->set_type_and_clear(wots_pk_adrs, SLH_ADRS_TYPE_WOTS_PK);
|
||||
adrsf->copy_keypair_address(wots_pk_adrs, adrs);
|
||||
hashf->T(hctx, pk_seed, wots_pk_adrs, tmp, ptmp - tmp, pk_out);
|
||||
return hashf->T(hctx, pk_seed, wots_pk_adrs, tmp, ptmp - tmp, pk_out);
|
||||
}
|
||||
|
@ -17,26 +17,23 @@
|
||||
* This is a recursive function that starts at an leaf index, that calculates
|
||||
* the hash of each parent using 2 child nodes.
|
||||
*
|
||||
* @param sk_seed A private key seed
|
||||
* @param pk_seed A public key seed
|
||||
* @param n The size of |sk_seed|, |pk_seed| and |pk_out|
|
||||
* @param adrs An ADRS object containing the layer address and tree address set
|
||||
* to the XMSS tree within which the XMSS tree is being computed.
|
||||
* @param ctx Contains SLH_DSA algorithm functions and constants.
|
||||
* @param sk_seed A private key seed of size |n|
|
||||
* @param nodeid The index of the target node being computed
|
||||
* (which must be < 2^(hm - height)
|
||||
* @param height The height within the tree of the node being computed.
|
||||
* (which must be <= hm) (hm is one of 3, 4, 8 or 9)
|
||||
* At height=0 There are 2^hm leaf nodes,
|
||||
* and the root node is at height = hm)
|
||||
* @param h The height within the tree of the node being computed.
|
||||
* (which must be <= hm) (hm is one of 3, 4, 8 or 9)
|
||||
* At height=0 There are 2^hm leaf nodes,
|
||||
* and the root node is at height = hm)
|
||||
* @param pk_seed A public key seed of size |n|
|
||||
* @param adrs An ADRS object containing the layer address and tree address set
|
||||
* to the XMSS tree within which the XMSS tree is being computed.
|
||||
* @param pk_out The generated public key of size |n|
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_xmss_node(SLH_DSA_CTX *ctx,
|
||||
const uint8_t *sk_seed,
|
||||
uint32_t node_id,
|
||||
uint32_t h,
|
||||
const uint8_t *pk_seed,
|
||||
SLH_ADRS adrs,
|
||||
uint8_t *pk_out)
|
||||
int ossl_slh_xmss_node(SLH_DSA_CTX *ctx, const uint8_t *sk_seed,
|
||||
uint32_t node_id, uint32_t h,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs, uint8_t *pk_out)
|
||||
{
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
|
||||
@ -44,41 +41,46 @@ void ossl_slh_xmss_node(SLH_DSA_CTX *ctx,
|
||||
/* For leaf nodes generate the public key */
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_WOTS_HASH);
|
||||
adrsf->set_keypair_address(adrs, node_id);
|
||||
ossl_slh_wots_pk_gen(ctx, sk_seed, pk_seed, adrs, pk_out);
|
||||
if (!ossl_slh_wots_pk_gen(ctx, sk_seed, pk_seed, adrs, pk_out))
|
||||
return 0;
|
||||
} else {
|
||||
uint8_t lnode[SLH_MAX_N], rnode[SLH_MAX_N];
|
||||
|
||||
ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id, h - 1, pk_seed, adrs,
|
||||
lnode);
|
||||
ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id + 1, h - 1, pk_seed, adrs,
|
||||
rnode);
|
||||
if (!ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id, h - 1, pk_seed, adrs,
|
||||
lnode)
|
||||
|| !ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id + 1, h - 1,
|
||||
pk_seed, adrs, rnode))
|
||||
return 0;
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_TREE);
|
||||
adrsf->set_tree_height(adrs, h);
|
||||
adrsf->set_tree_index(adrs, node_id);
|
||||
ctx->hash_func->H(&ctx->hash_ctx, pk_seed, adrs, lnode, rnode, pk_out);
|
||||
if (!ctx->hash_func->H(&ctx->hash_ctx, pk_seed, adrs, lnode, rnode, pk_out))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate an XMSS signature using a message and key.
|
||||
* See FIPS 205 Section 6.2 Algorithm 10
|
||||
*
|
||||
* @param ctx Contains SLH_DSA algorithm functions and constants.
|
||||
* @param msg A message of size |n| bytes to sign
|
||||
* @param sk_seed A private key seed
|
||||
* @param pk_seed A public key seed
|
||||
* @param n The size of |msg|, |sk_seed| and |pk_seed|
|
||||
* @param sk_seed A private key seed of size |n|
|
||||
* @param node_id The index of a WOTS+ key within the XMSS tree to use for signing.
|
||||
* @param pk_seed A public key seed f size |n|
|
||||
* @param adrs An ADRS object containing the layer address and tree address set
|
||||
* to the XMSS key being used to sign the message.
|
||||
* @param node_id The index of a WOTS+ key within the XMSS tree to use for signing.
|
||||
* @param tree_height The height of the XMSS tree.
|
||||
* @param sig_out The generated XMSS signature which consists of a WOTS+
|
||||
* signature of size [2 * n + 3][n] followed by an authentication
|
||||
* path of size [tree_height[n].
|
||||
* @param sig The generated XMSS signature.
|
||||
* @param sig_len The size of |sig|. which consists of a WOTS+
|
||||
* signature of size [2 * n + 3][n] followed by an authentication
|
||||
* path of size [tree_height[n].
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_xmss_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, uint32_t node_id,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *sig, size_t sig_len)
|
||||
int ossl_slh_xmss_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
const uint8_t *sk_seed, uint32_t node_id,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *sig, size_t sig_len)
|
||||
{
|
||||
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
|
||||
uint32_t h, id = node_id;
|
||||
@ -86,42 +88,39 @@ void ossl_slh_xmss_sign(SLH_DSA_CTX *ctx, const uint8_t *msg,
|
||||
uint32_t hm = ctx->params->hm;
|
||||
size_t wots_sig_len = n * SLH_WOTS_LEN(n);
|
||||
uint8_t *auth_path = sig + wots_sig_len;
|
||||
/*
|
||||
size_t auth_sig_len = n * hm;
|
||||
assert(sig_len == (wots_sig_len + auth_sig_len));
|
||||
*/
|
||||
|
||||
for (h = 0; h < hm; ++h) {
|
||||
ossl_slh_xmss_node(ctx, sk_seed, id ^ 1, h, pk_seed, adrs, auth_path);
|
||||
if (!ossl_slh_xmss_node(ctx, sk_seed, id ^ 1, h, pk_seed, adrs, auth_path))
|
||||
return 0;
|
||||
id >>= 1;
|
||||
auth_path += n;
|
||||
}
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_WOTS_HASH);
|
||||
adrsf->set_keypair_address(adrs, node_id);
|
||||
ossl_slh_wots_sign(ctx, msg, sk_seed, pk_seed, adrs, sig, wots_sig_len);
|
||||
return ossl_slh_wots_sign(ctx, msg, sk_seed, pk_seed, adrs, sig, wots_sig_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute a candidate XMSS public key from a message and XMSS signature
|
||||
* See FIPS 205 Section 6.3 Algorithm 11
|
||||
*
|
||||
* @param ctx Contains SLH_DSA algorithm functions and constants.
|
||||
* @param node_id Must be set to the |node_id| used in xmss_sign().
|
||||
* @param sig A XMSS signature which consists of a WOTS+ signature of
|
||||
* [2 * n + 3][n] bytes followed by an authentication path of
|
||||
* [hm][n] bytes (where hm is the height of the XMSS tree).
|
||||
* @param msg A message of size |n| bytes
|
||||
* @param sk_seed A private key seed
|
||||
* @param pk_seed A public key seed
|
||||
* @param n The hash size size if the size of |msg|, |sk_seed| and |pk_seed|
|
||||
* @param adrs An ADRS object containing a layer address and tress address of an
|
||||
* @param sk_seed A private key seed of size |n|
|
||||
* @param pk_seed A public key seed of size |n|
|
||||
* @param adrs An ADRS object containing a layer address and tree address of an
|
||||
* XMSS key used for signing the message.
|
||||
* @param node_id Must be set to the |node_id| used in xmss_sign().
|
||||
* @param tree_height The height of the XMSS tree.
|
||||
* @param pk_out The returned candidate XMSS public key of size |n|.
|
||||
* @returns 1 on success, or 0 on error.
|
||||
*/
|
||||
void ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *pk_out)
|
||||
int ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
const uint8_t *sig, const uint8_t *msg,
|
||||
const uint8_t *pk_seed, SLH_ADRS adrs,
|
||||
uint8_t *pk_out)
|
||||
{
|
||||
SLH_HASH_FUNC_DECLARE(ctx, hashf, hctx);
|
||||
SLH_HASH_FN_DECLARE(hashf, H);
|
||||
@ -137,7 +136,8 @@ void ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_WOTS_HASH);
|
||||
adrsf->set_keypair_address(adrs, node_id);
|
||||
ossl_slh_wots_pk_from_sig(ctx, sig, msg, pk_seed, adrs, node);
|
||||
if (!ossl_slh_wots_pk_from_sig(ctx, sig, msg, pk_seed, adrs, node))
|
||||
return 0;
|
||||
|
||||
adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_TREE);
|
||||
|
||||
@ -146,12 +146,15 @@ void ossl_slh_xmss_pk_from_sig(SLH_DSA_CTX *ctx, uint32_t node_id,
|
||||
if ((node_id & 1) == 0) { /* even */
|
||||
node_id >>= 1;
|
||||
set_tree_index(adrs, node_id);
|
||||
H(hctx, pk_seed, adrs, node, auth_path, node);
|
||||
if (!H(hctx, pk_seed, adrs, node, auth_path, node))
|
||||
return 0;
|
||||
} else { /* odd */
|
||||
node_id = (node_id - 1) >> 1;
|
||||
set_tree_index(adrs, node_id);
|
||||
H(hctx, pk_seed, adrs, auth_path, node, node);
|
||||
if (!H(hctx, pk_seed, adrs, auth_path, node, node))
|
||||
return 0;
|
||||
}
|
||||
auth_path += n;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -21,36 +21,36 @@
|
||||
|
||||
typedef struct slh_dsa_ctx_st SLH_DSA_CTX;
|
||||
|
||||
SLH_DSA_KEY *ossl_slh_dsa_key_new(OSSL_LIB_CTX *libctx, const char *alg);
|
||||
__owur SLH_DSA_KEY *ossl_slh_dsa_key_new(OSSL_LIB_CTX *libctx, const char *alg);
|
||||
void ossl_slh_dsa_key_free(SLH_DSA_KEY *key);
|
||||
int ossl_slh_dsa_key_up_ref(SLH_DSA_KEY *key);
|
||||
int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2,
|
||||
int selection);
|
||||
int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection);
|
||||
int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM *params,
|
||||
int include_private);
|
||||
int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *libctx,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
SLH_DSA_KEY *out);
|
||||
int ossl_slh_dsa_key_is_private(const SLH_DSA_KEY *key);
|
||||
const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key);
|
||||
const uint8_t *ossl_slh_dsa_key_get_priv(const SLH_DSA_KEY *key);
|
||||
size_t ossl_slh_dsa_key_get_len(const SLH_DSA_KEY *key);
|
||||
size_t ossl_slh_dsa_key_get_n(const SLH_DSA_KEY *key);
|
||||
int ossl_slh_dsa_key_type_matches(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key);
|
||||
__owur int ossl_slh_dsa_key_up_ref(SLH_DSA_KEY *key);
|
||||
__owur int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2,
|
||||
int selection);
|
||||
__owur int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection);
|
||||
__owur int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM *params,
|
||||
int include_private);
|
||||
__owur int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *libctx,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
SLH_DSA_KEY *out);
|
||||
__owur int ossl_slh_dsa_key_is_private(const SLH_DSA_KEY *key);
|
||||
__owur const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key);
|
||||
__owur const uint8_t *ossl_slh_dsa_key_get_priv(const SLH_DSA_KEY *key);
|
||||
__owur size_t ossl_slh_dsa_key_get_len(const SLH_DSA_KEY *key);
|
||||
__owur size_t ossl_slh_dsa_key_get_n(const SLH_DSA_KEY *key);
|
||||
__owur int ossl_slh_dsa_key_type_matches(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key);
|
||||
|
||||
SLH_DSA_CTX *ossl_slh_dsa_ctx_new(const char *alg,
|
||||
OSSL_LIB_CTX *lib_ctx, const char *propq);
|
||||
__owur SLH_DSA_CTX *ossl_slh_dsa_ctx_new(const char *alg,
|
||||
OSSL_LIB_CTX *lib_ctx, const char *propq);
|
||||
void ossl_slh_dsa_ctx_free(SLH_DSA_CTX *ctx);
|
||||
|
||||
int ossl_slh_dsa_sign(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *priv,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t *ctx, size_t ctx_len,
|
||||
const uint8_t *add_rand, int encode,
|
||||
unsigned char *sig, size_t *siglen, size_t sigsize);
|
||||
int ossl_slh_dsa_verify(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *pub,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t *ctx, size_t ctx_len, int encode,
|
||||
const uint8_t *sig, size_t sig_len);
|
||||
__owur int ossl_slh_dsa_sign(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *priv,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t *ctx, size_t ctx_len,
|
||||
const uint8_t *add_rand, int encode,
|
||||
unsigned char *sig, size_t *siglen, size_t sigsize);
|
||||
__owur int ossl_slh_dsa_verify(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *pub,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t *ctx, size_t ctx_len, int encode,
|
||||
const uint8_t *sig, size_t sig_len);
|
||||
|
||||
#endif /* OSSL_CRYPTO_SLH_DSA_H */
|
||||
|
@ -23,11 +23,20 @@ use lib srctop_dir('Configurations');
|
||||
use lib bldtop_dir('.');
|
||||
|
||||
plan skip_all => 'SLH-DSA is not supported in this build' if disabled('slh-dsa');
|
||||
plan tests => ($no_fips ? 0 : 1) + 1;
|
||||
plan tests => 2;
|
||||
|
||||
ok(run(test(["slh_dsa_test"])), "running slh_dsa_test");
|
||||
|
||||
unless ($no_fips) {
|
||||
SKIP: {
|
||||
skip "Skipping FIPS tests", 1
|
||||
if $no_fips;
|
||||
|
||||
# SLH-DSA is only present after OpenSSL 3.5
|
||||
run(test(["fips_version_test", "-config", $provconf, ">=3.5.0"]),
|
||||
capture => 1, statusvar => \my $exit);
|
||||
skip "FIPS provider version is too old for SLH_DSA test", 1
|
||||
if !$exit;
|
||||
|
||||
ok(run(test(["slh_dsa_test", "-config", $provconf])),
|
||||
"running slh_dsa_test with FIPS");
|
||||
}
|
||||
|
@ -137,6 +137,8 @@ static int slh_dsa_key_eq_test(void)
|
||||
goto end;
|
||||
ret = TEST_int_ne(EVP_PKEY_eq(key[0], eckey), 1);
|
||||
EVP_PKEY_free(eckey);
|
||||
#else
|
||||
ret = 1;
|
||||
#endif
|
||||
end:
|
||||
EVP_PKEY_free(key[2]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user