xref: /optee_os/ta/pkcs11/src/handle.c (revision 2bc50ed5e7c22cf959922893ed4e6848e74e460c)
122ada947SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
222ada947SEtienne Carriere /*
322ada947SEtienne Carriere  * Copyright (c) 2014-2020, Linaro Limited
422ada947SEtienne Carriere  */
522ada947SEtienne Carriere 
622ada947SEtienne Carriere #include <stdlib.h>
722ada947SEtienne Carriere #include <tee_internal_api.h>
822ada947SEtienne Carriere #include <tee_internal_api_extensions.h>
922ada947SEtienne Carriere 
1022ada947SEtienne Carriere #include "handle.h"
1122ada947SEtienne Carriere 
1222ada947SEtienne Carriere /*
1322ada947SEtienne Carriere  * Define the initial capacity of the database. It should be a low number
1422ada947SEtienne Carriere  * multiple of 2 since some databases a likely to only use a few handles.
1522ada947SEtienne Carriere  * Since the algorithm is to doubles up when growing it shouldn't cause a
1622ada947SEtienne Carriere  * noticeable overhead on large databases.
1722ada947SEtienne Carriere  */
1822ada947SEtienne Carriere #define HANDLE_DB_INITIAL_MAX_PTRS	4
1922ada947SEtienne Carriere 
20*2bc50ed5SEtienne Carriere /* Specific pointer ~0 denotes a still allocated but invalid handle */
21*2bc50ed5SEtienne Carriere #define INVALID_HANDLE_PTR	((void *)~0)
22*2bc50ed5SEtienne Carriere 
2322ada947SEtienne Carriere void handle_db_init(struct handle_db *db)
2422ada947SEtienne Carriere {
2522ada947SEtienne Carriere 	TEE_MemFill(db, 0, sizeof(*db));
2622ada947SEtienne Carriere }
2722ada947SEtienne Carriere 
2822ada947SEtienne Carriere void handle_db_destroy(struct handle_db *db)
2922ada947SEtienne Carriere {
3022ada947SEtienne Carriere 	if (db) {
3122ada947SEtienne Carriere 		TEE_Free(db->ptrs);
3222ada947SEtienne Carriere 		db->ptrs = NULL;
3322ada947SEtienne Carriere 		db->max_ptrs = 0;
3422ada947SEtienne Carriere 	}
3522ada947SEtienne Carriere }
3622ada947SEtienne Carriere 
3722ada947SEtienne Carriere uint32_t handle_get(struct handle_db *db, void *ptr)
3822ada947SEtienne Carriere {
3922ada947SEtienne Carriere 	uint32_t n = 0;
4022ada947SEtienne Carriere 	void *p = NULL;
4122ada947SEtienne Carriere 	uint32_t new_max_ptrs = 0;
4222ada947SEtienne Carriere 
43*2bc50ed5SEtienne Carriere 	if (!db || !ptr || ptr == INVALID_HANDLE_PTR)
4422ada947SEtienne Carriere 		return 0;
4522ada947SEtienne Carriere 
4622ada947SEtienne Carriere 	/* Try to find an empty location (index 0 is reserved as invalid) */
4722ada947SEtienne Carriere 	for (n = 1; n < db->max_ptrs; n++) {
4822ada947SEtienne Carriere 		if (!db->ptrs[n]) {
4922ada947SEtienne Carriere 			db->ptrs[n] = ptr;
5022ada947SEtienne Carriere 			return n;
5122ada947SEtienne Carriere 		}
5222ada947SEtienne Carriere 	}
5322ada947SEtienne Carriere 
5422ada947SEtienne Carriere 	/* No location available, grow the ptrs array */
5522ada947SEtienne Carriere 	if (db->max_ptrs)
5622ada947SEtienne Carriere 		new_max_ptrs = db->max_ptrs * 2;
5722ada947SEtienne Carriere 	else
5822ada947SEtienne Carriere 		new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS;
5922ada947SEtienne Carriere 
6022ada947SEtienne Carriere 	p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *));
6122ada947SEtienne Carriere 	if (!p)
6222ada947SEtienne Carriere 		return 0;
6322ada947SEtienne Carriere 	db->ptrs = p;
6422ada947SEtienne Carriere 	TEE_MemFill(db->ptrs + db->max_ptrs, 0,
6522ada947SEtienne Carriere 		    (new_max_ptrs - db->max_ptrs) * sizeof(void *));
6622ada947SEtienne Carriere 	db->max_ptrs = new_max_ptrs;
6722ada947SEtienne Carriere 
6822ada947SEtienne Carriere 	/* Since n stopped at db->max_ptrs there is an empty location there */
6922ada947SEtienne Carriere 	db->ptrs[n] = ptr;
7022ada947SEtienne Carriere 	return n;
7122ada947SEtienne Carriere }
7222ada947SEtienne Carriere 
73b8fa5170SEtienne Carriere static bool handle_is_valid(struct handle_db *db, uint32_t handle)
74b8fa5170SEtienne Carriere {
75b8fa5170SEtienne Carriere 	return db && handle && handle < db->max_ptrs;
76b8fa5170SEtienne Carriere }
77b8fa5170SEtienne Carriere 
7822ada947SEtienne Carriere void *handle_put(struct handle_db *db, uint32_t handle)
7922ada947SEtienne Carriere {
8022ada947SEtienne Carriere 	void *p = NULL;
8122ada947SEtienne Carriere 
82b8fa5170SEtienne Carriere 	if (!handle_is_valid(db, handle))
8322ada947SEtienne Carriere 		return NULL;
8422ada947SEtienne Carriere 
8522ada947SEtienne Carriere 	p = db->ptrs[handle];
8622ada947SEtienne Carriere 	db->ptrs[handle] = NULL;
8722ada947SEtienne Carriere 	return p;
8822ada947SEtienne Carriere }
8922ada947SEtienne Carriere 
9022ada947SEtienne Carriere void *handle_lookup(struct handle_db *db, uint32_t handle)
9122ada947SEtienne Carriere {
92*2bc50ed5SEtienne Carriere 	if (!handle_is_valid(db, handle) ||
93*2bc50ed5SEtienne Carriere 	    db->ptrs[handle] == INVALID_HANDLE_PTR)
9422ada947SEtienne Carriere 		return NULL;
9522ada947SEtienne Carriere 
9622ada947SEtienne Carriere 	return db->ptrs[handle];
9722ada947SEtienne Carriere }
9822ada947SEtienne Carriere 
99*2bc50ed5SEtienne Carriere void handle_invalidate(struct handle_db *db, uint32_t handle)
100*2bc50ed5SEtienne Carriere {
101*2bc50ed5SEtienne Carriere 	if (handle_is_valid(db, handle)) {
102*2bc50ed5SEtienne Carriere 		if (!db->ptrs[handle])
103*2bc50ed5SEtienne Carriere 			TEE_Panic(TEE_ERROR_GENERIC);
104*2bc50ed5SEtienne Carriere 
105*2bc50ed5SEtienne Carriere 		db->ptrs[handle] = INVALID_HANDLE_PTR;
106*2bc50ed5SEtienne Carriere 	}
107*2bc50ed5SEtienne Carriere }
108*2bc50ed5SEtienne Carriere 
10922ada947SEtienne Carriere uint32_t handle_lookup_handle(struct handle_db *db, void *ptr)
11022ada947SEtienne Carriere {
11122ada947SEtienne Carriere 	uint32_t n = 0;
11222ada947SEtienne Carriere 
113*2bc50ed5SEtienne Carriere 	if (ptr && ptr != INVALID_HANDLE_PTR) {
11422ada947SEtienne Carriere 		for (n = 1; n < db->max_ptrs; n++)
11522ada947SEtienne Carriere 			if (db->ptrs[n] == ptr)
11622ada947SEtienne Carriere 				return n;
11722ada947SEtienne Carriere 	}
11822ada947SEtienne Carriere 
11922ada947SEtienne Carriere 	return 0;
12022ada947SEtienne Carriere }
121