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