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 #include "tcs_key_ps.h"
30
31 /*
32 * mem_cache_lock will be responsible for protecting the key_mem_cache_head list. This is a
33 * TCSD global linked list of all keys which have been loaded into the TPM at some time.
34 */
35 MUTEX_DECLARE_INIT(mem_cache_lock);
36
37 /*
38 * tcs_keyhandle_lock is only used to make TCS keyhandle generation atomic for all TCSD
39 * threads.
40 */
41 static MUTEX_DECLARE_INIT(tcs_keyhandle_lock);
42
43 /*
44 * timestamp_lock is only used to make TCS key timestamp generation atomic for all TCSD
45 * threads.
46 */
47 static MUTEX_DECLARE_INIT(timestamp_lock);
48
49 TCS_KEY_HANDLE
getNextTcsKeyHandle()50 getNextTcsKeyHandle()
51 {
52 static TCS_KEY_HANDLE NextTcsKeyHandle = 0x22330000;
53 TCS_KEY_HANDLE ret;
54
55 MUTEX_LOCK(tcs_keyhandle_lock);
56
57 do {
58 ret = NextTcsKeyHandle++;
59 } while (NextTcsKeyHandle == SRK_TPM_HANDLE || NextTcsKeyHandle == NULL_TCS_HANDLE);
60
61 MUTEX_UNLOCK(tcs_keyhandle_lock);
62
63 return ret;
64 }
65
66 UINT32
getNextTimeStamp()67 getNextTimeStamp()
68 {
69 static UINT32 time_stamp = 1;
70 UINT32 ret;
71
72 MUTEX_LOCK(timestamp_lock);
73 ret = time_stamp++;
74 MUTEX_UNLOCK(timestamp_lock);
75
76 return ret;
77 }
78
79 /* only called from load key paths, so no locking */
80 TCPA_STORE_PUBKEY *
mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)81 mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)
82 {
83 struct key_mem_cache *tmp;
84 TCPA_STORE_PUBKEY *ret;
85
86 if (tpm_handle == NULL_TPM_HANDLE)
87 return NULL;
88
89 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
90 LogDebugFn("TCSD mem_cached handle: 0x%x",
91 tmp->tcs_handle);
92 if (tmp->tpm_handle == tpm_handle) {
93 ret = tmp->blob ? &tmp->blob->pubKey : NULL;
94 return ret;
95 }
96 }
97 LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
98 return NULL;
99 }
100
101 /* only called from load key paths, so no locking */
102 TCPA_STORE_PUBKEY *
mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)103 mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)
104 {
105 struct key_mem_cache *tmp;
106 TCPA_STORE_PUBKEY *ret;
107
108 LogDebugFn("looking for 0x%x", tcs_handle);
109
110 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
111 LogDebugFn("TCSD mem_cached handle: 0x%x",
112 tmp->tcs_handle);
113 if (tmp->tcs_handle == tcs_handle) {
114 ret = tmp->blob ? &tmp->blob->pubKey : NULL;
115 return ret;
116 }
117 }
118
119 LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
120 return NULL;
121 }
122
123 /* only called from load key paths, so no locking */
124 TSS_RESULT
mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle,TCS_KEY_HANDLE p_tcs_handle)125 mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle, TCS_KEY_HANDLE p_tcs_handle)
126 {
127 struct key_mem_cache *tmp, *parent;
128
129 /* find parent */
130 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
131 LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
132 if (tmp->tcs_handle == p_tcs_handle) {
133 parent = tmp;
134 break;
135 }
136 }
137
138 /* didn't find parent */
139 if (tmp == NULL)
140 goto done;
141
142 /* set parent blob in child */
143 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
144 if (tmp->tcs_handle == tcs_handle) {
145 tmp->parent = parent;
146 return TSS_SUCCESS;
147 }
148 }
149 done:
150 return TCSERR(TSS_E_FAIL);
151 }
152
153 TCPA_RESULT
ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE keyHandle,TCPA_KEY_HANDLE * keySlot)154 ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE keyHandle, TCPA_KEY_HANDLE * keySlot)
155 {
156 TCPA_RESULT result = TSS_SUCCESS;
157 TCPA_STORE_PUBKEY *myPub;
158
159 LogDebugFn("0x%x", keyHandle);
160
161 if (!ctx_has_key_loaded(hContext, keyHandle))
162 return TCSERR(TCS_E_INVALID_KEY);
163
164 MUTEX_LOCK(mem_cache_lock);
165
166 *keySlot = mc_get_slot_by_handle(keyHandle);
167 LogDebug("keySlot is %08X", *keySlot);
168 if (*keySlot == NULL_TPM_HANDLE || isKeyLoaded(*keySlot) == FALSE) {
169 LogDebug("calling mc_get_pub_by_handle");
170 if ((myPub = mc_get_pub_by_handle(keyHandle)) == NULL) {
171 LogDebug("Failed to find pub by handle");
172 result = TCSERR(TCS_E_KM_LOADFAILED);
173 goto done;
174 }
175
176 LogDebugFn("calling LoadKeyShim");
177 if ((result = LoadKeyShim(hContext, myPub, NULL, keySlot))) {
178 LogDebug("Failed shim");
179 goto done;
180 }
181
182 if (*keySlot == NULL_TPM_HANDLE) {
183 LogDebug("Key slot is still invalid after ensureKeyIsLoaded");
184 result = TCSERR(TCS_E_KM_LOADFAILED);
185 goto done;
186 }
187 }
188 mc_update_time_stamp(*keySlot);
189
190 done:
191 MUTEX_UNLOCK(mem_cache_lock);
192 LogDebugFn("Exit");
193 return result;
194 }
195
196
197 /* only called from load key paths, so no locking */
198 TSS_UUID *
mc_get_uuid_by_pub(TCPA_STORE_PUBKEY * pub)199 mc_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub)
200 {
201 TSS_UUID *ret;
202 struct key_mem_cache *tmp;
203
204 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
205 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
206 if (tmp->blob &&
207 tmp->blob->pubKey.keyLength == pub->keyLength &&
208 !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
209 ret = &tmp->uuid;
210 return ret;
211 }
212 }
213
214 return NULL;
215 }
216
217 TSS_RESULT
mc_get_handles_by_uuid(TSS_UUID * uuid,TCS_KEY_HANDLE * tcsHandle,TCPA_KEY_HANDLE * slot)218 mc_get_handles_by_uuid(TSS_UUID *uuid, TCS_KEY_HANDLE *tcsHandle, TCPA_KEY_HANDLE *slot)
219 {
220 struct key_mem_cache *tmp;
221
222 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
223 if (!memcmp(&tmp->uuid, uuid, sizeof(TSS_UUID))) {
224 *tcsHandle = tmp->tcs_handle;
225 *slot = tmp->tpm_handle;
226 return TSS_SUCCESS;
227 }
228 }
229
230 return TCSERR(TSS_E_FAIL);
231 }
232
233 TCS_KEY_HANDLE
mc_get_handle_by_encdata(BYTE * encData)234 mc_get_handle_by_encdata(BYTE *encData)
235 {
236 struct key_mem_cache *tmp;
237 TCS_KEY_HANDLE ret;
238
239 MUTEX_LOCK(mem_cache_lock);
240
241 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
242 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
243 if (!tmp->blob || tmp->blob->encSize == 0)
244 continue;
245 if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
246 ret = tmp->tcs_handle;
247 MUTEX_UNLOCK(mem_cache_lock);
248 return ret;
249 }
250 }
251 MUTEX_UNLOCK(mem_cache_lock);
252 return 0;
253 }
254
255 TSS_RESULT
mc_update_encdata(BYTE * encData,BYTE * newEncData)256 mc_update_encdata(BYTE *encData, BYTE *newEncData)
257 {
258 struct key_mem_cache *tmp;
259 BYTE *tmp_enc_data;
260
261 MUTEX_LOCK(mem_cache_lock);
262
263 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
264 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
265 if (!tmp->blob || tmp->blob->encSize == 0)
266 continue;
267 if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
268 tmp_enc_data = (BYTE *)malloc(tmp->blob->encSize);
269 if (tmp_enc_data == NULL) {
270 LogError("malloc of %u bytes failed.", tmp->blob->encSize);
271 MUTEX_UNLOCK(mem_cache_lock);
272 return TCSERR(TSS_E_OUTOFMEMORY);
273 }
274
275 memcpy(tmp_enc_data, newEncData, tmp->blob->encSize);
276 free(tmp->blob->encData);
277 tmp->blob->encData = tmp_enc_data;
278 MUTEX_UNLOCK(mem_cache_lock);
279 return TSS_SUCCESS;
280 }
281 }
282 MUTEX_UNLOCK(mem_cache_lock);
283 LogError("Couldn't find requested encdata in mem cache");
284 return TCSERR(TSS_E_INTERNAL_ERROR);
285 }
286
287 /*
288 * only called from load key paths and the init (single thread time) path,
289 * so no locking
290 */
291 TSS_RESULT
mc_add_entry(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle,TSS_KEY * key_blob)292 mc_add_entry(TCS_KEY_HANDLE tcs_handle,
293 TCPA_KEY_HANDLE tpm_handle,
294 TSS_KEY *key_blob)
295 {
296 struct key_mem_cache *entry, *tmp;
297
298 /* Make sure the cache doesn't already have an entry for this key */
299 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
300 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
301 if (tcs_handle == tmp->tcs_handle) {
302 return TSS_SUCCESS;
303 }
304 }
305
306 /* Not found - we need to create a new entry */
307 entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
308 if (entry == NULL) {
309 LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
310 return TCSERR(TSS_E_OUTOFMEMORY);
311 }
312
313 entry->tcs_handle = tcs_handle;
314 if (tpm_handle != NULL_TPM_HANDLE)
315 entry->time_stamp = getNextTimeStamp();
316
317 entry->tpm_handle = tpm_handle;
318
319 if (!key_blob)
320 goto add;
321
322 /* allocate space for the blob */
323 entry->blob = calloc(1, sizeof(TSS_KEY));
324 if (entry->blob == NULL) {
325 LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
326 free(entry);
327 return TCSERR(TSS_E_OUTOFMEMORY);
328 }
329 memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
330
331 /* allocate space for the key parameters if necessary */
332 if (key_blob->algorithmParms.parmSize) {
333 BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
334 if (tmp_parms == NULL) {
335 LogError("malloc of %u bytes failed.", key_blob->algorithmParms.parmSize);
336 free(entry->blob);
337 free(entry);
338 return TCSERR(TSS_E_OUTOFMEMORY);
339 }
340 memcpy(tmp_parms, key_blob->algorithmParms.parms, key_blob->algorithmParms.parmSize);
341 entry->blob->algorithmParms.parms = tmp_parms;
342 }
343 entry->blob->algorithmParms.parmSize = key_blob->algorithmParms.parmSize;
344
345 /* allocate space for the public key */
346 if (key_blob->pubKey.keyLength > 0) {
347 entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
348 if (entry->blob->pubKey.key == NULL) {
349 LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
350 free(entry->blob->algorithmParms.parms);
351 free(entry->blob);
352 free(entry);
353 return TCSERR(TSS_E_OUTOFMEMORY);
354 }
355 memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
356 }
357 entry->blob->pubKey.keyLength = key_blob->pubKey.keyLength;
358
359 /* allocate space for the PCR info */
360 if (key_blob->PCRInfoSize > 0) {
361 entry->blob->PCRInfo = (BYTE *)malloc(key_blob->PCRInfoSize);
362 if (entry->blob->PCRInfo == NULL) {
363 LogError("malloc of %u bytes failed.", key_blob->PCRInfoSize);
364 free(entry->blob->pubKey.key);
365 free(entry->blob->algorithmParms.parms);
366 free(entry->blob);
367 free(entry);
368 return TCSERR(TSS_E_OUTOFMEMORY);
369 }
370 memcpy(entry->blob->PCRInfo, key_blob->PCRInfo, key_blob->PCRInfoSize);
371 }
372 entry->blob->PCRInfoSize = key_blob->PCRInfoSize;
373
374 /* allocate space for the encData if necessary */
375 if (key_blob->encSize > 0) {
376 entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
377 if (entry->blob->encData == NULL) {
378 LogError("malloc of %u bytes failed.", key_blob->encSize);
379 free(entry->blob->PCRInfo);
380 free(entry->blob->pubKey.key);
381 free(entry->blob->algorithmParms.parms);
382 free(entry->blob);
383 free(entry);
384 return TCSERR(TSS_E_OUTOFMEMORY);
385 }
386 memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
387 }
388 entry->blob->encSize = key_blob->encSize;
389 add:
390 /* add to the front of the list */
391 entry->next = key_mem_cache_head;
392 if (key_mem_cache_head) {
393 /* set the reference count to 0 initially for all keys not being the SRK. Up
394 * the call chain, a reference to this mem cache entry will be set in the
395 * context object of the calling context and this reference count will be
396 * incremented there. */
397 entry->ref_cnt = 0;
398
399 key_mem_cache_head->prev = entry;
400 } else {
401 /* if we are the SRK, initially set the reference count to 1, so that it is
402 * always seen as loaded in the TPM. */
403 entry->ref_cnt = 1;
404 }
405 key_mem_cache_head = entry;
406
407 return TSS_SUCCESS;
408 }
409
410 /* caller must lock the mem cache before calling! */
411 TSS_RESULT
mc_remove_entry(TCS_KEY_HANDLE tcs_handle)412 mc_remove_entry(TCS_KEY_HANDLE tcs_handle)
413 {
414 struct key_mem_cache *cur;
415
416 for (cur = key_mem_cache_head; cur; cur = cur->next) {
417 if (cur->tcs_handle == tcs_handle) {
418 if (cur->blob) {
419 destroy_key_refs(cur->blob);
420 free(cur->blob);
421 }
422
423 if (cur->prev != NULL)
424 cur->prev->next = cur->next;
425 if (cur->next != NULL)
426 cur->next->prev = cur->prev;
427
428 if (cur == key_mem_cache_head)
429 key_mem_cache_head = cur->next;
430 free(cur);
431
432 return TSS_SUCCESS;
433 }
434 }
435
436 return TCSERR(TSS_E_FAIL);
437 }
438
439 TSS_RESULT
mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle,TSS_KEY * key_blob,TSS_UUID * uuid)440 mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,
441 TCPA_KEY_HANDLE tpm_handle,
442 TSS_KEY *key_blob,
443 TSS_UUID *uuid)
444 {
445 struct key_mem_cache *entry, *tmp;
446
447 /* Make sure the cache doesn't already have an entry for this key */
448 MUTEX_LOCK(mem_cache_lock);
449 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
450 if (tcs_handle == tmp->tcs_handle) {
451 mc_remove_entry(tcs_handle);
452 }
453 }
454 MUTEX_UNLOCK(mem_cache_lock);
455
456 /* Not found - we need to create a new entry */
457 entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
458 if (entry == NULL) {
459 LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
460 return TCSERR(TSS_E_OUTOFMEMORY);
461 }
462
463 entry->tcs_handle = tcs_handle;
464 if (tpm_handle != NULL_TPM_HANDLE)
465 entry->time_stamp = getNextTimeStamp();
466
467 entry->tpm_handle = tpm_handle;
468
469 if (key_blob) {
470 /* allocate space for the blob */
471 entry->blob = malloc(sizeof(TSS_KEY));
472 if (entry->blob == NULL) {
473 LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
474 free(entry);
475 return TCSERR(TSS_E_OUTOFMEMORY);
476 }
477
478 memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
479
480 /* allocate space for the key parameters if necessary */
481 if (key_blob->algorithmParms.parmSize) {
482 BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
483 if (tmp_parms == NULL) {
484 LogError("malloc of %u bytes failed.",
485 key_blob->algorithmParms.parmSize);
486 free(entry->blob);
487 free(entry);
488 return TCSERR(TSS_E_OUTOFMEMORY);
489 }
490 memcpy(tmp_parms, key_blob->algorithmParms.parms,
491 key_blob->algorithmParms.parmSize);
492 entry->blob->algorithmParms.parms = tmp_parms;
493 }
494
495 /* allocate space for the public key */
496 entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
497 if (entry->blob->pubKey.key == NULL) {
498 LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
499 free(entry->blob);
500 free(entry);
501 return TCSERR(TSS_E_OUTOFMEMORY);
502 }
503 memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
504
505 /* allocate space for the encData if necessary */
506 if (key_blob->encSize != 0) {
507 entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
508 if (entry->blob->encData == NULL) {
509 LogError("malloc of %u bytes failed.", key_blob->encSize);
510 free(entry->blob->pubKey.key);
511 free(entry->blob);
512 free(entry);
513 return TCSERR(TSS_E_OUTOFMEMORY);
514 }
515 memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
516 }
517 entry->blob->encSize = key_blob->encSize;
518 }
519
520 memcpy(&entry->uuid, uuid, sizeof(TSS_UUID));
521
522 MUTEX_LOCK(mem_cache_lock);
523
524 entry->next = key_mem_cache_head;
525 if (key_mem_cache_head)
526 key_mem_cache_head->prev = entry;
527
528 entry->ref_cnt = 1;
529 key_mem_cache_head = entry;
530 MUTEX_UNLOCK(mem_cache_lock);
531
532 return TSS_SUCCESS;
533 }
534
535 /* only called from evict key paths, so no locking */
536 TSS_RESULT
mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle,TCPA_KEY_HANDLE new_handle)537 mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle, TCPA_KEY_HANDLE new_handle)
538 {
539 struct key_mem_cache *tmp;
540
541 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
542 if (tmp->tpm_handle == old_handle) {
543 LogDebugFn("Set TCS key 0x%x, old TPM handle: 0x%x "
544 "new TPM handle: 0x%x", tmp->tcs_handle,
545 old_handle, new_handle);
546 if (new_handle == NULL_TPM_HANDLE)
547 tmp->time_stamp = 0;
548 else
549 tmp->time_stamp = getNextTimeStamp();
550 tmp->tpm_handle = new_handle;
551 return TSS_SUCCESS;
552 }
553 }
554
555 return TCSERR(TSS_E_FAIL);
556 }
557
558 /* only called from load key paths, so no locking */
559 TSS_RESULT
mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle,TCPA_KEY_HANDLE tpm_handle)560 mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle, TCPA_KEY_HANDLE tpm_handle)
561 {
562 struct key_mem_cache *tmp;
563
564 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
565 LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
566 if (tmp->tcs_handle == tcs_handle) {
567 if (tpm_handle == NULL_TPM_HANDLE)
568 tmp->time_stamp = 0;
569 else
570 tmp->time_stamp = getNextTimeStamp();
571 tmp->tpm_handle = tpm_handle;
572 return TSS_SUCCESS;
573 }
574 }
575
576 return TCSERR(TSS_E_FAIL);
577 }
578
579 /* the beginnings of a key manager start here ;-) */
580
581 TSS_RESULT
key_mgr_evict(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hKey)582 key_mgr_evict(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey)
583 {
584 TSS_RESULT result = TCS_SUCCESS;
585
586 if ((result = ctx_remove_key_loaded(hContext, hKey)))
587 return result;
588
589 if ((result = key_mgr_dec_ref_count(hKey)))
590 return result;
591
592 key_mgr_ref_count();
593
594 return result;
595 }
596
597 TSS_RESULT
key_mgr_load_by_blob(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hUnwrappingKey,UINT32 cWrappedKeyBlob,BYTE * rgbWrappedKeyBlob,TPM_AUTH * pAuth,TCS_KEY_HANDLE * phKeyTCSI,TCS_KEY_HANDLE * phKeyHMAC)598 key_mgr_load_by_blob(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hUnwrappingKey,
599 UINT32 cWrappedKeyBlob, BYTE *rgbWrappedKeyBlob,
600 TPM_AUTH *pAuth, TCS_KEY_HANDLE *phKeyTCSI, TCS_KEY_HANDLE *phKeyHMAC)
601 {
602 TSS_RESULT result;
603
604 /* Check that auth for the parent key is loaded outside the mem_cache_lock. We have to do
605 * this here because if the TPM can't process this request right now, the thread could be
606 * put to sleep while holding the mem_cache_lock, which would result in a deadlock */
607 if (pAuth) {
608 if ((result = auth_mgr_check(hContext, &pAuth->AuthHandle)))
609 return result;
610 }
611
612 MUTEX_LOCK(mem_cache_lock);
613
614 if (TPM_VERSION_IS(1,2)) {
615 result = TCSP_LoadKey2ByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
616 rgbWrappedKeyBlob, pAuth, phKeyTCSI);
617 } else {
618 result = TCSP_LoadKeyByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
619 rgbWrappedKeyBlob, pAuth, phKeyTCSI,
620 phKeyHMAC);
621 }
622
623 MUTEX_UNLOCK(mem_cache_lock);
624
625 return result;
626 }
627
628 /* create a reference to one key. This is called from the key_mgr_load_*
629 * functions only, so no locking is done.
630 */
631 TSS_RESULT
key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)632 key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)
633 {
634 struct key_mem_cache *cur;
635
636 for (cur = key_mem_cache_head; cur; cur = cur->next) {
637 LogDebugFn("TCSD mem_cached handle: 0x%x", cur->tcs_handle);
638 if (cur->tcs_handle == key_handle) {
639 cur->ref_cnt++;
640 return TSS_SUCCESS;
641 }
642 }
643
644 return TCSERR(TSS_E_FAIL);
645 }
646
647 /* de-reference one key. This is called by the context routines, so
648 * locking is necessary.
649 */
650 TSS_RESULT
key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)651 key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)
652 {
653 struct key_mem_cache *cur;
654
655 MUTEX_LOCK(mem_cache_lock);
656
657 for (cur = key_mem_cache_head; cur; cur = cur->next) {
658 if (cur->tcs_handle == key_handle) {
659 cur->ref_cnt--;
660 LogDebugFn("decrementing ref cnt for key 0x%x",
661 key_handle);
662 MUTEX_UNLOCK(mem_cache_lock);
663 return TSS_SUCCESS;
664 }
665 }
666
667 MUTEX_UNLOCK(mem_cache_lock);
668 return TCSERR(TSS_E_FAIL);
669 }
670
671 /* run through the global list and free any keys with reference counts of 0 */
672 void
key_mgr_ref_count()673 key_mgr_ref_count()
674 {
675 struct key_mem_cache *tmp, *cur;
676
677 MUTEX_LOCK(mem_cache_lock);
678
679 for (cur = key_mem_cache_head; cur;) {
680 if (cur->ref_cnt == 0) {
681 if (cur->tpm_handle != NULL_TPM_HANDLE) {
682 LogDebugFn("Key 0x%x being freed from TPM", cur->tpm_handle);
683 internal_EvictByKeySlot(cur->tpm_handle);
684 }
685 LogDebugFn("Key 0x%x being freed", cur->tcs_handle);
686 if (cur->blob) {
687 destroy_key_refs(cur->blob);
688 free(cur->blob);
689 }
690 if (cur->prev != NULL)
691 cur->prev->next = cur->next;
692 if (cur->next != NULL)
693 cur->next->prev = cur->prev;
694
695 tmp = cur;
696 if (cur == key_mem_cache_head)
697 key_mem_cache_head = cur->next;
698 cur = cur->next;
699 free(tmp);
700 } else {
701 cur = cur->next;
702 }
703 }
704
705 MUTEX_UNLOCK(mem_cache_lock);
706 }
707
708 /* only called from load key paths, so no locking */
709 TCPA_KEY_HANDLE
mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_handle)710 mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_handle)
711 {
712 struct key_mem_cache *tmp;
713 TCS_KEY_HANDLE ret;
714
715 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
716 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
717 if (tmp->tcs_handle == tcs_handle) {
718 ret = tmp->tpm_handle;
719 return ret;
720 }
721 }
722
723 LogDebugFn("returning NULL_TPM_HANDLE");
724 return NULL_TPM_HANDLE;
725 }
726
727 /* called from functions outside the load key path */
728 TCPA_KEY_HANDLE
mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_handle)729 mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_handle)
730 {
731 struct key_mem_cache *tmp;
732 TCS_KEY_HANDLE ret;
733
734 MUTEX_LOCK(mem_cache_lock);
735
736 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
737 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
738 if (tmp->tcs_handle == tcs_handle) {
739 ret = tmp->tpm_handle;
740 MUTEX_UNLOCK(mem_cache_lock);
741 return ret;
742 }
743 }
744
745 MUTEX_UNLOCK(mem_cache_lock);
746 LogDebugFn("returning NULL_TPM_HANDLE");
747 return NULL_TPM_HANDLE;
748 }
749
750 /* only called from load key paths, so no locking */
751 TCPA_KEY_HANDLE
mc_get_slot_by_pub(TCPA_STORE_PUBKEY * pub)752 mc_get_slot_by_pub(TCPA_STORE_PUBKEY *pub)
753 {
754 struct key_mem_cache *tmp;
755 TCPA_KEY_HANDLE ret;
756
757 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
758 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
759 if (tmp->blob &&
760 !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
761 ret = tmp->tpm_handle;
762 return ret;
763 }
764 }
765
766 LogDebugFn("returning NULL_TPM_HANDLE");
767 return NULL_TPM_HANDLE;
768 }
769
770 /* Check the mem cache for a key with public key pub. If a parent TCS key handle
771 * is passed in, make sure the parent of the key find matches it, else return
772 * key not found */
773 /* only called from load key paths, so no locking */
774 TCS_KEY_HANDLE
mc_get_handle_by_pub(TCPA_STORE_PUBKEY * pub,TCS_KEY_HANDLE parent)775 mc_get_handle_by_pub(TCPA_STORE_PUBKEY *pub, TCS_KEY_HANDLE parent)
776 {
777 struct key_mem_cache *tmp;
778
779 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
780 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
781 if (tmp->blob &&
782 pub->keyLength == tmp->blob->pubKey.keyLength &&
783 !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
784 if (parent) {
785 if (!tmp->parent)
786 continue;
787 if (parent == tmp->parent->tcs_handle)
788 return tmp->tcs_handle;
789 } else
790 return tmp->tcs_handle;
791 }
792 }
793
794 LogDebugFn("returning NULL_TCS_HANDLE");
795 return NULL_TCS_HANDLE;
796 }
797
798 /* only called from load key paths, so no locking */
799 TCPA_STORE_PUBKEY *
mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY * pub)800 mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY *pub)
801 {
802 struct key_mem_cache *tmp;
803 TCPA_STORE_PUBKEY *ret = NULL;
804
805 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
806 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
807 if (tmp->tcs_handle == TPM_KEYHND_SRK) {
808 LogDebugFn("skipping the SRK");
809 continue;
810 }
811 if (tmp->blob &&
812 !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
813 if (tmp->parent && tmp->parent->blob) {
814 ret = &tmp->parent->blob->pubKey;
815 LogDebugFn("Success");
816 } else {
817 LogError("parent pointer not set in key mem cache object w/ TCS "
818 "handle: 0x%x", tmp->tcs_handle);
819 }
820 return ret;
821 }
822 }
823
824 LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
825 return NULL;
826 }
827
828 /* only called from load key paths, so no locking */
829 TSS_RESULT
mc_get_blob_by_pub(TCPA_STORE_PUBKEY * pub,TSS_KEY ** ret_key)830 mc_get_blob_by_pub(TCPA_STORE_PUBKEY *pub, TSS_KEY **ret_key)
831 {
832 struct key_mem_cache *tmp;
833
834 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
835 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
836 if (tmp->blob &&
837 !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
838 *ret_key = tmp->blob;
839 return TSS_SUCCESS;
840 }
841 }
842
843 LogDebugFn("returning TSS_E_FAIL");
844 return TCSERR(TSS_E_FAIL);
845 }
846
847 /* only called from load key paths, so no locking */
848 TCS_KEY_HANDLE
mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_handle)849 mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_handle)
850 {
851 struct key_mem_cache *tmp;
852 TCS_KEY_HANDLE ret;
853
854 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
855 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
856 if (tmp->tpm_handle == tpm_handle) {
857 ret = tmp->tcs_handle;
858 return ret;
859 }
860 }
861
862 return NULL_TCS_HANDLE;
863 }
864
865 /* only called from load key paths, so no locking */
866 TSS_RESULT
mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)867 mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)
868 {
869 struct key_mem_cache *tmp;
870
871 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
872 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
873 if (tmp->tpm_handle == tpm_handle) {
874 tmp->time_stamp = getNextTimeStamp();
875 return TSS_SUCCESS;
876 }
877 }
878
879 return TCSERR(TSS_E_FAIL);
880 }
881
882 /* Right now this evicts the LRU key assuming it's not the parent */
883 TSS_RESULT
evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)884 evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)
885 {
886 struct key_mem_cache *tmp;
887 TCS_KEY_HANDLE tpm_handle_to_evict = NULL_TPM_HANDLE;
888 UINT32 smallestTimeStamp = ~(0U); /* largest */
889 TSS_RESULT result;
890 UINT32 count;
891
892 /* First, see if there are any known keys worth evicting */
893 if ((result = clearUnknownKeys(InternalContext, &count)))
894 return result;
895
896 if (count > 0) {
897 LogDebugFn("Evicted %u unknown keys", count);
898 return TSS_SUCCESS;
899 }
900
901 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
902 if (tmp->tpm_handle != NULL_TPM_HANDLE && /* not already evicted */
903 tmp->tpm_handle != SRK_TPM_HANDLE && /* not the srk */
904 tmp->tcs_handle != parent_tcs_handle && /* not my parent */
905 tmp->time_stamp < smallestTimeStamp) { /* is the smallest time
906 stamp so far */
907 tpm_handle_to_evict = tmp->tpm_handle;
908 smallestTimeStamp = tmp->time_stamp;
909 }
910 }
911
912 if (tpm_handle_to_evict != NULL_TCS_HANDLE) {
913 if ((result = internal_EvictByKeySlot(tpm_handle_to_evict)))
914 return result;
915
916 LogDebugFn("Evicted key w/ TPM handle 0x%x", tpm_handle_to_evict);
917 result = mc_set_slot_by_slot(tpm_handle_to_evict, NULL_TPM_HANDLE);
918 } else
919 return TSS_SUCCESS;
920
921 return result;
922 }
923
924 TSS_BOOL
isKeyLoaded(TCPA_KEY_HANDLE keySlot)925 isKeyLoaded(TCPA_KEY_HANDLE keySlot)
926 {
927 UINT64 offset;
928 UINT32 i;
929 TCPA_KEY_HANDLE_LIST keyList;
930 UINT32 respSize;
931 BYTE *resp;
932 TSS_RESULT result;
933
934 if (keySlot == SRK_TPM_HANDLE) {
935 return TRUE;
936 }
937
938 if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_KEY_HANDLE, 0, NULL,
939 &respSize, &resp)))
940 goto not_loaded;
941
942 offset = 0;
943 UnloadBlob_KEY_HANDLE_LIST(&offset, resp, &keyList);
944 free(resp);
945 for (i = 0; i < keyList.loaded; i++) {
946 LogDebugFn("loaded TPM key handle: 0x%x", keyList.handle[i]);
947 if (keyList.handle[i] == keySlot) {
948 free(keyList.handle);
949 return TRUE;
950 }
951 }
952
953 free(keyList.handle);
954
955 not_loaded:
956 LogDebugFn("Key is not loaded, changing slot");
957 mc_set_slot_by_slot(keySlot, NULL_TPM_HANDLE);
958 return FALSE;
959 }
960
961 /* all calls to LoadKeyShim are inside locks */
962 TSS_RESULT
LoadKeyShim(TCS_CONTEXT_HANDLE hContext,TCPA_STORE_PUBKEY * pubKey,TSS_UUID * parentUuid,TCPA_KEY_HANDLE * slotOut)963 LoadKeyShim(TCS_CONTEXT_HANDLE hContext, TCPA_STORE_PUBKEY *pubKey,
964 TSS_UUID *parentUuid, TCPA_KEY_HANDLE *slotOut)
965 {
966
967 TCPA_STORE_PUBKEY *parentPub;
968 UINT32 result;
969 TCPA_KEY_HANDLE keySlot;
970 TCPA_KEY_HANDLE parentSlot;
971 TCS_KEY_HANDLE tcsKeyHandle;
972 TSS_KEY *myKey;
973 UINT64 offset;
974 TCS_KEY_HANDLE parentHandle;
975 BYTE keyBlob[1024];
976
977 LogDebugFn("calling mc_get_slot_by_pub");
978
979 /* If I'm loaded, then no point being here. Get the slot and return */
980 keySlot = mc_get_slot_by_pub(pubKey);
981 if (keySlot != NULL_TPM_HANDLE && isKeyLoaded(keySlot)) {
982 *slotOut = keySlot;
983 return TSS_SUCCESS;
984 }
985
986 /*
987 * Before proceeding, the parent must be loaded.
988 * If the parent is registered, then it can be loaded by UUID.
989 * If not, then the shim will be called to load it's parent and then try
990 * to load it based on the persistent store.
991 */
992
993 LogDebugFn("calling mc_get_parent_pub_by_pub");
994 /* Check if the Key is in the memory cache */
995 if ((parentPub = mc_get_parent_pub_by_pub(pubKey)) == NULL) {
996 #if 0
997 LogDebugFn("parentPub is NULL");
998 /* If parentUUID is not handed in, then this key was never loaded and isn't reg'd */
999 if (parentUuid == NULL)
1000 return TCSERR(TCS_E_KM_LOADFAILED);
1001
1002 LogDebugFn("calling TCSP_LoadKeyByUUID_Internal");
1003 /* This will try to load my parent by UUID */
1004 if ((result = TCSP_LoadKeyByUUID_Internal(hContext, parentUuid, NULL, &parentSlot)))
1005 return result;
1006 #else
1007 return TCSERR(TCS_E_KM_LOADFAILED);
1008 #endif
1009 } else {
1010 LogDebugFn("calling LoadKeyShim");
1011 if ((result = LoadKeyShim(hContext, parentPub, NULL, &parentSlot)))
1012 return result;
1013 }
1014
1015 /*
1016 * Now that the parent is loaded, I can load myself.
1017 * If I'm registered, that's by UUID. If I'm not,
1018 * that's by blob. If there is no persistent storage data, then I cannot be
1019 * loaded by blob. The user must have some point loaded this key manually.
1020 */
1021
1022 /* check the mem cache */
1023 if (mc_get_blob_by_pub(pubKey, &myKey) == TSS_SUCCESS) {
1024 parentHandle = mc_get_handle_by_slot(parentSlot);
1025 if (parentHandle == 0)
1026 return TCSERR(TCS_E_KM_LOADFAILED);
1027
1028 offset = 0;
1029 LoadBlob_TSS_KEY(&offset, keyBlob, myKey);
1030 if (TPM_VERSION_IS(1,2))
1031 result = TCSP_LoadKey2ByBlob_Internal(hContext,
1032 parentHandle, offset,
1033 keyBlob, NULL,
1034 &tcsKeyHandle);
1035 else
1036 result = TCSP_LoadKeyByBlob_Internal(hContext,
1037 parentHandle, offset,
1038 keyBlob, NULL,
1039 &tcsKeyHandle, slotOut);
1040 if (result)
1041 return result;
1042
1043 return ctx_mark_key_loaded(hContext, tcsKeyHandle);
1044 #if TSS_BUILD_PS
1045 } else {
1046 TSS_UUID *uuid;
1047
1048 /* check registered */
1049 if (ps_is_pub_registered(pubKey) == FALSE)
1050 return TCSERR(TCS_E_KM_LOADFAILED);
1051 //uuid = mc_get_uuid_by_pub(pubKey); // XXX pub is not in MC
1052 if ((result = ps_get_uuid_by_pub(pubKey, &uuid)))
1053 return result;
1054
1055 if ((result = TCSP_LoadKeyByUUID_Internal(hContext, uuid, NULL, &tcsKeyHandle))) {
1056 free(uuid);
1057 return result;
1058 }
1059 free(uuid);
1060 *slotOut = mc_get_slot_by_handle(tcsKeyHandle);
1061
1062 return ctx_mark_key_loaded(hContext, tcsKeyHandle);
1063 #endif
1064 }
1065
1066 return TCSERR(TCS_E_KM_LOADFAILED);
1067 }
1068
1069 TSS_RESULT
owner_evict_init()1070 owner_evict_init()
1071 {
1072 TSS_RESULT result = TSS_SUCCESS;
1073 TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
1074 BYTE *respData = NULL, ownerEvictCtr = 0;
1075 UINT32 respDataSize = 0, i;
1076 UINT64 offset = 0;
1077
1078 /* If we're a 1.1 TPM, we can exit immediately since only 1.2+ supports owner evict */
1079 if (TPM_VERSION_IS(1,1))
1080 return TSS_SUCCESS;
1081
1082 if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_HANDLE, 0, NULL,
1083 &respDataSize, &respData)))
1084 return result;
1085
1086 if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) {
1087 free(respData);
1088 return result;
1089 }
1090
1091 free(respData);
1092 for (i = 0; i < keyList.loaded; i++) {
1093 UINT64 offset = 0;
1094 UINT32 keyHandle;
1095
1096 LoadBlob_UINT32(&offset, keyList.handle[i], (BYTE *)&keyHandle);
1097 /* get the ownerEvict flag for this key handle */
1098 result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_STATUS,
1099 sizeof(UINT32), (BYTE *)&keyHandle,
1100 &respDataSize, &respData);
1101 /* special case, invalid keys are automatically evicted later */
1102 if (result == TPM_E_INVALID_KEYHANDLE) {
1103 result = TSS_SUCCESS;
1104 continue;
1105 }
1106
1107 if (result != TSS_SUCCESS) {
1108 free(keyList.handle);
1109 return result;
1110 }
1111
1112 if (*(TPM_BOOL *)respData == TRUE) {
1113 TSS_UUID uuid = TSS_UUID_OWNEREVICT(ownerEvictCtr);
1114
1115 LogDebugFn("Found an owner evict key, assigned uuid %hhu", ownerEvictCtr);
1116 if ((result = mc_add_entry_init(getNextTcsKeyHandle(), keyList.handle[i],
1117 NULL, &uuid))) {
1118 free(keyList.handle);
1119 return result;
1120 }
1121 ownerEvictCtr++;
1122 }
1123 }
1124
1125 return result;
1126 }
1127
1128 /* find next lowest OWNEREVICT uuid */
1129 TSS_RESULT
mc_find_next_ownerevict_uuid(TSS_UUID * uuid)1130 mc_find_next_ownerevict_uuid(TSS_UUID *uuid)
1131 {
1132 TCS_KEY_HANDLE tmpKey;
1133 TCPA_KEY_HANDLE tmpSlot;
1134 UINT16 seed = 0;
1135 TSS_RESULT result = TCSERR(TSS_E_FAIL);
1136
1137 MUTEX_LOCK(mem_cache_lock);
1138
1139 for (seed = 0; seed <= 255; seed++) {
1140 TSS_UUID tmpUuid = TSS_UUID_OWNEREVICT(seed);
1141
1142 /* if UUID is found, continue on, trying the next UUID */
1143 if (!mc_get_handles_by_uuid(&tmpUuid, &tmpKey, &tmpSlot))
1144 continue;
1145
1146 /* UUID is not found, so its the first one available */
1147 memcpy(uuid, &tmpUuid, sizeof(TSS_UUID));
1148 result = TSS_SUCCESS;
1149 break;
1150 }
1151
1152 MUTEX_UNLOCK(mem_cache_lock);
1153 return result;
1154 }
1155
1156 TSS_RESULT
mc_set_uuid(TCS_KEY_HANDLE tcs_handle,TSS_UUID * uuid)1157 mc_set_uuid(TCS_KEY_HANDLE tcs_handle, TSS_UUID *uuid)
1158 {
1159 struct key_mem_cache *tmp;
1160 TSS_RESULT result = TCSERR(TSS_E_FAIL);
1161
1162 MUTEX_LOCK(mem_cache_lock);
1163
1164 LogDebugFn("looking for 0x%x", tcs_handle);
1165
1166 for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
1167 LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
1168 if (tmp->tcs_handle == tcs_handle) {
1169 LogDebugFn("Handle found, re-setting UUID");
1170 memcpy(&tmp->uuid, uuid, sizeof(TSS_UUID));
1171 result = TSS_SUCCESS;
1172 break;
1173 }
1174 }
1175 MUTEX_UNLOCK(mem_cache_lock);
1176
1177 return result;
1178 }
1179