diff options
Diffstat (limited to 'src/tcs/tcsi_random.c')
-rw-r--r-- | src/tcs/tcsi_random.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/tcs/tcsi_random.c b/src/tcs/tcsi_random.c new file mode 100644 index 0000000..9670df4 --- /dev/null +++ b/src/tcs/tcsi_random.c @@ -0,0 +1,147 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#include "trousers/tss.h" +#include "trousers_types.h" +#include "tcs_tsp.h" +#include "tcsps.h" +#include "tcs_utils.h" +#include "tcs_int_literals.h" +#include "capabilities.h" +#include "tcslog.h" +#include "req_mgr.h" +#include "tcsd_wrap.h" +#include "tcsd.h" + + +/* + * Get a random number generated by the TPM. Most (all?) TPMs return a maximum number of random + * bytes that's less than the max allowed to be returned at the TSP level, which is 4K bytes. + * According to the TPM compliance work posted here: http://www.prosec.rub.de/tpmcompliance.html, + * some TPMs return as little as 132 bytes per query, which would require about 30 loops to get 4K. + * We'll be extremely conservative here and loop 50 times, since it won't affect performance on + * TPMs that return more bytes. + */ +TSS_RESULT +TCSP_GetRandom_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ + UINT32 * bytesRequested, /* in, out */ + BYTE ** randomBytes) /* out */ +{ + UINT64 offset; + TSS_RESULT result; + UINT32 paramSize, totalReturned = 0, bytesReturned, retries = 50; + BYTE txBlob[TSS_TPM_TXBLOB_SIZE], *rnd_tmp = NULL, *rnd_tmp2 = NULL; + + LogDebugFn("%u bytes", *bytesRequested); + + if ((result = ctx_verify_context(hContext))) + return result; + + do { + offset = 0; + if ((result = tpm_rqu_build(TPM_ORD_GetRandom, &offset, txBlob, + *bytesRequested - totalReturned, NULL))) + break; + + if ((result = req_mgr_submit_req(txBlob))) + break;; + + result = UnloadBlob_Header(txBlob, ¶mSize); + if (!result) { +#if 0 + offset = 10; + UnloadBlob_UINT32(&offset, &bytesReturned, txBlob); + + LogDebugFn("received %u bytes from the TPM", bytesReturned); + + rnd_tmp = realloc(rnd_tmp, totalReturned + bytesReturned); + if (rnd_tmp == NULL) { + LogError("malloc of %u bytes failed.", bytesReturned); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset, bytesReturned, txBlob, &rnd_tmp[totalReturned]); +#else + /* XXX */ + if ((result = tpm_rsp_parse(TPM_ORD_GetRandom, txBlob, paramSize, + &bytesReturned, &rnd_tmp, NULL, NULL))) + break; + + rnd_tmp2 = realloc(*randomBytes, totalReturned + bytesReturned); + if (rnd_tmp2 == NULL) { + free(rnd_tmp); + rnd_tmp = NULL; + LogError("malloc of %u bytes failed.", bytesReturned); + result = TCSERR(TSS_E_OUTOFMEMORY); + break; + } + *randomBytes = rnd_tmp2; + memcpy(*randomBytes + totalReturned, rnd_tmp, bytesReturned); + free(rnd_tmp); + rnd_tmp = NULL; +#endif + totalReturned += bytesReturned; + } else { + free(rnd_tmp); + return result; + } + } while (totalReturned < *bytesRequested && retries--); + + if (totalReturned != *bytesRequested) { + LogDebugFn("Only %u random bytes recieved from TPM.", totalReturned); + free(rnd_tmp); + result = TCSERR(TSS_E_FAIL); +#if 0 + } else + *randomBytes = rnd_tmp; +#else + } +#endif + + return result; +} + +TSS_RESULT +TCSP_StirRandom_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ + UINT32 inDataSize, /* in */ + BYTE * inData) /* in */ +{ + UINT64 offset = 0; + UINT32 paramSize; + TSS_RESULT result; + BYTE txBlob[TSS_TPM_TXBLOB_SIZE]; + + LogDebug("Entering stir random"); + + if (inDataSize > 255) { + LogDebugFn("inData is too large! (%u bytes)", inDataSize); + return TCSERR(TSS_E_BAD_PARAMETER); + } + + if ((result = ctx_verify_context(hContext))) + return result; + + if ((result = tpm_rqu_build(TPM_ORD_StirRandom, &offset, txBlob, inDataSize, inDataSize, + inData, NULL, NULL))) + return result; + + if ((result = req_mgr_submit_req(txBlob))) + return result; + + result = UnloadBlob_Header(txBlob, ¶mSize); + LogResult("Stir random", result); + return result; +} + |