1 /* Software-based Trusted Platform Module (TPM) Emulator
2  * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
3  *
4  * This module is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  *
9  * This module is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * $Id: tpm_startup.c 367 2010-02-13 15:52:18Z mast $
15  */
16 
17 #include "tpm_emulator.h"
18 #include "tpm_commands.h"
19 #include "tpm_data.h"
20 #include "tpm_handles.h"
21 
22 /*
23  * Admin Startup and State ([TPM_Part3], Section 3)
24  * This section describes the commands that start a TPM.
25  */
26 
TPM_Init(TPM_STARTUP_TYPE startupType)27 void TPM_Init(TPM_STARTUP_TYPE startupType)
28 {
29   info("TPM_Init()");
30   /* startup the TPM */
31   tpmData.stany.flags.postInitialise = TRUE;
32   TPM_SelfTestFull();
33   TPM_Startup(startupType);
34 }
35 
36 #define SET_TO_ZERO(a) memset(a, 0x00, sizeof(*a))
37 #define SET_TO_0xFF(a) memset(a, 0xff, sizeof(*a))
38 #define SET_TO_RAND(a) tpm_get_random_bytes(a, sizeof(*a))
39 
TPM_Startup(TPM_STARTUP_TYPE startupType)40 TPM_RESULT TPM_Startup(TPM_STARTUP_TYPE startupType)
41 {
42   int i;
43   info("TPM_Startup(%d)", startupType);
44   if (tpmData.stany.flags.postInitialise == FALSE) return TPM_INVALID_POSTINIT;
45   /* reset STANY_FLAGS */
46   SET_TO_ZERO(&tpmData.stany.flags);
47   tpmData.stany.flags.tag = TPM_TAG_STANY_FLAGS;
48   /* set data and flags according to the given startup type */
49   if (startupType == TPM_ST_CLEAR) {
50     /* reset STANY_DATA (invalidates ALL sessions) */
51     SET_TO_ZERO(&tpmData.stany.data);
52     tpmData.stany.data.tag = TPM_TAG_STANY_DATA;
53     /* init session-context nonce */
54     SET_TO_RAND(&tpmData.stany.data.contextNonceSession);
55     /* reset PCR values */
56     for (i = 0; i < TPM_NUM_PCR; i++) {
57       if (tpmData.permanent.data.pcrAttrib[i].pcrReset)
58         SET_TO_0xFF(&tpmData.permanent.data.pcrValue[i].digest);
59       else
60         SET_TO_ZERO(&tpmData.permanent.data.pcrValue[i].digest);
61     }
62     /* reset STCLEAR_FLAGS */
63     SET_TO_ZERO(&tpmData.stclear.flags);
64     tpmData.stclear.flags.tag = TPM_TAG_STCLEAR_FLAGS;
65     tpmData.stclear.flags.deactivated = tpmData.permanent.flags.deactivated;
66     /* reset STCLEAR_DATA */
67     SET_TO_ZERO(&tpmData.stclear.data);
68     tpmData.stclear.data.tag = TPM_TAG_STCLEAR_DATA;
69     /* flush volatiles and PCR dependent keys */
70     for (i = 0; i < TPM_MAX_KEYS; i++) {
71       if (tpmData.permanent.data.keys[i].payload
72           && ((tpmData.permanent.data.keys[i].keyFlags & TPM_KEY_FLAG_VOLATILE)
73               || tpmData.permanent.data.keys[i].parentPCRStatus))
74         TPM_FlushSpecific(INDEX_TO_KEY_HANDLE(i), TPM_RT_KEY);
75     }
76     /* init key-context nonce */
77     SET_TO_RAND(&tpmData.stclear.data.contextNonceKey);
78     /* invalidate counter handle */
79     tpmData.stclear.data.countID = TPM_INVALID_HANDLE;
80     /* reset NV read and write flags */
81     for (i = 0; i < TPM_MAX_NVS; i++) {
82         tpmData.permanent.data.nvStorage[i].pubInfo.bReadSTClear = FALSE;
83         tpmData.permanent.data.nvStorage[i].pubInfo.bWriteSTClear = FALSE;
84     }
85   } else if (startupType == TPM_ST_STATE) {
86     if (!tpmData.permanent.flags.dataRestored) {
87       error("restoring permanent data failed");
88       tpmData.permanent.data.testResult = "tpm_restore_permanent_data() failed";
89       tpmData.permanent.flags.selfTestSucceeded = FALSE;
90       return TPM_FAIL;
91     }
92   } else if (startupType == TPM_ST_DEACTIVATED) {
93     tpmData.stclear.flags.deactivated = TRUE;
94     /* invalidate any saved state */
95     tpm_erase_permanent_data();
96   } else {
97     return TPM_BAD_PARAMETER;
98   }
99   tpmData.stany.flags.postInitialise = FALSE;
100   tpmData.stany.flags.TOSPresent = FALSE;
101   return TPM_SUCCESS;
102 }
103 
TPM_SaveState()104 TPM_RESULT TPM_SaveState()
105 {
106   info("TPM_SaveState()");
107   if (tpmData.permanent.flags.selfTestSucceeded && !tpmData.stclear.flags.deactivated) {
108     return (tpm_store_permanent_data()) ? TPM_FAIL : TPM_SUCCESS;
109   } else {
110     debug("TPM is deactivated or in fail-stop mode, thus the permanent data is not stored");
111     return TPM_SUCCESS;
112   }
113 }
114