diff options
author | Julian Hall <julian.hall@arm.com> | 2021-08-13 13:40:38 +0100 |
---|---|---|
committer | Gyorgy Szing <Gyorgy.Szing@arm.com> | 2021-10-06 00:49:16 +0200 |
commit | 7d7b24c080eb3ebcf9265b3b80f437ed754d11ac (patch) | |
tree | 4b4db27dd09f0d6446f5ef0b327442b5b84f6155 | |
parent | c203872fe81bbef0c66f0b0d86ccbb84743238f1 (diff) | |
download | trusted-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.c | 193 | ||||
-rw-r--r-- | components/service/locator/service_name.c | 247 | ||||
-rw-r--r-- | components/service/locator/test/sn_tests.cpp | 8 |
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 +} |