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"
18 int         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 //
28 LIB_EXPORT BOOL
_cpri__RngStartup(void)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 //
68 LIB_EXPORT CRYPT_RESULT
_cpri__DrbgGetPutState(GET_PUT direction,int bufferSize,BYTE * buffer)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 //
86 LIB_EXPORT CRYPT_RESULT
_cpri__StirRandom(INT32 entropySize,BYTE * entropy)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 //
107 LIB_EXPORT UINT16
_cpri__GenerateRandom(INT32 randomSize,BYTE * buffer)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 //
131 LIB_EXPORT UINT16
_cpri__GenerateSeededRandom(INT32 randomSize,BYTE * random,TPM_ALG_ID hashAlg,TPM2B * seed,const char * label,TPM2B * partyU,TPM2B * partyV)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