aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hall <julian.hall@arm.com>2020-11-23 17:33:31 +0100
committerGyorgy Szing <Gyorgy.Szing@arm.com>2020-11-27 16:47:02 +0100
commita7e89b0474fdc61a314c31f95a803c443e6ccd9a (patch)
treef5ab9f290bb16e44921019c94f710c5e381f2300
parentba1095cdb254ba4d34eb0773a8d0da235a7a1bb7 (diff)
downloadtrusted-services-a7e89b0474fdc61a314c31f95a803c443e6ccd9a.tar.gz
Add UUID helper component
Change-Id: I4227fd83fc81abb3e4d0a3be1dc7384eb8dfb4bc Signed-off-by: Julian Hall <julian.hall@arm.com>
-rw-r--r--components/common/uuid/component.cmake13
-rw-r--r--components/common/uuid/test/component.cmake13
-rw-r--r--components/common/uuid/test/uuid_tests.cpp113
-rw-r--r--components/common/uuid/uuid.c124
-rw-r--r--components/common/uuid/uuid.h63
5 files changed, 326 insertions, 0 deletions
diff --git a/components/common/uuid/component.cmake b/components/common/uuid/component.cmake
new file mode 100644
index 0000000..ebd7050
--- /dev/null
+++ b/components/common/uuid/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/uuid.c"
+ )
diff --git a/components/common/uuid/test/component.cmake b/components/common/uuid/test/component.cmake
new file mode 100644
index 0000000..029c46c
--- /dev/null
+++ b/components/common/uuid/test/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/uuid_tests.cpp"
+ )
diff --git a/components/common/uuid/test/uuid_tests.cpp b/components/common/uuid/test/uuid_tests.cpp
new file mode 100644
index 0000000..03f4f87
--- /dev/null
+++ b/components/common/uuid/test/uuid_tests.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cstring>
+#include <common/uuid/uuid.h>
+#include <CppUTest/TestHarness.h>
+
+TEST_GROUP(UuidTests) {
+
+};
+
+TEST(UuidTests, parseValidUuidLowerCase) {
+
+ /* A valid UUID unsing lower-case */
+ const char *uuid_text = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
+ CHECK(uuid_is_valid(uuid_text));
+
+ const uint8_t expected_bytes[] =
+ {0xd9,0xdf,0x52,0xd5,
+ 0x16,0xa2,
+ 0x4b,0xb2,
+ 0x9a,0xa4,
+ 0xd2,0x6d,0x3b,0x84,0xe8,0xc0};
+
+ uint8_t byte_array[UUID_OCTETS_LEN];
+ memset(byte_array, 0, sizeof(byte_array));
+
+ CHECK(uuid_parse_to_octets(uuid_text, byte_array, sizeof(byte_array)));
+ CHECK(memcmp(byte_array, expected_bytes, UUID_OCTETS_LEN) == 0);
+}
+
+TEST(UuidTests, parseValidUuidMixedCase) {
+
+ /* A valid UUID unsing mixed-case */
+ const char *uuid_text = "D9df52d5-16a2-4bB2-9aa4-d26d3b84E8c0";
+ CHECK(uuid_is_valid(uuid_text));
+
+ const uint8_t expected_bytes[] =
+ {0xd9,0xdf,0x52,0xd5,
+ 0x16,0xa2,
+ 0x4b,0xb2,
+ 0x9a,0xa4,
+ 0xd2,0x6d,0x3b,0x84,0xe8,0xc0};
+
+ uint8_t byte_array[UUID_OCTETS_LEN];
+ memset(byte_array, 0, sizeof(byte_array));
+
+ CHECK(uuid_parse_to_octets(uuid_text, byte_array, sizeof(byte_array)));
+ CHECK(memcmp(byte_array, expected_bytes, UUID_OCTETS_LEN) == 0);
+}
+
+TEST(UuidTests, parseUuidInUrn) {
+
+ /* A valid UUID embedded in a urn */
+ const char *urn_text = "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66:0";
+ CHECK(uuid_is_valid(&urn_text[9]));
+
+ const uint8_t expected_bytes[] =
+ {0x6e,0x8b,0xc4,0x30,
+ 0x9c,0x3a,
+ 0x11,0xd9,
+ 0x96,0x69,
+ 0x08,0x00,0x20,0x0c,0x9a,0x66};
+
+ uint8_t byte_array[UUID_OCTETS_LEN];
+ memset(byte_array, 0, sizeof(byte_array));
+
+ CHECK(uuid_parse_to_octets(&urn_text[9], byte_array, sizeof(byte_array)));
+ CHECK(memcmp(byte_array, expected_bytes, UUID_OCTETS_LEN) == 0);
+}
+
+TEST(UuidTests, parseError) {
+
+ /* Invalid digit */
+ const char *broken1 = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8X0";
+ CHECK(!uuid_is_valid(broken1));
+
+ /* Invalid separator */
+ const char *broken2 = "d9df52d5-16a2-4bb2-9aa4_d26d3b84e8c0";
+ CHECK(!uuid_is_valid(broken2));
+
+ /* Too short */
+ const char *broken3 = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c";
+ CHECK(!uuid_is_valid(broken3));
+
+ /* Zero length */
+ const char *broken4 = "";
+ CHECK(!uuid_is_valid(broken4));
+}
+
+TEST(UuidTests, parseValidUuidToReversed) {
+
+ /* A valid UUID unsing lower-case */
+ const char *uuid_text = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
+ CHECK(uuid_is_valid(uuid_text));
+
+ /* Reversed ouput is expected to be */
+ const uint8_t expected_bytes[] =
+ {0xd5,0x52,0xdf,0xd9,
+ 0xa2,0x16,
+ 0xb2,0x4b,
+ 0x9a,0xa4,
+ 0xd2,0x6d,0x3b,0x84,0xe8,0xc0};
+
+ uint8_t byte_array[UUID_OCTETS_LEN];
+ memset(byte_array, 0, sizeof(byte_array));
+
+ CHECK(uuid_parse_to_octets_reversed(uuid_text, byte_array, sizeof(byte_array)));
+ CHECK(memcmp(byte_array, expected_bytes, UUID_OCTETS_LEN) == 0);
+}
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;
+}
diff --git a/components/common/uuid/uuid.h b/components/common/uuid/uuid.h
new file mode 100644
index 0000000..e45e37a
--- /dev/null
+++ b/components/common/uuid/uuid.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UUID_H
+#define UUID_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define UUID_OCTETS_LEN (16)
+#define UUID_CANONICAL_FORM_LEN (36)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Structure for holding an octet representation of a UUID.
+ */
+struct uuid_octets
+{
+ uint8_t octets[UUID_OCTETS_LEN];
+};
+
+/*
+ * Structure for holding an canonical string representation of a UUID.
+ */
+struct uuid_canonical
+{
+ char characters[UUID_CANONICAL_FORM_LEN + 1];
+};
+
+/*
+ * Check if uuid string in canonical form is valid. Returns the number of
+ * valid characters. This will either be UUID_CANONICAL_FORM_LEN or zero
+ * if the string is invalid in some way.
+ */
+size_t uuid_is_valid(const char *canonical_form);
+
+/*
+ * Parses a uuid string in canonical string form, outputing as an array of bytes.
+ * Returns the number of characters parsed from the input string. Returns zero
+ * if there is a parsing error.
+ */
+size_t uuid_parse_to_octets(const char *canonical_form, uint8_t *buf, size_t buf_size);
+
+/*
+ * Parses a uuid string in canonical string form but instead of outputting octets
+ * in standard byte order, octets from each section of the canonical uuid are
+ * reversed.
+ */
+size_t uuid_parse_to_octets_reversed(const char *canonical_form, uint8_t *buf, size_t buf_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UUID_H */