aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hall <julian.hall@arm.com>2021-08-13 13:40:38 +0100
committerGyorgy Szing <Gyorgy.Szing@arm.com>2021-10-06 00:49:16 +0200
commit7d7b24c080eb3ebcf9265b3b80f437ed754d11ac (patch)
tree4b4db27dd09f0d6446f5ef0b327442b5b84f6155
parentc203872fe81bbef0c66f0b0d86ccbb84743238f1 (diff)
downloadtrusted-services-7d7b24c080eb3ebcf9265b3b80f437ed754d11ac.tar.gz
Improve reusability of service_name and uuid components
To allow the service_name and uuid components to be reused in constrained environments such as 'opteesp', the dependency on sscanf (stdio.h) is removed and replaced with a portable hex to byte and string to integer implementation. This allows the service locator to be used in SPs. Signed-off-by: Julian Hall <julian.hall@arm.com> Change-Id: I51bf7849d13568ef506c6244cab108e79b8bd09a
-rw-r--r--components/common/uuid/uuid.c193
-rw-r--r--components/service/locator/service_name.c247
-rw-r--r--components/service/locator/test/sn_tests.cpp8
3 files changed, 244 insertions, 204 deletions
diff --git a/components/common/uuid/uuid.c b/components/common/uuid/uuid.c
index 7ce46c24d..5d4644181 100644
--- a/components/common/uuid/uuid.c
+++ b/components/common/uuid/uuid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,80 +7,101 @@
#include "uuid.h"
#include <string.h>
#include <ctype.h>
-#include <stdio.h>
+
+static uint8_t hex_to_nibble(char hex)
+{
+ uint8_t nibble = 0;
+
+ if (hex >= '0' && hex <= '9') {
+ nibble = hex - '0';
+ }
+ else {
+ nibble = ((hex | 0x20) - 'a') + 10;
+ }
+
+ return nibble;
+}
+
+static uint8_t hex_to_byte(const char *hex)
+{
+ /* Takes a validated input and returns the byte value */
+ uint8_t byte = hex_to_nibble(hex[0]) << 4;
+ byte |= (hex_to_nibble(hex[1]) & 0x0f);
+ return byte;
+}
size_t uuid_is_valid(const char *canonical_form)
{
- size_t valid_chars = 0;
- size_t input_len = strlen(canonical_form);
+ size_t valid_chars = 0;
+ size_t input_len = strlen(canonical_form);
- if (input_len >= UUID_CANONICAL_FORM_LEN) {
+ if (input_len >= UUID_CANONICAL_FORM_LEN) {
- size_t i;
- valid_chars = UUID_CANONICAL_FORM_LEN;
+ size_t i;
+ valid_chars = UUID_CANONICAL_FORM_LEN;
- for (i = 0; i < UUID_CANONICAL_FORM_LEN; ++i) {
+ 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;
- }
- }
- }
+ 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;
+ 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;
+ 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) {
+ buf[octet_index++] = hex_to_byte(pos);
+ pos += 2;
+ }
+
+ pos = &canonical_form[9];
+ while (octet_index < 6) {
+ buf[octet_index++] = hex_to_byte(pos);
+ pos += 2;
+ }
+
+ pos = &canonical_form[14];
+ while (octet_index < 8) {
+ buf[octet_index++] = hex_to_byte(pos);
+ pos += 2;
+ }
+
+ pos = &canonical_form[19];
+ while (octet_index < 10) {
+ buf[octet_index++] = hex_to_byte(pos);
+ pos += 2;
+ }
+
+ pos = &canonical_form[24];
+ while (octet_index < 16) {
+ buf[octet_index++] = hex_to_byte(pos);
+ pos += 2;
+ }
+
+ return valid_chars;
}
/*
@@ -91,34 +112,34 @@ size_t uuid_parse_to_octets(const char *canonical_form, uint8_t *buf, size_t buf
*/
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];
+ size_t valid_chars;
+ uint8_t standard_octets[UUID_OCTETS_LEN];
- valid_chars = uuid_parse_to_octets(canonical_form, standard_octets, sizeof(standard_octets));
+ 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];
+ 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[4] = standard_octets[5];
+ buf[5] = standard_octets[4];
- buf[6] = standard_octets[7];
- buf[7] = standard_octets[6];
+ buf[6] = standard_octets[7];
+ buf[7] = standard_octets[6];
- buf[8] = standard_octets[8];
- buf[9] = standard_octets[9];
+ 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];
- }
+ 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;
+ return valid_chars;
}
diff --git a/components/service/locator/service_name.c b/components/service/locator/service_name.c
index 878b84bec..0999787f5 100644
--- a/components/service/locator/service_name.c
+++ b/components/service/locator/service_name.c
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <ctype.h>
#include <string.h>
-#include <stdio.h>
#include "service_name.h"
/*
@@ -15,14 +15,14 @@
*/
struct sn_parsed_fields
{
- size_t authority_pos;
- size_t authority_len;
- size_t service_pos;
- size_t service_len;
- size_t version_pos;
- size_t version_len;
- size_t instance_pos;
- size_t instance_len;
+ size_t authority_pos;
+ size_t authority_len;
+ size_t service_pos;
+ size_t service_len;
+ size_t version_pos;
+ size_t version_len;
+ size_t instance_pos;
+ size_t instance_len;
};
/*
@@ -31,18 +31,18 @@ struct sn_parsed_fields
*/
static size_t field_len(const char *sn, size_t from, size_t len, char separator)
{
- size_t field_len = 0;
- size_t pos = from;
+ size_t field_len = 0;
+ size_t pos = from;
- while (pos < len) {
+ while (pos < len) {
- if (sn[pos] == separator) break;
+ if (sn[pos] == separator) break;
- ++pos;
- ++field_len;
- }
+ ++pos;
+ ++field_len;
+ }
- return field_len;
+ return field_len;
}
/*
@@ -51,21 +51,21 @@ static size_t field_len(const char *sn, size_t from, size_t len, char separator)
*/
static bool find_next(const char *sn, size_t from, size_t len, char separator, size_t *next)
{
- bool found = false;
- size_t pos = from;
+ bool found = false;
+ size_t pos = from;
- while (pos < len) {
+ while (pos < len) {
- if (sn[pos] == separator) {
- *next = pos + 1;
- found = (*next < len);
- break;
- }
+ if (sn[pos] == separator) {
+ *next = pos + 1;
+ found = (*next < len);
+ break;
+ }
- ++pos;
- }
+ ++pos;
+ }
- return found;
+ return found;
}
/*
@@ -74,123 +74,142 @@ static bool find_next(const char *sn, size_t from, size_t len, char separator, s
*/
static bool sn_parse(const char *sn, struct sn_parsed_fields *fields)
{
- size_t sn_len = strlen(sn);
- size_t field_pos = 0;
-
- fields->authority_pos = 0;
- fields->authority_len = 0;
- fields->service_pos = 0;
- fields->service_len = 0;
- fields->version_pos = 0;
- fields->version_len = 0;
- fields->instance_pos = 0;
- fields->instance_len = 0;
-
- /* Absorb urn: if present */
- if (memcmp("urn", &sn[field_pos], strlen("urn")) == 0) {
- if (!find_next(sn, field_pos, sn_len, ':', &field_pos)) return false;
- }
-
- /* Check it is a service name */
- if (memcmp("sn", &sn[field_pos], strlen("sn")) != 0) {
- /* Not a service name */
- return false;
- }
-
- /* Expect the authority field */
- if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
- fields->authority_pos = field_pos;
- fields->authority_len = field_len(sn, field_pos, sn_len, ':');
- }
- else {
- /* Missing mandatory authority field */
- return false;
- }
-
- /* Expect the service field */
- if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
- fields->service_pos = field_pos;
- fields->service_len = field_len(sn, field_pos, sn_len, ':');
-
- /* Check for the optional version */
- if (find_next(sn, field_pos, field_pos + fields->service_len, '.', &field_pos)) {
- fields->version_pos = field_pos;
- fields->version_len = field_len(sn, field_pos, sn_len, ':');
- }
- }
- else {
- /* Missing mandatory service field */
- return false;
- }
-
- /* Check for optional instance */
- if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
- fields->instance_pos = field_pos;
- fields->instance_len = sn_len - field_pos;
- }
-
- return true;
+ size_t sn_len = strlen(sn);
+ size_t field_pos = 0;
+
+ fields->authority_pos = 0;
+ fields->authority_len = 0;
+ fields->service_pos = 0;
+ fields->service_len = 0;
+ fields->version_pos = 0;
+ fields->version_len = 0;
+ fields->instance_pos = 0;
+ fields->instance_len = 0;
+
+ /* Absorb urn: if present */
+ if (memcmp("urn", &sn[field_pos], strlen("urn")) == 0) {
+ if (!find_next(sn, field_pos, sn_len, ':', &field_pos)) return false;
+ }
+
+ /* Check it is a service name */
+ if (memcmp("sn", &sn[field_pos], strlen("sn")) != 0) {
+ /* Not a service name */
+ return false;
+ }
+
+ /* Expect the authority field */
+ if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
+ fields->authority_pos = field_pos;
+ fields->authority_len = field_len(sn, field_pos, sn_len, ':');
+ }
+ else {
+ /* Missing mandatory authority field */
+ return false;
+ }
+
+ /* Expect the service field */
+ if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
+ fields->service_pos = field_pos;
+ fields->service_len = field_len(sn, field_pos, sn_len, ':');
+
+ /* Check for the optional version */
+ if (find_next(sn, field_pos, field_pos + fields->service_len, '.', &field_pos)) {
+ fields->version_pos = field_pos;
+ fields->version_len = field_len(sn, field_pos, sn_len, ':');
+ }
+ }
+ else {
+ /* Missing mandatory service field */
+ return false;
+ }
+
+ /* Check for optional instance */
+ if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
+ fields->instance_pos = field_pos;
+ fields->instance_len = sn_len - field_pos;
+ }
+
+ return true;
}
bool sn_is_valid(const char *sn)
{
- struct sn_parsed_fields fields;
- return sn_parse(sn, &fields);
+ struct sn_parsed_fields fields;
+ return sn_parse(sn, &fields);
}
bool sn_check_authority(const char *sn, const char *auth)
{
- bool matched = false;
- struct sn_parsed_fields fields;
+ bool matched = false;
+ struct sn_parsed_fields fields;
- if (sn_parse(sn, &fields) && fields.authority_len) {
+ if (sn_parse(sn, &fields) && fields.authority_len) {
- matched = (memcmp(auth, &sn[fields.authority_pos], strlen(auth)) == 0);
- }
+ matched = (memcmp(auth, &sn[fields.authority_pos], strlen(auth)) == 0);
+ }
- return matched;
+ return matched;
}
bool sn_check_service(const char *sn, const char *service)
{
- bool matched = false;
- struct sn_parsed_fields fields;
+ bool matched = false;
+ struct sn_parsed_fields fields;
- if (sn_parse(sn, &fields) && fields.service_len) {
+ if (sn_parse(sn, &fields) && fields.service_len) {
- matched = (memcmp(service, &sn[fields.service_pos], strlen(service)) == 0);
- }
+ matched = (memcmp(service, &sn[fields.service_pos], strlen(service)) == 0);
+ }
- return matched;
+ return matched;
}
unsigned int sn_get_service_instance(const char *sn)
{
- unsigned int instance = 0;
+ unsigned int instance = 0;
- struct sn_parsed_fields fields;
+ struct sn_parsed_fields fields;
- if (sn_parse(sn, &fields) && fields.instance_len) {
+ if (sn_parse(sn, &fields) && fields.instance_len) {
- sscanf(&sn[fields.instance_pos], "%d", &instance);
- }
+ /* Instance must be expressed as a decimal */
+ unsigned int multiplier = 1;
- return instance;
+ for (size_t i = 0; i < fields.instance_len; i++) {
+
+ size_t digit_index = fields.instance_pos + fields.instance_len - 1 - i;
+ char digit = sn[digit_index];
+
+ if (isdigit(digit)) {
+
+ instance += ((digit - '0') * multiplier);
+ multiplier *= 10;
+ }
+ else {
+
+ /* Invalid instance string */
+ instance = 0;
+ break;
+ }
+ }
+ }
+
+ return instance;
}
size_t sn_read_service(const char *sn, char *buf, size_t buf_len)
{
- size_t field_len = 0;
+ size_t field_len = 0;
- memset(buf, 0, buf_len);
- struct sn_parsed_fields fields;
+ memset(buf, 0, buf_len);
+ struct sn_parsed_fields fields;
- if (sn_parse(sn, &fields) && fields.service_len && (fields.service_len < buf_len)) {
+ if (sn_parse(sn, &fields) && fields.service_len && (fields.service_len < buf_len)) {
- field_len = fields.service_len;
- memcpy(buf, &sn[fields.service_pos], field_len);
- buf[field_len] = '\0';
- }
+ field_len = fields.service_len;
+ memcpy(buf, &sn[fields.service_pos], field_len);
+ buf[field_len] = '\0';
+ }
- return field_len;
+ return field_len;
}
diff --git a/components/service/locator/test/sn_tests.cpp b/components/service/locator/test/sn_tests.cpp
index 4f8630aeb..50cce75b1 100644
--- a/components/service/locator/test/sn_tests.cpp
+++ b/components/service/locator/test/sn_tests.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,10 +54,10 @@ TEST(ServiceNameTests, checkFields) {
CHECK(sn_check_service(sn2, "secure-storage"));
CHECK_EQUAL(0, sn_get_service_instance(sn2));
- const char *sn3 = "sn:ffa:d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0:7";
+ const char *sn3 = "sn:ffa:d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0:77";
CHECK(sn_check_authority(sn3, "ffa"));
CHECK(sn_check_service(sn3, "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"));
- CHECK_EQUAL(7, sn_get_service_instance(sn3));
+ CHECK_EQUAL(77, sn_get_service_instance(sn3));
/* Check instance defaults to zero */
const char *sn4 = "sn:ffa:d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
@@ -88,4 +88,4 @@ TEST(ServiceNameTests, readService) {
CHECK_EQUAL(UUID_CANONICAL_FORM_LEN, sn_read_service(sn4, buf, sizeof(buf)));
CHECK(memcmp(buf, "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0", UUID_CANONICAL_FORM_LEN + 1) == 0);
CHECK_EQUAL(UUID_CANONICAL_FORM_LEN, strlen(buf));
-} \ No newline at end of file
+}