libtpms/src/tpm2/Entropy.c
Stefan Berger 74a9ab5515 tpm2: rev164: Trivial whitespace, command, and libtpms-unused changes
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2023-03-07 12:11:50 -05:00

186 lines
7.7 KiB
C

/********************************************************************************/
/* */
/* Entropy */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Entropy.c 1661 2021-03-18 19:00:58Z 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"
#if defined _MSC_VER || defined _MINGW
#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.
#if defined _MSC_VER || defined _MINGW
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;
}