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
62TSS_RESULT
63ps_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
78TSS_RESULT
79ps_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
95TSS_RESULT
96ps_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
111TSS_RESULT
112ps_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
133TSS_RESULT
134ps_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
148TSS_RESULT
149ps_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
171TSS_RESULT
172ps_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
193TSS_RESULT
194ps_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
208TSS_RESULT
209ps_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
224TSS_RESULT
225ps_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
240TSS_RESULT
241merge_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
266TSS_RESULT
267merge_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
293TSS_RESULT
294load_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