Message ID | 20240531-b4-dynamic-uuid-v3-1-ca4a4865db00@linaro.org |
---|---|
State | New |
Headers | show |
Series | efi: CapsuleUpdate: support for dynamic UUIDs | expand |
Hi Caleb, [...] > +#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 *))) { > + unsigned int 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); uuid->time_hi_and_version is a u16 so this should be better off with a be16_to_cpu? OTOH your initial implementation was using clrsetbits_be16 and clrsetbits_8. Looking at what we have the same calls are done in gen_rand_uuid(). I think it's better if you make a function call for this and replace both your code and the gen_rand_uuid() instead of open coding that Thanks /Ilias > + 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 >
Hi Caleb, On Fri, 31 May 2024 at 07:50, Caleb Connolly <caleb.connolly@linaro.org> wrote: > > Add support for generating 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. > > Tests for this are added in an upcoming patch. > > 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(+) > > 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 Can you explain somewhere why the static inline is needed? > + > /** > * 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 spelling > + 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..2df0523e717f 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 *))) { > + unsigned int 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
On 5/31/24 15:50, Caleb Connolly wrote: > Add support for generating 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. > > Tests for this are added in an upcoming patch. > > 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(+) > > 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 It is unclear what this might mean. According to your description ... could be struct { void *data; u32 *length; } ...[] = { { &data_1, &length_1 }, { &data_2, &length_2 }, { NULL, NULL } } Do we have pointer to lengths? Which data type do lengths have? Please, provide an unambiguous description. An example would help. > + */ > +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 'select SHA1' might make things easier. > + help > + Enable the generation of version 5 UUIDs, these are determistic and %s/determistic/deterministic/ > + 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..2df0523e717f 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 *))) { > + unsigned int 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); Currently we have #define UUID_VERSION 0x4 Shouldn't we create #define UUID_VARIANT_4 0x4 - to be used in gen_rand_uuid() #define UUID_VARIANT_5 0x5 - to be used in gen_uuid_v5() instead? Please, provide a unit test for gen_uuid_v5() that passes multiple strings to gen_uuid_v5() and checks the hash. Best regards Heinrich > + 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]; >
Hi Simon, On 05/06/2024 04:13, Simon Glass wrote: > Hi Caleb, > > On Fri, 31 May 2024 at 07:50, Caleb Connolly <caleb.connolly@linaro.org> wrote: >> >> Add support for generating 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. >> >> Tests for this are added in an upcoming patch. >> >> 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(+) >> >> 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 > > Can you explain somewhere why the static inline is needed? The explicit "inline" certainly isn't, but this must be static because it's defined in a header, so we'd otherwise have multiple definitions for every #include. > >> + >> /** >> * 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 > > spelling > >> + 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..2df0523e717f 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 *))) { >> + unsigned int 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
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..2df0523e717f 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 *))) { + unsigned int 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];
Add support for generating 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. Tests for this are added in an upcoming patch. 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(+)