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 <time.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 
17 #include "trousers/tss.h"
18 #include "trousers_types.h"
19 #include "tcs_context.h"
20 #include "tcs_tsp.h"
21 #include "tcs_utils.h"
22 #include "tcs_int_literals.h"
23 #include "capabilities.h"
24 #include "tcslog.h"
25 
26 MUTEX_DECLARE_EXTERN(tcs_ctx_lock);
27 
28 /* runs through the list of all keys loaded by context c and decrements
29  * their ref count by 1, then free's their structures.
30  */
31 void
ctx_ref_count_keys(struct tcs_context * c)32 ctx_ref_count_keys(struct tcs_context *c)
33 {
34 	struct keys_loaded *cur, *prev;
35 
36 	if (c == NULL)
37 		return;
38 
39 	cur = prev = c->keys;
40 
41 	while (cur != NULL) {
42 		key_mgr_dec_ref_count(cur->key_handle);
43 		cur = cur->next;
44 		free(prev);
45 		prev = cur;
46 	}
47 }
48 /* Traverse loaded keys list and if matching key handle is found return TRUE else return FALSE
49  */
50 TSS_BOOL
ctx_has_key_loaded(TCS_CONTEXT_HANDLE ctx_handle,TCS_KEY_HANDLE key_handle)51 ctx_has_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle)
52 {
53 	struct tcs_context *c;
54 	struct keys_loaded *k = NULL;
55 
56 	MUTEX_LOCK(tcs_ctx_lock);
57 
58 	c = get_context(ctx_handle);
59 	if (c == NULL) {
60 		MUTEX_UNLOCK(tcs_ctx_lock);
61 		return FALSE;
62 	}
63 	k = c->keys;
64 	while (k != NULL) {
65 		if (k->key_handle == key_handle) {
66 			MUTEX_UNLOCK(tcs_ctx_lock);
67 			return TRUE;
68 		}
69 		k = k->next;
70 	}
71 
72 	MUTEX_UNLOCK(tcs_ctx_lock);
73 	return FALSE;
74 }
75 
76 /* Traverse loaded keys list and if matching key handle is found remove it */
77 TSS_RESULT
ctx_remove_key_loaded(TCS_CONTEXT_HANDLE ctx_handle,TCS_KEY_HANDLE key_handle)78 ctx_remove_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle)
79 {
80 	struct tcs_context *c;
81 	struct keys_loaded *cur, *prev;
82 
83 	MUTEX_LOCK(tcs_ctx_lock);
84 
85 	c = get_context(ctx_handle);
86 	if (c == NULL) {
87 		MUTEX_UNLOCK(tcs_ctx_lock);
88 		return TCSERR(TCS_E_INVALID_CONTEXTHANDLE);
89 	}
90 
91 	for (prev = cur = c->keys; cur; prev = cur, cur = cur->next) {
92 		if (cur->key_handle == key_handle) {
93 			if (cur == c->keys)
94 				c->keys = cur->next;
95 			else
96 				prev->next = cur->next;
97 
98 			free(cur);
99 			MUTEX_UNLOCK(tcs_ctx_lock);
100 			return TCS_SUCCESS;
101 		}
102 	}
103 
104 	MUTEX_UNLOCK(tcs_ctx_lock);
105 	return TCSERR(TCS_E_INVALID_KEY);
106 }
107 
108 /* make a new entry in the per-context list of loaded keys. If the list already
109  * contains a pointer to the key in memory, just return success.
110  */
111 TSS_RESULT
ctx_mark_key_loaded(TCS_CONTEXT_HANDLE ctx_handle,TCS_KEY_HANDLE key_handle)112 ctx_mark_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle)
113 {
114 	struct tcs_context *c;
115 	struct keys_loaded *k = NULL, *new;
116 	TSS_RESULT result;
117 
118 	MUTEX_LOCK(tcs_ctx_lock);
119 
120 	c = get_context(ctx_handle);
121 
122 	if (c != NULL) {
123 		k = c->keys;
124 		while (k != NULL) {
125 			if (k->key_handle == key_handle) {
126 				/* we've previously created a pointer to key_handle in the global
127 				 * list of loaded keys and incremented that key's reference count,
128 				 * so there's no need to do anything.
129 				 */
130 				result = TSS_SUCCESS;
131 				break;
132 			}
133 
134 			k = k->next;
135 		}
136 	} else {
137 		MUTEX_UNLOCK(tcs_ctx_lock);
138 		return TCSERR(TSS_E_FAIL);
139 	}
140 
141 	/* if we have no record of this key being loaded by this context, create a new
142 	 * entry and increment the key's reference count in the global list.
143 	 */
144 	if (k == NULL) {
145 		new = calloc(1, sizeof(struct keys_loaded));
146 		if (new == NULL) {
147 			LogError("malloc of %zd bytes failed.", sizeof(struct keys_loaded));
148 			MUTEX_UNLOCK(tcs_ctx_lock);
149 			return TCSERR(TSS_E_OUTOFMEMORY);
150 		}
151 
152 		new->key_handle = key_handle;
153 		new->next = c->keys;
154 		c->keys = new;
155 		result = key_mgr_inc_ref_count(new->key_handle);
156 	}
157 
158 	MUTEX_UNLOCK(tcs_ctx_lock);
159 
160 	return result;
161 }
162 
163