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 "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 | }
|
---|