1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6 #include <ctype.h>
7 #include <endian.h>
8 #ifdef OPENSSL_FOUND
9 #include <openssl/evp.h>
10 #endif
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <tee_api_types.h>
16 #include <tee_client_api.h>
17 #include "xtest_uuid_helpers.h"
18
hex(char c)19 static int hex(char c)
20 {
21 char lc = tolower(c);
22
23 if (isdigit(lc))
24 return lc - '0';
25 if (isxdigit(lc))
26 return lc - 'a' + 10;
27 return -1;
28 }
29
parse_hex(const char * s,size_t nchars,uint32_t * res)30 static uint32_t parse_hex(const char *s, size_t nchars, uint32_t *res)
31 {
32 uint32_t v = 0;
33 size_t n = 0;
34 int c = 0;
35
36 for (n = 0; n < nchars; n++) {
37 c = hex(s[n]);
38 if (c == -1) {
39 *res = TEE_ERROR_BAD_FORMAT;
40 goto out;
41 }
42 v = (v << 4) + c;
43 }
44 *res = TEE_SUCCESS;
45 out:
46 return v;
47 }
48
xtest_uuid_from_str(TEEC_UUID * uuid,const char * s)49 TEEC_Result xtest_uuid_from_str(TEEC_UUID *uuid, const char *s)
50 {
51 TEEC_Result res = TEEC_SUCCESS;
52 TEEC_UUID u = { };
53 const char *p = s;
54 size_t i = 0;
55
56 if (!p || strnlen(p, 37) != 36)
57 return TEEC_ERROR_BAD_FORMAT;
58 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
59 return TEEC_ERROR_BAD_FORMAT;
60
61 u.timeLow = parse_hex(p, 8, &res);
62 if (res)
63 goto out;
64 p += 9;
65 u.timeMid = parse_hex(p, 4, &res);
66 if (res)
67 goto out;
68 p += 5;
69 u.timeHiAndVersion = parse_hex(p, 4, &res);
70 if (res)
71 goto out;
72 p += 5;
73 for (i = 0; i < 8; i++) {
74 u.clockSeqAndNode[i] = parse_hex(p, 2, &res);
75 if (res)
76 goto out;
77 if (i == 1)
78 p += 3;
79 else
80 p += 2;
81 }
82 *uuid = u;
83 out:
84 return res;
85 }
86
87 #define UUID_STR_LEN 37
88
xtest_uuid_to_allocated_str(const TEEC_UUID * uuid)89 char *xtest_uuid_to_allocated_str(const TEEC_UUID *uuid)
90 {
91 char *s = NULL;
92
93 s = malloc(UUID_STR_LEN);
94 if (!s)
95 return NULL;
96
97 sprintf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid->timeLow,
98 uuid->timeMid, uuid->timeHiAndVersion, uuid->clockSeqAndNode[0],
99 uuid->clockSeqAndNode[1], uuid->clockSeqAndNode[2],
100 uuid->clockSeqAndNode[3], uuid->clockSeqAndNode[4],
101 uuid->clockSeqAndNode[5], uuid->clockSeqAndNode[6],
102 uuid->clockSeqAndNode[7]);
103
104 return s;
105 }
106
107 #ifdef OPENSSL_FOUND
xtest_uuid_v5(TEEC_UUID * uuid,const TEEC_UUID * ns,const void * name,size_t size)108 TEEC_Result xtest_uuid_v5(TEEC_UUID *uuid, const TEEC_UUID *ns,
109 const void *name, size_t size)
110 {
111 TEEC_Result res = TEEC_SUCCESS;
112 EVP_MD_CTX *mdctx = NULL;
113 const EVP_MD *md = NULL;
114 unsigned char hash[EVP_MAX_MD_SIZE] = { };
115 unsigned int md_len = 0;
116 unsigned char nsbe[16] = { };
117 uint32_t be32 = 0;
118 uint16_t be16 = 0;
119 int ret = 0;
120
121 /* Convert from host to big endian */
122 be32 = htobe32(ns->timeLow);
123 memcpy(&nsbe[0], &be32, sizeof(be32));
124 be16 = htobe16(ns->timeMid);
125 memcpy(&nsbe[4], &be16, sizeof(be16));
126 be16 = htobe16(ns->timeHiAndVersion);
127 memcpy(&nsbe[6], &be16, sizeof(be16));
128 memcpy(&nsbe[8], &ns->clockSeqAndNode, sizeof(ns->clockSeqAndNode));
129
130 mdctx = EVP_MD_CTX_create();
131 if (!mdctx)
132 return TEEC_ERROR_OUT_OF_MEMORY;
133 md = EVP_sha1();
134 if (!md) {
135 res = TEEC_ERROR_NOT_SUPPORTED;
136 goto out;
137 }
138 ret = EVP_DigestInit_ex(mdctx, md, NULL);
139 if (!ret) {
140 res = TEEC_ERROR_GENERIC;
141 goto out;
142 }
143 ret = EVP_DigestUpdate(mdctx, nsbe, sizeof(nsbe));
144 if (!ret) {
145 res = TEEC_ERROR_GENERIC;
146 goto out;
147 }
148 ret = EVP_DigestUpdate(mdctx, name, size);
149 if (!ret) {
150 res = TEEC_ERROR_GENERIC;
151 goto out;
152 }
153 ret = EVP_DigestFinal_ex(mdctx, hash, &md_len);
154 if (!ret) {
155 res = TEEC_ERROR_GENERIC;
156 goto out;
157 }
158
159 /* Mark it as UUIDv5 */
160 hash[6] = (hash[6] & 0x0F) | 0x50;
161 hash[8] = (hash[8] & 0x3F) | 0x80;
162
163 /* Convert from big endian to host */
164 memcpy(&be32, &hash[0], sizeof(uint32_t));
165 uuid->timeLow = be32toh(be32);
166 memcpy(&be16, &hash[4], sizeof(uint16_t));
167 uuid->timeMid = be16toh(be16);
168 memcpy(&be16, &hash[6], sizeof(uint16_t));
169 uuid->timeHiAndVersion = be16toh(be16);
170 memcpy(uuid->clockSeqAndNode, &hash[8], sizeof(uuid->clockSeqAndNode));
171 out:
172 EVP_MD_CTX_destroy(mdctx);
173 return res;
174 }
175 #endif /*OPENSSL_FOUND*/
176