/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2004 * */ #include #include #include #include #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; }