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