From: slontis Date: Thu, 7 Nov 2024 08:01:16 +0000 (+1100) Subject: Added return code checks to SLH_DSA Hash functions and propogated the X-Git-Tag: openssl-3.5.0-alpha1~193 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=30a55b0cf19121e03c300b47e730e06d6e2311b3;p=thirdparty%2Fopenssl.git Added return code checks to SLH_DSA Hash functions and propogated the values thru the calling functions. Reviewed-by: Paul Dale Reviewed-by: Viktor Dukhovni Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/25882) --- diff --git a/crypto/slh_dsa/slh_dsa.c b/crypto/slh_dsa/slh_dsa.c index 8a51354ae1f..8f6736b91b8 100644 --- a/crypto/slh_dsa/slh_dsa.c +++ b/crypto/slh_dsa/slh_dsa.c @@ -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, diff --git a/crypto/slh_dsa/slh_dsa_key.c b/crypto/slh_dsa/slh_dsa_key.c index f7dbb0f785d..922d1650846 100644 --- a/crypto/slh_dsa/slh_dsa_key.c +++ b/crypto/slh_dsa/slh_dsa_key.c @@ -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)); } /** diff --git a/crypto/slh_dsa/slh_dsa_local.h b/crypto/slh_dsa/slh_dsa_local.h index 77bf6a410a2..59c5fb605d5 100644 --- a/crypto/slh_dsa/slh_dsa_local.h +++ b/crypto/slh_dsa/slh_dsa_local.h @@ -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); diff --git a/crypto/slh_dsa/slh_fors.c b/crypto/slh_dsa/slh_fors.c index baa7f905356..7eb12b07172 100644 --- a/crypto/slh_dsa/slh_fors.c +++ b/crypto/slh_dsa/slh_fors.c @@ -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); } /** diff --git a/crypto/slh_dsa/slh_hash.c b/crypto/slh_dsa/slh_hash.c index d0f2d29da4b..9eafb42002d 100644 --- a/crypto/slh_dsa/slh_hash.c +++ b/crypto/slh_dsa/slh_hash.c @@ -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) diff --git a/crypto/slh_dsa/slh_hash.h b/crypto/slh_dsa/slh_hash.h index e226db73cca..b6e3de77dba 100644 --- a/crypto/slh_dsa/slh_hash.h +++ b/crypto/slh_dsa/slh_hash.h @@ -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 diff --git a/crypto/slh_dsa/slh_hypertree.c b/crypto/slh_dsa/slh_hypertree.c index a0be9d38c59..fa16d45b77f 100644 --- a/crypto/slh_dsa/slh_hypertree.c +++ b/crypto/slh_dsa/slh_hypertree.c @@ -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; diff --git a/crypto/slh_dsa/slh_wots.c b/crypto/slh_dsa/slh_wots.c index 1c7c26b60b7..9d3912623a9 100644 --- a/crypto/slh_dsa/slh_wots.c +++ b/crypto/slh_dsa/slh_wots.c @@ -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); } diff --git a/crypto/slh_dsa/slh_xmss.c b/crypto/slh_dsa/slh_xmss.c index c2501e23c8d..08f112f0d2f 100644 --- a/crypto/slh_dsa/slh_xmss.c +++ b/crypto/slh_dsa/slh_xmss.c @@ -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; } diff --git a/include/crypto/slh_dsa.h b/include/crypto/slh_dsa.h index ab9903a4916..14139508b4c 100644 --- a/include/crypto/slh_dsa.h +++ b/include/crypto/slh_dsa.h @@ -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); - -SLH_DSA_CTX *ossl_slh_dsa_ctx_new(const char *alg, - OSSL_LIB_CTX *lib_ctx, const char *propq); +__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); + +__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 */ diff --git a/test/recipes/30-test_slh_dsa.t b/test/recipes/30-test_slh_dsa.t index e0ade7cfe8f..6d61f5b050b 100644 --- a/test/recipes/30-test_slh_dsa.t +++ b/test/recipes/30-test_slh_dsa.t @@ -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"); } diff --git a/test/slh_dsa_test.c b/test/slh_dsa_test.c index 81b3733931b..15cdf8bea0b 100644 --- a/test/slh_dsa_test.c +++ b/test/slh_dsa_test.c @@ -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]);