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, &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
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, &paramSize);
144	LogResult("Stir random", result);
145	return result;
146}
147
148