OSDN Git Service

f4416e9925a2828bb5e6160f31a3d7d3fa659fbe
[openpts/openpts.git] / src / tpm.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
4  * The Initial Developer of the Original Code is International
5  * Business Machines Corporation. Portions created by IBM
6  * Corporation are Copyright (C) 2010 International Business
7  * Machines Corporation. All Rights Reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the Common Public License as published by
11  * IBM Corporation; either version 1 of the License, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * Common Public License for more details.
18  *
19  * You should have received a copy of the Common Public License
20  * along with this program; if not, a copy can be viewed at
21  * http://www.opensource.org/licenses/cpl1.0.php.
22  */
23
24 /**
25  * \file src/tpm.c
26  * \brief emulate TPM
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-01
29  * cleanup 2011-12-31 SM
30  *
31  *  Emulate TPM to validate IML and PCR
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <tss/platform.h>
39 #include <tss/tss_defines.h>
40 #include <tss/tss_typedef.h>
41 #include <tss/tss_structs.h>
42 #include <tss/tss_error.h>
43 #include <tss/tspi.h>
44
45 #include <openssl/sha.h>
46
47 #include <openpts.h>
48
49
50 /* TPM functions */
51
52 /**
53  * reset TPM
54  */
55 int resetTpm(OPENPTS_TPM_CONTEXT *tctx, int drtm) {
56     int i, j;
57
58     DEBUG_TPM("tpm.c - RESET (POR)\n");
59
60     /* check */
61     if (tctx == NULL) {
62         LOG(LOG_ERR, "ERROR TPM_CONTEXT is NULL");
63         return -1;
64     }
65
66     for (i = 0; i < MAX_PCRNUM; i++) {
67         for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
68             tctx->pcr[i][j] = 0;
69         }
70     }
71     // no DRTM
72     for (i = 17; i < 23; i++) {
73         for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
74             if (drtm == 0) tctx->pcr[i][j] = 0xff;
75             else           tctx->pcr[i][j] = 0x00;
76         }
77     }
78
79     DEBUG_TPM("tpm.c - RESET (POR)\n");
80
81     return 0;
82 }
83
84 /**
85  * reset TPM PCR
86  */
87 int resetTpmPcr(OPENPTS_TPM_CONTEXT *tctx, int index) {
88     int j;
89
90     DEBUG_TPM("resetTpmPcr - RESET just one PCR %d\n", index);
91
92     /* check */
93     if (tctx == NULL) {
94         LOG(LOG_ERR, "ERROR TPM_CONTEXT is NULL");
95         return -1;
96     }
97
98     for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
99         tctx->pcr[index][j] = 0;
100     }
101     return 0;
102 }
103
104 /**
105  * check digest is Zero or not
106  *
107  * @param digest
108  * @return 1 if digest is Zero
109  */
110 int isZero(BYTE * digest) {
111     int i;
112
113     /* check */
114     if (digest == NULL) {
115         LOG(LOG_ERR, "null input");
116         return -1;
117     }
118
119     /* is zero? */
120     for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
121         if (digest[i] != 0 ) return 0;
122     }
123     return 1;
124 }
125
126 /**
127  * set digest to FF
128  *
129  * @param digest
130  */
131 void setFF(BYTE * digest) {
132     int i;
133
134     /* check */
135     if (digest == NULL) {
136         LOG(LOG_ERR, "null input");
137         return;
138     }
139
140     /* set FF... */
141     for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
142         digest[i] = 0xff;
143     }
144 }
145
146 /**
147  * extend event to TPM
148  *
149  * @param tctx
150  * @param event
151  */
152 int extendTpm(OPENPTS_TPM_CONTEXT *tctx, TSS_PCR_EVENT *event) {
153     SHA_CTX ctx;
154     int index;
155     BYTE * digest;
156
157     /* check */
158     if (tctx == NULL) {
159         LOG(LOG_ERR, "TPM_CONTEXT is NULL\n");
160         return PTS_FATAL;
161     }
162     if (event == NULL) {
163         LOG(LOG_ERR, "TSS_PCR_EVENT is NULL\n");
164         return PTS_FATAL;
165     }
166
167     digest = event->rgbPcrValue;
168     if (digest == NULL) {
169         LOG(LOG_ERR, "event->rgbPcrValue is NULL\n");
170         return PTS_FATAL;
171     }
172
173     index = event->ulPcrIndex;
174     if (index >= MAX_PCRNUM) {
175         LOG(LOG_ERR, "BAD PCR INDEX %d >= %d\n", index, MAX_PCRNUM);
176         return PTS_INTERNAL_ERROR;
177     }
178
179     if (index < 0) {
180         LOG(LOG_ERR, "ERROR BAD PCR INDEX %d < 0\n", index);
181         return PTS_INTERNAL_ERROR;
182     }
183
184     if (index == 10) {  // Linux-IML, 0000... -> FFFF...
185         if (isZero(digest) == 1) {
186             setFF(digest);
187         }
188     }
189
190     SHA1_Init(&ctx);
191     SHA1_Update(&ctx, &(tctx->pcr[index][0]), SHA1_DIGEST_SIZE);
192     SHA1_Update(&ctx, digest, SHA1_DIGEST_SIZE);
193     SHA1_Final(&tctx->pcr[index][0], &ctx);
194
195     if (isDebugFlagSet(DEBUG_TPM_FLAG)) {
196         int i;
197         DEBUG_TPM("\ttpm.c - extend pcr=%d digest=", index);
198         for (i = 0; i < SHA1_DIGEST_SIZE; i++) OUTPUT("%02x", digest[i]);
199         OUTPUT("  -> ");
200         for (i = 0; i < SHA1_DIGEST_SIZE; i++) OUTPUT("%02x", tctx->pcr[index][i]);
201         OUTPUT("\n");
202     }
203
204     return PTS_SUCCESS;
205 }
206
207 /**
208  * extend event to TPM (2)
209  *
210  * @param tctx
211  * @param index
212  * @param digest
213  */
214 int extendTpm2(OPENPTS_TPM_CONTEXT *tctx, int index, BYTE * digest) {
215     SHA_CTX ctx;
216
217     /* check */
218     if (tctx == NULL) {
219         LOG(LOG_ERR, "TPM_CONTEXT is NULL\n");
220         return PTS_FATAL;
221     }
222     if (digest == NULL) {
223         LOG(LOG_ERR, "null input\n");
224         return PTS_FATAL;
225     }
226
227     if (index >= MAX_PCRNUM) {
228         LOG(LOG_ERR, "BAD pcr index, %d >= %d", index, MAX_PCRNUM);
229         return PTS_INTERNAL_ERROR;
230     }
231
232     // TODO(munetoh)
233     if (index == 10) {  // Linux-IML, 0000... -> FFFF...
234         if (isZero(digest) == 1) {
235             setFF(digest);
236         }
237     }
238
239     SHA1_Init(&ctx);
240     SHA1_Update(&ctx, &(tctx->pcr[index][0]), SHA1_DIGEST_SIZE);
241     SHA1_Update(&ctx, digest, SHA1_DIGEST_SIZE);
242     SHA1_Final(&tctx->pcr[index][0], &ctx);
243
244     if (isDebugFlagSet(DEBUG_TPM_FLAG)) {
245         int i;
246         DEBUG_TPM("tpm.c - extend pcr=%d digest=", index);
247         for (i = 0; i < SHA1_DIGEST_SIZE; i++) OUTPUT("%02x", digest[i]);
248         OUTPUT("\n");
249     }
250
251     return PTS_SUCCESS;
252 }
253
254 /**
255  * check current PCR value with digest
256  *
257  * @param tctx
258  * @param index
259  * @param digest
260  */
261 int checkTpmPcr2(OPENPTS_TPM_CONTEXT *tctx, int index, BYTE * digest) {
262     int i;
263
264     /* check */
265     if (tctx == NULL) {
266         LOG(LOG_ERR, "TPM_CONTEXT is NULL\n");
267         return PTS_FATAL;
268     }
269
270     for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
271         if (tctx->pcr[index][i] != digest[i]) return PTS_INTERNAL_ERROR;  // TODO
272     }
273     return PTS_SUCCESS;
274 }
275
276 /**
277  * print TPM PCRs to stdout
278  */
279 int printTpm(OPENPTS_TPM_CONTEXT *tctx) {
280     int i, j;
281
282     DEBUG_FSM("tpm.c - pprint pcrs\n");
283
284     /* check */
285     if (tctx == NULL) {
286         LOG(LOG_ERR, "TPM_CONTEXT is NULL\n");
287         return PTS_FATAL;
288     }
289
290     for (i = 0; i < MAX_PCRNUM; i++) {
291         OUTPUT("PCR[%2d] = ", i);
292         for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
293             OUTPUT("%02x", tctx->pcr[i][j]);
294         }
295         OUTPUT("\n");
296     }
297
298     return PTS_SUCCESS;
299 }
300
301 /**
302  * get TPM PCR value
303  */
304 int getTpmPcrValue(OPENPTS_TPM_CONTEXT *tpm, int index, BYTE *digest) {
305     int j;
306
307     DEBUG_CAL("getTpmPcrValue - pcr[%d]\n", index);
308
309     /* check */
310     if (tpm == NULL) {
311         LOG(LOG_ERR, "null input");
312         return PTS_FATAL;
313     }
314     if (digest == NULL) {
315         LOG(LOG_ERR, "null input");
316         return PTS_FATAL;
317     }
318     if (index >= MAX_PCRNUM) {
319         LOG(LOG_ERR, "BAD PCR INDEX %d >= %d\n", index, MAX_PCRNUM);
320         return PTS_INTERNAL_ERROR;
321     }
322     if (index < 0) {
323         LOG(LOG_ERR, "ERROR BAD PCR INDEX %d < 0\n", index);
324         return PTS_INTERNAL_ERROR;
325     }
326
327     /* copy */
328     for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
329         digest[j]=tpm->pcr[index][j];
330     }
331
332     DEBUG_CAL("getTpmPcrValue - done\n");
333
334     return PTS_SUCCESS;
335 }
336
337