From: slontis Date: Thu, 23 Jan 2025 03:51:42 +0000 (+1100) Subject: SLH-DSA More fixups X-Git-Tag: openssl-3.5.0-alpha1~180 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f0a836abda4d391249466ecfe5ca600b92914ea;p=thirdparty%2Fopenssl.git SLH-DSA More fixups Also added slh_dsa_key_dup() 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_adrs.c b/crypto/slh_dsa/slh_adrs.c index 32b9863d2fe..d03b442fd54 100644 --- a/crypto/slh_dsa/slh_adrs.c +++ b/crypto/slh_dsa/slh_adrs.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ #include +#include #include "slh_adrs.h" /* See FIPS 205 - Section 4.3 Table 1 Uncompressed Addresses */ @@ -60,37 +61,13 @@ static OSSL_SLH_ADRS_FUNC_set_hash_address slh_adrsc_set_hash_address; static OSSL_SLH_ADRS_FUNC_zero slh_adrsc_zero; static OSSL_SLH_ADRS_FUNC_copy slh_adrsc_copy; -/* Variants of the FIPS 205 Algorithm 3 toByte(x, n) for 32 and 64 bit integers */ - -/* Convert a 32 bit value |in| to 4 bytes |out| in big endian format */ -static ossl_inline void U32TOSTR(unsigned char *out, uint32_t in) -{ - out[3] = (unsigned char)((in) & 0xff); - out[2] = (unsigned char)((in >> 8) & 0xff); - out[1] = (unsigned char)((in >> 16) & 0xff); - out[0] = (unsigned char)((in >> 24) & 0xff); -} - -/* Convert a 64 bit value |in| to 8 bytes |out| in big endian format */ -static ossl_inline void U64TOSTR(unsigned char *out, uint64_t in) -{ - out[7] = (unsigned char)((in) & 0xff); - out[6] = (unsigned char)((in >> 8) & 0xff); - out[5] = (unsigned char)((in >> 16) & 0xff); - out[4] = (unsigned char)((in >> 24) & 0xff); - out[3] = (unsigned char)((in >> 32) & 0xff); - out[2] = (unsigned char)((in >> 40) & 0xff); - out[1] = (unsigned char)((in >> 48) & 0xff); - out[0] = (unsigned char)((in >> 56) & 0xff); -} - /* * The non compressed versions of the ADRS functions use 32 bytes * This is only used by SHAKE. */ static void slh_adrs_set_layer_address(SLH_ADRS adrs, uint32_t layer) { - U32TOSTR(adrs + SLH_ADRS_OFF_LAYER_ADR, layer); + OPENSSL_store_u32_be(adrs + SLH_ADRS_OFF_LAYER_ADR, layer); } static void slh_adrs_set_tree_address(SLH_ADRS adrs, uint64_t address) { @@ -100,16 +77,16 @@ static void slh_adrs_set_tree_address(SLH_ADRS adrs, uint64_t address) * first 4 of the 12 bytes will be zeros. This assumes that the 4 bytes * are zero initially. */ - U64TOSTR(adrs + SLH_ADRS_OFF_TREE_ADR + 4, address); + OPENSSL_store_u64_be(adrs + SLH_ADRS_OFF_TREE_ADR + 4, address); } static void slh_adrs_set_type_and_clear(SLH_ADRS adrs, uint32_t type) { - U32TOSTR(adrs + SLH_ADRS_OFF_TYPE, type); + OPENSSL_store_u32_be(adrs + SLH_ADRS_OFF_TYPE, type); memset(adrs + SLH_ADRS_OFF_TYPE + SLH_ADRS_SIZE_TYPE, 0, SLH_ADRS_SIZE_TYPECLEAR); } static void slh_adrs_set_keypair_address(SLH_ADRS adrs, uint32_t in) { - U32TOSTR(adrs + SLH_ADRS_OFF_KEYPAIR_ADDR, in); + OPENSSL_store_u32_be(adrs + SLH_ADRS_OFF_KEYPAIR_ADDR, in); } static void slh_adrs_copy_keypair_address(SLH_ADRS dst, const SLH_ADRS src) { @@ -118,11 +95,11 @@ static void slh_adrs_copy_keypair_address(SLH_ADRS dst, const SLH_ADRS src) } static void slh_adrs_set_chain_address(SLH_ADRS adrs, uint32_t in) { - U32TOSTR(adrs + SLH_ADRS_OFF_CHAIN_ADDR, in); + OPENSSL_store_u32_be(adrs + SLH_ADRS_OFF_CHAIN_ADDR, in); } static void slh_adrs_set_hash_address(SLH_ADRS adrs, uint32_t in) { - U32TOSTR(adrs + SLH_ADRS_OFF_HASH_ADDR, in); + OPENSSL_store_u32_be(adrs + SLH_ADRS_OFF_HASH_ADDR, in); } static void slh_adrs_zero(SLH_ADRS adrs) { @@ -140,7 +117,7 @@ static void slh_adrsc_set_layer_address(SLH_ADRS adrsc, uint32_t layer) } static void slh_adrsc_set_tree_address(SLH_ADRS adrsc, uint64_t in) { - U64TOSTR(adrsc + SLH_ADRSC_OFF_TREE_ADR, in); + OPENSSL_store_u64_be(adrsc + SLH_ADRSC_OFF_TREE_ADR, in); } static void slh_adrsc_set_type_and_clear(SLH_ADRS adrsc, uint32_t type) { @@ -149,7 +126,7 @@ static void slh_adrsc_set_type_and_clear(SLH_ADRS adrsc, uint32_t type) } static void slh_adrsc_set_keypair_address(SLH_ADRS adrsc, uint32_t in) { - U32TOSTR(adrsc + SLH_ADRSC_OFF_KEYPAIR_ADDR, in); + OPENSSL_store_u32_be(adrsc + SLH_ADRSC_OFF_KEYPAIR_ADDR, in); } static void slh_adrsc_copy_keypair_address(SLH_ADRS dst, const SLH_ADRS src) { @@ -158,11 +135,11 @@ static void slh_adrsc_copy_keypair_address(SLH_ADRS dst, const SLH_ADRS src) } static void slh_adrsc_set_chain_address(SLH_ADRS adrsc, uint32_t in) { - U32TOSTR(adrsc + SLH_ADRSC_OFF_CHAIN_ADDR, in); + OPENSSL_store_u32_be(adrsc + SLH_ADRSC_OFF_CHAIN_ADDR, in); } static void slh_adrsc_set_hash_address(SLH_ADRS adrsc, uint32_t in) { - U32TOSTR(adrsc + SLH_ADRSC_OFF_HASH_ADDR, in); + OPENSSL_store_u32_be(adrsc + SLH_ADRSC_OFF_HASH_ADDR, in); } static void slh_adrsc_zero(SLH_ADRS adrsc) { diff --git a/crypto/slh_dsa/slh_dsa.c b/crypto/slh_dsa/slh_dsa.c index ad3855b0ee9..560b7f32df3 100644 --- a/crypto/slh_dsa/slh_dsa.c +++ b/crypto/slh_dsa/slh_dsa.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "slh_dsa_local.h" #include "slh_dsa_key.h" @@ -72,8 +74,10 @@ static int slh_sign_internal(SLH_DSA_HASH_CTX *hctx, if (sig_size < sig_len_expected) return 0; /* Exit if private key is not set */ - if (priv->has_priv == 0) + if (priv->has_priv == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return 0; + } if (!WPACKET_init_static_len(wpkt, sig, sig_len_expected, 0)) return 0; @@ -160,8 +164,10 @@ static int slh_verify_internal(SLH_DSA_HASH_CTX *hctx, uint32_t leaf_id; /* Exit if public key is not set */ - if (pub->pub == NULL) + if (pub->pub == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return 0; + } /* Exit if signature is invalid size */ if (sig_len != params->sig_len @@ -306,6 +312,7 @@ int ossl_slh_dsa_verify(SLH_DSA_HASH_CTX *slh_ctx, /* See FIPS 205 Algorithm 2 toInt(X, n) */ static uint64_t bytes_to_u64_be(const uint8_t *in, size_t in_len) { + size_t i; uint64_t total = 0; diff --git a/crypto/slh_dsa/slh_dsa_key.c b/crypto/slh_dsa/slh_dsa_key.c index 0fc157d566a..4fb6a495a9c 100644 --- a/crypto/slh_dsa/slh_dsa_key.c +++ b/crypto/slh_dsa/slh_dsa_key.c @@ -65,6 +65,16 @@ static int slh_dsa_key_hash_init(SLH_DSA_KEY *key) return 0; } +static void slh_dsa_key_hash_dup(SLH_DSA_KEY *dst, const SLH_DSA_KEY *src) +{ + if (src->md_big != NULL && src->md_big != src->md) + EVP_MD_up_ref(src->md_big); + if (src->md != NULL) + EVP_MD_up_ref(src->md); + if (src->hmac != NULL) + EVP_MAC_up_ref(src->hmac); +} + /** * @brief Create a new SLH_DSA_KEY object * @@ -113,6 +123,47 @@ void ossl_slh_dsa_key_free(SLH_DSA_KEY *key) OPENSSL_free(key); } +/** + * @brief Duplicate a key + * + * @param src A SLH_DSA_KEY object to copy + * @param selection to select public and/or private components. Selecting the + * private key will also select the public key + * @returns The duplicated key, or NULL on failure. + */ +SLH_DSA_KEY *ossl_slh_dsa_key_dup(const SLH_DSA_KEY *src, int selection) +{ + SLH_DSA_KEY *ret = NULL; + + if (src == NULL) + return NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret != NULL) { + *ret = *src; /* this copies everything including the keydata in priv[] */ + ret->propq = NULL; + ret->pub = NULL; + ret->has_priv = 0; + slh_dsa_key_hash_dup(ret, src); + if (src->propq != NULL) { + ret->propq = OPENSSL_strdup(src->propq); + if (ret->propq == NULL) + goto err; + } + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + /* The public components are present if the private key is present */ + if (src->pub != NULL) + ret->pub = SLH_DSA_PUB(ret); + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ret->has_priv = src->has_priv; + } + } + return ret; + err: + ossl_slh_dsa_key_free(ret); + return NULL; +} + /** * @brief Are 2 keys equal? * @@ -126,37 +177,32 @@ void ossl_slh_dsa_key_free(SLH_DSA_KEY *key) int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2, int selection) { - int ok = 1; + int key_checked = 0; + + /* The parameter sets must match - i.e. The same algorithm name */ + if (key1->params != key2->params) + return 0; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - /* The parameter sets must match - i.e. The same algorithm name */ - if (key1->params != key2->params) - return 0; - /* - * If both keys dont have a public key return 1 - * If only one of the keys has a public key return 0. - */ - if (key1->pub == NULL) - return (key2->pub == NULL); - else if (key2->pub == NULL) - return 0; - /* - * Gets here if both keys have a public key - * Since the public key always exists with the private key, check either - * that the private key matches (which includes the public key) OR - * check that the public key matches depending on the selection. - */ - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - ok = ok && (key1->has_priv == key2->has_priv); - if (key1->has_priv) - ok = ok && (memcmp(key1->priv, key2->priv, - ossl_slh_dsa_key_get_priv_len(key1)) == 0); - } else { - ok = ok && (memcmp(key1->pub, key2->pub, - ossl_slh_dsa_key_get_pub_len(key1)) == 0); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + if (key1->pub != NULL && key2->pub != NULL) { + if (memcmp(key1->pub, key2->pub, key1->params->pk_len) != 0) + return 0; + key_checked = 1; + } + } + if (!key_checked + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + if (key1->has_priv && key2->has_priv) { + if (memcmp(key1->priv, key2->priv, + key1->params->pk_len) != 0) + return 0; + key_checked = 1; + } } + return key_checked; } - return ok; + return 1; } int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection) diff --git a/crypto/slh_dsa/slh_hash.h b/crypto/slh_dsa/slh_hash.h index 097b8745e16..bcb3cbaca68 100644 --- a/crypto/slh_dsa/slh_hash.h +++ b/crypto/slh_dsa/slh_hash.h @@ -16,7 +16,7 @@ # include "internal/packet.h" # define SLH_HASH_FUNC_DECLARE(ctx, hashf) \ - const SLH_HASH_FUNC *hashf = ctx->hash_func; \ + const SLH_HASH_FUNC *hashf = ctx->hash_func \ # define SLH_HASH_FN_DECLARE(hashf, t) OSSL_SLH_HASHFUNC_##t * t = hashf->t diff --git a/crypto/slh_dsa/slh_wots.c b/crypto/slh_dsa/slh_wots.c index 829e8d341ea..7eb60b0c633 100644 --- a/crypto/slh_dsa/slh_wots.c +++ b/crypto/slh_dsa/slh_wots.c @@ -26,7 +26,6 @@ /* * @brief Convert a byte array to a byte array of (4 bit) nibbles * This is a Variant of the FIPS 205 Algorithm 4 base_2^b function. - * It assumes that |in_len| is an even number and b is 4 bits. * * @param in A byte message to convert * @param in_len The size of |in|. @@ -37,8 +36,6 @@ static ossl_inline void slh_bytes_to_nibbles(const uint8_t *in, size_t in_len, { size_t consumed = 0; - assert((in_len & 1) == 0); - for (consumed = 0; consumed < in_len; consumed++) { *out++ = (*in >> NIBBLE_SHIFT); *out++ = (*in++ & NIBBLE_MASK); diff --git a/include/crypto/slh_dsa.h b/include/crypto/slh_dsa.h index c6f1eb8c82f..15ea92f99d5 100644 --- a/include/crypto/slh_dsa.h +++ b/include/crypto/slh_dsa.h @@ -25,6 +25,7 @@ typedef struct slh_dsa_key_st SLH_DSA_KEY; __owur SLH_DSA_KEY *ossl_slh_dsa_key_new(OSSL_LIB_CTX *libctx, const char *propq, const char *alg); void ossl_slh_dsa_key_free(SLH_DSA_KEY *key); +__owur SLH_DSA_KEY *ossl_slh_dsa_key_dup(const SLH_DSA_KEY *src, int selection); __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);