Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uuid: Add Universally Unique Identifier (UUID) utilities #77884

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/services/misc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,16 @@ this API is limited to creating the simplistic tokens needed to
authenticate with the Google Core IoT infrastructure.

.. doxygengroup:: jwt

Identifier APIs
***************

UUID
====

Universally Unique Identifiers (UUID), also known as Globally Unique
IDentifiers (GUIDs) are an open, industry standard [RFC
9562](https://tools.ietf.org/html/rfc9562) 128 bits long identifiers
intended to guarantee uniqueness across space and time.

.. doxygengroup:: uuid
4 changes: 3 additions & 1 deletion include/zephyr/fs/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <stdint.h>

#include <zephyr/sys/uuid.h>

/** @brief Configuration used to format ext2 file system.
*
* If a field is set to 0 then default value is used.
Expand All @@ -27,7 +29,7 @@ struct ext2_cfg {
uint32_t block_size;
uint32_t fs_size; /* Number of blocks that we want to take. */
uint32_t bytes_per_inode;
uint8_t uuid[16];
struct uuid uuid;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an API change, isn't it?

If it is a stable API, then it needs to follow https://docs.zephyrproject.org/latest/develop/api/api_lifecycle.html#introducing-breaking-api-changes

An alternative which is a bit dirty would be to do

Suggested change
struct uuid uuid;
union {
uint8_t uuid[16];
struct uuid uuid;
};

So that it's not breaking. I'll leave this up to the maintainer(s) of the fs

uint8_t volume_name[17]; /* If first byte is 0 then name ext2" is given. */
bool set_uuid;
};
Expand Down
168 changes: 168 additions & 0 deletions include/zephyr/sys/uuid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2024, SECO Mind Srl
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_SYS_UUID_H_
#define ZEPHYR_INCLUDE_SYS_UUID_H_

/**
* @file
*
* @brief Utility functions for the generation and parsing of Universal Unique Identifier.
* @details This driver is compliant with RFC9562: https://datatracker.ietf.org/doc/rfc9562/
*/

#include <zephyr/kernel.h>
#include <zephyr/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @defgroup uuid UUID
* @since 4.0
* @version 0.1.0
* @ingroup utilities
* @{
*/

/** @brief Number of bytes in the binary representation of a UUID. */
#define UUID_SIZE 16U

/** @brief Length of the UUID canonical string representation, including the NULL terminator. */
#define UUID_STR_LEN 37U

/** @brief Length of the UUID base64 string representation, including the NULL terminator. */
#define UUID_BASE64_LEN 25U

/**
* @brief Length of the UUID base64 URL and filename safe string representation, including the
* NULL terminator.
*/
#define UUID_BASE64URL_LEN 23U

/** @brief Binary representation of a UUID. */
struct uuid {
/** @cond INTERNAL_HIDDEN */
uint8_t val[UUID_SIZE];
/** @endcond */
};

/**
* @brief Generate a UUIDv4.
*
* @param out The UUID where the result will be written.
*
* @retval 0 The UUID has been correctly generated and stored in @p out
* @retval -EINVAL @p out is not acceptable
*/
int uuid_generate_v4(struct uuid *out);

/**
* @brief Generate a UUIDv5.
*
* @details This function computes a deterministic UUID starting from a namespace UUID and binary
* data.
*
* @param[in] namespace The string representation of an UUID to be used as namespace.
* @param[in] data A pointer to the data that will be hashed to produce the UUID.
* @param[in] data_size The size of the data buffer.
* @param[out] out The UUID where the result will be written.
*
* @retval 0 The UUID has been correctly generated and stored in @p out
* @retval -EINVAL @p out is not acceptable
* @retval -ENOMEM Memory allocation failed
* @retval -ENOTSUP mbedTLS returned an unrecognized error
*/
int uuid_generate_v5(struct uuid namespace, const void *data, size_t data_size, struct uuid *out);

/**
* @brief Copy an UUID into another UUID.
*
* @param dst Destination for the copy.
* @param src Source for the copy.
*
* @retval 0 The UUID has been correctly copied in @p dst
* @retval -EINVAL @p dst is not acceptable
*/
int uuid_copy(struct uuid *dst, struct uuid src);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I've noticed now is that you more often than not pass by value (e.g. struct uuid src) rather than by reference (struct uuid *dst).

Is that something you have considered? Since the struct is 16 octets, that's quite a lot of data being passed around compared to a pointer (typically 4 octets).

Should the API primarily use pass by reference instead of value?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most functions you also have (src, dst) (e.g. uuid_from_buffer(const uint8_t data[UUID_SIZE], struct uuid *out); , but this functions does (dst, src).

Consider making them consistent


/**
* @brief Create a uuid_t from a binary (big-endian) formatted UUID.
*
* @param data The buffer where the binary UUID is stored in a big-endian order.
Thalley marked this conversation as resolved.
Show resolved Hide resolved
* @param out The UUID where the result will be written.
*
* @retval 0 The UUID has been correctly parsed and stored in @p out
* @retval -EINVAL @p data or @p out are not acceptable
*/
int uuid_from_buffer(const uint8_t data[UUID_SIZE], struct uuid *out);

/**
* @brief Parse a UUID from its canonical (RFC9562) string representation.
*
* @param input A pointer to the string to be parsed.
* @param out The UUID where the result will be written.
*
* @retval 0 The UUID has been correctly parsed and stored in @p out
* @retval -EINVAL @p input or @p out are not acceptable
*/
int uuid_from_string(const char input[UUID_STR_LEN], struct uuid *out);

/**
* @brief Create a uuid_t from a binary (big-endian) formatted UUID.
*
* @param input The input UUID to store in the buffer.
* @param buff The buffer where the binary UUID is stored in a big-endian order.
*
* @retval 0 The UUID has been correctly parsed and stored in @p buff
* @retval -EINVAL @p buff is not acceptable
*/
int uuid_to_buffer(struct uuid input, uint8_t buff[UUID_SIZE]);

/**
* @brief Convert a UUID to its canonical (RFC9562) string representation.
*
* @param input The UUID to convert to string.
* @param out A pointer to a previously allocated buffer where the result will be written.
*
* @retval 0 The UUID has been converted and written in @p out
* @retval -EINVAL @p out is not acceptable
*/
int uuid_to_string(struct uuid input, char out[UUID_STR_LEN]);

/**
* @brief Convert a UUID to its base 64 (RFC 3548, RFC 4648) string representation.
*
* @param input The UUID to convert to string.
* @param out A pointer to a previously allocated buffer where the result will be written.
*
* @retval 0 The UUID has been converted and written in @p out
* @retval -EINVAL @p out is not acceptable
*/
int uuid_to_base64(struct uuid input, char out[UUID_BASE64_LEN]);

/**
* @brief Convert a UUID to its base 64 (RFC 4648 sec. 5) URL and filename safe string
* representation.
*
* @param input The UUID to convert to string.
* @param out A pointer to a previously allocated buffer where the result will be written.
*
* @retval 0 The UUID has been converted and written in @p out
* @retval -EINVAL @p out is not acceptable
*/
int uuid_to_base64url(struct uuid input, char out[UUID_BASE64URL_LEN]);

/**
* @}
*/

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_SYS_UUID_H_ */
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ add_subdirectory(utils)
add_subdirectory_ifdef(CONFIG_SMF smf)
add_subdirectory_ifdef(CONFIG_OPENAMP open-amp)
add_subdirectory_ifdef(CONFIG_ACPI acpi)
add_subdirectory(uuid)
2 changes: 2 additions & 0 deletions lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ source "lib/acpi/Kconfig"
source "lib/runtime/Kconfig"

source "lib/utils/Kconfig"

source "lib/uuid/Kconfig"
endmenu
5 changes: 5 additions & 0 deletions lib/uuid/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_sources_ifdef(CONFIG_UUID uuid.c)

zephyr_library_link_libraries_ifdef(CONFIG_UUID_V5 mbedTLS)
40 changes: 40 additions & 0 deletions lib/uuid/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright (c) 2024, SECO Mind Srl
#
# SPDX-License-Identifier: Apache-2.0

menu "Universally Unique Identifier (UUID)"

config UUID
bool "UUID support [EXPERIMENTAL]"
select EXPERIMENTAL
help
Enable use of the UUID library.

config UUID_V4
bool "UUID version 4 generation support [EXPERIMENTAL]"
select EXPERIMENTAL
depends on UUID
depends on ENTROPY_GENERATOR
Thalley marked this conversation as resolved.
Show resolved Hide resolved
help
Enable generation of UUID v4.

config UUID_V5
bool "UUID version 5 generation support [EXPERIMENTAL]"
select EXPERIMENTAL
depends on UUID
depends on MBEDTLS
depends on MBEDTLS_MD
depends on MBEDTLS_SHA1
help
Enable generation of UUID v5.

config UUID_BASE64
bool "UUID Base64 support [EXPERIMENTAL]"
select EXPERIMENTAL
depends on UUID
depends on BASE64
help
Enable conversion functions to write UUIDs in base 64
formats.

endmenu
Loading
Loading