]> git.proxmox.com Git - libtpms.git/blob - src/tpm_tpm12_tis.c
d56d49d04a5f7b16549395a6abd0bd3c4abcf4c0
[libtpms.git] / src / tpm_tpm12_tis.c
1 /********************************************************************************/
2 /* */
3 /* TPM TIS I/O */
4 /* Written by Ken Goldman */
5 /* IBM Thomas J. Watson Research Center */
6 /* $Id: tpm_tis.c 4505 2011-03-20 17:43:27Z kgoldman $ */
7 /* */
8 /* (c) Copyright IBM Corporation 2006, 2011. */
9 /* */
10 /* All rights reserved. */
11 /* */
12 /* Redistribution and use in source and binary forms, with or without */
13 /* modification, are permitted provided that the following conditions are */
14 /* met: */
15 /* */
16 /* Redistributions of source code must retain the above copyright notice, */
17 /* this list of conditions and the following disclaimer. */
18 /* */
19 /* Redistributions in binary form must reproduce the above copyright */
20 /* notice, this list of conditions and the following disclaimer in the */
21 /* documentation and/or other materials provided with the distribution. */
22 /* */
23 /* Neither the names of the IBM Corporation nor the names of its */
24 /* contributors may be used to endorse or promote products derived from */
25 /* this software without specific prior written permission. */
26 /* */
27 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
28 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
29 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
30 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
31 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
33 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
34 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
35 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
36 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
37 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38 /********************************************************************************/
39
40 /*
41 This file implements the TPM TIS interface out-of-band commands.
42 */
43
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "tpm12/tpm_crypto.h"
48 #include "tpm12/tpm_cryptoh.h"
49 #include "tpm12/tpm_debug.h"
50 #include "tpm_error.h"
51 #include "tpm12/tpm_digest.h"
52 #include "tpm12/tpm_global.h"
53 #include "tpm12/tpm_pcr.h"
54 #include "tpm12/tpm_permanent.h"
55 #include "tpm12/tpm_platform.h"
56 #include "tpm12/tpm_process.h"
57 #include "tpm12/tpm_transport.h"
58
59 #include "tpm_tis.h"
60
61 /* These commands do not test for TPM_ContinueSelfTest:
62
63 The following operations MUST be available after TPM_Init and before a call to
64 TPM_ContinueSelfTest 1.9. TPM_HASH_START / TPM_HASH_DATA / TPM_HASH_END */
65
66 /* TPM_IO_Hash_Start() implements the LPC bus TPM_HASH_START command
67 */
68 TPM_RESULT TPM12_IO_Hash_Start(void)
69 {
70 TPM_RESULT rc = 0;
71 tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */
72 TPM_PCRVALUE zeroPCR;
73 TPM_BOOL altered = FALSE; /* TRUE if the structure has been changed */
74
75 printf("\nTPM_IO_Hash_Start: Ordinal Entry\n");
76 TPM_Digest_Init(zeroPCR);
77
78 /* Prior to receiving the TPM_HASH_START command the TPM must have received a TPM_Startup
79 command. If the TPM receives a TPM_HASH_START after a TPM_Init but before a startup command,
80 the TPM treats this as an error */
81 if (rc == 0) {
82 if (tpm_state->tpm_stany_flags.postInitialise) {
83 printf("TPM_IO_Hash_Start: Error, postInitialise is TRUE\n");
84 rc = TPM_INVALID_POSTINIT;
85 }
86 }
87 /* NOTE: Done by caller
88 (1) If no TPM_ACCESS_x.activeLocality field is set, the TPM MUST set the
89 TPM_ACCESS_x.activeLocality field to indicate Locality 4. Any currently executing command
90 MUST be aborted per and subject to Section 11.2.3. */
91 /* NOTE: Done by caller
92 (2) If TPM_ACCESS_x.activeLocality is set, and if the TPM_ACCESS_x.activeLocality field is
93 not 4, the TPM MUST ignore this command. */
94 /* NOTE: Done by caller
95 (3) The TPM MUST clear the write FIFO. */
96 if (rc == 0) {
97 /* (4) If there is an exclusive transport session, it MUST be invalidated. */
98 if (tpm_state->tpm_stany_flags.transportExclusive != 0) { /* active exclusive */
99 rc = TPM_TransportSessions_TerminateHandle
100 (tpm_state->tpm_stclear_data.transSessions,
101 tpm_state->tpm_stany_flags.transportExclusive,
102 &(tpm_state->tpm_stany_flags.transportExclusive));
103 }
104 }
105 if (rc == 0) {
106 /* (5) Set the TPM_PERMANENT_FLAGS->tpmEstablished flag to TRUE (1). Note: see description of
107 Bit Field: tpmEstablishment in 11.2.11 Access Register. */
108 TPM_SetCapability_Flag(&altered,
109 &(tpm_state->tpm_permanent_flags.tpmEstablished),
110 TRUE);
111 }
112 if (rc == 0) {
113 /* (6) Set the TPM_STANY_FLAGS->TOSPresent flag to TRUE (1). */
114 tpm_state->tpm_stany_flags.TOSPresent = TRUE;
115 /* (7) Set PCRs per column labeled TPM_HASH_START in Table 5: PCR Initial and Reset Values.
116 (PCR 17-22 to zero, others unchanged */
117 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 17, zeroPCR);
118 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 18, zeroPCR);
119 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 19, zeroPCR);
120 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 20, zeroPCR);
121 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 21, zeroPCR);
122 TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 22, zeroPCR);
123 /* (8) Ignore any data component of the TPM_HASH_START LPC command. */
124 /* (9) Allocate tempLocation of a size required to perform the SHA-1 operation. */
125 /* (10) Initialize tempLocation per SHA-1. */
126 rc = TPM_SHA1InitCmd(&(tpm_state->sha1_context_tis));
127 }
128 rc = TPM_PermanentAll_NVStore(tpm_state,
129 altered,
130 rc);
131 /*
132 1) Upon any error in the above steps the TPM:
133 a) MUST enter Failure Mode.
134 NOTE: Done by caller
135 b) MUST release locality.
136 */
137 if (rc != 0) {
138 printf("TPM_IO_Hash_Start: Error, (fatal)\n");
139 printf(" TPM_IO_Hash_Start: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
140 tpm_state->testState = TPM_TEST_STATE_FAILURE;
141 }
142 return rc;
143 }
144
145 /* TPM_IO_Hash_Data() implements the LPC bus TPM_HASH_DATA command
146 */
147 TPM_RESULT TPM12_IO_Hash_Data(const unsigned char *data,
148 uint32_t data_length)
149 {
150 TPM_RESULT rc = 0;
151 tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */
152
153 printf("\nTPM_IO_Hash_Data: Ordinal Entry\n");
154 /* (1) Transform tempLocation per SHA-1 with data received from this command. */
155 /* (2) Repeat for each TPM_HASH_DATA LPC command received. */
156 if (rc == 0) {
157 if (tpm_state->sha1_context_tis == NULL) {
158 printf("TPM_IO_Hash_Data: Error, no existing SHA1 thread\n");
159 rc = TPM_SHA_THREAD;
160 }
161 }
162 if (rc == 0) {
163 rc = TPM_SHA1UpdateCmd(tpm_state->sha1_context_tis, data, data_length);
164 }
165 /*
166 1) Upon any error in the above steps the TPM:
167 a) MUST enter Failure Mode.
168 NOTE: Done by caller
169 b) MUST release locality.
170 */
171 if (rc != 0) {
172 printf("TPM_IO_Hash_Data: Error, (fatal)\n");
173 printf(" TPM_IO_Hash_Data: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
174 tpm_state->testState = TPM_TEST_STATE_FAILURE;
175 }
176 return rc;
177 }
178
179 /* TPM_IO_Hash_End() implements the LPC bus TPM_HASH_END command
180 */
181 TPM_RESULT TPM12_IO_Hash_End(void)
182 {
183 TPM_RESULT rc = 0;
184 TPM_PCRVALUE zeroPCR;
185 TPM_DIGEST extendDigest;
186 tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */
187
188 printf("\nTPM_IO_Hash_End: Ordinal Entry\n");
189 if (rc == 0) {
190 if (tpm_state->sha1_context_tis == NULL) {
191 printf("TPM_IO_Hash_End: Error, no existing SHA1 thread\n");
192 rc = TPM_SHA_THREAD;
193 }
194 }
195 /* (1) Ignore any data sent with the command. */
196 /* (2) Perform finalize operation on tempLocation per SHA-1. */
197 if (rc == 0) {
198 rc = TPM_SHA1FinalCmd(extendDigest, tpm_state->sha1_context_tis);
199 }
200 /* (3) Perform an “extend” operation, as defined in the TPM_Extend command, of the value within
201 tempLocation into PCR[Locality 4]. */
202 if (rc == 0) {
203 /* In the previous line above, “PCR[Locality 4]” within and before the SHA-1 function is
204 TPM_PCRVALUE = 0 (i.e., 20 bytes of all zeros). */
205 TPM_Digest_Init(zeroPCR); /* initial PCR value */
206 /* PCR[Locality 4] = SHA-1( PCR[Locality 4] || tempLoc) */
207 rc = TPM_SHA1(tpm_state->tpm_stclear_data.PCRS[TPM_LOCALITY_4_PCR],
208 TPM_DIGEST_SIZE, zeroPCR,
209 TPM_DIGEST_SIZE, extendDigest,
210 0, NULL);
211 }
212 /* NOTE: Done by caller
213 (4) Clear TPM_ACCESS_x.activeLocality for Locality 4. */
214 /*
215 1) Upon any error in the above steps the TPM:
216 a) MUST enter Failure Mode.
217 NOTE: Done by caller
218 b) MUST release locality.
219 */
220 if (rc != 0) {
221 printf("TPM_IO_Hash_End: Error, (fatal)\n");
222 printf(" TPM_IO_Hash_End: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
223 tpm_state->testState = TPM_TEST_STATE_FAILURE;
224 }
225 TPM_SHA1Delete(&(tpm_state->sha1_context_tis));
226 return rc;
227 }
228
229 TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished)
230 {
231 TPM_RESULT rc = 0;
232 tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */
233
234 if (rc == 0) {
235 *tpmEstablished = tpm_state->tpm_permanent_flags.tpmEstablished;
236 }
237 /*
238 1) Upon any error in the above steps the TPM:
239 a) MUST enter Failure Mode.
240 NOTE: Done by caller
241 b) MUST release locality.
242 */
243 if (rc != 0) {
244 printf("TPM_IO_TpmEstablished_Get: Error, (fatal)\n");
245 printf(" TPM_IO_TpmEstablished_Get: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
246 tpm_state->testState = TPM_TEST_STATE_FAILURE;
247 }
248 return 0;
249 }
250
251 TPM_RESULT TPM12_IO_TpmEstablished_Reset(void)
252 {
253 TPM_RESULT returnCode = 0;
254 tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */
255 TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */
256
257 if (returnCode == TPM_SUCCESS) {
258 returnCode = TPM_IO_GetLocality(&(tpm_state->tpm_stany_flags.localityModifier),
259 tpm_state->tpm_number);
260 }
261
262 /* 1. Validate the assertion of locality 3 or locality 4 */
263 if (returnCode == TPM_SUCCESS) {
264 returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */
265 tpm_state->tpm_stany_flags.localityModifier);
266 }
267 /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */
268 if (returnCode == TPM_SUCCESS) {
269 TPM_SetCapability_Flag(&writeAllNV, /* altered */
270 &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */
271 FALSE); /* value */
272
273 }
274 /* Store the permanent flags back to NVRAM */
275 returnCode = TPM_PermanentAll_NVStore(tpm_state,
276 writeAllNV,
277 returnCode);
278
279 return returnCode;
280 }