ia64/xen-unstable

view tools/vtpm_manager/manager/dmictl.c @ 8977:f84d5cdd9895

Clean up segment selector fixup and validation.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 23 14:43:45 2006 +0100 (2006-02-23)
parents 06d84bf87159
children f3661f9a95dd
line source
1 // ===================================================================
2 //
3 // Copyright (c) 2005, Intel Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 // * Neither the name of Intel Corporation nor the names of its
17 // contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 // ===================================================================
33 //
34 // dmictl.c
35 //
36 // Functions for creating and destroying DMIs
37 //
38 // ==================================================================
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <string.h>
44 #ifndef VTPM_MUTLI_VM
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <signal.h>
49 #include <wait.h>
50 #endif
52 #include "vtpmpriv.h"
53 #include "bsg.h"
54 #include "buffer.h"
55 #include "log.h"
56 #include "hashtable.h"
57 #include "hashtable_itr.h"
59 #define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
61 TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {
62 TPM_RESULT status = TPM_FAIL;
64 if (dmi_res == NULL)
65 return TPM_SUCCESS;
67 status = TCS_CloseContext(dmi_res->TCSContext);
68 free ( dmi_res->NVMLocation );
69 dmi_res->connected = FALSE;
71 #ifndef VTPM_MULTI_VM
72 free(dmi_res->guest_tx_fname);
73 free(dmi_res->vtpm_tx_fname);
75 close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;
76 close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1;
78 #ifndef MANUAL_DM_LAUNCH
79 if (dmi_res->dmi_id != VTPM_CTL_DM) {
80 if (dmi_res->dmi_pid != 0) {
81 vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid);
82 if (kill(dmi_res->dmi_pid, SIGKILL) !=0) {
83 vtpmloginfo(VTPM_LOG_VTPM, "DMI on pid %d is already dead.\n", dmi_res->dmi_pid);
84 } else if (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid) {
85 vtpmlogerror(VTPM_LOG_VTPM, "DMI on pid %d failed to stop.\n", dmi_res->dmi_pid);
86 status = TPM_FAIL;
87 }
88 } else {
89 vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was 0.\n");
90 status = TPM_FAIL;
91 }
92 }
93 #endif
94 #endif
96 return status;
97 }
99 TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {
101 VTPM_DMI_RESOURCE *new_dmi=NULL;
102 TPM_RESULT status=TPM_FAIL;
103 BYTE type;
104 UINT32 dmi_id, domain_id, *dmi_id_key;
106 #ifndef VTPM_MULTI_VM
107 int fh;
108 char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
109 struct stat file_info;
110 #endif
112 if (param_buf == NULL) { // Assume creation of Dom 0 control
113 type = 0;
114 domain_id = VTPM_CTL_DM;
115 dmi_id = VTPM_CTL_DM;
116 } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) {
117 vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", buffer_len(param_buf));
118 status = TPM_BAD_PARAMETER;
119 goto abort_egress;
120 } else {
121 BSG_UnpackList( param_buf->bytes, 3,
122 BSG_TYPE_BYTE, &type,
123 BSG_TYPE_UINT32, &domain_id,
124 BSG_TYPE_UINT32, &dmi_id);
125 }
127 new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id);
128 if (new_dmi == NULL) {
129 vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on domain %d.\n", dmi_id, domain_id);
130 // Brand New DMI. Initialize the persistent pieces
131 if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) == NULL) {
132 status = TPM_RESOURCES;
133 goto abort_egress;
134 }
135 memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE));
136 new_dmi->dmi_id = dmi_id;
137 new_dmi->connected = FALSE;
139 if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) {
140 status = TPM_RESOURCES;
141 goto abort_egress;
142 }
143 *dmi_id_key = new_dmi->dmi_id;
145 // install into map
146 if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){
147 free(new_dmi);
148 free(dmi_id_key);
149 status = TPM_FAIL;
150 goto egress;
151 }
153 } else
154 vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d .\n", dmi_id, domain_id);
156 if (new_dmi->connected) {
157 vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached instance %d. Ignoring\n", dmi_id);
158 status = TPM_BAD_PARAMETER;
159 goto egress;
160 }
162 // Initialize the Non-persistent pieces
163 new_dmi->dmi_domain_id = domain_id;
164 new_dmi->NVMLocation = NULL;
166 new_dmi->TCSContext = 0;
167 TPMTRYRETURN( TCS_OpenContext(&new_dmi->TCSContext) );
169 new_dmi->NVMLocation = (char *) malloc(11 + strlen(DMI_NVM_FILE));
170 sprintf(new_dmi->NVMLocation, DMI_NVM_FILE, (uint32_t) new_dmi->dmi_id);
172 // Measure DMI
173 // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value
174 /*
175 fh = open(TPM_EMULATOR_PATH, O_RDONLY);
176 stat_ret = fstat(fh, &file_stat);
177 if (stat_ret == 0)
178 dmi_size = file_stat.st_size;
179 else {
180 vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n");
181 status = TPM_IOERROR;
182 goto abort_egress;
183 }
184 dmi_buffer
185 */
186 memset(&new_dmi->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
188 #ifndef VTPM_MULTI_VM
189 if (dmi_id != VTPM_CTL_DM) {
190 // Create a pair of fifo pipes
191 if( (new_dmi->guest_tx_fname = (char *) malloc(11 + strlen(GUEST_TX_FIFO))) == NULL){
192 status = TPM_RESOURCES;
193 goto abort_egress;
194 }
195 sprintf(new_dmi->guest_tx_fname, GUEST_TX_FIFO, (uint32_t) dmi_id);
197 if ((new_dmi->vtpm_tx_fname = (char *) malloc(11 + strlen(VTPM_TX_FIFO))) == NULL) {
198 status = TPM_RESOURCES;
199 goto abort_egress;
200 }
201 sprintf(new_dmi->vtpm_tx_fname, VTPM_TX_FIFO, (uint32_t) dmi_id);
203 new_dmi->guest_tx_fh = -1;
204 new_dmi->vtpm_tx_fh= -1;
206 if ( stat(new_dmi->guest_tx_fname, &file_info) == -1) {
207 if ( mkfifo(new_dmi->guest_tx_fname, S_IWUSR | S_IRUSR ) ){
208 vtpmlogerror(VTPM_LOG_VTPM, "Failed to create dmi fifo.\n");
209 status = TPM_IOERROR;
210 goto abort_egress;
211 }
212 }
214 if ( (fh = open(new_dmi->vtpm_tx_fname, O_RDWR)) == -1) {
215 if ( mkfifo(new_dmi->vtpm_tx_fname, S_IWUSR | S_IRUSR ) ) {
216 vtpmlogerror(VTPM_LOG_VTPM, "Failed to create dmi fifo.\n");
217 status = TPM_IOERROR;
218 goto abort_egress;
219 }
220 }
222 // Launch DMI
223 sprintf(dmi_id_str, "%d", (int) dmi_id);
224 #ifdef MANUAL_DM_LAUNCH
225 vtpmlogerror(VTPM_LOG_VTPM, "FAKING starting vtpm with dmi=%s\n", dmi_id_str);
226 new_dmi->dmi_pid = 0;
227 #else
228 pid_t pid = fork();
230 if (pid == -1) {
231 vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n");
232 status = TPM_RESOURCES;
233 goto abort_egress;
234 } else if (pid == 0) {
235 if ( stat(new_dmi->NVMLocation, &file_info) == -1)
236 execl (TPM_EMULATOR_PATH, "vtmpd", "clear", dmi_id_str, NULL);
237 else
238 execl (TPM_EMULATOR_PATH, "vtpmd", "save", dmi_id_str, NULL);
240 // Returning from these at all is an error.
241 vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n");
242 } else {
243 new_dmi->dmi_pid = pid;
244 vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
245 }
246 #endif // MANUAL_DM_LAUNCH
247 }
248 #else // VTPM_MUTLI_VM
249 // FIXME: Measure DMI through call to Measurement agent in platform.
250 #endif
252 vtpm_globals->DMI_table_dirty = TRUE;
253 new_dmi->connected = TRUE;
254 status=TPM_SUCCESS;
255 goto egress;
257 abort_egress:
258 vtpmlogerror(VTPM_LOG_VTPM, "Failed to create DMI id=%d due to status=%s. Cleaning.\n", dmi_id, tpm_get_error_name(status));
259 close_dmi( new_dmi );
261 egress:
262 return status;
263 }
265 TPM_RESULT VTPM_Handle_Close_DMI( const buffer_t *param_buf) {
267 TPM_RESULT status=TPM_FAIL;
268 VTPM_DMI_RESOURCE *dmi_res=NULL;
269 UINT32 dmi_id;
271 if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
272 vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.");
273 status = TPM_BAD_PARAMETER;
274 goto abort_egress;
275 }
277 BSG_UnpackList( param_buf->bytes, 1,
278 BSG_TYPE_UINT32, &dmi_id);
280 vtpmloginfo(VTPM_LOG_VTPM, "Closing DMI %d.\n", dmi_id);
282 dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id);
283 if (dmi_res == NULL ) {
284 vtpmlogerror(VTPM_LOG_VTPM, "Trying to close nonexistent DMI.\n");
285 status = TPM_BAD_PARAMETER;
286 goto abort_egress;
287 }
289 if (!dmi_res->connected) {
290 vtpmlogerror(VTPM_LOG_VTPM, "Closing non-connected DMI.\n");
291 status = TPM_BAD_PARAMETER;
292 goto abort_egress;
293 }
295 // Close Dmi
296 TPMTRYRETURN(close_dmi( dmi_res ));
298 status=TPM_SUCCESS;
299 goto egress;
301 abort_egress:
302 egress:
304 return status;
305 }
307 TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) {
309 TPM_RESULT status=TPM_FAIL;
310 VTPM_DMI_RESOURCE *dmi_res=NULL;
311 UINT32 dmi_id;
313 if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
314 vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.\n");
315 status = TPM_BAD_PARAMETER;
316 goto abort_egress;
317 }
319 BSG_UnpackList( param_buf->bytes, 1,
320 BSG_TYPE_UINT32, &dmi_id);
322 vtpmloginfo(VTPM_LOG_VTPM, "Deleting DMI %d.\n", dmi_id);
324 dmi_res = (VTPM_DMI_RESOURCE *) hashtable_remove(vtpm_globals->dmi_map, &dmi_id);
325 if (dmi_res == NULL) {
326 vtpmlogerror(VTPM_LOG_VTPM, "Closing non-existent DMI.\n");
327 status = TPM_BAD_PARAMETER;
328 goto abort_egress;
329 }
331 //TODO: Automatically delete file dmi_res->NVMLocation
333 // Close DMI first
334 TPMTRYRETURN(close_dmi( dmi_res ));
335 free ( dmi_res );
337 status=TPM_SUCCESS;
338 goto egress;
340 abort_egress:
341 egress:
343 return status;
344 }