1// This file was extracted from the TCG Published
2// Trusted Platform Module Library
3// Part 4: Supporting Routines
4// Family "2.0"
5// Level 00 Revision 01.16
6// October 30, 2014
7
8//#define __TPM_RNG_FOR_DEBUG__
9//
10//
11//          Introduction
12//
13//     This file contains the interface to the OpenSSL() random number functions.
14//
15//          Includes
16//
17#include "OsslCryptoEngine.h"
18int         s_entropyFailure;
19//
20//
21//          Functions
22//
23//          _cpri__RngStartup()
24//
25//     This function is called to initialize the random number generator. It collects entropy from the platform to
26//     seed the OpenSSL() random number generator.
27//
28LIB_EXPORT BOOL
29_cpri__RngStartup(void)
30{
31     UINT32           entropySize;
32     BYTE             entropy[MAX_RNG_ENTROPY_SIZE];
33     INT32            returnedSize = 0;
34     // Initialize the entropy source
35     s_entropyFailure = FALSE;
36     _plat__GetEntropy(NULL, 0);
37     // Collect entropy until we have enough
38     for(entropySize = 0;
39         entropySize < MAX_RNG_ENTROPY_SIZE && returnedSize >= 0;
40         entropySize += returnedSize)
41     {
42         returnedSize = _plat__GetEntropy(&entropy[entropySize],
43                                             MAX_RNG_ENTROPY_SIZE - entropySize);
44     }
45     // Got some entropy on the last call and did not get an error
46     if(returnedSize > 0)
47     {
48         // Seed OpenSSL with entropy
49         RAND_seed(entropy, entropySize);
50     }
51     else
52     {
53         s_entropyFailure = TRUE;
54     }
55     return s_entropyFailure == FALSE;
56}
57//
58//
59//          _cpri__DrbgGetPutState()
60//
61//     This function is used to set the state of the RNG (direction == PUT_STATE) or to recover the state of the
62//     RNG (direction == GET_STATE).
63//
64//
65//
66//     NOTE:           This not currently supported on OpenSSL() version.
67//
68LIB_EXPORT CRYPT_RESULT
69_cpri__DrbgGetPutState(
70    GET_PUT              direction,
71    int                  bufferSize,
72    BYTE                *buffer
73    )
74{
75    UNREFERENCED_PARAMETER(direction);
76    UNREFERENCED_PARAMETER(bufferSize);
77    UNREFERENCED_PARAMETER(buffer);
78    return CRYPT_SUCCESS;                 // Function is not implemented
79}
80//
81//
82//          _cpri__StirRandom()
83//
84//     This function is called to add external entropy to the OpenSSL() random number generator.
85//
86LIB_EXPORT CRYPT_RESULT
87_cpri__StirRandom(
88    INT32                entropySize,
89    BYTE                *entropy
90    )
91{
92    if (entropySize >= 0)
93    {
94        RAND_add((const void *)entropy, (int) entropySize, 0.0);
95    }
96    return CRYPT_SUCCESS;
97}
98//
99//
100//          _cpri__GenerateRandom()
101//
102//     This function is called to get a string of random bytes from the OpenSSL() random number generator. The
103//     return value is the number of bytes placed in the buffer. If the number of bytes returned is not equal to the
104//     number of bytes requested (randomSize) it is indicative of a failure of the OpenSSL() random number
105//     generator and is probably fatal.
106//
107LIB_EXPORT UINT16
108_cpri__GenerateRandom(
109    INT32                randomSize,
110    BYTE                *buffer
111    )
112{
113    //
114    // We don't do negative sizes or ones that are too large
115    if (randomSize < 0 || randomSize > UINT16_MAX)
116        return 0;
117    // RAND_bytes uses 1 for success and we use 0
118    if(RAND_bytes(buffer, randomSize) == 1)
119        return (UINT16)randomSize;
120    else
121        return 0;
122}
123//
124//
125//
126//          _cpri__GenerateSeededRandom()
127//
128//     This funciton is used to generate a pseudo-random number from some seed values This funciton returns
129//     the same result each time it is called with the same parameters
130//
131LIB_EXPORT UINT16
132_cpri__GenerateSeededRandom(
133   INT32               randomSize,      //   IN: the size of the request
134   BYTE               *random,          //   OUT: receives the data
135   TPM_ALG_ID          hashAlg,         //   IN: used by KDF version but not here
136   TPM2B              *seed,            //   IN: the seed value
137   const char         *label,           //   IN: a label string (optional)
138   TPM2B              *partyU,          //   IN: other data (oprtional)
139   TPM2B              *partyV           //   IN: still more (optional)
140   )
141{
142   return (_cpri__KDFa(hashAlg, seed, label, partyU, partyV,
143                       randomSize * 8, random, NULL, FALSE));
144}
145