blob: 6f8b2ecc697438f71b8307917a6fd472b2bd9154 [file] [log] [blame]
Julian Halla7e89b02020-11-23 17:33:31 +01001/*
Julian Hall7d7b24c2021-08-13 13:40:38 +01002 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
Julian Halla7e89b02020-11-23 17:33:31 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "uuid.h"
8#include <string.h>
9#include <ctype.h>
Julian Hall7d7b24c2021-08-13 13:40:38 +010010
11static uint8_t hex_to_nibble(char hex)
12{
13 uint8_t nibble = 0;
14
15 if (hex >= '0' && hex <= '9') {
16 nibble = hex - '0';
17 }
18 else {
19 nibble = ((hex | 0x20) - 'a') + 10;
20 }
21
22 return nibble;
23}
24
25static uint8_t hex_to_byte(const char *hex)
26{
27 /* Takes a validated input and returns the byte value */
28 uint8_t byte = hex_to_nibble(hex[0]) << 4;
29 byte |= (hex_to_nibble(hex[1]) & 0x0f);
30 return byte;
31}
Julian Halla7e89b02020-11-23 17:33:31 +010032
33size_t uuid_is_valid(const char *canonical_form)
34{
Julian Hall7d7b24c2021-08-13 13:40:38 +010035 size_t valid_chars = 0;
36 size_t input_len = strlen(canonical_form);
Julian Halla7e89b02020-11-23 17:33:31 +010037
Julian Hall7d7b24c2021-08-13 13:40:38 +010038 if (input_len >= UUID_CANONICAL_FORM_LEN) {
Julian Halla7e89b02020-11-23 17:33:31 +010039
Julian Hall7d7b24c2021-08-13 13:40:38 +010040 size_t i;
41 valid_chars = UUID_CANONICAL_FORM_LEN;
Julian Halla7e89b02020-11-23 17:33:31 +010042
Julian Hall7d7b24c2021-08-13 13:40:38 +010043 for (i = 0; i < UUID_CANONICAL_FORM_LEN; ++i) {
Julian Halla7e89b02020-11-23 17:33:31 +010044
Julian Hall7d7b24c2021-08-13 13:40:38 +010045 if (i == 8 || i == 13 || i == 18 || i == 23) {
46 if (canonical_form[i] != '-') return 0;
47 }
48 else {
49 if (!isxdigit(canonical_form[i])) return 0;
50 }
51 }
52 }
Julian Halla7e89b02020-11-23 17:33:31 +010053
Julian Hall7d7b24c2021-08-13 13:40:38 +010054 return valid_chars;
Julian Halla7e89b02020-11-23 17:33:31 +010055}
56
57size_t uuid_parse_to_octets(const char *canonical_form, uint8_t *buf, size_t buf_size)
58{
Julian Hall7d7b24c2021-08-13 13:40:38 +010059 size_t octet_index = 0;
60 const char *pos;
61 size_t valid_chars = uuid_is_valid(canonical_form);
Julian Halla7e89b02020-11-23 17:33:31 +010062
Julian Hall7d7b24c2021-08-13 13:40:38 +010063 if ((buf_size < UUID_OCTETS_LEN) ||
64 (valid_chars != UUID_CANONICAL_FORM_LEN)) {
65 /* Invalid input */
66 return 0;
67 }
Julian Halla7e89b02020-11-23 17:33:31 +010068
Julian Hall7d7b24c2021-08-13 13:40:38 +010069 /*
70 * UUID string has been validates as having the following form:
71 * xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
72 * 4 2 2 2 6
73 */
74 pos = &canonical_form[0];
75 while (octet_index < 4) {
76 buf[octet_index++] = hex_to_byte(pos);
77 pos += 2;
78 }
Julian Halla7e89b02020-11-23 17:33:31 +010079
Julian Hall7d7b24c2021-08-13 13:40:38 +010080 pos = &canonical_form[9];
81 while (octet_index < 6) {
82 buf[octet_index++] = hex_to_byte(pos);
83 pos += 2;
84 }
Julian Halla7e89b02020-11-23 17:33:31 +010085
Julian Hall7d7b24c2021-08-13 13:40:38 +010086 pos = &canonical_form[14];
87 while (octet_index < 8) {
88 buf[octet_index++] = hex_to_byte(pos);
89 pos += 2;
90 }
Julian Halla7e89b02020-11-23 17:33:31 +010091
Julian Hall7d7b24c2021-08-13 13:40:38 +010092 pos = &canonical_form[19];
93 while (octet_index < 10) {
94 buf[octet_index++] = hex_to_byte(pos);
95 pos += 2;
96 }
Julian Halla7e89b02020-11-23 17:33:31 +010097
Julian Hall7d7b24c2021-08-13 13:40:38 +010098 pos = &canonical_form[24];
99 while (octet_index < 16) {
100 buf[octet_index++] = hex_to_byte(pos);
101 pos += 2;
102 }
Julian Halla7e89b02020-11-23 17:33:31 +0100103
Julian Hall7d7b24c2021-08-13 13:40:38 +0100104 return valid_chars;
Julian Halla7e89b02020-11-23 17:33:31 +0100105}
106
107/*
Julian Halla7e89b02020-11-23 17:33:31 +0100108 * The byte order is reversed for the first 4 bytes, then 2 bytes, then 2 bytes.
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100109 * This is for compatibility with TF-A and OP-TEE where a binary uuid is represented as
110 * an uint32_t, 2x uint16_t, then uint8_t array.
Julian Halla7e89b02020-11-23 17:33:31 +0100111 */
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100112void uuid_reverse_octets(const struct uuid_octets *standard_encoding,
113 uint8_t *buf, size_t buf_size)
114{
115 if (buf_size >= UUID_OCTETS_LEN) {
116 /* Reverse bytes in each section */
117 buf[0] = standard_encoding->octets[3];
118 buf[1] = standard_encoding->octets[2];
119 buf[2] = standard_encoding->octets[1];
120 buf[3] = standard_encoding->octets[0];
121
122 buf[4] = standard_encoding->octets[5];
123 buf[5] = standard_encoding->octets[4];
124
125 buf[6] = standard_encoding->octets[7];
126 buf[7] = standard_encoding->octets[6];
127
128 buf[8] = standard_encoding->octets[8];
129 buf[9] = standard_encoding->octets[9];
130
131 buf[10] = standard_encoding->octets[10];
132 buf[11] = standard_encoding->octets[11];
133 buf[12] = standard_encoding->octets[12];
134 buf[13] = standard_encoding->octets[13];
135 buf[14] = standard_encoding->octets[14];
136 buf[15] = standard_encoding->octets[15];
137 }
138}
139
140size_t uuid_parse_to_octets_reversed(const char *canonical_form,
141 uint8_t *buf, size_t buf_size)
Julian Halla7e89b02020-11-23 17:33:31 +0100142{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100143 size_t valid_chars;
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100144 struct uuid_octets standard_encoding;
Julian Halla7e89b02020-11-23 17:33:31 +0100145
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100146 valid_chars = uuid_parse_to_octets(canonical_form,
147 standard_encoding.octets, sizeof(standard_encoding.octets));
Julian Halla7e89b02020-11-23 17:33:31 +0100148
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100149 if (valid_chars == UUID_CANONICAL_FORM_LEN) {
Julian Halla7e89b02020-11-23 17:33:31 +0100150
Julian Hall7c2ae0c2022-09-29 08:27:07 +0100151 uuid_reverse_octets(&standard_encoding, buf, buf_size);
Julian Hall7d7b24c2021-08-13 13:40:38 +0100152 }
Julian Halla7e89b02020-11-23 17:33:31 +0100153
Julian Hall7d7b24c2021-08-13 13:40:38 +0100154 return valid_chars;
Julian Halla7e89b02020-11-23 17:33:31 +0100155}