• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include "tlv_sharedmem.h"
14 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <securec.h>
18 
19 #include "teeos_uuid.h"
20 #include "set_teeos_cfg.h"
21 
22 static struct tlv_tag *g_tlv_start = NULL;
23 static uint64_t g_teeos_share_mem = 0;
24 
tlv_start_init(void)25 static int32_t tlv_start_init(void)
26 {
27     if (g_tlv_start != NULL) {
28         teelog("tlv already started\n");
29         return 0;
30     }
31 
32     uint64_t sharedmem_start = get_sharedmem_start();
33     uint64_t sharedmem_size = get_sharedmem_size();
34     if (sharedmem_start == 0 || sharedmem_size == 0) {
35         teelog("sharedmem start addr or size error\n");
36         return -1;
37     }
38 
39     if (sharedmem_size < sizeof(struct tlv_tag)) {
40         teelog("sharedmem size not enough\n");
41         return -1;
42     }
43 
44     if (memset_s((void *)(uintptr_t)sharedmem_start, sizeof(struct tlv_tag),
45                  0, sizeof(struct tlv_tag)) != EOK) {
46         teelog("memset tlv start failed\n");
47         return -1;
48     }
49 
50     g_teeos_share_mem = sharedmem_start + sizeof(*g_tlv_start);
51     struct tlv_tag *tlv = (struct tlv_tag *)(uintptr_t)sharedmem_start;
52     tlv->magic = MAGIC_START;
53     tlv->tlv_num = 0;
54     g_tlv_start = tlv;
55 
56     return 0;
57 }
58 
alloc_teeos_shared_mem(uint64_t * addr,uint32_t length)59 static int32_t alloc_teeos_shared_mem(uint64_t *addr, uint32_t length)
60 {
61     if (addr == NULL || length == 0) {
62         teelog("invalid params\n");
63         return -1;
64     }
65 
66     uint64_t teeos_mem_start = get_teeos_start();
67     uint64_t teeos_mem_size = get_teeos_size();
68 
69     if (UINT64_MAX - g_teeos_share_mem < length) {
70         teelog("tlv length too large\n");
71         return -1;
72     }
73 
74     if (g_teeos_share_mem + length > teeos_mem_start + teeos_mem_size) {
75         teelog("tlv length too large\n");
76         return -1;
77     }
78 
79     if (memset_s((void *)(uintptr_t)g_teeos_share_mem, length, 0, length) != EOK) {
80         teelog("memset sharedmem to zero failed\n");
81         return -1;
82     }
83 
84     *addr = g_teeos_share_mem;
85     g_teeos_share_mem += length;
86 
87     return 0;
88 }
89 
share_mem_tlv_init_item(struct tlv_item_tag * new_item,struct tlv_item_data tlv_item_data)90 static int32_t share_mem_tlv_init_item(struct tlv_item_tag *new_item, struct tlv_item_data tlv_item_data)
91 {
92     uint32_t magic = MAGIC_START + tlv_item_data.value_len + tlv_item_data.owner_len;
93     struct tlv_item_tag tmp_item;
94     if (new_item == NULL) {
95         teelog("invalide params\n");
96         return 1;
97     }
98 
99     if (tlv_item_data.value_len == 0)
100         return 1;
101 
102     (void)memset_s(&tmp_item, sizeof(tmp_item), 0, sizeof(tmp_item));
103     if (memcpy_s(tmp_item.type, MAX_TAG_LEN,
104                  tlv_item_data.type, tlv_item_data.type_size) != EOK) {
105         teelog("memcpy to tmp_item failed\n");
106         return -1;
107     }
108     tmp_item.length = tlv_item_data.value_len;
109     tmp_item.owner_len = tlv_item_data.owner_len;
110     tmp_item.magic = magic;
111 
112     if (memcpy_s(new_item, sizeof(struct tlv_item_tag), &tmp_item, sizeof(struct tlv_item_tag)) != EOK) {
113         teelog("memcpy tag to new_item failed\n");
114         return -1;
115     }
116 
117     if (memcpy_s((uint8_t *)(uintptr_t)TLV_ITEM_DATA(new_item), tlv_item_data.owner_len,
118                  (uint8_t *)tlv_item_data.owner_list, tlv_item_data.owner_len) != EOK) {
119         teelog("memcpy owner_list to new_item failed\n");
120         return -1;
121     }
122 
123     if (memcpy_s((uint8_t *)(uintptr_t)(TLV_ITEM_DATA(new_item) + tlv_item_data.owner_len), tlv_item_data.value_len,
124                  (uint8_t *)tlv_item_data.value, tlv_item_data.value_len) != EOK) {
125         teelog("memcpy value to new_item failed\n");
126         return -1;
127     }
128     return 0;
129 }
130 
share_mem_tlv_find(uint64_t start_share_mem,const struct tlv_tag * tlv,const char * type,uint32_t type_size)131 struct tlv_item_tag* share_mem_tlv_find(uint64_t start_share_mem,
132                                         const struct tlv_tag *tlv, const char *type, uint32_t type_size)
133 {
134     struct tlv_item_tag *pos = NULL;
135     uint32_t len;
136     uint64_t sharedmem_vaddr = g_teeos_share_mem + sizeof(struct tlv_tag);
137 
138     pos = (struct tlv_item_tag *)(uintptr_t)(start_share_mem + sizeof(struct tlv_tag));
139     for (uint32_t i = 0; i < tlv->tlv_num; i++) {
140         len = sizeof(struct tlv_item_tag) + pos->length + pos->owner_len;
141         if (memcmp(pos->type, type, type_size) == 0 && strnlen(pos->type, MAX_TAG_LEN) <= type_size)
142             return pos;
143         if (i < tlv->tlv_num - 1)
144             pos = (struct tlv_item_tag *)(uintptr_t)(sharedmem_vaddr + len);
145     }
146 
147     return NULL;
148 }
149 
update_share_mem_tlv(struct tlv_item_data tlv_item_data)150 uint32_t update_share_mem_tlv(struct tlv_item_data tlv_item_data)
151 {
152     struct tlv_item_tag *new_item = NULL;
153 
154     new_item = share_mem_tlv_find(g_teeos_share_mem, g_tlv_start, tlv_item_data.type, tlv_item_data.type_size);
155     if (new_item == NULL) {
156         teelog("invalide params\n");
157         return 1;
158     }
159 
160     if (new_item->length == tlv_item_data.value_len)
161         share_mem_tlv_init_item(new_item, tlv_item_data);
162     else
163         return 1;
164     return 0;
165 }
166 
share_mem_tlv_append(struct tlv_tag * tlv,struct tlv_item_data tlv_item_data)167 static uint32_t share_mem_tlv_append(struct tlv_tag *tlv, struct tlv_item_data tlv_item_data)
168 {
169     uint64_t addr;
170     if (tlv == NULL) {
171         teelog("invalide params\n");
172         return 1;
173     }
174 
175     if (tlv->magic != MAGIC_START) {
176         teelog("append error, tlv format error\n");
177         return 1;
178     }
179 
180     /* length is the tlv length */
181     uint32_t total_len = tlv_item_data.value_len + tlv_item_data.owner_len + sizeof(struct tlv_item_tag);
182     uint32_t ret = alloc_teeos_shared_mem(&addr, total_len);
183     if (ret != 0) {
184         teelog("get share mem error\n");
185         return 1;
186     }
187 
188     share_mem_tlv_init_item((struct tlv_item_tag *)(uintptr_t)addr, tlv_item_data);
189     tlv->tlv_num++;
190 
191     uint64_t sharedmem_size = get_sharedmem_size();
192     if (tlv->total_len + sizeof(struct tlv_tag) >= sharedmem_size) {
193         teelog("out of share mem size\n");
194         return 1;
195     }
196 
197     tlv->total_len += tlv_item_data.value_len + tlv_item_data.owner_len + sizeof(struct tlv_item_tag);
198     return 0;
199 }
200 
put_tlv_shared_mem(struct tlv_item_data tlv_item_data)201 uint32_t put_tlv_shared_mem(struct tlv_item_data tlv_item_data)
202 {
203     uint32_t ret;
204 
205     if (tlv_start_init() != 0) {
206         teelog("tlv init failed\n");
207         return 1;
208     }
209 
210     if (tlv_item_data.type == NULL || tlv_item_data.value == NULL) {
211         teelog("tlv_item data error\n");
212         return 1;
213     }
214 
215     if (tlv_item_data.owner_len % (uint32_t)(sizeof(TEE_UUID)) != 0) {
216         teelog("tlv_item owner_len error\n");
217         return 1;
218     }
219 
220     if (tlv_item_data.type_size >= MAX_TAG_LEN || tlv_item_data.type_size < MIN_TAG_LEN) {
221         teelog("tlv_item type_size error\n");
222         return 1;
223     }
224 
225     ret = share_mem_tlv_append(g_tlv_start, tlv_item_data);
226     if (ret != 0) {
227         teelog("add share mem error\n");
228         return ret;
229     }
230     return ret;
231 }
232