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 #include <limits.h>
12 #include <stdlib.h>
13 #include <sys/types.h>
14 #include <sys/file.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <limits.h>
20
21 #include "trousers/tss.h"
22 #include "trousers/trousers.h"
23 #include "trousers_types.h"
24 #include "spi_utils.h"
25 #include "tcs_tsp.h"
26 #include "tspps.h"
27 #include "tsplog.h"
28 #include "obj.h"
29
30 /*
31 * tsp_ps.c
32 *
33 * Functions used to query the user persistent storage file.
34 *
35 * Since other apps may be altering the file, all operations must be atomic WRT the file and no
36 * cache will be kept, since another app could delete keys from the file out from under us.
37 *
38 * Atomicity is guaranteed for operations inbetween calls to get_file() and put_file().
39 *
40 * A PS file will have the lifetime of the TSP context. For instance, this code will store hKeyA
41 * and hKeyB in the file "a":
42 *
43 * setenv("TSS_USER_PS_FILE=a");
44 * Tspi_Context_Create(&hContext);
45 * Tspi_Context_RegisterKey(hKeyA);
46 * setenv("TSS_USER_PS_FILE=b");
47 * Tspi_Context_RegisterKey(hKeyB);
48 *
49 * but this code will store hKeyA in file "a" and hKeyB in file "b":
50 *
51 * setenv("TSS_USER_PS_FILE=a");
52 * Tspi_Context_Create(&hContext);
53 * Tspi_Context_RegisterKey(hKeyA);
54 * Tspi_Context_Close(hContext);
55 *
56 * setenv("TSS_USER_PS_FILE=b");
57 * Tspi_Context_Create(&hContext);
58 * Tspi_Context_RegisterKey(hKeyB);
59 *
60 */
61
62 TSS_RESULT
ps_get_registered_keys(TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO ** keys)63 ps_get_registered_keys(TSS_UUID *uuid, TSS_UUID *tcs_uuid, UINT32 *size, TSS_KM_KEYINFO **keys)
64 {
65 int fd;
66 UINT32 result;
67
68 if ((result = get_file(&fd)))
69 return result;
70
71 result = psfile_get_registered_keys(fd, uuid, tcs_uuid, size, keys);
72
73 put_file(fd);
74
75 return result;
76 }
77
78 TSS_RESULT
ps_get_registered_keys2(TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO2 ** keys)79 ps_get_registered_keys2(TSS_UUID *uuid, TSS_UUID *tcs_uuid, UINT32 *size, TSS_KM_KEYINFO2 **keys)
80 {
81 int fd;
82 UINT32 result;
83
84 if ((result = get_file(&fd)))
85 return result;
86
87 /* Sets the proper TSS_KM_KEYINFO2 fields according to the UUID type */
88 result = psfile_get_registered_keys2(fd, uuid, tcs_uuid, size, keys);
89
90 put_file(fd);
91
92 return result;
93 }
94
95 TSS_RESULT
ps_is_key_registered(TSS_UUID * uuid,TSS_BOOL * answer)96 ps_is_key_registered(TSS_UUID *uuid, TSS_BOOL *answer)
97 {
98 int fd;
99 TSS_RESULT result;
100
101 if ((result = get_file(&fd)))
102 return result;
103
104 result = psfile_is_key_registered(fd, uuid, answer);
105
106 put_file(fd);
107
108 return result;
109 }
110
111 TSS_RESULT
ps_write_key(TSS_UUID * uuid,TSS_UUID * parent_uuid,UINT32 parent_ps,UINT32 blob_size,BYTE * blob)112 ps_write_key(TSS_UUID *uuid, TSS_UUID *parent_uuid, UINT32 parent_ps, UINT32 blob_size, BYTE *blob)
113 {
114 int fd;
115 TSS_RESULT result;
116 UINT16 short_blob_size = (UINT16)blob_size;
117
118 if (blob_size > USHRT_MAX) {
119 LogError("Blob data being written to disk is too large(%u bytes)!", blob_size);
120 return TSPERR(TSS_E_INTERNAL_ERROR);
121 }
122
123 if ((result = get_file(&fd)))
124 return result;
125
126 result = psfile_write_key(fd, uuid, parent_uuid, parent_ps, blob, short_blob_size);
127
128 put_file(fd);
129 return result;
130 }
131
132
133 TSS_RESULT
ps_remove_key(TSS_UUID * uuid)134 ps_remove_key(TSS_UUID *uuid)
135 {
136 int fd;
137 TSS_RESULT result;
138
139 if ((result = get_file(&fd)))
140 return result;
141
142 result = psfile_remove_key(fd, uuid);
143
144 put_file(fd);
145 return result;
146 }
147
148 TSS_RESULT
ps_get_key_by_pub(TSS_HCONTEXT tspContext,UINT32 pub_size,BYTE * pub,TSS_HKEY * hKey)149 ps_get_key_by_pub(TSS_HCONTEXT tspContext, UINT32 pub_size, BYTE *pub, TSS_HKEY *hKey)
150 {
151 int fd;
152 TSS_RESULT result = TSS_SUCCESS;
153 BYTE key[4096];
154 TSS_UUID uuid;
155
156 if ((result = get_file(&fd)))
157 return result;
158
159 if ((result = psfile_get_key_by_pub(fd, &uuid, pub_size, pub, key))) {
160 put_file(fd);
161 return result;
162 }
163
164 put_file(fd);
165
166 result = obj_rsakey_add_by_key(tspContext, &uuid, key, TSS_OBJ_FLAG_USER_PS, hKey);
167
168 return result;
169 }
170
171 TSS_RESULT
ps_get_key_by_uuid(TSS_HCONTEXT tspContext,TSS_UUID * uuid,TSS_HKEY * hKey)172 ps_get_key_by_uuid(TSS_HCONTEXT tspContext, TSS_UUID *uuid, TSS_HKEY *hKey)
173 {
174 int fd;
175 TSS_RESULT result = TSS_SUCCESS;
176 BYTE key[4096];
177
178 if ((result = get_file(&fd)))
179 return result;
180
181 if ((result = psfile_get_key_by_uuid(fd, uuid, key))) {
182 put_file(fd);
183 return result;
184 }
185
186 put_file(fd);
187
188 result = obj_rsakey_add_by_key(tspContext, uuid, key, TSS_OBJ_FLAG_USER_PS, hKey);
189
190 return result;
191 }
192
193 TSS_RESULT
ps_get_parent_uuid_by_uuid(TSS_UUID * uuid,TSS_UUID * parent_uuid)194 ps_get_parent_uuid_by_uuid(TSS_UUID *uuid, TSS_UUID *parent_uuid)
195 {
196 int fd;
197 TSS_RESULT result;
198
199 if ((result = get_file(&fd)))
200 return result;
201
202 result = psfile_get_parent_uuid_by_uuid(fd, uuid, parent_uuid);
203
204 put_file(fd);
205 return result;
206 }
207
208 TSS_RESULT
ps_get_parent_ps_type_by_uuid(TSS_UUID * uuid,UINT32 * type)209 ps_get_parent_ps_type_by_uuid(TSS_UUID *uuid, UINT32 *type)
210 {
211 int fd;
212 TSS_RESULT result;
213
214 if ((result = get_file(&fd)))
215 return result;
216
217 result = psfile_get_parent_ps_type(fd, uuid, type);
218
219 put_file(fd);
220
221 return result;
222 }
223
224 TSS_RESULT
ps_close()225 ps_close()
226 {
227 TSS_RESULT result;
228 int fd;
229
230 if ((result = get_file(&fd)))
231 return result;
232
233 psfile_close(fd);
234
235 /* No need to call put_file() here, the file is closed */
236
237 return TSS_SUCCESS;
238 }
239
240 TSS_RESULT
merge_key_hierarchies(TSS_HCONTEXT tspContext,UINT32 tsp_size,TSS_KM_KEYINFO * tsp_hier,UINT32 tcs_size,TSS_KM_KEYINFO * tcs_hier,UINT32 * merged_size,TSS_KM_KEYINFO ** merged_hier)241 merge_key_hierarchies(TSS_HCONTEXT tspContext, UINT32 tsp_size, TSS_KM_KEYINFO *tsp_hier,
242 UINT32 tcs_size, TSS_KM_KEYINFO *tcs_hier, UINT32 *merged_size,
243 TSS_KM_KEYINFO **merged_hier)
244 {
245 UINT32 i, j;
246
247 *merged_hier = malloc((tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO));
248 if (*merged_hier == NULL) {
249 LogError("malloc of %zu bytes failed.", (tsp_size + tcs_size) *
250 sizeof(TSS_KM_KEYINFO));
251 return TSPERR(TSS_E_OUTOFMEMORY);
252 }
253
254 for (i = 0; i < tsp_size; i++)
255 memcpy(&((*merged_hier)[i]), &tsp_hier[i], sizeof(TSS_KM_KEYINFO));
256
257 for (j = 0; j < tcs_size; j++)
258 memcpy(&((*merged_hier)[i + j]), &tcs_hier[j], sizeof(TSS_KM_KEYINFO));
259
260 *merged_size = i + j;
261
262 return TSS_SUCCESS;
263 }
264
265
266 TSS_RESULT
merge_key_hierarchies2(TSS_HCONTEXT tspContext,UINT32 tsp_size,TSS_KM_KEYINFO2 * tsp_hier,UINT32 tcs_size,TSS_KM_KEYINFO2 * tcs_hier,UINT32 * merged_size,TSS_KM_KEYINFO2 ** merged_hier)267 merge_key_hierarchies2(TSS_HCONTEXT tspContext, UINT32 tsp_size, TSS_KM_KEYINFO2 *tsp_hier,
268 UINT32 tcs_size, TSS_KM_KEYINFO2 *tcs_hier, UINT32 *merged_size,
269 TSS_KM_KEYINFO2 **merged_hier)
270 {
271 UINT32 i, j;
272
273 *merged_hier = malloc((tsp_size + tcs_size) * sizeof(TSS_KM_KEYINFO2));
274 if (*merged_hier == NULL) {
275 LogError("malloc of %zu bytes failed.", (tsp_size + tcs_size) *
276 sizeof(TSS_KM_KEYINFO2));
277 return TSPERR(TSS_E_OUTOFMEMORY);
278 }
279
280 for (i = 0; i < tsp_size; i++)
281 memcpy(&((*merged_hier)[i]), &tsp_hier[i], sizeof(TSS_KM_KEYINFO2));
282
283 for (j = 0; j < tcs_size; j++)
284 memcpy(&((*merged_hier)[i + j]), &tcs_hier[j], sizeof(TSS_KM_KEYINFO2));
285
286 *merged_size = i + j;
287
288 return TSS_SUCCESS;
289 }
290
291
292 #if 0
293 TSS_RESULT
294 load_from_system_ps(TSS_HCONTEXT tspContext, TSS_UUID *uuid, TSS_HKEY *phKey)
295 {
296 TCS_KEY_HANDLE tcsKeyHandle;
297 TCS_LOADKEY_INFO info;
298 BYTE *keyBlob = NULL;
299
300 __tspi_memset(&info, 0, sizeof(TCS_LOADKEY_INFO));
301
302 result = TCSP_LoadKeyByUUID(tspContext, uuidData, &info, &tcsKeyHandle);
303
304 if (TSS_ERROR_CODE(result) == TCS_E_KM_LOADFAILED) {
305 TSS_HKEY keyHandle;
306 TSS_HPOLICY hPolicy;
307
308 /* load failed, due to some key in the chain needing auth
309 * which doesn't yet exist at the TCS level. However, the
310 * auth may already be set in policies at the TSP level.
311 * To find out, get the key handle of the key requiring
312 * auth. First, look at the list of keys in memory. */
313 if ((obj_rsakey_get_by_uuid(&info.parentKeyUUID, &keyHandle))) {
314 /* If that failed, look on disk, in User PS. */
315 if (ps_get_key_by_uuid(tspContext, &info.parentKeyUUID, &keyHandle))
316 return result;
317 }
318
319 if (obj_rsakey_get_policy(keyHandle, TSS_POLICY_USAGE, &hPolicy, NULL))
320 return result;
321
322 if (secret_PerformAuth_OIAP(keyHandle, TPM_ORD_LoadKey, hPolicy, &info.paramDigest,
323 &info.authData))
324 return result;
325
326 if ((result = TCSP_LoadKeyByUUID(tspContext, *uuid, &info, &tcsKeyHandle)))
327 return result;
328 } else if (result)
329 return result;
330
331 if ((result = TCS_GetRegisteredKeyBlob(tspContext, *uuid, &keyBlobSize, &keyBlob)))
332 return result;
333
334 if ((result = obj_rsakey_add_by_key(tspContext, uuid, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS,
335 phKey))) {
336 free(keyBlob);
337 return result;
338 }
339
340 result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle);
341
342 free(keyBlob);
343
344 return result;
345 }
346 #endif
347
348