xref: /optee_os/core/tee/fs_dirfile.c (revision d7767217cb365fd91f5d592d1c96f0476cef811b)
1*d7767217SJens Wiklander /*
2*d7767217SJens Wiklander  * Copyright (c) 2017, Linaro Limited
3*d7767217SJens Wiklander  * All rights reserved.
4*d7767217SJens Wiklander  *
5*d7767217SJens Wiklander  * Redistribution and use in source and binary forms, with or without
6*d7767217SJens Wiklander  * modification, are permitted provided that the following conditions are met:
7*d7767217SJens Wiklander  *
8*d7767217SJens Wiklander  * 1. Redistributions of source code must retain the above copyright notice,
9*d7767217SJens Wiklander  * this list of conditions and the following disclaimer.
10*d7767217SJens Wiklander  *
11*d7767217SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*d7767217SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
13*d7767217SJens Wiklander  * and/or other materials provided with the distribution.
14*d7767217SJens Wiklander  *
15*d7767217SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*d7767217SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*d7767217SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*d7767217SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*d7767217SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*d7767217SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*d7767217SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*d7767217SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*d7767217SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*d7767217SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*d7767217SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
26*d7767217SJens Wiklander  */
27*d7767217SJens Wiklander 
28*d7767217SJens Wiklander #include <assert.h>
29*d7767217SJens Wiklander #include <bitstring.h>
30*d7767217SJens Wiklander #include <stdio.h>
31*d7767217SJens Wiklander #include <stdlib.h>
32*d7767217SJens Wiklander #include <string.h>
33*d7767217SJens Wiklander #include <tee/fs_dirfile.h>
34*d7767217SJens Wiklander #include <types_ext.h>
35*d7767217SJens Wiklander 
36*d7767217SJens Wiklander struct tee_fs_dirfile_dirh {
37*d7767217SJens Wiklander 	const TEE_UUID *uuid;
38*d7767217SJens Wiklander 	const struct tee_fs_dirfile_operations *fops;
39*d7767217SJens Wiklander 	struct tee_file_handle *fh;
40*d7767217SJens Wiklander 	int nbits;
41*d7767217SJens Wiklander 	bitstr_t *files;
42*d7767217SJens Wiklander 	size_t ndents;
43*d7767217SJens Wiklander };
44*d7767217SJens Wiklander 
45*d7767217SJens Wiklander struct dirfile_entry {
46*d7767217SJens Wiklander 	TEE_UUID uuid;
47*d7767217SJens Wiklander 	uint8_t oid[TEE_OBJECT_ID_MAX_LEN];
48*d7767217SJens Wiklander 	uint32_t oidlen;
49*d7767217SJens Wiklander 	uint8_t hash[TEE_FS_HTREE_HASH_SIZE];
50*d7767217SJens Wiklander 	uint32_t file_number;
51*d7767217SJens Wiklander };
52*d7767217SJens Wiklander 
53*d7767217SJens Wiklander /*
54*d7767217SJens Wiklander  * File layout
55*d7767217SJens Wiklander  *
56*d7767217SJens Wiklander  * dirfile_entry.0
57*d7767217SJens Wiklander  * ...
58*d7767217SJens Wiklander  * dirfile_entry.n
59*d7767217SJens Wiklander  *
60*d7767217SJens Wiklander  * where n the index is disconnected from file_number in struct dirfile_entry
61*d7767217SJens Wiklander  */
62*d7767217SJens Wiklander 
63*d7767217SJens Wiklander static TEE_Result maybe_grow_files(struct tee_fs_dirfile_dirh *dirh, int idx)
64*d7767217SJens Wiklander {
65*d7767217SJens Wiklander 	void *p;
66*d7767217SJens Wiklander 
67*d7767217SJens Wiklander 	if (idx < dirh->nbits)
68*d7767217SJens Wiklander 		return TEE_SUCCESS;
69*d7767217SJens Wiklander 
70*d7767217SJens Wiklander 	p = realloc(dirh->files, bitstr_size(idx + 1));
71*d7767217SJens Wiklander 	if (!p)
72*d7767217SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
73*d7767217SJens Wiklander 	dirh->files = p;
74*d7767217SJens Wiklander 
75*d7767217SJens Wiklander 	bit_nclear(dirh->files, dirh->nbits, idx);
76*d7767217SJens Wiklander 	dirh->nbits = idx + 1;
77*d7767217SJens Wiklander 
78*d7767217SJens Wiklander 	return TEE_SUCCESS;
79*d7767217SJens Wiklander }
80*d7767217SJens Wiklander 
81*d7767217SJens Wiklander static TEE_Result set_file(struct tee_fs_dirfile_dirh *dirh, int idx)
82*d7767217SJens Wiklander {
83*d7767217SJens Wiklander 	TEE_Result res = maybe_grow_files(dirh, idx);
84*d7767217SJens Wiklander 
85*d7767217SJens Wiklander 	if (!res)
86*d7767217SJens Wiklander 		bit_set(dirh->files, idx);
87*d7767217SJens Wiklander 
88*d7767217SJens Wiklander 	return res;
89*d7767217SJens Wiklander }
90*d7767217SJens Wiklander 
91*d7767217SJens Wiklander static void clear_file(struct tee_fs_dirfile_dirh *dirh, int idx)
92*d7767217SJens Wiklander {
93*d7767217SJens Wiklander 	if (idx < dirh->nbits)
94*d7767217SJens Wiklander 		bit_clear(dirh->files, idx);
95*d7767217SJens Wiklander }
96*d7767217SJens Wiklander 
97*d7767217SJens Wiklander static bool test_file(struct tee_fs_dirfile_dirh *dirh, int idx)
98*d7767217SJens Wiklander {
99*d7767217SJens Wiklander 	if (idx < dirh->nbits)
100*d7767217SJens Wiklander 		return bit_test(dirh->files, idx);
101*d7767217SJens Wiklander 
102*d7767217SJens Wiklander 	return false;
103*d7767217SJens Wiklander }
104*d7767217SJens Wiklander 
105*d7767217SJens Wiklander static TEE_Result read_dent(struct tee_fs_dirfile_dirh *dirh, int idx,
106*d7767217SJens Wiklander 			    struct dirfile_entry *dent)
107*d7767217SJens Wiklander {
108*d7767217SJens Wiklander 	TEE_Result res;
109*d7767217SJens Wiklander 	size_t l;
110*d7767217SJens Wiklander 
111*d7767217SJens Wiklander 	l = sizeof(*dent);
112*d7767217SJens Wiklander 	res = dirh->fops->read(dirh->fh, sizeof(struct dirfile_entry) * idx,
113*d7767217SJens Wiklander 			       dent, &l);
114*d7767217SJens Wiklander 	if (!res && l != sizeof(*dent))
115*d7767217SJens Wiklander 		res = TEE_ERROR_ITEM_NOT_FOUND;
116*d7767217SJens Wiklander 
117*d7767217SJens Wiklander 	return res;
118*d7767217SJens Wiklander }
119*d7767217SJens Wiklander 
120*d7767217SJens Wiklander static TEE_Result write_dent(struct tee_fs_dirfile_dirh *dirh, size_t n,
121*d7767217SJens Wiklander 			     struct dirfile_entry *dent)
122*d7767217SJens Wiklander {
123*d7767217SJens Wiklander 	TEE_Result res;
124*d7767217SJens Wiklander 
125*d7767217SJens Wiklander 	res = dirh->fops->write(dirh->fh, sizeof(*dent) * n,
126*d7767217SJens Wiklander 				dent, sizeof(*dent));
127*d7767217SJens Wiklander 	if (!res && n >= dirh->ndents)
128*d7767217SJens Wiklander 		dirh->ndents = n + 1;
129*d7767217SJens Wiklander 
130*d7767217SJens Wiklander 	return res;
131*d7767217SJens Wiklander }
132*d7767217SJens Wiklander 
133*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_open(const TEE_UUID *uuid,
134*d7767217SJens Wiklander 			       const struct tee_fs_dirfile_operations *fops,
135*d7767217SJens Wiklander 			       struct tee_fs_dirfile_dirh **dirh_ret)
136*d7767217SJens Wiklander {
137*d7767217SJens Wiklander 	TEE_Result res;
138*d7767217SJens Wiklander 	struct tee_fs_dirfile_dirh *dirh = calloc(1, sizeof(*dirh));
139*d7767217SJens Wiklander 	size_t n;
140*d7767217SJens Wiklander 
141*d7767217SJens Wiklander 	if (!dirh)
142*d7767217SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
143*d7767217SJens Wiklander 
144*d7767217SJens Wiklander 	dirh->uuid = uuid;
145*d7767217SJens Wiklander 	dirh->fops = fops;
146*d7767217SJens Wiklander 	res = fops->open(false, NULL, NULL, &dirh->fh);
147*d7767217SJens Wiklander 	if (res) {
148*d7767217SJens Wiklander 		res = fops->open(true, NULL, NULL, &dirh->fh);
149*d7767217SJens Wiklander 		if (res)
150*d7767217SJens Wiklander 			goto out;
151*d7767217SJens Wiklander 	}
152*d7767217SJens Wiklander 
153*d7767217SJens Wiklander 	for (n = 0;; n++) {
154*d7767217SJens Wiklander 		struct dirfile_entry dent;
155*d7767217SJens Wiklander 
156*d7767217SJens Wiklander 		res = read_dent(dirh, n, &dent);
157*d7767217SJens Wiklander 		if (res) {
158*d7767217SJens Wiklander 			if (res == TEE_ERROR_ITEM_NOT_FOUND)
159*d7767217SJens Wiklander 				res = TEE_SUCCESS;
160*d7767217SJens Wiklander 			goto out;
161*d7767217SJens Wiklander 		}
162*d7767217SJens Wiklander 
163*d7767217SJens Wiklander 		if (!dent.oidlen)
164*d7767217SJens Wiklander 			continue;
165*d7767217SJens Wiklander 
166*d7767217SJens Wiklander 		if (test_file(dirh, dent.file_number)) {
167*d7767217SJens Wiklander 			DMSG("clearing duplicate file number %" PRIu32,
168*d7767217SJens Wiklander 			     dent.file_number);
169*d7767217SJens Wiklander 			memset(&dent, 0, sizeof(dent));
170*d7767217SJens Wiklander 			res = write_dent(dirh, n, &dent);
171*d7767217SJens Wiklander 			if (res)
172*d7767217SJens Wiklander 				goto out;
173*d7767217SJens Wiklander 			continue;
174*d7767217SJens Wiklander 		}
175*d7767217SJens Wiklander 
176*d7767217SJens Wiklander 		res = set_file(dirh, dent.file_number);
177*d7767217SJens Wiklander 		if (res != TEE_SUCCESS)
178*d7767217SJens Wiklander 			goto out;
179*d7767217SJens Wiklander 	}
180*d7767217SJens Wiklander out:
181*d7767217SJens Wiklander 	if (!res) {
182*d7767217SJens Wiklander 		dirh->ndents = n;
183*d7767217SJens Wiklander 		*dirh_ret = dirh;
184*d7767217SJens Wiklander 	} else {
185*d7767217SJens Wiklander 		tee_fs_dirfile_close(dirh);
186*d7767217SJens Wiklander 	}
187*d7767217SJens Wiklander 	return res;
188*d7767217SJens Wiklander }
189*d7767217SJens Wiklander 
190*d7767217SJens Wiklander void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh)
191*d7767217SJens Wiklander {
192*d7767217SJens Wiklander 	if (dirh) {
193*d7767217SJens Wiklander 		dirh->fops->close(dirh->fh);
194*d7767217SJens Wiklander 		free(dirh->files);
195*d7767217SJens Wiklander 		free(dirh);
196*d7767217SJens Wiklander 	}
197*d7767217SJens Wiklander }
198*d7767217SJens Wiklander 
199*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh)
200*d7767217SJens Wiklander {
201*d7767217SJens Wiklander 	return dirh->fops->commit_writes(dirh->fh, NULL);
202*d7767217SJens Wiklander }
203*d7767217SJens Wiklander 
204*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh,
205*d7767217SJens Wiklander 				  struct tee_fs_dirfile_fileh *dfh)
206*d7767217SJens Wiklander {
207*d7767217SJens Wiklander 	TEE_Result res;
208*d7767217SJens Wiklander 	int i = 0;
209*d7767217SJens Wiklander 
210*d7767217SJens Wiklander 	if (dirh->files) {
211*d7767217SJens Wiklander 		bit_ffc(dirh->files, dirh->nbits, &i);
212*d7767217SJens Wiklander 		if (i == -1)
213*d7767217SJens Wiklander 			i = dirh->nbits;
214*d7767217SJens Wiklander 	}
215*d7767217SJens Wiklander 
216*d7767217SJens Wiklander 	res = set_file(dirh, i);
217*d7767217SJens Wiklander 	if (!res)
218*d7767217SJens Wiklander 		dfh->file_number = i;
219*d7767217SJens Wiklander 
220*d7767217SJens Wiklander 	return res;
221*d7767217SJens Wiklander }
222*d7767217SJens Wiklander 
223*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_find(struct tee_fs_dirfile_dirh *dirh,
224*d7767217SJens Wiklander 			       const void *oid, size_t oidlen,
225*d7767217SJens Wiklander 			       struct tee_fs_dirfile_fileh *dfh)
226*d7767217SJens Wiklander {
227*d7767217SJens Wiklander 	TEE_Result res;
228*d7767217SJens Wiklander 	struct dirfile_entry dent;
229*d7767217SJens Wiklander 	int n;
230*d7767217SJens Wiklander 	int first_free = -1;
231*d7767217SJens Wiklander 
232*d7767217SJens Wiklander 	for (n = 0;; n++) {
233*d7767217SJens Wiklander 		res = read_dent(dirh, n, &dent);
234*d7767217SJens Wiklander 		if (res == TEE_ERROR_ITEM_NOT_FOUND && !oidlen) {
235*d7767217SJens Wiklander 			memset(&dent, 0, sizeof(dent));
236*d7767217SJens Wiklander 			if (first_free != -1)
237*d7767217SJens Wiklander 				n = first_free;
238*d7767217SJens Wiklander 			break;
239*d7767217SJens Wiklander 		}
240*d7767217SJens Wiklander 		if (res)
241*d7767217SJens Wiklander 			return res;
242*d7767217SJens Wiklander 
243*d7767217SJens Wiklander 		if (!dent.oidlen && first_free == -1)
244*d7767217SJens Wiklander 			first_free = n;
245*d7767217SJens Wiklander 		if (dent.oidlen != oidlen)
246*d7767217SJens Wiklander 			continue;
247*d7767217SJens Wiklander 
248*d7767217SJens Wiklander 		assert(!oidlen || !dent.oidlen ||
249*d7767217SJens Wiklander 		       test_file(dirh, dent.file_number));
250*d7767217SJens Wiklander 
251*d7767217SJens Wiklander 		if (!memcmp(&dent.uuid, dirh->uuid, sizeof(dent.uuid)) &&
252*d7767217SJens Wiklander 		    !memcmp(&dent.oid, oid, oidlen))
253*d7767217SJens Wiklander 			break;
254*d7767217SJens Wiklander 	}
255*d7767217SJens Wiklander 
256*d7767217SJens Wiklander 	if (dfh) {
257*d7767217SJens Wiklander 		dfh->idx = n;
258*d7767217SJens Wiklander 		dfh->file_number = dent.file_number;
259*d7767217SJens Wiklander 		memcpy(dfh->hash, dent.hash, sizeof(dent.hash));
260*d7767217SJens Wiklander 	}
261*d7767217SJens Wiklander 
262*d7767217SJens Wiklander 	return TEE_SUCCESS;
263*d7767217SJens Wiklander }
264*d7767217SJens Wiklander 
265*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_fileh_to_fname(const struct tee_fs_dirfile_fileh *dfh,
266*d7767217SJens Wiklander 					 char *fname, size_t *fnlen)
267*d7767217SJens Wiklander {
268*d7767217SJens Wiklander 	int r;
269*d7767217SJens Wiklander 	size_t l = *fnlen;
270*d7767217SJens Wiklander 
271*d7767217SJens Wiklander 	if (dfh)
272*d7767217SJens Wiklander 		r = snprintf(fname, l, "%" PRIx32, dfh->file_number);
273*d7767217SJens Wiklander 	else
274*d7767217SJens Wiklander 		r = snprintf(fname, l, "dirf.db");
275*d7767217SJens Wiklander 
276*d7767217SJens Wiklander 	if (r < 0)
277*d7767217SJens Wiklander 		return TEE_ERROR_GENERIC;
278*d7767217SJens Wiklander 
279*d7767217SJens Wiklander 	*fnlen = r + 1;
280*d7767217SJens Wiklander 	if ((size_t)r >= l)
281*d7767217SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
282*d7767217SJens Wiklander 
283*d7767217SJens Wiklander 	return TEE_SUCCESS;
284*d7767217SJens Wiklander }
285*d7767217SJens Wiklander 
286*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_rename(struct tee_fs_dirfile_dirh *dirh,
287*d7767217SJens Wiklander 				 struct tee_fs_dirfile_fileh *dfh,
288*d7767217SJens Wiklander 				 const void *oid, size_t oidlen)
289*d7767217SJens Wiklander {
290*d7767217SJens Wiklander 	TEE_Result res;
291*d7767217SJens Wiklander 	struct dirfile_entry dent;
292*d7767217SJens Wiklander 
293*d7767217SJens Wiklander 	if (!oidlen || oidlen > sizeof(dent.oid))
294*d7767217SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
295*d7767217SJens Wiklander 	memset(&dent, 0, sizeof(dent));
296*d7767217SJens Wiklander 	dent.uuid = *dirh->uuid;
297*d7767217SJens Wiklander 	memcpy(dent.oid, oid, oidlen);
298*d7767217SJens Wiklander 	dent.oidlen = oidlen;
299*d7767217SJens Wiklander 	memcpy(dent.hash, dfh->hash, sizeof(dent.hash));
300*d7767217SJens Wiklander 	dent.file_number = dfh->file_number;
301*d7767217SJens Wiklander 
302*d7767217SJens Wiklander 	if (dfh->idx < 0) {
303*d7767217SJens Wiklander 		struct tee_fs_dirfile_fileh dfh2;
304*d7767217SJens Wiklander 
305*d7767217SJens Wiklander 		res = tee_fs_dirfile_find(dirh, oid, oidlen, &dfh2);
306*d7767217SJens Wiklander 		if (res) {
307*d7767217SJens Wiklander 			if (res == TEE_ERROR_ITEM_NOT_FOUND)
308*d7767217SJens Wiklander 				res = tee_fs_dirfile_find(dirh, NULL, 0, &dfh2);
309*d7767217SJens Wiklander 			if (res)
310*d7767217SJens Wiklander 				return res;
311*d7767217SJens Wiklander 		}
312*d7767217SJens Wiklander 		dfh->idx = dfh2.idx;
313*d7767217SJens Wiklander 	}
314*d7767217SJens Wiklander 
315*d7767217SJens Wiklander 	return write_dent(dirh, dfh->idx, &dent);
316*d7767217SJens Wiklander }
317*d7767217SJens Wiklander 
318*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_remove(struct tee_fs_dirfile_dirh *dirh,
319*d7767217SJens Wiklander 				 const struct tee_fs_dirfile_fileh *dfh)
320*d7767217SJens Wiklander {
321*d7767217SJens Wiklander 	TEE_Result res;
322*d7767217SJens Wiklander 	struct dirfile_entry dent;
323*d7767217SJens Wiklander 	uint32_t file_number;
324*d7767217SJens Wiklander 
325*d7767217SJens Wiklander 	res = read_dent(dirh, dfh->idx, &dent);
326*d7767217SJens Wiklander 	if (res)
327*d7767217SJens Wiklander 		return res;
328*d7767217SJens Wiklander 
329*d7767217SJens Wiklander 	if (!dent.oidlen)
330*d7767217SJens Wiklander 		return TEE_SUCCESS;
331*d7767217SJens Wiklander 
332*d7767217SJens Wiklander 	file_number = dent.file_number;
333*d7767217SJens Wiklander 	assert(dfh->file_number == file_number);
334*d7767217SJens Wiklander 	assert(test_file(dirh, file_number));
335*d7767217SJens Wiklander 
336*d7767217SJens Wiklander 	memset(&dent, 0, sizeof(dent));
337*d7767217SJens Wiklander 	res = write_dent(dirh, dfh->idx, &dent);
338*d7767217SJens Wiklander 	if (!res)
339*d7767217SJens Wiklander 		clear_file(dirh, file_number);
340*d7767217SJens Wiklander 
341*d7767217SJens Wiklander 	return res;
342*d7767217SJens Wiklander }
343*d7767217SJens Wiklander 
344*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_update_hash(struct tee_fs_dirfile_dirh *dirh,
345*d7767217SJens Wiklander 				      const struct tee_fs_dirfile_fileh *dfh)
346*d7767217SJens Wiklander {
347*d7767217SJens Wiklander 	TEE_Result res;
348*d7767217SJens Wiklander 	struct dirfile_entry dent;
349*d7767217SJens Wiklander 
350*d7767217SJens Wiklander 	res = read_dent(dirh, dfh->idx, &dent);
351*d7767217SJens Wiklander 	if (res)
352*d7767217SJens Wiklander 		return res;
353*d7767217SJens Wiklander 	assert(dent.file_number == dfh->file_number);
354*d7767217SJens Wiklander 	assert(test_file(dirh, dent.file_number));
355*d7767217SJens Wiklander 
356*d7767217SJens Wiklander 	memcpy(&dent.hash, dfh->hash, sizeof(dent.hash));
357*d7767217SJens Wiklander 
358*d7767217SJens Wiklander 	return write_dent(dirh, dfh->idx, &dent);
359*d7767217SJens Wiklander }
360*d7767217SJens Wiklander 
361*d7767217SJens Wiklander TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh,
362*d7767217SJens Wiklander 				   int *idx, void *oid, size_t *oidlen)
363*d7767217SJens Wiklander {
364*d7767217SJens Wiklander 	TEE_Result res;
365*d7767217SJens Wiklander 	int i = *idx + 1;
366*d7767217SJens Wiklander 	struct dirfile_entry dent;
367*d7767217SJens Wiklander 
368*d7767217SJens Wiklander 	if (i < 0)
369*d7767217SJens Wiklander 		i = 0;
370*d7767217SJens Wiklander 
371*d7767217SJens Wiklander 	for (;; i++) {
372*d7767217SJens Wiklander 		res = read_dent(dirh, i, &dent);
373*d7767217SJens Wiklander 		if (res)
374*d7767217SJens Wiklander 			return res;
375*d7767217SJens Wiklander 		if (!memcmp(&dent.uuid, dirh->uuid, sizeof(dent.uuid)) &&
376*d7767217SJens Wiklander 		    dent.oidlen)
377*d7767217SJens Wiklander 			break;
378*d7767217SJens Wiklander 	}
379*d7767217SJens Wiklander 
380*d7767217SJens Wiklander 	if (*oidlen < dent.oidlen)
381*d7767217SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
382*d7767217SJens Wiklander 
383*d7767217SJens Wiklander 	memcpy(oid, dent.oid, dent.oidlen);
384*d7767217SJens Wiklander 	*oidlen = dent.oidlen;
385*d7767217SJens Wiklander 	*idx = i;
386*d7767217SJens Wiklander 
387*d7767217SJens Wiklander 	return TEE_SUCCESS;
388*d7767217SJens Wiklander }
389