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 */ 38TSS_RESULT 39TCSP_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, ¶mSize); 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 116TSS_RESULT 117TCSP_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, ¶mSize); 144 LogResult("Stir random", result); 145 return result; 146} 147 148