summaryrefslogtreecommitdiffstats
path: root/src/tpm2/Entropy.c
blob: 2c2cc186cbceb08627928347e699f47b3b0ee846 (plain)
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/********************************************************************************/
/*										*/
/*			     Entropy						*/
/*			     Written by Ken Goldman				*/
/*		       IBM Thomas J. Watson Research Center			*/
/*            $Id: Entropy.c 1490 2019-07-26 21:13:22Z kgoldman $		*/
/*										*/
/*  Licenses and Notices							*/
/*										*/
/*  1. Copyright Licenses:							*/
/*										*/
/*  - Trusted Computing Group (TCG) grants to the user of the source code in	*/
/*    this specification (the "Source Code") a worldwide, irrevocable, 		*/
/*    nonexclusive, royalty free, copyright license to reproduce, create 	*/
/*    derivative works, distribute, display and perform the Source Code and	*/
/*    derivative works thereof, and to grant others the rights granted herein.	*/
/*										*/
/*  - The TCG grants to the user of the other parts of the specification 	*/
/*    (other than the Source Code) the rights to reproduce, distribute, 	*/
/*    display, and perform the specification solely for the purpose of 		*/
/*    developing products based on such documents.				*/
/*										*/
/*  2. Source Code Distribution Conditions:					*/
/*										*/
/*  - Redistributions of Source Code must retain the above copyright licenses, 	*/
/*    this list of conditions and the following disclaimers.			*/
/*										*/
/*  - Redistributions in binary form must reproduce the above copyright 	*/
/*    licenses, this list of conditions	and the following disclaimers in the 	*/
/*    documentation and/or other materials provided with the distribution.	*/
/*										*/
/*  3. Disclaimers:								*/
/*										*/
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF	*/
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH	*/
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)	*/
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.		*/
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for 		*/
/*  information on specification licensing rights available through TCG 	*/
/*  membership agreements.							*/
/*										*/
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED 	*/
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR 	*/
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR 		*/
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY 		*/
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.		*/
/*										*/
/*  - Without limitation, TCG and its members and licensors disclaim all 	*/
/*    liability, including liability for infringement of any proprietary 	*/
/*    rights, relating to use of information in this specification and to the	*/
/*    implementation of this specification, and TCG disclaims all liability for	*/
/*    cost of procurement of substitute goods or services, lost profits, loss 	*/
/*    of use, loss of data or any incidental, consequential, direct, indirect, 	*/
/*    or special damages, whether under contract, tort, warranty or otherwise, 	*/
/*    arising in any way out of use or reliance upon this specification or any 	*/
/*    information herein.							*/
/*										*/
/*  (c) Copyright IBM Corp. and others, 2016 - 2019				*/
/*										*/
/********************************************************************************/

/* C.4 Entropy.c */
/* C.4.1. Includes and Local values*/
#define _CRT_RAND_S
#include <stdlib.h>
#include <memory.h>

#include <openssl/rand.h>   /* libtpms added */

#include <time.h>
#include "Platform.h"
#ifdef _MSC_VER
#include <process.h>
#else
#include <unistd.h>
#endif

/* This is the last 32-bits of hardware entropy produced. We have to check to see that two
   consecutive 32-bit values are not the same because (according to FIPS 140-2, annex C */
/* "If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated
   after power-up, initialization, or reset shall not be used, but shall be saved for comparison
   with the next n-bit block to be generated. Each subsequent generation of an n-bit block shall be
   compared with the previously generated block. The test shall fail if any two compared n-bit
   blocks are equal." */
extern uint32_t        lastEntropy;

/* C.4.2.	Functions */
/* C.4.2.1.	rand32() */
/* Local function to get a 32-bit random number */

static uint32_t
rand32(
       void
       )
{
    uint32_t    rndNum = rand();
#if RAND_MAX < UINT16_MAX
    // If the maximum value of the random number is a 15-bit number, then shift it up
    // 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get
    // a full 32 bits.
    rndNum = (rndNum << 15) ^ rand();
    rndNum = (rndNum << 2) ^ rand();
#elif RAND_MAX == UINT16_MAX
    // If the maximum size is 16-bits, shift it and add another 16 bits
    rndNum = (rndNum << 16) ^ rand();
#elif RAND_MAX < UINT32_MAX
    // If 31 bits, then shift 1 and include another random value to get the extra bit
    rndNum = (rndNum << 1) ^ rand();
#endif
    return rndNum;
}

/* C.4.2.2 _plat__GetEntropy() */
/* This function is used to get available hardware entropy. In a hardware implementation of this
   function, there would be no call to the system to get entropy. */
/* Return Values Meaning */
/* < 0 hardware failure of the entropy generator, this is sticky */
/* >= 0 the returned amount of entropy (bytes) */
LIB_EXPORT int32_t
_plat__GetEntropy(
		  unsigned char       *entropy,           // output buffer
		  uint32_t             amount             // amount requested
		  )
{
    uint32_t            rndNum;
    int32_t             ret;
    //
    // libtpms added begin
    if (amount > 0 && RAND_bytes(entropy, amount) == 1)
        return amount;
    // fall back to 'original' method
    // libtpms added end

    if(amount == 0)
	{
	    // Seed the platform entropy source if the entropy source is software. There is
	    // no reason to put a guard macro (#if or #ifdef) around this code because this
	    // code would not be here if someone was changing it for a system with actual
	    // hardware.
	    //
	    // NOTE 1: The following command does not provide proper cryptographic entropy.
	    // Its primary purpose to make sure that different instances of the simulator,
	    // possibly started by a script on the same machine, are seeded differently.
	    // Vendors of the actual TPMs need to ensure availability of proper entropy
	    // using their platform specific means.
	    //
	    // NOTE 2: In debug builds by default the reference implementation will seed
	    // its RNG deterministically (without using any platform provided randomness).
	    // See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function.
#ifdef _MSC_VER
	    srand((unsigned)_plat__RealTime() ^ _getpid());
#else
	    srand((unsigned)_plat__RealTime() ^ getpid());
#endif
	    lastEntropy = rand32();
	    ret = 0;
	}
    else
	{
	    rndNum = rand32();
	    if(rndNum == lastEntropy)
		{
		    ret = -1;
		}
	    else
		{
		    lastEntropy = rndNum;
		    // Each process will have its random number generator initialized according
		    // to the process id and the initialization time. This is not a lot of
		    // entropy so, to add a bit more, XOR the current time value into the
		    // returned entropy value.
		    // NOTE: the reason for including the time here rather than have it in
		    // in the value assigned to lastEntropy is that rand() could be broken and
		    // using the time would in the lastEntropy value would hide this.
		    rndNum ^= (uint32_t)_plat__RealTime();
		    // Only provide entropy 32 bits at a time to test the ability
		    // of the caller to deal with partial results.
		    ret = MIN(amount, sizeof(rndNum));
		    memcpy(entropy, &rndNum, ret);
		}
	}
    return ret;
}