* 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 */
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)
{
* 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)
{
}
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)
{
}
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)
{
}
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)
{
}
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)
{
#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"
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;
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
/* 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;
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
*
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?
*
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)
# 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
/*
* @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|.
{
size_t consumed = 0;
- assert((in_len & 1) == 0);
-
for (consumed = 0; consumed < in_len; consumed++) {
*out++ = (*in >> NIBBLE_SHIFT);
*out++ = (*in++ & NIBBLE_MASK);
__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);