debuggers.hg

view tools/vtpm_manager/manager/securestorage.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children b22f9ab1716a
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 // securestorage.c
35 //
36 // Functions regarding securely storing DMI secrets.
37 //
38 // ==================================================================
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <string.h>
46 #include "tcg.h"
47 #include "vtpm_manager.h"
48 #include "vtpmpriv.h"
49 #include "vtsp.h"
50 #include "bsg.h"
51 #include "crypto.h"
52 #include "hashtable.h"
53 #include "hashtable_itr.h"
54 #include "buffer.h"
55 #include "log.h"
57 TPM_RESULT envelope_encrypt(const buffer_t *inbuf,
58 CRYPTO_INFO *asymkey,
59 buffer_t *sealed_data) {
60 TPM_RESULT status = TPM_SUCCESS;
61 symkey_t symkey;
62 buffer_t data_cipher = NULL_BUF,
63 symkey_cipher = NULL_BUF;
65 UINT32 i;
66 struct pack_constbuf_t symkey_cipher32, data_cipher32;
68 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Input[%d]: 0x", buffer_len(inbuf));
69 for (i=0; i< buffer_len(inbuf); i++)
70 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
71 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
73 // Generate a sym key and encrypt state with it
74 TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
75 TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &data_cipher) );
77 // Encrypt symmetric key
78 TPMTRYRETURN( VTSP_Bind( asymkey,
79 &symkey.key,
80 &symkey_cipher) );
82 // Create output blob: symkey_size + symkey_cipher + state_cipher_size + state_cipher
84 symkey_cipher32.size = buffer_len(&symkey_cipher);
85 symkey_cipher32.data = symkey_cipher.bytes;
87 data_cipher32.size = buffer_len(&data_cipher);
88 data_cipher32.data = data_cipher.bytes;
90 TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + symkey_cipher32.size + data_cipher32.size, NULL));
92 BSG_PackList(sealed_data->bytes, 2,
93 BSG_TPM_SIZE32_DATA, &symkey_cipher32,
94 BSG_TPM_SIZE32_DATA, &data_cipher32);
96 vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher));
98 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Output[%d]: 0x", buffer_len(sealed_data));
99 for (i=0; i< buffer_len(sealed_data); i++)
100 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_data->bytes[i]);
101 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
103 goto egress;
105 abort_egress:
106 vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope encrypt\n.");
108 egress:
110 buffer_free ( &data_cipher);
111 buffer_free ( &symkey_cipher);
112 Crypto_symcrypto_freekey (&symkey);
114 return status;
115 }
117 TPM_RESULT envelope_decrypt(const buffer_t *cipher,
118 TCS_CONTEXT_HANDLE TCSContext,
119 TPM_HANDLE keyHandle,
120 const TPM_AUTHDATA *key_usage_auth,
121 buffer_t *unsealed_data) {
123 TPM_RESULT status = TPM_SUCCESS;
124 symkey_t symkey;
125 buffer_t data_cipher = NULL_BUF,
126 symkey_clear = NULL_BUF,
127 symkey_cipher = NULL_BUF;
128 struct pack_buf_t symkey_cipher32, data_cipher32;
129 int i;
131 memset(&symkey, 0, sizeof(symkey_t));
133 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%d]: 0x", buffer_len(cipher) );
134 for (i=0; i< buffer_len(cipher); i++)
135 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher->bytes[i]);
136 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
138 BSG_UnpackList(cipher->bytes, 2,
139 BSG_TPM_SIZE32_DATA, &symkey_cipher32,
140 BSG_TPM_SIZE32_DATA, &data_cipher32);
142 TPMTRYRETURN( buffer_init_alias_convert (&symkey_cipher,
143 symkey_cipher32.size,
144 symkey_cipher32.data) );
146 TPMTRYRETURN( buffer_init_alias_convert (&data_cipher,
147 data_cipher32.size,
148 data_cipher32.data) );
150 // Decrypt Symmetric Key
151 TPMTRYRETURN( VTSP_Unbind( TCSContext,
152 keyHandle,
153 &symkey_cipher,
154 key_usage_auth,
155 &symkey_clear,
156 &(vtpm_globals->keyAuth) ) );
158 // create symmetric key using saved bits
159 Crypto_symcrypto_initkey (&symkey, &symkey_clear);
161 // Decrypt State
162 TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) );
164 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data));
165 for (i=0; i< buffer_len(unsealed_data); i++)
166 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", unsealed_data->bytes[i]);
167 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
169 goto egress;
171 abort_egress:
172 vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope decrypt data\n.");
174 egress:
175 buffer_free ( &data_cipher);
176 buffer_free ( &symkey_clear);
177 buffer_free ( &symkey_cipher);
178 Crypto_symcrypto_freekey (&symkey);
180 return status;
181 }
183 TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI,
184 const buffer_t *inbuf,
185 buffer_t *outbuf) {
187 TPM_RESULT status = TPM_SUCCESS;
188 int fh;
189 long bytes_written;
190 buffer_t sealed_NVM = NULL_BUF;
192 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf));
194 TPMTRYRETURN( envelope_encrypt(inbuf,
195 &vtpm_globals->storageKey,
196 &sealed_NVM) );
198 // Write sealed blob off disk from NVMLocation
199 // TODO: How to properly return from these. Do we care if we return failure
200 // after writing the file? We can't get the old one back.
201 // TODO: Backup old file and try and recover that way.
202 fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
203 if ( (bytes_written = write(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM) ) != (long) buffer_len(&sealed_NVM))) {
204 vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_NVM));
205 status = TPM_IOERROR;
206 goto abort_egress;
207 }
208 close(fh);
210 Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &myDMI->NVM_measurement);
212 goto egress;
214 abort_egress:
215 vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n.");
217 egress:
218 buffer_free(&sealed_NVM);
219 return status;
220 }
223 /* Expected Params: inbuf = null, outbuf = sealed blob size, sealed blob.*/
224 TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI,
225 const buffer_t *inbuf,
226 buffer_t *outbuf) {
228 TPM_RESULT status = TPM_SUCCESS;
230 buffer_t sealed_NVM = NULL_BUF;
231 long fh_size;
232 int fh, stat_ret, i;
233 struct stat file_stat;
234 TPM_DIGEST sealedNVMHash;
236 if (myDMI->NVMLocation == NULL) {
237 vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name NULL.\n");
238 status = TPM_AUTHFAIL;
239 goto abort_egress;
240 }
242 //Read sealed blob off disk from NVMLocation
243 fh = open(myDMI->NVMLocation, O_RDONLY);
244 stat_ret = fstat(fh, &file_stat);
245 if (stat_ret == 0)
246 fh_size = file_stat.st_size;
247 else {
248 status = TPM_IOERROR;
249 goto abort_egress;
250 }
252 TPMTRYRETURN( buffer_init( &sealed_NVM, fh_size, NULL) );
253 if (read(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM)) != fh_size) {
254 status = TPM_IOERROR;
255 goto abort_egress;
256 }
257 close(fh);
259 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%d],\n", buffer_len(&sealed_NVM));
261 Crypto_SHA1Full(sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &sealedNVMHash);
263 // Verify measurement of sealed blob.
264 if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) {
265 vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check failed.\n");
266 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");
267 for (i=0; i< sizeof(TPM_DIGEST); i++)
268 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&myDMI->NVM_measurement)[i]);
269 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
271 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");
272 for (i=0; i< sizeof(TPM_DIGEST); i++)
273 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]);
274 vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
276 status = TPM_AUTHFAIL;
277 goto abort_egress;
278 }
280 TPMTRYRETURN( envelope_decrypt(&sealed_NVM,
281 myDMI->TCSContext,
282 vtpm_globals->storageKeyHandle,
283 (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
284 outbuf) );
285 goto egress;
287 abort_egress:
288 vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
290 egress:
291 buffer_free( &sealed_NVM );
293 return status;
294 }
297 TPM_RESULT VTPM_SaveManagerData(void) {
298 TPM_RESULT status=TPM_SUCCESS;
299 int fh, dmis=-1;
301 BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL;
302 buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF;
303 UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
304 UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap);
305 struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes};
306 struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes};
307 BYTE vtpm_manager_gen = VTPM_MANAGER_GEN;
309 struct hashtable_itr *dmi_itr;
310 VTPM_DMI_RESOURCE *dmi_res;
312 UINT32 boot_key_size = 0, flat_dmis_size = 0;
314 // Initially fill these with buffer sizes for each data type. Later fill
315 // in actual size, once flattened.
316 boot_key_size = sizeof(UINT32) + // bootkeysize
317 bootKeySize; // boot key
319 TPMTRYRETURN(buffer_init(&clear_flat_global,sizeof(BYTE) + // manager version
320 3*sizeof(TPM_DIGEST) + // Auths
321 sizeof(UINT32) +// storagekeysize
322 storageKeySize, NULL) ); // storage key
325 flat_boot_key = (BYTE *) malloc( boot_key_size );
326 flat_enc = (BYTE *) malloc( sizeof(UINT32) );
328 boot_key_size = BSG_PackList(flat_boot_key, 1,
329 BSG_TPM_SIZE32_DATA, &boot_key_pack);
331 BSG_PackList(clear_flat_global.bytes, 4,
332 BSG_TYPE_BYTE, &vtpm_manager_gen,
333 BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
334 BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
335 BSG_TPM_SIZE32_DATA, &storage_key_pack);
337 TPMTRYRETURN(envelope_encrypt(&clear_flat_global,
338 &vtpm_globals->bootKey,
339 &enc_flat_global) );
341 BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc);
343 // Per DMI values to be saved (if any exit)
344 if (hashtable_count(vtpm_globals->dmi_map) > 1) {
346 flat_dmis = (BYTE *) malloc(
347 (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0)
348 (sizeof(UINT32) +sizeof(BYTE) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info
350 dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
351 do {
352 dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
353 dmis++;
355 // No need to save dmi0.
356 if (dmi_res->dmi_id == 0)
357 continue;
360 flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 4,
361 BSG_TYPE_UINT32, &dmi_res->dmi_id,
362 BSG_TYPE_BYTE, &dmi_res->dmi_type,
363 BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
364 BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
366 } while (hashtable_iterator_advance(dmi_itr));
367 }
369 fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
370 if (fh == -1) {
371 vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE);
372 status = TPM_IOERROR;
373 goto abort_egress;
374 }
376 if ( ( write(fh, flat_boot_key, boot_key_size) != boot_key_size ) ||
377 ( write(fh, flat_enc, sizeof(UINT32)) != sizeof(UINT32) ) ||
378 ( write(fh, enc_flat_global.bytes, buffer_len(&enc_flat_global)) != buffer_len(&enc_flat_global) ) ||
379 ( write(fh, flat_dmis, flat_dmis_size) != flat_dmis_size ) ) {
380 vtpmlogerror(VTPM_LOG_VTPM, "Failed to completely write service data.\n");
381 status = TPM_IOERROR;
382 goto abort_egress;
383 }
385 goto egress;
387 abort_egress:
388 egress:
390 free(flat_boot_key);
391 free(flat_enc);
392 buffer_free(&enc_flat_global);
393 free(flat_dmis);
394 close(fh);
396 vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Manager state (status = %d, dmis = %d)\n", (int) status, dmis);
397 return status;
398 }
400 TPM_RESULT VTPM_LoadManagerData(void) {
402 TPM_RESULT status=TPM_SUCCESS;
403 int fh, stat_ret, dmis=0;
404 long fh_size = 0, step_size;
405 BYTE *flat_table=NULL;
406 buffer_t unsealed_data, enc_table_abuf;
407 struct pack_buf_t storage_key_pack, boot_key_pack;
408 UINT32 *dmi_id_key, enc_size;
409 BYTE vtpm_manager_gen;
411 VTPM_DMI_RESOURCE *dmi_res;
412 UINT32 dmi_id;
413 BYTE dmi_type;
414 struct stat file_stat;
416 TPM_HANDLE boot_key_handle;
417 TPM_AUTHDATA boot_usage_auth;
418 memset(&boot_usage_auth, 0, sizeof(TPM_AUTHDATA));
420 fh = open(STATE_FILE, O_RDONLY );
421 stat_ret = fstat(fh, &file_stat);
422 if (stat_ret == 0)
423 fh_size = file_stat.st_size;
424 else {
425 status = TPM_IOERROR;
426 goto abort_egress;
427 }
429 flat_table = (BYTE *) malloc(fh_size);
431 if ((long) read(fh, flat_table, fh_size) != fh_size ) {
432 status = TPM_IOERROR;
433 goto abort_egress;
434 }
436 // Read Boot Key
437 step_size = BSG_UnpackList( flat_table, 2,
438 BSG_TPM_SIZE32_DATA, &boot_key_pack,
439 BSG_TYPE_UINT32, &enc_size);
441 TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) );
442 TPMTRYRETURN(buffer_init_alias_convert(&enc_table_abuf, enc_size, flat_table + step_size) );
443 TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) );
445 //Load Boot Key
446 TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
447 TPM_SRK_KEYHANDLE,
448 &vtpm_globals->bootKeyWrap,
449 &SRK_AUTH,
450 &boot_key_handle,
451 &vtpm_globals->keyAuth,
452 &vtpm_globals->bootKey,
453 FALSE) );
455 TPMTRYRETURN( envelope_decrypt(&enc_table_abuf,
456 vtpm_globals->manager_tcs_handle,
457 boot_key_handle,
458 (const TPM_AUTHDATA*) &boot_usage_auth,
459 &unsealed_data) );
460 step_size += enc_size;
462 if (*unsealed_data.bytes != VTPM_MANAGER_GEN) {
463 // Once there is more than one gen, this will include some compatability stuff
464 vtpmlogerror(VTPM_LOG_VTPM, "Warning: Manager Data file is gen %d, which this manager is gen %d.\n", vtpm_manager_gen, VTPM_MANAGER_GEN);
465 }
467 // Global Values needing to be saved
468 BSG_UnpackList( unsealed_data.bytes, 4,
469 BSG_TYPE_BYTE, &vtpm_manager_gen,
470 BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
471 BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
472 BSG_TPM_SIZE32_DATA, &storage_key_pack);
474 TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
475 TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) );
477 // Per DMI values to be saved
478 while ( step_size < fh_size ){
479 if (fh_size - step_size < (long) (sizeof(UINT32) + sizeof(BYTE) + 2*sizeof(TPM_DIGEST))) {
480 vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size);
481 step_size = fh_size;
482 } else {
483 step_size += BSG_UnpackList(flat_table + step_size, 2,
484 BSG_TYPE_UINT32, &dmi_id,
485 BSG_TYPE_BYTE, &dmi_type);
487 //TODO: Try and gracefully recover from problems.
488 TPMTRYRETURN(init_dmi(dmi_id, dmi_type, &dmi_res) );
489 dmis++;
491 step_size += BSG_UnpackList(flat_table + step_size, 2,
492 BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
493 BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
494 }
496 }
498 vtpmloginfo(VTPM_LOG_VTPM, "Loaded saved state (dmis = %d).\n", dmis);
499 goto egress;
501 abort_egress:
502 vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status));
503 egress:
505 free(flat_table);
506 close(fh);
508 // TODO: Could be nice and evict BootKey. (Need to add EvictKey to VTSP.
510 return status;
511 }