xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tsp_context_mem.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
1 
2 /*
3  * Licensed Materials - Property of IBM
4  *
5  * trousers - An open source TCG Software Stack
6  *
7  * (C) Copyright International Business Machines Corp. 2004
8  *
9  */
10 
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include "trousers/tss.h"
17 #include "trousers_types.h"
18 #include "spi_utils.h"
19 #include "capabilities.h"
20 #include "memmgr.h"
21 #include "tsplog.h"
22 #include "obj.h"
23 
24 static struct memTable *
__tspi_createTable()25 __tspi_createTable()
26 {
27 	struct memTable *table = NULL;
28 	/*
29 	 * No table has yet been created to hold the memory allocations of
30 	 * this context, so we need to create one
31 	 */
32 	table = calloc(1, sizeof(struct memTable));
33 	if (table == NULL) {
34 		LogError("malloc of %zd bytes failed.", sizeof(struct memTable));
35 		return NULL;
36 	}
37 	return (table);
38 }
39 
40 /* caller needs to lock memtable lock */
41 struct memTable *
getTable(TSS_HCONTEXT tspContext)42 getTable(TSS_HCONTEXT tspContext)
43 {
44 	struct memTable *tmp;
45 
46 	for (tmp = SpiMemoryTable; tmp; tmp = tmp->nextTable)
47 		if (tmp->tspContext == tspContext)
48 			return tmp;
49 
50 	return NULL;
51 }
52 
53 /* caller needs to lock memtable lock */
54 static void
__tspi_addTable(struct memTable * new)55 __tspi_addTable(struct memTable *new)
56 {
57 	struct memTable *tmp = SpiMemoryTable;
58 
59 	/* base case, this is the first table */
60 	if (SpiMemoryTable == NULL) {
61 		SpiMemoryTable = new;
62 		return;
63 	}
64 
65 	/* else add @new onto the end */
66 	for (; tmp; tmp = tmp->nextTable)
67 		if (tmp->nextTable == NULL) {
68 			tmp->nextTable = new;
69 			break;
70 		}
71 }
72 
73 /* caller needs to lock memtable lock and be sure the context mem slot for
74  * @tspContext exists before calling.
75  */
76 void
__tspi_addEntry(TSS_HCONTEXT tspContext,struct memEntry * new)77 __tspi_addEntry(TSS_HCONTEXT tspContext, struct memEntry *new)
78 {
79 	struct memTable *tmp = getTable(tspContext);
80 	struct memEntry *tmp_entry;
81 
82 	if (tmp == NULL) {
83 		if ((tmp = __tspi_createTable()) == NULL)
84 			return;
85 		tmp->tspContext = tspContext;
86 		__tspi_addTable(tmp);
87 	}
88 
89 	tmp_entry = tmp->entries;
90 
91 	if (tmp->entries == NULL) {
92 		tmp->entries = new;
93 		return;
94 	}
95 
96 	/* else tack @new onto the end */
97 	for (; tmp_entry; tmp_entry = tmp_entry->nextEntry) {
98 		if (tmp_entry->nextEntry == NULL) {
99 			tmp_entry->nextEntry = new;
100 			break;
101 		}
102 	}
103 }
104 
105 /* caller needs to lock memtable lock */
106 TSS_RESULT
__tspi_freeTable(TSS_HCONTEXT tspContext)107 __tspi_freeTable(TSS_HCONTEXT tspContext)
108 {
109 	struct memTable *prev = NULL, *index = NULL, *next = NULL;
110 	struct memEntry *entry = NULL, *entry_next = NULL;
111 
112 	for(index = SpiMemoryTable; index; index = index->nextTable) {
113 		next = index->nextTable;
114 		if (index->tspContext == tspContext) {
115 			for (entry = index->entries; entry; entry = entry_next) {
116 				/* this needs to be set before we do free(entry) */
117 				entry_next = entry->nextEntry;
118 				free(entry->memPointer);
119 				free(entry);
120 			}
121 
122 			if (prev != NULL)
123 				prev->nextTable = next;
124 			else
125 				SpiMemoryTable = NULL;
126 
127 			free(index);
128 			break;
129 		}
130 		prev = index;
131 	}
132 
133 	return TSS_SUCCESS;
134 }
135 
136 TSS_RESULT
__tspi_freeEntry(struct memTable * table,void * pointer)137 __tspi_freeEntry(struct memTable *table, void *pointer)
138 {
139 	struct memEntry *index = NULL;
140 	struct memEntry *prev = NULL;
141 	struct memEntry *toKill = NULL;
142 
143 	for (index = table->entries; index; prev = index, index = index->nextEntry) {
144 		if (index->memPointer == pointer) {
145 			toKill = index;
146 			if (prev == NULL)
147 				table->entries = toKill->nextEntry;
148 			else
149 				prev->nextEntry = toKill->nextEntry;
150 
151 			free(pointer);
152 			free(toKill);
153 			return TSS_SUCCESS;
154 		}
155 	}
156 
157 	return TSPERR(TSS_E_INVALID_RESOURCE);
158 }
159 
160 TSS_RESULT
__tspi_add_mem_entry(TSS_HCONTEXT tspContext,void * allocd_mem)161 __tspi_add_mem_entry(TSS_HCONTEXT tspContext, void *allocd_mem)
162 {
163 	struct memEntry *newEntry = calloc(1, sizeof(struct memEntry));
164 	if (newEntry == NULL) {
165 		LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
166 		return TSPERR(TSS_E_OUTOFMEMORY);
167 	}
168 
169 	newEntry->memPointer = allocd_mem;
170 
171 	MUTEX_LOCK(memtable_lock);
172 
173 	__tspi_addEntry(tspContext, newEntry);
174 
175 	MUTEX_UNLOCK(memtable_lock);
176 
177 	return TSS_SUCCESS;
178 }
179 
180 /*
181  * calloc_tspi will be called by functions outside of this file. All locking
182  * is done here.
183  */
184 void *
calloc_tspi(TSS_HCONTEXT tspContext,UINT32 howMuch)185 calloc_tspi(TSS_HCONTEXT tspContext, UINT32 howMuch)
186 {
187 	struct memTable *table = NULL;
188 	struct memEntry *newEntry = NULL;
189 
190 	MUTEX_LOCK(memtable_lock);
191 
192 	table = getTable(tspContext);
193 	if (table == NULL) {
194 		if ((table = __tspi_createTable()) == NULL) {
195 			MUTEX_UNLOCK(memtable_lock);
196 			return NULL;
197 		}
198 		table->tspContext = tspContext;
199 		__tspi_addTable(table);
200 	}
201 
202 	newEntry = calloc(1, sizeof(struct memEntry));
203 	if (newEntry == NULL) {
204 		LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
205 		MUTEX_UNLOCK(memtable_lock);
206 		return NULL;
207 	}
208 
209 	newEntry->memPointer = calloc(1, howMuch);
210 	if (newEntry->memPointer == NULL) {
211 		LogError("malloc of %d bytes failed.", howMuch);
212 		free(newEntry);
213 		MUTEX_UNLOCK(memtable_lock);
214 		return NULL;
215 	}
216 
217 	/* this call must happen inside the lock or else another thread could
218 	 * remove the context mem slot, causing a segfault
219 	 */
220 	__tspi_addEntry(tspContext, newEntry);
221 
222 	MUTEX_UNLOCK(memtable_lock);
223 
224 	return newEntry->memPointer;
225 }
226 
227 /*
228  * free_tspi will be called by functions outside of this file. All locking
229  * is done here.
230  */
231 TSS_RESULT
free_tspi(TSS_HCONTEXT tspContext,void * memPointer)232 free_tspi(TSS_HCONTEXT tspContext, void *memPointer)
233 {
234 	struct memTable *index;
235 	TSS_RESULT result;
236 
237 	MUTEX_LOCK(memtable_lock);
238 
239 	if (memPointer == NULL) {
240 		result = __tspi_freeTable(tspContext);
241 		MUTEX_UNLOCK(memtable_lock);
242 		return result;
243 	}
244 
245 	if ((index = getTable(tspContext)) == NULL) {
246 		MUTEX_UNLOCK(memtable_lock);
247 		/* Tspi_Context_FreeMemory checks that the TSP context is good before calling us,
248 		 * so we can be sure that the problem is with memPointer */
249 		return TSPERR(TSS_E_INVALID_RESOURCE);
250 	}
251 
252 	/* just free one entry */
253 	result = __tspi_freeEntry(index, memPointer);
254 
255 	MUTEX_UNLOCK(memtable_lock);
256 
257 	return result;
258 }
259 
260 /* definition for a memset that cannot be optimized away */
261 void * __no_optimize
__tspi_memset(void * s,int c,size_t n)262 __tspi_memset(void *s, int c, size_t n)
263 {
264 	return memset(s, c, n);
265 }
266