diff mbox series

[v2,1/7] lib: uuid: add UUID v5 support

Message ID 20240529-b4-dynamic-uuid-v2-1-c26f31057bbe@linaro.org
State Superseded
Headers show
Series efi: CapsuleUpdate: support for dynamic UUIDs | expand

Commit Message

Caleb Connolly May 29, 2024, 2:48 p.m. UTC
Add support for generate version 5 UUIDs, these are determistic and work
by hashing a "namespace" UUID together with some unique data. One intended
usecase is to allow for dynamically generate payload UUIDs for UEFI
capsule updates, so that supported boards can have their own UUIDs
without needing to hardcode them.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
 include/uuid.h | 17 +++++++++++++++++
 lib/Kconfig    |  8 ++++++++
 lib/uuid.c     | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

Comments

Simon Glass May 29, 2024, 4:30 p.m. UTC | #1
Hi Caleb,

On Wed, 29 May 2024 at 08:49, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> Add support for generate version 5 UUIDs, these are determistic and work

spelling

> by hashing a "namespace" UUID together with some unique data. One intended
> usecase is to allow for dynamically generate payload UUIDs for UEFI
> capsule updates, so that supported boards can have their own UUIDs
> without needing to hardcode them.
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
>  include/uuid.h | 17 +++++++++++++++++
>  lib/Kconfig    |  8 ++++++++
>  lib/uuid.c     | 37 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 62 insertions(+)
>

Can you please mention the tests for this? I believe they are in your
last commit?

> diff --git a/include/uuid.h b/include/uuid.h
> index f5a941250f48..539affaa47b9 100644
> --- a/include/uuid.h
> +++ b/include/uuid.h
> @@ -10,8 +10,9 @@
>  #ifndef __UUID_H__
>  #define __UUID_H__
>
>  #include <linux/bitops.h>
> +#include <linux/kconfig.h>
>
>  /*
>   * UUID - Universally Unique IDentifier - 128 bits unique number.
>   *        There are 5 versions and one variant of UUID defined by RFC4122
> @@ -142,8 +143,24 @@ void gen_rand_uuid(unsigned char *uuid_bin);
>   * @param          - uuid output type: UUID - 0, GUID - 1
>   */
>  void gen_rand_uuid_str(char *uuid_str, int str_format);
>
> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
> +/**
> + * gen_uuid_v5() - generate UUID v5 from namespace and other seed data.
> + *
> + * @namespace:   pointer to UUID namespace salt
> + * @uuid:        pointer to allocated UUID output
> + * @...:         NULL terminated list of seed data as pairs of pointers
> + *               to data and their lengths
> + */
> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...);
> +#else
> +static inline void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
> +{
> +}
> +#endif
> +
>  /**
>   * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
>   * @uuid_str:  pointer to UUID string
>   * @uuid_bin:  pointer to allocated array for little endian output [16B]
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 189e6eb31aa1..2941532f25cf 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -80,8 +80,16 @@ config RANDOM_UUID
>         help
>           Enable the generation of partitions with random UUIDs if none
>           are provided.
>
> +config UUID_GEN_V5
> +       bool "Enable UUID version 5 generation"
> +       select LIB_UUID
> +       depends on SHA1
> +       help
> +         Enable the generation of version 5 UUIDs, these are determistic and
> +         generated from a namespace UUID, and a string (such as a board name).
> +
>  config SPL_LIB_UUID
>         depends on SPL
>         bool
>
> diff --git a/lib/uuid.c b/lib/uuid.c
> index dfa2320ba267..6ef006cca1da 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -21,8 +21,9 @@
>  #include <part_efi.h>
>  #include <malloc.h>
>  #include <dm/uclass.h>
>  #include <rng.h>
> +#include <u-boot/sha1.h>
>
>  int uuid_str_valid(const char *uuid)
>  {
>         int i, valid;
> @@ -368,8 +369,44 @@ void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
>                 }
>         }
>  }
>
> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)

Is this in a header file somewhere? It needs a function comment there.

> +{
> +       sha1_context ctx;
> +       va_list args;
> +       const uint8_t *data;
> +       uint8_t hash[SHA1_SUM_LEN];
> +       uint32_t tmp;
> +
> +       sha1_starts(&ctx);
> +       /* Hash the namespace UUID as salt */
> +       sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN);
> +       va_start(args, uuid);
> +
> +       while ((data = va_arg(args, const uint8_t *))) {
> +               size_t len = va_arg(args, size_t);
> +
> +               sha1_update(&ctx, data, len);
> +       }
> +
> +       va_end(args);
> +       sha1_finish(&ctx, hash);
> +
> +       /* Truncate the hash into output UUID, it is already big endian */
> +       memcpy(uuid, hash, sizeof(*uuid));
> +
> +       /* Configure variant/version bits */
> +       tmp = be32_to_cpu(uuid->time_hi_and_version);
> +       tmp = (tmp & ~UUID_VERSION_MASK) | (5 << UUID_VERSION_SHIFT);
> +       uuid->time_hi_and_version = cpu_to_be32(tmp);
> +
> +       uuid->clock_seq_hi_and_reserved &= UUID_VARIANT_MASK;
> +       uuid->clock_seq_hi_and_reserved |= UUID_VARIANT << UUID_VARIANT_SHIFT;
> +}
> +#endif
> +
>  #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
>  void gen_rand_uuid(unsigned char *uuid_bin)
>  {
>         u32 ptr[4];
>
> --
> 2.45.0
>

Regards,
Simon
Caleb Connolly May 29, 2024, 6:55 p.m. UTC | #2
Hi Simon,

On 29/05/2024 18:30, Simon Glass wrote:
> Hi Caleb,
> 
> On Wed, 29 May 2024 at 08:49, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>>
>> Add support for generate version 5 UUIDs, these are determistic and work
> 
> spelling

Thanks
> 
>> by hashing a "namespace" UUID together with some unique data. One intended
>> usecase is to allow for dynamically generate payload UUIDs for UEFI
>> capsule updates, so that supported boards can have their own UUIDs
>> without needing to hardcode them.
>>
>> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
>> ---
>>   include/uuid.h | 17 +++++++++++++++++
>>   lib/Kconfig    |  8 ++++++++
>>   lib/uuid.c     | 37 +++++++++++++++++++++++++++++++++++++
>>   3 files changed, 62 insertions(+)
>>
> 
> Can you please mention the tests for this? I believe they are in your
> last commit?

Yeah will do.
> 
>> diff --git a/include/uuid.h b/include/uuid.h
>> index f5a941250f48..539affaa47b9 100644
>> --- a/include/uuid.h
>> +++ b/include/uuid.h
>> @@ -10,8 +10,9 @@
>>   #ifndef __UUID_H__
>>   #define __UUID_H__
>>
>>   #include <linux/bitops.h>
>> +#include <linux/kconfig.h>
>>
>>   /*
>>    * UUID - Universally Unique IDentifier - 128 bits unique number.
>>    *        There are 5 versions and one variant of UUID defined by RFC4122
>> @@ -142,8 +143,24 @@ void gen_rand_uuid(unsigned char *uuid_bin);
>>    * @param          - uuid output type: UUID - 0, GUID - 1
>>    */
>>   void gen_rand_uuid_str(char *uuid_str, int str_format);
>>
>> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
>> +/**
>> + * gen_uuid_v5() - generate UUID v5 from namespace and other seed data.
>> + *
>> + * @namespace:   pointer to UUID namespace salt
>> + * @uuid:        pointer to allocated UUID output
>> + * @...:         NULL terminated list of seed data as pairs of pointers
>> + *               to data and their lengths
>> + */
>> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...);
>> +#else
>> +static inline void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
>> +{
>> +}
>> +#endif
>> +
[...]
>> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
>> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
> 
> Is this in a header file somewhere? It needs a function comment there.

Yes, see directly above where I add it to include/uuid.h

Kind regards,
> 
>> +{
>> +       sha1_context ctx;
>> +       va_list args;
>> +       const uint8_t *data;
>> +       uint8_t hash[SHA1_SUM_LEN];
>> +       uint32_t tmp;
>> +
>> +       sha1_starts(&ctx);
>> +       /* Hash the namespace UUID as salt */
>> +       sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN);
>> +       va_start(args, uuid);
>> +
>> +       while ((data = va_arg(args, const uint8_t *))) {
>> +               size_t len = va_arg(args, size_t);
>> +
>> +               sha1_update(&ctx, data, len);
>> +       }
>> +
>> +       va_end(args);
>> +       sha1_finish(&ctx, hash);
>> +
>> +       /* Truncate the hash into output UUID, it is already big endian */
>> +       memcpy(uuid, hash, sizeof(*uuid));
>> +
>> +       /* Configure variant/version bits */
>> +       tmp = be32_to_cpu(uuid->time_hi_and_version);
>> +       tmp = (tmp & ~UUID_VERSION_MASK) | (5 << UUID_VERSION_SHIFT);
>> +       uuid->time_hi_and_version = cpu_to_be32(tmp);
>> +
>> +       uuid->clock_seq_hi_and_reserved &= UUID_VARIANT_MASK;
>> +       uuid->clock_seq_hi_and_reserved |= UUID_VARIANT << UUID_VARIANT_SHIFT;
>> +}
>> +#endif
>> +
>>   #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
>>   void gen_rand_uuid(unsigned char *uuid_bin)
>>   {
>>          u32 ptr[4];
>>
>> --
>> 2.45.0
>>
> 
> Regards,
> Simon
Simon Glass May 29, 2024, 7:46 p.m. UTC | #3
Hi Caleb,

On Wed, 29 May 2024 at 12:55, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> Hi Simon,
>
> On 29/05/2024 18:30, Simon Glass wrote:
> > Hi Caleb,
> >
> > On Wed, 29 May 2024 at 08:49, Caleb Connolly <caleb.connolly@linaro.org> wrote:
> >>
> >> Add support for generate version 5 UUIDs, these are determistic and work
> >
> > spelling
>
> Thanks
> >
> >> by hashing a "namespace" UUID together with some unique data. One intended
> >> usecase is to allow for dynamically generate payload UUIDs for UEFI
> >> capsule updates, so that supported boards can have their own UUIDs
> >> without needing to hardcode them.
> >>
> >> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> >> ---
> >>   include/uuid.h | 17 +++++++++++++++++
> >>   lib/Kconfig    |  8 ++++++++
> >>   lib/uuid.c     | 37 +++++++++++++++++++++++++++++++++++++
> >>   3 files changed, 62 insertions(+)
> >>
> >
> > Can you please mention the tests for this? I believe they are in your
> > last commit?
>
> Yeah will do.
> >
> >> diff --git a/include/uuid.h b/include/uuid.h
> >> index f5a941250f48..539affaa47b9 100644
> >> --- a/include/uuid.h
> >> +++ b/include/uuid.h
> >> @@ -10,8 +10,9 @@
> >>   #ifndef __UUID_H__
> >>   #define __UUID_H__
> >>
> >>   #include <linux/bitops.h>
> >> +#include <linux/kconfig.h>
> >>
> >>   /*
> >>    * UUID - Universally Unique IDentifier - 128 bits unique number.
> >>    *        There are 5 versions and one variant of UUID defined by RFC4122
> >> @@ -142,8 +143,24 @@ void gen_rand_uuid(unsigned char *uuid_bin);
> >>    * @param          - uuid output type: UUID - 0, GUID - 1
> >>    */
> >>   void gen_rand_uuid_str(char *uuid_str, int str_format);
> >>
> >> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
> >> +/**
> >> + * gen_uuid_v5() - generate UUID v5 from namespace and other seed data.
> >> + *
> >> + * @namespace:   pointer to UUID namespace salt
> >> + * @uuid:        pointer to allocated UUID output
> >> + * @...:         NULL terminated list of seed data as pairs of pointers
> >> + *               to data and their lengths
> >> + */
> >> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...);
> >> +#else
> >> +static inline void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
> >> +{
> >> +}
> >> +#endif
> >> +
> [...]
> >> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
> >> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
> >
> > Is this in a header file somewhere? It needs a function comment there.
>
> Yes, see directly above where I add it to include/uuid.h

OK thanks. We are using a different format now - the old @param stuff
is in the past :-)

Regards,
Simon
Ilias Apalodimas May 30, 2024, 3:08 p.m. UTC | #4
Hi Caleb,


> diff --git a/lib/uuid.c b/lib/uuid.c
> index dfa2320ba267..6ef006cca1da 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -21,8 +21,9 @@
>  #include <part_efi.h>
>  #include <malloc.h>
>  #include <dm/uclass.h>
>  #include <rng.h>
> +#include <u-boot/sha1.h>
>
>  int uuid_str_valid(const char *uuid)
>  {
>         int i, valid;
> @@ -368,8 +369,44 @@ void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
>                 }
>         }
>  }
>
> +#if IS_ENABLED(CONFIG_UUID_GEN_V5)
> +void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
> +{
> +       sha1_context ctx;
> +       va_list args;
> +       const uint8_t *data;
> +       uint8_t hash[SHA1_SUM_LEN];
> +       uint32_t tmp;
> +
> +       sha1_starts(&ctx);
> +       /* Hash the namespace UUID as salt */
> +       sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN);
> +       va_start(args, uuid);
> +
> +       while ((data = va_arg(args, const uint8_t *))) {
> +               size_t len = va_arg(args, size_t);

sha1_update takes an unsigned int
so i'd prefer
unsigned int len = .... etc

> +
> +               sha1_update(&ctx, data, len);
> +       }
> +
> +       va_end(args);
> +       sha1_finish(&ctx, hash);
> +
> +       /* Truncate the hash into output UUID, it is already big endian */
> +       memcpy(uuid, hash, sizeof(*uuid));
> +
> +       /* Configure variant/version bits */
> +       tmp = be32_to_cpu(uuid->time_hi_and_version);
> +       tmp = (tmp & ~UUID_VERSION_MASK) | (5 << UUID_VERSION_SHIFT);
> +       uuid->time_hi_and_version = cpu_to_be32(tmp);
> +
> +       uuid->clock_seq_hi_and_reserved &= UUID_VARIANT_MASK;
> +       uuid->clock_seq_hi_and_reserved |= UUID_VARIANT << UUID_VARIANT_SHIFT;
> +}
> +#endif
> +
>  #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
>  void gen_rand_uuid(unsigned char *uuid_bin)
>  {
>         u32 ptr[4];
>
> --
> 2.45.0
>

Thanks
/Ilias
diff mbox series

Patch

diff --git a/include/uuid.h b/include/uuid.h
index f5a941250f48..539affaa47b9 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -10,8 +10,9 @@ 
 #ifndef __UUID_H__
 #define __UUID_H__
 
 #include <linux/bitops.h>
+#include <linux/kconfig.h>
 
 /*
  * UUID - Universally Unique IDentifier - 128 bits unique number.
  *        There are 5 versions and one variant of UUID defined by RFC4122
@@ -142,8 +143,24 @@  void gen_rand_uuid(unsigned char *uuid_bin);
  * @param          - uuid output type: UUID - 0, GUID - 1
  */
 void gen_rand_uuid_str(char *uuid_str, int str_format);
 
+#if IS_ENABLED(CONFIG_UUID_GEN_V5)
+/**
+ * gen_uuid_v5() - generate UUID v5 from namespace and other seed data.
+ *
+ * @namespace:   pointer to UUID namespace salt
+ * @uuid:        pointer to allocated UUID output
+ * @...:         NULL terminated list of seed data as pairs of pointers
+ *               to data and their lengths
+ */
+void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...);
+#else
+static inline void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
+{
+}
+#endif
+
 /**
  * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
  * @uuid_str:	pointer to UUID string
  * @uuid_bin:	pointer to allocated array for little endian output [16B]
diff --git a/lib/Kconfig b/lib/Kconfig
index 189e6eb31aa1..2941532f25cf 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -80,8 +80,16 @@  config RANDOM_UUID
 	help
 	  Enable the generation of partitions with random UUIDs if none
 	  are provided.
 
+config UUID_GEN_V5
+	bool "Enable UUID version 5 generation"
+	select LIB_UUID
+	depends on SHA1
+	help
+	  Enable the generation of version 5 UUIDs, these are determistic and
+	  generated from a namespace UUID, and a string (such as a board name).
+
 config SPL_LIB_UUID
 	depends on SPL
 	bool
 
diff --git a/lib/uuid.c b/lib/uuid.c
index dfa2320ba267..6ef006cca1da 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -21,8 +21,9 @@ 
 #include <part_efi.h>
 #include <malloc.h>
 #include <dm/uclass.h>
 #include <rng.h>
+#include <u-boot/sha1.h>
 
 int uuid_str_valid(const char *uuid)
 {
 	int i, valid;
@@ -368,8 +369,44 @@  void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
 		}
 	}
 }
 
+#if IS_ENABLED(CONFIG_UUID_GEN_V5)
+void gen_uuid_v5(const struct uuid *namespace, struct uuid *uuid, ...)
+{
+	sha1_context ctx;
+	va_list args;
+	const uint8_t *data;
+	uint8_t hash[SHA1_SUM_LEN];
+	uint32_t tmp;
+
+	sha1_starts(&ctx);
+	/* Hash the namespace UUID as salt */
+	sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN);
+	va_start(args, uuid);
+
+	while ((data = va_arg(args, const uint8_t *))) {
+		size_t len = va_arg(args, size_t);
+
+		sha1_update(&ctx, data, len);
+	}
+
+	va_end(args);
+	sha1_finish(&ctx, hash);
+
+	/* Truncate the hash into output UUID, it is already big endian */
+	memcpy(uuid, hash, sizeof(*uuid));
+
+	/* Configure variant/version bits */
+	tmp = be32_to_cpu(uuid->time_hi_and_version);
+	tmp = (tmp & ~UUID_VERSION_MASK) | (5 << UUID_VERSION_SHIFT);
+	uuid->time_hi_and_version = cpu_to_be32(tmp);
+
+	uuid->clock_seq_hi_and_reserved &= UUID_VARIANT_MASK;
+	uuid->clock_seq_hi_and_reserved |= UUID_VARIANT << UUID_VARIANT_SHIFT;
+}
+#endif
+
 #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
 void gen_rand_uuid(unsigned char *uuid_bin)
 {
 	u32 ptr[4];