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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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