From 7e88ff9e9929040e92a0fa305686003cf370dbba Mon Sep 17 00:00:00 2001 From: Krzysztof Karas Date: Wed, 22 Feb 2023 12:48:55 +0100 Subject: [PATCH] uuid: add spdk_uuid_generate_sha1() Add implementation of uuid_generate_sha1() for systems that do not have this function in their system libraries. Use uuid_generate_sha1 from uuid.h inside a new function spdk_uuid_generate_sha1(). The reason for this addition is to prepare for UUID generation correction to conform to standards. First part of series addressing #2788. Change-Id: Ib357aa1ee832e886288d176d8a47efdaa326f537 Signed-off-by: Krzysztof Karas Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16414 Reviewed-by: Artur Paszkiewicz Reviewed-by: Konrad Sztyber Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot --- include/spdk/uuid.h | 13 ++++++++ lib/util/Makefile | 4 +++ lib/util/spdk_util.map | 1 + lib/util/uuid.c | 69 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/include/spdk/uuid.h b/include/spdk/uuid.h index d6352546d..7dead6f3e 100644 --- a/include/spdk/uuid.h +++ b/include/spdk/uuid.h @@ -65,6 +65,19 @@ int spdk_uuid_compare(const struct spdk_uuid *u1, const struct spdk_uuid *u2); */ void spdk_uuid_generate(struct spdk_uuid *uuid); +/** + * Generate a new UUID using SHA1 hash. + * + * \param[out] uuid User-provided UUID buffer to fill. + * \param ns_uuid Well-known namespace UUID for generated UUID. + * \param name Arbitrary, binary string. + * \param len Length of binary string. + * + * \return 0 on success, non-zero on failure. + */ +int spdk_uuid_generate_sha1(struct spdk_uuid *uuid, struct spdk_uuid *ns_uuid, const char *name, + size_t len); + /** * Copy a UUID. * diff --git a/lib/util/Makefile b/lib/util/Makefile index d05ff457b..8aaec6dfd 100644 --- a/lib/util/Makefile +++ b/lib/util/Makefile @@ -22,6 +22,10 @@ ifeq ($(CONFIG_ISAL), y) LOCAL_SYS_LIBS += -L$(ISAL_DIR)/.libs -lisal endif +ifeq ($(CONFIG_HAVE_UUID_GENERATE_SHA1), n) +LOCAL_SYS_LIBS += -lssl +endif + SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_util.map) include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/lib/util/spdk_util.map b/lib/util/spdk_util.map index 962c14b7a..60358e248 100644 --- a/lib/util/spdk_util.map +++ b/lib/util/spdk_util.map @@ -153,6 +153,7 @@ spdk_uuid_fmt_lower; spdk_uuid_compare; spdk_uuid_generate; + spdk_uuid_generate_sha1; spdk_uuid_copy; # public functions in fd_group.h diff --git a/lib/util/uuid.c b/lib/util/uuid.c index 5bf6a7e59..60b6e679f 100644 --- a/lib/util/uuid.c +++ b/lib/util/uuid.c @@ -4,6 +4,12 @@ */ #include "spdk/uuid.h" +#include "spdk/config.h" +#include "spdk/log.h" + +#ifndef SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 +#include +#endif /* SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 */ #ifndef __FreeBSD__ @@ -103,3 +109,66 @@ spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src) } #endif + +int +spdk_uuid_generate_sha1(struct spdk_uuid *uuid, struct spdk_uuid *ns_uuid, const char *name, + size_t len) +{ +#ifdef SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 + uuid_generate_sha1((void *)uuid, (void *)ns_uuid, name, len); + return 0; +#else + EVP_MD_CTX *mdctx; + const EVP_MD *md; + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len; + + md = EVP_sha1(); + assert(md != NULL); + + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + return -ENOMEM; + } + + if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + SPDK_ERRLOG("Could not initialize EVP digest!\n"); + goto err; + } + if (EVP_DigestUpdate(mdctx, ns_uuid, sizeof(struct spdk_uuid)) != 1) { + SPDK_ERRLOG("Could update EVP digest with namespace UUID!\n"); + goto err; + } + if (EVP_DigestUpdate(mdctx, name, len) != 1) { + SPDK_ERRLOG("Could update EVP digest with assigned name!\n"); + goto err; + } + if (EVP_DigestFinal_ex(mdctx, md_value, &md_len) != 1) { + SPDK_ERRLOG("Could not generate EVP digest!\n"); + goto err; + } + EVP_MD_CTX_free(mdctx); + + memcpy(uuid, md_value, 16); + /* This part mimics original uuid_generate_sha1() from libuuid/src/gen_uuid.c. + * The original uuid structure included from uuid.h looks like this: + * struct uuid { + * uint32_t time_low; + * uint16_t time_mid; + * uint16_t time_hi_and_version; + * uint16_t clock_seq; + * uint8_t node[6]; + * }; + * so uuid->u.raw[6] and uuid->u.raw[8] are time_hi_and_version and clock_seq respectively. + */ + uuid->u.raw[6] = (uuid->u.raw[6] & 0x0f) | 0x50; + uuid->u.raw[8] = (uuid->u.raw[8] & 0x3f) | 0x80; + + return 0; + +err: + EVP_MD_CTX_free(mdctx); + return -EINVAL; + +#endif /* SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 */ +}