/* Microsoft Reference Implementation for TPM 2.0 * * The copyright in this software is being made available under the BSD License, * included below. This software may be subject to other third party and * contributor rights, including patent rights, and no such rights are granted * under this license. * * Copyright (c) Microsoft Corporation * * All rights reserved. * * BSD License * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //** Includes and Local Values #define _CRT_RAND_S #include #include #include #include "Platform.h" #ifdef _MSC_VER #include #else #include #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 an 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; //** Functions //*** 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; } //*** _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 Type: int32_t // < 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; // 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; }