]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
SLH-DSA More fixups
authorslontis <shane.lontis@oracle.com>
Thu, 23 Jan 2025 03:51:42 +0000 (14:51 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Feb 2025 09:17:29 +0000 (10:17 +0100)
Also added slh_dsa_key_dup()

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)

crypto/slh_dsa/slh_adrs.c
crypto/slh_dsa/slh_dsa.c
crypto/slh_dsa/slh_dsa_key.c
crypto/slh_dsa/slh_hash.h
crypto/slh_dsa/slh_wots.c
include/crypto/slh_dsa.h

index 32b9863d2feda6e0b982968c02081d1f06138ccd..d03b442fd54d70f13db51789d90dd0228f06f67f 100644 (file)
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 #include <string.h>
+#include <openssl/byteorder.h>
 #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)
 {
index ad3855b0ee93cd40629e7834bf338d79654809b9..560b7f32df3375341206df552c339a65486d5706 100644 (file)
@@ -9,6 +9,8 @@
 #include <assert.h>
 #include <stddef.h>
 #include <string.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
 #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;
 
index 0fc157d566ae897c3a8b2d89e4629b0a05081191..4fb6a495a9cb24e454f6bf3aee871fb1b20d009a 100644 (file)
@@ -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)
index 097b8745e16810e0f1c59d41d5794a3041690413..bcb3cbaca68dad922c582a038f88fe9b8869a5b2 100644 (file)
@@ -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
 
index 829e8d341ea73a749ee4ad154a414214c943d41a..7eb60b0c63359924f2307499194b378ec58d1fda 100644 (file)
@@ -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);
index c6f1eb8c82ffecba2b454cd8e9c9d1d0725c3ff8..15ea92f99d5bc416d732b73caa683779b8c69c52 100644 (file)
@@ -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);