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