1 
2 /*
3  * Licensed Materials - Property of IBM
4  *
5  * trousers - An open source TCG Software Stack
6  *
7  * (C) Copyright International Business Machines Corp. 2004-2006
8  *
9  */
10 
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/mman.h>
18 #include <errno.h>
19 
20 #include "trousers/tss.h"
21 #include "trousers/trousers.h"
22 #include "trousers_types.h"
23 #include "trousers_types.h"
24 #include "spi_utils.h"
25 #include "capabilities.h"
26 #include "tsplog.h"
27 #include "obj.h"
28 
29 
30 UINT16
get_num_pcrs(TSS_HCONTEXT tspContext)31 get_num_pcrs(TSS_HCONTEXT tspContext)
32 {
33           TSS_RESULT result;
34           static UINT16 ret = 0;
35           UINT32 subCap;
36           UINT32 respSize;
37           BYTE *resp;
38 
39           if (ret != 0)
40                     return ret;
41 
42           subCap = endian32(TPM_CAP_PROP_PCR);
43           if ((result = TCS_API(tspContext)->GetTPMCapability(tspContext, TPM_CAP_PROPERTY,
44                                                                           sizeof(UINT32), (BYTE *)&subCap,
45                                                                           &respSize, &resp))) {
46                     if ((resp = (BYTE *)getenv("TSS_DEFAULT_NUM_PCRS")) == NULL)
47                               return TSS_DEFAULT_NUM_PCRS;
48 
49                     /* don't set ret here, next time we may be connected */
50                     return atoi((char *)resp);
51           }
52 
53           ret = (UINT16)Decode_UINT32(resp);
54           free(resp);
55 
56           return ret;
57 }
58 
59 TSS_RESULT
pcrs_calc_composite(TPM_PCR_SELECTION * select,TPM_PCRVALUE * arrayOfPcrs,TPM_DIGEST * digestOut)60 pcrs_calc_composite(TPM_PCR_SELECTION *select, TPM_PCRVALUE *arrayOfPcrs, TPM_DIGEST *digestOut)
61 {
62           UINT32 size, index;
63           BYTE mask;
64           BYTE hashBlob[1024];
65           UINT32 numPCRs = 0;
66           UINT64 offset = 0;
67           UINT64 sizeOffset = 0;
68 
69           if (select->sizeOfSelect > 0) {
70                     sizeOffset = 0;
71                     Trspi_LoadBlob_PCR_SELECTION(&sizeOffset, hashBlob, select);
72                     offset = sizeOffset + 4;
73 
74                     for (size = 0; size < select->sizeOfSelect; size++) {
75                               for (index = 0, mask = 1; index < 8; index++, mask = mask << 1) {
76                                         if (select->pcrSelect[size] & mask) {
77                                                   memcpy(&hashBlob[(numPCRs * TPM_SHA1_160_HASH_LEN) + offset],
78                                                          arrayOfPcrs[index + (size << 3)].digest,
79                                                          TPM_SHA1_160_HASH_LEN);
80                                                   numPCRs++;
81                                         }
82                               }
83                     }
84 
85                     if (numPCRs > 0) {
86                               offset += (numPCRs * TPM_SHA1_160_HASH_LEN);
87                               UINT32ToArray(numPCRs * TPM_SHA1_160_HASH_LEN, &hashBlob[sizeOffset]);
88 
89                               return Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, digestOut->digest);
90                     }
91           }
92 
93           return TSPERR(TSS_E_INTERNAL_ERROR);
94 }
95 
96 TSS_RESULT
pcrs_sanity_check_selection(TSS_HCONTEXT tspContext,struct tr_pcrs_obj * pcrs,TPM_PCR_SELECTION * select)97 pcrs_sanity_check_selection(TSS_HCONTEXT tspContext,
98                                   struct tr_pcrs_obj *pcrs,
99                                   TPM_PCR_SELECTION *select)
100 {
101           UINT16 num_pcrs, bytes_to_hold;
102 
103           if ((num_pcrs = get_num_pcrs(tspContext)) == 0)
104                     return TSPERR(TSS_E_INTERNAL_ERROR);
105 
106           bytes_to_hold = num_pcrs / 8;
107 
108           /* Is the current select object going to be interpretable by the TPM?
109            * If the select object is of a size greater than the one the TPM
110            * wants, just calculate the composite hash and let the TPM return an
111            * error code to the user.  If its less than the size of the one the
112            * TPM wants, add extra zero bytes until its the right size. */
113           if (bytes_to_hold > select->sizeOfSelect) {
114                     if ((select->pcrSelect = realloc(select->pcrSelect, bytes_to_hold)) == NULL) {
115                               LogError("malloc of %hu bytes failed.", bytes_to_hold);
116                               return TSPERR(TSS_E_OUTOFMEMORY);
117                     }
118                     /* set the newly allocated bytes to 0 */
119                     __tspi_memset(&select->pcrSelect[select->sizeOfSelect], 0,
120                                     bytes_to_hold - select->sizeOfSelect);
121                     select->sizeOfSelect = bytes_to_hold;
122 
123                     /* realloc the pcr array as well */
124                     if ((pcrs->pcrs = realloc(pcrs->pcrs,
125                                                     (bytes_to_hold * 8) * TPM_SHA1_160_HASH_LEN)) == NULL) {
126                               LogError("malloc of %d bytes failed.",
127                                          (bytes_to_hold * 8) * TPM_SHA1_160_HASH_LEN);
128                               return TSPERR(TSS_E_OUTOFMEMORY);
129                     }
130           }
131 
132 #ifdef TSS_DEBUG
133           {
134                     int i;
135                     for (i = 0; i < select->sizeOfSelect * 8; i++) {
136                               if (select->pcrSelect[i/8] & (1 << (i % 8))) {
137                                         LogDebug("PCR%d: Selected", i);
138                                         LogBlobData(APPID, TPM_SHA1_160_HASH_LEN,
139                                                       (unsigned char *)&pcrs->pcrs[i]);
140                               } else {
141                                         LogDebug("PCR%d: Not Selected", i);
142                               }
143                     }
144           }
145 #endif
146 
147           return TSS_SUCCESS;
148 }
149