Home | History | Annotate | Line # | Download | only in tspi
      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 		__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