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-2006
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <errno.h>
17
18 #include "trousers/tss.h"
19 #include "trousers_types.h"
20 #include "trousers_types.h"
21 #include "tcs_tsp.h"
22 #include "tcs_utils.h"
23 #include "tcs_int_literals.h"
24 #include "capabilities.h"
25 #include "tcslog.h"
26 #include "tcsps.h"
27 #include "req_mgr.h"
28
29
30 TSS_RESULT
ps_init_disk_cache(void)31 ps_init_disk_cache(void)
32 {
33 int fd;
34 TSS_RESULT rc;
35
36 MUTEX_INIT(disk_cache_lock);
37
38 if ((fd = get_file()) < 0)
39 return TCSERR(TSS_E_INTERNAL_ERROR);
40
41 if ((rc = init_disk_cache(fd)))
42 return rc;
43
44 /* this is temporary, to clear out a PS file from trousers
45 * versions before 0.2.1 */
46 if ((rc = clean_disk_cache(fd)))
47 return rc;
48
49 put_file(fd);
50 return TSS_SUCCESS;
51 }
52
53 void
ps_close_disk_cache(void)54 ps_close_disk_cache(void)
55 {
56 int fd;
57
58 if ((fd = get_file()) < 0) {
59 LogError("get_file() failed while trying to close disk cache.");
60 return;
61 }
62
63 close_disk_cache(fd);
64
65 put_file(fd);
66 }
67
68 TSS_BOOL
ps_is_key_registered(TCPA_STORE_PUBKEY * pub)69 ps_is_key_registered(TCPA_STORE_PUBKEY *pub)
70 {
71 TSS_UUID *uuid;
72 int fd;
73 TSS_RESULT rc;
74 TSS_BOOL is_reg = FALSE;
75
76 if ((fd = get_file()) < 0)
77 return FALSE;
78
79 if ((rc = psfile_get_uuid_by_pub(fd, pub, &uuid))) {
80 put_file(fd);
81 return FALSE;
82 }
83
84 put_file(fd);
85
86 if ((isUUIDRegistered(uuid, &is_reg)))
87 is_reg = FALSE;
88
89 free(uuid);
90 return is_reg;
91 }
92
93 TSS_RESULT
getParentUUIDByUUID(TSS_UUID * uuid,TSS_UUID * ret_uuid)94 getParentUUIDByUUID(TSS_UUID *uuid, TSS_UUID *ret_uuid)
95 {
96 struct key_disk_cache *disk_tmp;
97
98 /* check the registered key disk cache */
99 MUTEX_LOCK(disk_cache_lock);
100
101 for (disk_tmp = key_disk_cache_head; disk_tmp; disk_tmp = disk_tmp->next) {
102 if ((disk_tmp->flags & CACHE_FLAG_VALID) &&
103 !memcmp(&disk_tmp->uuid, uuid, sizeof(TSS_UUID))) {
104 memcpy(ret_uuid, &disk_tmp->parent_uuid, sizeof(TSS_UUID));
105 MUTEX_UNLOCK(disk_cache_lock);
106 return TSS_SUCCESS;
107 }
108 }
109 MUTEX_UNLOCK(disk_cache_lock);
110
111 return TCSERR(TSS_E_FAIL);
112 }
113
114 TSS_RESULT
isUUIDRegistered(TSS_UUID * uuid,TSS_BOOL * is_reg)115 isUUIDRegistered(TSS_UUID *uuid, TSS_BOOL *is_reg)
116 {
117 struct key_disk_cache *disk_tmp;
118
119 /* check the registered key disk cache */
120 MUTEX_LOCK(disk_cache_lock);
121
122 for (disk_tmp = key_disk_cache_head; disk_tmp; disk_tmp = disk_tmp->next) {
123 if ((disk_tmp->flags & CACHE_FLAG_VALID) &&
124 !memcmp(&disk_tmp->uuid, uuid, sizeof(TSS_UUID))) {
125 *is_reg = TRUE;
126 MUTEX_UNLOCK(disk_cache_lock);
127 return TSS_SUCCESS;
128 }
129 }
130 MUTEX_UNLOCK(disk_cache_lock);
131 *is_reg = FALSE;
132
133 return TSS_SUCCESS;
134 }
135
136 void
disk_cache_shift(struct key_disk_cache * c)137 disk_cache_shift(struct key_disk_cache *c)
138 {
139 UINT32 key_size, offset;
140 struct key_disk_cache *tmp = key_disk_cache_head;
141
142 /* offset is the end of the key location in the file */
143 offset = TSSPS_VENDOR_DATA_OFFSET(c) + c->vendor_data_size;
144 /* key_size is the size of the key entry on disk */
145 key_size = offset - TSSPS_UUID_OFFSET(c);
146
147 /* for each disk cache entry, if the data for that entry is at an
148 * offset greater than the key beign removed, then the entry needs to
149 * be decremented by the size of key's disk footprint (the key_size
150 * variable) */
151 while (tmp) {
152 if (tmp->offset >= offset) {
153 tmp->offset -= key_size;
154 }
155
156 tmp = tmp->next;
157 }
158 }
159
160 TSS_RESULT
ps_remove_key(TSS_UUID * uuid)161 ps_remove_key(TSS_UUID *uuid)
162 {
163 struct key_disk_cache *tmp, *prev = NULL;
164 TSS_RESULT rc;
165 int fd = -1;
166
167 MUTEX_LOCK(disk_cache_lock);
168 tmp = key_disk_cache_head;
169
170 for (; tmp; prev = tmp, tmp = tmp->next) {
171 if ((tmp->flags & CACHE_FLAG_VALID) &&
172 !memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID))) {
173 if ((fd = get_file()) < 0) {
174 rc = TCSERR(TSS_E_INTERNAL_ERROR);
175 break;
176 }
177
178 rc = psfile_remove_key(fd, tmp);
179
180 put_file(fd);
181
182 /* if moving the file contents around succeeded, then
183 * change the offsets of the keys in the cache in
184 * mem_cache_shift() and remove the key from the
185 * cache. */
186 if (!rc) {
187 disk_cache_shift(tmp);
188 if (prev) {
189 prev->next = tmp->next;
190 } else {
191 key_disk_cache_head = tmp->next;
192 }
193 free(tmp);
194 } else {
195 LogError("Error removing registered key.");
196 }
197
198 MUTEX_UNLOCK(disk_cache_lock);
199 return rc;
200 }
201 }
202
203 MUTEX_UNLOCK(disk_cache_lock);
204
205 return TCSERR(TCSERR(TSS_E_PS_KEY_NOTFOUND));
206 }
207
208 /*
209 * temporary function to clean out blanked keys from a PS file from
210 * trousers 0.2.0 and before
211 */
212 TSS_RESULT
clean_disk_cache(int fd)213 clean_disk_cache(int fd)
214 {
215 struct key_disk_cache *tmp, *prev = NULL;
216 TSS_RESULT rc;
217
218 MUTEX_LOCK(disk_cache_lock);
219 tmp = key_disk_cache_head;
220
221 for (; tmp; prev = tmp, tmp = tmp->next) {
222 if (!(tmp->flags & CACHE_FLAG_VALID)) {
223 rc = psfile_remove_key(fd, tmp);
224
225 /* if moving the file contents around succeeded, then
226 * change the offsets of the keys in the cache in
227 * mem_cache_shift() and remove the key from the
228 * cache. */
229 if (!rc) {
230 disk_cache_shift(tmp);
231 if (prev) {
232 prev->next = tmp->next;
233 }
234 free(tmp);
235 } else {
236 LogError("Error removing blank key.");
237 }
238
239 MUTEX_UNLOCK(disk_cache_lock);
240 return rc;
241 }
242 }
243
244 MUTEX_UNLOCK(disk_cache_lock);
245 return TSS_SUCCESS;
246 }
247
248 TSS_RESULT
ps_get_key_by_uuid(TSS_UUID * uuid,BYTE * blob,UINT16 * blob_size)249 ps_get_key_by_uuid(TSS_UUID *uuid, BYTE *blob, UINT16 *blob_size)
250 {
251 int fd = -1;
252 TSS_RESULT rc = TSS_SUCCESS;
253
254 if ((fd = get_file()) < 0)
255 return TCSERR(TSS_E_INTERNAL_ERROR);
256
257 rc = psfile_get_key_by_uuid(fd, uuid, blob, blob_size);
258
259 put_file(fd);
260 return rc;
261 }
262
263 TSS_RESULT
ps_get_key_by_cache_entry(struct key_disk_cache * c,BYTE * blob,UINT16 * blob_size)264 ps_get_key_by_cache_entry(struct key_disk_cache *c, BYTE *blob, UINT16 *blob_size)
265 {
266 int fd = -1;
267 TSS_RESULT rc = TSS_SUCCESS;
268
269 if ((fd = get_file()) < 0)
270 return TCSERR(TSS_E_INTERNAL_ERROR);
271
272 rc = psfile_get_key_by_cache_entry(fd, c, blob, blob_size);
273
274 put_file(fd);
275 return rc;
276 }
277
278 TSS_RESULT
ps_get_vendor_data(struct key_disk_cache * c,UINT32 * size,BYTE ** data)279 ps_get_vendor_data(struct key_disk_cache *c, UINT32 *size, BYTE **data)
280 {
281 int fd = -1;
282 TSS_RESULT rc;
283
284 if ((fd = get_file()) < 0)
285 return TCSERR(TSS_E_INTERNAL_ERROR);
286
287 rc = psfile_get_vendor_data(fd, c, size, data);
288
289 put_file(fd);
290 return rc;
291 }
292
293 TSS_RESULT
ps_is_pub_registered(TCPA_STORE_PUBKEY * key)294 ps_is_pub_registered(TCPA_STORE_PUBKEY *key)
295 {
296 int fd = -1;
297 TSS_BOOL answer;
298
299 if ((fd = get_file()) < 0)
300 return FALSE;
301
302 if (psfile_is_pub_registered(fd, key, &answer)) {
303 put_file(fd);
304 return FALSE;
305 }
306
307 put_file(fd);
308 return answer;
309 }
310
311 TSS_RESULT
ps_get_uuid_by_pub(TCPA_STORE_PUBKEY * pub,TSS_UUID ** uuid)312 ps_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub, TSS_UUID **uuid)
313 {
314 int fd = -1;
315 TSS_RESULT ret;
316
317 if ((fd = get_file()) < 0)
318 return TCSERR(TSS_E_INTERNAL_ERROR);
319
320 ret = psfile_get_uuid_by_pub(fd, pub, uuid);
321
322 put_file(fd);
323 return ret;
324 }
325
326 TSS_RESULT
ps_get_key_by_pub(TCPA_STORE_PUBKEY * pub,UINT32 * size,BYTE ** key)327 ps_get_key_by_pub(TCPA_STORE_PUBKEY *pub, UINT32 *size, BYTE **key)
328 {
329 int fd = -1;
330 TSS_RESULT ret;
331
332 if ((fd = get_file()) < 0)
333 return TCSERR(TSS_E_INTERNAL_ERROR);
334
335 ret = psfile_get_key_by_pub(fd, pub, size, key);
336
337 put_file(fd);
338 return ret;
339 }
340
341 TSS_RESULT
ps_write_key(TSS_UUID * uuid,TSS_UUID * parent_uuid,BYTE * vendor_data,UINT32 vendor_size,BYTE * blob,UINT32 blob_size)342 ps_write_key(TSS_UUID *uuid, TSS_UUID *parent_uuid, BYTE *vendor_data,
343 UINT32 vendor_size, BYTE *blob, UINT32 blob_size)
344 {
345 int fd = -1;
346 TSS_RESULT rc;
347 UINT32 parent_ps;
348 UINT16 short_blob_size = (UINT16)blob_size;
349
350 if ((fd = get_file()) < 0)
351 return TCSERR(TSS_E_INTERNAL_ERROR);
352
353 /* this case needed for PS file init. if the key file doesn't yet exist, the
354 * psfile_get_parent_ps_type_by_uuid() call would fail. */
355 if (!memcmp(parent_uuid, &NULL_UUID, sizeof(TSS_UUID))) {
356 parent_ps = TSS_PS_TYPE_SYSTEM;
357 } else {
358 if ((rc = psfile_get_ps_type_by_uuid(fd, parent_uuid, &parent_ps)))
359 return rc;
360 }
361
362 rc = psfile_write_key(fd, uuid, parent_uuid, &parent_ps, vendor_data,
363 vendor_size, blob, short_blob_size);
364
365 put_file(fd);
366 return TSS_SUCCESS;
367 }
368