diff options
-rw-r--r-- | include/uuid.h | 17 | ||||
-rw-r--r-- | lib/Kconfig | 1 | ||||
-rw-r--r-- | lib/uuid.c | 59 |
3 files changed, 68 insertions, 9 deletions
diff --git a/include/uuid.h b/include/uuid.h index f5a941250f4..1f4fa103b5e 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -11,6 +11,7 @@ #define __UUID_H__ #include <linux/bitops.h> +#include <linux/kconfig.h> /* * UUID - Universally Unique IDentifier - 128 bits unique number. @@ -46,8 +47,8 @@ * 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 @@ -143,6 +144,18 @@ void gen_rand_uuid(unsigned char *uuid_bin); */ 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 diff --git a/lib/Kconfig b/lib/Kconfig index 86919410cd7..1dd4f271595 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -73,6 +73,7 @@ config HAVE_PRIVATE_LIBGCC config LIB_UUID bool + select SHA1 config RANDOM_UUID bool "GPT Random UUID generation" diff --git a/lib/uuid.c b/lib/uuid.c index dfa2320ba26..c9dfdf007a1 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -22,6 +22,7 @@ #include <malloc.h> #include <dm/uclass.h> #include <rng.h> +#include <u-boot/sha1.h> int uuid_str_valid(const char *uuid) { @@ -369,6 +370,56 @@ 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) { @@ -395,13 +446,7 @@ void gen_rand_uuid(unsigned char *uuid_bin) 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); } |