Extend uuid component for FWU

This change extends uuid operations to better meet FWU and
GPT based configuration requirements. The change adds more
explicit support for the little-endian octet representation.
Although the little-endian octet order is not what's specified
in RFC4122, it is used by the UEFI specification which covers
disk and partition UUIDs. Because the acronym 'guid' is used
within the UEFI spec, the little-endian representation is
referred to as 'guid' in the names of uuid functions to
distinguish them from functions that assume standard octet
order.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ie3d1f3d9fe44ad80c84e541c69fdd2cbfdacd128
diff --git a/components/common/uuid/uuid.c b/components/common/uuid/uuid.c
index 6f8b2ec..7bf33ed 100644
--- a/components/common/uuid/uuid.c
+++ b/components/common/uuid/uuid.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include "uuid.h"
+#include <assert.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -33,9 +34,13 @@
 size_t uuid_is_valid(const char *canonical_form)
 {
 	size_t valid_chars = 0;
-	size_t input_len = strlen(canonical_form);
 
-	if (input_len >= UUID_CANONICAL_FORM_LEN) {
+	/* Note that a vaild canonical uuid may be part of a longer string
+	 * such as a urn.
+	 */
+	size_t input_len = strnlen(canonical_form, UUID_CANONICAL_FORM_LEN);
+
+	if (input_len == UUID_CANONICAL_FORM_LEN) {
 
 		size_t i;
 		valid_chars = UUID_CANONICAL_FORM_LEN;
@@ -46,7 +51,7 @@
 				if (canonical_form[i] != '-') return 0;
 			}
 			else {
-				if (!isxdigit(canonical_form[i])) return 0;
+				if (!isxdigit((int)canonical_form[i])) return 0;
 			}
 		}
 	}
@@ -54,6 +59,23 @@
 	return valid_chars;
 }
 
+bool uuid_is_equal(const uint8_t *octets_a, const uint8_t *octets_b)
+{
+	return memcmp(octets_a, octets_b, UUID_OCTETS_LEN) == 0;
+}
+
+bool uuid_is_nil(const uint8_t *octets)
+{
+	return memcmp(uuid_get_nil()->octets, octets, UUID_OCTETS_LEN) == 0;
+}
+
+const struct uuid_octets *uuid_get_nil(void)
+{
+	static const struct uuid_octets nil_uuid = {0};
+
+	return &nil_uuid;
+}
+
 size_t uuid_parse_to_octets(const char *canonical_form, uint8_t *buf, size_t buf_size)
 {
 	size_t octet_index = 0;
@@ -105,39 +127,38 @@
 }
 
 /*
- * The byte order is reversed for the first 4 bytes, then 2 bytes, then 2 bytes.
- * This is for compatibility with TF-A and OP-TEE where a binary uuid is represented as
- * an uint32_t, 2x uint16_t, then uint8_t array.
+ * The byte order is reversed for the integer sections of the UUID. Converts
+ * from standard to GUID octet representations an visa versa.
  */
-void uuid_reverse_octets(const struct uuid_octets *standard_encoding,
+void uuid_reverse_octets(const struct uuid_octets *input_octets,
 	uint8_t *buf, size_t buf_size)
 {
 	if (buf_size >= UUID_OCTETS_LEN) {
 		/* Reverse bytes in each section */
-		buf[0] = standard_encoding->octets[3];
-		buf[1] = standard_encoding->octets[2];
-		buf[2] = standard_encoding->octets[1];
-		buf[3] = standard_encoding->octets[0];
+		buf[0] = input_octets->octets[3];
+		buf[1] = input_octets->octets[2];
+		buf[2] = input_octets->octets[1];
+		buf[3] = input_octets->octets[0];
 
-		buf[4] = standard_encoding->octets[5];
-		buf[5] = standard_encoding->octets[4];
+		buf[4] = input_octets->octets[5];
+		buf[5] = input_octets->octets[4];
 
-		buf[6] = standard_encoding->octets[7];
-		buf[7] = standard_encoding->octets[6];
+		buf[6] = input_octets->octets[7];
+		buf[7] = input_octets->octets[6];
 
-		buf[8] = standard_encoding->octets[8];
-		buf[9] = standard_encoding->octets[9];
+		buf[8] = input_octets->octets[8];
+		buf[9] = input_octets->octets[9];
 
-		buf[10] = standard_encoding->octets[10];
-		buf[11] = standard_encoding->octets[11];
-		buf[12] = standard_encoding->octets[12];
-		buf[13] = standard_encoding->octets[13];
-		buf[14] = standard_encoding->octets[14];
-		buf[15] = standard_encoding->octets[15];
+		buf[10] = input_octets->octets[10];
+		buf[11] = input_octets->octets[11];
+		buf[12] = input_octets->octets[12];
+		buf[13] = input_octets->octets[13];
+		buf[14] = input_octets->octets[14];
+		buf[15] = input_octets->octets[15];
 	}
 }
 
-size_t uuid_parse_to_octets_reversed(const char *canonical_form,
+size_t uuid_parse_to_guid_octets(const char *canonical_form,
 	uint8_t *buf, size_t buf_size)
 {
 	size_t valid_chars;
@@ -153,3 +174,24 @@
 
 	return valid_chars;
 }
+
+void uuid_octets_from_canonical(struct uuid_octets *uuid_octets,
+	const char *canonical_form)
+{
+	size_t valid_chars = uuid_parse_to_octets(canonical_form,
+		uuid_octets->octets, sizeof(uuid_octets->octets));
+
+	/* Input string is assumed to be valid. Should not be used if canonical
+	 * string originates from an untrusted source.
+	 */
+	assert(valid_chars == UUID_CANONICAL_FORM_LEN);
+}
+
+void uuid_guid_octets_from_canonical(struct uuid_octets *uuid_octets,
+	const char *canonical_form)
+{
+	size_t valid_chars = uuid_parse_to_guid_octets(canonical_form,
+		uuid_octets->octets, sizeof(uuid_octets->octets));
+
+	assert(valid_chars == UUID_CANONICAL_FORM_LEN);
+}