On Fri, 9 Aug 2024 at 03:56, Caleb Connolly <[email protected]> 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. > > In addition, move the common bit twiddling code from gen_ran_uuid into a > separate function and rewrite it not to use clrsetbits (which is not > available when building as part of host tools). > > Tests for this are added in an upcoming patch. > > Signed-off-by: Caleb Connolly <[email protected]> > --- > include/uuid.h | 17 +++++++++++++++-- > lib/Kconfig | 1 + > lib/uuid.c | 58 > +++++++++++++++++++++++++++++++++++++++++++++++++++------- > 3 files changed, 67 insertions(+), 9 deletions(-) > > diff --git a/include/uuid.h b/include/uuid.h > index f5a941250f48..1f4fa103b5e9 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 > @@ -45,10 +46,10 @@ > * where x is a hexadecimal character. Fields are separated by '-'s. > * When converting to a binary UUID, le means the field should be converted > * to little endian and be means it should be converted to big endian. > * > - * UUID is also used as GUID (Globally Unique Identifier) with the same > binary > - * format but it differs in string format like below. > + * UUID is also used as GUID (Globally Unique Identifier) with the same > format > + * but with some fields stored in little endian. > * > * GUID: > * 0 9 14 19 24 > * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > @@ -142,8 +143,20 @@ 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); > > +struct efi_guid; > + > +/** > + * gen_v5_guid() - generate little endian v5 GUID from namespace and other > seed data. > + * > + * @namespace: pointer to UUID namespace salt > + * @guid: pointer to allocated GUID output > + * @...: NULL terminated list of seed data as pairs of pointers > + * to data and their lengths > + */ > +void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...); > + > /** > * 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 2059219a1207..5a48c016d2c5 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -72,8 +72,9 @@ config HAVE_PRIVATE_LIBGCC > bool > > config LIB_UUID > bool > + select SHA1 > > config RANDOM_UUID > bool "GPT Random UUID generation" > select LIB_UUID > diff --git a/lib/uuid.c b/lib/uuid.c > index dfa2320ba267..24b5881600fd 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,57 @@ void uuid_bin_to_str(const unsigned char *uuid_bin, char > *uuid_str, > } > } > } > > +static void configure_uuid(struct uuid *uuid, unsigned char version) > +{ > + uint16_t tmp; > + > + /* Configure variant/version bits */ > + tmp = be16_to_cpu(uuid->time_hi_and_version); > + tmp = (tmp & ~UUID_VERSION_MASK) | (version << UUID_VERSION_SHIFT); > + uuid->time_hi_and_version = cpu_to_be16(tmp); > + > + uuid->clock_seq_hi_and_reserved &= ~UUID_VARIANT_MASK; > + uuid->clock_seq_hi_and_reserved |= (UUID_VARIANT << > UUID_VARIANT_SHIFT); > +} > + > +void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...) > +{ > + sha1_context ctx; > + va_list args; > + const uint8_t *data; > + uint32_t *tmp32; > + uint16_t *tmp16; > + uint8_t hash[SHA1_SUM_LEN]; > + > + sha1_starts(&ctx); > + /* Hash the namespace UUID as salt */ > + sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN); > + va_start(args, guid); > + > + 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(guid, hash, sizeof(*guid)); > + > + configure_uuid((struct uuid *)guid, 5); > + > + /* Make little endian */ > + tmp32 = (uint32_t *)&guid->b[0]; > + *tmp32 = cpu_to_le32(be32_to_cpu(*tmp32)); > + tmp16 = (uint16_t *)&guid->b[4]; > + *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16)); > + tmp16 = (uint16_t *)&guid->b[6]; > + *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16)); > +} > + > #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID) > void gen_rand_uuid(unsigned char *uuid_bin) > { > u32 ptr[4]; > @@ -394,15 +444,9 @@ void gen_rand_uuid(unsigned char *uuid_bin) > /* Set all fields randomly */ > for (i = 0; i < 4; i++) > ptr[i] = rand(); > > - clrsetbits_be16(&uuid->time_hi_and_version, > - UUID_VERSION_MASK, > - UUID_VERSION << UUID_VERSION_SHIFT); > - > - clrsetbits_8(&uuid->clock_seq_hi_and_reserved, > - UUID_VARIANT_MASK, > - UUID_VARIANT << UUID_VARIANT_SHIFT); > + configure_uuid(uuid, UUID_VERSION); > > memcpy(uuid_bin, uuid, 16); > } > > > -- > 2.46.0 >
The series doesn't apply over -next or -master. Can you rebase and resend so I can run the CI? Also, checkpatch reports some minor issues, make sure you address those on the rebase Reviewed-by: Ilias Apalodimas <[email protected]>

