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