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:
slontis 2024-11-07 19:01:16 +11:00 committed by Tomas Mraz
parent 5901ca87ba
commit 30a55b0cf1
12 changed files with 305 additions and 242 deletions

View File

@ -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,

View File

@ -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));
}
/**

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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");
}

View File

@ -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]);