Home | History | Annotate | Line # | Download | only in tcs
      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
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <inttypes.h>
     16 
     17 #include "trousers/tss.h"
     18 #include "trousers_types.h"
     19 #include "tcs_tsp.h"
     20 #include "tcsps.h"
     21 #include "tcs_utils.h"
     22 #include "tcs_int_literals.h"
     23 #include "capabilities.h"
     24 #include "tcslog.h"
     25 #include "req_mgr.h"
     26 #include "tcsd_wrap.h"
     27 #include "tcsd.h"
     28 
     29 
     30 /*
     31  * Get a random number generated by the TPM.  Most (all?) TPMs return a maximum number of random
     32  * bytes that's less than the max allowed to be returned at the TSP level, which is 4K bytes.
     33  * According to the TPM compliance work posted here: http://www.prosec.rub.de/tpmcompliance.html,
     34  * some TPMs return as little as 132 bytes per query, which would require about 30 loops to get 4K.
     35  * We'll be extremely conservative here and loop 50 times, since it won't affect performance on
     36  * TPMs that return more bytes.
     37  */
     38 TSS_RESULT
     39 TCSP_GetRandom_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
     40 			UINT32 * bytesRequested,	/* in, out */
     41 			BYTE ** randomBytes)	/* out */
     42 {
     43 	UINT64 offset;
     44 	TSS_RESULT result;
     45 	UINT32 paramSize, totalReturned = 0, bytesReturned, retries = 50;
     46 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE], *rnd_tmp = NULL, *rnd_tmp2 = NULL;
     47 
     48 	LogDebugFn("%u bytes", *bytesRequested);
     49 
     50 	if ((result = ctx_verify_context(hContext)))
     51 		return result;
     52 
     53 	do {
     54 		offset = 0;
     55 		if ((result = tpm_rqu_build(TPM_ORD_GetRandom, &offset, txBlob,
     56 					    *bytesRequested - totalReturned, NULL)))
     57 			break;
     58 
     59 		if ((result = req_mgr_submit_req(txBlob)))
     60 			break;;
     61 
     62 		result = UnloadBlob_Header(txBlob, &paramSize);
     63 		if (!result) {
     64 #if 0
     65 			offset = 10;
     66 			UnloadBlob_UINT32(&offset, &bytesReturned, txBlob);
     67 
     68 			LogDebugFn("received %u bytes from the TPM", bytesReturned);
     69 
     70 			rnd_tmp = realloc(rnd_tmp, totalReturned + bytesReturned);
     71 			if (rnd_tmp == NULL) {
     72 				LogError("malloc of %u bytes failed.", bytesReturned);
     73 				return TCSERR(TSS_E_OUTOFMEMORY);
     74 			}
     75 			UnloadBlob(&offset, bytesReturned, txBlob, &rnd_tmp[totalReturned]);
     76 #else
     77 			/* XXX */
     78 			if ((result = tpm_rsp_parse(TPM_ORD_GetRandom, txBlob, paramSize,
     79 						    &bytesReturned, &rnd_tmp, NULL, NULL)))
     80 				break;
     81 
     82 			rnd_tmp2 = realloc(*randomBytes, totalReturned + bytesReturned);
     83 			if (rnd_tmp2 == NULL) {
     84 				free(rnd_tmp);
     85 				rnd_tmp = NULL;
     86 				LogError("malloc of %u bytes failed.", bytesReturned);
     87 				result = TCSERR(TSS_E_OUTOFMEMORY);
     88 				break;
     89 			}
     90 			*randomBytes = rnd_tmp2;
     91 			memcpy(*randomBytes + totalReturned, rnd_tmp, bytesReturned);
     92 			free(rnd_tmp);
     93 			rnd_tmp = NULL;
     94 #endif
     95 			totalReturned += bytesReturned;
     96 		} else {
     97 			free(rnd_tmp);
     98 			return result;
     99 		}
    100 	} while (totalReturned < *bytesRequested && retries--);
    101 
    102 	if (totalReturned != *bytesRequested) {
    103 		LogDebugFn("Only %u random bytes recieved from TPM.", totalReturned);
    104 		free(rnd_tmp);
    105 		result = TCSERR(TSS_E_FAIL);
    106 #if 0
    107 	} else
    108 		*randomBytes = rnd_tmp;
    109 #else
    110 	}
    111 #endif
    112 
    113 	return result;
    114 }
    115 
    116 TSS_RESULT
    117 TCSP_StirRandom_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
    118 			 UINT32 inDataSize,	/* in */
    119 			 BYTE * inData)	/* in */
    120 {
    121 	UINT64 offset = 0;
    122 	UINT32 paramSize;
    123 	TSS_RESULT result;
    124 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
    125 
    126 	LogDebug("Entering stir random");
    127 
    128 	if (inDataSize > 255) {
    129 		LogDebugFn("inData is too large! (%u bytes)", inDataSize);
    130 		return TCSERR(TSS_E_BAD_PARAMETER);
    131 	}
    132 
    133 	if ((result = ctx_verify_context(hContext)))
    134 		return result;
    135 
    136 	if ((result = tpm_rqu_build(TPM_ORD_StirRandom, &offset, txBlob, inDataSize, inDataSize,
    137 				    inData, NULL, NULL)))
    138 		return result;
    139 
    140 	if ((result = req_mgr_submit_req(txBlob)))
    141 		return result;
    142 
    143 	result = UnloadBlob_Header(txBlob, &paramSize);
    144 	LogResult("Stir random", result);
    145 	return result;
    146 }
    147 
    148