Add UUID helper component

Change-Id: I4227fd83fc81abb3e4d0a3be1dc7384eb8dfb4bc
Signed-off-by: Julian Hall <julian.hall@arm.com>
diff --git a/components/common/uuid/uuid.c b/components/common/uuid/uuid.c
new file mode 100644
index 0000000..7ce46c2
--- /dev/null
+++ b/components/common/uuid/uuid.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "uuid.h"
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+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) {
+
+        size_t i;
+        valid_chars = UUID_CANONICAL_FORM_LEN;
+
+        for (i = 0; i < UUID_CANONICAL_FORM_LEN; ++i) {
+
+            if (i == 8 || i == 13 || i == 18 || i == 23) {
+                if (canonical_form[i] != '-') return 0;
+            }
+            else {
+                if (!isxdigit(canonical_form[i])) return 0;
+            }
+        }
+    }
+
+    return valid_chars;
+}
+
+size_t uuid_parse_to_octets(const char *canonical_form, uint8_t *buf, size_t buf_size)
+{
+    size_t octet_index = 0;
+    const char *pos;
+    size_t valid_chars = uuid_is_valid(canonical_form);
+
+    if ((buf_size < UUID_OCTETS_LEN) ||
+        (valid_chars != UUID_CANONICAL_FORM_LEN)) {
+        /* Invalid input */
+        return 0;
+    }
+
+    /*
+     * UUID string has been validates as having the following form:
+     * xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
+     *     4      2    2   2       6
+     */
+    pos = &canonical_form[0];
+    while (octet_index < 4) {
+        sscanf(pos, "%02hhX", &buf[octet_index++]);
+        pos += 2;
+    }
+
+    pos = &canonical_form[9];
+    while (octet_index < 6) {
+        sscanf(pos, "%02hhX", &buf[octet_index++]);
+        pos += 2;
+    }
+
+    pos = &canonical_form[14];
+    while (octet_index < 8) {
+        sscanf(pos, "%02hhX", &buf[octet_index++]);
+        pos += 2;
+    }
+
+    pos = &canonical_form[19];
+    while (octet_index < 10) {
+        sscanf(pos, "%02hhX", &buf[octet_index++]);
+        pos += 2;
+    }
+
+    pos = &canonical_form[24];
+    while (octet_index < 16) {
+        sscanf(pos, "%02hhX", &buf[octet_index++]);
+        pos += 2;
+    }
+
+    return valid_chars;
+}
+
+/*
+ * TODO: Temorary workaround for optee compatibility
+ * The byte order is reversed for the first 4 bytes, then 2 bytes, then 2 bytes.
+ * This is because the UUID type in OP-TEE consists of an uint32_t, 2x uint16_t,
+ * then uint8_t array.
+ */
+size_t uuid_parse_to_octets_reversed(const char *canonical_form, uint8_t *buf, size_t buf_size)
+{
+    size_t valid_chars;
+    uint8_t standard_octets[UUID_OCTETS_LEN];
+
+    valid_chars = uuid_parse_to_octets(canonical_form, standard_octets, sizeof(standard_octets));
+
+    if ((valid_chars == UUID_CANONICAL_FORM_LEN) && (buf_size >= UUID_OCTETS_LEN)) {
+        /* Reverse bytes in each section */
+        buf[0] = standard_octets[3];
+        buf[1] = standard_octets[2];
+        buf[2] = standard_octets[1];
+        buf[3] = standard_octets[0];
+
+        buf[4] = standard_octets[5];
+        buf[5] = standard_octets[4];
+
+        buf[6] = standard_octets[7];
+        buf[7] = standard_octets[6];
+
+        buf[8] = standard_octets[8];
+        buf[9] = standard_octets[9];
+
+        buf[10] = standard_octets[10];
+        buf[11] = standard_octets[11];
+        buf[12] = standard_octets[12];
+        buf[13] = standard_octets[13];
+        buf[14] = standard_octets[14];
+        buf[15] = standard_octets[15];
+    }
+
+    return valid_chars;
+}