1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen // This file implements a DRBG with a behavior according to SP800-90A using
37*5c591343SA. Cody Schuffelen // a block cypher. This is also compliant to ISO/IEC 18031:2011(E) C.3.2.
38*5c591343SA. Cody Schuffelen //
39*5c591343SA. Cody Schuffelen // A state structure is created for use by TPM.lib and functions
40*5c591343SA. Cody Schuffelen // within the CryptoEngine my use their own state structures when they need to have
41*5c591343SA. Cody Schuffelen // deterministic values.
42*5c591343SA. Cody Schuffelen //
43*5c591343SA. Cody Schuffelen // A debug mode is available that allows the random numbers generated for TPM.lib
44*5c591343SA. Cody Schuffelen // to be repeated during runs of the simulator. The switch for it is in
45*5c591343SA. Cody Schuffelen // TpmBuildSwitches.h. It is USE_DEBUG_RNG.
46*5c591343SA. Cody Schuffelen //
47*5c591343SA. Cody Schuffelen //
48*5c591343SA. Cody Schuffelen // This is the implementation layer of CTR DRGB mechanism as defined in SP800-90A
49*5c591343SA. Cody Schuffelen // and the functions are organized as closely as practical to the organization in
50*5c591343SA. Cody Schuffelen // SP800-90A. It is intended to be compiled as a separate module that is linked
51*5c591343SA. Cody Schuffelen // with a secure application so that both reside inside the same boundary
52*5c591343SA. Cody Schuffelen // [SP 800-90A 8.5]. The secure application in particular manages the accesses
53*5c591343SA. Cody Schuffelen // protected storage for the state of the DRBG instantiations, and supplies the
54*5c591343SA. Cody Schuffelen // implementation functions here with a valid pointer to the working state of the
55*5c591343SA. Cody Schuffelen // given instantiations (as a DRBG_STATE structure).
56*5c591343SA. Cody Schuffelen //
57*5c591343SA. Cody Schuffelen // This DRBG mechanism implementation does not support prediction resistance. Thus
58*5c591343SA. Cody Schuffelen // 'prediction_resistance_flag' is omitted from Instantiate_function(),
59*5c591343SA. Cody Schuffelen // Reseed_function(), Generate_function() argument lists [SP 800-90A 9.1, 9.2,
60*5c591343SA. Cody Schuffelen // 9.3], as well as from the working state data structure DRBG_STATE [SP 800-90A
61*5c591343SA. Cody Schuffelen // 9.1].
62*5c591343SA. Cody Schuffelen //
63*5c591343SA. Cody Schuffelen // This DRBG mechanism implementation always uses the highest security strength of
64*5c591343SA. Cody Schuffelen // available in the block ciphers. Thus 'requested_security_strength' parameter is
65*5c591343SA. Cody Schuffelen // omitted from Instantiate_function() and Generate_function() argument lists
66*5c591343SA. Cody Schuffelen // [SP 800-90A 9.1, 9.2, 9.3], as well as from the working state data structure
67*5c591343SA. Cody Schuffelen // DRBG_STATE [SP 800-90A 9.1].
68*5c591343SA. Cody Schuffelen //
69*5c591343SA. Cody Schuffelen // Internal functions (ones without Crypt prefix) expect validated arguments and
70*5c591343SA. Cody Schuffelen // therefore use assertions instead of runtime parameter checks and mostly return
71*5c591343SA. Cody Schuffelen // void instead of a status value.
72*5c591343SA. Cody Schuffelen
73*5c591343SA. Cody Schuffelen #include "Tpm.h"
74*5c591343SA. Cody Schuffelen
75*5c591343SA. Cody Schuffelen // Pull in the test vector definitions and define the space
76*5c591343SA. Cody Schuffelen #include "PRNG_TestVectors.h"
77*5c591343SA. Cody Schuffelen
78*5c591343SA. Cody Schuffelen const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY};
79*5c591343SA. Cody Schuffelen const BYTE DRBG_NistTestVector_GeneratedInterm[] =
80*5c591343SA. Cody Schuffelen {DRBG_TEST_GENERATED_INTERM};
81*5c591343SA. Cody Schuffelen
82*5c591343SA. Cody Schuffelen const BYTE DRBG_NistTestVector_EntropyReseed[] =
83*5c591343SA. Cody Schuffelen {DRBG_TEST_RESEED_ENTROPY};
84*5c591343SA. Cody Schuffelen const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED};
85*5c591343SA. Cody Schuffelen
86*5c591343SA. Cody Schuffelen //** Derivation Functions
87*5c591343SA. Cody Schuffelen //*** Description
88*5c591343SA. Cody Schuffelen // The functions in this section are used to reduce the personalization input values
89*5c591343SA. Cody Schuffelen // to make them usable as input for reseeding and instantiation. The overall
90*5c591343SA. Cody Schuffelen // behavior is intended to produce the same results as described in SP800-90A,
91*5c591343SA. Cody Schuffelen // section 10.4.2 "Derivation Function Using a Block Cipher Algorithm
92*5c591343SA. Cody Schuffelen // (Block_Cipher_df)." The code is broken into several subroutines to deal with the
93*5c591343SA. Cody Schuffelen // fact that the data used for personalization may come in several separate blocks
94*5c591343SA. Cody Schuffelen // such as a Template hash and a proof value and a primary seed.
95*5c591343SA. Cody Schuffelen
96*5c591343SA. Cody Schuffelen //*** Derivation Function Defines and Structures
97*5c591343SA. Cody Schuffelen
98*5c591343SA. Cody Schuffelen #define DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1)
99*5c591343SA. Cody Schuffelen #if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256
100*5c591343SA. Cody Schuffelen # error "CryptRand.c only written for AES with 128- or 256-bit keys."
101*5c591343SA. Cody Schuffelen #endif
102*5c591343SA. Cody Schuffelen
103*5c591343SA. Cody Schuffelen typedef struct
104*5c591343SA. Cody Schuffelen {
105*5c591343SA. Cody Schuffelen DRBG_KEY_SCHEDULE keySchedule;
106*5c591343SA. Cody Schuffelen DRBG_IV iv[DF_COUNT];
107*5c591343SA. Cody Schuffelen DRBG_IV out1;
108*5c591343SA. Cody Schuffelen DRBG_IV buf;
109*5c591343SA. Cody Schuffelen int contents;
110*5c591343SA. Cody Schuffelen } DF_STATE, *PDF_STATE;
111*5c591343SA. Cody Schuffelen
112*5c591343SA. Cody Schuffelen //*** DfCompute()
113*5c591343SA. Cody Schuffelen // This function does the incremental update of the derivation function state. It
114*5c591343SA. Cody Schuffelen // encrypts the 'iv' value and XOR's the results into each of the blocks of the
115*5c591343SA. Cody Schuffelen // output. This is equivalent to processing all of input data for each output block.
116*5c591343SA. Cody Schuffelen static void
DfCompute(PDF_STATE dfState)117*5c591343SA. Cody Schuffelen DfCompute(
118*5c591343SA. Cody Schuffelen PDF_STATE dfState
119*5c591343SA. Cody Schuffelen )
120*5c591343SA. Cody Schuffelen {
121*5c591343SA. Cody Schuffelen int i;
122*5c591343SA. Cody Schuffelen int iv;
123*5c591343SA. Cody Schuffelen crypt_uword_t *pIv;
124*5c591343SA. Cody Schuffelen crypt_uword_t temp[DRBG_IV_SIZE_WORDS] = {0};
125*5c591343SA. Cody Schuffelen //
126*5c591343SA. Cody Schuffelen for(iv = 0; iv < DF_COUNT; iv++)
127*5c591343SA. Cody Schuffelen {
128*5c591343SA. Cody Schuffelen pIv = (crypt_uword_t *)&dfState->iv[iv].words[0];
129*5c591343SA. Cody Schuffelen for(i = 0; i < DRBG_IV_SIZE_WORDS; i++)
130*5c591343SA. Cody Schuffelen {
131*5c591343SA. Cody Schuffelen temp[i] ^= pIv[i] ^ dfState->buf.words[i];
132*5c591343SA. Cody Schuffelen }
133*5c591343SA. Cody Schuffelen DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv);
134*5c591343SA. Cody Schuffelen }
135*5c591343SA. Cody Schuffelen for(i = 0; i < DRBG_IV_SIZE_WORDS; i++)
136*5c591343SA. Cody Schuffelen dfState->buf.words[i] = 0;
137*5c591343SA. Cody Schuffelen dfState->contents = 0;
138*5c591343SA. Cody Schuffelen }
139*5c591343SA. Cody Schuffelen
140*5c591343SA. Cody Schuffelen //*** DfStart()
141*5c591343SA. Cody Schuffelen // This initializes the output blocks with an encrypted counter value and
142*5c591343SA. Cody Schuffelen // initializes the key schedule.
143*5c591343SA. Cody Schuffelen static void
DfStart(PDF_STATE dfState,uint32_t inputLength)144*5c591343SA. Cody Schuffelen DfStart(
145*5c591343SA. Cody Schuffelen PDF_STATE dfState,
146*5c591343SA. Cody Schuffelen uint32_t inputLength
147*5c591343SA. Cody Schuffelen )
148*5c591343SA. Cody Schuffelen {
149*5c591343SA. Cody Schuffelen BYTE init[8];
150*5c591343SA. Cody Schuffelen int i;
151*5c591343SA. Cody Schuffelen UINT32 drbgSeedSize = sizeof(DRBG_SEED);
152*5c591343SA. Cody Schuffelen
153*5c591343SA. Cody Schuffelen const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = {
154*5c591343SA. Cody Schuffelen 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
155*5c591343SA. Cody Schuffelen 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
156*5c591343SA. Cody Schuffelen #if DRBG_KEY_SIZE_BYTES > 16
157*5c591343SA. Cody Schuffelen ,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
158*5c591343SA. Cody Schuffelen 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
159*5c591343SA. Cody Schuffelen #endif
160*5c591343SA. Cody Schuffelen };
161*5c591343SA. Cody Schuffelen memset(dfState, 0, sizeof(DF_STATE));
162*5c591343SA. Cody Schuffelen DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule);
163*5c591343SA. Cody Schuffelen // Create the first chaining values
164*5c591343SA. Cody Schuffelen for(i = 0; i < DF_COUNT; i++)
165*5c591343SA. Cody Schuffelen ((BYTE *)&dfState->iv[i])[3] = (BYTE)i;
166*5c591343SA. Cody Schuffelen DfCompute(dfState);
167*5c591343SA. Cody Schuffelen // initialize the first 64 bits of the IV in a way that doesn't depend
168*5c591343SA. Cody Schuffelen // on the size of the words used.
169*5c591343SA. Cody Schuffelen UINT32_TO_BYTE_ARRAY(inputLength, init);
170*5c591343SA. Cody Schuffelen UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]);
171*5c591343SA. Cody Schuffelen memcpy(&dfState->iv[0], init, 8);
172*5c591343SA. Cody Schuffelen dfState->contents = 4;
173*5c591343SA. Cody Schuffelen }
174*5c591343SA. Cody Schuffelen
175*5c591343SA. Cody Schuffelen //*** DfUpdate()
176*5c591343SA. Cody Schuffelen // This updates the state with the input data. A byte at a time is moved into the
177*5c591343SA. Cody Schuffelen // state buffer until it is full and then that block is encrypted by DfCompute().
178*5c591343SA. Cody Schuffelen static void
DfUpdate(PDF_STATE dfState,int size,const BYTE * data)179*5c591343SA. Cody Schuffelen DfUpdate(
180*5c591343SA. Cody Schuffelen PDF_STATE dfState,
181*5c591343SA. Cody Schuffelen int size,
182*5c591343SA. Cody Schuffelen const BYTE *data
183*5c591343SA. Cody Schuffelen )
184*5c591343SA. Cody Schuffelen {
185*5c591343SA. Cody Schuffelen while(size > 0)
186*5c591343SA. Cody Schuffelen {
187*5c591343SA. Cody Schuffelen int toFill = DRBG_IV_SIZE_BYTES - dfState->contents;
188*5c591343SA. Cody Schuffelen if(size < toFill)
189*5c591343SA. Cody Schuffelen toFill = size;
190*5c591343SA. Cody Schuffelen // Copy as many bytes as there are or until the state buffer is full
191*5c591343SA. Cody Schuffelen memcpy(&dfState->buf.bytes[dfState->contents], data, toFill);
192*5c591343SA. Cody Schuffelen // Reduce the size left by the amount copied
193*5c591343SA. Cody Schuffelen size -= toFill;
194*5c591343SA. Cody Schuffelen // Advance the data pointer by the amount copied
195*5c591343SA. Cody Schuffelen data += toFill;
196*5c591343SA. Cody Schuffelen // increase the buffer contents count by the amount copied
197*5c591343SA. Cody Schuffelen dfState->contents += toFill;
198*5c591343SA. Cody Schuffelen pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES);
199*5c591343SA. Cody Schuffelen // If we have a full buffer, do a computation pass.
200*5c591343SA. Cody Schuffelen if(dfState->contents == DRBG_IV_SIZE_BYTES)
201*5c591343SA. Cody Schuffelen DfCompute(dfState);
202*5c591343SA. Cody Schuffelen }
203*5c591343SA. Cody Schuffelen }
204*5c591343SA. Cody Schuffelen
205*5c591343SA. Cody Schuffelen //*** DfEnd()
206*5c591343SA. Cody Schuffelen // This function is called to get the result of the derivation function computation.
207*5c591343SA. Cody Schuffelen // If the buffer is not full, it is padded with zeros. The output buffer is
208*5c591343SA. Cody Schuffelen // structured to be the same as a DRBG_SEED value so that the function can return
209*5c591343SA. Cody Schuffelen // a pointer to the DRBG_SEED value in the DF_STATE structure.
210*5c591343SA. Cody Schuffelen static DRBG_SEED *
DfEnd(PDF_STATE dfState)211*5c591343SA. Cody Schuffelen DfEnd(
212*5c591343SA. Cody Schuffelen PDF_STATE dfState
213*5c591343SA. Cody Schuffelen )
214*5c591343SA. Cody Schuffelen {
215*5c591343SA. Cody Schuffelen // Since DfCompute is always called when a buffer is full, there is always
216*5c591343SA. Cody Schuffelen // space in the buffer for the terminator
217*5c591343SA. Cody Schuffelen dfState->buf.bytes[dfState->contents++] = 0x80;
218*5c591343SA. Cody Schuffelen // If the buffer is not full, pad with zeros
219*5c591343SA. Cody Schuffelen while(dfState->contents < DRBG_IV_SIZE_BYTES)
220*5c591343SA. Cody Schuffelen dfState->buf.bytes[dfState->contents++] = 0;
221*5c591343SA. Cody Schuffelen // Do a final state update
222*5c591343SA. Cody Schuffelen DfCompute(dfState);
223*5c591343SA. Cody Schuffelen return (DRBG_SEED *)&dfState->iv;
224*5c591343SA. Cody Schuffelen }
225*5c591343SA. Cody Schuffelen
226*5c591343SA. Cody Schuffelen //*** DfBuffer()
227*5c591343SA. Cody Schuffelen // Function to take an input buffer and do the derivation function to produce a
228*5c591343SA. Cody Schuffelen // DRBG_SEED value that can be used in DRBG_Reseed();
229*5c591343SA. Cody Schuffelen static DRBG_SEED *
DfBuffer(DRBG_SEED * output,int size,BYTE * buf)230*5c591343SA. Cody Schuffelen DfBuffer(
231*5c591343SA. Cody Schuffelen DRBG_SEED *output, // OUT: receives the result
232*5c591343SA. Cody Schuffelen int size, // IN: size of the buffer to add
233*5c591343SA. Cody Schuffelen BYTE *buf // IN: address of the buffer
234*5c591343SA. Cody Schuffelen )
235*5c591343SA. Cody Schuffelen {
236*5c591343SA. Cody Schuffelen DF_STATE dfState;
237*5c591343SA. Cody Schuffelen if(size == 0 || buf == NULL)
238*5c591343SA. Cody Schuffelen return NULL;
239*5c591343SA. Cody Schuffelen // Initialize the derivation function
240*5c591343SA. Cody Schuffelen DfStart(&dfState, size);
241*5c591343SA. Cody Schuffelen DfUpdate(&dfState, size, buf);
242*5c591343SA. Cody Schuffelen DfEnd(&dfState);
243*5c591343SA. Cody Schuffelen memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED));
244*5c591343SA. Cody Schuffelen return output;
245*5c591343SA. Cody Schuffelen }
246*5c591343SA. Cody Schuffelen
247*5c591343SA. Cody Schuffelen //*** DRBG_GetEntropy()
248*5c591343SA. Cody Schuffelen // Even though this implementation never fails, it may get blocked
249*5c591343SA. Cody Schuffelen // indefinitely long in the call to get entropy from the platform
250*5c591343SA. Cody Schuffelen // (DRBG_GetEntropy32()).
251*5c591343SA. Cody Schuffelen // This function is only used during instantiation of the DRBG for
252*5c591343SA. Cody Schuffelen // manufacturing and on each start-up after an non-orderly shutdown.
253*5c591343SA. Cody Schuffelen //
254*5c591343SA. Cody Schuffelen // Return Type: BOOL
255*5c591343SA. Cody Schuffelen // TRUE(1) requested entropy returned
256*5c591343SA. Cody Schuffelen // FALSE(0) entropy Failure
257*5c591343SA. Cody Schuffelen BOOL
DRBG_GetEntropy(UINT32 requiredEntropy,BYTE * entropy)258*5c591343SA. Cody Schuffelen DRBG_GetEntropy(
259*5c591343SA. Cody Schuffelen UINT32 requiredEntropy, // IN: requested number of bytes of full
260*5c591343SA. Cody Schuffelen // entropy
261*5c591343SA. Cody Schuffelen BYTE *entropy // OUT: buffer to return collected entropy
262*5c591343SA. Cody Schuffelen )
263*5c591343SA. Cody Schuffelen {
264*5c591343SA. Cody Schuffelen #if !USE_DEBUG_RNG
265*5c591343SA. Cody Schuffelen
266*5c591343SA. Cody Schuffelen UINT32 obtainedEntropy;
267*5c591343SA. Cody Schuffelen INT32 returnedEntropy;
268*5c591343SA. Cody Schuffelen
269*5c591343SA. Cody Schuffelen // If in debug mode, always use the self-test values for initialization
270*5c591343SA. Cody Schuffelen if(IsSelfTest())
271*5c591343SA. Cody Schuffelen {
272*5c591343SA. Cody Schuffelen #endif
273*5c591343SA. Cody Schuffelen // If doing simulated DRBG, then check to see if the
274*5c591343SA. Cody Schuffelen // entropyFailure condition is being tested
275*5c591343SA. Cody Schuffelen if(!IsEntropyBad())
276*5c591343SA. Cody Schuffelen {
277*5c591343SA. Cody Schuffelen // In self-test, the caller should be asking for exactly the seed
278*5c591343SA. Cody Schuffelen // size of entropy.
279*5c591343SA. Cody Schuffelen pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy));
280*5c591343SA. Cody Schuffelen memcpy(entropy, DRBG_NistTestVector_Entropy,
281*5c591343SA. Cody Schuffelen sizeof(DRBG_NistTestVector_Entropy));
282*5c591343SA. Cody Schuffelen }
283*5c591343SA. Cody Schuffelen #if !USE_DEBUG_RNG
284*5c591343SA. Cody Schuffelen }
285*5c591343SA. Cody Schuffelen else if(!IsEntropyBad())
286*5c591343SA. Cody Schuffelen {
287*5c591343SA. Cody Schuffelen // Collect entropy
288*5c591343SA. Cody Schuffelen // Note: In debug mode, the only "entropy" value ever returned
289*5c591343SA. Cody Schuffelen // is the value of the self-test vector.
290*5c591343SA. Cody Schuffelen for(returnedEntropy = 1, obtainedEntropy = 0;
291*5c591343SA. Cody Schuffelen obtainedEntropy < requiredEntropy && !IsEntropyBad();
292*5c591343SA. Cody Schuffelen obtainedEntropy += returnedEntropy)
293*5c591343SA. Cody Schuffelen {
294*5c591343SA. Cody Schuffelen returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy],
295*5c591343SA. Cody Schuffelen requiredEntropy - obtainedEntropy);
296*5c591343SA. Cody Schuffelen if(returnedEntropy <= 0)
297*5c591343SA. Cody Schuffelen SetEntropyBad();
298*5c591343SA. Cody Schuffelen }
299*5c591343SA. Cody Schuffelen }
300*5c591343SA. Cody Schuffelen #endif
301*5c591343SA. Cody Schuffelen return !IsEntropyBad();
302*5c591343SA. Cody Schuffelen }
303*5c591343SA. Cody Schuffelen
304*5c591343SA. Cody Schuffelen //*** IncrementIv()
305*5c591343SA. Cody Schuffelen // This function increments the IV value by 1. It is used by EncryptDRBG().
306*5c591343SA. Cody Schuffelen void
IncrementIv(DRBG_IV * iv)307*5c591343SA. Cody Schuffelen IncrementIv(
308*5c591343SA. Cody Schuffelen DRBG_IV *iv
309*5c591343SA. Cody Schuffelen )
310*5c591343SA. Cody Schuffelen {
311*5c591343SA. Cody Schuffelen BYTE *ivP = ((BYTE *)iv) + DRBG_IV_SIZE_BYTES;
312*5c591343SA. Cody Schuffelen while((--ivP >= (BYTE *)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0));
313*5c591343SA. Cody Schuffelen }
314*5c591343SA. Cody Schuffelen
315*5c591343SA. Cody Schuffelen //*** EncryptDRBG()
316*5c591343SA. Cody Schuffelen // This does the encryption operation for the DRBG. It will encrypt
317*5c591343SA. Cody Schuffelen // the input state counter (IV) using the state key. Into the output
318*5c591343SA. Cody Schuffelen // buffer for as many times as it takes to generate the required
319*5c591343SA. Cody Schuffelen // number of bytes.
320*5c591343SA. Cody Schuffelen static BOOL
EncryptDRBG(BYTE * dOut,UINT32 dOutBytes,DRBG_KEY_SCHEDULE * keySchedule,DRBG_IV * iv,UINT32 * lastValue)321*5c591343SA. Cody Schuffelen EncryptDRBG(
322*5c591343SA. Cody Schuffelen BYTE *dOut,
323*5c591343SA. Cody Schuffelen UINT32 dOutBytes,
324*5c591343SA. Cody Schuffelen DRBG_KEY_SCHEDULE *keySchedule,
325*5c591343SA. Cody Schuffelen DRBG_IV *iv,
326*5c591343SA. Cody Schuffelen UINT32 *lastValue // Points to the last output value
327*5c591343SA. Cody Schuffelen )
328*5c591343SA. Cody Schuffelen {
329*5c591343SA. Cody Schuffelen #if FIPS_COMPLIANT
330*5c591343SA. Cody Schuffelen // For FIPS compliance, the DRBG has to do a continuous self-test to make sure that
331*5c591343SA. Cody Schuffelen // no two consecutive values are the same. This overhead is not incurred if the TPM
332*5c591343SA. Cody Schuffelen // is not required to be FIPS compliant
333*5c591343SA. Cody Schuffelen //
334*5c591343SA. Cody Schuffelen UINT32 temp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)];
335*5c591343SA. Cody Schuffelen int i;
336*5c591343SA. Cody Schuffelen BYTE *p;
337*5c591343SA. Cody Schuffelen
338*5c591343SA. Cody Schuffelen for(; dOutBytes > 0;)
339*5c591343SA. Cody Schuffelen {
340*5c591343SA. Cody Schuffelen // Increment the IV before each encryption (this is what makes this
341*5c591343SA. Cody Schuffelen // different from normal counter-mode encryption
342*5c591343SA. Cody Schuffelen IncrementIv(iv);
343*5c591343SA. Cody Schuffelen DRBG_ENCRYPT(keySchedule, iv, temp);
344*5c591343SA. Cody Schuffelen // Expect a 16 byte block
345*5c591343SA. Cody Schuffelen #if DRBG_IV_SIZE_BITS != 128
346*5c591343SA. Cody Schuffelen #error "Unsuppored IV size in DRBG"
347*5c591343SA. Cody Schuffelen #endif
348*5c591343SA. Cody Schuffelen if((lastValue[0] == temp[0])
349*5c591343SA. Cody Schuffelen && (lastValue[1] == temp[1])
350*5c591343SA. Cody Schuffelen && (lastValue[2] == temp[2])
351*5c591343SA. Cody Schuffelen && (lastValue[3] == temp[3])
352*5c591343SA. Cody Schuffelen )
353*5c591343SA. Cody Schuffelen {
354*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_ENTROPY);
355*5c591343SA. Cody Schuffelen return FALSE;
356*5c591343SA. Cody Schuffelen }
357*5c591343SA. Cody Schuffelen lastValue[0] = temp[0];
358*5c591343SA. Cody Schuffelen lastValue[1] = temp[1];
359*5c591343SA. Cody Schuffelen lastValue[2] = temp[2];
360*5c591343SA. Cody Schuffelen lastValue[3] = temp[3];
361*5c591343SA. Cody Schuffelen i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES);
362*5c591343SA. Cody Schuffelen dOutBytes -= i;
363*5c591343SA. Cody Schuffelen for(p = (BYTE *)temp; i > 0; i--)
364*5c591343SA. Cody Schuffelen *dOut++ = *p++;
365*5c591343SA. Cody Schuffelen }
366*5c591343SA. Cody Schuffelen #else // version without continuous self-test
367*5c591343SA. Cody Schuffelen NOT_REFERENCED(lastValue);
368*5c591343SA. Cody Schuffelen for(; dOutBytes >= DRBG_IV_SIZE_BYTES;
369*5c591343SA. Cody Schuffelen dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES)
370*5c591343SA. Cody Schuffelen {
371*5c591343SA. Cody Schuffelen // Increment the IV
372*5c591343SA. Cody Schuffelen IncrementIv(iv);
373*5c591343SA. Cody Schuffelen DRBG_ENCRYPT(keySchedule, iv, dOut);
374*5c591343SA. Cody Schuffelen }
375*5c591343SA. Cody Schuffelen // If there is a partial, generate into a block-sized
376*5c591343SA. Cody Schuffelen // temp buffer and copy to the output.
377*5c591343SA. Cody Schuffelen if(dOutBytes != 0)
378*5c591343SA. Cody Schuffelen {
379*5c591343SA. Cody Schuffelen BYTE temp[DRBG_IV_SIZE_BYTES];
380*5c591343SA. Cody Schuffelen // Increment the IV
381*5c591343SA. Cody Schuffelen IncrementIv(iv);
382*5c591343SA. Cody Schuffelen DRBG_ENCRYPT(keySchedule, iv, temp);
383*5c591343SA. Cody Schuffelen memcpy(dOut, temp, dOutBytes);
384*5c591343SA. Cody Schuffelen }
385*5c591343SA. Cody Schuffelen #endif
386*5c591343SA. Cody Schuffelen return TRUE;
387*5c591343SA. Cody Schuffelen }
388*5c591343SA. Cody Schuffelen
389*5c591343SA. Cody Schuffelen //*** DRBG_Update()
390*5c591343SA. Cody Schuffelen // This function performs the state update function.
391*5c591343SA. Cody Schuffelen // According to SP800-90A, a temp value is created by doing CTR mode
392*5c591343SA. Cody Schuffelen // encryption of 'providedData' and replacing the key and IV with
393*5c591343SA. Cody Schuffelen // these values. The one difference is that, with counter mode, the
394*5c591343SA. Cody Schuffelen // IV is incremented after each block is encrypted and in this
395*5c591343SA. Cody Schuffelen // operation, the counter is incremented before each block is
396*5c591343SA. Cody Schuffelen // encrypted. This function implements an 'optimized' version
397*5c591343SA. Cody Schuffelen // of the algorithm in that it does the update of the drbgState->seed
398*5c591343SA. Cody Schuffelen // in place and then 'providedData' is XORed into drbgState->seed
399*5c591343SA. Cody Schuffelen // to complete the encryption of 'providedData'. This works because
400*5c591343SA. Cody Schuffelen // the IV is the last thing that gets encrypted.
401*5c591343SA. Cody Schuffelen //
402*5c591343SA. Cody Schuffelen static BOOL
DRBG_Update(DRBG_STATE * drbgState,DRBG_KEY_SCHEDULE * keySchedule,DRBG_SEED * providedData)403*5c591343SA. Cody Schuffelen DRBG_Update(
404*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState, // IN:OUT state to update
405*5c591343SA. Cody Schuffelen DRBG_KEY_SCHEDULE *keySchedule, // IN: the key schedule (optional)
406*5c591343SA. Cody Schuffelen DRBG_SEED *providedData // IN: additional data
407*5c591343SA. Cody Schuffelen )
408*5c591343SA. Cody Schuffelen {
409*5c591343SA. Cody Schuffelen UINT32 i;
410*5c591343SA. Cody Schuffelen BYTE *temp = (BYTE *)&drbgState->seed;
411*5c591343SA. Cody Schuffelen DRBG_KEY *key = pDRBG_KEY(&drbgState->seed);
412*5c591343SA. Cody Schuffelen DRBG_IV *iv = pDRBG_IV(&drbgState->seed);
413*5c591343SA. Cody Schuffelen DRBG_KEY_SCHEDULE localKeySchedule;
414*5c591343SA. Cody Schuffelen //
415*5c591343SA. Cody Schuffelen pAssert(drbgState->magic == DRBG_MAGIC);
416*5c591343SA. Cody Schuffelen
417*5c591343SA. Cody Schuffelen // If an key schedule was not provided, make one
418*5c591343SA. Cody Schuffelen if(keySchedule == NULL)
419*5c591343SA. Cody Schuffelen {
420*5c591343SA. Cody Schuffelen if(DRBG_ENCRYPT_SETUP((BYTE *)key,
421*5c591343SA. Cody Schuffelen DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0)
422*5c591343SA. Cody Schuffelen {
423*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_INTERNAL);
424*5c591343SA. Cody Schuffelen return FALSE;
425*5c591343SA. Cody Schuffelen }
426*5c591343SA. Cody Schuffelen keySchedule = &localKeySchedule;
427*5c591343SA. Cody Schuffelen }
428*5c591343SA. Cody Schuffelen // Encrypt the temp value
429*5c591343SA. Cody Schuffelen
430*5c591343SA. Cody Schuffelen EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv,
431*5c591343SA. Cody Schuffelen drbgState->lastValue);
432*5c591343SA. Cody Schuffelen if(providedData != NULL)
433*5c591343SA. Cody Schuffelen {
434*5c591343SA. Cody Schuffelen BYTE *pP = (BYTE *)providedData;
435*5c591343SA. Cody Schuffelen for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--)
436*5c591343SA. Cody Schuffelen *temp++ ^= *pP++;
437*5c591343SA. Cody Schuffelen }
438*5c591343SA. Cody Schuffelen // Since temp points to the input key and IV, we are done and
439*5c591343SA. Cody Schuffelen // don't need to copy the resulting 'temp' to drbgState->seed
440*5c591343SA. Cody Schuffelen return TRUE;
441*5c591343SA. Cody Schuffelen }
442*5c591343SA. Cody Schuffelen
443*5c591343SA. Cody Schuffelen //*** DRBG_Reseed()
444*5c591343SA. Cody Schuffelen // This function is used when reseeding of the DRBG is required. If
445*5c591343SA. Cody Schuffelen // entropy is provided, it is used in lieu of using hardware entropy.
446*5c591343SA. Cody Schuffelen // Note: the provided entropy must be the required size.
447*5c591343SA. Cody Schuffelen //
448*5c591343SA. Cody Schuffelen // Return Type: BOOL
449*5c591343SA. Cody Schuffelen // TRUE(1) reseed succeeded
450*5c591343SA. Cody Schuffelen // FALSE(0) reseed failed, probably due to the entropy generation
451*5c591343SA. Cody Schuffelen BOOL
DRBG_Reseed(DRBG_STATE * drbgState,DRBG_SEED * providedEntropy,DRBG_SEED * additionalData)452*5c591343SA. Cody Schuffelen DRBG_Reseed(
453*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState, // IN: the state to update
454*5c591343SA. Cody Schuffelen DRBG_SEED *providedEntropy, // IN: entropy
455*5c591343SA. Cody Schuffelen DRBG_SEED *additionalData // IN:
456*5c591343SA. Cody Schuffelen )
457*5c591343SA. Cody Schuffelen {
458*5c591343SA. Cody Schuffelen DRBG_SEED seed;
459*5c591343SA. Cody Schuffelen
460*5c591343SA. Cody Schuffelen pAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC));
461*5c591343SA. Cody Schuffelen
462*5c591343SA. Cody Schuffelen if(providedEntropy == NULL)
463*5c591343SA. Cody Schuffelen {
464*5c591343SA. Cody Schuffelen providedEntropy = &seed;
465*5c591343SA. Cody Schuffelen if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE *)providedEntropy))
466*5c591343SA. Cody Schuffelen return FALSE;
467*5c591343SA. Cody Schuffelen }
468*5c591343SA. Cody Schuffelen if(additionalData != NULL)
469*5c591343SA. Cody Schuffelen {
470*5c591343SA. Cody Schuffelen unsigned int i;
471*5c591343SA. Cody Schuffelen
472*5c591343SA. Cody Schuffelen // XOR the provided data into the provided entropy
473*5c591343SA. Cody Schuffelen for(i = 0; i < sizeof(DRBG_SEED); i++)
474*5c591343SA. Cody Schuffelen ((BYTE *)providedEntropy)[i] ^= ((BYTE *)additionalData)[i];
475*5c591343SA. Cody Schuffelen }
476*5c591343SA. Cody Schuffelen DRBG_Update(drbgState, NULL, providedEntropy);
477*5c591343SA. Cody Schuffelen
478*5c591343SA. Cody Schuffelen drbgState->reseedCounter = 1;
479*5c591343SA. Cody Schuffelen
480*5c591343SA. Cody Schuffelen return TRUE;
481*5c591343SA. Cody Schuffelen }
482*5c591343SA. Cody Schuffelen
483*5c591343SA. Cody Schuffelen //*** DRBG_SelfTest()
484*5c591343SA. Cody Schuffelen // This is run when the DRBG is instantiated and at startup.
485*5c591343SA. Cody Schuffelen //
486*5c591343SA. Cody Schuffelen // Return Type: BOOL
487*5c591343SA. Cody Schuffelen // TRUE(1) test OK
488*5c591343SA. Cody Schuffelen // FALSE(0) test failed
489*5c591343SA. Cody Schuffelen BOOL
DRBG_SelfTest(void)490*5c591343SA. Cody Schuffelen DRBG_SelfTest(
491*5c591343SA. Cody Schuffelen void
492*5c591343SA. Cody Schuffelen )
493*5c591343SA. Cody Schuffelen {
494*5c591343SA. Cody Schuffelen BYTE buf[sizeof(DRBG_NistTestVector_Generated)];
495*5c591343SA. Cody Schuffelen DRBG_SEED seed;
496*5c591343SA. Cody Schuffelen UINT32 i;
497*5c591343SA. Cody Schuffelen BYTE *p;
498*5c591343SA. Cody Schuffelen DRBG_STATE testState;
499*5c591343SA. Cody Schuffelen //
500*5c591343SA. Cody Schuffelen pAssert(!IsSelfTest());
501*5c591343SA. Cody Schuffelen
502*5c591343SA. Cody Schuffelen SetSelfTest();
503*5c591343SA. Cody Schuffelen SetDrbgTested();
504*5c591343SA. Cody Schuffelen // Do an instantiate
505*5c591343SA. Cody Schuffelen if(!DRBG_Instantiate(&testState, 0, NULL))
506*5c591343SA. Cody Schuffelen return FALSE;
507*5c591343SA. Cody Schuffelen #if DRBG_DEBUG_PRINT
508*5c591343SA. Cody Schuffelen dbgDumpMemBlock(pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES,
509*5c591343SA. Cody Schuffelen "Key after Instantiate");
510*5c591343SA. Cody Schuffelen dbgDumpMemBlock(pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES,
511*5c591343SA. Cody Schuffelen "Value after Instantiate");
512*5c591343SA. Cody Schuffelen #endif
513*5c591343SA. Cody Schuffelen if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
514*5c591343SA. Cody Schuffelen return FALSE;
515*5c591343SA. Cody Schuffelen #if DRBG_DEBUG_PRINT
516*5c591343SA. Cody Schuffelen dbgDumpMemBlock(pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,
517*5c591343SA. Cody Schuffelen "Key after 1st Generate");
518*5c591343SA. Cody Schuffelen dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,
519*5c591343SA. Cody Schuffelen "Value after 1st Generate");
520*5c591343SA. Cody Schuffelen #endif
521*5c591343SA. Cody Schuffelen if(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0)
522*5c591343SA. Cody Schuffelen return FALSE;
523*5c591343SA. Cody Schuffelen memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed));
524*5c591343SA. Cody Schuffelen DRBG_Reseed(&testState, &seed, NULL);
525*5c591343SA. Cody Schuffelen #if DRBG_DEBUG_PRINT
526*5c591343SA. Cody Schuffelen dbgDumpMemBlock((BYTE *)pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,
527*5c591343SA. Cody Schuffelen "Key after 2nd Generate");
528*5c591343SA. Cody Schuffelen dbgDumpMemBlock((BYTE *)pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,
529*5c591343SA. Cody Schuffelen "Value after 2nd Generate");
530*5c591343SA. Cody Schuffelen dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated");
531*5c591343SA. Cody Schuffelen #endif
532*5c591343SA. Cody Schuffelen if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
533*5c591343SA. Cody Schuffelen return FALSE;
534*5c591343SA. Cody Schuffelen if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0)
535*5c591343SA. Cody Schuffelen return FALSE;
536*5c591343SA. Cody Schuffelen ClearSelfTest();
537*5c591343SA. Cody Schuffelen
538*5c591343SA. Cody Schuffelen DRBG_Uninstantiate(&testState);
539*5c591343SA. Cody Schuffelen for(p = (BYTE *)&testState, i = 0; i < sizeof(DRBG_STATE); i++)
540*5c591343SA. Cody Schuffelen {
541*5c591343SA. Cody Schuffelen if(*p++)
542*5c591343SA. Cody Schuffelen return FALSE;
543*5c591343SA. Cody Schuffelen }
544*5c591343SA. Cody Schuffelen // Simulate hardware failure to make sure that we get an error when
545*5c591343SA. Cody Schuffelen // trying to instantiate
546*5c591343SA. Cody Schuffelen SetEntropyBad();
547*5c591343SA. Cody Schuffelen if(DRBG_Instantiate(&testState, 0, NULL))
548*5c591343SA. Cody Schuffelen return FALSE;
549*5c591343SA. Cody Schuffelen ClearEntropyBad();
550*5c591343SA. Cody Schuffelen
551*5c591343SA. Cody Schuffelen return TRUE;
552*5c591343SA. Cody Schuffelen }
553*5c591343SA. Cody Schuffelen
554*5c591343SA. Cody Schuffelen //** Public Interface
555*5c591343SA. Cody Schuffelen //*** Description
556*5c591343SA. Cody Schuffelen // The functions in this section are the interface to the RNG. These
557*5c591343SA. Cody Schuffelen // are the functions that are used by TPM.lib.
558*5c591343SA. Cody Schuffelen
559*5c591343SA. Cody Schuffelen //*** CryptRandomStir()
560*5c591343SA. Cody Schuffelen // This function is used to cause a reseed. A DRBG_SEED amount of entropy is
561*5c591343SA. Cody Schuffelen // collected from the hardware and then additional data is added.
562*5c591343SA. Cody Schuffelen //
563*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
564*5c591343SA. Cody Schuffelen // TPM_RC_NO_RESULT failure of the entropy generator
565*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
CryptRandomStir(UINT16 additionalDataSize,BYTE * additionalData)566*5c591343SA. Cody Schuffelen CryptRandomStir(
567*5c591343SA. Cody Schuffelen UINT16 additionalDataSize,
568*5c591343SA. Cody Schuffelen BYTE *additionalData
569*5c591343SA. Cody Schuffelen )
570*5c591343SA. Cody Schuffelen {
571*5c591343SA. Cody Schuffelen #if !USE_DEBUG_RNG
572*5c591343SA. Cody Schuffelen DRBG_SEED tmpBuf;
573*5c591343SA. Cody Schuffelen DRBG_SEED dfResult;
574*5c591343SA. Cody Schuffelen //
575*5c591343SA. Cody Schuffelen // All reseed with outside data starts with a buffer full of entropy
576*5c591343SA. Cody Schuffelen if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf))
577*5c591343SA. Cody Schuffelen return TPM_RC_NO_RESULT;
578*5c591343SA. Cody Schuffelen
579*5c591343SA. Cody Schuffelen DRBG_Reseed(&drbgDefault, &tmpBuf,
580*5c591343SA. Cody Schuffelen DfBuffer(&dfResult, additionalDataSize, additionalData));
581*5c591343SA. Cody Schuffelen drbgDefault.reseedCounter = 1;
582*5c591343SA. Cody Schuffelen
583*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
584*5c591343SA. Cody Schuffelen
585*5c591343SA. Cody Schuffelen #else
586*5c591343SA. Cody Schuffelen // If doing debug, use the input data as the initial setting for the RNG state
587*5c591343SA. Cody Schuffelen // so that the test can be reset at any time.
588*5c591343SA. Cody Schuffelen // Note: If this is called with a data size of 0 or less, nothing happens. The
589*5c591343SA. Cody Schuffelen // presumption is that, in a debug environment, the caller will have specific
590*5c591343SA. Cody Schuffelen // values for initialization, so this check is just a simple way to prevent
591*5c591343SA. Cody Schuffelen // inadvertent programming errors from screwing things up. This doesn't use an
592*5c591343SA. Cody Schuffelen // pAssert() because the non-debug version of this function will accept these
593*5c591343SA. Cody Schuffelen // parameters as meaning that there is no additionalData and only hardware
594*5c591343SA. Cody Schuffelen // entropy is used.
595*5c591343SA. Cody Schuffelen if((additionalDataSize > 0) && (additionalData != NULL))
596*5c591343SA. Cody Schuffelen {
597*5c591343SA. Cody Schuffelen memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes));
598*5c591343SA. Cody Schuffelen memcpy(drbgDefault.seed.bytes, additionalData,
599*5c591343SA. Cody Schuffelen MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes)));
600*5c591343SA. Cody Schuffelen }
601*5c591343SA. Cody Schuffelen drbgDefault.reseedCounter = 1;
602*5c591343SA. Cody Schuffelen
603*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
604*5c591343SA. Cody Schuffelen #endif
605*5c591343SA. Cody Schuffelen }
606*5c591343SA. Cody Schuffelen
607*5c591343SA. Cody Schuffelen //*** CryptRandomGenerate()
608*5c591343SA. Cody Schuffelen // Generate a 'randomSize' number or random bytes.
609*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
CryptRandomGenerate(UINT16 randomSize,BYTE * buffer)610*5c591343SA. Cody Schuffelen CryptRandomGenerate(
611*5c591343SA. Cody Schuffelen UINT16 randomSize,
612*5c591343SA. Cody Schuffelen BYTE *buffer
613*5c591343SA. Cody Schuffelen )
614*5c591343SA. Cody Schuffelen {
615*5c591343SA. Cody Schuffelen return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, randomSize);
616*5c591343SA. Cody Schuffelen }
617*5c591343SA. Cody Schuffelen
618*5c591343SA. Cody Schuffelen
619*5c591343SA. Cody Schuffelen
620*5c591343SA. Cody Schuffelen //*** DRBG_InstantiateSeededKdf()
621*5c591343SA. Cody Schuffelen // This function is used to instantiate a KDF-based RNG. This is used for derivations.
622*5c591343SA. Cody Schuffelen // This function always returns TRUE.
623*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
DRBG_InstantiateSeededKdf(KDF_STATE * state,TPM_ALG_ID hashAlg,TPM_ALG_ID kdf,TPM2B * seed,const TPM2B * label,TPM2B * context,UINT32 limit)624*5c591343SA. Cody Schuffelen DRBG_InstantiateSeededKdf(
625*5c591343SA. Cody Schuffelen KDF_STATE *state, // OUT: buffer to hold the state
626*5c591343SA. Cody Schuffelen TPM_ALG_ID hashAlg, // IN: hash algorithm
627*5c591343SA. Cody Schuffelen TPM_ALG_ID kdf, // IN: the KDF to use
628*5c591343SA. Cody Schuffelen TPM2B *seed, // IN: the seed to use
629*5c591343SA. Cody Schuffelen const TPM2B *label, // IN: a label for the generation process.
630*5c591343SA. Cody Schuffelen TPM2B *context, // IN: the context value
631*5c591343SA. Cody Schuffelen UINT32 limit // IN: Maximum number of bits from the KDF
632*5c591343SA. Cody Schuffelen )
633*5c591343SA. Cody Schuffelen {
634*5c591343SA. Cody Schuffelen state->magic = KDF_MAGIC;
635*5c591343SA. Cody Schuffelen state->limit = limit;
636*5c591343SA. Cody Schuffelen state->seed = seed;
637*5c591343SA. Cody Schuffelen state->hash = hashAlg;
638*5c591343SA. Cody Schuffelen state->kdf = kdf;
639*5c591343SA. Cody Schuffelen state->label = label;
640*5c591343SA. Cody Schuffelen state->context = context;
641*5c591343SA. Cody Schuffelen state->digestSize = CryptHashGetDigestSize(hashAlg);
642*5c591343SA. Cody Schuffelen state->counter = 0;
643*5c591343SA. Cody Schuffelen state->residual.t.size = 0;
644*5c591343SA. Cody Schuffelen return TRUE;
645*5c591343SA. Cody Schuffelen }
646*5c591343SA. Cody Schuffelen
647*5c591343SA. Cody Schuffelen //*** DRBG_AdditionalData()
648*5c591343SA. Cody Schuffelen // Function to reseed the DRBG with additional entropy. This is normally called
649*5c591343SA. Cody Schuffelen // before computing the protection value of a primary key in the Endorsement
650*5c591343SA. Cody Schuffelen // hierarchy.
651*5c591343SA. Cody Schuffelen LIB_EXPORT void
DRBG_AdditionalData(DRBG_STATE * drbgState,TPM2B * additionalData)652*5c591343SA. Cody Schuffelen DRBG_AdditionalData(
653*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState, // IN:OUT state to update
654*5c591343SA. Cody Schuffelen TPM2B *additionalData // IN: value to incorporate
655*5c591343SA. Cody Schuffelen )
656*5c591343SA. Cody Schuffelen {
657*5c591343SA. Cody Schuffelen DRBG_SEED dfResult;
658*5c591343SA. Cody Schuffelen if(drbgState->magic == DRBG_MAGIC)
659*5c591343SA. Cody Schuffelen {
660*5c591343SA. Cody Schuffelen DfBuffer(&dfResult, additionalData->size, additionalData->buffer);
661*5c591343SA. Cody Schuffelen DRBG_Reseed(drbgState, &dfResult, NULL);
662*5c591343SA. Cody Schuffelen }
663*5c591343SA. Cody Schuffelen }
664*5c591343SA. Cody Schuffelen
665*5c591343SA. Cody Schuffelen
666*5c591343SA. Cody Schuffelen //*** DRBG_InstantiateSeeded()
667*5c591343SA. Cody Schuffelen // This function is used to instantiate a random number generator from seed values.
668*5c591343SA. Cody Schuffelen // The nominal use of this generator is to create sequences of pseudo-random
669*5c591343SA. Cody Schuffelen // numbers from a seed value.
670*5c591343SA. Cody Schuffelen //
671*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
672*5c591343SA. Cody Schuffelen // TPM_RC_FAILURE DRBG self-test failure
673*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
DRBG_InstantiateSeeded(DRBG_STATE * drbgState,const TPM2B * seed,const TPM2B * purpose,const TPM2B * name,const TPM2B * additional)674*5c591343SA. Cody Schuffelen DRBG_InstantiateSeeded(
675*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState, // IN/OUT: buffer to hold the state
676*5c591343SA. Cody Schuffelen const TPM2B *seed, // IN: the seed to use
677*5c591343SA. Cody Schuffelen const TPM2B *purpose, // IN: a label for the generation process.
678*5c591343SA. Cody Schuffelen const TPM2B *name, // IN: name of the object
679*5c591343SA. Cody Schuffelen const TPM2B *additional // IN: additional data
680*5c591343SA. Cody Schuffelen )
681*5c591343SA. Cody Schuffelen {
682*5c591343SA. Cody Schuffelen DF_STATE dfState;
683*5c591343SA. Cody Schuffelen int totalInputSize;
684*5c591343SA. Cody Schuffelen // DRBG should have been tested, but...
685*5c591343SA. Cody Schuffelen if(!IsDrbgTested() && !DRBG_SelfTest())
686*5c591343SA. Cody Schuffelen {
687*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_SELF_TEST);
688*5c591343SA. Cody Schuffelen return TPM_RC_FAILURE;
689*5c591343SA. Cody Schuffelen }
690*5c591343SA. Cody Schuffelen // Initialize the DRBG state
691*5c591343SA. Cody Schuffelen memset(drbgState, 0, sizeof(DRBG_STATE));
692*5c591343SA. Cody Schuffelen drbgState->magic = DRBG_MAGIC;
693*5c591343SA. Cody Schuffelen
694*5c591343SA. Cody Schuffelen // Size all of the values
695*5c591343SA. Cody Schuffelen totalInputSize = (seed != NULL) ? seed->size : 0;
696*5c591343SA. Cody Schuffelen totalInputSize += (purpose != NULL) ? purpose->size : 0;
697*5c591343SA. Cody Schuffelen totalInputSize += (name != NULL) ? name->size : 0;
698*5c591343SA. Cody Schuffelen totalInputSize += (additional != NULL) ? additional->size : 0;
699*5c591343SA. Cody Schuffelen
700*5c591343SA. Cody Schuffelen // Initialize the derivation
701*5c591343SA. Cody Schuffelen DfStart(&dfState, totalInputSize);
702*5c591343SA. Cody Schuffelen
703*5c591343SA. Cody Schuffelen // Run all the input strings through the derivation function
704*5c591343SA. Cody Schuffelen if(seed != NULL)
705*5c591343SA. Cody Schuffelen DfUpdate(&dfState, seed->size, seed->buffer);
706*5c591343SA. Cody Schuffelen if(purpose != NULL)
707*5c591343SA. Cody Schuffelen DfUpdate(&dfState, purpose->size, purpose->buffer);
708*5c591343SA. Cody Schuffelen if(name != NULL)
709*5c591343SA. Cody Schuffelen DfUpdate(&dfState, name->size, name->buffer);
710*5c591343SA. Cody Schuffelen if(additional != NULL)
711*5c591343SA. Cody Schuffelen DfUpdate(&dfState, additional->size, additional->buffer);
712*5c591343SA. Cody Schuffelen
713*5c591343SA. Cody Schuffelen // Used the derivation function output as the "entropy" input. This is not
714*5c591343SA. Cody Schuffelen // how it is described in SP800-90A but this is the equivalent function
715*5c591343SA. Cody Schuffelen DRBG_Reseed(((DRBG_STATE *)drbgState), DfEnd(&dfState), NULL);
716*5c591343SA. Cody Schuffelen
717*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
718*5c591343SA. Cody Schuffelen }
719*5c591343SA. Cody Schuffelen
720*5c591343SA. Cody Schuffelen //*** CryptRandStartup()
721*5c591343SA. Cody Schuffelen // This function is called when TPM_Startup is executed. This function always returns
722*5c591343SA. Cody Schuffelen // TRUE.
723*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
CryptRandStartup(void)724*5c591343SA. Cody Schuffelen CryptRandStartup(
725*5c591343SA. Cody Schuffelen void
726*5c591343SA. Cody Schuffelen )
727*5c591343SA. Cody Schuffelen {
728*5c591343SA. Cody Schuffelen #if ! _DRBG_STATE_SAVE
729*5c591343SA. Cody Schuffelen // If not saved in NV, re-instantiate on each startup
730*5c591343SA. Cody Schuffelen return DRBG_Instantiate(&drbgDefault, 0, NULL);
731*5c591343SA. Cody Schuffelen #else
732*5c591343SA. Cody Schuffelen // If the running state is saved in NV, NV has to be loaded before it can
733*5c591343SA. Cody Schuffelen // be updated
734*5c591343SA. Cody Schuffelen if(go.drbgState.magic == DRBG_MAGIC)
735*5c591343SA. Cody Schuffelen return DRBG_Reseed(&go.drbgState, NULL, NULL);
736*5c591343SA. Cody Schuffelen else
737*5c591343SA. Cody Schuffelen return DRBG_Instantiate(&go.drbgState, 0, NULL);
738*5c591343SA. Cody Schuffelen #endif
739*5c591343SA. Cody Schuffelen }
740*5c591343SA. Cody Schuffelen
741*5c591343SA. Cody Schuffelen //*** CryptRandInit()
742*5c591343SA. Cody Schuffelen // This function is called when _TPM_Init is being processed.
743*5c591343SA. Cody Schuffelen //
744*5c591343SA. Cody Schuffelen // Return Type: BOOL
745*5c591343SA. Cody Schuffelen // TRUE(1) success
746*5c591343SA. Cody Schuffelen // FALSE(0) failure
747*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
CryptRandInit(void)748*5c591343SA. Cody Schuffelen CryptRandInit(
749*5c591343SA. Cody Schuffelen void
750*5c591343SA. Cody Schuffelen )
751*5c591343SA. Cody Schuffelen {
752*5c591343SA. Cody Schuffelen #if !USE_DEBUG_RNG
753*5c591343SA. Cody Schuffelen _plat__GetEntropy(NULL, 0);
754*5c591343SA. Cody Schuffelen #endif
755*5c591343SA. Cody Schuffelen return DRBG_SelfTest();
756*5c591343SA. Cody Schuffelen }
757*5c591343SA. Cody Schuffelen
758*5c591343SA. Cody Schuffelen //*** DRBG_Generate()
759*5c591343SA. Cody Schuffelen // This function generates a random sequence according SP800-90A.
760*5c591343SA. Cody Schuffelen // If 'random' is not NULL, then 'randomSize' bytes of random values are generated.
761*5c591343SA. Cody Schuffelen // If 'random' is NULL or 'randomSize' is zero, then the function returns
762*5c591343SA. Cody Schuffelen // zero without generating any bits or updating the reseed counter.
763*5c591343SA. Cody Schuffelen // This function returns the number of bytes produced which could be less than the
764*5c591343SA. Cody Schuffelen // number requested if the request is too large ("too large" is implementation
765*5c591343SA. Cody Schuffelen // dependent.)
766*5c591343SA. Cody Schuffelen LIB_EXPORT UINT16
DRBG_Generate(RAND_STATE * state,BYTE * random,UINT16 randomSize)767*5c591343SA. Cody Schuffelen DRBG_Generate(
768*5c591343SA. Cody Schuffelen RAND_STATE *state,
769*5c591343SA. Cody Schuffelen BYTE *random, // OUT: buffer to receive the random values
770*5c591343SA. Cody Schuffelen UINT16 randomSize // IN: the number of bytes to generate
771*5c591343SA. Cody Schuffelen )
772*5c591343SA. Cody Schuffelen {
773*5c591343SA. Cody Schuffelen if(state == NULL)
774*5c591343SA. Cody Schuffelen state = (RAND_STATE *)&drbgDefault;
775*5c591343SA. Cody Schuffelen if(random == NULL)
776*5c591343SA. Cody Schuffelen return 0;
777*5c591343SA. Cody Schuffelen
778*5c591343SA. Cody Schuffelen // If the caller used a KDF state, generate a sequence from the KDF not to
779*5c591343SA. Cody Schuffelen // exceed the limit.
780*5c591343SA. Cody Schuffelen if(state->kdf.magic == KDF_MAGIC)
781*5c591343SA. Cody Schuffelen {
782*5c591343SA. Cody Schuffelen KDF_STATE *kdf = (KDF_STATE *)state;
783*5c591343SA. Cody Schuffelen UINT32 counter = (UINT32)kdf->counter;
784*5c591343SA. Cody Schuffelen INT32 bytesLeft = randomSize;
785*5c591343SA. Cody Schuffelen //
786*5c591343SA. Cody Schuffelen // If the number of bytes to be returned would put the generator
787*5c591343SA. Cody Schuffelen // over the limit, then return 0
788*5c591343SA. Cody Schuffelen if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit)
789*5c591343SA. Cody Schuffelen return 0;
790*5c591343SA. Cody Schuffelen // Process partial and full blocks until all requested bytes provided
791*5c591343SA. Cody Schuffelen while(bytesLeft > 0)
792*5c591343SA. Cody Schuffelen {
793*5c591343SA. Cody Schuffelen // If there is any residual data in the buffer, copy it to the output
794*5c591343SA. Cody Schuffelen // buffer
795*5c591343SA. Cody Schuffelen if(kdf->residual.t.size > 0)
796*5c591343SA. Cody Schuffelen {
797*5c591343SA. Cody Schuffelen INT32 size;
798*5c591343SA. Cody Schuffelen //
799*5c591343SA. Cody Schuffelen // Don't use more of the residual than will fit or more than are
800*5c591343SA. Cody Schuffelen // available
801*5c591343SA. Cody Schuffelen size = MIN(kdf->residual.t.size, bytesLeft);
802*5c591343SA. Cody Schuffelen
803*5c591343SA. Cody Schuffelen // Copy some or all of the residual to the output. The residual is
804*5c591343SA. Cody Schuffelen // at the end of the buffer. The residual might be a full buffer.
805*5c591343SA. Cody Schuffelen MemoryCopy(random,
806*5c591343SA. Cody Schuffelen &kdf->residual.t.buffer
807*5c591343SA. Cody Schuffelen [kdf->digestSize - kdf->residual.t.size], size);
808*5c591343SA. Cody Schuffelen
809*5c591343SA. Cody Schuffelen // Advance the buffer pointer
810*5c591343SA. Cody Schuffelen random += size;
811*5c591343SA. Cody Schuffelen
812*5c591343SA. Cody Schuffelen // Reduce the number of bytes left to get
813*5c591343SA. Cody Schuffelen bytesLeft -= size;
814*5c591343SA. Cody Schuffelen
815*5c591343SA. Cody Schuffelen // And reduce the residual size appropriately
816*5c591343SA. Cody Schuffelen kdf->residual.t.size -= (UINT16)size;
817*5c591343SA. Cody Schuffelen }
818*5c591343SA. Cody Schuffelen else
819*5c591343SA. Cody Schuffelen {
820*5c591343SA. Cody Schuffelen UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize);
821*5c591343SA. Cody Schuffelen //
822*5c591343SA. Cody Schuffelen // Get the number of required full blocks
823*5c591343SA. Cody Schuffelen if(blocks > 0)
824*5c591343SA. Cody Schuffelen {
825*5c591343SA. Cody Schuffelen UINT16 size = blocks * kdf->digestSize;
826*5c591343SA. Cody Schuffelen // Get some number of full blocks and put them in the return buffer
827*5c591343SA. Cody Schuffelen CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL,
828*5c591343SA. Cody Schuffelen kdf->limit, random, &counter, blocks);
829*5c591343SA. Cody Schuffelen
830*5c591343SA. Cody Schuffelen // reduce the size remaining to be moved and advance the pointer
831*5c591343SA. Cody Schuffelen bytesLeft -= size;
832*5c591343SA. Cody Schuffelen random += size;
833*5c591343SA. Cody Schuffelen }
834*5c591343SA. Cody Schuffelen else
835*5c591343SA. Cody Schuffelen {
836*5c591343SA. Cody Schuffelen // Fill the residual buffer with a full block and then loop to
837*5c591343SA. Cody Schuffelen // top to get part of it copied to the output.
838*5c591343SA. Cody Schuffelen kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed,
839*5c591343SA. Cody Schuffelen kdf->label, kdf->context, NULL,
840*5c591343SA. Cody Schuffelen kdf->limit,
841*5c591343SA. Cody Schuffelen kdf->residual.t.buffer,
842*5c591343SA. Cody Schuffelen &counter, 1);
843*5c591343SA. Cody Schuffelen }
844*5c591343SA. Cody Schuffelen }
845*5c591343SA. Cody Schuffelen }
846*5c591343SA. Cody Schuffelen kdf->counter = counter;
847*5c591343SA. Cody Schuffelen return randomSize;
848*5c591343SA. Cody Schuffelen }
849*5c591343SA. Cody Schuffelen else if(state->drbg.magic == DRBG_MAGIC)
850*5c591343SA. Cody Schuffelen {
851*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState = (DRBG_STATE *)state;
852*5c591343SA. Cody Schuffelen DRBG_KEY_SCHEDULE keySchedule;
853*5c591343SA. Cody Schuffelen DRBG_SEED *seed = &drbgState->seed;
854*5c591343SA. Cody Schuffelen
855*5c591343SA. Cody Schuffelen if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED)
856*5c591343SA. Cody Schuffelen {
857*5c591343SA. Cody Schuffelen if(drbgState == &drbgDefault)
858*5c591343SA. Cody Schuffelen {
859*5c591343SA. Cody Schuffelen DRBG_Reseed(drbgState, NULL, NULL);
860*5c591343SA. Cody Schuffelen if(IsEntropyBad() && !IsSelfTest())
861*5c591343SA. Cody Schuffelen return 0;
862*5c591343SA. Cody Schuffelen }
863*5c591343SA. Cody Schuffelen else
864*5c591343SA. Cody Schuffelen {
865*5c591343SA. Cody Schuffelen // If this is a PRNG then the only way to get
866*5c591343SA. Cody Schuffelen // here is if the SW has run away.
867*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_INTERNAL);
868*5c591343SA. Cody Schuffelen return 0;
869*5c591343SA. Cody Schuffelen }
870*5c591343SA. Cody Schuffelen }
871*5c591343SA. Cody Schuffelen // if the allowed number of bytes in a request is larger than the
872*5c591343SA. Cody Schuffelen // less than the number of bytes that can be requested, then check
873*5c591343SA. Cody Schuffelen #if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST
874*5c591343SA. Cody Schuffelen if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST)
875*5c591343SA. Cody Schuffelen randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST;
876*5c591343SA. Cody Schuffelen #endif
877*5c591343SA. Cody Schuffelen // Create encryption schedule
878*5c591343SA. Cody Schuffelen if(DRBG_ENCRYPT_SETUP((BYTE *)pDRBG_KEY(seed),
879*5c591343SA. Cody Schuffelen DRBG_KEY_SIZE_BITS, &keySchedule) != 0)
880*5c591343SA. Cody Schuffelen {
881*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_INTERNAL);
882*5c591343SA. Cody Schuffelen return 0;
883*5c591343SA. Cody Schuffelen }
884*5c591343SA. Cody Schuffelen // Generate the random data
885*5c591343SA. Cody Schuffelen EncryptDRBG(random, randomSize, &keySchedule, pDRBG_IV(seed),
886*5c591343SA. Cody Schuffelen drbgState->lastValue);
887*5c591343SA. Cody Schuffelen // Do a key update
888*5c591343SA. Cody Schuffelen DRBG_Update(drbgState, &keySchedule, NULL);
889*5c591343SA. Cody Schuffelen
890*5c591343SA. Cody Schuffelen // Increment the reseed counter
891*5c591343SA. Cody Schuffelen drbgState->reseedCounter += 1;
892*5c591343SA. Cody Schuffelen }
893*5c591343SA. Cody Schuffelen else
894*5c591343SA. Cody Schuffelen {
895*5c591343SA. Cody Schuffelen LOG_FAILURE(FATAL_ERROR_INTERNAL);
896*5c591343SA. Cody Schuffelen return FALSE;
897*5c591343SA. Cody Schuffelen }
898*5c591343SA. Cody Schuffelen return randomSize;
899*5c591343SA. Cody Schuffelen }
900*5c591343SA. Cody Schuffelen
901*5c591343SA. Cody Schuffelen //*** DRBG_Instantiate()
902*5c591343SA. Cody Schuffelen // This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1].
903*5c591343SA. Cody Schuffelen // This is called when a the TPM DRBG is to be instantiated. This is
904*5c591343SA. Cody Schuffelen // called to instantiate a DRBG used by the TPM for normal
905*5c591343SA. Cody Schuffelen // operations.
906*5c591343SA. Cody Schuffelen //
907*5c591343SA. Cody Schuffelen // Return Type: BOOL
908*5c591343SA. Cody Schuffelen // TRUE(1) instantiation succeeded
909*5c591343SA. Cody Schuffelen // FALSE(0) instantiation failed
910*5c591343SA. Cody Schuffelen LIB_EXPORT BOOL
DRBG_Instantiate(DRBG_STATE * drbgState,UINT16 pSize,BYTE * personalization)911*5c591343SA. Cody Schuffelen DRBG_Instantiate(
912*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState, // OUT: the instantiated value
913*5c591343SA. Cody Schuffelen UINT16 pSize, // IN: Size of personalization string
914*5c591343SA. Cody Schuffelen BYTE *personalization // IN: The personalization string
915*5c591343SA. Cody Schuffelen )
916*5c591343SA. Cody Schuffelen {
917*5c591343SA. Cody Schuffelen DRBG_SEED seed;
918*5c591343SA. Cody Schuffelen DRBG_SEED dfResult;
919*5c591343SA. Cody Schuffelen //
920*5c591343SA. Cody Schuffelen pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL));
921*5c591343SA. Cody Schuffelen // If the DRBG has not been tested, test when doing an instantiation. Since
922*5c591343SA. Cody Schuffelen // Instantiation is called during self test, make sure we don't get stuck in a
923*5c591343SA. Cody Schuffelen // loop.
924*5c591343SA. Cody Schuffelen if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest())
925*5c591343SA. Cody Schuffelen return FALSE;
926*5c591343SA. Cody Schuffelen // If doing a self test, DRBG_GetEntropy will return the NIST
927*5c591343SA. Cody Schuffelen // test vector value.
928*5c591343SA. Cody Schuffelen if(!DRBG_GetEntropy(sizeof(seed), (BYTE *)&seed))
929*5c591343SA. Cody Schuffelen return FALSE;
930*5c591343SA. Cody Schuffelen // set everything to zero
931*5c591343SA. Cody Schuffelen memset(drbgState, 0, sizeof(DRBG_STATE));
932*5c591343SA. Cody Schuffelen drbgState->magic = DRBG_MAGIC;
933*5c591343SA. Cody Schuffelen
934*5c591343SA. Cody Schuffelen // Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what
935*5c591343SA. Cody Schuffelen // reseeding does. So, do a reduction on the personalization value (if any)
936*5c591343SA. Cody Schuffelen // and do a reseed.
937*5c591343SA. Cody Schuffelen DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization));
938*5c591343SA. Cody Schuffelen
939*5c591343SA. Cody Schuffelen return TRUE;
940*5c591343SA. Cody Schuffelen }
941*5c591343SA. Cody Schuffelen
942*5c591343SA. Cody Schuffelen //*** DRBG_Uninstantiate()
943*5c591343SA. Cody Schuffelen // This is Uninstantiate_function() from [SP 800-90A 9.4].
944*5c591343SA. Cody Schuffelen //
945*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
946*5c591343SA. Cody Schuffelen // TPM_RC_VALUE not a valid state
947*5c591343SA. Cody Schuffelen LIB_EXPORT TPM_RC
DRBG_Uninstantiate(DRBG_STATE * drbgState)948*5c591343SA. Cody Schuffelen DRBG_Uninstantiate(
949*5c591343SA. Cody Schuffelen DRBG_STATE *drbgState // IN/OUT: working state to erase
950*5c591343SA. Cody Schuffelen )
951*5c591343SA. Cody Schuffelen {
952*5c591343SA. Cody Schuffelen if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC))
953*5c591343SA. Cody Schuffelen return TPM_RC_VALUE;
954*5c591343SA. Cody Schuffelen memset(drbgState, 0, sizeof(DRBG_STATE));
955*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
956*5c591343SA. Cody Schuffelen }
957