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 */
38 TSS_RESULT
TCSP_GetRandom_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 * bytesRequested,BYTE ** randomBytes)39 TCSP_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
116 TSS_RESULT
TCSP_StirRandom_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 inDataSize,BYTE * inData)117 TCSP_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