xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcsi_random.c (revision 2d5f7628c5531eb583b9313ac2fd1cf8582b4479)
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, &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 
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, &paramSize);
144 	LogResult("Stir random", result);
145 	return result;
146 }
147 
148