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