1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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;
}
|