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